From a823d7f2dc6715d870ec1962e7bd960465e8953d Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 9 Jul 2015 13:55:36 +0800 Subject: [PATCH 001/545] add readme --- blade-beetl/README.md | 44 +++++++++++ blade-jetbrick/README.md | 45 +++++++++++ blade-redis/README.md | 158 +++++++++++++++++++++++++++++++++++++++ blade-sql2o/README.md | 103 +++++++++++++++++++++++++ blade-velocity/README.md | 46 ++++++++++++ 5 files changed, 396 insertions(+) create mode 100644 blade-beetl/README.md create mode 100644 blade-jetbrick/README.md create mode 100644 blade-redis/README.md create mode 100644 blade-sql2o/README.md create mode 100644 blade-velocity/README.md diff --git a/blade-beetl/README.md b/blade-beetl/README.md new file mode 100644 index 000000000..d8121d3dd --- /dev/null +++ b/blade-beetl/README.md @@ -0,0 +1,44 @@ +#blade-beetl + +```java +public class App extends BladeApplication{ + + Logger logger = Logger.getLogger(App.class); + @Override + public void init() { + + // 设置路由、拦截器包所在包 + Blade.defaultRoute("blade.sample"); + + // 设置BeetlRender引擎 + Blade.viewEngin(new BeetlRender()); + } + +} +``` + +Route Code + +```java +@Route("/you/:username") +public String you(Request request) { + ModelAndView modelAndView = new ModelAndView(""); + modelAndView.add("username", request.pathParam(":username")); + return R.render(modelAndView); +} +``` + +View Code + +```html + + + + +Blade Beetl Demo + + +

hello ${username}

+ + +``` \ No newline at end of file diff --git a/blade-jetbrick/README.md b/blade-jetbrick/README.md new file mode 100644 index 000000000..6bcbb8d7a --- /dev/null +++ b/blade-jetbrick/README.md @@ -0,0 +1,45 @@ +#blade-jetbrick + +```java +public class App extends BladeApplication{ + + Logger logger = Logger.getLogger(App.class); + + @Override + public void init() { + + // 设置路由、拦截器包所在包 + Blade.defaultRoute("blade.sample"); + + // 设置JetbrickRender引擎 + Blade.viewEngin(new JetbrickRender()); + } + +} +``` + +Route Code + +```java +@Route("/you/:username") +public String you(Request request) { + ModelAndView modelAndView = new ModelAndView(""); + modelAndView.add("username", request.pathParam(":username")); + return R.render(modelAndView); +} +``` + +View Code + +```html + + + + +Blade Jetbrick Demo + + +

hello ${username}

+ + +``` \ No newline at end of file diff --git a/blade-redis/README.md b/blade-redis/README.md new file mode 100644 index 000000000..d949e489d --- /dev/null +++ b/blade-redis/README.md @@ -0,0 +1,158 @@ +# Blade-Redis + +在java中更方便的操作redis数据库,基于`blade`框架继承,支持多数据库集群配置。 + +##使用 + +```java +// 配置 +RedisPlugin redisPlugin = RedisPlugin.INSTANCE; +redisPlugin.host("127.0.0.1", 6379); +redisPlugin.run(); +``` + +* 使用redis +```java +JedisCache jedisCache = new JedisCache(); + +//基础操作,更多请查看源代码 +public String set(final String key, final String value) { + return super.setString(key, value); +} + +public String set(final String key, final Serializable value) { + return super.setObject(key, value); +} + +public String set(final String key, final String value, final int timeout) { + return super.setString(key, value, timeout); +} + +public Long hset(final String key, final String field, final String value) { + return super.hashSet(key, field, value); +} + +public Long hset(final String key, final String field, final String value, final int timeout) { + return super.hashSet(key, field, value, timeout); +} + +public String hset(final String key, final Map map) { + return super.hashMultipleSet(key, map); +} + +public String hset(final String key, Map map, final int timeout) { + return super.hashMultipleSet(key, map, timeout); +} + +public Long hset(final String key, final String field, final Serializable value) { + return super.hset(key, field, value); +} + +public Long hset(final String key, final String field, final Serializable value, int timeout) { + return super.hset(key, field, value, timeout); +} + +public boolean exists(final String key, final String field) { + return super.exists(key, field); +} + +public boolean exists(final String key) { + return super.exists(key); +} + +public Long del(final String key) { + return super.delKey(key); +} + +public Long del(final String key, final String field) { + return super.delKey(key, field); +} + +public T get(final String key) { + return super.get(key); +} + +public String get(final String key, final String field) { + return super.hashGet(key, field); +} + +public Map getAllHash(final String key) { + return super.hashGetAll(key); +} + +public Serializable getModel(final String key, final String field) { + return SerializeKit.unserialize(super.hashGet(key, field).getBytes()); +} + +public List getSet(final String key, final Integer start, final Integer end) { + return super.listRange(key, start, end); +} + +public Set getKeys(final String pattern) { + return super.getKeyLike(pattern); +} + +public Long delLike(final String patten) { + return super.delKeysLike(patten); +} + +public String hget(final String key, final String field) { + return super.hashGet(key, field); +} + +public String hget(final String key, final String field, final int timeout) { + return super.hashGet(key, field, timeout); +} + +public String hget(String key, Map map) { + return super.hashMultipleSet(key, map); +} + +public Long hcount(String key) { + return super.hashLen(key); +} + +public Long sadd(String key, String... members) { + return super.sadd(key, members); +} + +public Long srem(String key, String... members) { + return super.srem(key, members); +} + +public Set sunion(String... keys) { + return super.sunion(keys); +} + +public Set sdiff(String... keys) { + return super.sdiff(keys); +} + +public Long scard(String key) { + return super.scard(key); +} + +public Long lpush(String key, String... values) { + return super.listPushHead(key, values); +} + +public Long rpush(String key, String... values) { + return super.listPushTail(key, values); +} + +public Long lpushTrim(String key, String value, long size) { + return super.listPushHeadAndTrim(key, value, size); +} + +public Long ldel(String key, String value) { + return super.listDel(key, value, -1); +} + +public Long llength(String key) { + return super.listLen(key); +} + +public T hgetModel(String key, String field) { + return super.hgetObj(key, field); +} +``` diff --git a/blade-sql2o/README.md b/blade-sql2o/README.md new file mode 100644 index 000000000..38c2a0303 --- /dev/null +++ b/blade-sql2o/README.md @@ -0,0 +1,103 @@ +# Blade-Sql2o + +轻小,简单,快速,高效的数据库框架。 + +### 特性 +基于`blade`框架为核心搭建的操作数据库基础框架,一行代码即可完成增删改查,分页等操作; +内置基于LRU的缓存机制进行缓存,可配置的缓存开关以及扩展。 + +##快速入门 +它使用起来非常方便,首先配置好数据库 + +```java +// 配置数据库插件 +Sql2oPlugin sql2oPlugin = Sql2oPlugin.INSTANCE; +sql2oPlugin.config("jdbc:mysql://localhost:3306/test", "com.mysql.jdbc.Driver", "root", "root"); +// 开启缓存 +sql2oPlugin.openCache(); +sql2oPlugin.run(); +``` +* 添加一条数据 +```java +User model = new User(); + +Date birthday = new Date(); +Long uid = model.insert().param("name", "jack").param("birthday", birthday).param("sex", "男").executeAndCommit(); +LOGGER.INFO("uid = " + uid); +``` + +* 查询一条数据 +```java +User model = new User(); + +// 根据主键查询User +User user = model.select().fetchByPk(1); +LOGGER.INFO("user = " + user); + +// 查询性别为男性,名字以`张`开头,年龄在50一下的User +User user = model.select().where("sex", "男").like("name", "张%").less("age", 50).fetchOne(); +LOGGER.INFO("user = " + user); +``` + +* 查询一个数据集合 +```java +User model = new User(); + +// 查询性别为男性,名字以`张`开头,年龄在50一下的User集合 +List users = model.select().where("sex", "男").like("name", "张%").less("age", 50).order("age asc").fetchList(); +LOGGER.INFO("user = " + user); +``` + + +* 分页查询一个数据集合 +```java +Post model = new Post(); + +Page postPage = model.select("select pid, title, type, access_count, create_time, update_time from post") + .where("status", "publish") + .like("title", "%java") + .orderBy("pid desc") + .fetchPage(1, 10); +``` + + +* 联合查询一个数据集合 +```java +Post model = new Post(); + +List posts = model.select("select a.* from post a inner join relation b on a.pid = b.pid") + .where("a.type", "post") + .where("b.mid", 15) + .like("a.title", "%java") + .orderBy("a.pid desc") + .fetchList(); +``` + +* 修改数据 +```java +Post model = new Post(); + +Long count = model.update() + .param("title", "test1") + .where("pid", 11).executeAndCommit(); + +``` + +* 删除数据 +```java +Post model = new Post(); + +Long count = model.delete().where("pid", pid).executeAndCommit(); + +``` + +### v1.1.4 + 1. 添加动态数据源支持 + +### v1.1.3 + 1. 适配`blade`最新版本 + +### 联系我 +Mail: biezhi.me#gmail.com + +Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) \ No newline at end of file diff --git a/blade-velocity/README.md b/blade-velocity/README.md new file mode 100644 index 000000000..22592c2ce --- /dev/null +++ b/blade-velocity/README.md @@ -0,0 +1,46 @@ +#blade-velocity + +```java +public class App implements BladeApplication{ + + Logger logger = Logger.getLogger(App.class); + + @Override + public void init() { + + // 设置路由、拦截器包所在包 + Blade.defaultRoute("blade.sample"); + + // 设置VelocityRender引擎 + final Render render = new VelocityRender(); + Blade.viewEngin(render); + } + +} +``` + +Route Code + +```java +@Route("/you/:username") +public String you(Request request) { + ModelAndView modelAndView = new ModelAndView(""); + modelAndView.add("username", request.pathParam(":username")); + return R.render(modelAndView); +} +``` + +View Code + +```html + + + + +Blade Velocity Demo + + +

hello $username

+ + +``` \ No newline at end of file From e8b4e3dd64393706a5ccade49e11d516b704e62a Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 9 Jul 2015 14:26:52 +0800 Subject: [PATCH 002/545] update readme --- README.md | 2 +- README_EN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e008e5718..72a82039b 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ ```xml com.bladejava - blade + blade-core x.x.x ``` diff --git a/README_EN.md b/README_EN.md index d134c612f..2e115c789 100644 --- a/README_EN.md +++ b/README_EN.md @@ -33,7 +33,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for ```xml com.bladejava - blade + blade-core x.x.x ``` From 60ce64ac33b22f7af2ec67e78e397a82492b5715 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 9 Jul 2015 16:32:09 +0800 Subject: [PATCH 003/545] update version --- README.md | 5 +- .../src/main/java/blade/kit/package-info.java | 4 -- .../src/main/java/blade/kit/IpKit.java | 0 .../src/main/java/blade/kit/PathKit.java | 0 pom.xml | 46 ++++++++----------- 5 files changed, 22 insertions(+), 33 deletions(-) delete mode 100644 blade-core/src/main/java/blade/kit/package-info.java rename {blade-core => blade-kit}/src/main/java/blade/kit/IpKit.java (100%) rename {blade-core => blade-kit}/src/main/java/blade/kit/PathKit.java (100%) diff --git a/README.md b/README.md index 72a82039b..fd19557fa 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ## 更新日志 -### v1.1.3 +### v1.2 1. 修复sql2o更新Bug 2. 去除blade-kit无用类 3. 添加邮件支持 @@ -131,8 +131,9 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 5. 添加http网络请求支持 6. 优化内置日志输出 7. 添加定时任务支持 + 8. 重构项目结构 -### v1.1.0 +### v1.1.x 1. 去除对外公开的多余方法展示 2. 添加`Blade.run()`方式运行jetty 3. 添加`Blade.register()`方法注册bean对象 diff --git a/blade-core/src/main/java/blade/kit/package-info.java b/blade-core/src/main/java/blade/kit/package-info.java deleted file mode 100644 index 66554ccaf..000000000 --- a/blade-core/src/main/java/blade/kit/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * blade工具包 - */ -package blade.kit; \ No newline at end of file diff --git a/blade-core/src/main/java/blade/kit/IpKit.java b/blade-kit/src/main/java/blade/kit/IpKit.java similarity index 100% rename from blade-core/src/main/java/blade/kit/IpKit.java rename to blade-kit/src/main/java/blade/kit/IpKit.java diff --git a/blade-core/src/main/java/blade/kit/PathKit.java b/blade-kit/src/main/java/blade/kit/PathKit.java similarity index 100% rename from blade-core/src/main/java/blade/kit/PathKit.java rename to blade-kit/src/main/java/blade/kit/PathKit.java diff --git a/pom.xml b/pom.xml index 2fd395ea7..2e3194fac 100644 --- a/pom.xml +++ b/pom.xml @@ -1,35 +1,36 @@ - + 4.0.0 - + com.bladejava blade-root 1.0 pom - + blade-root https://github.com/biezhi/blade - + 1.6 1.6 UTF-8 4.11 - 1.1.4 + 1.2 3.0.1 - + blade-kit blade-core blade-cache - blade-jetbrick - blade-sql2o - blade-velocity - blade-beetl - blade-redis - - + blade-jetbrick + blade-sql2o + blade-velocity + blade-beetl + blade-redis + + junit @@ -44,7 +45,7 @@ provided - + @@ -57,19 +58,10 @@ UTF-8 - + - + \ No newline at end of file From c3f0e681c6c530817e3ebf6159af8736f9575196 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 9 Jul 2015 16:33:51 +0800 Subject: [PATCH 004/545] update readme --- README_EN.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README_EN.md b/README_EN.md index 2e115c789..cf2211165 100644 --- a/README_EN.md +++ b/README_EN.md @@ -125,7 +125,7 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ### Update -### v1.1.3 +### v1.2 1. Update Bug fix sql2o 2. Remove the blade-kit useless class 3. Add email support @@ -133,8 +133,9 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex 5. Add the HTTP request support network 6. Optimization of the built-in logging output 7. Add tasks to support regularly + 8. Reconstruction project structure -### v1.1.0 +### v1.1.x 1. Remove excess public methods 2. Add the `Blade.run()` run jetty 3. Add the `Blade.register()` method register bean object From ebfb8f57fbdb687db2ce09928ccea8b8baa6e086 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 10 Jul 2015 17:46:44 +0800 Subject: [PATCH 005/545] update jetty version --- blade-core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index c9a8a1f25..401428b80 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -16,7 +16,7 @@ https://github.com/biezhi/blade/blade-core - 9.0.2.v20130417 + 9.3.0.v20150612 From 4752438d594574ad8fa7a8d0d4a109da5e579143 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 10 Jul 2015 18:14:36 +0800 Subject: [PATCH 006/545] update readme --- README.md | 2 +- README_EN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fd19557fa..cc73f234d 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ com.bladejava blade-core - x.x.x + 1.2.1 ``` diff --git a/README_EN.md b/README_EN.md index cf2211165..02c4852b9 100644 --- a/README_EN.md +++ b/README_EN.md @@ -34,7 +34,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - x.x.x + 1.2.1 ``` From 2c98a3cc829dde57109a4641acc02c2594fe908b Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 10 Jul 2015 18:16:16 +0800 Subject: [PATCH 007/545] update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2e3194fac..dbbebd430 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ 1.6 UTF-8 4.11 - 1.2 + 1.2.1 3.0.1 From f9199ac3a4de398ca3844eb37a1ea70d52b5bf15 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 10 Jul 2015 18:35:31 +0800 Subject: [PATCH 008/545] update readme --- README.md | 2 ++ README_EN.md | 3 +++ 2 files changed, 5 insertions(+) diff --git a/README.md b/README.md index cc73f234d..6fb30530c 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,8 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 Blade框架基于 [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) ## 联系我 +OSC Blog:[http://my.oschina.net/biezhi/blog](http://my.oschina.net/biezhi/blog) + Mail: biezhi.me#gmail.com Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) diff --git a/README_EN.md b/README_EN.md index 02c4852b9..7349213f9 100644 --- a/README_EN.md +++ b/README_EN.md @@ -157,6 +157,9 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) ## Contact + +OSC Blog:[http://my.oschina.net/biezhi/blog](http://my.oschina.net/biezhi/blog) + Mail: biezhi.me#gmail.com QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) \ No newline at end of file From fe98323f8b3bc5ecee000124a55cbf2a654d0223 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 10 Jul 2015 18:36:58 +0800 Subject: [PATCH 009/545] update readme --- README.md | 2 +- README_EN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6fb30530c..96593e7e0 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 Blade框架基于 [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) ## 联系我 -OSC Blog:[http://my.oschina.net/biezhi/blog](http://my.oschina.net/biezhi/blog) +OSC Blog:[http://my.oschina.net/biezhi](http://my.oschina.net/biezhi) Mail: biezhi.me#gmail.com diff --git a/README_EN.md b/README_EN.md index 7349213f9..88a04cdf2 100644 --- a/README_EN.md +++ b/README_EN.md @@ -158,7 +158,7 @@ Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LI ## Contact -OSC Blog:[http://my.oschina.net/biezhi/blog](http://my.oschina.net/biezhi/blog) +OSC Blog:[http://my.oschina.net/biezhi](http://my.oschina.net/biezhi) Mail: biezhi.me#gmail.com From 9cdd82d285fd33a83248a1614fc5498c55d404c6 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 13 Jul 2015 10:53:45 +0800 Subject: [PATCH 010/545] fix sql2o exception throw --- README.md | 1 - README_EN.md | 1 - blade-sql2o/pom.xml | 2 +- .../main/java/blade/plugin/sql2o/Model.java | 216 ++++++++++-------- 4 files changed, 124 insertions(+), 96 deletions(-) diff --git a/README.md b/README.md index 96593e7e0..95b7bc03d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) -[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) **blade** 是一个简洁强大的web框架,它内置了`IOC`管理,拦截器配置,`REST API`开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送等常用功能,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! diff --git a/README_EN.md b/README_EN.md index 88a04cdf2..0e542d6c9 100644 --- a/README_EN.md +++ b/README_EN.md @@ -7,7 +7,6 @@ [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) -[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) ## Introduction diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 06a2c5b4f..63acb5493 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - ${blade.version} + 1.2.2 blade-sql2o https://github.com/biezhi/blade/blade-sql2o diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index a2b3bd265..f586a7d64 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -532,21 +532,25 @@ public M fetchOne(){ } } - Connection conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - condition.clearMap(); - - res = (M) query.executeAndFetchFirst(model); - - // 重新放入缓存 - if(isCache() && null != res){ - sql2oCache.hset(CACHE_KEY_DETAIL, field, res); - } - return res; + try { + Connection conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd); + query = parseParams(query); + + LOGGER.debug("execute sql:" + query.toString()); + condition.printLog(); + condition.clearMap(); + + res = (M) query.executeAndFetchFirst(model); + + // 重新放入缓存 + if(isCache() && null != res){ + sql2oCache.hset(CACHE_KEY_DETAIL, field, res); + } + return res; + } catch (Exception e) { + LOGGER.error(e); + } } return null; } @@ -570,20 +574,24 @@ public M fetchByPk(Serializable pk){ String sqlEnd = condition.sql + " where " + pk() + " = :pk"; - Connection conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd).addParameter("pk", pk); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - condition.clearMap(); - - res = (M) query.executeAndFetchFirst(model); - - if(isCache() && null != res){ - sql2oCache.hset(CACHE_KEY_DETAIL, field, res); - } + try { + Connection conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd).addParameter("pk", pk); + + LOGGER.debug("execute sql:" + query.toString()); + condition.printLog(); + condition.clearMap(); + + res = (M) query.executeAndFetchFirst(model); + + if(isCache() && null != res){ + sql2oCache.hset(CACHE_KEY_DETAIL, field, res); + } + return res; + } catch (Exception e) { + LOGGER.error(e); + } - return res; } return null; } @@ -597,15 +605,19 @@ public M fetchColum(){ String sqlEnd = condition.getConditionSql(); - Connection conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - condition.clearMap(); - - return (M) query.executeScalar(); + try { + Connection conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd); + query = parseParams(query); + + LOGGER.debug("execute sql:" + query.toString()); + condition.printLog(); + condition.clearMap(); + + return (M) query.executeScalar(); + } catch (Exception e) { + LOGGER.error(e); + } } return null; } @@ -635,22 +647,26 @@ public List fetchList(){ sqlEnd += " order by " + condition.orderby; } - Connection conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - - condition.printLog(); - condition.clearMap(); - - result = (List) query.executeAndFetch(model); - - if(isCache() && null != result){ - sql2oCache.hsetlist(CACHE_KEY_LIST, field, result); - } - - return result; + try { + Connection conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd); + query = parseParams(query); + + LOGGER.debug("execute sql:" + query.toString()); + + condition.printLog(); + condition.clearMap(); + + result = (List) query.executeAndFetch(model); + + if(isCache() && null != result){ + sql2oCache.hsetlist(CACHE_KEY_LIST, field, result); + } + + return result; + } catch (Exception e) { + LOGGER.error(e); + } } return null; } @@ -719,24 +735,28 @@ public Page fetchPage(Integer page, Integer pageSize){ condition.equalsParams.put("page", page - 1); condition.equalsParams.put("pageSize", pageSize); - // 设置query - Connection conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - - results = query.executeAndFetch(this.model); - if(null != results && results.size() > 0){ + try { + // 设置query + Connection conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd); + query = parseParams(query); + + LOGGER.debug("execute sql:" + query.toString()); + condition.printLog(); - if(isCache()){ - sql2oCache.hsetlist(CACHE_KEY_LIST, field, results); + results = query.executeAndFetch(this.model); + if(null != results && results.size() > 0){ + + if(isCache()){ + sql2oCache.hsetlist(CACHE_KEY_LIST, field, results); + } + pageModel.setResults((List) results); } - pageModel.setResults((List) results); + + return pageModel; + } catch (Exception e) { + LOGGER.error(e); } - - return pageModel; } condition.clearMap(); @@ -832,13 +852,19 @@ public T executeAndCommit(Class returnType){ condition.clearMap(); - T key = null; - if(null != returnType){ - key = query.executeUpdate().getKey(returnType); - } else { - key = (T) query.executeUpdate().getKey(); + try { + T key = null; + if(null != returnType){ + key = query.executeUpdate().getKey(returnType); + } else { + key = (T) query.executeUpdate().getKey(); + } + return key; + } catch (Exception e) { + LOGGER.error(e); } - return key; + + return null; } @@ -852,25 +878,29 @@ public Query execute(Connection connection){ Query query = null; - if(null == connection){ - connection = sql2o.beginTransaction(); - } - - // 插入 - if(condition.dmlType.equals(DmlType.INSERT)){ - query = insertCommit(connection); - } - - // 更新 - if(condition.dmlType.equals(DmlType.UPDATE)){ - query = updateCommit(connection); - } - - // 删除 - if(condition.dmlType.equals(DmlType.DELETE)){ - query = deleteCommit(connection); - } - + try { + if (null == connection) { + connection = sql2o.beginTransaction(); + } + + // 插入 + if (condition.dmlType.equals(DmlType.INSERT)) { + query = insertCommit(connection); + } + + // 更新 + if (condition.dmlType.equals(DmlType.UPDATE)) { + query = updateCommit(connection); + } + + // 删除 + if (condition.dmlType.equals(DmlType.DELETE)) { + query = deleteCommit(connection); + } + } catch (Exception e) { + LOGGER.error(e); + } + condition.clearMap(); return query; From 248aa40783dac8b239026a00b76ae183ccc5fa88 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 13 Jul 2015 16:20:08 +0800 Subject: [PATCH 011/545] the test code to add sql2o transaction --- blade-sql2o/pom.xml | 6 ++ .../main/java/blade/plugin/sql2o/Model.java | 70 ++++++++++--------- blade-sql2o/src/test/java/BladeDemo.java | 36 ++++++++++ blade-sql2o/src/test/java/TestBladeSql2o.java | 63 +++++++++++++++++ 4 files changed, 142 insertions(+), 33 deletions(-) create mode 100644 blade-sql2o/src/test/java/BladeDemo.java create mode 100644 blade-sql2o/src/test/java/TestBladeSql2o.java diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 63acb5493..bcf385ac0 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -28,6 +28,12 @@ ${blade.version} provided + + mysql + mysql-connector-java + 5.1.35 + provided + org.sql2o sql2o diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index f586a7d64..9043afb15 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -804,7 +804,7 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ * 执行并提交 * @return */ - public T executeAndCommit(){ + public T executeAndCommit() { return executeAndCommit(null); } @@ -814,41 +814,45 @@ public T executeAndCommit(){ * @return 返回主键 */ @SuppressWarnings("unchecked") - public T executeAndCommit(Class returnType){ + public T executeAndCommit(Class returnType) { Query query = null; - // 插入 - if(condition.dmlType.equals(DmlType.INSERT)){ - query = insertCommit(null); - - LOGGER.debug("更新缓存:" + model.getName() + " -> count,list"); - - sql2oCache.hdel(CACHE_KEY_COUNT); - sql2oCache.hdel(CACHE_KEY_LIST); + try { + // 插入 + if(condition.dmlType.equals(DmlType.INSERT)){ + query = insertCommit(null); + + LOGGER.debug("更新缓存:" + model.getName() + " -> count,list"); + + sql2oCache.hdel(CACHE_KEY_COUNT); + sql2oCache.hdel(CACHE_KEY_LIST); + + } - } - - // 更新 - if(condition.dmlType.equals(DmlType.UPDATE)){ - query = updateCommit(null); - - LOGGER.debug("更新缓存:" + model.getName() + " -> detail,list"); - - sql2oCache.hdel(CACHE_KEY_DETAIL); - sql2oCache.hdel(CACHE_KEY_LIST); - } - - // 删除 - if(condition.dmlType.equals(DmlType.DELETE)){ - query = deleteCommit(null); - - LOGGER.debug("更新缓存:" + model.getName() + " -> count,list,detail"); - - sql2oCache.hdel(CACHE_KEY_COUNT); - sql2oCache.hdel(CACHE_KEY_LIST); - sql2oCache.hdel(CACHE_KEY_DETAIL); - - } + // 更新 + if(condition.dmlType.equals(DmlType.UPDATE)){ + query = updateCommit(null); + + LOGGER.debug("更新缓存:" + model.getName() + " -> detail,list"); + + sql2oCache.hdel(CACHE_KEY_DETAIL); + sql2oCache.hdel(CACHE_KEY_LIST); + } + + // 删除 + if(condition.dmlType.equals(DmlType.DELETE)){ + query = deleteCommit(null); + + LOGGER.debug("更新缓存:" + model.getName() + " -> count,list,detail"); + + sql2oCache.hdel(CACHE_KEY_COUNT); + sql2oCache.hdel(CACHE_KEY_LIST); + sql2oCache.hdel(CACHE_KEY_DETAIL); + + } + } catch (Exception e) { + LOGGER.error(e); + } condition.clearMap(); diff --git a/blade-sql2o/src/test/java/BladeDemo.java b/blade-sql2o/src/test/java/BladeDemo.java new file mode 100644 index 000000000..423807557 --- /dev/null +++ b/blade-sql2o/src/test/java/BladeDemo.java @@ -0,0 +1,36 @@ +import blade.plugin.sql2o.Model; +import blade.plugin.sql2o.Table; + +/** + * + * CREATE TABLE `blade_demo` ( + `id` int(10) NOT NULL AUTO_INCREMENT, + `val` varchar(10) NOT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf-8 + */ + +@Table("blade_demo") +public class BladeDemo extends Model { + + private static final long serialVersionUID = -9181747713955766758L; + private Integer id; + private String val; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getVal() { + return val; + } + + public void setVal(String val) { + this.val = val; + } + +} diff --git a/blade-sql2o/src/test/java/TestBladeSql2o.java b/blade-sql2o/src/test/java/TestBladeSql2o.java new file mode 100644 index 000000000..5564f6a7e --- /dev/null +++ b/blade-sql2o/src/test/java/TestBladeSql2o.java @@ -0,0 +1,63 @@ +import org.junit.Before; +import org.junit.Test; +import org.sql2o.Connection; +import org.sql2o.Sql2o; + +import blade.exception.BladeException; +import blade.plugin.sql2o.Model; +import blade.plugin.sql2o.Sql2oPlugin; + +public class TestBladeSql2o { + + private Model model = null; + + @Before + public void before() { + try { + Class.forName("com.mysql.jdbc.Driver"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + + // 配置数据库插件 + Sql2oPlugin sql2oPlugin = Sql2oPlugin.INSTANCE; + sql2oPlugin.config("jdbc:mysql://127.0.0.1:3306/test", "com.mysql.jdbc.Driver", "root", "root"); + sql2oPlugin.openCache(); + sql2oPlugin.run(); + + model = Model.getModel(BladeDemo.class); + } + + @Test + public void testTransaction() { + + Sql2o sql2o = model.getSql2o(); + final String insertSql = "insert into blade_demo(val) values (:val)"; + final String updateSql = "update blade_demo set val = :val where id = :id"; + Connection con = sql2o.beginTransaction(); + try{ + con.createQuery(insertSql).addParameter("val", "foo").executeUpdate(); + con.createQuery(updateSql).addParameter("val2", "bar").executeUpdate(); + con.commit(); + } catch(Exception e){ + if(null != con){ + con.rollback(); + } + e.printStackTrace(); + } + + } + + @Test + public void testException() { + + try { + Integer count = model.insert().param("val", "asdadasdadasdsaadsadadasdadsadasdadad").executeAndCommit(); + System.out.println(count); + } catch (BladeException e1) { + e1.printStackTrace(); + } + + + } +} From 4af09a0e30a2c40d567d127ea36ca023c2f93c62 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 13 Jul 2015 18:25:15 +0800 Subject: [PATCH 012/545] remove test code --- blade-sql2o/src/test/java/BladeDemo.java | 36 ----------- blade-sql2o/src/test/java/TestBladeSql2o.java | 63 ------------------- 2 files changed, 99 deletions(-) delete mode 100644 blade-sql2o/src/test/java/BladeDemo.java delete mode 100644 blade-sql2o/src/test/java/TestBladeSql2o.java diff --git a/blade-sql2o/src/test/java/BladeDemo.java b/blade-sql2o/src/test/java/BladeDemo.java deleted file mode 100644 index 423807557..000000000 --- a/blade-sql2o/src/test/java/BladeDemo.java +++ /dev/null @@ -1,36 +0,0 @@ -import blade.plugin.sql2o.Model; -import blade.plugin.sql2o.Table; - -/** - * - * CREATE TABLE `blade_demo` ( - `id` int(10) NOT NULL AUTO_INCREMENT, - `val` varchar(10) NOT NULL, - PRIMARY KEY (`id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf-8 - */ - -@Table("blade_demo") -public class BladeDemo extends Model { - - private static final long serialVersionUID = -9181747713955766758L; - private Integer id; - private String val; - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getVal() { - return val; - } - - public void setVal(String val) { - this.val = val; - } - -} diff --git a/blade-sql2o/src/test/java/TestBladeSql2o.java b/blade-sql2o/src/test/java/TestBladeSql2o.java deleted file mode 100644 index 5564f6a7e..000000000 --- a/blade-sql2o/src/test/java/TestBladeSql2o.java +++ /dev/null @@ -1,63 +0,0 @@ -import org.junit.Before; -import org.junit.Test; -import org.sql2o.Connection; -import org.sql2o.Sql2o; - -import blade.exception.BladeException; -import blade.plugin.sql2o.Model; -import blade.plugin.sql2o.Sql2oPlugin; - -public class TestBladeSql2o { - - private Model model = null; - - @Before - public void before() { - try { - Class.forName("com.mysql.jdbc.Driver"); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - - // 配置数据库插件 - Sql2oPlugin sql2oPlugin = Sql2oPlugin.INSTANCE; - sql2oPlugin.config("jdbc:mysql://127.0.0.1:3306/test", "com.mysql.jdbc.Driver", "root", "root"); - sql2oPlugin.openCache(); - sql2oPlugin.run(); - - model = Model.getModel(BladeDemo.class); - } - - @Test - public void testTransaction() { - - Sql2o sql2o = model.getSql2o(); - final String insertSql = "insert into blade_demo(val) values (:val)"; - final String updateSql = "update blade_demo set val = :val where id = :id"; - Connection con = sql2o.beginTransaction(); - try{ - con.createQuery(insertSql).addParameter("val", "foo").executeUpdate(); - con.createQuery(updateSql).addParameter("val2", "bar").executeUpdate(); - con.commit(); - } catch(Exception e){ - if(null != con){ - con.rollback(); - } - e.printStackTrace(); - } - - } - - @Test - public void testException() { - - try { - Integer count = model.insert().param("val", "asdadasdadasdsaadsadadasdadsadasdadad").executeAndCommit(); - System.out.println(count); - } catch (BladeException e1) { - e1.printStackTrace(); - } - - - } -} From e67b8a56e456852e613f01b8530a0a29a50f655f Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 14 Jul 2015 16:19:48 +0800 Subject: [PATCH 013/545] fix sql2o like match the null bug --- .../src/main/java/blade/render/BeetlRender.java | 2 +- .../src/main/java/blade/plugin/sql2o/Condition.java | 4 +++- .../src/main/java/blade/plugin/sql2o/Model.java | 10 +++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/blade-beetl/src/main/java/blade/render/BeetlRender.java b/blade-beetl/src/main/java/blade/render/BeetlRender.java index d2ee6d82a..9a1569f08 100644 --- a/blade-beetl/src/main/java/blade/render/BeetlRender.java +++ b/blade-beetl/src/main/java/blade/render/BeetlRender.java @@ -17,7 +17,7 @@ import blade.exception.BladeException; /** - * Velocity渲染引擎 + * Beetl渲染引擎 * @author biezhi * */ diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java index a044963ba..2ac162eb8 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java @@ -360,7 +360,9 @@ public void lessThan(String name, Object value){ * @param value */ public void like(String name, String value){ - if(StringKit.isNotBlank(name) && StringKit.isNotBlank(value) && !value.equals("%%")){ + + if(StringKit.isNotBlank(name) && StringKit.isNotBlank(value) + && value.indexOf("%null")==-1 && value.indexOf("null%")==-1 && !value.equals("%%")){ if(null == this.likeParams){ this.likeParams = CollectionKit.newHashMap(); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 9043afb15..cd1f2b445 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -541,7 +541,7 @@ public M fetchOne(){ condition.printLog(); condition.clearMap(); - res = (M) query.executeAndFetchFirst(model); + res = (M) query.executeAndFetchFirst(this.model); // 重新放入缓存 if(isCache() && null != res){ @@ -582,7 +582,7 @@ public M fetchByPk(Serializable pk){ condition.printLog(); condition.clearMap(); - res = (M) query.executeAndFetchFirst(model); + res = (M) query.executeAndFetchFirst(this.model); if(isCache() && null != res){ sql2oCache.hset(CACHE_KEY_DETAIL, field, res); @@ -657,7 +657,7 @@ public List fetchList(){ condition.printLog(); condition.clearMap(); - result = (List) query.executeAndFetch(model); + result = (List) query.executeAndFetch(this.model); if(isCache() && null != result){ sql2oCache.hsetlist(CACHE_KEY_LIST, field, result); @@ -804,8 +804,8 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ * 执行并提交 * @return */ - public T executeAndCommit() { - return executeAndCommit(null); + public Integer executeAndCommit() { + return executeAndCommit(Integer.class); } /** From b36324d9268a62ab67ded12f3f5c1056581f4273 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 15 Jul 2015 11:40:38 +0800 Subject: [PATCH 014/545] fix beetl parameter problem and add the current Unix timestamp --- .../main/java/blade/render/BeetlRender.java | 47 +++++++++++++++++-- .../src/main/java/blade/BladeWebContext.java | 1 + .../src/main/java/blade/kit/DateKit.java | 9 ++-- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/blade-beetl/src/main/java/blade/render/BeetlRender.java b/blade-beetl/src/main/java/blade/render/BeetlRender.java index 9a1569f08..c111b4f4c 100644 --- a/blade-beetl/src/main/java/blade/render/BeetlRender.java +++ b/blade-beetl/src/main/java/blade/render/BeetlRender.java @@ -2,6 +2,8 @@ import java.io.IOException; import java.util.Enumeration; +import java.util.Map; +import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -10,7 +12,7 @@ import org.beetl.core.GroupTemplate; import org.beetl.core.Template; import org.beetl.core.exception.BeetlException; -import org.beetl.core.resource.FileResourceLoader; +import org.beetl.core.resource.WebAppResourceLoader; import blade.Blade; import blade.BladeWebContext; @@ -29,9 +31,11 @@ public class BeetlRender extends Render { * 默认构造函数 */ public BeetlRender() { - String root = Blade.webRoot(); - FileResourceLoader resourceLoader = new FileResourceLoader(root,"utf-8"); try { + String root = Blade.webRoot() + Blade.viewPath(); + WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); + resourceLoader.setAutoCheck(true); + resourceLoader.setRoot(root); Configuration cfg = Configuration.defaultConfiguration(); groupTemplate = new GroupTemplate(resourceLoader, cfg); } catch (IOException e) { @@ -39,6 +43,20 @@ public BeetlRender() { } } + public BeetlRender(Configuration configuration) { + try { + String root = Blade.webRoot() + Blade.viewPath(); + WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); + resourceLoader.setAutoCheck(true); + resourceLoader.setRoot(root); + Configuration cfg = Configuration.defaultConfiguration(); + groupTemplate = new GroupTemplate(resourceLoader, cfg); + groupTemplate.setConf(configuration); + } catch (IOException e) { + e.printStackTrace(); + } + } + /** * 渲染视图 */ @@ -90,6 +108,8 @@ public Object render(ModelAndView modelAndView) { Template template = groupTemplate.getTemplate(view); + Map context = modelAndView.getModel(); + Enumeration attrs = servletRequest.getAttributeNames(); if(null != attrs && attrs.hasMoreElements()){ @@ -99,6 +119,13 @@ public Object render(ModelAndView modelAndView) { } } + if(null != context && context.size() > 0){ + Set keys = context.keySet(); + for(String key : keys){ + template.binding(key, context.get(key)); + } + } + template.renderTo(servletResponse.getOutputStream()); } catch (BeetlException e) { e.printStackTrace(); @@ -109,4 +136,18 @@ public Object render(ModelAndView modelAndView) { return null; } + /** + * 处理视图 + * @param view 视图名称 + * @return 返回取出多余"/"的全路径 + */ + String disposeView(String view){ + if(null != view){ + view = view.replaceAll("[/]+", "/"); + if(!view.endsWith(Blade.viewExt())){ + view = view + Blade.viewExt(); + } + } + return view; + } } diff --git a/blade-core/src/main/java/blade/BladeWebContext.java b/blade-core/src/main/java/blade/BladeWebContext.java index 0b9b9300a..7bc2862c1 100644 --- a/blade-core/src/main/java/blade/BladeWebContext.java +++ b/blade-core/src/main/java/blade/BladeWebContext.java @@ -106,6 +106,7 @@ public static ServletContext servletContext() { * @param response HttpServletResponse对象 */ public static void put(Request request, Response response) { + remove(); currentRequest.set(request); currentResponse.set(response); } diff --git a/blade-kit/src/main/java/blade/kit/DateKit.java b/blade-kit/src/main/java/blade/kit/DateKit.java index ae3090d08..c8cfba44e 100644 --- a/blade-kit/src/main/java/blade/kit/DateKit.java +++ b/blade-kit/src/main/java/blade/kit/DateKit.java @@ -123,7 +123,6 @@ public static Date dateFormat(String date, String dateFormat) { /** * 使用默认格式 yyyy-MM-dd HH:mm:ss * - * @author Robin Chang * @param date * @return */ @@ -582,7 +581,6 @@ private static String getFormatTime(int time, int format) { * @param birthday * @return int * @exception - * @author 豆皮 * @Date Apr 24, 2008 */ public static int getUserAge(Date birthday) { @@ -604,19 +602,21 @@ public static int getUserAge(Date birthday) { * @param unixTime * 1970年至今的秒数 * @return - * @author 郑卿 */ public static Date getDateByUnixTime(int unixTime) { return new Date(unixTime * 1000L); } + public static int getCurrentUnixTime() { + return getUnixTimeByDate(new Date()); + } + /** * 将Date型时间转换成int型时间(1970年至今的秒数) * * @param unixTime * 1970年至今的秒数 * @return - * @author 郑卿 */ public static int getUnixTimeByDate(Date date) { return (int) (date.getTime() / 1000); @@ -765,7 +765,6 @@ public static long getSpecifyTimeSec(long time, int range) { * @param dateFormat * 时间格式 * @return - * @author sky */ public static String formatDateByUnixTime(long unixTime, String dateFormat) { return dateFormat(new Date(unixTime * 1000), dateFormat); From 5eaca837a6b37817d8c8ff6d281078987b9905a7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 15 Jul 2015 15:11:53 +0800 Subject: [PATCH 015/545] add the model clear the cache function --- .../src/main/java/blade/plugin/sql2o/Model.java | 16 ++++++++++++++++ .../plugin/sql2o/cache/SimpleSql2oCache.java | 5 +++++ .../blade/plugin/sql2o/cache/Sql2oCache.java | 1 + 3 files changed, 22 insertions(+) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index cd1f2b445..3d9bc5571 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -697,6 +697,14 @@ public List> fetchListMap(){ @SuppressWarnings("unchecked") public Page fetchPage(Integer page, Integer pageSize){ + if(null == page || page < 1){ + page = 1; + } + + if(null == pageSize || pageSize < 1){ + pageSize = 1; + } + Page pageModel = new Page(0, page, pageSize); if(condition.dmlType.equals(DmlType.SELECT) && null != page && null != pageSize && page > 0 && pageSize > 0){ @@ -773,6 +781,14 @@ public Page fetchPage(Integer page, Integer pageSize){ */ public Page> fetchPageMap(Integer page, Integer pageSize){ + if(null == page || page < 1){ + page = 1; + } + + if(null == pageSize || pageSize < 1){ + pageSize = 1; + } + Page> pageMap = new Page>(0, page, pageSize); if(condition.dmlType.equals(DmlType.SELECT) && null != page && null != pageSize && page > 0 && pageSize > 0){ diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java index 3031b51e7..33b7a105d 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java @@ -102,5 +102,10 @@ public void hdel(String key, String field) { public void hsetlist(String key, String field, List value) { cache.hset(key, field, value); } + + @Override + public void clean() { + cache.clear(); + } } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java index 47cb9c07f..f43f604a3 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java @@ -32,4 +32,5 @@ public interface Sql2oCache { void hdel(String key, String field); + void clean(); } From 4bbfb77a7c07c930ae84d67100b966cca07e8c7d Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 16 Jul 2015 10:53:41 +0800 Subject: [PATCH 016/545] optimize sql2o print statements --- .../java/blade/plugin/sql2o/Condition.java | 44 ++++++++----------- .../main/java/blade/plugin/sql2o/Model.java | 6 +-- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java index 2ac162eb8..f311738a7 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java @@ -1,8 +1,9 @@ package blade.plugin.sql2o; import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; import java.util.Map; -import java.util.Set; import blade.kit.CollectionKit; import blade.kit.StringKit; @@ -44,6 +45,8 @@ public class Condition { // in Map inParams; + List logParams = new LinkedList(); + enum DmlType { SELECT, COUNT, INSERT, UPDATE, DELETE } @@ -106,30 +109,9 @@ public String filterKeyWord(String field) { * 打印参数列表 */ public void printLog() { - if (null != equalsParams && equalsParams.size() > 0) { - LOGGER.debug("execute parameter:" + equalsParams.values()); - } - if (null != greaterParams && greaterParams.size() > 0) { - LOGGER.debug("execute parameter:" + greaterParams.values()); - } - if (null != lessParams && lessParams.size() > 0) { - LOGGER.debug("execute parameter:" + lessParams.values()); - } - if (null != greaterThanParams && greaterThanParams.size() > 0) { - LOGGER.debug("execute parameter:" + greaterThanParams.values()); - } - if (null != lessThanParams && lessThanParams.size() > 0) { - LOGGER.debug("execute parameter:" + lessThanParams.values()); - } - if (null != likeParams && likeParams.size() > 0) { - LOGGER.debug("execute parameter:" + likeParams.values()); - } - if (null != inParams && inParams.size() > 0) { - Set keys = inParams.keySet(); - for (String name : keys) { - LOGGER.debug("execute parameter:" - + Arrays.toString(inParams.get(name))); - } + + if (null != logParams && logParams.size() > 0) { + LOGGER.debug("execute parameter:" + logParams.toString()); } } @@ -178,6 +160,9 @@ public void clearMap() { this.inParams = null; } + if(null != this.logParams){ + this.logParams.clear(); + } } public void select() { @@ -275,6 +260,7 @@ public void delete(String sql){ public void param(String name, Object value){ if(StringKit.isNotBlank(name) && null != value){ this.params.put(name, value); + this.logParams.add(value); } } @@ -287,6 +273,7 @@ public void param(String name, Object value){ public void where(String name, Object value){ if(StringKit.isNotBlank(name) && null != value){ this.equalsParams.put(name, value); + this.logParams.add(value); } } @@ -302,6 +289,7 @@ public void greater(String name, Object value){ this.greaterParams = CollectionKit.newHashMap(); } this.greaterParams.put(name, value); + this.logParams.add(value); } } @@ -317,6 +305,7 @@ public void greaterThan(String name, Object value){ this.greaterThanParams = CollectionKit.newHashMap(); } this.greaterThanParams.put(name, value); + this.logParams.add(value); } } @@ -333,6 +322,7 @@ public void less(String name, Object value){ this.lessParams = CollectionKit.newHashMap(); } this.lessParams.put(name, value); + this.logParams.add(value); } } @@ -348,8 +338,8 @@ public void lessThan(String name, Object value){ if(null == this.lessThanParams){ this.lessThanParams = CollectionKit.newHashMap(); } - this.lessThanParams.put(name, value); + this.logParams.add(value); } } @@ -368,6 +358,7 @@ public void like(String name, String value){ this.likeParams = CollectionKit.newHashMap(); } this.likeParams.put(name, value); + this.logParams.add(value); } } @@ -383,6 +374,7 @@ public void in(String name, Object... values){ this.inParams = CollectionKit.newHashMap(); } this.inParams.put(name, values); + this.logParams.add(Arrays.toString(values)); } } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 3d9bc5571..9ff186d55 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -740,9 +740,9 @@ public Page fetchPage(Integer page, Integer pageSize){ sqlEnd += " limit :page, :pageSize"; - condition.equalsParams.put("page", page - 1); - condition.equalsParams.put("pageSize", pageSize); - + condition.where("page", page - 1); + condition.where("pageSize", pageSize); + try { // 设置query Connection conn = sql2o.open(); From 79e44e38ce35ab1fd73d08ccd8aad01e999768ad Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 16 Jul 2015 16:49:46 +0800 Subject: [PATCH 017/545] fix sql2o model fetchByPK bug --- .../src/main/java/blade/plugin/sql2o/Model.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 9ff186d55..65d4c0ed0 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -67,7 +67,7 @@ public static Model getModel(Class clazz){ public Model() { this.model = this.getClass(); - this.condition = new Condition(table(), pk()); + this.condition = new Condition(this.table(), this.pk()); } public Model(Class clazz) { @@ -331,7 +331,7 @@ private String getCacheKey(String sql){ cacheSql = cacheSql.substring(0, cacheSql.length() - 5); } - if(null != condition.orderby){ + if(StringKit.isNotBlank(condition.orderby)){ cacheSql += " order by " + condition.orderby; } @@ -557,10 +557,11 @@ public M fetchOne(){ @SuppressWarnings("unchecked") public M fetchByPk(Serializable pk){ + M res = null; - if(condition.dmlType.equals(DmlType.SELECT) && null != pk){ + if(null != pk){ + this.select(); - M res = null; String field = null; // 启用缓存 if(isCache()){ @@ -587,13 +588,11 @@ public M fetchByPk(Serializable pk){ if(isCache() && null != res){ sql2oCache.hset(CACHE_KEY_DETAIL, field, res); } - return res; } catch (Exception e) { LOGGER.error(e); } - } - return null; + return res; } /** From 2a80d05e1cd963d188e8c7f7106ae10ffb108e31 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 16 Jul 2015 17:27:48 +0800 Subject: [PATCH 018/545] updated version to 1.2.2 --- blade-sql2o/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index bcf385ac0..c8acfd516 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - 1.2.2 + ${blade.version} blade-sql2o https://github.com/biezhi/blade/blade-sql2o diff --git a/pom.xml b/pom.xml index dbbebd430..e42573f52 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ 1.6 UTF-8 4.11 - 1.2.1 + 1.2.2 3.0.1 From bb0c4e8fbe43efdf6893f749637cd1b87c92e4b9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 16 Jul 2015 17:39:22 +0800 Subject: [PATCH 019/545] update readme --- README.md | 11 ++++++++--- README_EN.md | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 95b7bc03d..259bf8d20 100644 --- a/README.md +++ b/README.md @@ -116,12 +116,17 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ### 计划 1. 完善文档 - 2. 完成用`blade`开发的单用户博客系统 - 3. 编写英文文档 - 4. 优化代码性能 + 2. 用`blade`开发单用户博客系统、音乐系统、图片系统等 + 3. 优化代码性能 + 4. 编写英文文档 ## 更新日志 +### v1.2.2 + 1. `DateKit`添加获取当前unix时间戳 + 2. 修复`blade-sql2o`分页bug + 3. 修复`blade-beetl`没有存储`ModelAndView`的数据 + ### v1.2 1. 修复sql2o更新Bug 2. 去除blade-kit无用类 diff --git a/README_EN.md b/README_EN.md index 0e542d6c9..d0d8d59d6 100644 --- a/README_EN.md +++ b/README_EN.md @@ -118,12 +118,17 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ### Plan 1. Perfect the documents - 2. Complete with `blade` single-user blog system development - 3. Write English document - 4. Optimize the code performance + 2. With `blade` development single-user blog system, music, pictures, etc + 3. Optimize the code performance + 4. Write English document ### Update +### v1.2.2 + 1. `DateKit` added to obtain the current Unix timestamp + 2. fix `blade-sql2o` paging bug + 3. fix `blade-beetl` not stored `ModelAndView` data + ### v1.2 1. Update Bug fix sql2o 2. Remove the blade-kit useless class From 458ab69347709a6eb5a207b96e441e80aadb146a Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 16 Jul 2015 17:40:02 +0800 Subject: [PATCH 020/545] update readme --- README.md | 2 +- README_EN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 259bf8d20..87ef6c21b 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ com.bladejava blade-core - 1.2.1 + 1.2.2 ``` diff --git a/README_EN.md b/README_EN.md index d0d8d59d6..acdf274bd 100644 --- a/README_EN.md +++ b/README_EN.md @@ -33,7 +33,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.1 + 1.2.2 ``` From 8edd0d44d750ceddb056714a9f08e54297993e50 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 17 Jul 2015 09:45:34 +0800 Subject: [PATCH 021/545] add blade-cache readme --- blade-cache/README.md | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 blade-cache/README.md diff --git a/blade-cache/README.md b/blade-cache/README.md new file mode 100644 index 000000000..7f72ca454 --- /dev/null +++ b/blade-cache/README.md @@ -0,0 +1,56 @@ +# blade-cache + +一个简单的缓存引擎,内部有基于`FIFO`,`LFU`,`LRU`算法的基本实现。 + +## 使用 +```java +public class CacheTest { + + @Test + public void testLRU2(){ + CacheManager cm = CacheManager.getInstance(); + + Cache cache = cm.newLRUCache(); + cache.set("name:1", "jack"); + cache.set("name:2", "jack2"); + + System.out.println(cache.get("name:2")); + + } + + @Test + public void testAutoClean(){ + CacheManager cm = CacheManager.getInstance(); + cm.setCleanInterval(1000); + + Cache cache = cm.newLRUCache(); + cache.set("name:1", "jack"); + cache.set("name:2", "jack2"); + + System.out.println(cache.get("name:2")); + + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println(cache.get("name:2")); + } + + @Test + public void testHashCache(){ + CacheManager cm = CacheManager.getInstance(); + + Cache cache = cm.newLRUCache(); + cache.hset("user:list", "a1", "123"); + cache.hset("user:list", "a2", "456"); + cache.hset("user:list", "a3", "789"); + + System.out.println(cache.hget("user:list", "a1")); + System.out.println(cache.hget("user:list", "a2")); + System.out.println(cache.hget("user:list", "a3")); + + } + +} +``` \ No newline at end of file From c62227f86c08dd347817448a82df50783ba015a7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 17 Jul 2015 09:48:33 +0800 Subject: [PATCH 022/545] update readme --- blade-core/README.md | 3 +++ blade-sql2o/README.md | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 blade-core/README.md diff --git a/blade-core/README.md b/blade-core/README.md new file mode 100644 index 000000000..9d3e67164 --- /dev/null +++ b/blade-core/README.md @@ -0,0 +1,3 @@ +# blade-core + +`blade`框架核心库,是整个web运行的基础服务。 \ No newline at end of file diff --git a/blade-sql2o/README.md b/blade-sql2o/README.md index 38c2a0303..3d5b8ee3c 100644 --- a/blade-sql2o/README.md +++ b/blade-sql2o/README.md @@ -91,11 +91,14 @@ Long count = model.delete().where("pid", pid).executeAndCommit(); ``` -### v1.1.4 - 1. 添加动态数据源支持 +### v1.2.x + 1. 修复分页bug + 2. 修复按主键查询bug + 3. 添加内置缓存支持 -### v1.1.3 +### v1.1.x 1. 适配`blade`最新版本 + 2. 添加动态数据源支持 ### 联系我 Mail: biezhi.me#gmail.com From d74933fab3b6575ddda6d2684470f5d0ed92d098 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 17 Jul 2015 10:07:56 +0800 Subject: [PATCH 023/545] fix primary key cache bug --- blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java | 4 ++++ blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java index f311738a7..3eac041fd 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java @@ -169,6 +169,7 @@ public void select() { this.sql = "select * from " + this.tableName; this.equalsParams = CollectionKit.newHashMap(); this.dmlType = DmlType.SELECT; + this.orderby = null; } /** @@ -179,6 +180,7 @@ public void select(String sql) { this.sql = sql; this.equalsParams = CollectionKit.newHashMap(); this.dmlType = DmlType.SELECT; + this.orderby = null; } /** @@ -188,6 +190,7 @@ public void count(){ this.sql = "select count(1) from " + this.tableName; this.equalsParams = CollectionKit.newHashMap(); this.dmlType = DmlType.COUNT; + this.orderby = null; } /** @@ -199,6 +202,7 @@ public void count(String sql){ this.sql = sql; this.equalsParams = CollectionKit.newHashMap(); this.dmlType = DmlType.COUNT; + this.orderby = null; } public void update(){ diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 65d4c0ed0..cbd7c35a9 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -560,14 +560,15 @@ public M fetchByPk(Serializable pk){ M res = null; if(null != pk){ - this.select(); + + this.select().where(this.pk(), pk); String field = null; // 启用缓存 if(isCache()){ + field = MD5.create(getCacheKey(null)); res = sql2oCache.hget(CACHE_KEY_DETAIL, field); - if(null != res){ return res; } From f2c48af890a3029346385acf104e41f9772dce39 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 17 Jul 2015 10:34:11 +0800 Subject: [PATCH 024/545] add last version md --- LAST_VERSION.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 4 +-- README_EN.md | 4 +-- 3 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 LAST_VERSION.md diff --git a/LAST_VERSION.md b/LAST_VERSION.md new file mode 100644 index 000000000..6da5adc73 --- /dev/null +++ b/LAST_VERSION.md @@ -0,0 +1,72 @@ +# blade last version + +## blade-kit +```xml + +    com.bladejava +    blade-kit +    1.2.2 + +``` + +## blade-core +```xml + +    com.bladejava +    blade-core +    1.2.3 + +``` +## blade-sql2o +```xml + +    com.bladejava +    blade-sql2o +    1.2.3 + +``` + +## blade-jetbrick +```xml + +    com.bladejava +    blade-jetbrick +    1.2.2 + +``` + +## blade-beetl +```xml + +    com.bladejava +    blade-beetl +    1.2.2 + +``` + +## blade-velocity +```xml + +    com.bladejava +    blade-velocity +    1.2.1 + +``` + +## blade-cache +```xml + +    com.bladejava +    blade-cache +    1.2.2 + +``` + +## blade-redis +```xml + +    com.bladejava +    blade-redis +    1.2.1 + +``` \ No newline at end of file diff --git a/README.md b/README.md index 87ef6c21b..40de2dca3 100644 --- a/README.md +++ b/README.md @@ -25,13 +25,13 @@ * ... ## 快速入门 -第一步、用maven构建一个webapp,加入blade的依赖,推荐获取[最新版本](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +第一步、用maven构建一个webapp,加入blade的依赖,推荐获取[最新版本](LAST_VERSION.md) ```xml com.bladejava blade-core - 1.2.2 + 1.2.3 ``` diff --git a/README_EN.md b/README_EN.md index acdf274bd..3b1cf5439 100644 --- a/README_EN.md +++ b/README_EN.md @@ -27,13 +27,13 @@ * ... ## Quick start -First. Use maven to build a webapp, join dependency on the blade,Recommended for the [latest version](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +First. Use maven to build a webapp, join dependency on the blade,Recommended for the [latest version](LAST_VERSION.md) ```xml com.bladejava blade-core - 1.2.2 + 1.2.3 ``` From 2fa09982dad8bd7805b678316a519616bb2bd3d8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 17 Jul 2015 10:37:01 +0800 Subject: [PATCH 025/545] - --- LAST_VERSION.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 6da5adc73..f2a4b72d6 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -1,6 +1,6 @@ # blade last version -## blade-kit +## [blade-kit](http://search.maven.org/#search%7Cga%7C1%7Cblade-kit) ```xml     com.bladejava @@ -9,7 +9,7 @@ ``` -## blade-core +## [blade-core](http://search.maven.org/#search%7Cga%7C1%7Cblade-core) ```xml     com.bladejava @@ -17,7 +17,7 @@     1.2.3 ``` -## blade-sql2o +## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) ```xml     com.bladejava @@ -26,7 +26,7 @@ ``` -## blade-jetbrick +## [blade-jetbrick](http://search.maven.org/#search%7Cga%7C1%7Cblade-jetbrick) ```xml     com.bladejava @@ -35,7 +35,7 @@ ``` -## blade-beetl +## [blade-beetl](http://search.maven.org/#search%7Cga%7C1%7Cblade-beetl) ```xml     com.bladejava @@ -44,7 +44,7 @@ ``` -## blade-velocity +## [blade-velocity](http://search.maven.org/#search%7Cga%7C1%7Cblade-velocity) ```xml     com.bladejava @@ -53,7 +53,7 @@ ``` -## blade-cache +## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache) ```xml     com.bladejava @@ -62,7 +62,7 @@ ``` -## blade-redis +## [blade-redis](http://search.maven.org/#search%7Cga%7C1%7Cblade-redis) ```xml     com.bladejava From 619ebbbc4a0c1295d4c48bb8eab526a41e087e31 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 17 Jul 2015 10:59:43 +0800 Subject: [PATCH 026/545] optimization of the timer --- LAST_VERSION.md | 2 +- .../src/main/java/blade/kit/TimwKit.java | 15 ++++-- .../main/java/blade/kit/timw/TimwMonitor.java | 47 ++++++++++++------- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index f2a4b72d6..0d637c0f5 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -5,7 +5,7 @@     com.bladejava     blade-kit -    1.2.2 +    1.2.3 ``` diff --git a/blade-kit/src/main/java/blade/kit/TimwKit.java b/blade-kit/src/main/java/blade/kit/TimwKit.java index 73b5b043d..409cf284e 100644 --- a/blade-kit/src/main/java/blade/kit/TimwKit.java +++ b/blade-kit/src/main/java/blade/kit/TimwKit.java @@ -17,6 +17,7 @@ import java.math.BigDecimal; import java.util.ArrayList; +import java.util.List; import blade.kit.log.Logger; @@ -56,16 +57,24 @@ public void clear() { * * @return */ - public Number size() { + public int size() { return numList.size(); } + public List numbers() { + return numList; + } + + public Number current() { + return numList.get(numList.size() - 1); + } + /** * 获取平均数 * * @return */ - public Number getAverage() { + public Number avg() { if (numList.size() == 0) { return 0; } else { @@ -94,7 +103,7 @@ public String print() { * @return */ public String printAvg() { - Number number = getAverage(); + Number number = avg(); BigDecimal b = new BigDecimal(number.doubleValue()); double avg = b.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue(); String str = "平均耗时: " + avg + " ms"; diff --git a/blade-kit/src/main/java/blade/kit/timw/TimwMonitor.java b/blade-kit/src/main/java/blade/kit/timw/TimwMonitor.java index a721e172c..945179b07 100644 --- a/blade-kit/src/main/java/blade/kit/timw/TimwMonitor.java +++ b/blade-kit/src/main/java/blade/kit/timw/TimwMonitor.java @@ -31,77 +31,88 @@ public class TimwMonitor { /** * 计时器 */ - private TimwCounter timeKit; + private TimwCounter timeCounter; /** * 均值器 */ - private TimwKit averager; + private TimwKit timwKit; TimwMonitor() { - this.timeKit = new TimwCounter(); - this.averager = new TimwKit(); + this.timeCounter = new TimwCounter(); + this.timwKit = new TimwKit(); } - public TimwCounter getTimeKit() { - return timeKit; + public TimwCounter getTimeCounter() { + return timeCounter; } - public TimwKit getAverager() { - return averager; + public TimwKit getTimwKit() { + return timwKit; } /** * 一个计时开始 */ public void start() { - timeKit.start(); + timeCounter.start(); } /** * 一个计时结束 */ public void end() { - long time = timeKit.duration(); - averager.add(time); + long time = timeCounter.duration(); + timwKit.add(time); } /** * 一个计时结束,并且启动下次计时。 */ public long endAndRestart() { - long time = timeKit.durationRestart(); - averager.add(time); + long time = timeCounter.durationRestart(); + timwKit.add(time); return time; } + public int size() { + return timwKit.size(); + } + + /** + * 求全部计时均值 + */ + public Number avg() { + return timwKit.avg(); + } + /** * 求全部计时均值 */ - public Number average() { - return averager.getAverage(); + public Number current() { + return timwKit.current(); } /** * 打印全部时间值 */ public String render() { - return averager.print(); + return timwKit.print(); } /** * 打印全部时间值 */ public String renderAvg() { - return averager.printAvg(); + return timwKit.printAvg(); } /** * 清楚数据 */ public void clear() { - averager.clear(); + timwKit.clear(); } } From 8c47b0a360799289d3fdf89ee83c561bc8728048 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 17 Jul 2015 14:01:44 +0800 Subject: [PATCH 027/545] update readme --- README.md | 1 + README_EN.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 40de2dca3..3a7eebe0f 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) +[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) **blade** 是一个简洁强大的web框架,它内置了`IOC`管理,拦截器配置,`REST API`开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送等常用功能,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! diff --git a/README_EN.md b/README_EN.md index 3b1cf5439..2b88d6493 100644 --- a/README_EN.md +++ b/README_EN.md @@ -7,6 +7,7 @@ [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) +[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) ## Introduction From 10ed0d62ae7120a69e94713ebecf5b00da59f888 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 20 Jul 2015 15:27:59 +0800 Subject: [PATCH 028/545] add json parser and add config file --- blade-core/src/main/java/blade/BladeBase.java | 40 + .../main/java/blade/server/BladeServer.java | 2 +- .../main/java/blade/kit/json/JSONArray.java | 1061 ++++++++++ .../java/blade/kit/json/JSONException.java | 43 + .../src/main/java/blade/kit/json/JSONKit.java | 80 + .../src/main/java/blade/kit/json/JSONMap.java | 38 + .../main/java/blade/kit/json/JSONObject.java | 1779 +++++++++++++++++ .../main/java/blade/kit/json/JSONString.java | 18 + .../java/blade/kit/json/JSONStringer.java | 78 + .../main/java/blade/kit/json/JSONTokener.java | 446 +++++ .../main/java/blade/kit/json/JSONWriter.java | 327 +++ .../src/test/java/blade/test/JSONTest.java | 36 + 12 files changed, 3947 insertions(+), 1 deletion(-) create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONArray.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONException.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONKit.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONMap.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONObject.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONString.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONStringer.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONTokener.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONWriter.java create mode 100644 blade-kit/src/test/java/blade/test/JSONTest.java diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index d9bebb8ac..e396ee40e 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -15,12 +15,17 @@ */ package blade; +import java.io.IOException; +import java.io.InputStream; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; import blade.ioc.Container; import blade.ioc.DefaultContainer; +import blade.kit.IOKit; +import blade.kit.PropertyKit; +import blade.kit.json.JSONKit; import blade.render.Render; import blade.render.RenderFactory; import blade.route.DefaultRouteMatcher; @@ -48,6 +53,8 @@ abstract class BladeBase { public static final Charset UTF_8 = Charset.forName("UTF-8"); + public static Map confMap = null; + /** * 是否以jetty方式运行 */ @@ -464,6 +471,39 @@ public static synchronized void register(Object object){ container.registBean(object); } + /** + * 设置配置文件名称 + * @param confName 配置文件名称 + */ + public static synchronized void config(String confName){ + confMap = PropertyKit.getPropertyMap(confName); + + } + + /** + * 设置JSON配置文件名称 + * @param confName 配置文件名称 + */ + public static synchronized void configJsonPath(String jsonPath){ + InputStream inputStream = BladeBase.class.getResourceAsStream(jsonPath); + if(null != inputStream){ + try { + String json = IOKit.toString(inputStream); + confMap = JSONKit.toMap(json); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 设置JSON配置 + * @param json json配置 + */ + public static synchronized void configJson(String json){ + confMap = JSONKit.toMap(json); + } + static synchronized void init() { BladeBase.IS_INIT = true; } diff --git a/blade-core/src/main/java/blade/server/BladeServer.java b/blade-core/src/main/java/blade/server/BladeServer.java index 820782515..2957aa5de 100644 --- a/blade-core/src/main/java/blade/server/BladeServer.java +++ b/blade-core/src/main/java/blade/server/BladeServer.java @@ -112,7 +112,7 @@ public static void run(Integer port, String host, String contextPath){ } if(null == host){ - host = "0.0.0.0"; + host = "127.0.0.1"; } if(null == contextPath){ diff --git a/blade-kit/src/main/java/blade/kit/json/JSONArray.java b/blade-kit/src/main/java/blade/kit/json/JSONArray.java new file mode 100644 index 000000000..c2fa9e2ac --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONArray.java @@ -0,0 +1,1061 @@ +package blade.kit.json; + +/* + Copyright (c) 2002 JSON.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + The Software shall be used for Good, not Evil. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Array; +import java.math.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +/** + * A JSONArray is an ordered sequence of values. Its external text form is a + * string wrapped in square brackets with commas separating the values. The + * internal form is an object having get and opt + * methods for accessing the values by index, and put methods for + * adding or replacing values. The values can be any of these types: + * Boolean, JSONArray, JSONObject, + * Number, String, or the + * JSONObject.NULL object. + *

+ * The constructor can convert a JSON text into a Java object. The + * toString method converts to JSON text. + *

+ * A get method returns a value if one can be found, and throws an + * exception if one cannot be found. An opt method returns a + * default value instead of throwing an exception, and so is useful for + * obtaining optional values. + *

+ * The generic get() and opt() methods return an + * object which you can cast or query for type. There are also typed + * get and opt methods that do type checking and type + * coercion for you. + *

+ * The texts produced by the toString methods strictly conform to + * JSON syntax rules. The constructors are more forgiving in the texts they will + * accept: + *

    + *
  • An extra , (comma) may appear just + * before the closing bracket.
  • + *
  • The null value will be inserted when there is , + *  (comma) elision.
  • + *
  • Strings may be quoted with ' (single + * quote).
  • + *
  • Strings do not need to be quoted at all if they do not begin with a quote + * or single quote, and if they do not contain leading or trailing spaces, and + * if they do not contain any of these characters: + * { } [ ] / \ : , # and if they do not look like numbers and + * if they are not the reserved words true, false, or + * null.
  • + *
+ * + * @author JSON.org + * @version 2015-07-06 + */ +public class JSONArray implements Iterable { + + /** + * The arrayList where the JSONArray's properties are kept. + */ + private final ArrayList myArrayList; + + /** + * Construct an empty JSONArray. + */ + public JSONArray() { + this.myArrayList = new ArrayList(); + } + + /** + * Construct a JSONArray from a JSONTokener. + * + * @param x + * A JSONTokener + * @throws JSONException + * If there is a syntax error. + */ + public JSONArray(JSONTokener x) throws JSONException { + this(); + if (x.nextClean() != '[') { + throw x.syntaxError("A JSONArray text must start with '['"); + } + if (x.nextClean() != ']') { + x.back(); + for (;;) { + if (x.nextClean() == ',') { + x.back(); + this.myArrayList.add(JSONObject.NULL); + } else { + x.back(); + this.myArrayList.add(x.nextValue()); + } + switch (x.nextClean()) { + case ',': + if (x.nextClean() == ']') { + return; + } + x.back(); + break; + case ']': + return; + default: + throw x.syntaxError("Expected a ',' or ']'"); + } + } + } + } + + /** + * Construct a JSONArray from a source JSON text. + * + * @param source + * A string that begins with [ (left + * bracket) and ends with ] + *  (right bracket). + * @throws JSONException + * If there is a syntax error. + */ + public JSONArray(String source) throws JSONException { + this(new JSONTokener(source)); + } + + /** + * Construct a JSONArray from a Collection. + * + * @param collection + * A Collection. + */ + public JSONArray(Collection collection) { + this.myArrayList = new ArrayList(); + if (collection != null) { + Iterator iter = collection.iterator(); + while (iter.hasNext()) { + this.myArrayList.add(JSONObject.wrap(iter.next())); + } + } + } + + /** + * Construct a JSONArray from an array + * + * @throws JSONException + * If not an array. + */ + public JSONArray(Object array) throws JSONException { + this(); + if (array.getClass().isArray()) { + int length = Array.getLength(array); + for (int i = 0; i < length; i += 1) { + this.put(JSONObject.wrap(Array.get(array, i))); + } + } else { + throw new JSONException( + "JSONArray initial value should be a string or collection or array."); + } + } + + @Override + public Iterator iterator() { + return myArrayList.iterator(); + } + + /** + * Get the object value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return An object value. + * @throws JSONException + * If there is no value for the index. + */ + public Object get(int index) throws JSONException { + Object object = this.opt(index); + if (object == null) { + throw new JSONException("JSONArray[" + index + "] not found."); + } + return object; + } + + /** + * Get the boolean value associated with an index. The string values "true" + * and "false" are converted to boolean. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The truth. + * @throws JSONException + * If there is no value for the index or if the value is not + * convertible to boolean. + */ + public boolean getBoolean(int index) throws JSONException { + Object object = this.get(index); + if (object.equals(Boolean.FALSE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("false"))) { + return false; + } else if (object.equals(Boolean.TRUE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("true"))) { + return true; + } + throw new JSONException("JSONArray[" + index + "] is not a boolean."); + } + + /** + * Get the double value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a number. + */ + public double getDouble(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number ? ((Number) object).doubleValue() + : Double.parseDouble((String) object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + "] is not a number."); + } + } + + /** + * Get the BigDecimal value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a BigDecimal. + */ + public BigDecimal getBigDecimal (int index) throws JSONException { + Object object = this.get(index); + try { + return new BigDecimal(object.toString()); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + + "] could not convert to BigDecimal."); + } + } + + /** + * Get the BigInteger value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a BigInteger. + */ + public BigInteger getBigInteger (int index) throws JSONException { + Object object = this.get(index); + try { + return new BigInteger(object.toString()); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + + "] could not convert to BigInteger."); + } + } + + /** + * Get the int value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value is not a number. + */ + public int getInt(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number ? ((Number) object).intValue() + : Integer.parseInt((String) object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + "] is not a number."); + } + } + + /** + * Get the JSONArray associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A JSONArray value. + * @throws JSONException + * If there is no value for the index. or if the value is not a + * JSONArray + */ + public JSONArray getJSONArray(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof JSONArray) { + return (JSONArray) object; + } + throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); + } + + /** + * Get the JSONObject associated with an index. + * + * @param index + * subscript + * @return A JSONObject value. + * @throws JSONException + * If there is no value for the index or if the value is not a + * JSONObject + */ + public JSONObject getJSONObject(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof JSONObject) { + return (JSONObject) object; + } + throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); + } + + /** + * Get the long value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a number. + */ + public long getLong(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number ? ((Number) object).longValue() + : Long.parseLong((String) object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + "] is not a number."); + } + } + + /** + * Get the string associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A string value. + * @throws JSONException + * If there is no string value for the index. + */ + public String getString(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof String) { + return (String) object; + } + throw new JSONException("JSONArray[" + index + "] not a string."); + } + + /** + * Determine if the value is null. + * + * @param index + * The index must be between 0 and length() - 1. + * @return true if the value at the index is null, or if there is no value. + */ + public boolean isNull(int index) { + return JSONObject.NULL.equals(this.opt(index)); + } + + /** + * Make a string from the contents of this JSONArray. The + * separator string is inserted between each element. Warning: + * This method assumes that the data structure is acyclical. + * + * @param separator + * A string that will be inserted between the elements. + * @return a string. + * @throws JSONException + * If the array contains an invalid number. + */ + public String join(String separator) throws JSONException { + int len = this.length(); + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < len; i += 1) { + if (i > 0) { + sb.append(separator); + } + sb.append(JSONObject.valueToString(this.myArrayList.get(i))); + } + return sb.toString(); + } + + /** + * Get the number of elements in the JSONArray, included nulls. + * + * @return The length (or size). + */ + public int length() { + return this.myArrayList.size(); + } + + /** + * Get the optional object value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return An object value, or null if there is no object at that index. + */ + public Object opt(int index) { + return (index < 0 || index >= this.length()) ? null : this.myArrayList + .get(index); + } + + /** + * Get the optional boolean value associated with an index. It returns false + * if there is no value at that index, or if the value is not Boolean.TRUE + * or the String "true". + * + * @param index + * The index must be between 0 and length() - 1. + * @return The truth. + */ + public boolean optBoolean(int index) { + return this.optBoolean(index, false); + } + + /** + * Get the optional boolean value associated with an index. It returns the + * defaultValue if there is no value at that index or if it is not a Boolean + * or the String "true" or "false" (case insensitive). + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * A boolean default. + * @return The truth. + */ + public boolean optBoolean(int index, boolean defaultValue) { + try { + return this.getBoolean(index); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get the optional double value associated with an index. NaN is returned + * if there is no value for the index, or if the value is not a number and + * cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + */ + public double optDouble(int index) { + return this.optDouble(index, Double.NaN); + } + + /** + * Get the optional double value associated with an index. The defaultValue + * is returned if there is no value for the index, or if the value is not a + * number and cannot be converted to a number. + * + * @param index + * subscript + * @param defaultValue + * The default value. + * @return The value. + */ + public double optDouble(int index, double defaultValue) { + try { + return this.getDouble(index); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get the optional int value associated with an index. Zero is returned if + * there is no value for the index, or if the value is not a number and + * cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + */ + public int optInt(int index) { + return this.optInt(index, 0); + } + + /** + * Get the optional int value associated with an index. The defaultValue is + * returned if there is no value for the index, or if the value is not a + * number and cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return The value. + */ + public int optInt(int index, int defaultValue) { + try { + return this.getInt(index); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get the optional BigInteger value associated with an index. The + * defaultValue is returned if there is no value for the index, or if the + * value is not a number and cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return The value. + */ + public BigInteger optBigInteger(int index, BigInteger defaultValue) { + try { + return this.getBigInteger(index); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get the optional BigDecimal value associated with an index. The + * defaultValue is returned if there is no value for the index, or if the + * value is not a number and cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return The value. + */ + public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) { + try { + return this.getBigDecimal(index); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get the optional JSONArray associated with an index. + * + * @param index + * subscript + * @return A JSONArray value, or null if the index has no value, or if the + * value is not a JSONArray. + */ + public JSONArray optJSONArray(int index) { + Object o = this.opt(index); + return o instanceof JSONArray ? (JSONArray) o : null; + } + + /** + * Get the optional JSONObject associated with an index. Null is returned if + * the key is not found, or null if the index has no value, or if the value + * is not a JSONObject. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A JSONObject value. + */ + public JSONObject optJSONObject(int index) { + Object o = this.opt(index); + return o instanceof JSONObject ? (JSONObject) o : null; + } + + /** + * Get the optional long value associated with an index. Zero is returned if + * there is no value for the index, or if the value is not a number and + * cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + */ + public long optLong(int index) { + return this.optLong(index, 0); + } + + /** + * Get the optional long value associated with an index. The defaultValue is + * returned if there is no value for the index, or if the value is not a + * number and cannot be converted to a number. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return The value. + */ + public long optLong(int index, long defaultValue) { + try { + return this.getLong(index); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get the optional string value associated with an index. It returns an + * empty string if there is no value at that index. If the value is not a + * string and is not null, then it is coverted to a string. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A String value. + */ + public String optString(int index) { + return this.optString(index, ""); + } + + /** + * Get the optional string associated with an index. The defaultValue is + * returned if the key is not found. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return A String value. + */ + public String optString(int index, String defaultValue) { + Object object = this.opt(index); + return JSONObject.NULL.equals(object) ? defaultValue : object + .toString(); + } + + /** + * Append a boolean value. This increases the array's length by one. + * + * @param value + * A boolean value. + * @return this. + */ + public JSONArray put(boolean value) { + this.put(value ? Boolean.TRUE : Boolean.FALSE); + return this; + } + + /** + * Put a value in the JSONArray, where the value will be a JSONArray which + * is produced from a Collection. + * + * @param value + * A Collection value. + * @return this. + */ + public JSONArray put(Collection value) { + this.put(new JSONArray(value)); + return this; + } + + /** + * Append a double value. This increases the array's length by one. + * + * @param value + * A double value. + * @throws JSONException + * if the value is not finite. + * @return this. + */ + public JSONArray put(double value) throws JSONException { + Double d = new Double(value); + JSONObject.testValidity(d); + this.put(d); + return this; + } + + /** + * Append an int value. This increases the array's length by one. + * + * @param value + * An int value. + * @return this. + */ + public JSONArray put(int value) { + this.put(new Integer(value)); + return this; + } + + /** + * Append an long value. This increases the array's length by one. + * + * @param value + * A long value. + * @return this. + */ + public JSONArray put(long value) { + this.put(new Long(value)); + return this; + } + + /** + * Put a value in the JSONArray, where the value will be a JSONObject which + * is produced from a Map. + * + * @param value + * A Map value. + * @return this. + */ + public JSONArray put(Map value) { + this.put(new JSONObject(value)); + return this; + } + + /** + * Append an object value. This increases the array's length by one. + * + * @param value + * An object value. The value should be a Boolean, Double, + * Integer, JSONArray, JSONObject, Long, or String, or the + * JSONObject.NULL object. + * @return this. + */ + public JSONArray put(Object value) { + this.myArrayList.add(value); + return this; + } + + /** + * Put or replace a boolean value in the JSONArray. If the index is greater + * than the length of the JSONArray, then null elements will be added as + * necessary to pad it out. + * + * @param index + * The subscript. + * @param value + * A boolean value. + * @return this. + * @throws JSONException + * If the index is negative. + */ + public JSONArray put(int index, boolean value) throws JSONException { + this.put(index, value ? Boolean.TRUE : Boolean.FALSE); + return this; + } + + /** + * Put a value in the JSONArray, where the value will be a JSONArray which + * is produced from a Collection. + * + * @param index + * The subscript. + * @param value + * A Collection value. + * @return this. + * @throws JSONException + * If the index is negative or if the value is not finite. + */ + public JSONArray put(int index, Collection value) throws JSONException { + this.put(index, new JSONArray(value)); + return this; + } + + /** + * Put or replace a double value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad it + * out. + * + * @param index + * The subscript. + * @param value + * A double value. + * @return this. + * @throws JSONException + * If the index is negative or if the value is not finite. + */ + public JSONArray put(int index, double value) throws JSONException { + this.put(index, new Double(value)); + return this; + } + + /** + * Put or replace an int value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad it + * out. + * + * @param index + * The subscript. + * @param value + * An int value. + * @return this. + * @throws JSONException + * If the index is negative. + */ + public JSONArray put(int index, int value) throws JSONException { + this.put(index, new Integer(value)); + return this; + } + + /** + * Put or replace a long value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad it + * out. + * + * @param index + * The subscript. + * @param value + * A long value. + * @return this. + * @throws JSONException + * If the index is negative. + */ + public JSONArray put(int index, long value) throws JSONException { + this.put(index, new Long(value)); + return this; + } + + /** + * Put a value in the JSONArray, where the value will be a JSONObject that + * is produced from a Map. + * + * @param index + * The subscript. + * @param value + * The Map value. + * @return this. + * @throws JSONException + * If the index is negative or if the the value is an invalid + * number. + */ + public JSONArray put(int index, Map value) throws JSONException { + this.put(index, new JSONObject(value)); + return this; + } + + /** + * Put or replace an object value in the JSONArray. If the index is greater + * than the length of the JSONArray, then null elements will be added as + * necessary to pad it out. + * + * @param index + * The subscript. + * @param value + * The value to put into the array. The value should be a + * Boolean, Double, Integer, JSONArray, JSONObject, Long, or + * String, or the JSONObject.NULL object. + * @return this. + * @throws JSONException + * If the index is negative or if the the value is an invalid + * number. + */ + public JSONArray put(int index, Object value) throws JSONException { + JSONObject.testValidity(value); + if (index < 0) { + throw new JSONException("JSONArray[" + index + "] not found."); + } + if (index < this.length()) { + this.myArrayList.set(index, value); + } else { + while (index != this.length()) { + this.put(JSONObject.NULL); + } + this.put(value); + } + return this; + } + + /** + * Remove an index and close the hole. + * + * @param index + * The index of the element to be removed. + * @return The value that was associated with the index, or null if there + * was no value. + */ + public Object remove(int index) { + return index >= 0 && index < this.length() + ? this.myArrayList.remove(index) + : null; + } + + /** + * Determine if two JSONArrays are similar. + * They must contain similar sequences. + * + * @param other The other JSONArray + * @return true if they are equal + */ + public boolean similar(Object other) { + if (!(other instanceof JSONArray)) { + return false; + } + int len = this.length(); + if (len != ((JSONArray)other).length()) { + return false; + } + for (int i = 0; i < len; i += 1) { + Object valueThis = this.get(i); + Object valueOther = ((JSONArray)other).get(i); + if (valueThis instanceof JSONObject) { + if (!((JSONObject)valueThis).similar(valueOther)) { + return false; + } + } else if (valueThis instanceof JSONArray) { + if (!((JSONArray)valueThis).similar(valueOther)) { + return false; + } + } else if (!valueThis.equals(valueOther)) { + return false; + } + } + return true; + } + + /** + * Produce a JSONObject by combining a JSONArray of names with the values of + * this JSONArray. + * + * @param names + * A JSONArray containing a list of key strings. These will be + * paired with the values. + * @return A JSONObject, or null if there are no names or if this JSONArray + * has no values. + * @throws JSONException + * If any of the names are null. + */ + public JSONObject toJSONObject(JSONArray names) throws JSONException { + if (names == null || names.length() == 0 || this.length() == 0) { + return null; + } + JSONObject jo = new JSONObject(); + for (int i = 0; i < names.length(); i += 1) { + jo.put(names.getString(i), this.opt(i)); + } + return jo; + } + + /** + * Make a JSON text of this JSONArray. For compactness, no unnecessary + * whitespace is added. If it is not possible to produce a syntactically + * correct JSON text then null will be returned instead. This could occur if + * the array contains an invalid number. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a printable, displayable, transmittable representation of the + * array. + */ + public String toString() { + try { + return this.toString(0); + } catch (Exception e) { + return null; + } + } + + /** + * Make a prettyprinted JSON text of this JSONArray. Warning: This method + * assumes that the data structure is acyclical. + * + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @return a printable, displayable, transmittable representation of the + * object, beginning with [ (left + * bracket) and ending with ] + *  (right bracket). + * @throws JSONException + */ + public String toString(int indentFactor) throws JSONException { + StringWriter sw = new StringWriter(); + synchronized (sw.getBuffer()) { + return this.write(sw, indentFactor, 0).toString(); + } + } + + /** + * Write the contents of the JSONArray as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + public Writer write(Writer writer) throws JSONException { + return this.write(writer, 0, 0); + } + + /** + * Write the contents of the JSONArray as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @param indent + * The indention of the top level. + * @return The writer. + * @throws JSONException + */ + Writer write(Writer writer, int indentFactor, int indent) + throws JSONException { + try { + boolean commanate = false; + int length = this.length(); + writer.write('['); + + if (length == 1) { + JSONObject.writeValue(writer, this.myArrayList.get(0), + indentFactor, indent); + } else if (length != 0) { + final int newindent = indent + indentFactor; + + for (int i = 0; i < length; i += 1) { + if (commanate) { + writer.write(','); + } + if (indentFactor > 0) { + writer.write('\n'); + } + JSONObject.indent(writer, newindent); + JSONObject.writeValue(writer, this.myArrayList.get(i), + indentFactor, newindent); + commanate = true; + } + if (indentFactor > 0) { + writer.write('\n'); + } + JSONObject.indent(writer, indent); + } + writer.write(']'); + return writer; + } catch (IOException e) { + throw new JSONException(e); + } + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONException.java b/blade-kit/src/main/java/blade/kit/json/JSONException.java new file mode 100644 index 000000000..1f0564e74 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONException.java @@ -0,0 +1,43 @@ +package blade.kit.json; + +/** + * The JSONException is thrown by the JSON.org classes when things are amiss. + * + * @author JSON.org + * @version 2014-05-03 + */ +public class JSONException extends RuntimeException { + private static final long serialVersionUID = 0; + private Throwable cause; + + /** + * Constructs a JSONException with an explanatory message. + * + * @param message + * Detail about the reason for the exception. + */ + public JSONException(String message) { + super(message); + } + + /** + * Constructs a new JSONException with the specified cause. + * @param cause The cause. + */ + public JSONException(Throwable cause) { + super(cause.getMessage()); + this.cause = cause; + } + + /** + * Returns the cause of this exception or null if the cause is nonexistent + * or unknown. + * + * @return the cause of this exception or null if the cause is nonexistent + * or unknown. + */ + @Override + public Throwable getCause() { + return this.cause; + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONKit.java b/blade-kit/src/main/java/blade/kit/json/JSONKit.java new file mode 100644 index 000000000..92d945034 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONKit.java @@ -0,0 +1,80 @@ +package blade.kit.json; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("unchecked") +public class JSONKit { + + public static Map toMap(String json){ + try { + JSONObject jsonObject = new JSONObject(json); + return JSONMap.toMap(jsonObject); + } catch (JSONException e) { + e.printStackTrace(); + } + return null; + } + + public static List toList(String json){ + JSONArray jsonArray = new JSONArray(json); + List list = new ArrayList(); + int len = jsonArray.length(); + for(int i=0; i String toJSONString(Map map){ + try { + return toJSON(map).toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static JSONObject toJSON(Map map){ + try { + JSONObject jsonObj = new JSONObject(); + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + try { + jsonObj.put(key, value); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return jsonObj; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static String toJSONString(List> list){ + if(null != list && list.size() > 0){ + JSONArray jsonArr = new JSONArray(); + for (Map map : list) { + jsonArr.put(toJSON(map)); + } + return jsonArr.toString(); + } + return null; + } + + public static String toJSONString(Object bean){ + try { + JSONObject jsonObject = new JSONObject(bean); + return jsonObject.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONMap.java b/blade-kit/src/main/java/blade/kit/json/JSONMap.java new file mode 100644 index 000000000..834840211 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONMap.java @@ -0,0 +1,38 @@ +package blade.kit.json; + +import java.util.Iterator; +import java.util.Map; + +import blade.kit.CollectionKit; + +@SuppressWarnings("unchecked") +public class JSONMap { + + public static JSONObject toJSONObject(Map map) throws JSONException { + JSONObject jo = new JSONObject(); + if (map != null && !map.isEmpty()) { + Iterator iterator = map.entrySet().iterator(); + while(iterator.hasNext()) { + Map.Entry entry = (Map.Entry) iterator.next(); + String key = entry.getKey(); + Object val = entry.getValue(); + jo.put(key, val); + } + } + return jo; + } + + public static Map toMap(JSONObject jo) throws JSONException { + Map properties = CollectionKit.newHashMap(); + if (jo != null) { + Iterator keys = jo.keys(); + while (keys.hasNext()) { + String name = keys.next(); + K k = (K) name; + V v = (V) jo.get(name); + properties.put(k, v); + } + } + return properties; + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONObject.java b/blade-kit/src/main/java/blade/kit/json/JSONObject.java new file mode 100644 index 000000000..303595e01 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONObject.java @@ -0,0 +1,1779 @@ +package blade.kit.json; + +/* + Copyright (c) 2002 JSON.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + The Software shall be used for Good, not Evil. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.math.*; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.ResourceBundle; +import java.util.Set; + +/** + * A JSONObject is an unordered collection of name/value pairs. Its external + * form is a string wrapped in curly braces with colons between the names and + * values, and commas between the values and names. The internal form is an + * object having get and opt methods for accessing + * the values by name, and put methods for adding or replacing + * values by name. The values can be any of these types: Boolean, + * JSONArray, JSONObject, Number, + * String, or the JSONObject.NULL object. A + * JSONObject constructor can be used to convert an external form JSON text + * into an internal form whose values can be retrieved with the + * get and opt methods, or to convert values into a + * JSON text using the put and toString methods. A + * get method returns a value if one can be found, and throws an + * exception if one cannot be found. An opt method returns a + * default value instead of throwing an exception, and so is useful for + * obtaining optional values. + *

+ * The generic get() and opt() methods return an + * object, which you can cast or query for type. There are also typed + * get and opt methods that do type checking and type + * coercion for you. The opt methods differ from the get methods in that they + * do not throw. Instead, they return a specified value, such as null. + *

+ * The put methods add or replace values in an object. For + * example, + * + *

+ * myString = new JSONObject()
+ *         .put("JSON", "Hello, World!").toString();
+ * 
+ * + * produces the string {"JSON": "Hello, World"}. + *

+ * The texts produced by the toString methods strictly conform to + * the JSON syntax rules. The constructors are more forgiving in the texts they + * will accept: + *

    + *
  • An extra , (comma) may appear just + * before the closing brace.
  • + *
  • Strings may be quoted with ' (single + * quote).
  • + *
  • Strings do not need to be quoted at all if they do not begin with a + * quote or single quote, and if they do not contain leading or trailing + * spaces, and if they do not contain any of these characters: + * { } [ ] / \ : , # and if they do not look like numbers and + * if they are not the reserved words true, false, + * or null.
  • + *
+ * + * @author JSON.org + * @version 2015-07-06 + */ +public class JSONObject { + /** + * JSONObject.NULL is equivalent to the value that JavaScript calls null, + * whilst Java's null is equivalent to the value that JavaScript calls + * undefined. + */ + private static final class Null { + + /** + * There is only intended to be a single instance of the NULL object, + * so the clone method returns itself. + * + * @return NULL. + */ + @Override + protected final Object clone() { + return this; + } + + /** + * A Null object is equal to the null value and to itself. + * + * @param object + * An object to test for nullness. + * @return true if the object parameter is the JSONObject.NULL object or + * null. + */ + @Override + public boolean equals(Object object) { + return object == null || object == this; + } + + /** + * Get the "null" string value. + * + * @return The string "null". + */ + public String toString() { + return "null"; + } + } + + /** + * The map where the JSONObject's properties are kept. + */ + private final Map map; + + /** + * It is sometimes more convenient and less ambiguous to have a + * NULL object than to use Java's null value. + * JSONObject.NULL.equals(null) returns true. + * JSONObject.NULL.toString() returns "null". + */ + public static final Object NULL = new Null(); + + /** + * Construct an empty JSONObject. + */ + public JSONObject() { + this.map = new HashMap(); + } + + /** + * Construct a JSONObject from a subset of another JSONObject. An array of + * strings is used to identify the keys that should be copied. Missing keys + * are ignored. + * + * @param jo + * A JSONObject. + * @param names + * An array of strings. + * @throws JSONException + * @exception JSONException + * If a value is a non-finite number or if a name is + * duplicated. + */ + public JSONObject(JSONObject jo, String[] names) { + this(); + for (int i = 0; i < names.length; i += 1) { + try { + this.putOnce(names[i], jo.opt(names[i])); + } catch (Exception ignore) { + } + } + } + + /** + * Construct a JSONObject from a JSONTokener. + * + * @param x + * A JSONTokener object containing the source string. + * @throws JSONException + * If there is a syntax error in the source string or a + * duplicated key. + */ + public JSONObject(JSONTokener x) throws JSONException { + this(); + char c; + String key; + + if (x.nextClean() != '{') { + throw x.syntaxError("A JSONObject text must begin with '{'"); + } + for (;;) { + c = x.nextClean(); + switch (c) { + case 0: + throw x.syntaxError("A JSONObject text must end with '}'"); + case '}': + return; + default: + x.back(); + key = x.nextValue().toString(); + } + +// The key is followed by ':'. + + c = x.nextClean(); + if (c != ':') { + throw x.syntaxError("Expected a ':' after a key"); + } + this.putOnce(key, x.nextValue()); + +// Pairs are separated by ','. + + switch (x.nextClean()) { + case ';': + case ',': + if (x.nextClean() == '}') { + return; + } + x.back(); + break; + case '}': + return; + default: + throw x.syntaxError("Expected a ',' or '}'"); + } + } + } + + /** + * Construct a JSONObject from a Map. + * + * @param map + * A map object that can be used to initialize the contents of + * the JSONObject. + * @throws JSONException + */ + public JSONObject(Map map) { + this.map = new HashMap(); + if (map != null) { + Iterator> i = map.entrySet().iterator(); + while (i.hasNext()) { + Entry entry = i.next(); + Object value = entry.getValue(); + if (value != null) { + this.map.put(entry.getKey(), wrap(value)); + } + } + } + } + + /** + * Construct a JSONObject from an Object using bean getters. It reflects on + * all of the public methods of the object. For each of the methods with no + * parameters and a name starting with "get" or + * "is" followed by an uppercase letter, the method is invoked, + * and a key and the value returned from the getter method are put into the + * new JSONObject. + * + * The key is formed by removing the "get" or "is" + * prefix. If the second remaining character is not upper case, then the + * first character is converted to lower case. + * + * For example, if an object has a method named "getName", and + * if the result of calling object.getName() is + * "Larry Fine", then the JSONObject will contain + * "name": "Larry Fine". + * + * @param bean + * An object that has getter methods that should be used to make + * a JSONObject. + */ + public JSONObject(Object bean) { + this(); + this.populateMap(bean); + } + + /** + * Construct a JSONObject from an Object, using reflection to find the + * public members. The resulting JSONObject's keys will be the strings from + * the names array, and the values will be the field values associated with + * those keys in the object. If a key is not found or not visible, then it + * will not be copied into the new JSONObject. + * + * @param object + * An object that has fields that should be used to make a + * JSONObject. + * @param names + * An array of strings, the names of the fields to be obtained + * from the object. + */ + public JSONObject(Object object, String names[]) { + this(); + Class c = object.getClass(); + for (int i = 0; i < names.length; i += 1) { + String name = names[i]; + try { + this.putOpt(name, c.getField(name).get(object)); + } catch (Exception ignore) { + } + } + } + + /** + * Construct a JSONObject from a source JSON text string. This is the most + * commonly used JSONObject constructor. + * + * @param source + * A string beginning with { (left + * brace) and ending with } + *  (right brace). + * @exception JSONException + * If there is a syntax error in the source string or a + * duplicated key. + */ + public JSONObject(String source) throws JSONException { + this(new JSONTokener(source)); + } + + /** + * Construct a JSONObject from a ResourceBundle. + * + * @param baseName + * The ResourceBundle base name. + * @param locale + * The Locale to load the ResourceBundle for. + * @throws JSONException + * If any JSONExceptions are detected. + */ + public JSONObject(String baseName, Locale locale) throws JSONException { + this(); + ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, + Thread.currentThread().getContextClassLoader()); + +// Iterate through the keys in the bundle. + + Enumeration keys = bundle.getKeys(); + while (keys.hasMoreElements()) { + Object key = keys.nextElement(); + if (key != null) { + +// Go through the path, ensuring that there is a nested JSONObject for each +// segment except the last. Add the value using the last segment's name into +// the deepest nested JSONObject. + + String[] path = ((String) key).split("\\."); + int last = path.length - 1; + JSONObject target = this; + for (int i = 0; i < last; i += 1) { + String segment = path[i]; + JSONObject nextTarget = target.optJSONObject(segment); + if (nextTarget == null) { + nextTarget = new JSONObject(); + target.put(segment, nextTarget); + } + target = nextTarget; + } + target.put(path[last], bundle.getString((String) key)); + } + } + } + + /** + * Accumulate values under a key. It is similar to the put method except + * that if there is already an object stored under the key then a JSONArray + * is stored under the key to hold all of the accumulated values. If there + * is already a JSONArray, then the new value is appended to it. In + * contrast, the put method replaces the previous value. + * + * If only one value is accumulated that is not a JSONArray, then the result + * will be the same as using put. But if multiple values are accumulated, + * then the result will be like append. + * + * @param key + * A key string. + * @param value + * An object to be accumulated under the key. + * @return this. + * @throws JSONException + * If the value is an invalid number or if the key is null. + */ + public JSONObject accumulate(String key, Object value) throws JSONException { + testValidity(value); + Object object = this.opt(key); + if (object == null) { + this.put(key, + value instanceof JSONArray ? new JSONArray().put(value) + : value); + } else if (object instanceof JSONArray) { + ((JSONArray) object).put(value); + } else { + this.put(key, new JSONArray().put(object).put(value)); + } + return this; + } + + /** + * Append values to the array under a key. If the key does not exist in the + * JSONObject, then the key is put in the JSONObject with its value being a + * JSONArray containing the value parameter. If the key was already + * associated with a JSONArray, then the value parameter is appended to it. + * + * @param key + * A key string. + * @param value + * An object to be accumulated under the key. + * @return this. + * @throws JSONException + * If the key is null or if the current value associated with + * the key is not a JSONArray. + */ + public JSONObject append(String key, Object value) throws JSONException { + testValidity(value); + Object object = this.opt(key); + if (object == null) { + this.put(key, new JSONArray().put(value)); + } else if (object instanceof JSONArray) { + this.put(key, ((JSONArray) object).put(value)); + } else { + throw new JSONException("JSONObject[" + key + + "] is not a JSONArray."); + } + return this; + } + + /** + * Produce a string from a double. The string "null" will be returned if the + * number is not finite. + * + * @param d + * A double. + * @return A String. + */ + public static String doubleToString(double d) { + if (Double.isInfinite(d) || Double.isNaN(d)) { + return "null"; + } + +// Shave off trailing zeros and decimal point, if possible. + + String string = Double.toString(d); + if (string.indexOf('.') > 0 && string.indexOf('e') < 0 + && string.indexOf('E') < 0) { + while (string.endsWith("0")) { + string = string.substring(0, string.length() - 1); + } + if (string.endsWith(".")) { + string = string.substring(0, string.length() - 1); + } + } + return string; + } + + /** + * Get the value object associated with a key. + * + * @param key + * A key string. + * @return The object associated with the key. + * @throws JSONException + * if the key is not found. + */ + public Object get(String key) throws JSONException { + if (key == null) { + throw new JSONException("Null key."); + } + Object object = this.opt(key); + if (object == null) { + throw new JSONException("JSONObject[" + quote(key) + "] not found."); + } + return object; + } + + /** + * Get the boolean value associated with a key. + * + * @param key + * A key string. + * @return The truth. + * @throws JSONException + * if the value is not a Boolean or the String "true" or + * "false". + */ + public boolean getBoolean(String key) throws JSONException { + Object object = this.get(key); + if (object.equals(Boolean.FALSE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("false"))) { + return false; + } else if (object.equals(Boolean.TRUE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("true"))) { + return true; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a Boolean."); + } + + /** + * Get the BigInteger value associated with a key. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value cannot + * be converted to BigInteger. + */ + public BigInteger getBigInteger(String key) throws JSONException { + Object object = this.get(key); + try { + return new BigInteger(object.toString()); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] could not be converted to BigInteger."); + } + } + + /** + * Get the BigDecimal value associated with a key. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value + * cannot be converted to BigDecimal. + */ + public BigDecimal getBigDecimal(String key) throws JSONException { + Object object = this.get(key); + try { + return new BigDecimal(object.toString()); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] could not be converted to BigDecimal."); + } + } + + /** + * Get the double value associated with a key. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value is not a Number + * object and cannot be converted to a number. + */ + public double getDouble(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number ? ((Number) object).doubleValue() + : Double.parseDouble((String) object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not a number."); + } + } + + /** + * Get the int value associated with a key. + * + * @param key + * A key string. + * @return The integer value. + * @throws JSONException + * if the key is not found or if the value cannot be converted + * to an integer. + */ + public int getInt(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number ? ((Number) object).intValue() + : Integer.parseInt((String) object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not an int."); + } + } + + /** + * Get the JSONArray value associated with a key. + * + * @param key + * A key string. + * @return A JSONArray which is the value. + * @throws JSONException + * if the key is not found or if the value is not a JSONArray. + */ + public JSONArray getJSONArray(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof JSONArray) { + return (JSONArray) object; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a JSONArray."); + } + + /** + * Get the JSONObject value associated with a key. + * + * @param key + * A key string. + * @return A JSONObject which is the value. + * @throws JSONException + * if the key is not found or if the value is not a JSONObject. + */ + public JSONObject getJSONObject(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof JSONObject) { + return (JSONObject) object; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a JSONObject."); + } + + /** + * Get the long value associated with a key. + * + * @param key + * A key string. + * @return The long value. + * @throws JSONException + * if the key is not found or if the value cannot be converted + * to a long. + */ + public long getLong(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number ? ((Number) object).longValue() + : Long.parseLong((String) object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not a long."); + } + } + + /** + * Get an array of field names from a JSONObject. + * + * @return An array of field names, or null if there are no names. + */ + public static String[] getNames(JSONObject jo) { + int length = jo.length(); + if (length == 0) { + return null; + } + Iterator iterator = jo.keys(); + String[] names = new String[length]; + int i = 0; + while (iterator.hasNext()) { + names[i] = iterator.next(); + i += 1; + } + return names; + } + + /** + * Get an array of field names from an Object. + * + * @return An array of field names, or null if there are no names. + */ + public static String[] getNames(Object object) { + if (object == null) { + return null; + } + Class klass = object.getClass(); + Field[] fields = klass.getFields(); + int length = fields.length; + if (length == 0) { + return null; + } + String[] names = new String[length]; + for (int i = 0; i < length; i += 1) { + names[i] = fields[i].getName(); + } + return names; + } + + /** + * Get the string associated with a key. + * + * @param key + * A key string. + * @return A string which is the value. + * @throws JSONException + * if there is no string value for the key. + */ + public String getString(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof String) { + return (String) object; + } + throw new JSONException("JSONObject[" + quote(key) + "] not a string."); + } + + /** + * Determine if the JSONObject contains a specific key. + * + * @param key + * A key string. + * @return true if the key exists in the JSONObject. + */ + public boolean has(String key) { + return this.map.containsKey(key); + } + + /** + * Increment a property of a JSONObject. If there is no such property, + * create one with a value of 1. If there is such a property, and if it is + * an Integer, Long, Double, or Float, then add one to it. + * + * @param key + * A key string. + * @return this. + * @throws JSONException + * If there is already a property with this name that is not an + * Integer, Long, Double, or Float. + */ + public JSONObject increment(String key) throws JSONException { + Object value = this.opt(key); + if (value == null) { + this.put(key, 1); + } else if (value instanceof BigInteger) { + this.put(key, ((BigInteger)value).add(BigInteger.ONE)); + } else if (value instanceof BigDecimal) { + this.put(key, ((BigDecimal)value).add(BigDecimal.ONE)); + } else if (value instanceof Integer) { + this.put(key, (Integer) value + 1); + } else if (value instanceof Long) { + this.put(key, (Long) value + 1); + } else if (value instanceof Double) { + this.put(key, (Double) value + 1); + } else if (value instanceof Float) { + this.put(key, (Float) value + 1); + } else { + throw new JSONException("Unable to increment [" + quote(key) + "]."); + } + return this; + } + + /** + * Determine if the value associated with the key is null or if there is no + * value. + * + * @param key + * A key string. + * @return true if there is no value associated with the key or if the value + * is the JSONObject.NULL object. + */ + public boolean isNull(String key) { + return JSONObject.NULL.equals(this.opt(key)); + } + + /** + * Get an enumeration of the keys of the JSONObject. + * + * @return An iterator of the keys. + */ + public Iterator keys() { + return this.keySet().iterator(); + } + + /** + * Get a set of keys of the JSONObject. + * + * @return A keySet. + */ + public Set keySet() { + return this.map.keySet(); + } + + /** + * Get the number of keys stored in the JSONObject. + * + * @return The number of keys in the JSONObject. + */ + public int length() { + return this.map.size(); + } + + /** + * Produce a JSONArray containing the names of the elements of this + * JSONObject. + * + * @return A JSONArray containing the key strings, or null if the JSONObject + * is empty. + */ + public JSONArray names() { + JSONArray ja = new JSONArray(); + Iterator keys = this.keys(); + while (keys.hasNext()) { + ja.put(keys.next()); + } + return ja.length() == 0 ? null : ja; + } + + /** + * Produce a string from a Number. + * + * @param number + * A Number + * @return A String. + * @throws JSONException + * If n is a non-finite number. + */ + public static String numberToString(Number number) throws JSONException { + if (number == null) { + throw new JSONException("Null pointer"); + } + testValidity(number); + +// Shave off trailing zeros and decimal point, if possible. + + String string = number.toString(); + if (string.indexOf('.') > 0 && string.indexOf('e') < 0 + && string.indexOf('E') < 0) { + while (string.endsWith("0")) { + string = string.substring(0, string.length() - 1); + } + if (string.endsWith(".")) { + string = string.substring(0, string.length() - 1); + } + } + return string; + } + + /** + * Get an optional value associated with a key. + * + * @param key + * A key string. + * @return An object which is the value, or null if there is no value. + */ + public Object opt(String key) { + return key == null ? null : this.map.get(key); + } + + /** + * Get an optional boolean associated with a key. It returns false if there + * is no such key, or if the value is not Boolean.TRUE or the String "true". + * + * @param key + * A key string. + * @return The truth. + */ + public boolean optBoolean(String key) { + return this.optBoolean(key, false); + } + + /** + * Get an optional boolean associated with a key. It returns the + * defaultValue if there is no such key, or if it is not a Boolean or the + * String "true" or "false" (case insensitive). + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return The truth. + */ + public boolean optBoolean(String key, boolean defaultValue) { + try { + return this.getBoolean(key); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get an optional double associated with a key, or NaN if there is no such + * key or if its value is not a number. If the value is a string, an attempt + * will be made to evaluate it as a number. + * + * @param key + * A string which is the key. + * @return An object which is the value. + */ + public double optDouble(String key) { + return this.optDouble(key, Double.NaN); + } + + /** + * Get an optional BigInteger associated with a key, or the defaultValue if + * there is no such key or if its value is not a number. If the value is a + * string, an attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public BigInteger optBigInteger(String key, BigInteger defaultValue) { + try { + return this.getBigInteger(key); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get an optional BigDecimal associated with a key, or the defaultValue if + * there is no such key or if its value is not a number. If the value is a + * string, an attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) { + try { + return this.getBigDecimal(key); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get an optional double associated with a key, or the defaultValue if + * there is no such key or if its value is not a number. If the value is a + * string, an attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public double optDouble(String key, double defaultValue) { + try { + return this.getDouble(key); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get an optional int value associated with a key, or zero if there is no + * such key or if the value is not a number. If the value is a string, an + * attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @return An object which is the value. + */ + public int optInt(String key) { + return this.optInt(key, 0); + } + + /** + * Get an optional int value associated with a key, or the default if there + * is no such key or if the value is not a number. If the value is a string, + * an attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public int optInt(String key, int defaultValue) { + try { + return this.getInt(key); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get an optional JSONArray associated with a key. It returns null if there + * is no such key, or if its value is not a JSONArray. + * + * @param key + * A key string. + * @return A JSONArray which is the value. + */ + public JSONArray optJSONArray(String key) { + Object o = this.opt(key); + return o instanceof JSONArray ? (JSONArray) o : null; + } + + /** + * Get an optional JSONObject associated with a key. It returns null if + * there is no such key, or if its value is not a JSONObject. + * + * @param key + * A key string. + * @return A JSONObject which is the value. + */ + public JSONObject optJSONObject(String key) { + Object object = this.opt(key); + return object instanceof JSONObject ? (JSONObject) object : null; + } + + /** + * Get an optional long value associated with a key, or zero if there is no + * such key or if the value is not a number. If the value is a string, an + * attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @return An object which is the value. + */ + public long optLong(String key) { + return this.optLong(key, 0); + } + + /** + * Get an optional long value associated with a key, or the default if there + * is no such key or if the value is not a number. If the value is a string, + * an attempt will be made to evaluate it as a number. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return An object which is the value. + */ + public long optLong(String key, long defaultValue) { + try { + return this.getLong(key); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * Get an optional string associated with a key. It returns an empty string + * if there is no such key. If the value is not a string and is not null, + * then it is converted to a string. + * + * @param key + * A key string. + * @return A string which is the value. + */ + public String optString(String key) { + return this.optString(key, ""); + } + + /** + * Get an optional string associated with a key. It returns the defaultValue + * if there is no such key. + * + * @param key + * A key string. + * @param defaultValue + * The default. + * @return A string which is the value. + */ + public String optString(String key, String defaultValue) { + Object object = this.opt(key); + return NULL.equals(object) ? defaultValue : object.toString(); + } + + private void populateMap(Object bean) { + Class klass = bean.getClass(); + +// If klass is a System class then set includeSuperClass to false. + + boolean includeSuperClass = klass.getClassLoader() != null; + + Method[] methods = includeSuperClass ? klass.getMethods() : klass + .getDeclaredMethods(); + for (int i = 0; i < methods.length; i += 1) { + try { + Method method = methods[i]; + if (Modifier.isPublic(method.getModifiers())) { + String name = method.getName(); + String key = ""; + if (name.startsWith("get")) { + if ("getClass".equals(name) + || "getDeclaringClass".equals(name)) { + key = ""; + } else { + key = name.substring(3); + } + } else if (name.startsWith("is")) { + key = name.substring(2); + } + if (key.length() > 0 + && Character.isUpperCase(key.charAt(0)) + && method.getParameterTypes().length == 0) { + if (key.length() == 1) { + key = key.toLowerCase(); + } else if (!Character.isUpperCase(key.charAt(1))) { + key = key.substring(0, 1).toLowerCase() + + key.substring(1); + } + + Object result = method.invoke(bean, (Object[]) null); + if (result != null) { + this.map.put(key, wrap(result)); + } + } + } + } catch (Exception ignore) { + } + } + } + + /** + * Put a key/boolean pair in the JSONObject. + * + * @param key + * A key string. + * @param value + * A boolean which is the value. + * @return this. + * @throws JSONException + * If the key is null. + */ + public JSONObject put(String key, boolean value) throws JSONException { + this.put(key, value ? Boolean.TRUE : Boolean.FALSE); + return this; + } + + /** + * Put a key/value pair in the JSONObject, where the value will be a + * JSONArray which is produced from a Collection. + * + * @param key + * A key string. + * @param value + * A Collection value. + * @return this. + * @throws JSONException + */ + public JSONObject put(String key, Collection value) throws JSONException { + this.put(key, new JSONArray(value)); + return this; + } + + /** + * Put a key/double pair in the JSONObject. + * + * @param key + * A key string. + * @param value + * A double which is the value. + * @return this. + * @throws JSONException + * If the key is null or if the number is invalid. + */ + public JSONObject put(String key, double value) throws JSONException { + this.put(key, new Double(value)); + return this; + } + + /** + * Put a key/int pair in the JSONObject. + * + * @param key + * A key string. + * @param value + * An int which is the value. + * @return this. + * @throws JSONException + * If the key is null. + */ + public JSONObject put(String key, int value) throws JSONException { + this.put(key, new Integer(value)); + return this; + } + + /** + * Put a key/long pair in the JSONObject. + * + * @param key + * A key string. + * @param value + * A long which is the value. + * @return this. + * @throws JSONException + * If the key is null. + */ + public JSONObject put(String key, long value) throws JSONException { + this.put(key, new Long(value)); + return this; + } + + /** + * Put a key/value pair in the JSONObject, where the value will be a + * JSONObject which is produced from a Map. + * + * @param key + * A key string. + * @param value + * A Map value. + * @return this. + * @throws JSONException + */ + public JSONObject put(String key, Map value) throws JSONException { + this.put(key, new JSONObject(value)); + return this; + } + + /** + * Put a key/value pair in the JSONObject. If the value is null, then the + * key will be removed from the JSONObject if it is present. + * + * @param key + * A key string. + * @param value + * An object which is the value. It should be of one of these + * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, + * String, or the JSONObject.NULL object. + * @return this. + * @throws JSONException + * If the value is non-finite number or if the key is null. + */ + public JSONObject put(String key, Object value) throws JSONException { + if (key == null) { + throw new NullPointerException("Null key."); + } + if (value != null) { + testValidity(value); + this.map.put(key, value); + } else { + this.remove(key); + } + return this; + } + + /** + * Put a key/value pair in the JSONObject, but only if the key and the value + * are both non-null, and only if there is not already a member with that + * name. + * + * @param key string + * @param value object + * @return this. + * @throws JSONException + * if the key is a duplicate + */ + public JSONObject putOnce(String key, Object value) throws JSONException { + if (key != null && value != null) { + if (this.opt(key) != null) { + throw new JSONException("Duplicate key \"" + key + "\""); + } + this.put(key, value); + } + return this; + } + + /** + * Put a key/value pair in the JSONObject, but only if the key and the value + * are both non-null. + * + * @param key + * A key string. + * @param value + * An object which is the value. It should be of one of these + * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, + * String, or the JSONObject.NULL object. + * @return this. + * @throws JSONException + * If the value is a non-finite number. + */ + public JSONObject putOpt(String key, Object value) throws JSONException { + if (key != null && value != null) { + this.put(key, value); + } + return this; + } + + /** + * Produce a string in double quotes with backslash sequences in all the + * right places. A backslash will be inserted within = '\u0080' && c < '\u00a0') + || (c >= '\u2000' && c < '\u2100')) { + w.write("\\u"); + hhhh = Integer.toHexString(c); + w.write("0000", 0, 4 - hhhh.length()); + w.write(hhhh); + } else { + w.write(c); + } + } + } + w.write('"'); + return w; + } + + /** + * Remove a name and its value, if present. + * + * @param key + * The name to be removed. + * @return The value that was associated with the name, or null if there was + * no value. + */ + public Object remove(String key) { + return this.map.remove(key); + } + + /** + * Determine if two JSONObjects are similar. + * They must contain the same set of names which must be associated with + * similar values. + * + * @param other The other JSONObject + * @return true if they are equal + */ + public boolean similar(Object other) { + try { + if (!(other instanceof JSONObject)) { + return false; + } + Set set = this.keySet(); + if (!set.equals(((JSONObject)other).keySet())) { + return false; + } + Iterator iterator = set.iterator(); + while (iterator.hasNext()) { + String name = iterator.next(); + Object valueThis = this.get(name); + Object valueOther = ((JSONObject)other).get(name); + if (valueThis instanceof JSONObject) { + if (!((JSONObject)valueThis).similar(valueOther)) { + return false; + } + } else if (valueThis instanceof JSONArray) { + if (!((JSONArray)valueThis).similar(valueOther)) { + return false; + } + } else if (!valueThis.equals(valueOther)) { + return false; + } + } + return true; + } catch (Throwable exception) { + return false; + } + } + + /** + * Try to convert a string into a number, boolean, or null. If the string + * can't be converted, return the string. + * + * @param string + * A String. + * @return A simple JSON value. + */ + public static Object stringToValue(String string) { + Double d; + if (string.equals("")) { + return string; + } + if (string.equalsIgnoreCase("true")) { + return Boolean.TRUE; + } + if (string.equalsIgnoreCase("false")) { + return Boolean.FALSE; + } + if (string.equalsIgnoreCase("null")) { + return JSONObject.NULL; + } + + /* + * If it might be a number, try converting it. If a number cannot be + * produced, then the value will just be a string. + */ + + char b = string.charAt(0); + if ((b >= '0' && b <= '9') || b == '-') { + try { + if (string.indexOf('.') > -1 || string.indexOf('e') > -1 + || string.indexOf('E') > -1) { + d = Double.valueOf(string); + if (!d.isInfinite() && !d.isNaN()) { + return d; + } + } else { + Long myLong = new Long(string); + if (string.equals(myLong.toString())) { + if (myLong == myLong.intValue()) { + return myLong.intValue(); + } else { + return myLong; + } + } + } + } catch (Exception ignore) { + } + } + return string; + } + + /** + * Throw an exception if the object is a NaN or infinite number. + * + * @param o + * The object to test. + * @throws JSONException + * If o is a non-finite number. + */ + public static void testValidity(Object o) throws JSONException { + if (o != null) { + if (o instanceof Double) { + if (((Double) o).isInfinite() || ((Double) o).isNaN()) { + throw new JSONException( + "JSON does not allow non-finite numbers."); + } + } else if (o instanceof Float) { + if (((Float) o).isInfinite() || ((Float) o).isNaN()) { + throw new JSONException( + "JSON does not allow non-finite numbers."); + } + } + } + } + + /** + * Produce a JSONArray containing the values of the members of this + * JSONObject. + * + * @param names + * A JSONArray containing a list of key strings. This determines + * the sequence of the values in the result. + * @return A JSONArray of values. + * @throws JSONException + * If any of the values are non-finite numbers. + */ + public JSONArray toJSONArray(JSONArray names) throws JSONException { + if (names == null || names.length() == 0) { + return null; + } + JSONArray ja = new JSONArray(); + for (int i = 0; i < names.length(); i += 1) { + ja.put(this.opt(names.getString(i))); + } + return ja; + } + + /** + * Make a JSON text of this JSONObject. For compactness, no whitespace is + * added. If this would not result in a syntactically correct JSON text, + * then null will be returned instead. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a printable, displayable, portable, transmittable representation + * of the object, beginning with { (left + * brace) and ending with } (right + * brace). + */ + public String toString() { + try { + return this.toString(0); + } catch (Exception e) { + return null; + } + } + + /** + * Make a prettyprinted JSON text of this JSONObject. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @return a printable, displayable, portable, transmittable representation + * of the object, beginning with { (left + * brace) and ending with } (right + * brace). + * @throws JSONException + * If the object contains an invalid number. + */ + public String toString(int indentFactor) throws JSONException { + StringWriter w = new StringWriter(); + synchronized (w.getBuffer()) { + return this.write(w, indentFactor, 0).toString(); + } + } + + /** + * Make a JSON text of an Object value. If the object has an + * value.toJSONString() method, then that method will be used to produce the + * JSON text. The method is required to produce a strictly conforming text. + * If the object does not contain a toJSONString method (which is the most + * common case), then a text will be produced by other means. If the value + * is an array or Collection, then a JSONArray will be made from it and its + * toJSONString method will be called. If the value is a MAP, then a + * JSONObject will be made from it and its toJSONString method will be + * called. Otherwise, the value's toString method will be called, and the + * result will be quoted. + * + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @param value + * The value to be serialized. + * @return a printable, displayable, transmittable representation of the + * object, beginning with { (left + * brace) and ending with } (right + * brace). + * @throws JSONException + * If the value is or contains an invalid number. + */ + public static String valueToString(Object value) throws JSONException { + if (value == null || value.equals(null)) { + return "null"; + } + if (value instanceof JSONString) { + Object object; + try { + object = ((JSONString) value).toJSONString(); + } catch (Exception e) { + throw new JSONException(e); + } + if (object instanceof String) { + return (String) object; + } + throw new JSONException("Bad value from toJSONString: " + object); + } + if (value instanceof Number) { + return numberToString((Number) value); + } + if (value instanceof Boolean || value instanceof JSONObject + || value instanceof JSONArray) { + return value.toString(); + } + if (value instanceof Map) { + @SuppressWarnings("unchecked") + Map map = (Map) value; + return new JSONObject(map).toString(); + } + if (value instanceof Collection) { + @SuppressWarnings("unchecked") + Collection coll = (Collection) value; + return new JSONArray(coll).toString(); + } + if (value.getClass().isArray()) { + return new JSONArray(value).toString(); + } + return quote(value.toString()); + } + + /** + * Wrap an object, if necessary. If the object is null, return the NULL + * object. If it is an array or collection, wrap it in a JSONArray. If it is + * a map, wrap it in a JSONObject. If it is a standard property (Double, + * String, et al) then it is already wrapped. Otherwise, if it comes from + * one of the java packages, turn it into a string. And if it doesn't, try + * to wrap it in a JSONObject. If the wrapping fails, then null is returned. + * + * @param object + * The object to wrap + * @return The wrapped value + */ + public static Object wrap(Object object) { + try { + if (object == null) { + return NULL; + } + if (object instanceof JSONObject || object instanceof JSONArray + || NULL.equals(object) || object instanceof JSONString + || object instanceof Byte || object instanceof Character + || object instanceof Short || object instanceof Integer + || object instanceof Long || object instanceof Boolean + || object instanceof Float || object instanceof Double + || object instanceof String || object instanceof BigInteger + || object instanceof BigDecimal) { + return object; + } + + if (object instanceof Collection) { + @SuppressWarnings("unchecked") + Collection coll = (Collection) object; + return new JSONArray(coll); + } + if (object.getClass().isArray()) { + return new JSONArray(object); + } + if (object instanceof Map) { + @SuppressWarnings("unchecked") + Map map = (Map) object; + return new JSONObject(map); + } + Package objectPackage = object.getClass().getPackage(); + String objectPackageName = objectPackage != null ? objectPackage + .getName() : ""; + if (objectPackageName.startsWith("java.") + || objectPackageName.startsWith("javax.") + || object.getClass().getClassLoader() == null) { + return object.toString(); + } + return new JSONObject(object); + } catch (Exception exception) { + return null; + } + } + + /** + * Write the contents of the JSONObject as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + public Writer write(Writer writer) throws JSONException { + return this.write(writer, 0, 0); + } + + static final Writer writeValue(Writer writer, Object value, + int indentFactor, int indent) throws JSONException, IOException { + if (value == null || value.equals(null)) { + writer.write("null"); + } else if (value instanceof JSONObject) { + ((JSONObject) value).write(writer, indentFactor, indent); + } else if (value instanceof JSONArray) { + ((JSONArray) value).write(writer, indentFactor, indent); + } else if (value instanceof Map) { + @SuppressWarnings("unchecked") + Map map = (Map) value; + new JSONObject(map).write(writer, indentFactor, indent); + } else if (value instanceof Collection) { + @SuppressWarnings("unchecked") + Collection coll = (Collection) value; + new JSONArray(coll).write(writer, indentFactor, + indent); + } else if (value.getClass().isArray()) { + new JSONArray(value).write(writer, indentFactor, indent); + } else if (value instanceof Number) { + writer.write(numberToString((Number) value)); + } else if (value instanceof Boolean) { + writer.write(value.toString()); + } else if (value instanceof JSONString) { + Object o; + try { + o = ((JSONString) value).toJSONString(); + } catch (Exception e) { + throw new JSONException(e); + } + writer.write(o != null ? o.toString() : quote(value.toString())); + } else { + quote(value.toString(), writer); + } + return writer; + } + + static final void indent(Writer writer, int indent) throws IOException { + for (int i = 0; i < indent; i += 1) { + writer.write(' '); + } + } + + /** + * Write the contents of the JSONObject as JSON text to a writer. For + * compactness, no whitespace is added. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + Writer write(Writer writer, int indentFactor, int indent) + throws JSONException { + try { + boolean commanate = false; + final int length = this.length(); + Iterator keys = this.keys(); + writer.write('{'); + + if (length == 1) { + Object key = keys.next(); + writer.write(quote(key.toString())); + writer.write(':'); + if (indentFactor > 0) { + writer.write(' '); + } + writeValue(writer, this.map.get(key), indentFactor, indent); + } else if (length != 0) { + final int newindent = indent + indentFactor; + while (keys.hasNext()) { + Object key = keys.next(); + if (commanate) { + writer.write(','); + } + if (indentFactor > 0) { + writer.write('\n'); + } + indent(writer, newindent); + writer.write(quote(key.toString())); + writer.write(':'); + if (indentFactor > 0) { + writer.write(' '); + } + writeValue(writer, this.map.get(key), indentFactor, newindent); + commanate = true; + } + if (indentFactor > 0) { + writer.write('\n'); + } + indent(writer, indent); + } + writer.write('}'); + return writer; + } catch (IOException exception) { + throw new JSONException(exception); + } + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONString.java b/blade-kit/src/main/java/blade/kit/json/JSONString.java new file mode 100644 index 000000000..70d3f5508 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONString.java @@ -0,0 +1,18 @@ +package blade.kit.json; +/** + * The JSONString interface allows a toJSONString() + * method so that a class can change the behavior of + * JSONObject.toString(), JSONArray.toString(), + * and JSONWriter.value(Object). The + * toJSONString method will be used instead of the default behavior + * of using the Object's toString() method and quoting the result. + */ +public interface JSONString { + /** + * The toJSONString method allows a class to produce its own JSON + * serialization. + * + * @return A strictly syntactically correct JSON text. + */ + public String toJSONString(); +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONStringer.java b/blade-kit/src/main/java/blade/kit/json/JSONStringer.java new file mode 100644 index 000000000..9e128f4d4 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONStringer.java @@ -0,0 +1,78 @@ +package blade.kit.json; + +/* +Copyright (c) 2006 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import java.io.StringWriter; + +/** + * JSONStringer provides a quick and convenient way of producing JSON text. + * The texts produced strictly conform to JSON syntax rules. No whitespace is + * added, so the results are ready for transmission or storage. Each instance of + * JSONStringer can produce one JSON text. + *

+ * A JSONStringer instance provides a value method for appending + * values to the + * text, and a key + * method for adding keys before values in objects. There are array + * and endArray methods that make and bound array values, and + * object and endObject methods which make and bound + * object values. All of these methods return the JSONWriter instance, + * permitting cascade style. For example,

+ * myString = new JSONStringer()
+ *     .object()
+ *         .key("JSON")
+ *         .value("Hello, World!")
+ *     .endObject()
+ *     .toString();
which produces the string
+ * {"JSON":"Hello, World!"}
+ *

+ * The first method called must be array or object. + * There are no methods for adding commas or colons. JSONStringer adds them for + * you. Objects and arrays can be nested up to 20 levels deep. + *

+ * This can sometimes be easier than using a JSONObject to build a string. + * @author JSON.org + * @version 2008-09-18 + */ +public class JSONStringer extends JSONWriter { + /** + * Make a fresh JSONStringer. It can be used to build one JSON text. + */ + public JSONStringer() { + super(new StringWriter()); + } + + /** + * Return the JSON text. This method is used to obtain the product of the + * JSONStringer instance. It will return null if there was a + * problem in the construction of the JSON text (such as the calls to + * array were not properly balanced with calls to + * endArray). + * @return The JSON text. + */ + public String toString() { + return this.mode == 'd' ? this.writer.toString() : null; + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONTokener.java b/blade-kit/src/main/java/blade/kit/json/JSONTokener.java new file mode 100644 index 000000000..fb271e1cd --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONTokener.java @@ -0,0 +1,446 @@ +package blade.kit.json; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * A JSONTokener takes a source string and extracts characters and tokens from + * it. It is used by the JSONObject and JSONArray constructors to parse + * JSON source strings. + * @author JSON.org + * @version 2014-05-03 + */ +public class JSONTokener { + + private long character; + private boolean eof; + private long index; + private long line; + private char previous; + private Reader reader; + private boolean usePrevious; + + + /** + * Construct a JSONTokener from a Reader. + * + * @param reader A reader. + */ + public JSONTokener(Reader reader) { + this.reader = reader.markSupported() + ? reader + : new BufferedReader(reader); + this.eof = false; + this.usePrevious = false; + this.previous = 0; + this.index = 0; + this.character = 1; + this.line = 1; + } + + + /** + * Construct a JSONTokener from an InputStream. + * @param inputStream The source. + */ + public JSONTokener(InputStream inputStream) throws JSONException { + this(new InputStreamReader(inputStream)); + } + + + /** + * Construct a JSONTokener from a string. + * + * @param s A source string. + */ + public JSONTokener(String s) { + this(new StringReader(s)); + } + + + /** + * Back up one character. This provides a sort of lookahead capability, + * so that you can test for a digit or letter before attempting to parse + * the next number or identifier. + */ + public void back() throws JSONException { + if (this.usePrevious || this.index <= 0) { + throw new JSONException("Stepping back two steps is not supported"); + } + this.index -= 1; + this.character -= 1; + this.usePrevious = true; + this.eof = false; + } + + + /** + * Get the hex value of a character (base16). + * @param c A character between '0' and '9' or between 'A' and 'F' or + * between 'a' and 'f'. + * @return An int between 0 and 15, or -1 if c was not a hex digit. + */ + public static int dehexchar(char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } + if (c >= 'A' && c <= 'F') { + return c - ('A' - 10); + } + if (c >= 'a' && c <= 'f') { + return c - ('a' - 10); + } + return -1; + } + + public boolean end() { + return this.eof && !this.usePrevious; + } + + + /** + * Determine if the source string still contains characters that next() + * can consume. + * @return true if not yet at the end of the source. + */ + public boolean more() throws JSONException { + this.next(); + if (this.end()) { + return false; + } + this.back(); + return true; + } + + + /** + * Get the next character in the source string. + * + * @return The next character, or 0 if past the end of the source string. + */ + public char next() throws JSONException { + int c; + if (this.usePrevious) { + this.usePrevious = false; + c = this.previous; + } else { + try { + c = this.reader.read(); + } catch (IOException exception) { + throw new JSONException(exception); + } + + if (c <= 0) { // End of stream + this.eof = true; + c = 0; + } + } + this.index += 1; + if (this.previous == '\r') { + this.line += 1; + this.character = c == '\n' ? 0 : 1; + } else if (c == '\n') { + this.line += 1; + this.character = 0; + } else { + this.character += 1; + } + this.previous = (char) c; + return this.previous; + } + + + /** + * Consume the next character, and check that it matches a specified + * character. + * @param c The character to match. + * @return The character. + * @throws JSONException if the character does not match. + */ + public char next(char c) throws JSONException { + char n = this.next(); + if (n != c) { + throw this.syntaxError("Expected '" + c + "' and instead saw '" + + n + "'"); + } + return n; + } + + + /** + * Get the next n characters. + * + * @param n The number of characters to take. + * @return A string of n characters. + * @throws JSONException + * Substring bounds error if there are not + * n characters remaining in the source string. + */ + public String next(int n) throws JSONException { + if (n == 0) { + return ""; + } + + char[] chars = new char[n]; + int pos = 0; + + while (pos < n) { + chars[pos] = this.next(); + if (this.end()) { + throw this.syntaxError("Substring bounds error"); + } + pos += 1; + } + return new String(chars); + } + + + /** + * Get the next char in the string, skipping whitespace. + * @throws JSONException + * @return A character, or 0 if there are no more characters. + */ + public char nextClean() throws JSONException { + for (;;) { + char c = this.next(); + if (c == 0 || c > ' ') { + return c; + } + } + } + + + /** + * Return the characters up to the next close quote character. + * Backslash processing is done. The formal JSON format does not + * allow strings in single quotes, but an implementation is allowed to + * accept them. + * @param quote The quoting character, either + * " (double quote) or + * ' (single quote). + * @return A String. + * @throws JSONException Unterminated string. + */ + public String nextString(char quote) throws JSONException { + char c; + StringBuilder sb = new StringBuilder(); + for (;;) { + c = this.next(); + switch (c) { + case 0: + case '\n': + case '\r': + throw this.syntaxError("Unterminated string"); + case '\\': + c = this.next(); + switch (c) { + case 'b': + sb.append('\b'); + break; + case 't': + sb.append('\t'); + break; + case 'n': + sb.append('\n'); + break; + case 'f': + sb.append('\f'); + break; + case 'r': + sb.append('\r'); + break; + case 'u': + sb.append((char)Integer.parseInt(this.next(4), 16)); + break; + case '"': + case '\'': + case '\\': + case '/': + sb.append(c); + break; + default: + throw this.syntaxError("Illegal escape."); + } + break; + default: + if (c == quote) { + return sb.toString(); + } + sb.append(c); + } + } + } + + + /** + * Get the text up but not including the specified character or the + * end of line, whichever comes first. + * @param delimiter A delimiter character. + * @return A string. + */ + public String nextTo(char delimiter) throws JSONException { + StringBuilder sb = new StringBuilder(); + for (;;) { + char c = this.next(); + if (c == delimiter || c == 0 || c == '\n' || c == '\r') { + if (c != 0) { + this.back(); + } + return sb.toString().trim(); + } + sb.append(c); + } + } + + + /** + * Get the text up but not including one of the specified delimiter + * characters or the end of line, whichever comes first. + * @param delimiters A set of delimiter characters. + * @return A string, trimmed. + */ + public String nextTo(String delimiters) throws JSONException { + char c; + StringBuilder sb = new StringBuilder(); + for (;;) { + c = this.next(); + if (delimiters.indexOf(c) >= 0 || c == 0 || + c == '\n' || c == '\r') { + if (c != 0) { + this.back(); + } + return sb.toString().trim(); + } + sb.append(c); + } + } + + + /** + * Get the next value. The value can be a Boolean, Double, Integer, + * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. + * @throws JSONException If syntax error. + * + * @return An object. + */ + public Object nextValue() throws JSONException { + char c = this.nextClean(); + String string; + + switch (c) { + case '"': + case '\'': + return this.nextString(c); + case '{': + this.back(); + return new JSONObject(this); + case '[': + this.back(); + return new JSONArray(this); + } + + /* + * Handle unquoted text. This could be the values true, false, or + * null, or it can be a number. An implementation (such as this one) + * is allowed to also accept non-standard forms. + * + * Accumulate characters until we reach the end of the text or a + * formatting character. + */ + + StringBuilder sb = new StringBuilder(); + while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { + sb.append(c); + c = this.next(); + } + this.back(); + + string = sb.toString().trim(); + if ("".equals(string)) { + throw this.syntaxError("Missing value"); + } + return JSONObject.stringToValue(string); + } + + + /** + * Skip characters until the next character is the requested character. + * If the requested character is not found, no characters are skipped. + * @param to A character to skip to. + * @return The requested character, or zero if the requested character + * is not found. + */ + public char skipTo(char to) throws JSONException { + char c; + try { + long startIndex = this.index; + long startCharacter = this.character; + long startLine = this.line; + this.reader.mark(1000000); + do { + c = this.next(); + if (c == 0) { + this.reader.reset(); + this.index = startIndex; + this.character = startCharacter; + this.line = startLine; + return c; + } + } while (c != to); + } catch (IOException exception) { + throw new JSONException(exception); + } + this.back(); + return c; + } + + + /** + * Make a JSONException to signal a syntax error. + * + * @param message The error message. + * @return A JSONException object, suitable for throwing + */ + public JSONException syntaxError(String message) { + return new JSONException(message + this.toString()); + } + + + /** + * Make a printable string of this JSONTokener. + * + * @return " at {index} [character {character} line {line}]" + */ + public String toString() { + return " at " + this.index + " [character " + this.character + " line " + + this.line + "]"; + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONWriter.java b/blade-kit/src/main/java/blade/kit/json/JSONWriter.java new file mode 100644 index 000000000..6d001b981 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONWriter.java @@ -0,0 +1,327 @@ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; + +/* +Copyright (c) 2006 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * JSONWriter provides a quick and convenient way of producing JSON text. + * The texts produced strictly conform to JSON syntax rules. No whitespace is + * added, so the results are ready for transmission or storage. Each instance of + * JSONWriter can produce one JSON text. + *

+ * A JSONWriter instance provides a value method for appending + * values to the + * text, and a key + * method for adding keys before values in objects. There are array + * and endArray methods that make and bound array values, and + * object and endObject methods which make and bound + * object values. All of these methods return the JSONWriter instance, + * permitting a cascade style. For example,

+ * new JSONWriter(myWriter)
+ *     .object()
+ *         .key("JSON")
+ *         .value("Hello, World!")
+ *     .endObject();
which writes
+ * {"JSON":"Hello, World!"}
+ *

+ * The first method called must be array or object. + * There are no methods for adding commas or colons. JSONWriter adds them for + * you. Objects and arrays can be nested up to 20 levels deep. + *

+ * This can sometimes be easier than using a JSONObject to build a string. + * @author JSON.org + * @version 2011-11-24 + */ +public class JSONWriter { + private static final int maxdepth = 200; + + /** + * The comma flag determines if a comma should be output before the next + * value. + */ + private boolean comma; + + /** + * The current mode. Values: + * 'a' (array), + * 'd' (done), + * 'i' (initial), + * 'k' (key), + * 'o' (object). + */ + protected char mode; + + /** + * The object/array stack. + */ + private final JSONObject stack[]; + + /** + * The stack top index. A value of 0 indicates that the stack is empty. + */ + private int top; + + /** + * The writer that will receive the output. + */ + protected Writer writer; + + /** + * Make a fresh JSONWriter. It can be used to build one JSON text. + */ + public JSONWriter(Writer w) { + this.comma = false; + this.mode = 'i'; + this.stack = new JSONObject[maxdepth]; + this.top = 0; + this.writer = w; + } + + /** + * Append a value. + * @param string A string value. + * @return this + * @throws JSONException If the value is out of sequence. + */ + private JSONWriter append(String string) throws JSONException { + if (string == null) { + throw new JSONException("Null pointer"); + } + if (this.mode == 'o' || this.mode == 'a') { + try { + if (this.comma && this.mode == 'a') { + this.writer.write(','); + } + this.writer.write(string); + } catch (IOException e) { + throw new JSONException(e); + } + if (this.mode == 'o') { + this.mode = 'k'; + } + this.comma = true; + return this; + } + throw new JSONException("Value out of sequence."); + } + + /** + * Begin appending a new array. All values until the balancing + * endArray will be appended to this array. The + * endArray method must be called to mark the array's end. + * @return this + * @throws JSONException If the nesting is too deep, or if the object is + * started in the wrong place (for example as a key or after the end of the + * outermost array or object). + */ + public JSONWriter array() throws JSONException { + if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { + this.push(null); + this.append("["); + this.comma = false; + return this; + } + throw new JSONException("Misplaced array."); + } + + /** + * End something. + * @param mode Mode + * @param c Closing character + * @return this + * @throws JSONException If unbalanced. + */ + private JSONWriter end(char mode, char c) throws JSONException { + if (this.mode != mode) { + throw new JSONException(mode == 'a' + ? "Misplaced endArray." + : "Misplaced endObject."); + } + this.pop(mode); + try { + this.writer.write(c); + } catch (IOException e) { + throw new JSONException(e); + } + this.comma = true; + return this; + } + + /** + * End an array. This method most be called to balance calls to + * array. + * @return this + * @throws JSONException If incorrectly nested. + */ + public JSONWriter endArray() throws JSONException { + return this.end('a', ']'); + } + + /** + * End an object. This method most be called to balance calls to + * object. + * @return this + * @throws JSONException If incorrectly nested. + */ + public JSONWriter endObject() throws JSONException { + return this.end('k', '}'); + } + + /** + * Append a key. The key will be associated with the next value. In an + * object, every value must be preceded by a key. + * @param string A key string. + * @return this + * @throws JSONException If the key is out of place. For example, keys + * do not belong in arrays or if the key is null. + */ + public JSONWriter key(String string) throws JSONException { + if (string == null) { + throw new JSONException("Null key."); + } + if (this.mode == 'k') { + try { + this.stack[this.top - 1].putOnce(string, Boolean.TRUE); + if (this.comma) { + this.writer.write(','); + } + this.writer.write(JSONObject.quote(string)); + this.writer.write(':'); + this.comma = false; + this.mode = 'o'; + return this; + } catch (IOException e) { + throw new JSONException(e); + } + } + throw new JSONException("Misplaced key."); + } + + + /** + * Begin appending a new object. All keys and values until the balancing + * endObject will be appended to this object. The + * endObject method must be called to mark the object's end. + * @return this + * @throws JSONException If the nesting is too deep, or if the object is + * started in the wrong place (for example as a key or after the end of the + * outermost array or object). + */ + public JSONWriter object() throws JSONException { + if (this.mode == 'i') { + this.mode = 'o'; + } + if (this.mode == 'o' || this.mode == 'a') { + this.append("{"); + this.push(new JSONObject()); + this.comma = false; + return this; + } + throw new JSONException("Misplaced object."); + + } + + + /** + * Pop an array or object scope. + * @param c The scope to close. + * @throws JSONException If nesting is wrong. + */ + private void pop(char c) throws JSONException { + if (this.top <= 0) { + throw new JSONException("Nesting error."); + } + char m = this.stack[this.top - 1] == null ? 'a' : 'k'; + if (m != c) { + throw new JSONException("Nesting error."); + } + this.top -= 1; + this.mode = this.top == 0 + ? 'd' + : this.stack[this.top - 1] == null + ? 'a' + : 'k'; + } + + /** + * Push an array or object scope. + * @param jo The scope to open. + * @throws JSONException If nesting is too deep. + */ + private void push(JSONObject jo) throws JSONException { + if (this.top >= maxdepth) { + throw new JSONException("Nesting too deep."); + } + this.stack[this.top] = jo; + this.mode = jo == null ? 'a' : 'k'; + this.top += 1; + } + + + /** + * Append either the value true or the value + * false. + * @param b A boolean. + * @return this + * @throws JSONException + */ + public JSONWriter value(boolean b) throws JSONException { + return this.append(b ? "true" : "false"); + } + + /** + * Append a double value. + * @param d A double. + * @return this + * @throws JSONException If the number is not finite. + */ + public JSONWriter value(double d) throws JSONException { + return this.value(new Double(d)); + } + + /** + * Append a long value. + * @param l A long. + * @return this + * @throws JSONException + */ + public JSONWriter value(long l) throws JSONException { + return this.append(Long.toString(l)); + } + + + /** + * Append an object value. + * @param object The object to append. It can be null, or a Boolean, Number, + * String, JSONObject, or JSONArray, or an object that implements JSONString. + * @return this + * @throws JSONException If the value is out of sequence. + */ + public JSONWriter value(Object object) throws JSONException { + return this.append(JSONObject.valueToString(object)); + } +} diff --git a/blade-kit/src/test/java/blade/test/JSONTest.java b/blade-kit/src/test/java/blade/test/JSONTest.java new file mode 100644 index 000000000..565c32112 --- /dev/null +++ b/blade-kit/src/test/java/blade/test/JSONTest.java @@ -0,0 +1,36 @@ +package blade.test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import blade.kit.json.JSONKit; + +public class JSONTest { + + + public static void main(String[] args) { + //[{"text": "首页","href": "/"},{"text": "博客","href": "blog"},{"text": "关于","href": "about"},{"text": "联系","href": "contact"}] + String json = "[{\"text\": \"博客\",\"href\": \"blog\"}]"; + + // 下面构造两个map、一个list和一个Employee对象 + Map map1 = new HashMap(); + map1.put("name", "Alexia"); + map1.put("sex", "female"); + map1.put("age", "23"); + + List> list = new ArrayList>(); + Map map = new HashMap(); + + map.put("abc", "123456"); + map.put("def", "hmm"); + list.add(map); + + String string = JSONKit.toJSONString(list); + System.out.println(string); + + System.out.println(JSONKit.toList(json)); + } + +} From 7379ec53dc045926f65bf7da0333c1d826d1b46d Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 20 Jul 2015 15:41:45 +0800 Subject: [PATCH 029/545] RE --- README.md | 5 +++++ README_EN.md | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/README.md b/README.md index 3a7eebe0f..96bd23a34 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,11 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ## 更新日志 +### v1.2.4 + 1. 添加配置文件方式 + 2. 优化代码性能 + 3. 添加404、500页面配置 + ### v1.2.2 1. `DateKit`添加获取当前unix时间戳 2. 修复`blade-sql2o`分页bug diff --git a/README_EN.md b/README_EN.md index 2b88d6493..c36ea3a8c 100644 --- a/README_EN.md +++ b/README_EN.md @@ -125,6 +125,11 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ### Update +### v1.2.4 + 1. Add a configuration file + 2. Optimize the code performance + 3. Add 404, 500 page configuration + ### v1.2.2 1. `DateKit` added to obtain the current Unix timestamp 2. fix `blade-sql2o` paging bug From 7c6c618492edd6fc85353ee97aaf9e9f99520be1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 20 Jul 2015 16:16:21 +0800 Subject: [PATCH 030/545] update readme --- README.md | 3 ++- README_EN.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 96bd23a34..aeb4e992b 100644 --- a/README.md +++ b/README.md @@ -16,13 +16,14 @@ * 简洁的MVC & 拦截器 * REST风格API -* 注解方式开发 +* 注解方式 开发 * 微内核IOC容器 * 实用工具类 * 模板引擎支持 * 支持JDK1.6+ * 内置Jetty启动 * 插件扩展机制 +* 缓存数据信息 * ... ## 快速入门 diff --git a/README_EN.md b/README_EN.md index c36ea3a8c..0e53c2c98 100644 --- a/README_EN.md +++ b/README_EN.md @@ -25,6 +25,7 @@ * Support JDK1.6 + * Jetty is started * Plug-in extension mechanism +* Cache the data information * ... ## Quick start From a43faf6a87f45b2e3d0e653291bfc6bcfb2b19d5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 21 Jul 2015 15:40:11 +0800 Subject: [PATCH 031/545] add the blade configuration object remove redundant code --- blade-core/src/main/java/blade/BladeBase.java | 186 +++++++----------- .../src/main/java/blade/IocApplication.java | 3 +- .../src/main/java/blade/render/Render.java | 6 +- .../java/blade/route/RouteMatcherBuilder.java | 27 ++- .../java/blade/plugin/sql2o/Condition.java | 36 ++-- pom.xml | 2 +- 6 files changed, 114 insertions(+), 146 deletions(-) diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index e396ee40e..816adc786 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -17,8 +17,6 @@ import java.io.IOException; import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.HashMap; import java.util.Map; import blade.ioc.Container; @@ -39,42 +37,13 @@ */ abstract class BladeBase { - /** - * 默认路由后缀包,用户扫描路由所在位置,默认为route,用户可自定义 - */ - public static String PACKAGE_ROUTE = "route"; - protected static final String DEFAULT_ACCEPT_TYPE = "*/*"; - /** - * 默认拦截器后缀包,用户扫描拦截器所在位置,默认为interceptor,用户可自定义 - */ - public static String PACKAGE_INTERCEPTOR = "interceptor"; - - public static final Charset UTF_8 = Charset.forName("UTF-8"); - - public static Map confMap = null; - /** * 是否以jetty方式运行 */ public static boolean runJetty = false; - /** - * web应用根目录,应用启动时载入 - */ - private static String WEB_ROOT = ""; - - /** - * Blade默认编码,可修改 - */ - protected static String ENCODING = UTF_8.toString(); - - /** - * 默认视图的路径,默认渲染引擎为JSP,设置WEB-INF目录更安全,可配置 - */ - protected static String VIEW_PATH = "/WEB-INF/"; - /** * 静态资源所在文件夹 */ @@ -85,11 +54,6 @@ abstract class BladeBase { */ protected static boolean IS_INIT = false; - /** - * 默认视图文件后缀名 - */ - protected static String VIEW_EXT = ".jsp"; - /** * blade全局初始化对象,在web.xml中配置,必须 */ @@ -100,47 +64,21 @@ abstract class BladeBase { */ protected static DefaultRouteMatcher routeMatcher; - /** - * 存放要扫描的包map - */ - protected static final Map packageMap = new HashMap(); - - /** - * 默认的404视图 - */ - protected static String VIEW_404 = null; - - /** - * 默认的500视图 - */ - protected static String VIEW_500 = null; - /** * jetty启动的默认端口 */ protected static int PORT = 9000; - protected static boolean DEBUG = true; - + /** + * 全局配置对象 + */ + private final static BladeConfig BLADE_CONFIG = new BladeConfig(); + /** * IOC容器,存储路由到ioc中 */ private final static Container container = DefaultContainer.single(); - /** - * 包类型枚举 - * - * basepackge 基础包,默认的路由,拦截器包 - * route 路由包,所有路由所在包,可递归 - * interceptor 拦截器包,所有拦截器所在包,不可递归 - * ioc IOC对象所在包,可递归 - * @author biezhi - * - */ - public enum PackageNames { - basepackge, route, interceptor, ioc - } - protected BladeBase() { } @@ -150,11 +88,11 @@ protected BladeBase() { * 设置路由包,如:com.baldejava.route * 可传入多个包,所有的路由类都在该包下 * - * @param pckages 路由包路径 + * @param packages 路由包路径 */ - public static synchronized void routes(String...pckages){ - if(null != pckages && pckages.length >0){ - packageMap.put(PackageNames.route, pckages); + public static synchronized void routes(String...packages){ + if(null != packages && packages.length >0){ + BLADE_CONFIG.setRoutePackages(packages); } } @@ -166,7 +104,7 @@ public static synchronized void routes(String...pckages){ */ public static synchronized void defaultRoute(String basePackage){ if(null != basePackage){ - packageMap.put(PackageNames.basepackge, new String[]{basePackage}); + BLADE_CONFIG.setBasePackage(basePackage); } } @@ -177,18 +115,18 @@ public static synchronized void defaultRoute(String basePackage){ */ public static synchronized void interceptor(String packageName) { if(null != packageName && packageName.length() >0){ - packageMap.put(PackageNames.interceptor, new String[]{packageName}); + BLADE_CONFIG.setInterceptorPackage(packageName); } } /** * 设置依赖注入包,如:com.bladejava.service * - * @param pckages 所有需要做注入的包,可传入多个 + * @param packages 所有需要做注入的包,可传入多个 */ - public static synchronized void ioc(String...pckages){ - if(null != pckages && pckages.length >0){ - packageMap.put(PackageNames.ioc, pckages); + public static synchronized void ioc(String...packages){ + if(null != packages && packages.length >0){ + BLADE_CONFIG.setIocPackages(packages); } } @@ -202,13 +140,13 @@ public static synchronized void viewEngin(Render render) { } /** - * 设置默认视图路径,默认为WEB_ROOT/WEB-INF目录 + * 设置默认视图前缀,默认为WEB_ROOT/WEB-INF目录 * - * @param viewPath 视图路径,如:/WEB-INF/views + * @param prefix 视图路径,如:/WEB-INF/views */ - public static synchronized void viewPath(final String viewPath) { - if(null != viewPath && viewPath.startsWith("/")){ - VIEW_PATH = viewPath; + public static synchronized void viewPrefix(final String prefix) { + if(null != prefix && prefix.startsWith("/")){ + BLADE_CONFIG.setViewPrefix(prefix); } } @@ -217,9 +155,9 @@ public static synchronized void viewPath(final String viewPath) { * * @param viewExt 视图后缀,如:.html .vm */ - public static synchronized void viewExt(final String viewExt) { - if(null != viewExt && viewExt.startsWith(".")){ - VIEW_EXT = viewExt; + public static synchronized void viewSuffix(final String suffix) { + if(null != suffix && suffix.startsWith(".")){ + BLADE_CONFIG.setViewSuffix(suffix); } } @@ -230,17 +168,18 @@ public static synchronized void viewExt(final String viewExt) { * @param viewExt 视图后缀,如:.html .vm */ public static synchronized void view(final String viewPath, final String viewExt) { - viewPath(viewPath); - viewExt(viewExt); + viewPrefix(viewPath); + viewSuffix(viewExt); } /** * 设置框架静态文件所在文件夹 * - * @param folder + * @param folders */ - public static synchronized void staticFolder(final String ... folder) { - STATIC_FOLDER = folder; + public static synchronized void staticFolder(final String ... folders) { + BLADE_CONFIG.setStaticFolders(folders); + STATIC_FOLDER = folders; } /** @@ -272,7 +211,7 @@ public static synchronized void app(BladeApplication bladeApplication){ * @param view404 404视图页面 */ public static synchronized void view404(final String view404){ - BladeBase.VIEW_404 = view404; + BLADE_CONFIG.setView404(view404); } /** @@ -281,7 +220,7 @@ public static synchronized void view404(final String view404){ * @param view500 500视图页面 */ public static synchronized void view500(final String view500){ - BladeBase.VIEW_500 = view500; + BLADE_CONFIG.setView500(view500); } /** @@ -290,7 +229,7 @@ public static synchronized void view500(final String view500){ * @param webRoot web根目录物理路径 */ public static synchronized void webRoot(final String webRoot){ - BladeBase.WEB_ROOT = webRoot; + BLADE_CONFIG.setWebRoot(webRoot); } /** @@ -298,7 +237,8 @@ public static synchronized void webRoot(final String webRoot){ * @param isdebug true:是,默认true;false:否 */ public static synchronized void debug(boolean isdebug){ - BladeBase.DEBUG = isdebug; + BLADE_CONFIG.setDebug(isdebug); +// BladeBase.DEBUG = isdebug; } /**--------------------SET CONST:END-------------------------*/ @@ -307,81 +247,93 @@ public static synchronized void debug(boolean isdebug){ /**--------------------GET CONST:START-------------------------*/ + public static BladeConfig config(){ + return BLADE_CONFIG; + } + /** * @return 返回Blade要扫描的基础包 */ - public static String[] defaultRoutes(){ - return packageMap.get(PackageNames.basepackge); + public static String basePackage(){ + return BLADE_CONFIG.getBasePackage(); } /** * @return 返回路由包数组 */ public static String[] routes(){ - return packageMap.get(PackageNames.route); + return BLADE_CONFIG.getRoutePackages(); + } + + /** + * @return 返回IOC所有包 + */ + public static String[] iocs(){ + return BLADE_CONFIG.getIocPackages(); } /** * @return 返回拦截器包数组,只有一个元素 这里统一用String[] */ - public static String[] interceptor(){ - return packageMap.get(PackageNames.interceptor); + public static String interceptor(){ + return BLADE_CONFIG.getInterceptorPackage(); } + /** * @return 返回视图存放路径 */ - public static String viewPath(){ - return VIEW_PATH; + public static String viewPrefix(){ + return BLADE_CONFIG.getViewPrefix(); } /** * @return 返回系统默认字符编码 */ public static String encoding(){ - return ENCODING; + return BLADE_CONFIG.getEncoding(); } /** * @return 返回balde启动端口 */ - public static String viewExt(){ - return VIEW_EXT; + public static String viewSuffix(){ + return BLADE_CONFIG.getViewSuffix(); } /** * @return 返回404视图 */ public static String view404(){ - return BladeBase.VIEW_404; + return BLADE_CONFIG.getView404(); } /** * @return 返回500视图 */ public static String view500(){ - return BladeBase.VIEW_500; + return BLADE_CONFIG.getView500(); } /** * @return 返回webroot路径 */ public static String webRoot(){ - return BladeBase.WEB_ROOT; + return BLADE_CONFIG.getWebRoot(); } /** * @return 返回系统是否以debug方式运行 */ public static boolean debug(){ - return BladeBase.DEBUG; + return BLADE_CONFIG.isDebug(); } /** * @return 返回静态资源目录 */ public static String[] staticFolder(){ - return BladeBase.STATIC_FOLDER; + return BLADE_CONFIG.getStaticFolders(); } /** @@ -476,8 +428,8 @@ public static synchronized void register(Object object){ * @param confName 配置文件名称 */ public static synchronized void config(String confName){ - confMap = PropertyKit.getPropertyMap(confName); - + Map configMap = PropertyKit.getPropertyMap(confName); + configuration(configMap); } /** @@ -489,7 +441,8 @@ public static synchronized void configJsonPath(String jsonPath){ if(null != inputStream){ try { String json = IOKit.toString(inputStream); - confMap = JSONKit.toMap(json); + Map configMap = JSONKit.toMap(json); + configuration(configMap); } catch (IOException e) { e.printStackTrace(); } @@ -501,7 +454,14 @@ public static synchronized void configJsonPath(String jsonPath){ * @param json json配置 */ public static synchronized void configJson(String json){ - confMap = JSONKit.toMap(json); + Map configMap = JSONKit.toMap(json); + configuration(configMap); + } + + private static void configuration(Map configMap){ + if(null != configMap && configMap.size() > 0){ + + } } static synchronized void init() { diff --git a/blade-core/src/main/java/blade/IocApplication.java b/blade-core/src/main/java/blade/IocApplication.java index bafdfa520..311a618dc 100644 --- a/blade-core/src/main/java/blade/IocApplication.java +++ b/blade-core/src/main/java/blade/IocApplication.java @@ -17,7 +17,6 @@ import java.util.Set; -import blade.BladeBase.PackageNames; import blade.ioc.Container; import blade.ioc.DefaultContainer; import blade.kit.log.Logger; @@ -69,7 +68,7 @@ private static void initApp(){ * */ private static void initIOC() { - String[] iocPackages = BladeBase.packageMap.get(PackageNames.ioc); + String[] iocPackages = BladeBase.iocs(); if(null != iocPackages && iocPackages.length > 0){ for(String packageName : iocPackages){ registerBean(packageName); diff --git a/blade-core/src/main/java/blade/render/Render.java b/blade-core/src/main/java/blade/render/Render.java index 04145010c..0900ee32c 100644 --- a/blade-core/src/main/java/blade/render/Render.java +++ b/blade-core/src/main/java/blade/render/Render.java @@ -231,10 +231,10 @@ public void javascript(String javascript){ */ String disposeView(String view){ if(null != view){ - view = Blade.viewPath() + view; + view = Blade.viewPrefix() + view; view = view.replaceAll("[/]+", "/"); - if(!view.endsWith(Blade.viewExt())){ - view = view + Blade.viewExt(); + if(!view.endsWith(Blade.viewSuffix())){ + view = view + Blade.viewSuffix(); } } return view; diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index 6a98ec274..d79bcfa90 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -26,6 +26,7 @@ import blade.annotation.Route; import blade.ioc.Container; import blade.ioc.DefaultContainer; +import blade.kit.StringKit; import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; @@ -42,6 +43,16 @@ public final class RouteMatcherBuilder { private static DefaultRouteMatcher routeMatcher = null; + /** + * 默认路由后缀包,用户扫描路由所在位置,默认为route,用户可自定义 + */ + private final static String PACKAGE_ROUTE = "route"; + + /** + * 默认拦截器后缀包,用户扫描拦截器所在位置,默认为interceptor,用户可自定义 + */ + private final static String PACKAGE_INTERCEPTOR = "interceptor"; + /** * 类读取器,用于在指定规则中扫描类 */ @@ -73,18 +84,16 @@ public static synchronized DefaultRouteMatcher building() { LOGGER.debug("creates RouteMatcher"); } - String[] basePackages = Blade.defaultRoutes(); + String basePackage = Blade.basePackage(); - if(null != basePackages && basePackages.length > 0){ - - String basePackage = basePackages[0]; + if(StringKit.isNotBlank(basePackage)){ // 处理如:com.xxx.* 表示递归扫描包 String suffix = basePackage.endsWith(".*") ? ".*" : ""; basePackage = basePackage.endsWith(".*") ? basePackage.substring(0, basePackage.length() - 2) : basePackage; - String routePackage = basePackage + "." + Blade.PACKAGE_ROUTE + suffix; - String interceptorPackage = basePackage + "." + Blade.PACKAGE_INTERCEPTOR + suffix; + String routePackage = basePackage + "." + PACKAGE_ROUTE + suffix; + String interceptorPackage = basePackage + "." + PACKAGE_INTERCEPTOR + suffix; buildRoute(routePackage); @@ -98,9 +107,9 @@ public static synchronized DefaultRouteMatcher building() { } // 拦截器 - String[] interceptorPackages = Blade.interceptor(); - if(null != interceptorPackages && interceptorPackages.length > 0){ - buildInterceptor(interceptorPackages); + String interceptorPackage = Blade.interceptor(); + if(StringKit.isNotBlank(interceptorPackage)){ + buildInterceptor(interceptorPackage); } } return routeMatcher; diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java index 3eac041fd..e26d0dd77 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java @@ -167,7 +167,7 @@ public void clearMap() { public void select() { this.sql = "select * from " + this.tableName; - this.equalsParams = CollectionKit.newHashMap(); + this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.SELECT; this.orderby = null; } @@ -178,7 +178,7 @@ public void select() { */ public void select(String sql) { this.sql = sql; - this.equalsParams = CollectionKit.newHashMap(); + this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.SELECT; this.orderby = null; } @@ -188,7 +188,7 @@ public void select(String sql) { */ public void count(){ this.sql = "select count(1) from " + this.tableName; - this.equalsParams = CollectionKit.newHashMap(); + this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.COUNT; this.orderby = null; } @@ -200,15 +200,15 @@ public void count(){ */ public void count(String sql){ this.sql = sql; - this.equalsParams = CollectionKit.newHashMap(); + this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.COUNT; this.orderby = null; } public void update(){ this.sql = "update " + this.tableName; - this.params = CollectionKit.newHashMap(); - this.equalsParams = CollectionKit.newHashMap(); + this.params = CollectionKit.newLinkedHashMap(); + this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.UPDATE; } @@ -218,14 +218,14 @@ public void update(){ */ public void update(String sql){ this.sql = sql; - this.params = CollectionKit.newHashMap(); - this.equalsParams = CollectionKit.newHashMap(); + this.params = CollectionKit.newLinkedHashMap(); + this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.UPDATE; } public void insert(){ this.sql = "insert into " + this.tableName; - this.params = CollectionKit.newHashMap(); + this.params = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.INSERT; } @@ -235,13 +235,13 @@ public void insert(){ */ public void insert(String sql){ this.sql = sql; - this.params = CollectionKit.newHashMap(); + this.params = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.INSERT; } public void delete(){ this.sql = "delete from " + this.tableName; - this.equalsParams = CollectionKit.newHashMap(); + this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.DELETE; } @@ -251,7 +251,7 @@ public void delete(){ */ public void delete(String sql){ this.sql = sql; - this.equalsParams = CollectionKit.newHashMap(); + this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.DELETE; } @@ -290,7 +290,7 @@ public void where(String name, Object value){ public void greater(String name, Object value){ if(StringKit.isNotBlank(name) && null != value){ if(null == this.greaterParams){ - this.greaterParams = CollectionKit.newHashMap(); + this.greaterParams = CollectionKit.newLinkedHashMap(); } this.greaterParams.put(name, value); this.logParams.add(value); @@ -306,7 +306,7 @@ public void greater(String name, Object value){ public void greaterThan(String name, Object value){ if(StringKit.isNotBlank(name) && null != value){ if(null == this.greaterThanParams){ - this.greaterThanParams = CollectionKit.newHashMap(); + this.greaterThanParams = CollectionKit.newLinkedHashMap(); } this.greaterThanParams.put(name, value); this.logParams.add(value); @@ -323,7 +323,7 @@ public void greaterThan(String name, Object value){ public void less(String name, Object value){ if(StringKit.isNotBlank(name) && null != value){ if(null == this.lessParams){ - this.lessParams = CollectionKit.newHashMap(); + this.lessParams = CollectionKit.newLinkedHashMap(); } this.lessParams.put(name, value); this.logParams.add(value); @@ -340,7 +340,7 @@ public void lessThan(String name, Object value){ if(StringKit.isNotBlank(name) && null != value){ if(null == this.lessThanParams){ - this.lessThanParams = CollectionKit.newHashMap(); + this.lessThanParams = CollectionKit.newLinkedHashMap(); } this.lessThanParams.put(name, value); this.logParams.add(value); @@ -359,7 +359,7 @@ public void like(String name, String value){ && value.indexOf("%null")==-1 && value.indexOf("null%")==-1 && !value.equals("%%")){ if(null == this.likeParams){ - this.likeParams = CollectionKit.newHashMap(); + this.likeParams = CollectionKit.newLinkedHashMap(); } this.likeParams.put(name, value); this.logParams.add(value); @@ -375,7 +375,7 @@ public void like(String name, String value){ public void in(String name, Object... values){ if(StringKit.isNotBlank(name) && null != values && values.length > 1){ if(null == this.inParams){ - this.inParams = CollectionKit.newHashMap(); + this.inParams = CollectionKit.newLinkedHashMap(); } this.inParams.put(name, values); this.logParams.add(Arrays.toString(values)); diff --git a/pom.xml b/pom.xml index e42573f52..8a425f2cf 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ 1.6 UTF-8 4.11 - 1.2.2 + 1.2.4 3.0.1 From 017f99e7d29ed105514387bbe7ff43e407cbf7dc Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 22 Jul 2015 09:48:14 +0800 Subject: [PATCH 032/545] add blade config --- .../src/main/java/blade/BladeConfig.java | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 blade-core/src/main/java/blade/BladeConfig.java diff --git a/blade-core/src/main/java/blade/BladeConfig.java b/blade-core/src/main/java/blade/BladeConfig.java new file mode 100644 index 000000000..aa3853d9b --- /dev/null +++ b/blade-core/src/main/java/blade/BladeConfig.java @@ -0,0 +1,192 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Blade配置类 + * + * @author biezhi + * @since 1.0 + * + */ +public class BladeConfig { + + private List routePackages = new ArrayList(); + private List iocPackages = new ArrayList(); + private List staticFolders = new ArrayList(); + private String basePackage; + private String interceptorPackage; + private String encoding = "utf-8"; + private String viewPrefix = "/WEB-INF/"; + private String viewSuffix = ".jsp"; + private String webRoot; + private String view404; + private String view500; + private String dbUrl; + private String dbDriver; + private String dbUser; + private String dbPass; + private boolean isOpenCache = false; + private boolean isDebug = false; + + public BladeConfig() { + } + + public String[] getRoutePackages() { + String[] routeArr = new String[routePackages.size()]; + return routePackages.toArray(routeArr); + } + + public void setRoutePackages(String ... packages) { + routePackages.addAll(Arrays.asList(packages)); + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } + + public String[] getIocPackages() { + String[] iocArr = new String[iocPackages.size()]; + return iocPackages.toArray(iocArr); + } + + public void setIocPackages(String ... packages) { + iocPackages.addAll(Arrays.asList(packages)); + } + + public String getInterceptorPackage() { + return interceptorPackage; + } + + public void setInterceptorPackage(String interceptorPackage) { + this.interceptorPackage = interceptorPackage; + } + + public String getViewPrefix() { + return viewPrefix; + } + + public void setViewPrefix(String viewPrefix) { + this.viewPrefix = viewPrefix; + } + + public String getViewSuffix() { + return viewSuffix; + } + + + public void setViewSuffix(String viewSuffix) { + this.viewSuffix = viewSuffix; + } + + public String[] getStaticFolders() { + String[] folderArr = new String[staticFolders.size()]; + return staticFolders.toArray(folderArr); + } + + public void setStaticFolders(String ... packages) { + staticFolders.addAll(Arrays.asList(packages)); + } + + public String getDbUrl() { + return dbUrl; + } + + public void setDbUrl(String dbUrl) { + this.dbUrl = dbUrl; + } + + public String getDbDriver() { + return dbDriver; + } + + public void setDbDriver(String dbDriver) { + this.dbDriver = dbDriver; + } + + public String getDbUser() { + return dbUser; + } + + public void setDbUser(String dbUser) { + this.dbUser = dbUser; + } + + public String getDbPass() { + return dbPass; + } + + public void setDbPass(String dbPass) { + this.dbPass = dbPass; + } + + public boolean isOpenCache() { + return isOpenCache; + } + + public void setOpenCache(boolean isOpenCache) { + this.isOpenCache = isOpenCache; + } + + public String getView404() { + return view404; + } + + public void setView404(String view404) { + this.view404 = view404; + } + + public String getView500() { + return view500; + } + + public void setView500(String view500) { + this.view500 = view500; + } + + public String getWebRoot() { + return webRoot; + } + + public void setWebRoot(String webRoot) { + this.webRoot = webRoot; + } + + public boolean isDebug() { + return isDebug; + } + + public void setDebug(boolean isDebug) { + this.isDebug = isDebug; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + +} From 947b20c0c2cd6cceab6b6009eb357e10af1dea9f Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 22 Jul 2015 13:19:37 +0800 Subject: [PATCH 033/545] add the blade configurator --- blade-core/src/main/java/blade/BladeBase.java | 29 ++-- .../src/main/java/blade/BladeConfig.java | 2 +- .../main/java/blade/BladeConfigurator.java | 137 ++++++++++++++++++ .../java/blade/plugin/sql2o/Sql2oPlugin.java | 34 ++++- 4 files changed, 188 insertions(+), 14 deletions(-) create mode 100644 blade-core/src/main/java/blade/BladeConfigurator.java diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index 816adc786..451714869 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -44,11 +44,6 @@ abstract class BladeBase { */ public static boolean runJetty = false; - /** - * 静态资源所在文件夹 - */ - protected static String[] STATIC_FOLDER = null; - /** * 框架是否已经初始化 */ @@ -179,7 +174,6 @@ public static synchronized void view(final String viewPath, final String viewExt */ public static synchronized void staticFolder(final String ... folders) { BLADE_CONFIG.setStaticFolders(folders); - STATIC_FOLDER = folders; } /** @@ -458,10 +452,27 @@ public static synchronized void configJson(String json){ configuration(configMap); } + /** + * 配置文件属性 + * blade.route= + * blade.interceptor= + * blade.ioc= + * blade.prefix= + * blade.suffix= + * blade.filter_folder= + * blade.dburl= + * blade.dbdriver= + * blade.dbuser= + * blade.dbpass= + * blade.opencache= + * blade.encoding= + * blade.view404= + * blade.view500= + * blade.debug= + * @param json json配置 + */ private static void configuration(Map configMap){ - if(null != configMap && configMap.size() > 0){ - - } + new BladeConfigurator(BladeBase.BLADE_CONFIG, configMap).run(); } static synchronized void init() { diff --git a/blade-core/src/main/java/blade/BladeConfig.java b/blade-core/src/main/java/blade/BladeConfig.java index aa3853d9b..d8c09ac44 100644 --- a/blade-core/src/main/java/blade/BladeConfig.java +++ b/blade-core/src/main/java/blade/BladeConfig.java @@ -44,7 +44,7 @@ public class BladeConfig { private String dbUser; private String dbPass; private boolean isOpenCache = false; - private boolean isDebug = false; + private boolean isDebug = true; public BladeConfig() { } diff --git a/blade-core/src/main/java/blade/BladeConfigurator.java b/blade-core/src/main/java/blade/BladeConfigurator.java new file mode 100644 index 000000000..fc692546c --- /dev/null +++ b/blade-core/src/main/java/blade/BladeConfigurator.java @@ -0,0 +1,137 @@ +package blade; + +import java.util.Map; + +import blade.kit.StringKit; + +public class BladeConfigurator { + + private BladeConfig bladeConfig; + + private Map configMap; + + public BladeConfigurator(BladeConfig bladeConfig, + Map configMap) { + this.bladeConfig = bladeConfig; + this.configMap = configMap; + } + + private static final String BLADE_ROUTE = "blade.route"; + private static final String BLADE_INTERCEPTOR = "blade.interceptor"; + private static final String BLADE_IOC = "blade.ioc"; + private static final String BLADE_PREFIX = "blade.prefix"; + private static final String BLADE_SUFFIX = "blade.suffix"; + private static final String BLADE_FILTER_FOLDER = "blade.filter_folder"; + private static final String BLADE_DBURL = "blade.dburl"; + private static final String BLADE_DBDRIVER = "blade.dbdriver"; + private static final String BLADE_DBUSER = "blade.dbuser"; + private static final String BLADE_DBPASS = "blade.dbpass"; + private static final String BLADE_OPENCACHE = "blade.opencache"; + private static final String BLADE_ENCODING = "blade.encoding"; + private static final String BLADE_VIEW_404 = "blade.view404"; + private static final String BLADE_VIEW_500 = "blade.view500"; + private static final String BLADE_DEBUG = "blade.debug"; + + /** + * 配置文件属性 + * blade.route= + * blade.interceptor= + * blade.ioc= + * blade.prefix= + * blade.suffix= + * blade.filter_folder= + * blade.dburl= + * blade.dbdriver= + * blade.dbuser= + * blade.dbpass= + * blade.opencache= + * blade.encoding= + * blade.view404= + * blade.view500= + * blade.debug= + */ + public void run() { + if (null != configMap && configMap.size() > 0) { + String route = configMap.get(BLADE_ROUTE); + String interceptor = configMap.get(BLADE_INTERCEPTOR); + String ioc = configMap.get(BLADE_IOC); + String prefix = configMap.get(BLADE_PREFIX); + String suffix = configMap.get(BLADE_SUFFIX); + String filter_folder = configMap.get(BLADE_FILTER_FOLDER); + String dburl = configMap.get(BLADE_DBURL); + String dbdriver = configMap.get(BLADE_DBDRIVER); + String dbuser = configMap.get(BLADE_DBUSER); + String dbpass = configMap.get(BLADE_DBPASS); + String opencache = configMap.get(BLADE_OPENCACHE); + String encoding = configMap.get(BLADE_ENCODING); + String view404 = configMap.get(BLADE_VIEW_404); + String view500 = configMap.get(BLADE_VIEW_500); + String debug = configMap.get(BLADE_DEBUG); + + if (StringKit.isNotBlank(route)) { + String[] blade_routes = route.split(","); + bladeConfig.setRoutePackages(blade_routes); + } + + if (StringKit.isNotBlank(filter_folder)) { + String[] blade_filter_folders = filter_folder.split(","); + bladeConfig.setStaticFolders(blade_filter_folders); + } + + if (StringKit.isNotBlank(interceptor)) { + bladeConfig.setInterceptorPackage(interceptor); + } + + if (StringKit.isNotBlank(ioc)) { + String[] blade_iocs = ioc.split(","); + bladeConfig.setIocPackages(blade_iocs); + } + + if (StringKit.isNotBlank(prefix)) { + bladeConfig.setViewPrefix(prefix); + } + + if (StringKit.isNotBlank(suffix)) { + bladeConfig.setViewSuffix(suffix); + } + + if (StringKit.isNotBlank(dburl)) { + bladeConfig.setDbUrl(dburl); + } + + if (StringKit.isNotBlank(dbdriver)) { + bladeConfig.setDbDriver(dbdriver); + } + + if (StringKit.isNotBlank(dbuser)) { + bladeConfig.setDbUser(dbuser); + } + + if (StringKit.isNotBlank(dbpass)) { + bladeConfig.setDbPass(dbpass); + } + + if (StringKit.isNotBlank(encoding)) { + bladeConfig.setEncoding(encoding); + } + + if (StringKit.isNotBlank(view404)) { + bladeConfig.setView404(view404); + } + + if (StringKit.isNotBlank(view500)) { + bladeConfig.setView500(view500); + } + + if (StringKit.isNotBlank(opencache)) { + Boolean opencacheBool = Boolean.valueOf(opencache); + bladeConfig.setOpenCache(opencacheBool); + } + + if (StringKit.isNotBlank(debug)) { + Boolean debugBool = Boolean.valueOf(debug); + bladeConfig.setDebug(debugBool); + } + } + } +} \ No newline at end of file diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index 5e36b7272..022a2720a 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -2,6 +2,7 @@ import javax.sql.DataSource; +import blade.Blade; import blade.kit.StringKit; import blade.kit.log.Logger; import blade.plugin.Plugin; @@ -26,6 +27,31 @@ public enum Sql2oPlugin implements Plugin { private Sql2oPlugin() { } + /** + * 设置数据库配置 + * + * @param dbConfig 数据库配置 + */ + public Sql2oPlugin autoConfig(){ + String drive = Blade.config().getDbDriver(); + String url = Blade.config().getDbUrl(); + String user = Blade.config().getDbUser(); + String password = Blade.config().getDbPass(); + INSTANCE.dbConfig = new DBConfig(drive, url, user, password); + INSTANCE.openCache = Blade.config().isOpenCache(); + return INSTANCE; + } + + /** + * 设置数据库配置 + * + * @param dbConfig 数据库配置 + */ + public Sql2oPlugin config(DBConfig dbConfig){ + INSTANCE.dbConfig = dbConfig; + return INSTANCE; + } + /** * 设置数据库配置 * @@ -39,23 +65,23 @@ public Sql2oPlugin config(String url, String driver, String user, String pass){ if(StringKit.isNotEmpty(url) && StringKit.isNotEmpty(driver) && StringKit.isNotEmpty(user) && StringKit.isNotEmpty(pass)){ - dbConfig = new DBConfig(driver, url, user, pass); + INSTANCE.dbConfig = new DBConfig(driver, url, user, pass); } return INSTANCE; } public Sql2oPlugin openCache(){ - this.openCache = true; + INSTANCE.openCache = true; return INSTANCE; } public boolean isOpenCache() { - return openCache; + return INSTANCE.openCache; } public DBConfig dbConfig(){ - return dbConfig; + return INSTANCE.dbConfig; } @Override From a6cade0d536707594d77c14257172427ff5e3d0e Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 22 Jul 2015 13:56:11 +0800 Subject: [PATCH 034/545] update readme --- README.md | 4 ++-- README_EN.md | 4 ++-- blade-core/src/main/java/blade/BladeBase.java | 17 +------------- .../main/java/blade/BladeConfigurator.java | 22 ++++++------------- .../src/main/java/blade/IocApplication.java | 6 ++++- .../main/java/blade/ioc/DefaultContainer.java | 5 +++-- 6 files changed, 20 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index aeb4e992b..352490867 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ * 内置Jetty启动 * 插件扩展机制 * 缓存数据信息 +* 编码/JSON/配置文件 * ... ## 快速入门 @@ -125,9 +126,8 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ## 更新日志 ### v1.2.4 - 1. 添加配置文件方式 + 1. 添加JSON、Properties文件配置 2. 优化代码性能 - 3. 添加404、500页面配置 ### v1.2.2 1. `DateKit`添加获取当前unix时间戳 diff --git a/README_EN.md b/README_EN.md index 0e53c2c98..8ed592bfb 100644 --- a/README_EN.md +++ b/README_EN.md @@ -26,6 +26,7 @@ * Jetty is started * Plug-in extension mechanism * Cache the data information +* Coding/JSON/config file * ... ## Quick start @@ -127,9 +128,8 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ### Update ### v1.2.4 - 1. Add a configuration file + 1. Add JSON, configuration Properties file 2. Optimize the code performance - 3. Add 404, 500 page configuration ### v1.2.2 1. `DateKit` added to obtain the current Unix timestamp diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index 451714869..dc8efccb9 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -453,22 +453,7 @@ public static synchronized void configJson(String json){ } /** - * 配置文件属性 - * blade.route= - * blade.interceptor= - * blade.ioc= - * blade.prefix= - * blade.suffix= - * blade.filter_folder= - * blade.dburl= - * blade.dbdriver= - * blade.dbuser= - * blade.dbpass= - * blade.opencache= - * blade.encoding= - * blade.view404= - * blade.view500= - * blade.debug= + * 配置 * @param json json配置 */ private static void configuration(Map configMap){ diff --git a/blade-core/src/main/java/blade/BladeConfigurator.java b/blade-core/src/main/java/blade/BladeConfigurator.java index fc692546c..50ed67f09 100644 --- a/blade-core/src/main/java/blade/BladeConfigurator.java +++ b/blade-core/src/main/java/blade/BladeConfigurator.java @@ -95,20 +95,17 @@ public void run() { bladeConfig.setViewSuffix(suffix); } - if (StringKit.isNotBlank(dburl)) { + if (StringKit.isNotBlank(dburl) && StringKit.isNotBlank(dbdriver) && + StringKit.isNotBlank(dbuser) && StringKit.isNotBlank(dbpass)) { bladeConfig.setDbUrl(dburl); - } - - if (StringKit.isNotBlank(dbdriver)) { bladeConfig.setDbDriver(dbdriver); - } - - if (StringKit.isNotBlank(dbuser)) { bladeConfig.setDbUser(dbuser); - } - - if (StringKit.isNotBlank(dbpass)) { bladeConfig.setDbPass(dbpass); + + if (StringKit.isNotBlank(opencache)) { + Boolean opencacheBool = Boolean.valueOf(opencache); + bladeConfig.setOpenCache(opencacheBool); + } } if (StringKit.isNotBlank(encoding)) { @@ -123,11 +120,6 @@ public void run() { bladeConfig.setView500(view500); } - if (StringKit.isNotBlank(opencache)) { - Boolean opencacheBool = Boolean.valueOf(opencache); - bladeConfig.setOpenCache(opencacheBool); - } - if (StringKit.isNotBlank(debug)) { Boolean debugBool = Boolean.valueOf(debug); bladeConfig.setDebug(debugBool); diff --git a/blade-core/src/main/java/blade/IocApplication.java b/blade-core/src/main/java/blade/IocApplication.java index 311a618dc..f56fa7387 100644 --- a/blade-core/src/main/java/blade/IocApplication.java +++ b/blade-core/src/main/java/blade/IocApplication.java @@ -55,7 +55,11 @@ public static void init(){ initIOC(); // 初始化注入 - container.initWired(); + try { + container.initWired(); + } catch (Exception e) { + LOGGER.error(e); + } } private static void initApp(){ diff --git a/blade-core/src/main/java/blade/ioc/DefaultContainer.java b/blade-core/src/main/java/blade/ioc/DefaultContainer.java index 466d18809..edc123f4e 100644 --- a/blade-core/src/main/java/blade/ioc/DefaultContainer.java +++ b/blade-core/src/main/java/blade/ioc/DefaultContainer.java @@ -27,6 +27,7 @@ import blade.annotation.Component; import blade.annotation.Inject; import blade.annotation.Path; +import blade.exception.BladeException; import blade.kit.CloneKit; import blade.kit.CollectionKit; import blade.kit.ReflectKit; @@ -218,7 +219,7 @@ private void put(Class clazz, List listObject){ * 初始化注入 */ @Override - public void initWired() { + public void initWired() throws RuntimeException { Iterator it = beansMap.values().iterator(); try { while (it.hasNext()) { @@ -250,7 +251,7 @@ public void initWired() { } } if (null == injectField) { - throw new RuntimeException("Unable to load " + field.getType().getCanonicalName() + "!"); + throw new BladeException("Unable to load " + field.getType().getCanonicalName() + "!"); } boolean accessible = field.isAccessible(); field.setAccessible(true); From aca9fc377c8b0a187afe606ef6142b41ca5baf76 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 22 Jul 2015 14:38:12 +0800 Subject: [PATCH 035/545] refactoring --- .../main/java/blade/render/BeetlRender.java | 92 +++++++++++-------- .../src/main/java/blade/render/Render.java | 16 ++-- .../src/main/java/blade/servlet/Request.java | 7 ++ .../src/main/java/blade/servlet/Response.java | 20 +++- .../java/blade/render/JetbrickRender.java | 62 ++++++++----- .../java/blade/render/VelocityRender.java | 90 ++++++++++-------- 6 files changed, 179 insertions(+), 108 deletions(-) diff --git a/blade-beetl/src/main/java/blade/render/BeetlRender.java b/blade-beetl/src/main/java/blade/render/BeetlRender.java index c111b4f4c..23def105e 100644 --- a/blade-beetl/src/main/java/blade/render/BeetlRender.java +++ b/blade-beetl/src/main/java/blade/render/BeetlRender.java @@ -1,13 +1,9 @@ package blade.render; import java.io.IOException; -import java.util.Enumeration; import java.util.Map; import java.util.Set; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.beetl.core.Configuration; import org.beetl.core.GroupTemplate; import org.beetl.core.Template; @@ -17,6 +13,10 @@ import blade.Blade; import blade.BladeWebContext; import blade.exception.BladeException; +import blade.kit.log.Logger; +import blade.servlet.Request; +import blade.servlet.Response; +import blade.servlet.Session; /** * Beetl渲染引擎 @@ -25,6 +25,8 @@ */ public class BeetlRender extends Render { + private static final Logger LOGGER = Logger.getLogger(BeetlRender.class); + private GroupTemplate groupTemplate = null; /** @@ -32,20 +34,20 @@ public class BeetlRender extends Render { */ public BeetlRender() { try { - String root = Blade.webRoot() + Blade.viewPath(); + String root = Blade.webRoot() + Blade.viewPrefix(); WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); resourceLoader.setAutoCheck(true); resourceLoader.setRoot(root); Configuration cfg = Configuration.defaultConfiguration(); groupTemplate = new GroupTemplate(resourceLoader, cfg); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } } public BeetlRender(Configuration configuration) { try { - String root = Blade.webRoot() + Blade.viewPath(); + String root = Blade.webRoot() + Blade.viewPrefix(); WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); resourceLoader.setAutoCheck(true); resourceLoader.setRoot(root); @@ -53,7 +55,7 @@ public BeetlRender(Configuration configuration) { groupTemplate = new GroupTemplate(resourceLoader, cfg); groupTemplate.setConf(configuration); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } } @@ -63,28 +65,34 @@ public BeetlRender(Configuration configuration) { @Override public Object render(String view) { + Response response = BladeWebContext.response(); try { - HttpServletRequest servletRequest = BladeWebContext.servletRequest(); - HttpServletResponse servletResponse = BladeWebContext.servletResponse(); + Request request = BladeWebContext.request(); + Session session = BladeWebContext.session(); view = disposeView(view); Template template = groupTemplate.getTemplate(view); - Enumeration attrs = servletRequest.getAttributeNames(); + Set attrs = request.attributes(); + if(null != attrs && attrs.size() > 0){ + for(String attr : attrs){ + template.binding(attr, request.attribute(attr)); + } + } - if(null != attrs && attrs.hasMoreElements()){ - while(attrs.hasMoreElements()){ - String attr = attrs.nextElement(); - template.binding(attr, servletRequest.getAttribute(attr)); + Set session_attrs = session.attributes(); + if(null != session_attrs && session_attrs.size() > 0){ + for(String attr : session_attrs){ + template.binding(attr, session.attribute(attr)); } } - template.renderTo(servletResponse.getOutputStream()); + template.renderTo(response.outputStream()); } catch (BeetlException e) { - e.printStackTrace(); + LOGGER.error(e); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } return null; } @@ -95,30 +103,22 @@ public Object render(String view) { */ @Override public Object render(ModelAndView modelAndView) { - HttpServletRequest servletRequest = BladeWebContext.servletRequest(); - HttpServletResponse servletResponse = BladeWebContext.servletResponse(); - - if(null == modelAndView){ - throw new BladeException("modelAndView is null"); - } + Response response = BladeWebContext.response(); try { + Request request = BladeWebContext.request(); + Session session = BladeWebContext.session(); + + if(null == modelAndView){ + throw new BladeException("modelAndView is null"); + } + String view = disposeView(modelAndView.getView()); Template template = groupTemplate.getTemplate(view); Map context = modelAndView.getModel(); - - Enumeration attrs = servletRequest.getAttributeNames(); - - if(null != attrs && attrs.hasMoreElements()){ - while(attrs.hasMoreElements()){ - String attr = attrs.nextElement(); - template.binding(attr, servletRequest.getAttribute(attr)); - } - } - if(null != context && context.size() > 0){ Set keys = context.keySet(); for(String key : keys){ @@ -126,11 +126,25 @@ public Object render(ModelAndView modelAndView) { } } - template.renderTo(servletResponse.getOutputStream()); + Set attrs = request.attributes(); + if(null != attrs && attrs.size() > 0){ + for(String attr : attrs){ + template.binding(attr, request.attribute(attr)); + } + } + + Set session_attrs = session.attributes(); + if(null != session_attrs && session_attrs.size() > 0){ + for(String attr : session_attrs){ + template.binding(attr, session.attribute(attr)); + } + } + + template.renderTo(response.outputStream()); } catch (BeetlException e) { - e.printStackTrace(); + LOGGER.error(e); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } return null; @@ -144,8 +158,8 @@ public Object render(ModelAndView modelAndView) { String disposeView(String view){ if(null != view){ view = view.replaceAll("[/]+", "/"); - if(!view.endsWith(Blade.viewExt())){ - view = view + Blade.viewExt(); + if(!view.endsWith(Blade.viewSuffix())){ + view = view + Blade.viewSuffix(); } } return view; diff --git a/blade-core/src/main/java/blade/render/Render.java b/blade-core/src/main/java/blade/render/Render.java index 0900ee32c..ae48dc9f8 100644 --- a/blade-core/src/main/java/blade/render/Render.java +++ b/blade-core/src/main/java/blade/render/Render.java @@ -25,6 +25,7 @@ import blade.Blade; import blade.BladeWebContext; +import blade.servlet.Response; /** * 渲染器抽象类 * @@ -42,10 +43,10 @@ public void render404(String viewName){ /** * 404视图 * - * @param httpResponse HttpServletResponse对象 + * @param response Responsee对象 * @param viewName 视图名称 */ - public void render404(HttpServletResponse httpResponse, String viewName){ + public void render404(Response response, String viewName){ try { String view404 = Blade.view404(); if(null != view404){ @@ -53,13 +54,12 @@ public void render404(HttpServletResponse httpResponse, String viewName){ modelAndView.add("viewName", viewName); render(modelAndView); } else { - if(null == httpResponse){ - httpResponse = BladeWebContext.servletResponse(); + if(null == response){ + response = BladeWebContext.response(); } - - httpResponse.setContentType("text/html; charset=utf-8"); - httpResponse.setStatus(404); - ServletOutputStream outputStream = httpResponse.getOutputStream(); + response.contentType("text/html; charset=utf-8"); + response.status(404); + ServletOutputStream outputStream = response.outputStream(); outputStream.print(String.format(VIEW_NOTFOUND, viewName + " Not Found")); outputStream.flush(); outputStream.close(); diff --git a/blade-core/src/main/java/blade/servlet/Request.java b/blade-core/src/main/java/blade/servlet/Request.java index 35f22d15c..cb0377497 100644 --- a/blade-core/src/main/java/blade/servlet/Request.java +++ b/blade-core/src/main/java/blade/servlet/Request.java @@ -193,6 +193,13 @@ public String contextPath() { return servletRequest.getContextPath(); } + /** + * @return 返回realPath + */ + public String realPath(String path) { + return servletRequest.getServletContext().getRealPath(path); + } + /** * @return 返回url */ diff --git a/blade-core/src/main/java/blade/servlet/Response.java b/blade-core/src/main/java/blade/servlet/Response.java index 2b89a0566..1f583c140 100644 --- a/blade-core/src/main/java/blade/servlet/Response.java +++ b/blade-core/src/main/java/blade/servlet/Response.java @@ -16,7 +16,9 @@ package blade.servlet; import java.io.IOException; +import java.io.PrintWriter; +import javax.servlet.ServletOutputStream; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; @@ -87,6 +89,22 @@ public String body() { return this.body; } + /** + * @return 返回输出流 + * @throws IOException + */ + public ServletOutputStream outputStream() throws IOException { + return response.getOutputStream(); + } + + /** + * @return 返回PrintWriter + * @throws IOException + */ + public PrintWriter writer() throws IOException { + return response.getWriter(); + } + /** * @return 返回原生HttpServletResponse */ @@ -262,7 +280,7 @@ public void html(String html){ * @param viewName */ public void render404(String viewName){ - render.render404(this.response, viewName); + render.render404(this, viewName); } /** diff --git a/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java b/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java index 16f885f0d..fea8ce88e 100644 --- a/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java +++ b/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java @@ -1,13 +1,10 @@ package blade.render; import java.io.IOException; -import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Properties; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import java.util.Set; import jetbrick.io.resource.ResourceNotFoundException; import jetbrick.template.JetEngine; @@ -15,6 +12,10 @@ import blade.Blade; import blade.BladeWebContext; import blade.exception.BladeException; +import blade.kit.log.Logger; +import blade.servlet.Request; +import blade.servlet.Response; +import blade.servlet.Session; /** * Velocity渲染引擎 @@ -23,6 +24,8 @@ */ public class JetbrickRender extends Render { + private static final Logger LOGGER = Logger.getLogger(JetbrickRender.class); + private JetEngine jetEngine; private Properties config; @@ -100,10 +103,10 @@ public JetbrickRender(JetEngine jetEngine) { @Override public Object render(String view) { - HttpServletRequest request = BladeWebContext.servletRequest(); - HttpServletResponse response = BladeWebContext.servletResponse(); - + Response response = BladeWebContext.response(); try { + Request request = BladeWebContext.request(); + Session session = BladeWebContext.session(); view = Blade.webRoot() + disposeView(view); @@ -111,20 +114,25 @@ public Object render(String view) { Map context = new HashMap(); - Enumeration attrs = request.getAttributeNames(); + Set attrs = request.attributes(); + if(null != attrs && attrs.size() > 0){ + for(String attr : attrs){ + context.put(attr, request.attribute(attr)); + } + } - if(null != attrs && attrs.hasMoreElements()){ - while(attrs.hasMoreElements()){ - String attr = attrs.nextElement(); - context.put(attr, request.getAttribute(attr)); + Set session_attrs = session.attributes(); + if(null != session_attrs && session_attrs.size() > 0){ + for(String attr : session_attrs){ + context.put(attr, session.attribute(attr)); } } - template.render(context, response.getOutputStream()); + template.render(context, response.outputStream()); } catch (ResourceNotFoundException e) { render404(response, view); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } return null; } @@ -135,10 +143,12 @@ public Object render(String view) { */ @Override public Object render(ModelAndView modelAndView) { - HttpServletRequest request = BladeWebContext.servletRequest(); - HttpServletResponse response = BladeWebContext.servletResponse(); + + Response response = BladeWebContext.response(); try { + Request request = BladeWebContext.request(); + Session session = BladeWebContext.session(); if(null == modelAndView){ throw new BladeException("modelAndView is null"); @@ -150,22 +160,26 @@ public Object render(ModelAndView modelAndView) { Map context = modelAndView.getModel(); - Enumeration attrs = request.getAttributeNames(); - - if(null != attrs && attrs.hasMoreElements()){ - while(attrs.hasMoreElements()){ - String attr = attrs.nextElement(); - context.put(attr, request.getAttribute(attr)); + Set attrs = request.attributes(); + if(null != attrs && attrs.size() > 0){ + for(String attr : attrs){ + context.put(attr, request.attribute(attr)); } } + Set session_attrs = session.attributes(); + if(null != session_attrs && session_attrs.size() > 0){ + for(String attr : session_attrs){ + context.put(attr, session.attribute(attr)); + } + } - template.render(context, response.getOutputStream()); + template.render(context, response.outputStream()); } catch (ResourceNotFoundException e) { render404(response, modelAndView.getView()); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } return null; } diff --git a/blade-velocity/src/main/java/blade/render/VelocityRender.java b/blade-velocity/src/main/java/blade/render/VelocityRender.java index 4031c74f6..9230522cc 100644 --- a/blade-velocity/src/main/java/blade/render/VelocityRender.java +++ b/blade-velocity/src/main/java/blade/render/VelocityRender.java @@ -5,11 +5,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; -import java.util.Enumeration; import java.util.Properties; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import java.util.Set; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; @@ -22,6 +19,10 @@ import blade.Blade; import blade.BladeWebContext; import blade.exception.BladeException; +import blade.kit.log.Logger; +import blade.servlet.Request; +import blade.servlet.Response; +import blade.servlet.Session; /** * Velocity渲染引擎 @@ -30,6 +31,8 @@ */ public class VelocityRender extends Render { + private static final Logger LOGGER = Logger.getLogger(VelocityRender.class); + private final VelocityEngine velocityEngine; /** @@ -77,8 +80,8 @@ public VelocityRender(Properties properties) { * 手动构造Velocity引擎 * @param velocityEngine_ */ - public VelocityRender(VelocityEngine velocityEngine_) { - velocityEngine = velocityEngine_; + public VelocityRender(VelocityEngine velocityEngine) { + this.velocityEngine = velocityEngine; } /** @@ -87,24 +90,32 @@ public VelocityRender(VelocityEngine velocityEngine_) { @Override public Object render(String view) { - HttpServletRequest servletRequest = BladeWebContext.servletRequest(); - HttpServletResponse servletResponse = BladeWebContext.servletResponse(); - + Response response = BladeWebContext.response(); try { - PrintWriter writer = null; - VelocityContext context = new VelocityContext(); - - Enumeration attrs = servletRequest.getAttributeNames(); - while (attrs.hasMoreElements()) { - String attrName = attrs.nextElement(); - context.put(attrName, servletRequest.getAttribute(attrName)); - } + Request request = BladeWebContext.request(); + Session session = BladeWebContext.session(); view = disposeView(view); + VelocityContext context = new VelocityContext(); + Template template = velocityEngine.getTemplate(view); - writer = servletResponse.getWriter(); + Set attrs = request.attributes(); + if(null != attrs && attrs.size() > 0){ + for(String attr : attrs){ + context.put(attr, request.attribute(attr)); + } + } + + Set session_attrs = session.attributes(); + if(null != session_attrs && session_attrs.size() > 0){ + for(String attr : session_attrs){ + context.put(attr, session.attribute(attr)); + } + } + + PrintWriter writer = response.writer(); template.merge(context, writer); @@ -112,13 +123,13 @@ public Object render(String view) { writer.close(); } catch (ResourceNotFoundException e) { - render404(servletResponse, view); + render404(response, view); } catch (ParseErrorException e) { - e.printStackTrace(); + LOGGER.error(e); } catch (MethodInvocationException e) { - e.printStackTrace(); + LOGGER.error(e); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } return null; } @@ -129,29 +140,36 @@ public Object render(String view) { */ @Override public Object render(ModelAndView modelAndView) { - HttpServletRequest servletRequest = BladeWebContext.servletRequest(); - HttpServletResponse servletResponse = BladeWebContext.servletResponse(); - + Response response = BladeWebContext.response(); try { + Request request = BladeWebContext.request(); + Session session = BladeWebContext.session(); if(null == modelAndView){ throw new BladeException("modelAndView is null"); } - PrintWriter writer = null; + String view = disposeView(modelAndView.getView()); + VelocityContext context = new VelocityContext(modelAndView.getModel()); - Enumeration attrs = servletRequest.getAttributeNames(); - while (attrs.hasMoreElements()) { - String attrName = attrs.nextElement(); - context.put(attrName, servletRequest.getAttribute(attrName)); + Set attrs = request.attributes(); + if(null != attrs && attrs.size() > 0){ + for(String attr : attrs){ + context.put(attr, request.attribute(attr)); + } } - String view = disposeView(modelAndView.getView()); + Set session_attrs = session.attributes(); + if(null != session_attrs && session_attrs.size() > 0){ + for(String attr : session_attrs){ + context.put(attr, session.attribute(attr)); + } + } Template template = velocityEngine.getTemplate(view); - writer = servletResponse.getWriter(); + PrintWriter writer = response.writer(); template.merge(context, writer); @@ -159,13 +177,13 @@ public Object render(ModelAndView modelAndView) { writer.close(); } catch (ResourceNotFoundException e) { - render404(servletResponse, modelAndView.getView()); + render404(response, modelAndView.getView()); } catch (ParseErrorException e) { - e.printStackTrace(); + LOGGER.error(e); } catch (MethodInvocationException e) { - e.printStackTrace(); + LOGGER.error(e); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } return null; } From fa9936ec9881c31b71fed0d9e6c951ae04899dd6 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 22 Jul 2015 14:56:01 +0800 Subject: [PATCH 036/545] optimizing --- .../src/main/java/blade/BladeWebContext.java | 31 ++++++++++++++----- .../src/main/java/blade/RequestHandler.java | 4 +-- .../src/main/java/blade/servlet/Response.java | 1 - .../java/blade/wrapper/ResponseWrapper.java | 3 -- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/blade-core/src/main/java/blade/BladeWebContext.java b/blade-core/src/main/java/blade/BladeWebContext.java index 7bc2862c1..0d7033787 100644 --- a/blade-core/src/main/java/blade/BladeWebContext.java +++ b/blade-core/src/main/java/blade/BladeWebContext.java @@ -22,6 +22,8 @@ import blade.servlet.Request; import blade.servlet.Response; import blade.servlet.Session; +import blade.wrapper.RequestWrapper; +import blade.wrapper.ResponseWrapper; /** * 全局的WeContext @@ -34,12 +36,12 @@ public final class BladeWebContext { /** * 当前线程的Request对象 */ - private static ThreadLocal currentRequest = new ThreadLocal(); + private static ThreadLocal currentRequest = new ThreadLocal(); /** * 当前线程的Response对象 */ - private static ThreadLocal currentResponse = new ThreadLocal(); + private static ThreadLocal currentResponse = new ThreadLocal(); /** * ServletContext对象,在应用初始化时创建 @@ -52,6 +54,13 @@ private BladeWebContext(){} * @return 返回当前线程的Request对象 */ public static Request request() { + return requestWrapper().getDelegate(); + } + + /** + * @return 返回当前线程的RequestWrapper对象 + */ + public static RequestWrapper requestWrapper() { return currentRequest.get(); } @@ -66,9 +75,17 @@ public static HttpServletRequest servletRequest() { * @return 返回当前线程的Response对象 */ public static Response response() { + return responseWrapper().getDelegate(); + } + + /** + * @return 返回当前线程的RequestWrapper对象 + */ + public static ResponseWrapper responseWrapper() { return currentResponse.get(); } + /** * @return 返回当前线程的HttpServletResponse对象 */ @@ -102,13 +119,13 @@ public static ServletContext servletContext() { /** * 设置context对象到ActionContext中 * - * @param request HttpServletRequest对象 - * @param response HttpServletResponse对象 + * @param requestWrapper RequestWrapper对象 + * @param responseWrapper ResponseWrapper对象 */ - public static void put(Request request, Response response) { + public static void put(RequestWrapper requestWrapper, ResponseWrapper responseWrapper) { remove(); - currentRequest.set(request); - currentResponse.set(response); + currentRequest.set(requestWrapper); + currentResponse.set(responseWrapper); } /** diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 36e99c370..d866ddde4 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -288,10 +288,10 @@ private Object[] getArgs(Request request, Response response, Class[] params){ * @param response Response对象,作为参数注入 * @return 返回方法执行后的返回值 */ - private Object executeMethod(Object object, Method method, Request request, Response response){ + private Object executeMethod(Object object, Method method, RequestWrapper requestWrapper, ResponseWrapper responseWrapper){ int len = method.getParameterTypes().length; if(len > 0){ - Object[] args = getArgs(request, response, method.getParameterTypes()); + Object[] args = getArgs(requestWrapper.getDelegate(), responseWrapper.getDelegate(), method.getParameterTypes()); return ReflectKit.invokeMehod(object, method, args); } else { return ReflectKit.invokeMehod(object, method); diff --git a/blade-core/src/main/java/blade/servlet/Response.java b/blade-core/src/main/java/blade/servlet/Response.java index 1f583c140..bfac6849c 100644 --- a/blade-core/src/main/java/blade/servlet/Response.java +++ b/blade-core/src/main/java/blade/servlet/Response.java @@ -54,7 +54,6 @@ public Response(HttpServletResponse response) { this.response = response; } - /** * 设置响应状态码 * diff --git a/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java b/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java index 7b3282632..48ad7835d 100644 --- a/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java +++ b/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java @@ -31,9 +31,6 @@ public class ResponseWrapper extends Response { private boolean redirected = false; - public ResponseWrapper() { - // TODO Auto-generated constructor stub - } public ResponseWrapper(Response delegate) { this.delegate = delegate; From 5ca15e8a63bcce78e813196336ba80e2c20c3716 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 22 Jul 2015 15:34:41 +0800 Subject: [PATCH 037/545] optimized code --- blade-core/src/main/java/blade/BladeBase.java | 8 +-- .../src/main/java/blade/BladeConfig.java | 9 +-- .../main/java/blade/BladeConfigurator.java | 6 +- .../src/main/java/blade/ioc/Container.java | 8 +-- .../main/java/blade/ioc/DefaultContainer.java | 56 ++++++++++--------- .../main/java/blade/render/ModelAndView.java | 5 +- .../java/blade/route/DefaultRouteMatcher.java | 20 +++---- .../java/blade/route/RouteMatcherBuilder.java | 7 ++- .../java/blade/servlet/QueryParamsMap.java | 7 ++- .../src/main/java/blade/servlet/Request.java | 9 ++- .../java/blade/servlet/ServletFileUpload.java | 7 +-- .../src/main/java/blade/kit/DateKit.java | 2 +- .../src/main/java/blade/kit/MimeParse.java | 7 ++- .../src/main/java/blade/kit/PathKit.java | 16 +++--- .../src/main/java/blade/kit/http/HttpKit.java | 6 +- 15 files changed, 91 insertions(+), 82 deletions(-) diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index dc8efccb9..fb14b07a3 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -349,7 +349,7 @@ public static BladeApplication application(){ */ public static synchronized void port(int port){ if(port > 0 && port < 65535){ - PORT = port; + BladeBase.PORT = port; } } @@ -361,7 +361,7 @@ public static synchronized void port(int port){ * @param context context,应用上下文,默认为"/" */ public static void run(Integer port, String host, String context) { - PORT = port; + BladeBase.PORT = port; BladeServer.run(port, host, context); } @@ -369,7 +369,7 @@ public static void run(Integer port, String host, String context) { * 运行jetty服务 */ public static void run() { - run(PORT, null, null); + run(BladeBase.PORT, null, null); } /** @@ -378,7 +378,7 @@ public static void run() { * @param host host,默认为本机;127.0.0.1/localhost */ public static void run(String host) { - run(PORT, host, null); + run(BladeBase.PORT, host, null); } /** diff --git a/blade-core/src/main/java/blade/BladeConfig.java b/blade-core/src/main/java/blade/BladeConfig.java index d8c09ac44..e65a46eb9 100644 --- a/blade-core/src/main/java/blade/BladeConfig.java +++ b/blade-core/src/main/java/blade/BladeConfig.java @@ -15,10 +15,11 @@ */ package blade; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import blade.kit.CollectionKit; + /** * Blade配置类 * @@ -28,9 +29,9 @@ */ public class BladeConfig { - private List routePackages = new ArrayList(); - private List iocPackages = new ArrayList(); - private List staticFolders = new ArrayList(); + private List routePackages = CollectionKit.newArrayList(); + private List iocPackages = CollectionKit.newArrayList(); + private List staticFolders = CollectionKit.newArrayList(); private String basePackage; private String interceptorPackage; private String encoding = "utf-8"; diff --git a/blade-core/src/main/java/blade/BladeConfigurator.java b/blade-core/src/main/java/blade/BladeConfigurator.java index 50ed67f09..354f40956 100644 --- a/blade-core/src/main/java/blade/BladeConfigurator.java +++ b/blade-core/src/main/java/blade/BladeConfigurator.java @@ -69,12 +69,12 @@ public void run() { String debug = configMap.get(BLADE_DEBUG); if (StringKit.isNotBlank(route)) { - String[] blade_routes = route.split(","); + String[] blade_routes = StringKit.split(route, ","); bladeConfig.setRoutePackages(blade_routes); } if (StringKit.isNotBlank(filter_folder)) { - String[] blade_filter_folders = filter_folder.split(","); + String[] blade_filter_folders = StringKit.split(filter_folder, ","); bladeConfig.setStaticFolders(blade_filter_folders); } @@ -83,7 +83,7 @@ public void run() { } if (StringKit.isNotBlank(ioc)) { - String[] blade_iocs = ioc.split(","); + String[] blade_iocs = StringKit.split(ioc, ","); bladeConfig.setIocPackages(blade_iocs); } diff --git a/blade-core/src/main/java/blade/ioc/Container.java b/blade-core/src/main/java/blade/ioc/Container.java index 3517f98a4..2246cbc3c 100644 --- a/blade-core/src/main/java/blade/ioc/Container.java +++ b/blade-core/src/main/java/blade/ioc/Container.java @@ -36,7 +36,7 @@ public interface Container { * @param scope 对象作用域,单例或者每次都创建 * @return 一个bean对象 */ - Object getBean(String name, Scope scope); + T getBean(String name, Scope scope); /** * 根据class和对象作用于获取一个bean对象 @@ -45,7 +45,7 @@ public interface Container { * @param scope 对象作用域,单例或者每次都创建 * @return 一个bean对象 */ - Object getBean(Class type, Scope scope); + T getBean(Class type, Scope scope); /** * @return 返回所有bean的名称集合 @@ -55,7 +55,7 @@ public interface Container { /** * @return 返回所有bean的集合 */ - Collection getBeans(); + Collection getBeans(); /** * 根据注解获取ioc容器中匹配的bean class集合 @@ -71,7 +71,7 @@ public interface Container { * @param annotation annotation class类型 * @return 返回符合annotation class类型的所有bean */ - List getBeansByAnnotation(Class annotation); + List getBeansByAnnotation(Class annotation); /** * 判断是否存在一个bean,根据class类型 diff --git a/blade-core/src/main/java/blade/ioc/DefaultContainer.java b/blade-core/src/main/java/blade/ioc/DefaultContainer.java index edc123f4e..bbb57e3d2 100644 --- a/blade-core/src/main/java/blade/ioc/DefaultContainer.java +++ b/blade-core/src/main/java/blade/ioc/DefaultContainer.java @@ -39,6 +39,7 @@ * @author biezhi * @since 1.0 */ +@SuppressWarnings("unchecked") public class DefaultContainer implements Container { private static final Logger LOGGER = Logger.getLogger(DefaultContainer.class); @@ -46,12 +47,12 @@ public class DefaultContainer implements Container { /** * 保存所有bean对象 */ - private static final Map beansMap = CollectionKit.newConcurrentHashMap(); + private static final Map BEAN_CONTAINER = CollectionKit.newConcurrentHashMap(); /** * 保存所有注解的class */ - private static final Map, List> annotationMap = CollectionKit.newConcurrentHashMap(); + private static final Map, List> ANNOTATION_CONTAINER = CollectionKit.newConcurrentHashMap(); private DefaultContainer() { } @@ -65,36 +66,36 @@ private static class DefaultContainerHoder { } public Map getBeanMap() { - return beansMap; + return BEAN_CONTAINER; } - @Override - public Object getBean(String name, Scope scope) { - Object obj = beansMap.get(name); + @Override + public T getBean(String name, Scope scope) { + Object obj = BEAN_CONTAINER.get(name); if(null != scope && scope == Scope.PROTOTYPE){ try { - return CloneKit.deepClone(obj); + return (T) CloneKit.deepClone(obj); } catch (Exception e) { LOGGER.error("克隆对象失败," + e.getMessage()); } } - return obj; + return (T) obj; } @Override - public Object getBean(Class type, Scope scope) { - Iterator it = beansMap.values().iterator(); + public T getBean(Class type, Scope scope) { + Iterator it = BEAN_CONTAINER.values().iterator(); while (it.hasNext()) { Object obj = it.next(); if (type.isAssignableFrom(obj.getClass())) { if(null != scope && scope == Scope.PROTOTYPE){ try { - return CloneKit.deepClone(obj); + return (T) CloneKit.deepClone(obj); } catch (Exception e) { LOGGER.error("克隆对象失败," + e.getMessage()); } } else { - return obj; + return (T) obj; } } } @@ -103,12 +104,12 @@ public Object getBean(Class type, Scope scope) { @Override public Set getBeanNames() { - return beansMap.keySet(); + return BEAN_CONTAINER.keySet(); } @Override public Collection getBeans() { - return beansMap.values(); + return BEAN_CONTAINER.values(); } @Override @@ -129,13 +130,13 @@ public boolean hasBean(String name) { @Override public boolean removeBean(String name) { - Object object = beansMap.remove(name); + Object object = BEAN_CONTAINER.remove(name); return (null != object); } @Override public boolean removeBean(Class clazz) { - Object object = beansMap.remove(clazz.getName()); + Object object = BEAN_CONTAINER.remove(clazz.getName()); return (null != object); } @@ -178,8 +179,8 @@ public Object registBean(Class clazz) { * @param object 要进入IOC容器的bean对象 */ private void put(String name, Object object){ - if(null == beansMap.get(name)){ - beansMap.put(name, object); + if(null == BEAN_CONTAINER.get(name)){ + BEAN_CONTAINER.put(name, object); } } @@ -191,14 +192,15 @@ private void put(String name, Object object){ */ private void putAnnotationMap(Class clazz, Object object){ Annotation[] annotations = clazz.getAnnotations(); + List listObject = null; for(Annotation annotation : annotations){ if(null != annotation){ - List listObject = annotationMap.get(annotation.annotationType()); + listObject = ANNOTATION_CONTAINER.get(annotation.annotationType()); if(CollectionKit.isEmpty(listObject)){ listObject = CollectionKit.newArrayList(); } listObject.add(object); - put(annotation.annotationType(), listObject); + this.put(annotation.annotationType(), listObject); } } } @@ -210,8 +212,8 @@ private void putAnnotationMap(Class clazz, Object object){ * @param listObject 要注入的对象列表 */ private void put(Class clazz, List listObject){ - if(null == annotationMap.get(clazz)){ - annotationMap.put(clazz, listObject); + if(null == ANNOTATION_CONTAINER.get(clazz)){ + ANNOTATION_CONTAINER.put(clazz, listObject); } } @@ -220,7 +222,7 @@ private void put(Class clazz, List listObject){ */ @Override public void initWired() throws RuntimeException { - Iterator it = beansMap.values().iterator(); + Iterator it = BEAN_CONTAINER.values().iterator(); try { while (it.hasNext()) { @@ -302,8 +304,8 @@ public List> getClassesByAnnotation(Class annotat } @Override - public List getBeansByAnnotation(Class annotation) { - return annotationMap.get(annotation); + public List getBeansByAnnotation(Class annotation) { + return (List) ANNOTATION_CONTAINER.get(annotation); } @Override @@ -324,8 +326,8 @@ public Object registBean(Object object) { @Override public boolean removeAll() { - beansMap.clear(); - annotationMap.clear(); + BEAN_CONTAINER.clear(); + ANNOTATION_CONTAINER.clear(); return true; } diff --git a/blade-core/src/main/java/blade/render/ModelAndView.java b/blade-core/src/main/java/blade/render/ModelAndView.java index aa3a6d9fd..5aa25ab58 100644 --- a/blade-core/src/main/java/blade/render/ModelAndView.java +++ b/blade-core/src/main/java/blade/render/ModelAndView.java @@ -15,9 +15,10 @@ */ package blade.render; -import java.util.HashMap; import java.util.Map; +import blade.kit.CollectionKit; + /** * ModelAndView使用模型和视图来渲染 * @@ -43,7 +44,7 @@ public class ModelAndView { */ public ModelAndView(String view) { super(); - this.model = new HashMap(); + this.model = CollectionKit.newHashMap(); this.view = view; } diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index cb2a988b7..9998b965c 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -16,13 +16,12 @@ package blade.route; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; import blade.Blade; +import blade.kit.CollectionKit; import blade.kit.MimeParse; import blade.kit.StringKit; import blade.kit.log.Logger; @@ -43,8 +42,8 @@ public class DefaultRouteMatcher { private List interceptors; public DefaultRouteMatcher() { - routes = new ArrayList(); - interceptors = new ArrayList(); + routes = CollectionKit.newArrayList(); + interceptors = CollectionKit.newArrayList(); } /** @@ -57,7 +56,7 @@ public DefaultRouteMatcher() { */ public RouteMatcher findRouteMatcher(HttpMethod httpMethod, String uri, String acceptType) { - uri = uri.length() > 1 && uri.endsWith("/") ? uri.substring(0, uri.length() - 1) : uri; + uri = (uri.length() > 1 && uri.endsWith("/")) ? uri.substring(0, uri.length() - 1) : uri; List routeEntries = this.findRouteMatcher(httpMethod, uri); @@ -78,7 +77,7 @@ public List findInterceptor(HttpMethod httpMethod, String uri, Str if(uri.length() > 1){ uri = uri.endsWith("/") ? uri.substring(0, uri.length() - 1) : uri; } - List matchSet = new ArrayList(); + List matchSet = CollectionKit.newArrayList(); List routeEntries = this.findInterceptor(httpMethod, uri); for (RouteMatcher routeEntry : routeEntries) { @@ -129,7 +128,6 @@ public boolean removeRoute(String path) { if (StringKit.isEmpty(path)) { throw new IllegalArgumentException("path cannot be null or blank"); } - return removeRoute((HttpMethod)null, path); } @@ -186,7 +184,7 @@ public void addInterceptor(Class target, Method execMethod, String url, HttpM } private Map getAcceptedMimeTypes(List routes) { - Map acceptedTypes = new HashMap(); + Map acceptedTypes = CollectionKit.newHashMap(); for (RouteMatcher routeEntry : routes) { if (!acceptedTypes.containsKey(routeEntry.acceptType)) { @@ -211,7 +209,7 @@ private boolean routeWithGivenAcceptType(String bestMatch) { private List findRouteMatcher(HttpMethod httpMethod, String path) { path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - List matchSet = new ArrayList(); + List matchSet = CollectionKit.newArrayList(); for (RouteMatcher entry : routes) { if (entry.matches(httpMethod, path)) { matchSet.add(entry); @@ -228,7 +226,7 @@ private List findRouteMatcher(HttpMethod httpMethod, String path) * @return 返回匹配的所有路由集合 */ private List findInterceptor(HttpMethod httpMethod, String path) { - List matchSet = new ArrayList(); + List matchSet = CollectionKit.newArrayList(); for (RouteMatcher entry : interceptors) { if (entry.matches(httpMethod, path)) { matchSet.add(entry); @@ -263,7 +261,7 @@ private RouteMatcher findTargetWithGivenAcceptType(List routeMatch } private boolean removeRoute(HttpMethod httpMethod, String path) { - List forRemoval = new ArrayList(); + List forRemoval = CollectionKit.newArrayList(); for (RouteMatcher routeEntry : routes) { HttpMethod httpMethodToMatch = httpMethod; diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index d79bcfa90..51499a9cd 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -121,6 +121,8 @@ public static synchronized DefaultRouteMatcher building() { * @param interceptorPackages 要添加的拦截器包 */ private static void buildInterceptor(String... interceptorPackages){ + // 扫描所有的Interceptor + Set> classes = null; // 拦截器 for(String packageName : interceptorPackages){ @@ -132,7 +134,7 @@ private static void buildInterceptor(String... interceptorPackages){ } // 扫描所有的Interceptor - Set> classes = classReader.getClassByAnnotation(packageName, Interceptor.class, recursive); + classes = classReader.getClassByAnnotation(packageName, Interceptor.class, recursive); if(null != classes && classes.size() > 0){ for(Class interceptorClazz : classes){ @@ -148,6 +150,7 @@ private static void buildInterceptor(String... interceptorPackages){ * @param routePackages 要添加的路由包 */ private static void buildRoute(String... routePackages){ + Set> classes = null; // 路由 for(String packageName : routePackages){ @@ -159,7 +162,7 @@ private static void buildRoute(String... routePackages){ } // 扫描所有的Controoler - Set> classes = classReader.getClassByAnnotation(packageName, Path.class, recursive); + classes = classReader.getClassByAnnotation(packageName, Path.class, recursive); if(null != classes && classes.size() > 0){ for(Class pathClazz : classes){ diff --git a/blade-core/src/main/java/blade/servlet/QueryParamsMap.java b/blade-core/src/main/java/blade/servlet/QueryParamsMap.java index 5bdcb7d89..ca8b1f561 100644 --- a/blade-core/src/main/java/blade/servlet/QueryParamsMap.java +++ b/blade-core/src/main/java/blade/servlet/QueryParamsMap.java @@ -15,7 +15,6 @@ */ package blade.servlet; -import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; @@ -23,6 +22,8 @@ import javax.servlet.http.HttpServletRequest; +import blade.kit.CollectionKit; + /** * 查询参数封装 *

@@ -42,7 +43,7 @@ public class QueryParamsMap { /** * 查询参数字典,存放url上传输的参数 */ - private Map queryMap = new HashMap(); + private Map queryMap = CollectionKit.newHashMap(); /** * 所有的值数组 @@ -257,7 +258,7 @@ String[] getValues() { * @return 将queryMap转换为map */ public Map toMap() { - Map map = new HashMap(); + Map map = CollectionKit.newHashMap(); for (Entry key : this.queryMap.entrySet()) { map.put(key.getKey(), key.getValue().values); diff --git a/blade-core/src/main/java/blade/servlet/Request.java b/blade-core/src/main/java/blade/servlet/Request.java index cb0377497..f9da3d554 100644 --- a/blade-core/src/main/java/blade/servlet/Request.java +++ b/blade-core/src/main/java/blade/servlet/Request.java @@ -15,10 +15,8 @@ */ package blade.servlet; -import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -29,6 +27,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import blade.kit.CollectionKit; import blade.kit.IOKit; import blade.kit.PathKit; import blade.kit.StringKit; @@ -472,7 +471,7 @@ public Session session(boolean create) { * @return 返回cookies */ public Map cookies() { - Map result = new HashMap(); + Map result = CollectionKit.newHashMap(); Cookie[] cookies = servletRequest.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { @@ -516,7 +515,7 @@ public String protocol() { private static Map getPathParams(List request, List matched) { - Map params = new HashMap(); + Map params = CollectionKit.newHashMap(); for (int i = 0; (i < request.size()) && (i < matched.size()); i++) { String matchedPart = matched.get(i); @@ -538,7 +537,7 @@ private static List getSplat(List request, List matched) boolean sameLength = (nbrOfRequestParts == nbrOfMatchedParts); - List splat = new ArrayList(); + List splat = CollectionKit.newArrayList(); for (int i = 0; (i < nbrOfRequestParts) && (i < nbrOfMatchedParts); i++) { String matchedPart = matched.get(i); diff --git a/blade-core/src/main/java/blade/servlet/ServletFileUpload.java b/blade-core/src/main/java/blade/servlet/ServletFileUpload.java index 5abaa2b09..fa34c3502 100644 --- a/blade-core/src/main/java/blade/servlet/ServletFileUpload.java +++ b/blade-core/src/main/java/blade/servlet/ServletFileUpload.java @@ -16,8 +16,6 @@ package blade.servlet; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -27,6 +25,7 @@ import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; +import blade.kit.CollectionKit; import blade.route.HttpMethod; /** @@ -245,12 +244,12 @@ private void putFileItem(FileItem fileItem) { return; if (allFileItems == null) { - allFileItems = new HashMap>(); + allFileItems = CollectionKit.newHashMap(); } List list = allFileItems.get(fileItem.getName()); if (list == null) { - list = new ArrayList(); + list = CollectionKit.newArrayList(); allFileItems.put(fileItem.getName(), list); } diff --git a/blade-kit/src/main/java/blade/kit/DateKit.java b/blade-kit/src/main/java/blade/kit/DateKit.java index c8cfba44e..3dfb9f082 100644 --- a/blade-kit/src/main/java/blade/kit/DateKit.java +++ b/blade-kit/src/main/java/blade/kit/DateKit.java @@ -697,7 +697,7 @@ public static Date getWeekAgo(Date date) { public static Date getDatebyTime(Date date, int n) { String str = DateKit.dateFormat(date, "yyyy-MM-dd"); - String[] strs = str.split("-"); + String[] strs = StringKit.split(str, "-"); int month = Integer.parseInt(strs[1]); int monthnow = (month + n) % 12; int year = Integer.parseInt(strs[0]) + (month + n) / 12; diff --git a/blade-kit/src/main/java/blade/kit/MimeParse.java b/blade-kit/src/main/java/blade/kit/MimeParse.java index 82c1b70c6..d942e1c36 100644 --- a/blade-kit/src/main/java/blade/kit/MimeParse.java +++ b/blade-kit/src/main/java/blade/kit/MimeParse.java @@ -63,13 +63,13 @@ public String toString() { * ('application', 'xhtml', {'q', '0.5'}) */ private static ParseResults parseMimeType(String mimeType) { - String[] parts = mimeType.split(";"); + String[] parts = StringKit.split(mimeType, ";"); ParseResults results = new ParseResults(); results.params = new HashMap(); for (int i = 1; i < parts.length; ++i) { String p = parts[i]; - String[] subParts = p.split("="); + String[] subParts = StringKit.split(p, "="); if (subParts.length == 2) { results.params.put(subParts[0].trim(), subParts[1].trim()); } @@ -191,7 +191,8 @@ private static FitnessAndQuality fitnessAndQualityParsed(String mimeType, Collec public static String bestMatch(Collection supported, String header) { List parseResults = new LinkedList(); List weightedMatches = new LinkedList(); - for (String r : header.split(",")) { + String[] headers = StringKit.split(header, ","); + for (String r : headers) { parseResults.add(parseMediaRange(r)); } diff --git a/blade-kit/src/main/java/blade/kit/PathKit.java b/blade-kit/src/main/java/blade/kit/PathKit.java index 168c6b7f3..b0513dc00 100644 --- a/blade-kit/src/main/java/blade/kit/PathKit.java +++ b/blade-kit/src/main/java/blade/kit/PathKit.java @@ -17,7 +17,6 @@ import java.io.UnsupportedEncodingException; import java.net.URLDecoder; -import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; @@ -59,14 +58,17 @@ public static String getRelativePath(HttpServletRequest request) { } public static List convertRouteToList(String route) { - String[] pathArray = route.split("/"); - List path = new ArrayList(); - for (String p : pathArray) { - if (p.length() > 0) { - path.add(p); + String[] pathArray = StringKit.split(route, "/"); + if(null != pathArray && pathArray.length > 0){ + List path = CollectionKit.newArrayList(); + for (String p : pathArray) { + if (p.length() > 0) { + path.add(p); + } } + return path; } - return path; + return CollectionKit.newArrayList(0); } public static boolean isParam(String routePart) { diff --git a/blade-kit/src/main/java/blade/kit/http/HttpKit.java b/blade-kit/src/main/java/blade/kit/http/HttpKit.java index d91d83750..c82839bdc 100644 --- a/blade-kit/src/main/java/blade/kit/http/HttpKit.java +++ b/blade-kit/src/main/java/blade/kit/http/HttpKit.java @@ -6,6 +6,8 @@ import java.util.Map; import java.util.Set; +import blade.kit.StringKit; + /** * http util * @author biezhi @@ -21,11 +23,11 @@ public class HttpKit { */ public static Map parseQuery(String query, boolean decode) { Map queryMap = new HashMap(); - String[] kvArr = query.split("&"); + String[] kvArr = StringKit.split(query, "&"); if(null != kvArr && kvArr.length > 0){ for(String k : kvArr){ if(k.indexOf("=") != -1){ - String[] kv = k.split("="); + String[] kv = StringKit.split(k, "="); queryMap.put(kv[0], kv[1]); } } From a00e5babd6d9f28af7641099e7fad13ff3e53ed4 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 23 Jul 2015 10:54:20 +0800 Subject: [PATCH 038/545] fixes transaction bug --- .../java/blade/plugin/sql2o/Condition.java | 10 +++ .../main/java/blade/plugin/sql2o/Model.java | 65 +++++++++++-------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java index e26d0dd77..5078f5de1 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java @@ -167,6 +167,7 @@ public void clearMap() { public void select() { this.sql = "select * from " + this.tableName; + clearMap(); this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.SELECT; this.orderby = null; @@ -178,6 +179,7 @@ public void select() { */ public void select(String sql) { this.sql = sql; + clearMap(); this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.SELECT; this.orderby = null; @@ -188,6 +190,7 @@ public void select(String sql) { */ public void count(){ this.sql = "select count(1) from " + this.tableName; + clearMap(); this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.COUNT; this.orderby = null; @@ -200,6 +203,7 @@ public void count(){ */ public void count(String sql){ this.sql = sql; + clearMap(); this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.COUNT; this.orderby = null; @@ -207,6 +211,7 @@ public void count(String sql){ public void update(){ this.sql = "update " + this.tableName; + clearMap(); this.params = CollectionKit.newLinkedHashMap(); this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.UPDATE; @@ -218,6 +223,7 @@ public void update(){ */ public void update(String sql){ this.sql = sql; + clearMap(); this.params = CollectionKit.newLinkedHashMap(); this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.UPDATE; @@ -225,6 +231,7 @@ public void update(String sql){ public void insert(){ this.sql = "insert into " + this.tableName; + clearMap(); this.params = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.INSERT; } @@ -235,12 +242,14 @@ public void insert(){ */ public void insert(String sql){ this.sql = sql; + clearMap(); this.params = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.INSERT; } public void delete(){ this.sql = "delete from " + this.tableName; + clearMap(); this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.DELETE; } @@ -251,6 +260,7 @@ public void delete(){ */ public void delete(String sql){ this.sql = sql; + clearMap(); this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.DELETE; } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index cbd7c35a9..2dd9121a4 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -840,8 +840,10 @@ public T executeAndCommit(Class returnType) { LOGGER.debug("更新缓存:" + model.getName() + " -> count,list"); - sql2oCache.hdel(CACHE_KEY_COUNT); - sql2oCache.hdel(CACHE_KEY_LIST); + if(isCache()){ + sql2oCache.hdel(CACHE_KEY_COUNT); + sql2oCache.hdel(CACHE_KEY_LIST); + } } @@ -851,8 +853,11 @@ public T executeAndCommit(Class returnType) { LOGGER.debug("更新缓存:" + model.getName() + " -> detail,list"); - sql2oCache.hdel(CACHE_KEY_DETAIL); - sql2oCache.hdel(CACHE_KEY_LIST); + if(isCache()){ + sql2oCache.hdel(CACHE_KEY_DETAIL); + sql2oCache.hdel(CACHE_KEY_LIST); + } + } // 删除 @@ -861,18 +866,14 @@ public T executeAndCommit(Class returnType) { LOGGER.debug("更新缓存:" + model.getName() + " -> count,list,detail"); - sql2oCache.hdel(CACHE_KEY_COUNT); - sql2oCache.hdel(CACHE_KEY_LIST); - sql2oCache.hdel(CACHE_KEY_DETAIL); + if(isCache()){ + sql2oCache.hdel(CACHE_KEY_COUNT); + sql2oCache.hdel(CACHE_KEY_LIST); + sql2oCache.hdel(CACHE_KEY_DETAIL); + } } - } catch (Exception e) { - LOGGER.error(e); - } - - condition.clearMap(); - - try { + condition.clearMap(); T key = null; if(null != returnType){ key = query.executeUpdate().getKey(returnType); @@ -883,9 +884,7 @@ public T executeAndCommit(Class returnType) { } catch (Exception e) { LOGGER.error(e); } - return null; - } /** @@ -894,36 +893,45 @@ public T executeAndCommit(Class returnType) { * @param connection * @return */ - public Query execute(Connection connection){ - + public Connection execute(Connection connection){ Query query = null; - try { if (null == connection) { connection = sql2o.beginTransaction(); } - // 插入 if (condition.dmlType.equals(DmlType.INSERT)) { query = insertCommit(connection); + if(isCache()){ + sql2oCache.hdel(CACHE_KEY_COUNT); + sql2oCache.hdel(CACHE_KEY_LIST); + } } - // 更新 if (condition.dmlType.equals(DmlType.UPDATE)) { query = updateCommit(connection); + if(isCache()){ + sql2oCache.hdel(CACHE_KEY_DETAIL); + sql2oCache.hdel(CACHE_KEY_LIST); + } } - // 删除 if (condition.dmlType.equals(DmlType.DELETE)) { query = deleteCommit(connection); + if(isCache()){ + sql2oCache.hdel(CACHE_KEY_COUNT); + sql2oCache.hdel(CACHE_KEY_LIST); + sql2oCache.hdel(CACHE_KEY_DETAIL); + } + } + condition.clearMap(); + if(null != query){ + return query.getConnection(); } } catch (Exception e) { LOGGER.error(e); } - - condition.clearMap(); - - return query; + return null; } /** @@ -939,6 +947,7 @@ private Query deleteCommit(Connection conn) { Query query = conn.createQuery(deleteSql); query = parseParams(query); + query.executeUpdate(); LOGGER.debug("execute sql:" + query.toString()); LOGGER.debug("execute parameter:" + condition.equalsParams.values()); @@ -979,7 +988,7 @@ private Query insertCommit(Connection conn){ Query query = conn.createQuery(insertSql); query = parseParams(query); - + query.executeUpdate(); LOGGER.debug("execute sql:" + query.toString()); LOGGER.debug("execute parameter:" + condition.params.values()); @@ -1024,7 +1033,7 @@ private Query updateCommit(Connection conn){ Query query = conn.createQuery(updateSql); query = parseParams(query); - + query.executeUpdate(); LOGGER.debug("execute sql:" + query.toString()); LOGGER.debug("execute parameter:" + condition.params.values() + condition.equalsParams.values()); From ce59c185ef1c4f5d2567513cd27edea633c15d90 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 23 Jul 2015 11:11:00 +0800 Subject: [PATCH 039/545] fix update, delete, return record number --- .../main/java/blade/plugin/sql2o/Model.java | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 2dd9121a4..d00841f11 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -831,55 +831,52 @@ public Integer executeAndCommit() { */ @SuppressWarnings("unchecked") public T executeAndCommit(Class returnType) { - + T key = null; Query query = null; try { // 插入 if(condition.dmlType.equals(DmlType.INSERT)){ query = insertCommit(null); - LOGGER.debug("更新缓存:" + model.getName() + " -> count,list"); - if(isCache()){ + LOGGER.debug("更新缓存:" + model.getName() + " -> count,list"); sql2oCache.hdel(CACHE_KEY_COUNT); sql2oCache.hdel(CACHE_KEY_LIST); } + if(null != returnType){ + key = query.executeUpdate().getKey(returnType); + } else { + key = (T) query.executeUpdate().getKey(); + } } // 更新 if(condition.dmlType.equals(DmlType.UPDATE)){ query = updateCommit(null); - LOGGER.debug("更新缓存:" + model.getName() + " -> detail,list"); - if(isCache()){ + LOGGER.debug("更新缓存:" + model.getName() + " -> detail,list"); sql2oCache.hdel(CACHE_KEY_DETAIL); sql2oCache.hdel(CACHE_KEY_LIST); } - + key = (T) Integer.valueOf(query.executeUpdate().getResult()); } // 删除 if(condition.dmlType.equals(DmlType.DELETE)){ query = deleteCommit(null); - LOGGER.debug("更新缓存:" + model.getName() + " -> count,list,detail"); - if(isCache()){ + LOGGER.debug("更新缓存:" + model.getName() + " -> count,list,detail"); sql2oCache.hdel(CACHE_KEY_COUNT); sql2oCache.hdel(CACHE_KEY_LIST); sql2oCache.hdel(CACHE_KEY_DETAIL); } - + key = (T) Integer.valueOf(query.executeUpdate().getResult()); } + condition.clearMap(); - T key = null; - if(null != returnType){ - key = query.executeUpdate().getKey(returnType); - } else { - key = (T) query.executeUpdate().getKey(); - } return key; } catch (Exception e) { LOGGER.error(e); From 33afe6608ada4b2ab695fd2d81b40b1803dc7844 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 23 Jul 2015 14:20:43 +0800 Subject: [PATCH 040/545] add priority matching rules, optimize the code --- .../src/main/java/blade/BladeFilter.java | 47 ++++++++++--------- .../java/blade/route/DefaultRouteMatcher.java | 19 +++++++- .../main/java/blade/route/RouteMatcher.java | 2 +- .../src/main/java/blade/kit/json/JSONKit.java | 24 ++++++++-- 4 files changed, 65 insertions(+), 27 deletions(-) diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java index 690d38e2e..3ab762209 100644 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ b/blade-core/src/main/java/blade/BladeFilter.java @@ -49,27 +49,32 @@ public class BladeFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { // 防止重复初始化 - if(!Blade.IS_INIT){ - - BladeBase.webRoot(filterConfig.getServletContext().getRealPath("/")); - - BladeWebContext.servletContext(filterConfig.getServletContext()); - - final BladeApplication application = getApplication(filterConfig); - application.init(); - Blade.app(application); - - // 构建所有路由 - RequestHandler.routeMatcher = RouteMatcherBuilder.building(); - - // 全局初始化 - IocApplication.init(); - - application.contextInitialized(BladeWebContext.servletContext()); - - LOGGER.info("blade init complete!"); - BladeBase.init(); - } + try { + if(!Blade.IS_INIT){ + + BladeBase.webRoot(filterConfig.getServletContext().getRealPath("/")); + + BladeWebContext.servletContext(filterConfig.getServletContext()); + + final BladeApplication application = getApplication(filterConfig); + application.init(); + Blade.app(application); + + // 构建所有路由 + RequestHandler.routeMatcher = RouteMatcherBuilder.building(); + + // 全局初始化 + IocApplication.init(); + + application.contextInitialized(BladeWebContext.servletContext()); + + LOGGER.info("blade init complete!"); + BladeBase.init(); + } + } catch (Exception e) { + LOGGER.error(e); + System.exit(0); + } } diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index 9998b965c..311b467c6 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -17,6 +17,7 @@ import java.lang.reflect.Method; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.Map; @@ -60,12 +61,28 @@ public RouteMatcher findRouteMatcher(HttpMethod httpMethod, String uri, String a List routeEntries = this.findRouteMatcher(httpMethod, uri); + // 优先匹配原则 + giveMatch(uri, routeEntries); + RouteMatcher entry = findTargetWithGivenAcceptType(routeEntries, acceptType); return entry != null ? new RouteMatcher(entry.target, entry.execMethod, entry.httpMethod, entry.path, uri, acceptType) : null; } - /** + private void giveMatch(final String uri, List routeEntries) { + routeEntries.sort(new Comparator() { + @Override + public int compare(RouteMatcher o1, RouteMatcher o2) { + if(o2.path.equals(uri)){ + return o2.path.indexOf(uri); + } + return -1; + } + }); +// System.out.println(routeEntries.toString()); + } + + /** * 查询一个路由集合 * * @param httpMethod http请求方法,GET/POST diff --git a/blade-core/src/main/java/blade/route/RouteMatcher.java b/blade-core/src/main/java/blade/route/RouteMatcher.java index bd37b2f80..ab7600dd3 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/blade/route/RouteMatcher.java @@ -203,7 +203,7 @@ public boolean equals(Object obj) { @Override public String toString() { - return httpMethod.name() + "------" + path; + return httpMethod.name() + ":" + path; } } diff --git a/blade-kit/src/main/java/blade/kit/json/JSONKit.java b/blade-kit/src/main/java/blade/kit/json/JSONKit.java index 92d945034..6a9ad97cd 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONKit.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONKit.java @@ -1,9 +1,10 @@ package blade.kit.json; -import java.util.ArrayList; import java.util.List; import java.util.Map; +import blade.kit.CollectionKit; + @SuppressWarnings("unchecked") public class JSONKit { @@ -17,13 +18,28 @@ public static Map toMap(String json){ return null; } + public static Map toMap(JSONObject jsonObject){ + try { + return JSONMap.toMap(jsonObject); + } catch (JSONException e) { + e.printStackTrace(); + } + return null; + } + public static List toList(String json){ JSONArray jsonArray = new JSONArray(json); - List list = new ArrayList(); int len = jsonArray.length(); + List list = CollectionKit.newArrayList(len); for(int i=0; i Date: Thu, 23 Jul 2015 15:53:46 +0800 Subject: [PATCH 041/545] add comments and submit to the maven repository --- LAST_VERSION.md | 12 +++--- blade-core/src/main/java/blade/BladeBase.java | 34 +++++++++++---- .../src/main/java/blade/BladeConfig.java | 17 ++++++++ .../main/java/blade/BladeConfigurator.java | 41 +++++++++++-------- 4 files changed, 71 insertions(+), 33 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 0d637c0f5..d23ef7f9e 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -5,7 +5,7 @@     com.bladejava     blade-kit -    1.2.3 +    1.2.4 ``` @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.3 +    1.2.4 ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -22,7 +22,7 @@     com.bladejava     blade-sql2o -    1.2.3 +    1.2.4 ``` @@ -31,7 +31,7 @@     com.bladejava     blade-jetbrick -    1.2.2 +    1.2.3 ``` @@ -40,7 +40,7 @@     com.bladejava     blade-beetl -    1.2.2 +    1.2.3 ``` @@ -49,7 +49,7 @@     com.bladejava     blade-velocity -    1.2.1 +    1.2.2 ``` diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index fb14b07a3..b087fb403 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -409,17 +409,23 @@ public static void run(String host, Integer port) { /**----------------------jetty:END-------------------------*/ /** + *

 	 * 手动注册一个对象到ioc容器中
+	 * 
* - * @param object 要注册的object + * @param object 要注册的object */ public static synchronized void register(Object object){ container.registBean(object); } /** - * 设置配置文件名称 - * @param confName 配置文件名称 + *
+	 * Properties配置文件方式
+	 * 文件的路径基于classpath
+	 * 
+ * + * @param confName 配置文件路径 */ public static synchronized void config(String confName){ Map configMap = PropertyKit.getPropertyMap(confName); @@ -427,8 +433,12 @@ public static synchronized void config(String confName){ } /** - * 设置JSON配置文件名称 - * @param confName 配置文件名称 + *
+	 * JSON文件的配置
+	 * 文件的路径基于classpath
+	 * 
+ * + * @param jsonPath json文件路径 */ public static synchronized void configJsonPath(String jsonPath){ InputStream inputStream = BladeBase.class.getResourceAsStream(jsonPath); @@ -444,8 +454,11 @@ public static synchronized void configJsonPath(String jsonPath){ } /** - * 设置JSON配置 - * @param json json配置 + *
+	 * JSON格式的配置
+	 * 
+ * + * @param json json配置 */ public static synchronized void configJson(String json){ Map configMap = JSONKit.toMap(json); @@ -453,8 +466,11 @@ public static synchronized void configJson(String json){ } /** - * 配置 - * @param json json配置 + *
+	 * 根据配置map保存配置
+	 * 
+ * + * @param configMap 存放配置的map */ private static void configuration(Map configMap){ new BladeConfigurator(BladeBase.BLADE_CONFIG, configMap).run(); diff --git a/blade-core/src/main/java/blade/BladeConfig.java b/blade-core/src/main/java/blade/BladeConfig.java index e65a46eb9..b48d665d0 100644 --- a/blade-core/src/main/java/blade/BladeConfig.java +++ b/blade-core/src/main/java/blade/BladeConfig.java @@ -29,22 +29,39 @@ */ public class BladeConfig { + // 存放所有路由的包 private List routePackages = CollectionKit.newArrayList(); + // 存放所有IOC的包 private List iocPackages = CollectionKit.newArrayList(); + // 存放所有过滤目录 private List staticFolders = CollectionKit.newArrayList(); + // 基础包 private String basePackage; + // 拦截器包 private String interceptorPackage; + // 编码 private String encoding = "utf-8"; + // 视图前缀 private String viewPrefix = "/WEB-INF/"; + // 视图后缀 private String viewSuffix = ".jsp"; + // webroot根目录,物理路径 private String webRoot; + // 404视图位置 private String view404; + // 500视图位置 private String view500; + // 数据库URL private String dbUrl; + // 数据库驱动 private String dbDriver; + // 数据库登录名 private String dbUser; + // 数据库登录密码 private String dbPass; + // 是否开启数据库缓存 private boolean isOpenCache = false; + // 是否是DEBUG模式 private boolean isDebug = true; public BladeConfig() { diff --git a/blade-core/src/main/java/blade/BladeConfigurator.java b/blade-core/src/main/java/blade/BladeConfigurator.java index 354f40956..f95c06688 100644 --- a/blade-core/src/main/java/blade/BladeConfigurator.java +++ b/blade-core/src/main/java/blade/BladeConfigurator.java @@ -1,13 +1,36 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade; import java.util.Map; import blade.kit.StringKit; +/** + * Blade配置文件注入 + * + * @author biezhi + * @since 1.0 + */ public class BladeConfigurator { + // 配置文件对象 private BladeConfig bladeConfig; + // 配置map private Map configMap; public BladeConfigurator(BladeConfig bladeConfig, @@ -32,24 +55,6 @@ public BladeConfigurator(BladeConfig bladeConfig, private static final String BLADE_VIEW_500 = "blade.view500"; private static final String BLADE_DEBUG = "blade.debug"; - /** - * 配置文件属性 - * blade.route= - * blade.interceptor= - * blade.ioc= - * blade.prefix= - * blade.suffix= - * blade.filter_folder= - * blade.dburl= - * blade.dbdriver= - * blade.dbuser= - * blade.dbpass= - * blade.opencache= - * blade.encoding= - * blade.view404= - * blade.view500= - * blade.debug= - */ public void run() { if (null != configMap && configMap.size() > 0) { String route = configMap.get(BLADE_ROUTE); From ea5bd95da390ca3e6275feb3134804c805fdf711 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 24 Jul 2015 16:33:16 +0800 Subject: [PATCH 042/545] add access to configuration files of the other parameters method --- blade-core/src/main/java/blade/BladeConfig.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/blade-core/src/main/java/blade/BladeConfig.java b/blade-core/src/main/java/blade/BladeConfig.java index b48d665d0..a2acce6f3 100644 --- a/blade-core/src/main/java/blade/BladeConfig.java +++ b/blade-core/src/main/java/blade/BladeConfig.java @@ -17,6 +17,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Map; import blade.kit.CollectionKit; @@ -29,6 +30,8 @@ */ public class BladeConfig { + // 存放所有变量 + private Map configMap = CollectionKit.newHashMap(); // 存放所有路由的包 private List routePackages = CollectionKit.newArrayList(); // 存放所有IOC的包 @@ -67,6 +70,18 @@ public class BladeConfig { public BladeConfig() { } + public Map getConfigMap() { + return configMap; + } + + public void setConfigMap(Map configMap) { + this.configMap = configMap; + } + + public String get(String key){ + return configMap.get(key); + } + public String[] getRoutePackages() { String[] routeArr = new String[routePackages.size()]; return routePackages.toArray(routeArr); From f94dc225104c6d0be0d7e9dc65ae9fe8f859833b Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 27 Jul 2015 11:11:34 +0800 Subject: [PATCH 043/545] update readme --- README.md | 2 +- README_EN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 352490867..15dca7d2c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) [![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) -[![release](https://img.shields.io/maven-central/v/com.bladejava/blade.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) **blade** 是一个简洁强大的web框架,它内置了`IOC`管理,拦截器配置,`REST API`开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送等常用功能,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! diff --git a/README_EN.md b/README_EN.md index 8ed592bfb..14e15ba45 100644 --- a/README_EN.md +++ b/README_EN.md @@ -8,7 +8,7 @@ [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) [![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) -[![release](https://img.shields.io/maven-central/v/com.bladejava/blade.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) ## Introduction From fbf3d352356672f6d2b45926a7106639e3b9ac8d Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 27 Jul 2015 16:53:43 +0800 Subject: [PATCH 044/545] fix sql2o repeated injection --- blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index d00841f11..7018e79a1 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -985,10 +985,8 @@ private Query insertCommit(Connection conn){ Query query = conn.createQuery(insertSql); query = parseParams(query); - query.executeUpdate(); LOGGER.debug("execute sql:" + query.toString()); LOGGER.debug("execute parameter:" + condition.params.values()); - return query; } From 9ef80a9753ca52c70c5eb4c580df28a62d9a9093 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 27 Jul 2015 16:57:04 +0800 Subject: [PATCH 045/545] update sql2o version --- LAST_VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index d23ef7f9e..b6f2dd2b5 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -22,7 +22,7 @@     com.bladejava     blade-sql2o -    1.2.4 +    1.2.5 ``` From 419e27f9666d3c14602ddbb0b3d258dc6690a77d Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 28 Jul 2015 10:33:03 +0800 Subject: [PATCH 046/545] remove jetty server and update pom --- README.md | 4 +- README_EN.md | 4 +- blade-beetl/pom.xml | 6 +- blade-cache/pom.xml | 10 +- blade-core/src/main/java/blade/BladeBase.java | 70 --------- .../main/java/blade/server/BladeServer.java | 134 ------------------ .../main/java/blade/server/package-info.java | 4 - blade-jetbrick/pom.xml | 6 +- blade-kit/pom.xml | 16 ++- blade-sql2o/pom.xml | 2 +- blade-velocity/pom.xml | 6 +- pom.xml | 102 ++++++------- 12 files changed, 83 insertions(+), 281 deletions(-) delete mode 100644 blade-core/src/main/java/blade/server/BladeServer.java delete mode 100644 blade-core/src/main/java/blade/server/package-info.java diff --git a/README.md b/README.md index 15dca7d2c..bb33ddf0a 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ * 实用工具类 * 模板引擎支持 * 支持JDK1.6+ -* 内置Jetty启动 * 插件扩展机制 * 缓存数据信息 * 编码/JSON/配置文件 @@ -125,9 +124,10 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ## 更新日志 -### v1.2.4 +### v1.2.5 1. 添加JSON、Properties文件配置 2. 优化代码性能 + 3. 去除内置jetty服务 ### v1.2.2 1. `DateKit`添加获取当前unix时间戳 diff --git a/README_EN.md b/README_EN.md index 14e15ba45..fdb6d2dcf 100644 --- a/README_EN.md +++ b/README_EN.md @@ -23,7 +23,6 @@ * Utility class * A template engine support * Support JDK1.6 + -* Jetty is started * Plug-in extension mechanism * Cache the data information * Coding/JSON/config file @@ -127,9 +126,10 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ### Update -### v1.2.4 +### v1.2.5 1. Add JSON, configuration Properties file 2. Optimize the code performance + 3. Remove inlay Jetty Server ### v1.2.2 1. `DateKit` added to obtain the current Unix timestamp diff --git a/blade-beetl/pom.xml b/blade-beetl/pom.xml index 318680756..7b4e8d193 100644 --- a/blade-beetl/pom.xml +++ b/blade-beetl/pom.xml @@ -13,9 +13,13 @@ jar ${blade.version} blade-beetl - https://github.com/biezhi/blade/blade-beetl + https://github.com/biezhi/blade/tree/master/blade-beetl + + javax.servlet + javax.servlet-api + com.bladejava blade-core diff --git a/blade-cache/pom.xml b/blade-cache/pom.xml index 36ba051b1..bc1733811 100644 --- a/blade-cache/pom.xml +++ b/blade-cache/pom.xml @@ -13,6 +13,12 @@ jar ${blade.version} blade-cache - https://github.com/biezhi/blade/blade-cache - + https://github.com/biezhi/blade/tree/master/blade-cache + + + + junit + junit + + diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index b087fb403..6e954c7ad 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -27,7 +27,6 @@ import blade.render.Render; import blade.render.RenderFactory; import blade.route.DefaultRouteMatcher; -import blade.server.BladeServer; /** * Blade的基础类 @@ -339,75 +338,6 @@ public static BladeApplication application(){ /**--------------------GET CONST:END-------------------------*/ - - /**----------------------jetty:START-------------------------*/ - - /** - * 设置jetty启动端口 - * - * @param port 端口号,范围在0~65535之间,默认为9000 - */ - public static synchronized void port(int port){ - if(port > 0 && port < 65535){ - BladeBase.PORT = port; - } - } - - /** - * 运行jetty服务 - * - * @param port 端口号,范围在0~65535之间,默认为9000 - * @param host host,默认为本机;127.0.0.1/localhost - * @param context context,应用上下文,默认为"/" - */ - public static void run(Integer port, String host, String context) { - BladeBase.PORT = port; - BladeServer.run(port, host, context); - } - - /** - * 运行jetty服务 - */ - public static void run() { - run(BladeBase.PORT, null, null); - } - - /** - * 运行jetty服务并设置主机 - * - * @param host host,默认为本机;127.0.0.1/localhost - */ - public static void run(String host) { - run(BladeBase.PORT, host, null); - } - - /** - * 运行jetty服务并设置端口 - * - * @param port 端口号,范围在0~65535之间,默认为9000 - */ - public static void run(Integer port) { - run(port, null, null); - } - - public static void run(Class clazz, Integer port) { - if(null != clazz){ - app(clazz); - } - run(port, null, null); - } - - /** - * 运行jetty服务并设置端口和主机 - * - * @param host host,默认为本机;127.0.0.1/localhost - * @param port 端口号,范围在0~65535之间,默认为9000 - */ - public static void run(String host, Integer port) { - run(port, host, null); - } - /**----------------------jetty:END-------------------------*/ - /** *
 	 * 手动注册一个对象到ioc容器中
diff --git a/blade-core/src/main/java/blade/server/BladeServer.java b/blade-core/src/main/java/blade/server/BladeServer.java
deleted file mode 100644
index 2957aa5de..000000000
--- a/blade-core/src/main/java/blade/server/BladeServer.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.server;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.EnumSet;
-
-import javax.servlet.DispatcherType;
-
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.webapp.WebAppContext;
-
-import blade.Blade;
-import blade.BladeFilter;
-import blade.kit.log.Logger;
-
-/**
- * 内置jetty服务
- *
- * @author	biezhi
- * @since	1.0
- */
-public final class BladeServer {
-	
-	/**
-	 * 默认的应用所在位置
-	 */
-	private static String DEFAULT_APP_PATH = BladeServer.class.getClassLoader().getResource("").getPath();
-	
-	private static final Logger LOGGER = Logger.getLogger(BladeServer.class);
-	
-	private BladeServer(){
-		
-	}
-	
-	static{
-		try {
-			File rootDir = new File("");// 参数为空
-			final String courseFile = rootDir.getCanonicalPath();
-			
-			// 标准maven构建的webapp
-			File webapp = new File(courseFile + File.separator + "src/main/webapp");
-			if(webapp.exists()){
-				DEFAULT_APP_PATH = "src/main/webapp";
-			} else {
-				// 普通web项目
-				webapp = new File(courseFile + File.separator + "WebContent/");
-				if(webapp.exists()){
-					DEFAULT_APP_PATH = "WebContent";
-				}
-			}
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-	}
-	
-	public static void setDefaultAppPath(final String defaultPath){
-		BladeServer.DEFAULT_APP_PATH = defaultPath;
-	}
-	
-	/**
-	 * 创建用于开发运行调试的Jetty Server,
-	 */
-	public static Server createServerInSource(Integer port, String host, String contextPath) {
-		
-		Server server = new Server();
-		// 设置在JVM退出时关闭Jetty的钩子。
-		server.setStopAtShutdown(true);
-
-		// 这是http的连接器
-		ServerConnector connector = new ServerConnector(server);
-		connector.setPort(port);
-		connector.setHost(host);
-		
-		// 解决Windows下重复启动Jetty居然不报告端口冲突的问题.
-		connector.setReuseAddress(false);
-		connector.setName("blade-jetty-server");
-		server.setConnectors(new Connector[] { connector });
-		
-		WebAppContext webContext = new WebAppContext(DEFAULT_APP_PATH, contextPath);
-		
-		webContext.addFilter(BladeFilter.class, "/*", EnumSet.of(DispatcherType.INCLUDE,DispatcherType.REQUEST,DispatcherType.FORWARD, DispatcherType.ASYNC));
-		
-		// 设置webapp的位置
-		webContext.setResourceBase(DEFAULT_APP_PATH);
-		webContext.setClassLoader(Thread.currentThread().getContextClassLoader());
-		server.setHandler(webContext);
-		return server;
-	}
-	
-	public static void run(Integer port, String host, String contextPath){
-		try {
-			
-			if(null == port){
-				port = 9000;
-			}
-			
-			if(null == host){
-				host = "127.0.0.1";
-			}
-			
-			if(null == contextPath){
-				contextPath = "/";
-			}
-			
-			final Server server = createServerInSource(port, host, contextPath);
-			
-			Blade.runJetty = true;
-			server.stop();
-			server.start();
-			LOGGER.info("Blade Server Run In : http://" + host + ":" + port + contextPath);
-			server.join();
-		} catch (Exception e) {
-			e.printStackTrace();
-			System.exit(-1);
-		}
-	}
-}
\ No newline at end of file
diff --git a/blade-core/src/main/java/blade/server/package-info.java b/blade-core/src/main/java/blade/server/package-info.java
deleted file mode 100644
index 132a123fd..000000000
--- a/blade-core/src/main/java/blade/server/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * blade jetty服务
- */
-package blade.server;
\ No newline at end of file
diff --git a/blade-jetbrick/pom.xml b/blade-jetbrick/pom.xml
index b130b1e5c..6e48618cf 100644
--- a/blade-jetbrick/pom.xml
+++ b/blade-jetbrick/pom.xml
@@ -13,9 +13,13 @@
 	jar
 	${blade.version}
 	blade-jetbrick
-	https://github.com/biezhi/blade/blade-jetbrick
+	https://github.com/biezhi/blade/tree/master/blade-jetbrick
 
 	
+		
+            javax.servlet
+            javax.servlet-api
+        
 		
 			com.bladejava
 			blade-core
diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml
index 5b52dab77..cf6a85741 100644
--- a/blade-kit/pom.xml
+++ b/blade-kit/pom.xml
@@ -8,14 +8,18 @@
 		blade-root
 		1.0
 	
-	
+
 	blade-kit
 	jar
 	${blade.version}
 	blade-kit
-	https://github.com/biezhi/blade/blade-kit
-	
+	https://github.com/biezhi/blade/tree/master/blade-kit
+
 	
+		
+			junit
+			junit
+		
 		
 			javax.mail
 			mail
@@ -28,6 +32,10 @@
 			1.2.17
 			provided
 		
+		
+			javax.servlet
+			javax.servlet-api
+		
 	
-	
+
 
diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml
index c8acfd516..2e69bf317 100644
--- a/blade-sql2o/pom.xml
+++ b/blade-sql2o/pom.xml
@@ -13,7 +13,7 @@
 	jar
 	${blade.version}
 	blade-sql2o
-	https://github.com/biezhi/blade/blade-sql2o
+	https://github.com/biezhi/blade/tree/master/blade-sql2o
 
 	
 		
diff --git a/blade-velocity/pom.xml b/blade-velocity/pom.xml
index 32e7ae0ed..da33e9a3d 100644
--- a/blade-velocity/pom.xml
+++ b/blade-velocity/pom.xml
@@ -13,9 +13,13 @@
 	jar
 	${blade.version}
 	blade-velocity
-	https://github.com/biezhi/blade/blade-velocity
+	https://github.com/biezhi/blade/tree/master/blade-velocity
 
 	
+		
+            javax.servlet
+            javax.servlet-api
+        
 		
 			com.bladejava
 			blade-core
diff --git a/pom.xml b/pom.xml
index 8a425f2cf..006b7c9b7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,67 +1,51 @@
 
 
-	4.0.0
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    4.0.0
 
-	com.bladejava
-	blade-root
-	1.0
-	pom
+    com.bladejava
+    blade-root
+    1.0
+    pom
 
-	blade-root
-	https://github.com/biezhi/blade
+    blade-root
+    https://github.com/biezhi/blade
 
-	
-		1.6
-		1.6
-		UTF-8
-		4.11
-		1.2.4
-		3.0.1
-	
+    
+        1.6
+        1.6
+        UTF-8
+        4.11
+        1.2.4
+        3.0.1
+    
 
-	
-		blade-kit
-		blade-core
-		blade-cache
-		blade-jetbrick
-		blade-sql2o
-		blade-velocity
-		blade-beetl
-		blade-redis
-	
-
-	
-		
-			junit
-			junit
-			${junit.version}
-		
-		
-		
-			javax.servlet
-			javax.servlet-api
-			${servlet.version}
-			provided
-		
-	
-
-	
-		
-			
-				org.apache.maven.plugins
-				maven-compiler-plugin
-				2.3.2
-				
-					1.6
-					1.6
-					UTF-8
-				
-			
-			
-		
-	
+    
+        blade-kit
+        blade-core
+        blade-cache
+        blade-jetbrick
+        blade-sql2o
+        blade-velocity
+        blade-beetl
+        blade-redis
+    
+    
+    
+        
+            
+                junit
+                junit
+                ${junit.version}
+            
+            
+                javax.servlet
+                javax.servlet-api
+                ${servlet.version}
+                provided
+            
+        
+    
+    
 
 
\ No newline at end of file

From b9adb8a8a5d3b09384084a5b013ef1fbb8908cbf Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Tue, 28 Jul 2015 11:24:43 +0800
Subject: [PATCH 047/545] update version and readme

---
 LAST_VERSION.md | 2 +-
 README.md       | 1 -
 README_EN.md    | 1 -
 pom.xml         | 3 +--
 4 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/LAST_VERSION.md b/LAST_VERSION.md
index b6f2dd2b5..5aebcd435 100644
--- a/LAST_VERSION.md
+++ b/LAST_VERSION.md
@@ -14,7 +14,7 @@
 
     com.bladejava
     blade-core
-    1.2.4
+    1.2.5-alpha
 
 ```
 ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o)
diff --git a/README.md b/README.md
index bb33ddf0a..3c073c7d3 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,6 @@
 [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773)
 [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)
 [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade)
-[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master)
 [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22)
 
 **blade** 是一个简洁强大的web框架,它内置了`IOC`管理,拦截器配置,`REST API`开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送等常用功能,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) !
diff --git a/README_EN.md b/README_EN.md
index fdb6d2dcf..9f986468c 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -7,7 +7,6 @@
 [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773)
 [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)
 [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade)
-[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master)
 [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22)
 
 ## Introduction
diff --git a/pom.xml b/pom.xml
index 006b7c9b7..8a8561c31 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
         1.6
         UTF-8
         4.11
-        1.2.4
+        1.2.5-alpha
         3.0.1
     
 
@@ -46,6 +46,5 @@
             
         
     
-    
 
 
\ No newline at end of file

From e619d30616e8ea9a79af6467470550aa147c41cf Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Wed, 29 Jul 2015 10:44:21 +0800
Subject: [PATCH 048/545] optimize the logging code

---
 .../src/main/java/blade/kit/log/SysLoggerAdaptor.java      | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java b/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java
index 6a0ce0ea9..76c37b375 100644
--- a/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java
+++ b/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java
@@ -1,5 +1,6 @@
 package blade.kit.log;
 
+import java.io.PrintStream;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
@@ -13,6 +14,8 @@ public class SysLoggerAdaptor extends Logger {
 
 	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
 	
+    private static PrintStream outprint = System.out;
+    
 	public SysLoggerAdaptor() {
 	}
 	
@@ -34,6 +37,7 @@ private String getLevel(int level){
 			return "WARN";
 		}
 		if(level <= ERROR){
+			outprint = System.err;
 			return "ERROR";
 		}
 		if(level <= FATAL){
@@ -60,7 +64,8 @@ public void log(int level, Object message, Throwable t, Object... args) {
 		sb.append("[").append(Thread.currentThread().getName()).append("]").append(" ");
 		sb.append(getName()).append(" | ");
 		sb.append(format(message, args));
-		System.out.println(sb.toString());
+		
+		outprint.println(sb.toString());
 		if (t != null) {
 			t.printStackTrace(System.err);
 		}

From 8c8f0595759759fdcddac21837e0389eaf615e8d Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Wed, 29 Jul 2015 10:47:13 +0800
Subject: [PATCH 049/545] Add a file transfer string method

---
 blade-kit/src/main/java/blade/kit/IOKit.java | 26 +++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/blade-kit/src/main/java/blade/kit/IOKit.java b/blade-kit/src/main/java/blade/kit/IOKit.java
index aa4451c3d..d4725ad78 100644
--- a/blade-kit/src/main/java/blade/kit/IOKit.java
+++ b/blade-kit/src/main/java/blade/kit/IOKit.java
@@ -15,9 +15,11 @@
  */
 package blade.kit;
 
+import java.io.BufferedReader;
 import java.io.Closeable;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -67,7 +69,29 @@ public static String toString(InputStream input) throws IOException {
         copy(input, sw);
         return sw.toString();
     }
-
+    
+    public static String toString(File file) throws IOException {
+    	try {
+            BufferedReader reader = new BufferedReader(new FileReader(file));
+            StringBuilder data = readFromBufferedReader(reader);
+            reader.close();
+            return new String(data.toString().getBytes(), "utf-8");
+        } catch (IOException ex) {
+            throw new RuntimeException("File " + file + " not found.");
+        }
+    }
+    
+    private static StringBuilder readFromBufferedReader(BufferedReader reader) throws IOException {
+        StringBuilder builder = new StringBuilder();
+        char[] buffer = new char[DEFAULT_BUFFER_SIZE];
+        int numRead = 0;
+        while((numRead = reader.read(buffer)) != -1) {
+            builder.append(String.valueOf(buffer, 0, numRead));
+            buffer = new char[DEFAULT_BUFFER_SIZE];
+        }
+        return builder;
+    }
+    
     public static byte[] toByteArray(InputStream input) throws IOException {
         @SuppressWarnings("resource")
 		FastByteArrayOutputStream os = new FastByteArrayOutputStream();

From bd857aba313cda41ed536881f93926424cf08f70 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Wed, 29 Jul 2015 10:53:09 +0800
Subject: [PATCH 050/545] modify comments

---
 blade-kit/src/main/java/blade/kit/Base64.java | 129 ++++++++++++++++++
 .../src/main/java/blade/kit/BeanKit.java      |  15 ++
 .../src/main/java/blade/kit/CharKit.java      |  15 ++
 .../main/java/blade/kit/CollectionKit.java    |  15 ++
 .../src/main/java/blade/kit/DateKit.java      |  15 ++
 blade-kit/src/main/java/blade/kit/Emptys.java |  15 ++
 .../src/main/java/blade/kit/EncrypKit.java    |  96 +++++++++++++
 .../src/main/java/blade/kit/ExceptionKit.java |  15 ++
 .../src/main/java/blade/kit/FileKit.java      |  17 ++-
 .../src/main/java/blade/kit/MailKit.java      |  15 ++
 .../src/main/java/blade/kit/ReflectKit.java   |  15 ++
 .../src/main/java/blade/kit/ShellKit.java     |  16 +++
 .../src/main/java/blade/kit/StreamKit.java    |  15 ++
 .../src/main/java/blade/kit/SystemKit.java    |  15 ++
 .../src/main/java/blade/kit/TaskKit.java      |  15 ++
 .../src/main/java/blade/kit/package-info.java |   2 +-
 16 files changed, 423 insertions(+), 2 deletions(-)
 create mode 100644 blade-kit/src/main/java/blade/kit/Base64.java
 create mode 100644 blade-kit/src/main/java/blade/kit/EncrypKit.java

diff --git a/blade-kit/src/main/java/blade/kit/Base64.java b/blade-kit/src/main/java/blade/kit/Base64.java
new file mode 100644
index 000000000..0c7db1f37
--- /dev/null
+++ b/blade-kit/src/main/java/blade/kit/Base64.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * BASE64工具类
+ *
+ * @author	biezhi
+ * @since	1.0
+ */
+public class Base64 {
+	
+	private static char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+			'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+			'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
+			'2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
+	
+	private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+			-1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
+			5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26,
+			27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1,
+			-1, -1, -1 };
+
+	//编码
+	public static String encode(byte[] data) {
+		StringBuffer sb = new StringBuffer();
+		int len = data.length;
+		int i = 0;
+		int b1, b2, b3;
+		while (i < len) {
+			b1 = data[i++] & 0xff;
+			if (i == len) {
+				sb.append(base64EncodeChars[b1 >>> 2]);
+				sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
+				sb.append("==");
+				break;
+			}
+			b2 = data[i++] & 0xff;
+			if (i == len) {
+				sb.append(base64EncodeChars[b1 >>> 2]);
+				sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
+				sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
+				sb.append("=");
+				break;
+			}
+			b3 = data[i++] & 0xff;
+			sb.append(base64EncodeChars[b1 >>> 2]);
+			sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
+			sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]);
+			sb.append(base64EncodeChars[b3 & 0x3f]);
+		}
+		return sb.toString();
+	}
+
+	//解码
+	public static byte[] decode(String str) throws UnsupportedEncodingException {
+		StringBuffer sb = new StringBuffer();
+		byte[] data = str.getBytes("US-ASCII");
+		int len = data.length;
+		int i = 0;
+		int b1, b2, b3, b4;
+		while (i < len) {
+			/* b1 */
+			do {
+				b1 = base64DecodeChars[data[i++]];
+			} while (i < len && b1 == -1);
+			if (b1 == -1)
+				break;
+			/* b2 */
+			do {
+				b2 = base64DecodeChars[data[i++]];
+			} while (i < len && b2 == -1);
+			if (b2 == -1)
+				break;
+			sb.append((char) ((b1 << 2) | ((b2 & 0X30) >>> 4)));
+			/* b3 */
+			do {
+				b3 = data[i++];
+				if (b3 == 61)
+					return sb.toString().getBytes("iso8859-1");
+				b3 = base64DecodeChars[b3];
+			} while (i < len && b3 == -1);
+			if (b3 == -1)
+				break;
+			sb.append((char) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));
+			/* b4 */
+			do {
+				b4 = data[i++];
+				if (b4 == 61)
+					return sb.toString().getBytes("iso8859-1");
+				b4 = base64DecodeChars[b4];
+			} while (i < len && b4 == -1);
+			if (b4 == -1)
+				break;
+			sb.append((char) (((b3 & 0X03) << 6) | b4));
+		}
+		return sb.toString().getBytes("iso8859-1");
+	}
+	
+	/**
+	 * 加密
+	 * @param str
+	 * @return
+	 */
+	public static String encoder(String str){
+		return encode(str.getBytes());
+	}
+	
+	public static String decoder(String str) throws UnsupportedEncodingException{
+		return new String(decode(str));
+	}
+	
+}
\ No newline at end of file
diff --git a/blade-kit/src/main/java/blade/kit/BeanKit.java b/blade-kit/src/main/java/blade/kit/BeanKit.java
index 6433c0cd3..eaaf3b1d6 100644
--- a/blade-kit/src/main/java/blade/kit/BeanKit.java
+++ b/blade-kit/src/main/java/blade/kit/BeanKit.java
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit;
 
 import java.beans.BeanInfo;
diff --git a/blade-kit/src/main/java/blade/kit/CharKit.java b/blade-kit/src/main/java/blade/kit/CharKit.java
index aab0e086d..48b8a267d 100644
--- a/blade-kit/src/main/java/blade/kit/CharKit.java
+++ b/blade-kit/src/main/java/blade/kit/CharKit.java
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit;
 
 import java.io.UnsupportedEncodingException;
diff --git a/blade-kit/src/main/java/blade/kit/CollectionKit.java b/blade-kit/src/main/java/blade/kit/CollectionKit.java
index 411e8c62e..cf455f29c 100644
--- a/blade-kit/src/main/java/blade/kit/CollectionKit.java
+++ b/blade-kit/src/main/java/blade/kit/CollectionKit.java
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit;
 
 import java.util.ArrayDeque;
diff --git a/blade-kit/src/main/java/blade/kit/DateKit.java b/blade-kit/src/main/java/blade/kit/DateKit.java
index 3dfb9f082..a3c7f78d0 100644
--- a/blade-kit/src/main/java/blade/kit/DateKit.java
+++ b/blade-kit/src/main/java/blade/kit/DateKit.java
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit;
 
 import java.text.DateFormat;
diff --git a/blade-kit/src/main/java/blade/kit/Emptys.java b/blade-kit/src/main/java/blade/kit/Emptys.java
index 7d33e5114..520f66f01 100644
--- a/blade-kit/src/main/java/blade/kit/Emptys.java
+++ b/blade-kit/src/main/java/blade/kit/Emptys.java
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit;
 
 import java.io.Serializable;
diff --git a/blade-kit/src/main/java/blade/kit/EncrypKit.java b/blade-kit/src/main/java/blade/kit/EncrypKit.java
new file mode 100644
index 000000000..58698febe
--- /dev/null
+++ b/blade-kit/src/main/java/blade/kit/EncrypKit.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit;
+
+import java.security.MessageDigest;
+
+/**
+ * md5 sha加密类
+ *
+ * @author	biezhi
+ * @since	1.0
+ */
+public class EncrypKit {
+
+	private static final String ALGORITHM = "MD5";
+
+	private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
+			'e', 'f' };
+
+	/**
+	 * encode string
+	 *
+	 * @param algorithm
+	 * @param str
+	 * @return String
+	 */
+	public static String encode(String algorithm, String str) {
+		if (str == null) {
+			return null;
+		}
+		try {
+			MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
+			messageDigest.update(str.getBytes());
+			return getFormattedText(messageDigest.digest());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+
+	}
+
+	/**
+	 * encode By MD5
+	 *
+	 * @param str
+	 * @return String
+	 */
+	public static String md5(String str) {
+		if (str == null) {
+			return null;
+		}
+		try {
+			MessageDigest messageDigest = MessageDigest.getInstance(ALGORITHM);
+			messageDigest.update(str.getBytes());
+			return getFormattedText(messageDigest.digest());
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+
+	}
+
+	/**
+	 * Takes the raw bytes from the digest and formats them correct.
+	 *
+	 * @param bytes
+	 *            the raw bytes from the digest.
+	 * @return the formatted bytes.
+	 */
+	private static String getFormattedText(byte[] bytes) {
+		int len = bytes.length;
+		StringBuilder buf = new StringBuilder(len * 2);
+		// 把密文转换成十六进制的字符串形式
+		for (int j = 0; j < len; j++) {
+			buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
+			buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
+		}
+		return buf.toString();
+	}
+	
+	public static String sha1(final String str){
+		return EncrypKit.encode("SHA1", str);
+	}
+	
+}
\ No newline at end of file
diff --git a/blade-kit/src/main/java/blade/kit/ExceptionKit.java b/blade-kit/src/main/java/blade/kit/ExceptionKit.java
index ddabf2e0d..258a11719 100644
--- a/blade-kit/src/main/java/blade/kit/ExceptionKit.java
+++ b/blade-kit/src/main/java/blade/kit/ExceptionKit.java
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit;
 
 import java.io.PrintWriter;
diff --git a/blade-kit/src/main/java/blade/kit/FileKit.java b/blade-kit/src/main/java/blade/kit/FileKit.java
index 4acd4a08d..a45c3e9c1 100644
--- a/blade-kit/src/main/java/blade/kit/FileKit.java
+++ b/blade-kit/src/main/java/blade/kit/FileKit.java
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit;
 
 import java.io.File;
@@ -15,7 +30,7 @@
 import blade.exception.IllegalPathException;
 
 /**
- * 有关File处理的工具类。
+ * 有关文件处理的工具类。
  * 

* 这个类中的每个方法都可以“安全”地处理 null ,而不会抛出 NullPointerException。 *

diff --git a/blade-kit/src/main/java/blade/kit/MailKit.java b/blade-kit/src/main/java/blade/kit/MailKit.java index 1a7d984e7..937f0f93c 100644 --- a/blade-kit/src/main/java/blade/kit/MailKit.java +++ b/blade-kit/src/main/java/blade/kit/MailKit.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; import java.util.Arrays; diff --git a/blade-kit/src/main/java/blade/kit/ReflectKit.java b/blade-kit/src/main/java/blade/kit/ReflectKit.java index 02dc03e47..6a4cb812a 100644 --- a/blade-kit/src/main/java/blade/kit/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/ReflectKit.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; import java.io.File; diff --git a/blade-kit/src/main/java/blade/kit/ShellKit.java b/blade-kit/src/main/java/blade/kit/ShellKit.java index ec7db4db9..a37b70f58 100644 --- a/blade-kit/src/main/java/blade/kit/ShellKit.java +++ b/blade-kit/src/main/java/blade/kit/ShellKit.java @@ -1,4 +1,20 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; + import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; diff --git a/blade-kit/src/main/java/blade/kit/StreamKit.java b/blade-kit/src/main/java/blade/kit/StreamKit.java index d69e09cd3..b25ebcec5 100644 --- a/blade-kit/src/main/java/blade/kit/StreamKit.java +++ b/blade-kit/src/main/java/blade/kit/StreamKit.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; import java.io.Closeable; diff --git a/blade-kit/src/main/java/blade/kit/SystemKit.java b/blade-kit/src/main/java/blade/kit/SystemKit.java index a8b1a1fcc..7707a6ada 100644 --- a/blade-kit/src/main/java/blade/kit/SystemKit.java +++ b/blade-kit/src/main/java/blade/kit/SystemKit.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; import java.io.PrintWriter; diff --git a/blade-kit/src/main/java/blade/kit/TaskKit.java b/blade-kit/src/main/java/blade/kit/TaskKit.java index 220520313..aa59e5663 100644 --- a/blade-kit/src/main/java/blade/kit/TaskKit.java +++ b/blade-kit/src/main/java/blade/kit/TaskKit.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; import java.text.ParseException; diff --git a/blade-kit/src/main/java/blade/kit/package-info.java b/blade-kit/src/main/java/blade/kit/package-info.java index 08a579341..0bf487f17 100644 --- a/blade-kit/src/main/java/blade/kit/package-info.java +++ b/blade-kit/src/main/java/blade/kit/package-info.java @@ -1,4 +1,4 @@ /** - * 一些通用工具包 + * 最常用的工具类集合 */ package blade.kit; \ No newline at end of file From a49fe02e9a845c321464d6affc408a2af7376e91 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 29 Jul 2015 10:58:24 +0800 Subject: [PATCH 051/545] update pom --- blade-beetl/pom.xml | 2 +- blade-cache/pom.xml | 2 +- blade-jetbrick/pom.xml | 2 +- blade-kit/pom.xml | 2 +- blade-redis/pom.xml | 2 +- blade-sql2o/pom.xml | 2 +- blade-velocity/pom.xml | 2 +- pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/blade-beetl/pom.xml b/blade-beetl/pom.xml index 7b4e8d193..757ec55b5 100644 --- a/blade-beetl/pom.xml +++ b/blade-beetl/pom.xml @@ -11,7 +11,7 @@ blade-beetl jar - ${blade.version} + 1.2.3 blade-beetl https://github.com/biezhi/blade/tree/master/blade-beetl diff --git a/blade-cache/pom.xml b/blade-cache/pom.xml index bc1733811..55b636e64 100644 --- a/blade-cache/pom.xml +++ b/blade-cache/pom.xml @@ -11,7 +11,7 @@ blade-cache jar - ${blade.version} + 1.2.2 blade-cache https://github.com/biezhi/blade/tree/master/blade-cache diff --git a/blade-jetbrick/pom.xml b/blade-jetbrick/pom.xml index 6e48618cf..f8b01ae18 100644 --- a/blade-jetbrick/pom.xml +++ b/blade-jetbrick/pom.xml @@ -11,7 +11,7 @@ blade-jetbrick jar - ${blade.version} + 1.2.3 blade-jetbrick https://github.com/biezhi/blade/tree/master/blade-jetbrick diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index cf6a85741..f29301b07 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - ${blade.version} + 1.2.4 blade-kit https://github.com/biezhi/blade/tree/master/blade-kit diff --git a/blade-redis/pom.xml b/blade-redis/pom.xml index 244bc6a3e..25a8e92c5 100644 --- a/blade-redis/pom.xml +++ b/blade-redis/pom.xml @@ -11,7 +11,7 @@ blade-redis jar - ${blade.version} + 1.2.1 blade-redis https://github.com/biezhi/blade/blade-redis diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 2e69bf317..7ba95e893 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - ${blade.version} + 1.2.5 blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o diff --git a/blade-velocity/pom.xml b/blade-velocity/pom.xml index da33e9a3d..5049587fc 100644 --- a/blade-velocity/pom.xml +++ b/blade-velocity/pom.xml @@ -11,7 +11,7 @@ blade-velocity jar - ${blade.version} + 1.2.2 blade-velocity https://github.com/biezhi/blade/tree/master/blade-velocity diff --git a/pom.xml b/pom.xml index 8a8561c31..576dba92f 100644 --- a/pom.xml +++ b/pom.xml @@ -16,8 +16,8 @@ 1.6 UTF-8 4.11 - 1.2.5-alpha 3.0.1 + 1.2.5-alpha From 48b7639bbd3e93fbe40074fcc5920e36acc5ec6f Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 29 Jul 2015 10:59:52 +0800 Subject: [PATCH 052/545] update pom --- blade-core/pom.xml | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 401428b80..fe68e7079 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -14,30 +14,16 @@ ${blade.version} blade-core https://github.com/biezhi/blade/blade-core - - - 9.3.0.v20150612 - - + - com.bladejava blade-kit - ${blade.version} + 1.2.4 - - org.eclipse.jetty - jetty-server - ${jetty.version} - provided - - - org.eclipse.jetty - jetty-webapp - ${jetty.version} - provided - + javax.servlet + javax.servlet-api +
From dfecdcc4f9161306c1960dd3b7e8c4da78efefed Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 29 Jul 2015 11:31:46 +0800 Subject: [PATCH 053/545] modify the grammar --- .../src/main/java/blade/route/DefaultRouteMatcher.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index 311b467c6..0b3cf0d22 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -17,6 +17,7 @@ import java.lang.reflect.Method; import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; @@ -70,9 +71,9 @@ public RouteMatcher findRouteMatcher(HttpMethod httpMethod, String uri, String a } private void giveMatch(final String uri, List routeEntries) { - routeEntries.sort(new Comparator() { - @Override - public int compare(RouteMatcher o1, RouteMatcher o2) { + Collections.sort(routeEntries, new Comparator() { + @Override + public int compare(RouteMatcher o1, RouteMatcher o2) { if(o2.path.equals(uri)){ return o2.path.indexOf(uri); } From 1c965b39dbe052b3c6724eebcf2224c93695ce15 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 29 Jul 2015 11:34:39 +0800 Subject: [PATCH 054/545] update pom --- blade-sql2o/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 7ba95e893..f9aeb2aaf 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -25,7 +25,7 @@ com.bladejava blade-cache - ${blade.version} + 1.2.2 provided From 56d90c538735aa04bb83c14aa0ab3b4d2a0091c6 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 29 Jul 2015 11:42:47 +0800 Subject: [PATCH 055/545] update pom --- pom.xml | 105 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 42 deletions(-) diff --git a/pom.xml b/pom.xml index 576dba92f..ac73a51fb 100644 --- a/pom.xml +++ b/pom.xml @@ -1,50 +1,71 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - com.bladejava - blade-root - 1.0 - pom + com.bladejava + blade-root + 1.0 + pom - blade-root - https://github.com/biezhi/blade + blade-root + https://github.com/biezhi/blade - - 1.6 - 1.6 - UTF-8 - 4.11 - 3.0.1 - 1.2.5-alpha - + + 1.6 + 1.6 + UTF-8 + 4.11 + 3.0.1 + 1.2.5-alpha + - - blade-kit - blade-core - blade-cache - blade-jetbrick - blade-sql2o - blade-velocity - blade-beetl - blade-redis - - - - - - junit - junit - ${junit.version} - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - + + blade-kit + blade-core + blade-cache + blade-jetbrick + blade-sql2o + blade-velocity + blade-beetl + blade-redis + + + + + + junit + junit + ${junit.version} + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + + + + + + org.apache.maven.plugin + maven-compiler-plugin + 2.1 + + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.5 + + true + + + + \ No newline at end of file From 5f97439083d67c1be5d946112bad0df90a99c6b2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 29 Jul 2015 11:45:46 +0800 Subject: [PATCH 056/545] update readme --- README.md | 1 + README_EN.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 3c073c7d3..bb33ddf0a 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) +[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) **blade** 是一个简洁强大的web框架,它内置了`IOC`管理,拦截器配置,`REST API`开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送等常用功能,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! diff --git a/README_EN.md b/README_EN.md index 9f986468c..fdb6d2dcf 100644 --- a/README_EN.md +++ b/README_EN.md @@ -7,6 +7,7 @@ [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) +[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) ## Introduction From 99731fb005846ed3dfd4d7e935280847308d179e Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 29 Jul 2015 18:51:30 +0800 Subject: [PATCH 057/545] update LAST_VERSION --- LAST_VERSION.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 5aebcd435..d62a0ef21 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -5,7 +5,7 @@     com.bladejava     blade-kit -    1.2.4 +    1.2.5-beta ``` @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.5-alpha +    1.2.5-beta ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) From 1fa64fcea51a8e0f2696eef44639d5b9deebbe0f Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 29 Jul 2015 18:52:29 +0800 Subject: [PATCH 058/545] update readme --- README.md | 2 +- README_EN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bb33ddf0a..ca9e79df7 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ com.bladejava blade-core - 1.2.3 + 1.2.5-beta ``` diff --git a/README_EN.md b/README_EN.md index fdb6d2dcf..f14ae087c 100644 --- a/README_EN.md +++ b/README_EN.md @@ -35,7 +35,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.3 + 1.2.5-beta ``` From 25039fed8289d987e5293ca08747faf8d8271c61 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 30 Jul 2015 09:41:01 +0800 Subject: [PATCH 059/545] update readme --- README.md | 7 ++++--- README_EN.md | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ca9e79df7..c0a8de007 100644 --- a/README.md +++ b/README.md @@ -118,9 +118,10 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ### 计划 1. 完善文档 - 2. 用`blade`开发单用户博客系统、音乐系统、图片系统等 - 3. 优化代码性能 - 4. 编写英文文档 + 2. 单用户博客系统开发 + 3. 相册系统开发 + 4. 音乐系统开发 + 5. 优化代码性能 ## 更新日志 diff --git a/README_EN.md b/README_EN.md index f14ae087c..07eaccbd7 100644 --- a/README_EN.md +++ b/README_EN.md @@ -119,10 +119,11 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex + [Some Examples](https://github.com/bladejava) ### Plan - 1. Perfect the documents - 2. With `blade` development single-user blog system, music, pictures, etc - 3. Optimize the code performance - 4. Write English document + 1. Improve the document + 2. Single user blog system development + 3. The photo album system development + 4. Music system development + 5. Optimize the code performance ### Update From 5df327a36801996abf81cd576a471e306f9d19ad Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 31 Jul 2015 10:50:33 +0800 Subject: [PATCH 060/545] remove realPath method --- blade-core/src/main/java/blade/servlet/Request.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/blade-core/src/main/java/blade/servlet/Request.java b/blade-core/src/main/java/blade/servlet/Request.java index f9da3d554..3d4c644f2 100644 --- a/blade-core/src/main/java/blade/servlet/Request.java +++ b/blade-core/src/main/java/blade/servlet/Request.java @@ -192,13 +192,6 @@ public String contextPath() { return servletRequest.getContextPath(); } - /** - * @return 返回realPath - */ - public String realPath(String path) { - return servletRequest.getServletContext().getRealPath(path); - } - /** * @return 返回url */ From 9d6e6a0f86f6e77f0fe797999f06ff0d7aca71c1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 31 Jul 2015 13:19:15 +0800 Subject: [PATCH 061/545] add copy and move method --- .../src/main/java/blade/kit/FileKit.java | 97 ++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/blade-kit/src/main/java/blade/kit/FileKit.java b/blade-kit/src/main/java/blade/kit/FileKit.java index a45c3e9c1..4d9511132 100644 --- a/blade-kit/src/main/java/blade/kit/FileKit.java +++ b/blade-kit/src/main/java/blade/kit/FileKit.java @@ -18,11 +18,13 @@ import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLDecoder; +import java.nio.channels.FileChannel; import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -1698,5 +1700,98 @@ public static String getClassFilePath(Class clazz) throws IOException { File file = new File(filePath); return file.getAbsolutePath(); } - + + /** + * 复制单个文件 + * @param sourceFile 准备复制的文件源 + * @param destFile 拷贝到新绝对路径带文件名 + * @return + * @throws IOException + */ + @SuppressWarnings("resource") + public static void copy(String sourceFile, String destFile) throws IOException { + + File source = new File(sourceFile); + if (source.exists()) { + FileChannel inputChannel = null; + FileChannel outputChannel = null; + try { + File dest = new File(destFile); + inputChannel = new FileInputStream(source).getChannel(); + outputChannel = new FileOutputStream(dest).getChannel(); + outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); + } finally { + inputChannel.close(); + outputChannel.close(); + } + } + } + + /** + * 复制整个文件夹的内容 + * @param oldPath 准备拷贝的目录 + * @param newPath 指定绝对路径的新目录 + * @return + */ + @SuppressWarnings("resource") + public static void copyDir(String oldPath, String newPath) { + try { + /**如果文件夹不存在 则建立新文件**/ + new File(newPath).mkdirs(); + File a = new File(oldPath); + String[] file = a.list(); + File temp = null; + for (int i = 0; i < file.length; i++) { + if (oldPath.endsWith(File.separator)) { + temp = new File(oldPath + file[i]); + } else { + temp = new File(oldPath + File.separator + file[i]); + } + if (temp.isFile()) { + + FileChannel inputChannel = null; + FileChannel outputChannel = null; + try { + File dest = new File(newPath + "/" + (temp.getName()).toString()); + inputChannel = new FileInputStream(temp).getChannel(); + outputChannel = new FileOutputStream(dest).getChannel(); + outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); + } finally { + inputChannel.close(); + outputChannel.close(); + } + } + /**如果是子文件**/ + if (temp.isDirectory()) { + copyDir(oldPath + "/" + file[i], newPath + "/" + file[i]); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 移动文件 + * @param oldPath + * @param newPath + * @return + * @throws IOException + */ + public static void moveFile(String oldPath, String newPath) throws IOException { + copy(oldPath, newPath); + delete(oldPath); + } + + /** + * 移动目录 + * @param oldPath + * @param newPath + * @return + */ + public static void moveFolder(String oldPath, String newPath) { + copyDir(oldPath, newPath); + deleteDir(oldPath); + } + } \ No newline at end of file From 8dc2f8234fd390ff15b1378302c40108dbeeaedc Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 4 Aug 2015 15:28:28 +0800 Subject: [PATCH 062/545] before add return value --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ac73a51fb..c85e49951 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.5-alpha + 1.2.5-beta From 74bc0f1ac94a6fcf6410c3b918b48b1d3e75c3f5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 4 Aug 2015 18:23:17 +0800 Subject: [PATCH 063/545] after add return value --- .../src/main/java/blade/RequestHandler.java | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index d866ddde4..bebd32a27 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -122,11 +122,16 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse } HttpMethod httpMethod = HttpMethod.valueOf(method); + boolean isHandler = true; try { // 执行before拦截 - before(requestWrapper, responseWrapper, httpRequest, uri, acceptType); + isHandler = before(requestWrapper, responseWrapper, httpRequest, uri, acceptType); + + if(!isHandler){ + return false; + } // 查找用户请求的uri RouteMatcher match = routeMatcher.findRouteMatcher(httpMethod, uri, acceptType); @@ -155,8 +160,11 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse Object result = executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); // 执行after拦截 - after(requestWrapper, responseWrapper, httpRequest, uri, acceptType); - + isHandler = after(requestWrapper, responseWrapper, httpRequest, uri, acceptType); + if(!isHandler){ + return false; + } + if(null != result){ render(responseWrapper, result); } @@ -196,10 +204,12 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse * @param uri 请求的URI * @param acceptType 请求头过滤 */ - private void before(RequestWrapper requestWrapper, ResponseWrapper responseWrapper, HttpServletRequest httpRequest, final String uri, final String acceptType){ + private boolean before(RequestWrapper requestWrapper, ResponseWrapper responseWrapper, HttpServletRequest httpRequest, final String uri, final String acceptType){ List matchSet = routeMatcher.findInterceptor(HttpMethod.BEFORE, uri, acceptType); + boolean isHandler = true; + for (RouteMatcher filterMatch : matchSet) { Class target = filterMatch.getTarget(); @@ -211,9 +221,16 @@ private void before(RequestWrapper requestWrapper, ResponseWrapper responseWrapp Request request = RequestResponseBuilder.build(filterMatch, httpRequest); requestWrapper.setDelegate(request); - executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); + Object object = executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); + if(null != object && object instanceof Boolean){ + isHandler = (Boolean) object; + if(!isHandler){ + return false; + } + } } + return isHandler; } /** @@ -225,10 +242,11 @@ private void before(RequestWrapper requestWrapper, ResponseWrapper responseWrapp * @param uri 请求的URI * @param acceptType 请求头过滤 */ - private String after(RequestWrapper requestWrapper, ResponseWrapper responseWrapper, HttpServletRequest httpRequest, final String uri, final String acceptType){ + private boolean after(RequestWrapper requestWrapper, ResponseWrapper responseWrapper, HttpServletRequest httpRequest, final String uri, final String acceptType){ List matchSet = routeMatcher.findInterceptor(HttpMethod.AFTER, uri, acceptType); - String bodyContent = null; + boolean isHandler = true; + for (RouteMatcher filterMatch : matchSet) { Class target = filterMatch.getTarget(); @@ -243,15 +261,15 @@ private String after(RequestWrapper requestWrapper, ResponseWrapper responseWrap requestWrapper.initRequest(filterMatch); } - executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); - - String bodyAfterFilter = responseWrapper.getDelegate().body(); - if (bodyAfterFilter != null) { - bodyContent = bodyAfterFilter; - } + Object object = executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); + if(null != object && object instanceof Boolean){ + isHandler = (Boolean) object; + if(!isHandler){ + return false; + } + } } - - return bodyContent; + return isHandler; } /** From 3403fed6531b5e5cd8f6d765bceb1542e76049b4 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 4 Aug 2015 18:29:05 +0800 Subject: [PATCH 064/545] update version --- LAST_VERSION.md | 4 ++-- README.md | 2 +- README_EN.md | 2 +- pom.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index d62a0ef21..4d30ec0b2 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -5,7 +5,7 @@     com.bladejava     blade-kit -    1.2.5-beta +    1.2.5 ``` @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.5-beta +    1.2.5 ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/README.md b/README.md index c0a8de007..0ed18dc47 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ com.bladejava blade-core - 1.2.5-beta + 1.2.5 ``` diff --git a/README_EN.md b/README_EN.md index 07eaccbd7..ef47e2160 100644 --- a/README_EN.md +++ b/README_EN.md @@ -35,7 +35,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.5-beta + 1.2.5 ``` diff --git a/pom.xml b/pom.xml index c85e49951..f6c9aa8f4 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.5-beta + 1.2.5 From 66c8e3ca97841bb3a7c609dfb147050abe2e76d0 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 11:55:40 +0800 Subject: [PATCH 065/545] add a variety of routing configuration --- LAST_VERSION.md | 4 +- README.md | 85 ++++++++----------- README_EN.md | 76 +++++++---------- UPDATE_LOG.md | 42 +++++++++ blade-core/pom.xml | 2 +- blade-core/src/main/java/blade/BladeBase.java | 76 ++++++++++------- .../main/java/blade/BladeConfigurator.java | 3 + .../src/main/java/blade/BladeFilter.java | 18 ++-- .../src/main/java/blade/IocApplication.java | 2 +- .../src/main/java/blade/RequestHandler.java | 8 +- .../java/blade/route/DefaultRouteMatcher.java | 15 +++- .../java/blade/route/RouteMatcherBuilder.java | 53 +++++++++--- .../src/main/java/blade/kit/ReflectKit.java | 13 ++- pom.xml | 2 +- 14 files changed, 235 insertions(+), 164 deletions(-) create mode 100644 UPDATE_LOG.md diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 4d30ec0b2..99f319dd1 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -5,7 +5,7 @@     com.bladejava     blade-kit -    1.2.5 +    1.2.6-alpha ``` @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.5 +    1.2.6-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/README.md b/README.md index 0ed18dc47..ada016ecb 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ com.bladejava blade-core - 1.2.5 + 1.2.6-alpha ``` @@ -67,15 +67,36 @@ public class App extends BladeApplication{ Logger logger = Logger.getLogger(App.class); @Override public void init() { - // 设置路由、拦截器包所在包 - Blade.defaultRoute("blade.sample"); + // 注册函数式路由 + Blade.regRoute("/hello", SayHi.class, "hello"); + + // 匿名路由,java8方式更简化 + Blade.get("/get", new RouteHandler() { + @Override + public String run(Request request, Response response) { + System.out.println("进入get!!"); + System.out.println(request.query("name")); + return "get"; + } + }); } - } ``` - +#### 函数式路由 ```java +public class SayHi { + + public String hello(Request request, Response response){ + System.out.println("进入hello~"); + request.attribute("name", "rose baby"); + return "hi"; + } +} +``` + +#### 控制器路由 +``` @Path("/") public class Hello { @@ -112,61 +133,23 @@ public class Hello { OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: ++ [hello应用](https://github.com/bladejava/hello) + [API docs](http://bladejava.com/apidocs/) + [使用指南](http://bladejava.com/doc/cn/index.html) (完善中...) -+ [一些例子](https://github.com/bladejava) ++ [更多例子](https://github.com/bladejava) ### 计划 1. 完善文档 - 2. 单用户博客系统开发 - 3. 相册系统开发 - 4. 音乐系统开发 - 5. 优化代码性能 + 2. 单用户博客系统 + 3. web聊天系统 + 4. 优化代码性能 -## 更新日志 +### [更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) -### v1.2.5 - 1. 添加JSON、Properties文件配置 - 2. 优化代码性能 - 3. 去除内置jetty服务 - -### v1.2.2 - 1. `DateKit`添加获取当前unix时间戳 - 2. 修复`blade-sql2o`分页bug - 3. 修复`blade-beetl`没有存储`ModelAndView`的数据 - -### v1.2 - 1. 修复sql2o更新Bug - 2. 去除blade-kit无用类 - 3. 添加邮件支持 - 4. 添加程序计时支持 - 5. 添加http网络请求支持 - 6. 优化内置日志输出 - 7. 添加定时任务支持 - 8. 重构项目结构 - -### v1.1.x - 1. 去除对外公开的多余方法展示 - 2. 添加`Blade.run()`方式运行jetty - 3. 添加`Blade.register()`方法注册bean对象 - 4. 优化IOC对象管理 - 5. 优化底层IO - 6. 简化插件扩展 - 7. 拦截器路由匹配分离 - 8. 修复jetty在多maven环境下运行bug - 9. 添加初始化监听context - 10. 优化文件上传 - 11. 优化路由匹配 - 12. 添加方法执行监测 - 13. 添加缓存支持 - -### v1.0.0 - 第一个稳定版本发布 - -## 开源协议 +### 开源协议 Blade框架基于 [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) -## 联系我 +### 联系我 OSC Blog:[http://my.oschina.net/biezhi](http://my.oschina.net/biezhi) Mail: biezhi.me#gmail.com diff --git a/README_EN.md b/README_EN.md index ef47e2160..21b8b9fe1 100644 --- a/README_EN.md +++ b/README_EN.md @@ -35,7 +35,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.5 + 1.2.6-alpha ``` @@ -69,15 +69,37 @@ public class App extends BladeApplication{ Logger logger = Logger.getLogger(App.class); @Override public void init() { - // Set up routing and interceptor bag in bag - Blade.defaultRoute("blade.sample"); + // register route + Blade.regRoute("/hello", SayHi.class, "hello"); + + // anonymous router,java8 so simple + Blade.get("/get", new RouteHandler() { + @Override + public String run(Request request, Response response) { + System.out.println("come get!!"); + System.out.println(request.query("name")); + return "get"; + } + }); } } ``` - +#### Functional routing ```java +public class SayHi { + + public String hello(Request request, Response response){ + System.out.println("come hello~"); + request.attribute("name", "rose baby"); + return "hi"; + } +} +``` + +#### The controller routing +``` @Path("/") public class Hello { @@ -114,6 +136,7 @@ public class Hello { OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: ++ [hello project](https://github.com/bladejava/hello) + [API Docs](http://bladejava.com/apidocs/) + [Use Guide](http://bladejava.com/doc/cn/index.html) (The ongoing...) + [Some Examples](https://github.com/bladejava) @@ -121,49 +144,10 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ### Plan 1. Improve the document 2. Single user blog system development - 3. The photo album system development - 4. Music system development - 5. Optimize the code performance - -### Update - -### v1.2.5 - 1. Add JSON, configuration Properties file - 2. Optimize the code performance - 3. Remove inlay Jetty Server - -### v1.2.2 - 1. `DateKit` added to obtain the current Unix timestamp - 2. fix `blade-sql2o` paging bug - 3. fix `blade-beetl` not stored `ModelAndView` data - -### v1.2 - 1. Update Bug fix sql2o - 2. Remove the blade-kit useless class - 3. Add email support - 4. Add a program timing - 5. Add the HTTP request support network - 6. Optimization of the built-in logging output - 7. Add tasks to support regularly - 8. Reconstruction project structure + 3. web chat system + 4. Optimize the code performance -### v1.1.x - 1. Remove excess public methods - 2. Add the `Blade.run()` run jetty - 3. Add the `Blade.register()` method register bean object - 4. Optimize the ioc object management - 5. Add initialization to monitor the context - 6. Optimize the underlying IO - 7. Simplify the plug-in extension - 8. Matching vehicle routing separation - 9. Repair jetty in running maven environment more bugs - 10. Optimize the file upload - 11. Optimized matching routing - 12. Add methods perform monitoring - 13. Add cache support - -### v1.0.0 - The first stable release +### [Update](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) ## licenses Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md new file mode 100644 index 000000000..3dda8eb1a --- /dev/null +++ b/UPDATE_LOG.md @@ -0,0 +1,42 @@ +#Blade 更新日志 + +### v1.2.6 + 1. 添加多重路由配置方式 + +### v1.2.5 + 1. 添加JSON、Properties文件配置 + 2. 优化代码性能 + 3. 去除内置jetty服务 + +### v1.2.2 + 1. `DateKit`添加获取当前unix时间戳 + 2. 修复`blade-sql2o`分页bug + 3. 修复`blade-beetl`没有存储`ModelAndView`的数据 + +### v1.2 + 1. 修复sql2o更新Bug + 2. 去除blade-kit无用类 + 3. 添加邮件支持 + 4. 添加程序计时支持 + 5. 添加http网络请求支持 + 6. 优化内置日志输出 + 7. 添加定时任务支持 + 8. 重构项目结构 + +### v1.1.x + 1. 去除对外公开的多余方法展示 + 2. 添加`Blade.run()`方式运行jetty + 3. 添加`Blade.register()`方法注册bean对象 + 4. 优化IOC对象管理 + 5. 优化底层IO + 6. 简化插件扩展 + 7. 拦截器路由匹配分离 + 8. 修复jetty在多maven环境下运行bug + 9. 添加初始化监听context + 10. 优化文件上传 + 11. 优化路由匹配 + 12. 添加方法执行监测 + 13. 添加缓存支持 + +### v1.0.0 + 第一个稳定版本发布 \ No newline at end of file diff --git a/blade-core/pom.xml b/blade-core/pom.xml index fe68e7079..5de2c6827 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -19,7 +19,7 @@ com.bladejava blade-kit - 1.2.4 + 1.2.6-alpha javax.servlet diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index 6e954c7ad..e5b00bb4f 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -26,7 +26,9 @@ import blade.kit.json.JSONKit; import blade.render.Render; import blade.render.RenderFactory; -import blade.route.DefaultRouteMatcher; +import blade.route.HttpMethod; +import blade.route.RouteHandler; +import blade.route.RouteMatcherBuilder; /** * Blade的基础类 @@ -36,13 +38,6 @@ */ abstract class BladeBase { - protected static final String DEFAULT_ACCEPT_TYPE = "*/*"; - - /** - * 是否以jetty方式运行 - */ - public static boolean runJetty = false; - /** * 框架是否已经初始化 */ @@ -52,16 +47,6 @@ abstract class BladeBase { * blade全局初始化对象,在web.xml中配置,必须 */ protected static BladeApplication bladeApplication; - - /** - * 路由匹配器,用于添加,删除,查找路由 - */ - protected static DefaultRouteMatcher routeMatcher; - - /** - * jetty启动的默认端口 - */ - protected static int PORT = 9000; /** * 全局配置对象 @@ -175,20 +160,6 @@ public static synchronized void staticFolder(final String ... folders) { BLADE_CONFIG.setStaticFolders(folders); } - /** - * 动态设置全局初始化类 - * - * @param clazz 全局初始化Class - */ - public static synchronized void app(Class clazz){ - try { - BladeBase.bladeApplication = clazz.newInstance(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } /** * 动态设置全局初始化类 * @@ -231,9 +202,48 @@ public static synchronized void webRoot(final String webRoot){ */ public static synchronized void debug(boolean isdebug){ BLADE_CONFIG.setDebug(isdebug); -// BladeBase.DEBUG = isdebug; } + /** + * 注册一个函数式的路由 + * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + */ + public static synchronized void regRoute(String path, Class clazz, String methodName){ + RouteMatcherBuilder.buildFunctional(path, clazz, methodName, null); + } + + /** + * 注册一个函数式的路由 + * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + * @param httpMethod 请求类型,GET/POST + */ + public static synchronized void regRoute(String path, Class clazz, String methodName, HttpMethod httpMethod){ + RouteMatcherBuilder.buildFunctional(path, clazz, methodName, httpMethod); + } + + /** + * GET请求 + * @param path + * @param routeHandler + */ + public static synchronized void get(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.GET); + } + + /** + * POST请求 + * @param path + * @param routeHandler + */ + public static synchronized void post(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.POST); + } + + /**--------------------SET CONST:END-------------------------*/ diff --git a/blade-core/src/main/java/blade/BladeConfigurator.java b/blade-core/src/main/java/blade/BladeConfigurator.java index f95c06688..68f6edeaf 100644 --- a/blade-core/src/main/java/blade/BladeConfigurator.java +++ b/blade-core/src/main/java/blade/BladeConfigurator.java @@ -57,6 +57,9 @@ public BladeConfigurator(BladeConfig bladeConfig, public void run() { if (null != configMap && configMap.size() > 0) { + + bladeConfig.setConfigMap(configMap); + String route = configMap.get(BLADE_ROUTE); String interceptor = configMap.get(BLADE_INTERCEPTOR); String ioc = configMap.get(BLADE_IOC); diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java index 3ab762209..d268011a2 100644 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ b/blade-core/src/main/java/blade/BladeFilter.java @@ -60,10 +60,9 @@ public void init(FilterConfig filterConfig) throws ServletException { application.init(); Blade.app(application); - // 构建所有路由 - RequestHandler.routeMatcher = RouteMatcherBuilder.building(); + // 构建路由 + RouteMatcherBuilder.building(); - // 全局初始化 IocApplication.init(); application.contextInitialized(BladeWebContext.servletContext()); @@ -86,16 +85,21 @@ public void init(FilterConfig filterConfig) throws ServletException { * @throws ServletException */ private BladeApplication getApplication(FilterConfig filterConfig) throws ServletException { + BladeApplication bladeApplication = null; try { String applicationClassName = filterConfig.getInitParameter(APPLCATION_CLASS); - if(!BladeBase.runJetty && null != applicationClassName){ + if(null != applicationClassName){ Class applicationClass = Class.forName(applicationClassName); - return (BladeApplication) applicationClass.newInstance(); - } - return BladeBase.bladeApplication; + if(null != applicationClass){ + bladeApplication = (BladeApplication) applicationClass.newInstance(); + } + } else { + throw new ServletException("applicationClass is null !"); + } } catch (Exception e) { throw new ServletException(e); } + return bladeApplication; } @Override diff --git a/blade-core/src/main/java/blade/IocApplication.java b/blade-core/src/main/java/blade/IocApplication.java index f56fa7387..2e57fbb2d 100644 --- a/blade-core/src/main/java/blade/IocApplication.java +++ b/blade-core/src/main/java/blade/IocApplication.java @@ -119,4 +119,4 @@ public static void destroy() { container.removeAll(); } -} +} \ No newline at end of file diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index bebd32a27..068aa6043 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -63,7 +63,7 @@ public class RequestHandler { /** * 路由处理器,查找请求过来的URL */ - static DefaultRouteMatcher routeMatcher; + private static DefaultRouteMatcher defaultRouteMatcher = DefaultRouteMatcher.instance(); private RequestHandler(){} @@ -134,7 +134,7 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse } // 查找用户请求的uri - RouteMatcher match = routeMatcher.findRouteMatcher(httpMethod, uri, acceptType); + RouteMatcher match = defaultRouteMatcher.findRouteMatcher(httpMethod, uri, acceptType); // 如果找到 if (match != null) { @@ -206,7 +206,7 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse */ private boolean before(RequestWrapper requestWrapper, ResponseWrapper responseWrapper, HttpServletRequest httpRequest, final String uri, final String acceptType){ - List matchSet = routeMatcher.findInterceptor(HttpMethod.BEFORE, uri, acceptType); + List matchSet = defaultRouteMatcher.findInterceptor(HttpMethod.BEFORE, uri, acceptType); boolean isHandler = true; @@ -243,7 +243,7 @@ private boolean before(RequestWrapper requestWrapper, ResponseWrapper responseWr * @param acceptType 请求头过滤 */ private boolean after(RequestWrapper requestWrapper, ResponseWrapper responseWrapper, HttpServletRequest httpRequest, final String uri, final String acceptType){ - List matchSet = routeMatcher.findInterceptor(HttpMethod.AFTER, uri, acceptType); + List matchSet = defaultRouteMatcher.findInterceptor(HttpMethod.AFTER, uri, acceptType); boolean isHandler = true; diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index 0b3cf0d22..595843533 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -38,16 +38,23 @@ public class DefaultRouteMatcher { private static final Logger LOGGER = Logger.getLogger(DefaultRouteMatcher.class); + private static final DefaultRouteMatcher DEFAULT_ROUTE_MATCHER = new DefaultRouteMatcher(); + // 存储所有路由 private List routes; + // 存储所有拦截器 private List interceptors; - public DefaultRouteMatcher() { + private DefaultRouteMatcher() { routes = CollectionKit.newArrayList(); interceptors = CollectionKit.newArrayList(); } - + + public static DefaultRouteMatcher instance(){ + return DEFAULT_ROUTE_MATCHER; + } + /** * 查询是否有路由 * @@ -60,7 +67,7 @@ public RouteMatcher findRouteMatcher(HttpMethod httpMethod, String uri, String a uri = (uri.length() > 1 && uri.endsWith("/")) ? uri.substring(0, uri.length() - 1) : uri; - List routeEntries = this.findRouteMatcher(httpMethod, uri); + List routeEntries = DEFAULT_ROUTE_MATCHER.findRouteMatcher(httpMethod, uri); // 优先匹配原则 giveMatch(uri, routeEntries); @@ -96,7 +103,7 @@ public List findInterceptor(HttpMethod httpMethod, String uri, Str uri = uri.endsWith("/") ? uri.substring(0, uri.length() - 1) : uri; } List matchSet = CollectionKit.newArrayList(); - List routeEntries = this.findInterceptor(httpMethod, uri); + List routeEntries = DEFAULT_ROUTE_MATCHER.findInterceptor(httpMethod, uri); for (RouteMatcher routeEntry : routeEntries) { if (acceptType != null) { diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index 51499a9cd..51997eac0 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -24,8 +24,10 @@ import blade.annotation.Interceptor; import blade.annotation.Path; import blade.annotation.Route; +import blade.exception.BladeException; import blade.ioc.Container; import blade.ioc.DefaultContainer; +import blade.kit.ReflectKit; import blade.kit.StringKit; import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; @@ -41,7 +43,7 @@ public final class RouteMatcherBuilder { private static final Logger LOGGER = Logger.getLogger(RouteMatcherBuilder.class); - private static DefaultRouteMatcher routeMatcher = null; + private static DefaultRouteMatcher defaultRouteMatcher = DefaultRouteMatcher.instance(); /** * 默认路由后缀包,用户扫描路由所在位置,默认为route,用户可自定义 @@ -71,15 +73,7 @@ private RouteMatcherBuilder() { * * @return 返回构建路由后的构造器 */ - public static synchronized DefaultRouteMatcher building() { - - if (routeMatcher != null) { - routeMatcher.clearRoutes(); - routeMatcher = null; - } - - routeMatcher = new DefaultRouteMatcher(); - + public static synchronized void building() { if(Blade.debug()){ LOGGER.debug("creates RouteMatcher"); } @@ -112,7 +106,40 @@ public static synchronized DefaultRouteMatcher building() { buildInterceptor(interceptorPackage); } } - return routeMatcher; + } + + /** + * 函数式路由构建 + */ + public static void buildFunctional(String path, Class clazz, String methodName, HttpMethod httpMethod){ + if(StringKit.isNotBlank(path) && null != clazz && StringKit.isNotBlank(methodName)){ + if(null == httpMethod){ + httpMethod = HttpMethod.ALL; + } + // 查找 + Object target = container.getBean(clazz, null); + if(null == target){ + container.registBean(clazz); + } + Method execMethod = ReflectKit.getMethodByName(clazz, methodName); + defaultRouteMatcher.addRoute(clazz, execMethod, path, httpMethod, "*/*"); + } else { + throw new BladeException("an unqualified configuration"); + } + } + + /** + * Handler路由构建 + */ + public static void buildHandler(String path, RouteHandler routeHandler, HttpMethod httpMethod){ + if(StringKit.isNotBlank(path) && null != routeHandler){ + Class clazz = RouteHandler.class; + container.registBean(routeHandler); + Method execMethod = ReflectKit.getMethodByName(clazz, "run"); + defaultRouteMatcher.addRoute(clazz, execMethod, path, httpMethod, "*/*"); + } else { + throw new BladeException("an unqualified configuration"); + } } /** @@ -263,7 +290,7 @@ private static void parseRouter(final Class router){ * @param acceptType 路由acceptType */ private static void buildRoute(Class target, Method execMethod, String path, HttpMethod method, String acceptType){ - routeMatcher.addRoute(target, execMethod, path, method, acceptType); + defaultRouteMatcher.addRoute(target, execMethod, path, method, acceptType); } /** @@ -276,7 +303,7 @@ private static void buildRoute(Class target, Method execMethod, String path, * @param acceptType 路由acceptType */ private static void buildInterceptor(Class target, Method execMethod, String path, HttpMethod method, String acceptType){ - routeMatcher.addInterceptor(target, execMethod, path, method, acceptType); + defaultRouteMatcher.addInterceptor(target, execMethod, path, method, acceptType); } } diff --git a/blade-kit/src/main/java/blade/kit/ReflectKit.java b/blade-kit/src/main/java/blade/kit/ReflectKit.java index 6a4cb812a..be9c117c0 100644 --- a/blade-kit/src/main/java/blade/kit/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/ReflectKit.java @@ -128,7 +128,18 @@ public static Method getMethodByName(Object classOrBean, String methodName) { } return ret; } - + + public static Method getMethodByName(Class clazz, String methodName) { + Method ret = null; + for (Method method : clazz.getMethods()) { + if (method.getName().equals(methodName)) { + ret = method; + break; + } + } + return ret; + } + /** * * @param bean 类实例 diff --git a/pom.xml b/pom.xml index f6c9aa8f4..6a3fbcb96 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.5 + 1.2.6-alpha From aafcad68919af62d27f529df2d0be10832aa81b0 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 12:07:07 +0800 Subject: [PATCH 066/545] update blade-kit pom --- blade-kit/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index f29301b07..ff99b5f67 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - 1.2.4 + 1.2.6-alpha blade-kit https://github.com/biezhi/blade/tree/master/blade-kit From f7e0cff6e39c2e3673345888221f9dc9958c1985 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 12:09:30 +0800 Subject: [PATCH 067/545] update pom.xml --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 6a3fbcb96..e3093266d 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,7 @@ junit junit ${junit.version} + test javax.servlet From 8126757a250ad4057256a0e09511559427f86441 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 13:40:47 +0800 Subject: [PATCH 068/545] add the routing configuration mode --- blade-core/src/main/java/blade/BladeBase.java | 64 +++++++++++++++++-- .../java/blade/route/RouteMatcherBuilder.java | 24 ++++++- 2 files changed, 81 insertions(+), 7 deletions(-) diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index e5b00bb4f..8342fa2fd 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -205,7 +205,10 @@ public static synchronized void debug(boolean isdebug){ } /** - * 注册一个函数式的路由 + * 注册一个函数式的路由
+ *

+ * 方法上指定请求类型,如:post:signin + *

* @param path 路由url * @param clazz 路由处理类 * @param methodName 路由处理方法名称 @@ -226,7 +229,7 @@ public static synchronized void regRoute(String path, Class clazz, String met } /** - * GET请求 + * get请求 * @param path * @param routeHandler */ @@ -235,7 +238,7 @@ public static synchronized void get(String path, RouteHandler routeHandler){ } /** - * POST请求 + * post请求 * @param path * @param routeHandler */ @@ -243,6 +246,59 @@ public static synchronized void post(String path, RouteHandler routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.POST); } + /** + * delete请求 + * @param path + * @param routeHandler + */ + public static synchronized void delete(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.DELETE); + } + + /** + * put请求 + * @param path + * @param routeHandler + */ + public static synchronized void put(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.PUT); + } + + /** + * patch请求 + * @param path + * @param routeHandler + */ + public static synchronized void patch(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.PATCH); + } + + /** + * head请求 + * @param path + * @param routeHandler + */ + public static synchronized void head(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.HEAD); + } + + /** + * trace请求 + * @param path + * @param routeHandler + */ + public static synchronized void trace(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.TRACE); + } + + /** + * options请求 + * @param path + * @param routeHandler + */ + public static synchronized void options(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.OPTIONS); + } /**--------------------SET CONST:END-------------------------*/ @@ -355,7 +411,7 @@ public static BladeApplication application(){ * * @param object 要注册的object */ - public static synchronized void register(Object object){ + public static synchronized void regObject(Object object){ container.registBean(object); } diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index 51997eac0..f481c9619 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -113,15 +113,26 @@ public static synchronized void building() { */ public static void buildFunctional(String path, Class clazz, String methodName, HttpMethod httpMethod){ if(StringKit.isNotBlank(path) && null != clazz && StringKit.isNotBlank(methodName)){ + + // 字符串上写请求 get:hello + if(methodName.indexOf(":") != -1){ + String[] methodArr = StringKit.split(methodName, ":"); + httpMethod = getHttpMethod(methodArr[0]); + methodName = methodArr[1]; + } + if(null == httpMethod){ httpMethod = HttpMethod.ALL; } + // 查找 Object target = container.getBean(clazz, null); if(null == target){ container.registBean(clazz); } + Method execMethod = ReflectKit.getMethodByName(clazz, methodName); + defaultRouteMatcher.addRoute(clazz, execMethod, path, httpMethod, "*/*"); } else { throw new BladeException("an unqualified configuration"); @@ -252,10 +263,10 @@ private static void parseRouter(final Class router){ return; } + container.registBean(router); + final String nameSpace = router.getAnnotation(Path.class).value(); - container.registBean(router); - for (Method method : methods) { Route mapping = method.getAnnotation(Route.class); @@ -264,7 +275,6 @@ private static void parseRouter(final Class router){ if (null != mapping) { ////构建路由 - String path = mapping.value().startsWith("/") ? mapping.value() : "/" + mapping.value(); path = nameSpace + path; path = path.replaceAll("[/]+", "/"); @@ -306,4 +316,12 @@ private static void buildInterceptor(Class target, Method execMethod, String defaultRouteMatcher.addInterceptor(target, execMethod, path, method, acceptType); } + private static HttpMethod getHttpMethod(String name){ + try { + return Enum.valueOf(HttpMethod.class, name.toUpperCase()); + } catch (Exception e) { + LOGGER.error("HttpMethod conversion failure", e); + } + return null; + } } From 85623eeca6ccf5bc8425352d50fe4004eca7ea8f Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 16:16:09 +0800 Subject: [PATCH 069/545] update readme --- README.md | 2 +- README_EN.md | 2 +- blade-core/src/main/java/blade/route/RouteHandler.java | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 blade-core/src/main/java/blade/route/RouteHandler.java diff --git a/README.md b/README.md index ada016ecb..9441fec3c 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 + [hello应用](https://github.com/bladejava/hello) + [API docs](http://bladejava.com/apidocs/) -+ [使用指南](http://bladejava.com/doc/cn/index.html) (完善中...) ++ [使用指南](https://github.com/biezhi/blade/wiki) (完善中...) + [更多例子](https://github.com/bladejava) ### 计划 diff --git a/README_EN.md b/README_EN.md index 21b8b9fe1..d2c6d51b4 100644 --- a/README_EN.md +++ b/README_EN.md @@ -138,7 +138,7 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex + [hello project](https://github.com/bladejava/hello) + [API Docs](http://bladejava.com/apidocs/) -+ [Use Guide](http://bladejava.com/doc/cn/index.html) (The ongoing...) ++ [Use Guide](https://github.com/biezhi/blade/wiki) (The ongoing...) + [Some Examples](https://github.com/bladejava) ### Plan diff --git a/blade-core/src/main/java/blade/route/RouteHandler.java b/blade-core/src/main/java/blade/route/RouteHandler.java new file mode 100644 index 000000000..b06081e2b --- /dev/null +++ b/blade-core/src/main/java/blade/route/RouteHandler.java @@ -0,0 +1,10 @@ +package blade.route; + +import blade.servlet.Request; +import blade.servlet.Response; + +public interface RouteHandler { + + public String run(Request request, Response response); + +} From 60f7b8ec84cb53ad571049754e88bdbf8a5c7cdc Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 16:22:48 +0800 Subject: [PATCH 070/545] update readme --- README.md | 88 ++++++++++++++-------------- README_EN.md | 161 --------------------------------------------------- 2 files changed, 46 insertions(+), 203 deletions(-) delete mode 100644 README_EN.md diff --git a/README.md b/README.md index 9441fec3c..d2c6d51b4 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ #Blade -[![简洁强大的JavaWeb框架](http://i1.tietuku.com/0c4b9726253b6268.png "简洁强大的JavaWeb框架")](http://bladejava.com) +[![a concise and powerful web development framework](http://i1.tietuku.com/0c4b9726253b6268.png "a concise and powerful web development framework")](http://bladejava.com) -[English](https://github.com/biezhi/blade/blob/master/README_EN.md) +[中文](https://github.com/biezhi/blade/blob/master/README.md) [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) @@ -10,24 +10,26 @@ [![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -**blade** 是一个简洁强大的web框架,它内置了`IOC`管理,拦截器配置,`REST API`开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送等常用功能,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! +## Introduction -## Blade特性 +**blade** Is a concise and powerful web development framework, it is built into the `IOC` administration, the interceptor configuration, `REST API` development and so on many mainstream web features, integrate the template engine, a cache plug-in, database operations, commonly used functions such as email, concise source deserves your reading. If you like it, can be `Star or Fork`, thanks! -* 简洁的MVC & 拦截器 -* REST风格API -* 注解方式 开发 -* 微内核IOC容器 -* 实用工具类 -* 模板引擎支持 -* 支持JDK1.6+ -* 插件扩展机制 -* 缓存数据信息 -* 编码/JSON/配置文件 +## Features + +* Simple MVC & Interceptor +* REST API +* Annotation way development +* The microkernel IOC container +* Utility class +* A template engine support +* Support JDK1.6 + +* Plug-in extension mechanism +* Cache the data information +* Coding/JSON/config file * ... -## 快速入门 -第一步、用maven构建一个webapp,加入blade的依赖,推荐获取[最新版本](LAST_VERSION.md) +## Quick start +First. Use maven to build a webapp, join dependency on the blade,Recommended for the [latest version](LAST_VERSION.md) ```xml @@ -37,7 +39,7 @@ ``` -第二步、在`web.xml`中配置Blade核心过滤器并设置你的初始化类,你也可以不配置(使用jetty启动) +Second. Configuration in the `web.xml` Blade core filter initialization and set your class, and you can also not configuration(using jetty start) ```xml @@ -59,7 +61,7 @@ ``` -第三步、编写App.java和路由文件,下面是一个示例 +Third. Write App.java and routing file, here is an example ```java public class App extends BladeApplication{ @@ -67,35 +69,36 @@ public class App extends BladeApplication{ Logger logger = Logger.getLogger(App.class); @Override public void init() { - // 注册函数式路由 + // register route Blade.regRoute("/hello", SayHi.class, "hello"); - // 匿名路由,java8方式更简化 + // anonymous router,java8 so simple Blade.get("/get", new RouteHandler() { @Override public String run(Request request, Response response) { - System.out.println("进入get!!"); + System.out.println("come get!!"); System.out.println(request.query("name")); return "get"; } }); } + } ``` -#### 函数式路由 +#### Functional routing ```java public class SayHi { public String hello(Request request, Response response){ - System.out.println("进入hello~"); + System.out.println("come hello~"); request.attribute("name", "rose baby"); return "hi"; } } ``` -#### 控制器路由 +#### The controller routing ``` @Path("/") public class Hello { @@ -131,27 +134,28 @@ public class Hello { } ``` -OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: - -+ [hello应用](https://github.com/bladejava/hello) -+ [API docs](http://bladejava.com/apidocs/) -+ [使用指南](https://github.com/biezhi/blade/wiki) (完善中...) -+ [更多例子](https://github.com/bladejava) - -### 计划 - 1. 完善文档 - 2. 单用户博客系统 - 3. web聊天系统 - 4. 优化代码性能 - -### [更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) +OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: + ++ [hello project](https://github.com/bladejava/hello) ++ [API Docs](http://bladejava.com/apidocs/) ++ [Use Guide](https://github.com/biezhi/blade/wiki) (The ongoing...) ++ [Some Examples](https://github.com/bladejava) + +### Plan + 1. Improve the document + 2. Single user blog system development + 3. web chat system + 4. Optimize the code performance + +### [Update](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## licenses +Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) -### 开源协议 -Blade框架基于 [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) +## Contact -### 联系我 OSC Blog:[http://my.oschina.net/biezhi](http://my.oschina.net/biezhi) Mail: biezhi.me#gmail.com -Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) +QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) \ No newline at end of file diff --git a/README_EN.md b/README_EN.md deleted file mode 100644 index d2c6d51b4..000000000 --- a/README_EN.md +++ /dev/null @@ -1,161 +0,0 @@ -#Blade - -[![a concise and powerful web development framework](http://i1.tietuku.com/0c4b9726253b6268.png "a concise and powerful web development framework")](http://bladejava.com) - -[中文](https://github.com/biezhi/blade/blob/master/README.md) - -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) -[![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) -[![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) -[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) -[![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) - -## Introduction - -**blade** Is a concise and powerful web development framework, it is built into the `IOC` administration, the interceptor configuration, `REST API` development and so on many mainstream web features, integrate the template engine, a cache plug-in, database operations, commonly used functions such as email, concise source deserves your reading. If you like it, can be `Star or Fork`, thanks! - -## Features - -* Simple MVC & Interceptor -* REST API -* Annotation way development -* The microkernel IOC container -* Utility class -* A template engine support -* Support JDK1.6 + -* Plug-in extension mechanism -* Cache the data information -* Coding/JSON/config file -* ... - -## Quick start -First. Use maven to build a webapp, join dependency on the blade,Recommended for the [latest version](LAST_VERSION.md) - -```xml - - com.bladejava - blade-core - 1.2.6-alpha - -``` - -Second. Configuration in the `web.xml` Blade core filter initialization and set your class, and you can also not configuration(using jetty start) - -```xml - - Archetype Created Web Application - - BladeFilter - blade.BladeFilter - - applicationClass - blade.sample.App - - - - - BladeFilter - /* - - - -``` - -Third. Write App.java and routing file, here is an example - -```java -public class App extends BladeApplication{ - - Logger logger = Logger.getLogger(App.class); - @Override - public void init() { - // register route - Blade.regRoute("/hello", SayHi.class, "hello"); - - // anonymous router,java8 so simple - Blade.get("/get", new RouteHandler() { - @Override - public String run(Request request, Response response) { - System.out.println("come get!!"); - System.out.println(request.query("name")); - return "get"; - } - }); - } - -} -``` - -#### Functional routing -```java -public class SayHi { - - public String hello(Request request, Response response){ - System.out.println("come hello~"); - request.attribute("name", "rose baby"); - return "hi"; - } -} -``` - -#### The controller routing -``` -@Path("/") -public class Hello { - - @Route("hello") - public String hello() { - System.out.println("hello"); - return "hello.jsp"; - } - - @Route(value = "post", method = HttpMethod.POST) - public void post(Request request) { - String name = request.query("name"); - System.out.println("name = " + name); - } - - @Route("users/:name") - public ModelAndView users(Request request, Response response) { - System.out.println("users"); - String name = request.pathParam(":name"); - - ModelAndView modelAndView = new ModelAndView("users"); - modelAndView.add("name", name); - return modelAndView; - } - - @Route("index") - public String index(Request request) { - request.attribute("name", "jack"); - return "index.jsp"; - } - -} -``` - -OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: - -+ [hello project](https://github.com/bladejava/hello) -+ [API Docs](http://bladejava.com/apidocs/) -+ [Use Guide](https://github.com/biezhi/blade/wiki) (The ongoing...) -+ [Some Examples](https://github.com/bladejava) - -### Plan - 1. Improve the document - 2. Single user blog system development - 3. web chat system - 4. Optimize the code performance - -### [Update](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## licenses -Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) - -## Contact - -OSC Blog:[http://my.oschina.net/biezhi](http://my.oschina.net/biezhi) - -Mail: biezhi.me#gmail.com - -QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) \ No newline at end of file From 316cc04bc00d5c499bc3ff1cbb07e41ad0408694 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 16:29:13 +0800 Subject: [PATCH 071/545] update readme --- README.md | 18 +++--- README_CN.md | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 README_CN.md diff --git a/README.md b/README.md index d2c6d51b4..39c3c33d6 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,16 @@ ## Features -* Simple MVC & Interceptor -* REST API -* Annotation way development -* The microkernel IOC container -* Utility class -* A template engine support -* Support JDK1.6 + +* Simple MVC & interceptor +* RESTful +* Multiple routing configuration +* Micro kernel IOC container +* Practical tools +* Coding/JSON/configuration file +* JDK1.6 + * Plug-in extension mechanism -* Cache the data information -* Coding/JSON/config file +* Template engine Plugin +* Cache Plugin * ... ## Quick start diff --git a/README_CN.md b/README_CN.md new file mode 100644 index 000000000..ae503c98e --- /dev/null +++ b/README_CN.md @@ -0,0 +1,157 @@ +#Blade + +[![简洁强大的JavaWeb框架](http://i1.tietuku.com/0c4b9726253b6268.png "简洁强大的JavaWeb框架")](http://bladejava.com) + +[English](https://github.com/biezhi/blade/blob/master/README_EN.md) + +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) +[![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) +[![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) +[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) +[![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) + +**blade** 是一个简洁强大的web框架,它内置了`IOC`管理,拦截器配置,`REST API`开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送等常用功能,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! + +## Blade特性 + +* 简洁的MVC & 拦截器 +* RESTful +* 多种路由配置方式 +* 微内核IOC容器 +* 实用工具类 +* 编码/JSON/配置文件 +* 模板引擎支持 +* 支持JDK1.6+ +* 插件扩展机制 +* 缓存支持 +* ... + +## 快速入门 +第一步、用maven构建一个webapp,加入blade的依赖,推荐获取[最新版本](LAST_VERSION.md) + +```xml + + com.bladejava + blade-core + 1.2.6-alpha + +``` + +第二步、在`web.xml`中配置Blade核心过滤器并设置你的初始化类,你也可以不配置(使用jetty启动) + +```xml + + Archetype Created Web Application + + BladeFilter + blade.BladeFilter + + applicationClass + blade.sample.App + + + + + BladeFilter + /* + + + +``` + +第三步、编写App.java和路由文件,下面是一个示例 + +```java +public class App extends BladeApplication{ + + Logger logger = Logger.getLogger(App.class); + @Override + public void init() { + // 注册函数式路由 + Blade.regRoute("/hello", SayHi.class, "hello"); + + // 匿名路由,java8方式更简化 + Blade.get("/get", new RouteHandler() { + @Override + public String run(Request request, Response response) { + System.out.println("进入get!!"); + System.out.println(request.query("name")); + return "get"; + } + }); + } +} +``` + +#### 函数式路由 +```java +public class SayHi { + + public String hello(Request request, Response response){ + System.out.println("进入hello~"); + request.attribute("name", "rose baby"); + return "hi"; + } +} +``` + +#### 控制器路由 +``` +@Path("/") +public class Hello { + + @Route("hello") + public String hello() { + System.out.println("hello"); + return "hello.jsp"; + } + + @Route(value = "post", method = HttpMethod.POST) + public void post(Request request) { + String name = request.query("name"); + System.out.println("name = " + name); + } + + @Route("users/:name") + public ModelAndView users(Request request, Response response) { + System.out.println("users"); + String name = request.pathParam(":name"); + + ModelAndView modelAndView = new ModelAndView("users"); + modelAndView.add("name", name); + return modelAndView; + } + + @Route("index") + public String index(Request request) { + request.attribute("name", "jack"); + return "index.jsp"; + } + +} +``` + +OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: + ++ [hello应用](https://github.com/bladejava/hello) ++ [API docs](http://bladejava.com/apidocs/) ++ [使用指南](https://github.com/biezhi/blade/wiki) (完善中...) ++ [更多例子](https://github.com/bladejava) + +### 计划 + 1. 完善文档 + 2. 单用户博客系统 + 3. web聊天系统 + 4. 优化代码性能 + +### [更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +### 开源协议 +Blade框架基于 [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) + +### 联系我 +OSC Blog:[http://my.oschina.net/biezhi](http://my.oschina.net/biezhi) + +Mail: biezhi.me#gmail.com + +Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) From 1b5fee643f1a6dc432b9843223d29603e0a06f63 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 16:30:47 +0800 Subject: [PATCH 072/545] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 39c3c33d6..b42a62aa6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![a concise and powerful web development framework](http://i1.tietuku.com/0c4b9726253b6268.png "a concise and powerful web development framework")](http://bladejava.com) -[中文](https://github.com/biezhi/blade/blob/master/README.md) +[中文](https://github.com/biezhi/blade/blob/master/README_CN.md) [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) From 740a0548349b8f47de1326839f6e748c7a5e64a9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 16:32:57 +0800 Subject: [PATCH 073/545] update readme --- README.md | 6 +++--- README_CN.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b42a62aa6..cdbaacffe 100644 --- a/README.md +++ b/README.md @@ -137,9 +137,9 @@ public class Hello { OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: + [hello project](https://github.com/bladejava/hello) -+ [API Docs](http://bladejava.com/apidocs/) -+ [Use Guide](https://github.com/biezhi/blade/wiki) (The ongoing...) -+ [Some Examples](https://github.com/bladejava) ++ [api docs](http://bladejava.com/apidocs/) ++ [user guide](https://github.com/biezhi/blade/wiki) (The ongoing...) ++ [some examples](https://github.com/bladejava) ### Plan 1. Improve the document diff --git a/README_CN.md b/README_CN.md index ae503c98e..e9c9d1b89 100644 --- a/README_CN.md +++ b/README_CN.md @@ -133,8 +133,8 @@ public class Hello { OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: -+ [hello应用](https://github.com/bladejava/hello) -+ [API docs](http://bladejava.com/apidocs/) ++ [hello](https://github.com/bladejava/hello) ++ [api docs](http://bladejava.com/apidocs/) + [使用指南](https://github.com/biezhi/blade/wiki) (完善中...) + [更多例子](https://github.com/bladejava) From 91ae4106473049f41ec9d3ca5de9bed0ae6b05ca Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 17:44:28 +0800 Subject: [PATCH 074/545] update method name --- blade-core/src/main/java/blade/BladeWebContext.java | 2 +- blade-core/src/main/java/blade/RequestHandler.java | 2 +- blade-core/src/main/java/blade/servlet/Request.java | 4 ++++ blade-core/src/main/java/blade/wrapper/RequestWrapper.java | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/blade-core/src/main/java/blade/BladeWebContext.java b/blade-core/src/main/java/blade/BladeWebContext.java index 0d7033787..51f79ea1f 100644 --- a/blade-core/src/main/java/blade/BladeWebContext.java +++ b/blade-core/src/main/java/blade/BladeWebContext.java @@ -122,7 +122,7 @@ public static ServletContext servletContext() { * @param requestWrapper RequestWrapper对象 * @param responseWrapper ResponseWrapper对象 */ - public static void put(RequestWrapper requestWrapper, ResponseWrapper responseWrapper) { + public static void init(RequestWrapper requestWrapper, ResponseWrapper responseWrapper) { remove(); currentRequest.set(requestWrapper); currentResponse.set(responseWrapper); diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 068aa6043..5412cf0ae 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -154,7 +154,7 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse } requestWrapper.setDelegate(request); - BladeWebContext.put(requestWrapper, responseWrapper); + BladeWebContext.init(requestWrapper, responseWrapper); // 执行route方法 Object result = executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); diff --git a/blade-core/src/main/java/blade/servlet/Request.java b/blade-core/src/main/java/blade/servlet/Request.java index 3d4c644f2..60a59b433 100644 --- a/blade-core/src/main/java/blade/servlet/Request.java +++ b/blade-core/src/main/java/blade/servlet/Request.java @@ -65,6 +65,10 @@ public class Request { protected Request() { } + public Request(HttpServletRequest request) { + this.servletRequest = request; + } + /** * 构造一个Request对象 * diff --git a/blade-core/src/main/java/blade/wrapper/RequestWrapper.java b/blade-core/src/main/java/blade/wrapper/RequestWrapper.java index 3d5347ddd..4caf4b9cf 100644 --- a/blade-core/src/main/java/blade/wrapper/RequestWrapper.java +++ b/blade-core/src/main/java/blade/wrapper/RequestWrapper.java @@ -33,7 +33,7 @@ public final class RequestWrapper extends Request { private Request delegate; - + public void setDelegate(Request delegate) { this.delegate = delegate; } From fa983f7c35d110697a7344930c2fc670e26108a2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 18:09:07 +0800 Subject: [PATCH 075/545] add all http method --- blade-core/src/main/java/blade/BladeBase.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index 8342fa2fd..04ff77e9d 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -300,6 +300,15 @@ public static synchronized void options(String path, RouteHandler routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.OPTIONS); } + /** + * 任意请求 + * @param path + * @param routeHandler + */ + public static synchronized void all(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.ALL); + } + /**--------------------SET CONST:END-------------------------*/ From e8f4877ef024b04534c1d33372c3ee901781a7fe Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 10 Aug 2015 18:12:00 +0800 Subject: [PATCH 076/545] add httpmethod connect --- blade-core/src/main/java/blade/BladeBase.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index 04ff77e9d..c2b4d0c7c 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -300,6 +300,15 @@ public static synchronized void options(String path, RouteHandler routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.OPTIONS); } + /** + * connect请求 + * @param path + * @param routeHandler + */ + public static synchronized void connect(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.CONNECT); + } + /** * 任意请求 * @param path From 081cb5141e19977a810b26faf1a7b77ec207e11b Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 10:03:12 +0800 Subject: [PATCH 077/545] update readme --- README.md | 14 +++++++++----- README_CN.md | 15 ++++++++++----- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index cdbaacffe..f97496815 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ public class App extends BladeApplication{ Logger logger = Logger.getLogger(App.class); @Override public void init() { - // register route + // register router Blade.regRoute("/hello", SayHi.class, "hello"); // anonymous router,java8 so simple @@ -86,7 +86,7 @@ public class App extends BladeApplication{ } ``` -#### Functional routing +#### Functional router ```java public class SayHi { @@ -98,7 +98,7 @@ public class SayHi { } ``` -#### The controller routing +#### Annotations router ``` @Path("/") public class Hello { @@ -141,15 +141,19 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex + [user guide](https://github.com/biezhi/blade/wiki) (The ongoing...) + [some examples](https://github.com/bladejava) -### Plan +## Plan + 1. Improve the document 2. Single user blog system development 3. web chat system 4. Optimize the code performance -### [Update](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) +## Update + +[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) ## licenses + Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) ## Contact diff --git a/README_CN.md b/README_CN.md index e9c9d1b89..d6e9dc6cb 100644 --- a/README_CN.md +++ b/README_CN.md @@ -2,7 +2,7 @@ [![简洁强大的JavaWeb框架](http://i1.tietuku.com/0c4b9726253b6268.png "简洁强大的JavaWeb框架")](http://bladejava.com) -[English](https://github.com/biezhi/blade/blob/master/README_EN.md) +[English](https://github.com/biezhi/blade/blob/master/README.md) [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) @@ -95,7 +95,7 @@ public class SayHi { } ``` -#### 控制器路由 +#### 注解路由 ``` @Path("/") public class Hello { @@ -139,17 +139,22 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 + [更多例子](https://github.com/bladejava) ### 计划 + 1. 完善文档 2. 单用户博客系统 3. web聊天系统 4. 优化代码性能 -### [更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) +## 更新日志 + +[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## 开源协议 -### 开源协议 Blade框架基于 [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) -### 联系我 +## 联系我 + OSC Blog:[http://my.oschina.net/biezhi](http://my.oschina.net/biezhi) Mail: biezhi.me#gmail.com From be9d667799866fe9c708ef8c40ef52657a9b1e7b Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 10:05:28 +0800 Subject: [PATCH 078/545] update readme --- README.md | 2 +- README_CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f97496815..0dc2dfacb 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ public class SayHi { ``` #### Annotations router -``` +```java @Path("/") public class Hello { diff --git a/README_CN.md b/README_CN.md index d6e9dc6cb..a902bf5ce 100644 --- a/README_CN.md +++ b/README_CN.md @@ -96,7 +96,7 @@ public class SayHi { ``` #### 注解路由 -``` +```java @Path("/") public class Hello { From f91cbff10a9d36526f4886ac46d883386c049236 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 11:02:21 +0800 Subject: [PATCH 079/545] adding functional registered interceptors --- README.md | 30 ++++++++---------- README_CN.md | 30 ++++++++---------- blade-core/src/main/java/blade/BladeBase.java | 27 ++++++++++++++++ .../java/blade/route/RouteMatcherBuilder.java | 31 +++++++++++++++++++ .../src/main/java/blade/servlet/Request.java | 13 ++++++++ 5 files changed, 97 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 0dc2dfacb..6fd9e05ef 100644 --- a/README.md +++ b/README.md @@ -42,23 +42,19 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for Second. Configuration in the `web.xml` Blade core filter initialization and set your class, and you can also not configuration(using jetty start) ```xml - - Archetype Created Web Application - - BladeFilter - blade.BladeFilter - - applicationClass - blade.sample.App - - - - - BladeFilter - /* - - - + + BladeFilter + blade.BladeFilter + + applicationClass + blade.sample.App + + + + + BladeFilter + /* + ``` Third. Write App.java and routing file, here is an example diff --git a/README_CN.md b/README_CN.md index a902bf5ce..65be61d1e 100644 --- a/README_CN.md +++ b/README_CN.md @@ -40,23 +40,19 @@ 第二步、在`web.xml`中配置Blade核心过滤器并设置你的初始化类,你也可以不配置(使用jetty启动) ```xml - - Archetype Created Web Application - - BladeFilter - blade.BladeFilter - - applicationClass - blade.sample.App - - - - - BladeFilter - /* - - - + + BladeFilter + blade.BladeFilter + + applicationClass + blade.sample.App + + + + + BladeFilter + /* + ``` 第三步、编写App.java和路由文件,下面是一个示例 diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index c2b4d0c7c..9a570d477 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -318,6 +318,33 @@ public static synchronized void all(String path, RouteHandler routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.ALL); } + /** + * 注册一个函数式的拦截器
+ *

+ * 方法上指定请求类型,如:post:signin + *

+ * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + */ + public static synchronized void regInterceptor(String path, Class clazz, String methodName){ + RouteMatcherBuilder.buildInterceptor(path, clazz, methodName, null); + } + + /** + * 注册一个函数式的拦截器
+ *

+ * 方法上指定请求类型,如:post:signin + *

+ * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + * @param acceptType acceptType + */ + public static synchronized void regInterceptor(String path, Class clazz, String methodName, String acceptType){ + RouteMatcherBuilder.buildInterceptor(path, clazz, methodName, acceptType); + } + /**--------------------SET CONST:END-------------------------*/ diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index f481c9619..8d687c727 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -153,6 +153,37 @@ public static void buildHandler(String path, RouteHandler routeHandler, HttpMeth } } + /** + * 函数式拦截器构建 + */ + public static void buildInterceptor(String path, Class clazz, String methodName, String acceptType){ + if(StringKit.isNotBlank(path) && null != clazz && StringKit.isNotBlank(methodName)){ + + // 字符串上写请求 */*:hello + if(methodName.indexOf(":") != -1){ + String[] methodArr = StringKit.split(methodName, ":"); + acceptType = methodArr[0]; + methodName = methodArr[1]; + } + + if(null == acceptType){ + acceptType = "*/*"; + } + + // 查找 + Object target = container.getBean(clazz, null); + if(null == target){ + container.registBean(clazz); + } + + Method execMethod = ReflectKit.getMethodByName(clazz, methodName); + + defaultRouteMatcher.addInterceptor(clazz, execMethod, path, HttpMethod.BEFORE, acceptType); + } else { + throw new BladeException("an unqualified configuration"); + } + } + /** * 构建拦截器 * diff --git a/blade-core/src/main/java/blade/servlet/Request.java b/blade-core/src/main/java/blade/servlet/Request.java index 60a59b433..82c895ff3 100644 --- a/blade-core/src/main/java/blade/servlet/Request.java +++ b/blade-core/src/main/java/blade/servlet/Request.java @@ -132,6 +132,19 @@ public Integer pathParamToInt(String param) { return null; } + /** + * 返回long类型的path param + * @param param 参数名称 + * @return 返回URL上对应的Long参数值 + */ + public Long pathParamToLong(String param) { + String value = pathParam(param); + if(null != value){ + return Long.valueOf(value); + } + return null; + } + /** * @return 返回通配符 */ From 830c741f0eb1268e9592a3b3de76c3248d746bba Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 13:45:56 +0800 Subject: [PATCH 080/545] - --- blade-kit/src/test/java/blade/test/LogTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/blade-kit/src/test/java/blade/test/LogTest.java b/blade-kit/src/test/java/blade/test/LogTest.java index 58c983b93..42e463fa3 100644 --- a/blade-kit/src/test/java/blade/test/LogTest.java +++ b/blade-kit/src/test/java/blade/test/LogTest.java @@ -8,7 +8,6 @@ public class LogTest { public static void main(String[] args) { Logger.setLoggerImpl(SysLoggerAdaptor.class); Logger logger = Logger.getLogger(LogTest.class); - //[duxue]2015-07-06 11:02:56,606 INFO [localhost-startStop-1] org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions | Loading XML bean definitions logger.info("hello %s", "aaa"); } } From 5cb8a04b6aa610d5feee25dda56496d6c5c3624a Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 13:47:22 +0800 Subject: [PATCH 081/545] update readme --- README.md | 2 +- README_CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6fd9e05ef..f54c6988a 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex + [hello project](https://github.com/bladejava/hello) + [api docs](http://bladejava.com/apidocs/) -+ [user guide](https://github.com/biezhi/blade/wiki) (The ongoing...) ++ [user guide](https://github.com/biezhi/blade/wiki) + [some examples](https://github.com/bladejava) ## Plan diff --git a/README_CN.md b/README_CN.md index 65be61d1e..fa38c7777 100644 --- a/README_CN.md +++ b/README_CN.md @@ -131,7 +131,7 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 + [hello](https://github.com/bladejava/hello) + [api docs](http://bladejava.com/apidocs/) -+ [使用指南](https://github.com/biezhi/blade/wiki) (完善中...) ++ [使用指南](https://github.com/biezhi/blade/wiki) + [更多例子](https://github.com/bladejava) ### 计划 From d1377c3bc6f36745ced1a0105c42926c34798a77 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 15:07:21 +0800 Subject: [PATCH 082/545] replace the HTTP request --- UPDATE_LOG.md | 2 + blade-core/pom.xml | 2 +- blade-kit/pom.xml | 2 +- blade-kit/src/main/java/blade/kit/Base64.java | 359 +- .../blade/kit/http/ConnectionFactory.java | 42 + .../src/main/java/blade/kit/http/Header.java | 123 + .../main/java/blade/kit/http/HttpBase.java | 684 ---- .../blade/kit/http/HttpConnectionWrapper.java | 372 --- .../java/blade/kit/http/HttpException.java | 37 - .../src/main/java/blade/kit/http/HttpKit.java | 63 - .../main/java/blade/kit/http/HttpRequest.java | 2938 ++++++++++++++++- .../blade/kit/http/HttpRequestException.java | 23 + .../java/blade/kit/http/HttpResponse.java | 86 - .../main/java/blade/kit/http/MethodType.java | 51 + .../blade/kit/http/RequestOutputStream.java | 48 + .../java/blade/kit/http/UploadProgress.java | 22 + pom.xml | 2 +- 17 files changed, 3332 insertions(+), 1524 deletions(-) create mode 100644 blade-kit/src/main/java/blade/kit/http/ConnectionFactory.java create mode 100644 blade-kit/src/main/java/blade/kit/http/Header.java delete mode 100644 blade-kit/src/main/java/blade/kit/http/HttpBase.java delete mode 100644 blade-kit/src/main/java/blade/kit/http/HttpConnectionWrapper.java delete mode 100644 blade-kit/src/main/java/blade/kit/http/HttpException.java delete mode 100644 blade-kit/src/main/java/blade/kit/http/HttpKit.java create mode 100644 blade-kit/src/main/java/blade/kit/http/HttpRequestException.java delete mode 100644 blade-kit/src/main/java/blade/kit/http/HttpResponse.java create mode 100644 blade-kit/src/main/java/blade/kit/http/MethodType.java create mode 100644 blade-kit/src/main/java/blade/kit/http/RequestOutputStream.java create mode 100644 blade-kit/src/main/java/blade/kit/http/UploadProgress.java diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 3dda8eb1a..898955d0e 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -2,6 +2,8 @@ ### v1.2.6 1. 添加多重路由配置方式 + 2. 添加函数式定义拦截器 + 3. 优化Http请求 ### v1.2.5 1. 添加JSON、Properties文件配置 diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 5de2c6827..46be761ad 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -19,7 +19,7 @@ com.bladejava blade-kit - 1.2.6-alpha + 1.2.6 javax.servlet diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index ff99b5f67..2dee888a6 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - 1.2.6-alpha + 1.2.6 blade-kit https://github.com/biezhi/blade/tree/master/blade-kit diff --git a/blade-kit/src/main/java/blade/kit/Base64.java b/blade-kit/src/main/java/blade/kit/Base64.java index 0c7db1f37..ca9042aec 100644 --- a/blade-kit/src/main/java/blade/kit/Base64.java +++ b/blade-kit/src/main/java/blade/kit/Base64.java @@ -24,106 +24,269 @@ * @since 1.0 */ public class Base64 { - - private static char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', - '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; - - private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, - -1, -1, -1 }; - - //编码 - public static String encode(byte[] data) { - StringBuffer sb = new StringBuffer(); - int len = data.length; - int i = 0; - int b1, b2, b3; - while (i < len) { - b1 = data[i++] & 0xff; - if (i == len) { - sb.append(base64EncodeChars[b1 >>> 2]); - sb.append(base64EncodeChars[(b1 & 0x3) << 4]); - sb.append("=="); - break; - } - b2 = data[i++] & 0xff; - if (i == len) { - sb.append(base64EncodeChars[b1 >>> 2]); - sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); - sb.append(base64EncodeChars[(b2 & 0x0f) << 2]); - sb.append("="); - break; - } - b3 = data[i++] & 0xff; - sb.append(base64EncodeChars[b1 >>> 2]); - sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); - sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]); - sb.append(base64EncodeChars[b3 & 0x3f]); - } - return sb.toString(); - } + /** The equals sign (=) as a byte. */ + private final static byte EQUALS_SIGN = (byte) '='; - //解码 - public static byte[] decode(String str) throws UnsupportedEncodingException { - StringBuffer sb = new StringBuffer(); - byte[] data = str.getBytes("US-ASCII"); - int len = data.length; - int i = 0; - int b1, b2, b3, b4; - while (i < len) { - /* b1 */ - do { - b1 = base64DecodeChars[data[i++]]; - } while (i < len && b1 == -1); - if (b1 == -1) - break; - /* b2 */ - do { - b2 = base64DecodeChars[data[i++]]; - } while (i < len && b2 == -1); - if (b2 == -1) - break; - sb.append((char) ((b1 << 2) | ((b2 & 0X30) >>> 4))); - /* b3 */ - do { - b3 = data[i++]; - if (b3 == 61) - return sb.toString().getBytes("iso8859-1"); - b3 = base64DecodeChars[b3]; - } while (i < len && b3 == -1); - if (b3 == -1) - break; - sb.append((char) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2))); - /* b4 */ - do { - b4 = data[i++]; - if (b4 == 61) - return sb.toString().getBytes("iso8859-1"); - b4 = base64DecodeChars[b4]; - } while (i < len && b4 == -1); - if (b4 == -1) - break; - sb.append((char) (((b3 & 0X03) << 6) | b4)); - } - return sb.toString().getBytes("iso8859-1"); - } - - /** - * 加密 - * @param str - * @return - */ - public static String encoder(String str){ - return encode(str.getBytes()); - } + /** Preferred encoding. */ + private final static String PREFERRED_ENCODING = "US-ASCII"; + + /** The 64 valid Base64 values. */ + private final static byte[] _STANDARD_ALPHABET = { (byte) 'A', (byte) 'B', + (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', + (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', + (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', + (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', + (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', + (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', + (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', + (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', + (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', + (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', + (byte) '+', (byte) '/' }; + + private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, + -1, -1, -1 }; + + /** Defeats instantiation. */ + private Base64() { + } + + /** + *

+ * Encodes up to three bytes of the array source and writes the + * resulting four Base64 bytes to destination. The source and + * destination arrays can be manipulated anywhere along their length by + * specifying srcOffset and destOffset. This method + * does not check to make sure your arrays are large enough to accomodate + * srcOffset + 3 for the source array or + * destOffset + 4 for the destination array. The + * actual number of significant bytes in your array is given by + * numSigBytes. + *

+ *

+ * This is the lowest level of the encoding methods with all possible + * parameters. + *

+ * + * @param source + * the array to convert + * @param srcOffset + * the index where conversion begins + * @param numSigBytes + * the number of significant bytes in your array + * @param destination + * the array to hold the conversion + * @param destOffset + * the index where output will be put + * @return the destination array + * @since 1.3 + */ + private static byte[] encode3to4(byte[] source, int srcOffset, + int numSigBytes, byte[] destination, int destOffset) { + + byte[] ALPHABET = _STANDARD_ALPHABET; + + int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) + | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) + | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); + + switch (numSigBytes) { + case 3: + destination[destOffset] = ALPHABET[(inBuff >>> 18)]; + destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; + destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; + destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f]; + return destination; + + case 2: + destination[destOffset] = ALPHABET[(inBuff >>> 18)]; + destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; + destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; + destination[destOffset + 3] = EQUALS_SIGN; + return destination; + + case 1: + destination[destOffset] = ALPHABET[(inBuff >>> 18)]; + destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; + destination[destOffset + 2] = EQUALS_SIGN; + destination[destOffset + 3] = EQUALS_SIGN; + return destination; + + default: + return destination; + } + } + + /** + * Encode string as a byte array in Base64 annotation. + * + * @param string + * @return The Base64-encoded data as a string + */ + public static String encode(String string) { + byte[] bytes; + try { + bytes = string.getBytes(PREFERRED_ENCODING); + } catch (UnsupportedEncodingException e) { + bytes = string.getBytes(); + } + return encodeBytes(bytes); + } + + /** + * Encodes a byte array into Base64 notation. + * + * @param source + * The data to convert + * @return The Base64-encoded data as a String + * @throws NullPointerException + * if source array is null + * @throws IllegalArgumentException + * if source array, offset, or length are invalid + * @since 2.0 + */ + public static String encodeBytes(byte[] source) { + return encodeBytes(source, 0, source.length); + } + + /** + * Encodes a byte array into Base64 notation. + * + * @param source + * The data to convert + * @param off + * Offset in array where conversion should begin + * @param len + * Length of data to convert + * @return The Base64-encoded data as a String + * @throws NullPointerException + * if source array is null + * @throws IllegalArgumentException + * if source array, offset, or length are invalid + * @since 2.0 + */ + public static String encodeBytes(byte[] source, int off, int len) { + byte[] encoded = encodeBytesToBytes(source, off, len); + try { + return new String(encoded, PREFERRED_ENCODING); + } catch (UnsupportedEncodingException uue) { + return new String(encoded); + } + } + + /** + * Similar to {@link #encodeBytes(byte[], int, int)} but returns a byte + * array instead of instantiating a String. This is more efficient if you're + * working with I/O streams and have large data sets to encode. + * + * + * @param source + * The data to convert + * @param off + * Offset in array where conversion should begin + * @param len + * Length of data to convert + * @return The Base64-encoded data as a String if there is an error + * @throws NullPointerException + * if source array is null + * @throws IllegalArgumentException + * if source array, offset, or length are invalid + * @since 2.3.1 + */ + public static byte[] encodeBytesToBytes(byte[] source, int off, int len) { + + if (source == null) + throw new NullPointerException("Cannot serialize a null array."); + + if (off < 0) + throw new IllegalArgumentException("Cannot have negative offset: " + + off); + + if (len < 0) + throw new IllegalArgumentException("Cannot have length offset: " + len); + + if (off + len > source.length) + throw new IllegalArgumentException( + String + .format( + "Cannot have offset of %d and length of %d with array of length %d", + off, len, source.length)); + + // Bytes needed for actual encoding + int encLen = (len / 3) * 4 + (len % 3 > 0 ? 4 : 0); + + byte[] outBuff = new byte[encLen]; + + int d = 0; + int e = 0; + int len2 = len - 2; + for (; d < len2; d += 3, e += 4) + encode3to4(source, d + off, 3, outBuff, e); + + if (d < len) { + encode3to4(source, d + off, len - d, outBuff, e); + e += 4; + } + + if (e <= outBuff.length - 1) { + byte[] finalOut = new byte[e]; + System.arraycopy(outBuff, 0, finalOut, 0, e); + return finalOut; + } else + return outBuff; + } - public static String decoder(String str) throws UnsupportedEncodingException{ + //解码 + public static byte[] decode(String str) throws UnsupportedEncodingException { + StringBuffer sb = new StringBuffer(); + byte[] data = str.getBytes("US-ASCII"); + int len = data.length; + int i = 0; + int b1, b2, b3, b4; + while (i < len) { + /* b1 */ + do { + b1 = base64DecodeChars[data[i++]]; + } while (i < len && b1 == -1); + if (b1 == -1) + break; + /* b2 */ + do { + b2 = base64DecodeChars[data[i++]]; + } while (i < len && b2 == -1); + if (b2 == -1) + break; + sb.append((char) ((b1 << 2) | ((b2 & 0X30) >>> 4))); + /* b3 */ + do { + b3 = data[i++]; + if (b3 == 61) + return sb.toString().getBytes("iso8859-1"); + b3 = base64DecodeChars[b3]; + } while (i < len && b3 == -1); + if (b3 == -1) + break; + sb.append((char) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2))); + /* b4 */ + do { + b4 = data[i++]; + if (b4 == 61) + return sb.toString().getBytes("iso8859-1"); + b4 = base64DecodeChars[b4]; + } while (i < len && b4 == -1); + if (b4 == -1) + break; + sb.append((char) (((b3 & 0X03) << 6) | b4)); + } + return sb.toString().getBytes("iso8859-1"); + } + + public static String decoder(String str) throws UnsupportedEncodingException{ return new String(decode(str)); } - + } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/http/ConnectionFactory.java b/blade-kit/src/main/java/blade/kit/http/ConnectionFactory.java new file mode 100644 index 000000000..c695eff71 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/http/ConnectionFactory.java @@ -0,0 +1,42 @@ +package blade.kit.http; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.Proxy; +import java.net.URL; + +/** + * HttpURLConnection工厂 + * + * @author biezhi + * @since 1.0 + */ +public interface ConnectionFactory { + /** + * 根据URL创建一个HttpURLConnection + * + * @throws IOException + */ + HttpURLConnection create(URL url) throws IOException; + + /** + * 根据URL和代理对象创建一个HttpURLConnection + * + * @throws IOException + */ + HttpURLConnection create(URL url, Proxy proxy) throws IOException; + + /** + * 一个默认的连接工厂 + */ + ConnectionFactory DEFAULT = new ConnectionFactory() { + public HttpURLConnection create(URL url) throws IOException { + return (HttpURLConnection) url.openConnection(); + } + + public HttpURLConnection create(URL url, Proxy proxy) + throws IOException { + return (HttpURLConnection) url.openConnection(proxy); + } + }; +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/http/Header.java b/blade-kit/src/main/java/blade/kit/http/Header.java new file mode 100644 index 000000000..77c29dd89 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/http/Header.java @@ -0,0 +1,123 @@ +package blade.kit.http; + +/** + * 头信息常量 + * + * @author biezhi + * @since 1.0 + */ +public class Header { + + public static final String CHARSET_UTF8 = "UTF-8"; + + /** + * 表单类型头信息 + */ + public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded"; + + /** + * json类型头信息 + */ + public static final String CONTENT_TYPE_JSON = "application/json"; + + /** + * gzip压缩 + */ + public static final String ENCODING_GZIP = "gzip"; + + /** + * Accept + */ + public static final String HEADER_ACCEPT = "Accept"; + + /** + * Accept-Charset + */ + public static final String HEADER_ACCEPT_CHARSET = "Accept-Charset"; + + /** + * Accept-Encoding + */ + public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding"; + + /** + * Authorization + */ + public static final String HEADER_AUTHORIZATION = "Authorization"; + + /** + * 'Cache-Control' header name + */ + public static final String HEADER_CACHE_CONTROL = "Cache-Control"; + + /** + * 'Content-Encoding' header name + */ + public static final String HEADER_CONTENT_ENCODING = "Content-Encoding"; + + /** + * 'Content-Length' header name + */ + public static final String HEADER_CONTENT_LENGTH = "Content-Length"; + + /** + * 'Content-Type' header name + */ + public static final String HEADER_CONTENT_TYPE = "Content-Type"; + + /** + * 'Date' header name + */ + public static final String HEADER_DATE = "Date"; + + /** + * 'ETag' header name + */ + public static final String HEADER_ETAG = "ETag"; + + /** + * 'Expires' header name + */ + public static final String HEADER_EXPIRES = "Expires"; + + /** + * 'If-None-Match' header name + */ + public static final String HEADER_IF_NONE_MATCH = "If-None-Match"; + + /** + * 'Last-Modified' header name + */ + public static final String HEADER_LAST_MODIFIED = "Last-Modified"; + + /** + * 'Location' header name + */ + public static final String HEADER_LOCATION = "Location"; + + /** + * 'Proxy-Authorization' header name + */ + public static final String HEADER_PROXY_AUTHORIZATION = "Proxy-Authorization"; + + /** + * 'Referer' header name + */ + public static final String HEADER_REFERER = "Referer"; + + /** + * 'Server' header name + */ + public static final String HEADER_SERVER = "Server"; + + /** + * 'User-Agent' header name + */ + public static final String HEADER_USER_AGENT = "User-Agent"; + + /** + * 'charset' header value parameter + */ + public static final String PARAM_CHARSET = "charset"; + +} diff --git a/blade-kit/src/main/java/blade/kit/http/HttpBase.java b/blade-kit/src/main/java/blade/kit/http/HttpBase.java deleted file mode 100644 index 29a371712..000000000 --- a/blade-kit/src/main/java/blade/kit/http/HttpBase.java +++ /dev/null @@ -1,684 +0,0 @@ - -package blade.kit.http; - -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import blade.kit.io.StringBuilderWriter; - -/** - * http基类 - *

- *

- * - * @author biezhi - * @since 1.0 - * @param - */ -@SuppressWarnings("unchecked") -public abstract class HttpBase { - - //////////////////////////const/////////////////////////////////// - - /**Accept*/ - public static final String HEADER_ACCEPT = "Accept"; - - /**Accept-Encoding*/ - public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding"; - - /**User-Agent*/ - public static final String HEADER_USER_AGENT = "User-Agent"; - - /**Content-Type*/ - public static final String HEADER_CONTENT_TYPE = "Content-Type"; - - /**Content-Length*/ - public static final String HEADER_CONTENT_LENGTH = "Content-Length"; - - /**Content-Encoding*/ - public static final String HEADER_CONTENT_ENCODING = "Content-Encoding"; - - /**Host*/ - public static final String HEADER_HOST = "Host"; - - /**ETag*/ - public static final String HEADER_ETAG = "ETag"; - - /**Connection*/ - public static final String HEADER_CONNECTION = "Connection"; - - /**Keep-Alive*/ - public static final String HEADER_KEEP_ALIVE = "Keep-Alive"; - - /**Close*/ - public static final String HEADER_CLOSE = "Close"; - - /**HTTP/1.0*/ - public static final String HTTP_1_0 = "HTTP/1.0"; - - /**HTTP/1.1*/ - public static final String HTTP_1_1 = "HTTP/1.1"; - - /**UTF-8*/ - protected String charset = "UTF-8"; - - /**默认缓冲*/ - protected static final int DEFAULT_BUFFER_SIZE = 1024 * 4; - - /**http版本*/ - protected String httpVersion = HTTP_1_1; - - /**存储头信息*/ - protected Map> headers = new HashMap>(); - - /**存储表单数据*/ - protected Map form = new HashMap(); - - /**存储响应主体*/ - protected String body; - - /** - * 返回http版本 - * @return String - */ - public String httpVersion() { - return httpVersion; - } - - /** - * 设置http版本 - * @param httpVersion - * @return T - */ - public T httpVersion(String httpVersion) { - this.httpVersion = httpVersion; - return (T) this; - } - - // ---------------------------------------------------------------- headers - - /** - * 根据name获取头信息 - * @param name - * @return String - */ - public String header(String name) { - String key = name.trim(); - if(null == headers.get(key)){ - return null; - } - String value = headers.get(key).get(0); - if (value == null) { - return null; - } - return value; - } - - /** - * 移除一个头信息 - * @param name - */ - public void removeHeader(String name) { - String key = name.trim(); - headers.remove(key); - } - - /** - * 设置一个header - * @param name - * @param value - * @return T - */ - public T header(String name, String value) { - if(null != name && null != value){ - String key = name.trim(); - value = value.trim(); - headers.put(key, Arrays.asList(value)); - } - return (T) this; - } - - /** - * 覆盖一个header - * @param name - * @param value - * @param flag - * @return T - */ - public T header(String name, String value, boolean flag) { - if(null != name && null != value){ - String key = name.trim(); - value = value.trim(); - if(headers.containsKey(key)){ - headers.remove(key); - } - headers.put(key, Arrays.asList(value)); - } - return (T) this; - } - - /** - * header - * @param name - * @param value - * @return T - */ - public T header(String name, int value) { - return header(name, String.valueOf(value)); - } - - /** - * header - * @param name - * @param millis - * @return T - */ - public T header(String name, long millis) { - return header(name, String.valueOf(millis)); - } - - /** - * 获取headers - * @return Map> - */ - public Map> headers() { - return Collections.unmodifiableMap(headers); - } - - /** - * 返回字符集 - * @return String - */ - public String charset() { - return charset; - } - - /** - * 设置字符集 - * @param charset - * @return T - */ - public T charset(String charset) { - this.charset = null; - contentType(null, charset); - return (T) this; - } - - /**mediaType*/ - protected String mediaType; - - /** - * 获取mediaType - * @return String - */ - public String mediaType() { - return mediaType; - } - - /** - * 设置mediaType - * @param mediaType - * @return T - */ - public T mediaType(String mediaType) { - contentType(mediaType, null); - return (T) this; - } - - /** - * 获取contentType - * @return String - */ - public String contentType() { - return header(HEADER_CONTENT_TYPE); - } - - /** - * 设置contentType - * @param contentType - * @return T - */ - public T contentType(String contentType) { - header(HEADER_CONTENT_TYPE, contentType); - return (T) this; - } - - /** - * 设置mediaType包含字符集 - * @param mediaType - * @param charset - * @return T - */ - public T contentType(String mediaType, String charset) { - if (mediaType == null) { - mediaType = this.mediaType; - } else { - this.mediaType = mediaType; - } - - if (charset == null) { - charset = this.charset; - } else { - this.charset = charset; - } - - String contentType = mediaType; - if (charset != null) { - contentType += ";charset=" + charset; - } - - header(HEADER_CONTENT_TYPE, contentType); - return (T) this; - } - - /** - * 设置是否为活动连接 - * @param keepAlive - * @return T - */ - public T connectionKeepAlive(boolean keepAlive) { - if (keepAlive) { - header(HEADER_CONNECTION, HEADER_KEEP_ALIVE); - } else { - header(HEADER_CONNECTION, HEADER_CLOSE); - } - return (T) this; - } - - /** - * 获取是否为活动连接 - * @return boolean - */ - public boolean isConnectionPersistent() { - String connection = header(HEADER_CONNECTION); - if (connection == null) { - return !httpVersion.equalsIgnoreCase(HTTP_1_0); - } - - return !connection.equalsIgnoreCase(HEADER_CLOSE); - } - - /** - * 获取内容长度 - * @return String - */ - public String contentLength() { - return header(HEADER_CONTENT_LENGTH); - } - - /** - * 设置内容长度 - * @param value - * @return T - */ - public T contentLength(int value) { - header(HEADER_CONTENT_LENGTH, String.valueOf(value)); - return (T) this; - } - - /** - * 获取内容编码 - * @return String - */ - public String contentEncoding() { - return header(HEADER_CONTENT_ENCODING); - } - - /** - * 获取请求头 - * @return String - */ - public String accept() { - return header(HEADER_ACCEPT); - } - - /** - * 设置请求头 - * @param encodings - * @return T - */ - public T accept(String encodings) { - header(HEADER_ACCEPT, encodings); - return (T) this; - } - - /** - * 获取请求编码 - * @return String - */ - public String acceptEncoding() { - return header(HEADER_ACCEPT_ENCODING); - } - - /** - * 设置请求编码 - * @param encodings - * @return T - */ - public T acceptEncoding(String encodings) { - header(HEADER_ACCEPT_ENCODING, encodings); - return (T) this; - } - - /** - * 初始化表单 - */ - protected void initForm() { - if (form == null) { - form = new HashMap(); - } - } - - /** - * 转换数据类型 - * @param value - * @return Object - */ - protected Object wrapFormValue(Object value) { - if (value == null) { - return null; - } - if (value instanceof CharSequence) { - return value.toString(); - } - if (value instanceof Number) { - return value.toString(); - } - if (value instanceof Boolean) { - return value.toString(); - } - throw new HttpException("Unsupported value type: " + value.getClass().getName()); - } - - /** - * 设置表单数据 - * @param name - * @param value - * @return T - */ - public T query(String name, Object value) { - initForm(); - value = wrapFormValue(value); - form.put(name, value); - - return (T) this; - } - - /** - * 设置表单数据,是否覆盖 - * @param name - * @param value - * @param overwrite - * @return T - */ - public T query(String name, Object value, boolean overwrite) { - initForm(); - - value = wrapFormValue(value); - - if (overwrite) { - form.put(name, value); - } else { - form.put(name, value); - } - - return (T) this; - } - - /** - * 设置表单数据 - * @param name - * @param value - * @param parameters - * @return T - */ - public T query(String name, Object value, Object... parameters) { - initForm(); - - query(name, value); - - for (int i = 0; i < parameters.length; i += 2) { - name = parameters[i].toString(); - - query(name, parameters[i + 1]); - } - return (T) this; - } - - /** - * 设置map类型表单数据 - * @param formMap - * @return T - */ - public T query(Map formMap) { - initForm(); - - for (Map.Entry entry : formMap.entrySet()) { - query(entry.getKey(), entry.getValue()); - } - return (T) this; - } - - /** - * 获取表单数据 - * @return Map - */ - public Map form() { - return form; - } - - // ---------------------------------------------------------------- form encoding - - /**formEncoding*/ - protected String formEncoding = "UTF-8"; - - /** - * 设置表单编码 - * @param encoding - * @return T - */ - public T formEncoding(String encoding) { - this.formEncoding = encoding; - return (T) this; - } - - /** - * 获取响应主体 - * @return String - */ - public String body() { - return body; - } - - /** - * 获取响应流字节码 - * @return byte[] - */ - public byte[] bodyBytes() { - if (body == null) { - return null; - } - try { - return body.getBytes("ISO8859-1"); - } catch (UnsupportedEncodingException ignore) { - return null; - } - } - - /** - * 获取响应文本 - * @return String - */ - public String bodyText() { - if (body == null) { - return null; - } - if (charset != null) { - try { - return new String(body.getBytes("ISO8859-1"), charset); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - return body(); - } - - /** - * 设置内容主体 - * @param body - * @return T - */ - public T body(String body) { - this.body = body; - this.form = null; - contentLength(body.length()); - return (T) this; - } - - /** - * 设置内容主体编码 - * @param charset - * @return String - */ - public String bodyText(String charset) { - try { - return new String(body.getBytes(charset), "ISO8859-1"); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return null; - } - - /** - * 设置内容mediaType - * @param body - * @param mediaType - * @return T - */ - public T bodyText(String body, String mediaType) { - return bodyText(body, mediaType, "UTF-8"); - } - - /** - * 设置内容html - * @param body - * @return T - */ - public T bodyHtml(String body) { - return bodyText(body, "text/html", "UTF-8"); - } - - /** - * 设置主体文本 - * @param body - * @param mediaType - * @param charset - * @return T - */ - public T bodyText(String body, String mediaType, String charset) { - try { - body = new String(body.getBytes(charset), "ISO8859-1"); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - contentType(mediaType, charset); - body(body); - return (T) this; - } - - /** - * 设置主体字节码 - * @param content - * @param contentType - * @return T - */ - public T body(byte[] content, String contentType) { - String body = null; - try { - body = new String(content, "ISO8859-1"); - } catch (UnsupportedEncodingException ignore) { - } - contentType(contentType); - return body(body); - } - - /** - * 读取主体 - * @param input - * @return String - * @throws IOException - */ - public String readBody(InputStream input) throws IOException{ - StringBuilderWriter sw = new StringBuilderWriter(); - InputStreamReader in = new InputStreamReader(input, Charset.defaultCharset()); - copy(in, sw); - close(input); - return sw.toString(); - } - - /** - * 复制数据流 - * @param input - * @param output - * @return int - * @throws IOException - */ - public int copy(Reader input, Writer output) throws IOException { - long count = copyLarge(input, output); - if (count > Integer.MAX_VALUE) { - return -1; - } - return (int) count; - } - - /** - * 复制长数据流 - * @param input - * @param output - * @return long - * @throws IOException - */ - public long copyLarge(Reader input, Writer output) throws IOException { - return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]); - } - - /** - * 复制长数据流 - * @param input - * @param output - * @param buffer - * @return long - * @throws IOException - */ - public long copyLarge(Reader input, Writer output, char [] buffer) throws IOException { - long count = 0; - int n = 0; - while (-1 != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; - } - - /** - * 关闭数据流 - * @param closeable - * @throws IOException - */ - public void close(Closeable closeable) throws IOException{ - if(null != closeable){ - closeable.close(); - } - } -} diff --git a/blade-kit/src/main/java/blade/kit/http/HttpConnectionWrapper.java b/blade-kit/src/main/java/blade/kit/http/HttpConnectionWrapper.java deleted file mode 100644 index deb823da0..000000000 --- a/blade-kit/src/main/java/blade/kit/http/HttpConnectionWrapper.java +++ /dev/null @@ -1,372 +0,0 @@ -package blade.kit.http; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - -/** - * http连接对象包装 - *

- *

- * - * @author biezhi - * @since 1.0 - */ -public class HttpConnectionWrapper { - - /** - * httpsURLConnection - */ - private HttpsURLConnection httpsURLConnection; - - /** - * httpURLConnection - */ - private HttpURLConnection httpURLConnection; - - /** - * timeout超时,以毫秒为单位 - */ - private int timeout; - - /** - * url - */ - private String url; - - /** - * method请求方法 - */ - private String method = "GET"; - - /** - * 初始化HttpConnection - * @param url - * @param method - * @throws IOException - * @throws KeyManagementException - * @throws NoSuchAlgorithmException - * @throws NoSuchProviderException - */ - public HttpConnectionWrapper(String url, String method) throws IOException, KeyManagementException, NoSuchAlgorithmException, NoSuchProviderException { - this.url = url; - this.method = method; - - if(isHttps(this.url)){ - initHttps(); - } else { - initHttp(); - } - } - - /** - * 初始化http请求参数 - */ - private void initHttp() throws IOException { - URL _url = new URL(this.url); - this.httpURLConnection = (HttpURLConnection) _url.openConnection(); - - // method - if (this.method.equalsIgnoreCase("post")) { - this.httpURLConnection.setDoOutput(true); - this.httpURLConnection.setUseCaches(false); - } - this.httpURLConnection.setDoInput(true); - this.httpURLConnection.setRequestMethod(this.method); - - // header - this.httpURLConnection.setRequestProperty(HttpBase.HEADER_ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); - this.httpURLConnection.setRequestProperty(HttpBase.HEADER_CONTENT_TYPE, "application/x-www-form-urlencoded"); - this.httpURLConnection.setRequestProperty(HttpBase.HEADER_USER_AGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0"); - - this.httpsURLConnection = null; - - } - - /** - * 初始化http请求参数 - */ - private void initHttps() throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException { - TrustManager[] tm = { new MyX509TrustManager() }; - SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); - sslContext.init(null, tm, new java.security.SecureRandom()); - - // 从上述SSLContext对象中得到SSLSocketFactory对象 - SSLSocketFactory ssf = sslContext.getSocketFactory(); - - URL _url = new URL(url); - this.httpsURLConnection = (HttpsURLConnection) _url.openConnection(); - - // domain validate - this.httpsURLConnection.setHostnameVerifier(new TrustAnyHostnameVerifier()); - - this.httpsURLConnection.setSSLSocketFactory(ssf); - - // method - if (this.method.equalsIgnoreCase("post")) { - this.httpsURLConnection.setDoOutput(true); - this.httpsURLConnection.setUseCaches(false); - } - this.httpsURLConnection.setDoInput(true); - this.httpsURLConnection.setRequestMethod(this.method); - - // header - this.httpsURLConnection.setRequestProperty(HttpBase.HEADER_ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); - this.httpsURLConnection.setRequestProperty(HttpBase.HEADER_CONTENT_TYPE, "application/x-www-form-urlencoded"); - this.httpsURLConnection.setRequestProperty(HttpBase.HEADER_USER_AGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0"); - - this.httpURLConnection = null; - } - - /** - * 获取请求方法,GET/POST - * @return String - */ - public String getMethod() { - return method; - } - - /** - * 设置请求方法 - * @param method - */ - public void setMethod(String method) { - this.method = method; - } - - /** - * 获取请求URL - * @return String - */ - public String getUrl() { - return url; - } - - /** - * 设置请求URL - * @param url - */ - public void setUrl(String url) { - this.url = url; - } - - /** - * 获取超时 - * @return int - */ - public int getTimeout() { - return timeout; - } - - /** - * 设置超时 - * @param timeout - */ - public void setTimeout(int timeout) { - this.timeout = timeout; - } - - /** - * 获取HttpsURLConnection对象 - * @return HttpsURLConnection - */ - public HttpsURLConnection getHttpsURLConnection() { - return httpsURLConnection; - } - - /** - * 获取HttpURLConnection对象 - * @return HttpURLConnection - */ - public HttpURLConnection getHttpURLConnection() { - return httpURLConnection; - } - - /** - * 检测是否https - * @param url - * @return boolean - */ - private boolean isHttps(String url) { - return url.startsWith("https"); - } - - /** - * https 域名校验 - * - * @author biezhi - * @since 1.0 - */ - public class TrustAnyHostnameVerifier implements HostnameVerifier { - public boolean verify(String hostname, SSLSession session) { - return true;// 直接返回true - } - } - - /** - * 设置连接超时 - * @param timeout - */ - public void setConnectTimeout(int timeout){ - if(null != this.httpURLConnection){ - this.httpURLConnection.setConnectTimeout(timeout); - } - if(null != this.httpsURLConnection){ - this.httpsURLConnection.setConnectTimeout(timeout); - } - } - - /** - * 设置读取超时 - * @param timeout - */ - public void setReadTimeout(int timeout){ - if(null != this.httpURLConnection){ - this.httpURLConnection.setReadTimeout(timeout); - } - if(null != this.httpsURLConnection){ - this.httpsURLConnection.setReadTimeout(timeout); - } - } - - /** - * 设置请求头 - * @param key - * @param value - */ - public void setRequestProperty(String key, String value){ - if(null != this.httpURLConnection){ - this.httpURLConnection.setRequestProperty(key, value); - } - if(null != this.httpsURLConnection){ - this.httpsURLConnection.setRequestProperty(key, value); - } - } - - /** - * 设置请求头 - * @param headers - */ - public void setRequestProperty(Map> headers){ - Set keySet = headers.keySet(); - for(String key : keySet){ - List valueList = headers.get(key); - this.setRequestProperty(key, valueList.get(0)); - } - } - - /** - * 连接 - * @throws IOException - */ - public void connect() throws IOException{ - if(null != this.httpURLConnection){ - this.httpURLConnection.connect(); - } - if(null != this.httpsURLConnection){ - this.httpsURLConnection.connect(); - } - } - - /** - * 断开连接 - */ - public void disconnect(){ - if(null != this.httpURLConnection){ - this.httpURLConnection.disconnect(); - } - if(null != this.httpsURLConnection){ - this.httpsURLConnection.disconnect(); - } - } - - public InputStream getInputStream() throws IOException{ - if(null != this.httpURLConnection){ - return this.httpURLConnection.getInputStream(); - } - if(null != this.httpsURLConnection){ - return this.httpsURLConnection.getInputStream(); - } - return null; - } - - /** - * 获取输出流对象 - * @return OutputStream - * @throws IOException - */ - public OutputStream getOutputStream() throws IOException{ - if(null != this.httpURLConnection){ - return this.httpURLConnection.getOutputStream(); - } - if(null != this.httpsURLConnection){ - return this.httpsURLConnection.getOutputStream(); - } - return null; - } - - /** - * 获取请求头信息 - * @return Map> - */ - public Map> getHeaderFields(){ - if(null != this.httpURLConnection){ - return this.httpURLConnection.getHeaderFields(); - } - if(null != this.httpsURLConnection){ - return this.httpsURLConnection.getHeaderFields(); - } - return null; - } - - /** - * 获取响应码 - * @return int - * @throws IOException - */ - public int getResponseCode() throws IOException{ - if(null != this.httpURLConnection){ - return this.httpURLConnection.getResponseCode(); - } - if(null != this.httpsURLConnection){ - return this.httpsURLConnection.getResponseCode(); - } - return 0; - } -} - -// 证书管理 -class MyX509TrustManager implements X509TrustManager { - - public X509Certificate[] getAcceptedIssuers() { - return null; - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - } -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/http/HttpException.java b/blade-kit/src/main/java/blade/kit/http/HttpException.java deleted file mode 100644 index 128e0ae77..000000000 --- a/blade-kit/src/main/java/blade/kit/http/HttpException.java +++ /dev/null @@ -1,37 +0,0 @@ -package blade.kit.http; - -/** - * http异常封装 - *

- *

- * - * @author biezhi - * @since 1.0 - */ -public class HttpException extends RuntimeException { - - private static final long serialVersionUID = -6657642586184082657L; - - /** - * HttpException - */ - public HttpException() { - // TODO Auto-generated constructor stub - } - - /** - * HttpException - * @param msg - */ - public HttpException(String msg) { - super(msg); - } - - /** - * HttpException - * @param t - */ - public HttpException(Throwable t) { - super(t); - } -} diff --git a/blade-kit/src/main/java/blade/kit/http/HttpKit.java b/blade-kit/src/main/java/blade/kit/http/HttpKit.java deleted file mode 100644 index c82839bdc..000000000 --- a/blade-kit/src/main/java/blade/kit/http/HttpKit.java +++ /dev/null @@ -1,63 +0,0 @@ -package blade.kit.http; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import blade.kit.StringKit; - -/** - * http util - * @author biezhi - * - */ -public class HttpKit { - - /** - * 参数转换为map,a=1&b=2 - * @param query - * @param decode - * @return Map - */ - public static Map parseQuery(String query, boolean decode) { - Map queryMap = new HashMap(); - String[] kvArr = StringKit.split(query, "&"); - if(null != kvArr && kvArr.length > 0){ - for(String k : kvArr){ - if(k.indexOf("=") != -1){ - String[] kv = StringKit.split(k, "="); - queryMap.put(kv[0], kv[1]); - } - } - } - return queryMap; - } - - /** - * map转为url参数 - * @param map - * @return String - */ - public static String getQuery(Map map){ - try { - if(null != map && map.size() > 0){ - StringBuffer sBuffer = new StringBuffer(); - Set keySet = map.keySet(); - for(String key : keySet){ - sBuffer.append(key + "=" + URLEncoder.encode(map.get(key).toString(), "UTF-8") + "&"); - } - return sBuffer.substring(0, sBuffer.length() - 1).toString(); - } - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return ""; - } - - public static HttpRequest createRequest(String url){ - return new HttpRequest(url); - } -} - diff --git a/blade-kit/src/main/java/blade/kit/http/HttpRequest.java b/blade-kit/src/main/java/blade/kit/http/HttpRequest.java index c3a4ec767..6e9299ed8 100644 --- a/blade-kit/src/main/java/blade/kit/http/HttpRequest.java +++ b/blade-kit/src/main/java/blade/kit/http/HttpRequest.java @@ -1,181 +1,2757 @@ -package blade.kit.http; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.util.List; -import java.util.Map; - -/** - * http请求类 - *

- *

- * - * @author biezhi - * @since 1.0 - */ -public class HttpRequest extends HttpBase{ - - /** - * method - */ - protected String method = "GET"; - - /** - * URL - */ - private String url = ""; - - /** - * 默认超时 - */ - private int timeout = -1; - - /** - * 连接对象 - */ - private HttpConnectionWrapper httpConnection; - - /** - * 设置请求方法 - * @param method - * @return HttpRequest - */ - private HttpRequest method(String method) { - this.method = method.toUpperCase(); - return this; - } - - /** - * 设置请求URL - * @param url - */ - public HttpRequest(String url) { - this.url = url; - } - - /** - * POST请求 - * @param url - * @return HttpRequest - */ - public static HttpRequest post(String url) { - return new HttpRequest(url).method("POST"); - } - - /** - * GET请求 - * @param url - * @return HttpRequest - */ - public static HttpRequest get(String url) { - return new HttpRequest(url).method("GET"); - } - - /** - * 设置超时 - * @param milliseconds - * @return HttpRequest - */ - public HttpRequest timeout(int milliseconds) { - this.timeout = milliseconds; - return this; - } - - /** - * 执行Reuqest请求 - * @return HttpResponse - * @throws IOException - * @throws NoSuchProviderException - * @throws NoSuchAlgorithmException - * @throws KeyManagementException - */ - public HttpResponse execute() throws Exception{ - - if(this.method.equalsIgnoreCase("get")){ - withUrl(); - } - // init connection - this.httpConnection = new HttpConnectionWrapper(this.url, this.method); - - // response - HttpResponse httpResponse = null; - if(this.timeout != -1){ - // connect timeout - this.httpConnection.setConnectTimeout(this.timeout); - // read timeout - this.httpConnection.setReadTimeout(this.timeout); - } - - // set header - if(!this.headers.isEmpty()){ - this.httpConnection.setRequestProperty(this.headers); - } - - try { - - if(this.method.equalsIgnoreCase("POST")){ - OutputStream outputStream = httpConnection.getOutputStream(); - sendTo(outputStream); - } else { - this.httpConnection.connect(); - } - - InputStream inputStream = this.httpConnection.getInputStream(); - Map> headerFields = this.httpConnection.getHeaderFields(); - - httpResponse = HttpResponse.readResponse(inputStream); - - httpResponse.setHeader(headerFields); - httpResponse.setStatusCode(this.httpConnection.getResponseCode()); - httpResponse.setHttpRequest(this); - - } catch (IOException ioex) { - throw new HttpException(ioex); - } - boolean keepAlive = httpResponse.isConnectionPersistent(); - if (keepAlive == false) { - // closes connection if keep alive is false, or if counter reached 0 - this.httpConnection.disconnect(); - this.httpConnection = null; - } - return httpResponse; - } - - /** - * 转换URL - */ - private void withUrl(){ - String queryString = HttpKit.getQuery(this.form); - if(null != queryString && !"".equals(queryString)){ - if(this.url.endsWith("?")){ - this.url += queryString; - } else { - this.url += "?" + queryString; - } - } - } - - /** - * 发送数据流 - * @param outputStream - * @throws IOException - */ - private void sendTo(OutputStream outputStream) throws IOException { - if(null != outputStream){ - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, this.formEncoding)); - String queryString = HttpKit.getQuery(this.form); - writer.write(queryString); - writer.flush(); - writer.close(); - - outputStream.close(); - } - } - -} +/* + * Copyright (c) 2014 Kevin Sawicki + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +package blade.kit.http; + +import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; +import static java.net.HttpURLConnection.HTTP_CREATED; +import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR; +import static java.net.HttpURLConnection.HTTP_NOT_FOUND; +import static java.net.HttpURLConnection.HTTP_NOT_MODIFIED; +import static java.net.HttpURLConnection.HTTP_NO_CONTENT; +import static java.net.HttpURLConnection.HTTP_OK; +import static java.net.Proxy.Type.HTTP; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.Flushable; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.CharBuffer; +import java.security.AccessController; +import java.security.GeneralSecurityException; +import java.security.PrivilegedAction; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.util.zip.GZIPInputStream; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import blade.kit.Base64; + +/** + * Http请求类 + * + * @author biezhi + * @since 1.0 + */ +public class HttpRequest { + + private static final String BOUNDARY = "00content0boundary00"; + + private static final String CONTENT_TYPE_MULTIPART = "multipart/form-data; boundary=" + BOUNDARY; + + private static final String CRLF = "\r\n"; + + private static final String[] EMPTY_STRINGS = new String[0]; + + private static SSLSocketFactory TRUSTED_FACTORY; + + private static HostnameVerifier TRUSTED_VERIFIER; + + private static ConnectionFactory CONNECTION_FACTORY = ConnectionFactory.DEFAULT; + + public static String getValidCharset(final String charset) { + if (charset != null && charset.length() > 0) + return charset; + else + return Header.CHARSET_UTF8; + } + + /** + * @return 返回SSL套接字工厂 + * @throws HttpRequestException + */ + private static SSLSocketFactory getTrustedFactory() + throws HttpRequestException { + if (TRUSTED_FACTORY == null) { + final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) { + // Intentionally left blank + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) { + // Intentionally left blank + } + } }; + try { + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, trustAllCerts, new SecureRandom()); + TRUSTED_FACTORY = context.getSocketFactory(); + } catch (GeneralSecurityException e) { + IOException ioException = new IOException( + "Security exception configuring SSL context"); + ioException.initCause(e); + throw new HttpRequestException(ioException); + } + } + + return TRUSTED_FACTORY; + } + + private static HostnameVerifier getTrustedVerifier() { + if (TRUSTED_VERIFIER == null) + TRUSTED_VERIFIER = new HostnameVerifier() { + + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + return TRUSTED_VERIFIER; + } + + private static StringBuilder addPathSeparator(final String baseUrl, + final StringBuilder result) { + // Add trailing slash if the base URL doesn't have any path segments. + // + // The following test is checking for the last slash not being part of + // the protocol to host separator: '://'. + if (baseUrl.indexOf(':') + 2 == baseUrl.lastIndexOf('/')) + result.append('/'); + return result; + } + + private static StringBuilder addParamPrefix(final String baseUrl, + final StringBuilder result) { + // Add '?' if missing and add '&' if params already exist in base url + final int queryStart = baseUrl.indexOf('?'); + final int lastChar = result.length() - 1; + if (queryStart == -1) + result.append('?'); + else if (queryStart < lastChar && baseUrl.charAt(lastChar) != '&') + result.append('&'); + return result; + } + + private static StringBuilder addParam(final Object key, Object value, + final StringBuilder result) { + if (value != null && value.getClass().isArray()) + value = arrayToList(value); + + if (value instanceof Iterable) { + Iterator iterator = ((Iterable) value).iterator(); + while (iterator.hasNext()) { + result.append(key); + result.append("[]="); + Object element = iterator.next(); + if (element != null) + result.append(element); + if (iterator.hasNext()) + result.append("&"); + } + } else { + result.append(key); + result.append("="); + if (value != null) + result.append(value); + } + + return result; + } + + /** + * Specify the {@link ConnectionFactory} used to create new requests. + */ + public static void setConnectionFactory(final ConnectionFactory connectionFactory) { + if (connectionFactory == null) + CONNECTION_FACTORY = ConnectionFactory.DEFAULT; + else + CONNECTION_FACTORY = connectionFactory; + } + + /** + * Operation that handles executing a callback once complete and handling + * nested exceptions + * + * @param + */ + protected static abstract class Operation implements Callable { + + /** + * Run operation + * + * @return result + * @throws HttpRequestException + * @throws IOException + */ + protected abstract V run() throws HttpRequestException, IOException; + + /** + * Operation complete callback + * + * @throws IOException + */ + protected abstract void done() throws IOException; + + public V call() throws HttpRequestException { + boolean thrown = false; + try { + return run(); + } catch (HttpRequestException e) { + thrown = true; + throw e; + } catch (IOException e) { + thrown = true; + throw new HttpRequestException(e); + } finally { + try { + done(); + } catch (IOException e) { + if (!thrown) + throw new HttpRequestException(e); + } + } + } + } + + /** + * Class that ensures a {@link Closeable} gets closed with proper exception + * handling. + * + * @param + */ + protected static abstract class CloseOperation extends Operation { + + private final Closeable closeable; + + private final boolean ignoreCloseExceptions; + + /** + * Create closer for operation + * + * @param closeable + * @param ignoreCloseExceptions + */ + protected CloseOperation(final Closeable closeable, + final boolean ignoreCloseExceptions) { + this.closeable = closeable; + this.ignoreCloseExceptions = ignoreCloseExceptions; + } + + @Override + protected void done() throws IOException { + if (closeable instanceof Flushable) + ((Flushable) closeable).flush(); + if (ignoreCloseExceptions) + try { + closeable.close(); + } catch (IOException e) { + // Ignored + } + else + closeable.close(); + } + } + + /** + * Class that and ensures a {@link Flushable} gets flushed with proper + * exception handling. + * + * @param + */ + protected static abstract class FlushOperation extends Operation { + + private final Flushable flushable; + + /** + * Create flush operation + * + * @param flushable + */ + protected FlushOperation(final Flushable flushable) { + this.flushable = flushable; + } + + @Override + protected void done() throws IOException { + flushable.flush(); + } + } + + + + /** + * Represents array of any type as list of objects so we can easily iterate over it + * @param array of elements + * @return list with the same elements + */ + private static List arrayToList(final Object array) { + if (array instanceof Object[]) + return Arrays.asList((Object[]) array); + + List result = new ArrayList(); + // Arrays of the primitive types can't be cast to array of Object, so this: + if (array instanceof int[]) + for (int value : (int[]) array) result.add(value); + else if (array instanceof boolean[]) + for (boolean value : (boolean[]) array) result.add(value); + else if (array instanceof long[]) + for (long value : (long[]) array) result.add(value); + else if (array instanceof float[]) + for (float value : (float[]) array) result.add(value); + else if (array instanceof double[]) + for (double value : (double[]) array) result.add(value); + else if (array instanceof short[]) + for (short value : (short[]) array) result.add(value); + else if (array instanceof byte[]) + for (byte value : (byte[]) array) result.add(value); + else if (array instanceof char[]) + for (char value : (char[]) array) result.add(value); + return result; + } + + /** + * Encode the given URL as an ASCII {@link String} + *

+ * This method ensures the path and query segments of the URL are properly + * encoded such as ' ' characters being encoded to '%20' or any UTF-8 + * characters that are non-ASCII. No encoding of URLs is done by default by + * the {@link HttpRequest} constructors and so if URL encoding is needed this + * method should be called before calling the {@link HttpRequest} constructor. + * + * @param url + * @return encoded URL + * @throws HttpRequestException + */ + public static String encode(final String url) + throws HttpRequestException { + URL parsed; + try { + parsed = new URL(url.toString()); + } catch (IOException e) { + throw new HttpRequestException(e); + } + + String host = parsed.getHost(); + int port = parsed.getPort(); + if (port != -1) + host = host + ':' + Integer.toString(port); + + try { + String encoded = new URI(parsed.getProtocol(), host, parsed.getPath(), + parsed.getQuery(), null).toASCIIString(); + int paramsStart = encoded.indexOf('?'); + if (paramsStart > 0 && paramsStart + 1 < encoded.length()) + encoded = encoded.substring(0, paramsStart + 1) + + encoded.substring(paramsStart + 1).replace("+", "%2B"); + return encoded; + } catch (URISyntaxException e) { + IOException io = new IOException("Parsing URI failed"); + io.initCause(e); + throw new HttpRequestException(io); + } + } + + /** + * Append given map as query parameters to the base URL + *

+ * Each map entry's key will be a parameter name and the value's + * {@link Object#toString()} will be the parameter value. + * + * @param url + * @param params + * @return URL with appended query params + */ + public static String append(final String url, final Map params) { + final String baseUrl = url.toString(); + if (params == null || params.isEmpty()) + return baseUrl; + + final StringBuilder result = new StringBuilder(baseUrl); + + addPathSeparator(baseUrl, result); + addParamPrefix(baseUrl, result); + + Entry entry; + Iterator iterator = params.entrySet().iterator(); + entry = (Entry) iterator.next(); + addParam(entry.getKey().toString(), entry.getValue(), result); + + while (iterator.hasNext()) { + result.append('&'); + entry = (Entry) iterator.next(); + addParam(entry.getKey().toString(), entry.getValue(), result); + } + + return result.toString(); + } + + /** + * Append given name/value pairs as query parameters to the base URL + *

+ * The params argument is interpreted as a sequence of name/value pairs so the + * given number of params must be divisible by 2. + * + * @param url + * @param params + * name/value pairs + * @return URL with appended query params + */ + public static String append(final String url, final Object... params) { + final String baseUrl = url.toString(); + if (params == null || params.length == 0) + return baseUrl; + + if (params.length % 2 != 0) + throw new IllegalArgumentException( + "Must specify an even number of parameter names/values"); + + final StringBuilder result = new StringBuilder(baseUrl); + + addPathSeparator(baseUrl, result); + addParamPrefix(baseUrl, result); + + addParam(params[0], params[1], result); + + for (int i = 2; i < params.length; i += 2) { + result.append('&'); + addParam(params[i], params[i + 1], result); + } + + return result.toString(); + } + + /** + * GET请求 + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest get(final String url) + throws HttpRequestException { + return new HttpRequest(url, MethodType.GET); + } + + /** + * GET请求 + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest get(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.GET); + } + + /** + * 带参数的GET请求 + * @see #append(String, Map) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest get(final String baseUrl, final Map params, final boolean encode) { + String url = append(baseUrl, params); + return get(encode ? encode(url) : url); + } + + /** + * Start a 'GET' request to the given URL along with the query params + * + * @param baseUrl + * @param encode + * true to encode the full URL + * @param params + * the name/value query parameter pairs to include as part of the + * baseUrl + * + * @see #append(String, Object...) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest get(final String baseUrl, final boolean encode, final Object... params) { + String url = append(baseUrl, params); + return get(encode ? encode(url) : url); + } + + /** + * Start a 'POST' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest post(final String url) + throws HttpRequestException { + return new HttpRequest(url, MethodType.POST); + } + + /** + * Start a 'POST' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest post(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.POST); + } + + /** + * Start a 'POST' request to the given URL along with the query params + * + * @param baseUrl + * @param params + * the query parameters to include as part of the baseUrl + * @param encode + * true to encode the full URL + * + * @see #append(String, Map) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest post(final String baseUrl, + final Map params, final boolean encode) { + String url = append(baseUrl, params); + return post(encode ? encode(url) : url); + } + + /** + * Start a 'POST' request to the given URL along with the query params + * + * @param baseUrl + * @param encode + * true to encode the full URL + * @param params + * the name/value query parameter pairs to include as part of the + * baseUrl + * + * @see #append(String, Object...) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest post(final String baseUrl, + final boolean encode, final Object... params) { + String url = append(baseUrl, params); + return post(encode ? encode(url) : url); + } + + /** + * Start a 'PUT' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest put(final String url) + throws HttpRequestException { + return new HttpRequest(url, MethodType.PUT); + } + + /** + * Start a 'PUT' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest put(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.PUT); + } + + /** + * Start a 'PUT' request to the given URL along with the query params + * + * @param baseUrl + * @param params + * the query parameters to include as part of the baseUrl + * @param encode + * true to encode the full URL + * + * @see #append(String, Map) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest put(final String baseUrl, + final Map params, final boolean encode) { + String url = append(baseUrl, params); + return put(encode ? encode(url) : url); + } + + /** + * Start a 'PUT' request to the given URL along with the query params + * + * @param baseUrl + * @param encode + * true to encode the full URL + * @param params + * the name/value query parameter pairs to include as part of the + * baseUrl + * + * @see #append(String, Object...) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest put(final String baseUrl, + final boolean encode, final Object... params) { + String url = append(baseUrl, params); + return put(encode ? encode(url) : url); + } + + /** + * Start a 'DELETE' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest delete(final String url) + throws HttpRequestException { + return new HttpRequest(url, MethodType.DELETE); + } + + /** + * Start a 'DELETE' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest delete(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.DELETE); + } + + /** + * Start a 'DELETE' request to the given URL along with the query params + * + * @param baseUrl + * @param params + * The query parameters to include as part of the baseUrl + * @param encode + * true to encode the full URL + * + * @see #append(String, Map) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest delete(final String baseUrl, + final Map params, final boolean encode) { + String url = append(baseUrl, params); + return delete(encode ? encode(url) : url); + } + + /** + * Start a 'DELETE' request to the given URL along with the query params + * + * @param baseUrl + * @param encode + * true to encode the full URL + * @param params + * the name/value query parameter pairs to include as part of the + * baseUrl + * + * @see #append(String, Object...) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest delete(final String baseUrl, + final boolean encode, final Object... params) { + String url = append(baseUrl, params); + return delete(encode ? encode(url) : url); + } + + /** + * Start a 'HEAD' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest head(final String url) + throws HttpRequestException { + return new HttpRequest(url, MethodType.HEAD); + } + + /** + * Start a 'HEAD' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest head(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.HEAD); + } + + /** + * Start a 'HEAD' request to the given URL along with the query params + * + * @param baseUrl + * @param params + * The query parameters to include as part of the baseUrl + * @param encode + * true to encode the full URL + * + * @see #append(String, Map) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest head(final String baseUrl, + final Map params, final boolean encode) { + String url = append(baseUrl, params); + return head(encode ? encode(url) : url); + } + + /** + * Start a 'GET' request to the given URL along with the query params + * + * @param baseUrl + * @param encode + * true to encode the full URL + * @param params + * the name/value query parameter pairs to include as part of the + * baseUrl + * + * @see #append(String, Object...) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest head(final String baseUrl, + final boolean encode, final Object... params) { + String url = append(baseUrl, params); + return head(encode ? encode(url) : url); + } + + /** + * Start an 'OPTIONS' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest options(final String url) + throws HttpRequestException { + return new HttpRequest(url, MethodType.OPTIONS); + } + + /** + * Start an 'OPTIONS' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest options(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.OPTIONS); + } + + /** + * Start a 'TRACE' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest trace(final String url) + throws HttpRequestException { + return new HttpRequest(url, MethodType.TRACE); + } + + /** + * Start a 'TRACE' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest trace(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.TRACE); + } + + /** + * Set the 'http.keepAlive' property to the given value. + *

+ * This setting will apply to all requests. + * + * @param keepAlive + */ + public static void keepAlive(final boolean keepAlive) { + setProperty("http.keepAlive", Boolean.toString(keepAlive)); + } + + /** + * Set the 'http.maxConnections' property to the given value. + *

+ * This setting will apply to all requests. + * + * @param maxConnections + */ + public static void maxConnections(final int maxConnections) { + setProperty("http.maxConnections", Integer.toString(maxConnections)); + } + + /** + * Set the 'http.proxyHost' and 'https.proxyHost' properties to the given host + * value. + *

+ * This setting will apply to all requests. + * + * @param host + */ + public static void proxyHost(final String host) { + setProperty("http.proxyHost", host); + setProperty("https.proxyHost", host); + } + + /** + * Set the 'http.proxyPort' and 'https.proxyPort' properties to the given port + * number. + *

+ * This setting will apply to all requests. + * + * @param port + */ + public static void proxyPort(final int port) { + final String portValue = Integer.toString(port); + setProperty("http.proxyPort", portValue); + setProperty("https.proxyPort", portValue); + } + + /** + * Set the 'http.nonProxyHosts' property to the given host values. + *

+ * Hosts will be separated by a '|' character. + *

+ * This setting will apply to all requests. + * + * @param hosts + */ + public static void nonProxyHosts(final String... hosts) { + if (hosts != null && hosts.length > 0) { + StringBuilder separated = new StringBuilder(); + int last = hosts.length - 1; + for (int i = 0; i < last; i++) + separated.append(hosts[i]).append('|'); + separated.append(hosts[last]); + setProperty("http.nonProxyHosts", separated.toString()); + } else + setProperty("http.nonProxyHosts", null); + } + + /** + * Set property to given value. + *

+ * Specifying a null value will cause the property to be cleared + * + * @param name + * @param value + * @return previous value + */ + private static String setProperty(final String name, final String value) { + final PrivilegedAction action; + if (value != null) + action = new PrivilegedAction() { + + public String run() { + return System.setProperty(name, value); + } + }; + else + action = new PrivilegedAction() { + + public String run() { + return System.clearProperty(name); + } + }; + return AccessController.doPrivileged(action); + } + + private HttpURLConnection connection = null; + + private final URL url; + + private final String requestMethod; + + private RequestOutputStream output; + + private boolean multipart; + + private boolean form; + + private boolean ignoreCloseExceptions = true; + + private boolean uncompress = false; + + private int bufferSize = 8192; + + private long totalSize = -1; + + private long totalWritten = 0; + + private String httpProxyHost; + + private int httpProxyPort; + + private UploadProgress progress = UploadProgress.DEFAULT; + + /** + * Create HTTP connection wrapper + * + * @param url Remote resource URL. + * @param method HTTP request method (e.g., "GET", "POST"). + * @throws HttpRequestException + */ + public HttpRequest(final String url, final String method) + throws HttpRequestException { + try { + this.url = new URL(url.toString()); + } catch (MalformedURLException e) { + throw new HttpRequestException(e); + } + this.requestMethod = method; + } + + /** + * Create HTTP connection wrapper + * + * @param url Remote resource URL. + * @param method HTTP request method (e.g., "GET", "POST"). + * @throws HttpRequestException + */ + public HttpRequest(final URL url, final String method) + throws HttpRequestException { + this.url = url; + this.requestMethod = method; + } + + private Proxy createProxy() { + return new Proxy(HTTP, new InetSocketAddress(httpProxyHost, httpProxyPort)); + } + + private HttpURLConnection createConnection() { + try { + final HttpURLConnection connection; + if (httpProxyHost != null) + connection = CONNECTION_FACTORY.create(url, createProxy()); + else + connection = CONNECTION_FACTORY.create(url); + connection.setRequestMethod(requestMethod); + return connection; + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + @Override + public String toString() { + return method() + ' ' + url(); + } + + /** + * Get underlying connection + * + * @return connection + */ + public HttpURLConnection getConnection() { + if (connection == null) + connection = createConnection(); + return connection; + } + + /** + * Set whether or not to ignore exceptions that occur from calling + * {@link Closeable#close()} + *

+ * The default value of this setting is true + * + * @param ignore + * @return this request + */ + public HttpRequest ignoreCloseExceptions(final boolean ignore) { + ignoreCloseExceptions = ignore; + return this; + } + + /** + * Get whether or not exceptions thrown by {@link Closeable#close()} are + * ignored + * + * @return true if ignoring, false if throwing + */ + public boolean ignoreCloseExceptions() { + return ignoreCloseExceptions; + } + + /** + * Get the status code of the response + * + * @return the response code + * @throws HttpRequestException + */ + public int code() throws HttpRequestException { + try { + closeOutput(); + return getConnection().getResponseCode(); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Set the value of the given {@link AtomicInteger} to the status code of the + * response + * + * @param output + * @return this request + * @throws HttpRequestException + */ + public HttpRequest code(final AtomicInteger output) + throws HttpRequestException { + output.set(code()); + return this; + } + + /** + * Is the response code a 200 OK? + * + * @return true if 200, false otherwise + * @throws HttpRequestException + */ + public boolean ok() throws HttpRequestException { + return HTTP_OK == code(); + } + + /** + * Is the response code a 201 Created? + * + * @return true if 201, false otherwise + * @throws HttpRequestException + */ + public boolean created() throws HttpRequestException { + return HTTP_CREATED == code(); + } + + /** + * Is the response code a 204 No Content? + * + * @return true if 204, false otherwise + * @throws HttpRequestException + */ + public boolean noContent() throws HttpRequestException { + return HTTP_NO_CONTENT == code(); + } + + /** + * Is the response code a 500 Internal Server Error? + * + * @return true if 500, false otherwise + * @throws HttpRequestException + */ + public boolean serverError() throws HttpRequestException { + return HTTP_INTERNAL_ERROR == code(); + } + + /** + * Is the response code a 400 Bad Request? + * + * @return true if 400, false otherwise + * @throws HttpRequestException + */ + public boolean badRequest() throws HttpRequestException { + return HTTP_BAD_REQUEST == code(); + } + + /** + * Is the response code a 404 Not Found? + * + * @return true if 404, false otherwise + * @throws HttpRequestException + */ + public boolean notFound() throws HttpRequestException { + return HTTP_NOT_FOUND == code(); + } + + /** + * Is the response code a 304 Not Modified? + * + * @return true if 304, false otherwise + * @throws HttpRequestException + */ + public boolean notModified() throws HttpRequestException { + return HTTP_NOT_MODIFIED == code(); + } + + /** + * Get status message of the response + * + * @return message + * @throws HttpRequestException + */ + public String message() throws HttpRequestException { + try { + closeOutput(); + return getConnection().getResponseMessage(); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Disconnect the connection + * + * @return this request + */ + public HttpRequest disconnect() { + getConnection().disconnect(); + return this; + } + + /** + * Set chunked streaming mode to the given size + * + * @param size + * @return this request + */ + public HttpRequest chunk(final int size) { + getConnection().setChunkedStreamingMode(size); + return this; + } + + /** + * Set the size used when buffering and copying between streams + *

+ * This size is also used for send and receive buffers created for both char + * and byte arrays + *

+ * The default buffer size is 8,192 bytes + * + * @param size + * @return this request + */ + public HttpRequest bufferSize(final int size) { + if (size < 1) + throw new IllegalArgumentException("Size must be greater than zero"); + bufferSize = size; + return this; + } + + /** + * Get the configured buffer size + *

+ * The default buffer size is 8,192 bytes + * + * @return buffer size + */ + public int bufferSize() { + return bufferSize; + } + + /** + * Set whether or not the response body should be automatically uncompressed + * when read from. + *

+ * This will only affect requests that have the 'Content-Encoding' response + * header set to 'gzip'. + *

+ * This causes all receive methods to use a {@link GZIPInputStream} when + * applicable so that higher level streams and readers can read the data + * uncompressed. + *

+ * Setting this option does not cause any request headers to be set + * automatically so {@link #acceptGzipEncoding()} should be used in + * conjunction with this setting to tell the server to gzip the response. + * + * @param uncompress + * @return this request + */ + public HttpRequest uncompress(final boolean uncompress) { + this.uncompress = uncompress; + return this; + } + + /** + * Create byte array output stream + * + * @return stream + */ + protected ByteArrayOutputStream byteStream() { + final int size = contentLength(); + if (size > 0) + return new ByteArrayOutputStream(size); + else + return new ByteArrayOutputStream(); + } + + /** + * Get response as {@link String} in given character set + *

+ * This will fall back to using the UTF-8 character set if the given charset + * is null + * + * @param charset + * @return string + * @throws HttpRequestException + */ + public String body(final String charset) throws HttpRequestException { + final ByteArrayOutputStream output = byteStream(); + try { + copy(buffer(), output); + return output.toString(getValidCharset(charset)); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Get response as {@link String} using character set returned from + * {@link #charset()} + * + * @return string + * @throws HttpRequestException + */ + public String body() throws HttpRequestException { + return body(charset()); + } + + /** + * Get the response body as a {@link String} and set it as the value of the + * given reference. + * + * @param output + * @return this request + * @throws HttpRequestException + */ + public HttpRequest body(final AtomicReference output) throws HttpRequestException { + output.set(body()); + return this; + } + + /** + * Get the response body as a {@link String} and set it as the value of the + * given reference. + * + * @param output + * @param charset + * @return this request + * @throws HttpRequestException + */ + public HttpRequest body(final AtomicReference output, final String charset) throws HttpRequestException { + output.set(body(charset)); + return this; + } + + + /** + * Is the response body empty? + * + * @return true if the Content-Length response header is 0, false otherwise + * @throws HttpRequestException + */ + public boolean isBodyEmpty() throws HttpRequestException { + return contentLength() == 0; + } + + /** + * Get response as byte array + * + * @return byte array + * @throws HttpRequestException + */ + public byte[] bytes() throws HttpRequestException { + final ByteArrayOutputStream output = byteStream(); + try { + copy(buffer(), output); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return output.toByteArray(); + } + + /** + * Get response in a buffered stream + * + * @see #bufferSize(int) + * @return stream + * @throws HttpRequestException + */ + public BufferedInputStream buffer() throws HttpRequestException { + return new BufferedInputStream(stream(), bufferSize); + } + + /** + * Get stream to response body + * + * @return stream + * @throws HttpRequestException + */ + public InputStream stream() throws HttpRequestException { + InputStream stream; + if (code() < HTTP_BAD_REQUEST) + try { + stream = getConnection().getInputStream(); + } catch (IOException e) { + throw new HttpRequestException(e); + } + else { + stream = getConnection().getErrorStream(); + if (stream == null) + try { + stream = getConnection().getInputStream(); + } catch (IOException e) { + if (contentLength() > 0) + throw new HttpRequestException(e); + else + stream = new ByteArrayInputStream(new byte[0]); + } + } + + if (!uncompress || !Header.ENCODING_GZIP.equals(contentEncoding())) + return stream; + else + try { + return new GZIPInputStream(stream); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Get reader to response body using given character set. + *

+ * This will fall back to using the UTF-8 character set if the given charset + * is null + * + * @param charset + * @return reader + * @throws HttpRequestException + */ + public InputStreamReader reader(final String charset) + throws HttpRequestException { + try { + return new InputStreamReader(stream(), getValidCharset(charset)); + } catch (UnsupportedEncodingException e) { + throw new HttpRequestException(e); + } + } + + /** + * Get reader to response body using the character set returned from + * {@link #charset()} + * + * @return reader + * @throws HttpRequestException + */ + public InputStreamReader reader() throws HttpRequestException { + return reader(charset()); + } + + /** + * Get buffered reader to response body using the given character set r and + * the configured buffer size + * + * + * @see #bufferSize(int) + * @param charset + * @return reader + * @throws HttpRequestException + */ + public BufferedReader bufferedReader(final String charset) + throws HttpRequestException { + return new BufferedReader(reader(charset), bufferSize); + } + + /** + * Get buffered reader to response body using the character set returned from + * {@link #charset()} and the configured buffer size + * + * @see #bufferSize(int) + * @return reader + * @throws HttpRequestException + */ + public BufferedReader bufferedReader() throws HttpRequestException { + return bufferedReader(charset()); + } + + /** + * Stream response body to file + * + * @param file + * @return this request + * @throws HttpRequestException + */ + public HttpRequest receive(final File file) throws HttpRequestException { + final OutputStream output; + try { + output = new BufferedOutputStream(new FileOutputStream(file), bufferSize); + } catch (FileNotFoundException e) { + throw new HttpRequestException(e); + } + return new CloseOperation(output, ignoreCloseExceptions) { + + @Override + protected HttpRequest run() throws HttpRequestException, IOException { + return receive(output); + } + }.call(); + } + + /** + * Stream response to given output stream + * + * @param output + * @return this request + * @throws HttpRequestException + */ + public HttpRequest receive(final OutputStream output) + throws HttpRequestException { + try { + return copy(buffer(), output); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Stream response to given print stream + * + * @param output + * @return this request + * @throws HttpRequestException + */ + public HttpRequest receive(final PrintStream output) + throws HttpRequestException { + return receive((OutputStream) output); + } + + /** + * Receive response into the given appendable + * + * @param appendable + * @return this request + * @throws HttpRequestException + */ + public HttpRequest receive(final Appendable appendable) + throws HttpRequestException { + final BufferedReader reader = bufferedReader(); + return new CloseOperation(reader, ignoreCloseExceptions) { + + @Override + public HttpRequest run() throws IOException { + final CharBuffer buffer = CharBuffer.allocate(bufferSize); + int read; + while ((read = reader.read(buffer)) != -1) { + buffer.rewind(); + appendable.append(buffer, 0, read); + buffer.rewind(); + } + return HttpRequest.this; + } + }.call(); + } + + /** + * Receive response into the given writer + * + * @param writer + * @return this request + * @throws HttpRequestException + */ + public HttpRequest receive(final Writer writer) throws HttpRequestException { + final BufferedReader reader = bufferedReader(); + return new CloseOperation(reader, ignoreCloseExceptions) { + + @Override + public HttpRequest run() throws IOException { + return copy(reader, writer); + } + }.call(); + } + + /** + * Set read timeout on connection to given value + * + * @param timeout + * @return this request + */ + public HttpRequest readTimeout(final int timeout) { + getConnection().setReadTimeout(timeout); + return this; + } + + /** + * Set connect timeout on connection to given value + * + * @param timeout + * @return this request + */ + public HttpRequest connectTimeout(final int timeout) { + getConnection().setConnectTimeout(timeout); + return this; + } + + /** + * Set header name to given value + * + * @param name + * @param value + * @return this request + */ + public HttpRequest header(final String name, final String value) { + getConnection().setRequestProperty(name, value); + return this; + } + + /** + * Set header name to given value + * + * @param name + * @param value + * @return this request + */ + public HttpRequest header(final String name, final Number value) { + return header(name, value != null ? value.toString() : null); + } + + /** + * Set all headers found in given map where the keys are the header names and + * the values are the header values + * + * @param headers + * @return this request + */ + public HttpRequest headers(final Map headers) { + if (!headers.isEmpty()) + for (Entry header : headers.entrySet()) + header(header); + return this; + } + + /** + * Set header to have given entry's key as the name and value as the value + * + * @param header + * @return this request + */ + public HttpRequest header(final Entry header) { + return header(header.getKey(), header.getValue()); + } + + /** + * Get a response header + * + * @param name + * @return response header + * @throws HttpRequestException + */ + public String header(final String name) throws HttpRequestException { + closeOutputQuietly(); + return getConnection().getHeaderField(name); + } + + /** + * Get all the response headers + * + * @return map of response header names to their value(s) + * @throws HttpRequestException + */ + public Map> headers() throws HttpRequestException { + closeOutputQuietly(); + return getConnection().getHeaderFields(); + } + + /** + * Get a date header from the response falling back to returning -1 if the + * header is missing or parsing fails + * + * @param name + * @return date, -1 on failures + * @throws HttpRequestException + */ + public long dateHeader(final String name) throws HttpRequestException { + return dateHeader(name, -1L); + } + + /** + * Get a date header from the response falling back to returning the given + * default value if the header is missing or parsing fails + * + * @param name + * @param defaultValue + * @return date, default value on failures + * @throws HttpRequestException + */ + public long dateHeader(final String name, final long defaultValue) + throws HttpRequestException { + closeOutputQuietly(); + return getConnection().getHeaderFieldDate(name, defaultValue); + } + + /** + * Get an integer header from the response falling back to returning -1 if the + * header is missing or parsing fails + * + * @param name + * @return header value as an integer, -1 when missing or parsing fails + * @throws HttpRequestException + */ + public int intHeader(final String name) throws HttpRequestException { + return intHeader(name, -1); + } + + /** + * Get an integer header value from the response falling back to the given + * default value if the header is missing or if parsing fails + * + * @param name + * @param defaultValue + * @return header value as an integer, default value when missing or parsing + * fails + * @throws HttpRequestException + */ + public int intHeader(final String name, final int defaultValue) + throws HttpRequestException { + closeOutputQuietly(); + return getConnection().getHeaderFieldInt(name, defaultValue); + } + + /** + * Get all values of the given header from the response + * + * @param name + * @return non-null but possibly empty array of {@link String} header values + */ + public String[] headers(final String name) { + final Map> headers = headers(); + if (headers == null || headers.isEmpty()) + return EMPTY_STRINGS; + + final List values = headers.get(name); + if (values != null && !values.isEmpty()) + return values.toArray(new String[values.size()]); + else + return EMPTY_STRINGS; + } + + /** + * Get parameter with given name from header value in response + * + * @param headerName + * @param paramName + * @return parameter value or null if missing + */ + public String parameter(final String headerName, final String paramName) { + return getParam(header(headerName), paramName); + } + + /** + * Get all parameters from header value in response + *

+ * This will be all key=value pairs after the first ';' that are separated by + * a ';' + * + * @param headerName + * @return non-null but possibly empty map of parameter headers + */ + public Map parameters(final String headerName) { + return getParams(header(headerName)); + } + + /** + * Get parameter values from header value + * + * @param header + * @return parameter value or null if none + */ + protected Map getParams(final String header) { + if (header == null || header.length() == 0) + return Collections.emptyMap(); + + final int headerLength = header.length(); + int start = header.indexOf(';') + 1; + if (start == 0 || start == headerLength) + return Collections.emptyMap(); + + int end = header.indexOf(';', start); + if (end == -1) + end = headerLength; + + Map params = new LinkedHashMap(); + while (start < end) { + int nameEnd = header.indexOf('=', start); + if (nameEnd != -1 && nameEnd < end) { + String name = header.substring(start, nameEnd).trim(); + if (name.length() > 0) { + String value = header.substring(nameEnd + 1, end).trim(); + int length = value.length(); + if (length != 0) + if (length > 2 && '"' == value.charAt(0) + && '"' == value.charAt(length - 1)) + params.put(name, value.substring(1, length - 1)); + else + params.put(name, value); + } + } + + start = end + 1; + end = header.indexOf(';', start); + if (end == -1) + end = headerLength; + } + + return params; + } + + /** + * Get parameter value from header value + * + * @param value + * @param paramName + * @return parameter value or null if none + */ + protected String getParam(final String value, final String paramName) { + if (value == null || value.length() == 0) + return null; + + final int length = value.length(); + int start = value.indexOf(';') + 1; + if (start == 0 || start == length) + return null; + + int end = value.indexOf(';', start); + if (end == -1) + end = length; + + while (start < end) { + int nameEnd = value.indexOf('=', start); + if (nameEnd != -1 && nameEnd < end + && paramName.equals(value.substring(start, nameEnd).trim())) { + String paramValue = value.substring(nameEnd + 1, end).trim(); + int valueLength = paramValue.length(); + if (valueLength != 0) + if (valueLength > 2 && '"' == paramValue.charAt(0) + && '"' == paramValue.charAt(valueLength - 1)) + return paramValue.substring(1, valueLength - 1); + else + return paramValue; + } + + start = end + 1; + end = value.indexOf(';', start); + if (end == -1) + end = length; + } + + return null; + } + + /** + * Get 'charset' parameter from 'Content-Type' response header + * + * @return charset or null if none + */ + public String charset() { + return parameter(Header.HEADER_CONTENT_TYPE, Header.PARAM_CHARSET); + } + + /** + * Set the 'User-Agent' header to given value + * + * @param userAgent + * @return this request + */ + public HttpRequest userAgent(final String userAgent) { + return header(Header.HEADER_USER_AGENT, userAgent); + } + + /** + * Set the 'Referer' header to given value + * + * @param referer + * @return this request + */ + public HttpRequest referer(final String referer) { + return header(Header.HEADER_REFERER, referer); + } + + /** + * Set value of {@link HttpURLConnection#setUseCaches(boolean)} + * + * @param useCaches + * @return this request + */ + public HttpRequest useCaches(final boolean useCaches) { + getConnection().setUseCaches(useCaches); + return this; + } + + /** + * Set the 'Accept-Encoding' header to given value + * + * @param acceptEncoding + * @return this request + */ + public HttpRequest acceptEncoding(final String acceptEncoding) { + return header(Header.HEADER_ACCEPT_ENCODING, acceptEncoding); + } + + /** + * Set the 'Accept-Encoding' header to 'gzip' + * + * @see #uncompress(boolean) + * @return this request + */ + public HttpRequest acceptGzipEncoding() { + return acceptEncoding(Header.ENCODING_GZIP); + } + + /** + * Set the 'Accept-Charset' header to given value + * + * @param acceptCharset + * @return this request + */ + public HttpRequest acceptCharset(final String acceptCharset) { + return header(Header.HEADER_ACCEPT_CHARSET, acceptCharset); + } + + /** + * Get the 'Content-Encoding' header from the response + * + * @return this request + */ + public String contentEncoding() { + return header(Header.HEADER_CONTENT_ENCODING); + } + + /** + * Get the 'Server' header from the response + * + * @return server + */ + public String server() { + return header(Header.HEADER_SERVER); + } + + /** + * Get the 'Date' header from the response + * + * @return date value, -1 on failures + */ + public long date() { + return dateHeader(Header.HEADER_DATE); + } + + /** + * Get the 'Cache-Control' header from the response + * + * @return cache control + */ + public String cacheControl() { + return header(Header.HEADER_CACHE_CONTROL); + } + + /** + * Get the 'ETag' header from the response + * + * @return entity tag + */ + public String eTag() { + return header(Header.HEADER_ETAG); + } + + /** + * Get the 'Expires' header from the response + * + * @return expires value, -1 on failures + */ + public long expires() { + return dateHeader(Header.HEADER_EXPIRES); + } + + /** + * Get the 'Last-Modified' header from the response + * + * @return last modified value, -1 on failures + */ + public long lastModified() { + return dateHeader(Header.HEADER_LAST_MODIFIED); + } + + /** + * Get the 'Location' header from the response + * + * @return location + */ + public String location() { + return header(Header.HEADER_LOCATION); + } + + /** + * Set the 'Authorization' header to given value + * + * @param authorization + * @return this request + */ + public HttpRequest authorization(final String authorization) { + return header(Header.HEADER_AUTHORIZATION, authorization); + } + + /** + * Set the 'Proxy-Authorization' header to given value + * + * @param proxyAuthorization + * @return this request + */ + public HttpRequest proxyAuthorization(final String proxyAuthorization) { + return header(Header.HEADER_PROXY_AUTHORIZATION, proxyAuthorization); + } + + /** + * Set the 'Authorization' header to given values in Basic authentication + * format + * + * @param name + * @param password + * @return this request + */ + public HttpRequest basic(final String name, final String password) { + return authorization("Basic " + Base64.encode(name + ':' + password)); + } + + /** + * Set the 'Proxy-Authorization' header to given values in Basic authentication + * format + * + * @param name + * @param password + * @return this request + */ + public HttpRequest proxyBasic(final String name, final String password) { + return proxyAuthorization("Basic " + Base64.encode(name + ':' + password)); + } + + /** + * Set the 'If-Modified-Since' request header to the given value + * + * @param ifModifiedSince + * @return this request + */ + public HttpRequest ifModifiedSince(final long ifModifiedSince) { + getConnection().setIfModifiedSince(ifModifiedSince); + return this; + } + + /** + * Set the 'If-None-Match' request header to the given value + * + * @param ifNoneMatch + * @return this request + */ + public HttpRequest ifNoneMatch(final String ifNoneMatch) { + return header(Header.HEADER_IF_NONE_MATCH, ifNoneMatch); + } + + /** + * Set the 'Content-Type' request header to the given value + * + * @param contentType + * @return this request + */ + public HttpRequest contentType(final String contentType) { + return contentType(contentType, null); + } + + /** + * Set the 'Content-Type' request header to the given value and charset + * + * @param contentType + * @param charset + * @return this request + */ + public HttpRequest contentType(final String contentType, final String charset) { + if (charset != null && charset.length() > 0) { + final String separator = "; " + Header.PARAM_CHARSET + '='; + return header(Header.HEADER_CONTENT_TYPE, contentType + separator + charset); + } else + return header(Header.HEADER_CONTENT_TYPE, contentType); + } + + /** + * Get the 'Content-Type' header from the response + * + * @return response header value + */ + public String contentType() { + return header(Header.HEADER_CONTENT_TYPE); + } + + /** + * Get the 'Content-Length' header from the response + * + * @return response header value + */ + public int contentLength() { + return intHeader(Header.HEADER_CONTENT_LENGTH); + } + + /** + * Set the 'Content-Length' request header to the given value + * + * @param contentLength + * @return this request + */ + public HttpRequest contentLength(final String contentLength) { + return contentLength(Integer.parseInt(contentLength)); + } + + /** + * Set the 'Content-Length' request header to the given value + * + * @param contentLength + * @return this request + */ + public HttpRequest contentLength(final int contentLength) { + getConnection().setFixedLengthStreamingMode(contentLength); + return this; + } + + /** + * Set the 'Accept' header to given value + * + * @param accept + * @return this request + */ + public HttpRequest accept(final String accept) { + return header(Header.HEADER_ACCEPT, accept); + } + + /** + * Set the 'Accept' header to 'application/json' + * + * @return this request + */ + public HttpRequest acceptJson() { + return accept(Header.CONTENT_TYPE_JSON); + } + + /** + * Copy from input stream to output stream + * + * @param input + * @param output + * @return this request + * @throws IOException + */ + protected HttpRequest copy(final InputStream input, final OutputStream output) + throws IOException { + return new CloseOperation(input, ignoreCloseExceptions) { + + @Override + public HttpRequest run() throws IOException { + final byte[] buffer = new byte[bufferSize]; + int read; + while ((read = input.read(buffer)) != -1) { + output.write(buffer, 0, read); + totalWritten += read; + progress.onUpload(totalWritten, totalSize); + } + return HttpRequest.this; + } + }.call(); + } + + /** + * Copy from reader to writer + * + * @param input + * @param output + * @return this request + * @throws IOException + */ + protected HttpRequest copy(final Reader input, final Writer output) + throws IOException { + return new CloseOperation(input, ignoreCloseExceptions) { + + @Override + public HttpRequest run() throws IOException { + final char[] buffer = new char[bufferSize]; + int read; + while ((read = input.read(buffer)) != -1) { + output.write(buffer, 0, read); + totalWritten += read; + progress.onUpload(totalWritten, -1); + } + return HttpRequest.this; + } + }.call(); + } + + /** + * Set the UploadProgress callback for this request + * + * @param callback + * @return this request + */ + public HttpRequest progress(final UploadProgress callback) { + if (callback == null) + progress = UploadProgress.DEFAULT; + else + progress = callback; + return this; + } + + private HttpRequest incrementTotalSize(final long size) { + if (totalSize == -1) + totalSize = 0; + totalSize += size; + return this; + } + + /** + * Close output stream + * + * @return this request + * @throws HttpRequestException + * @throws IOException + */ + protected HttpRequest closeOutput() throws IOException { + progress(null); + if (output == null) + return this; + if (multipart) + output.write(CRLF + "--" + BOUNDARY + "--" + CRLF); + if (ignoreCloseExceptions) + try { + output.close(); + } catch (IOException ignored) { + // Ignored + } + else + output.close(); + output = null; + return this; + } + + /** + * Call {@link #closeOutput()} and re-throw a caught {@link IOException}s as + * an {@link HttpRequestException} + * + * @return this request + * @throws HttpRequestException + */ + protected HttpRequest closeOutputQuietly() throws HttpRequestException { + try { + return closeOutput(); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Open output stream + * + * @return this request + * @throws IOException + */ + protected HttpRequest openOutput() throws IOException { + if (output != null) + return this; + getConnection().setDoOutput(true); + final String charset = getParam( + getConnection().getRequestProperty(Header.HEADER_CONTENT_TYPE), Header.PARAM_CHARSET); + output = new RequestOutputStream(getConnection().getOutputStream(), charset, + bufferSize); + return this; + } + + /** + * Start part of a multipart + * + * @return this request + * @throws IOException + */ + protected HttpRequest startPart() throws IOException { + if (!multipart) { + multipart = true; + contentType(CONTENT_TYPE_MULTIPART).openOutput(); + output.write("--" + BOUNDARY + CRLF); + } else + output.write(CRLF + "--" + BOUNDARY + CRLF); + return this; + } + + /** + * Write part header + * + * @param name + * @param filename + * @return this request + * @throws IOException + */ + protected HttpRequest writePartHeader(final String name, final String filename) + throws IOException { + return writePartHeader(name, filename, null); + } + + /** + * Write part header + * + * @param name + * @param filename + * @param contentType + * @return this request + * @throws IOException + */ + protected HttpRequest writePartHeader(final String name, + final String filename, final String contentType) throws IOException { + final StringBuilder partBuffer = new StringBuilder(); + partBuffer.append("form-data; name=\"").append(name); + if (filename != null) + partBuffer.append("\"; filename=\"").append(filename); + partBuffer.append('"'); + partHeader("Content-Disposition", partBuffer.toString()); + if (contentType != null) + partHeader(Header.HEADER_CONTENT_TYPE, contentType); + return send(CRLF); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param part + * @return this request + */ + public HttpRequest part(final String name, final String part) { + return part(name, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, + final String part) throws HttpRequestException { + return part(name, filename, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param contentType + * value of the Content-Type part header + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, + final String contentType, final String part) throws HttpRequestException { + try { + startPart(); + writePartHeader(name, filename, contentType); + output.write(part); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return this; + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final Number part) + throws HttpRequestException { + return part(name, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, + final Number part) throws HttpRequestException { + return part(name, filename, part != null ? part.toString() : null); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final File part) + throws HttpRequestException { + return part(name, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, + final File part) throws HttpRequestException { + return part(name, filename, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param contentType + * value of the Content-Type part header + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, + final String contentType, final File part) throws HttpRequestException { + final InputStream stream; + try { + stream = new BufferedInputStream(new FileInputStream(part)); + incrementTotalSize(part.length()); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return part(name, filename, contentType, stream); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final InputStream part) + throws HttpRequestException { + return part(name, null, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param contentType + * value of the Content-Type part header + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, + final String contentType, final InputStream part) + throws HttpRequestException { + try { + startPart(); + writePartHeader(name, filename, contentType); + copy(part, output); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return this; + } + + /** + * Write a multipart header to the response body + * + * @param name + * @param value + * @return this request + * @throws HttpRequestException + */ + public HttpRequest partHeader(final String name, final String value) + throws HttpRequestException { + return send(name).send(": ").send(value).send(CRLF); + } + + /** + * Write contents of file to request body + * + * @param input + * @return this request + * @throws HttpRequestException + */ + public HttpRequest send(final File input) throws HttpRequestException { + final InputStream stream; + try { + stream = new BufferedInputStream(new FileInputStream(input)); + incrementTotalSize(input.length()); + } catch (FileNotFoundException e) { + throw new HttpRequestException(e); + } + return send(stream); + } + + /** + * Write byte array to request body + * + * @param input + * @return this request + * @throws HttpRequestException + */ + public HttpRequest send(final byte[] input) throws HttpRequestException { + if (input != null) + incrementTotalSize(input.length); + return send(new ByteArrayInputStream(input)); + } + + /** + * Write stream to request body + *

+ * The given stream will be closed once sending completes + * + * @param input + * @return this request + * @throws HttpRequestException + */ + public HttpRequest send(final InputStream input) throws HttpRequestException { + try { + openOutput(); + copy(input, output); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return this; + } + + /** + * Write reader to request body + *

+ * The given reader will be closed once sending completes + * + * @param input + * @return this request + * @throws HttpRequestException + */ + public HttpRequest send(final Reader input) throws HttpRequestException { + try { + openOutput(); + } catch (IOException e) { + throw new HttpRequestException(e); + } + final Writer writer = new OutputStreamWriter(output, + output.encoder.charset()); + return new FlushOperation(writer) { + + @Override + protected HttpRequest run() throws IOException { + return copy(input, writer); + } + }.call(); + } + + /** + * Write char sequence to request body + *

+ * The charset configured via {@link #contentType(String)} will be used and + * UTF-8 will be used if it is unset. + * + * @param value + * @return this request + * @throws HttpRequestException + */ + public HttpRequest send(final String value) throws HttpRequestException { + try { + openOutput(); + output.write(value.toString()); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return this; + } + + /** + * Create writer to request output stream + * + * @return writer + * @throws HttpRequestException + */ + public OutputStreamWriter writer() throws HttpRequestException { + try { + openOutput(); + return new OutputStreamWriter(output, output.encoder.charset()); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Write the values in the map as form data to the request body + *

+ * The pairs specified will be URL-encoded in UTF-8 and sent with the + * 'application/x-www-form-urlencoded' content-type + * + * @param values + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Map values) throws HttpRequestException { + return form(values, Header.CHARSET_UTF8); + } + + /** + * Write the key and value in the entry as form data to the request body + *

+ * The pair specified will be URL-encoded in UTF-8 and sent with the + * 'application/x-www-form-urlencoded' content-type + * + * @param entry + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Entry entry) throws HttpRequestException { + return form(entry, Header.CHARSET_UTF8); + } + + /** + * Write the key and value in the entry as form data to the request body + *

+ * The pair specified will be URL-encoded and sent with the + * 'application/x-www-form-urlencoded' content-type + * + * @param entry + * @param charset + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Entry entry, final String charset) + throws HttpRequestException { + return form(entry.getKey(), entry.getValue(), charset); + } + + /** + * Write the name/value pair as form data to the request body + *

+ * The pair specified will be URL-encoded in UTF-8 and sent with the + * 'application/x-www-form-urlencoded' content-type + * + * @param name + * @param value + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Object name, final Object value) + throws HttpRequestException { + return form(name, value, Header.CHARSET_UTF8); + } + + /** + * Write the name/value pair as form data to the request body + *

+ * The values specified will be URL-encoded and sent with the + * 'application/x-www-form-urlencoded' content-type + * + * @param name + * @param value + * @param charset + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Object name, final Object value, String charset) + throws HttpRequestException { + final boolean first = !form; + if (first) { + contentType(Header.CONTENT_TYPE_FORM, charset); + form = true; + } + charset = getValidCharset(charset); + try { + openOutput(); + if (!first) + output.write('&'); + output.write(URLEncoder.encode(name.toString(), charset)); + output.write('='); + if (value != null) + output.write(URLEncoder.encode(value.toString(), charset)); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return this; + } + + /** + * Write the values in the map as encoded form data to the request body + * + * @param values + * @param charset + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Map values, final String charset) + throws HttpRequestException { + if (!values.isEmpty()) + for (Entry entry : values.entrySet()) + form(entry, charset); + return this; + } + + /** + * Configure HTTPS connection to trust all certificates + *

+ * This method does nothing if the current request is not a HTTPS request + * + * @return this request + * @throws HttpRequestException + */ + public HttpRequest trustAllCerts() throws HttpRequestException { + final HttpURLConnection connection = getConnection(); + if (connection instanceof HttpsURLConnection) + ((HttpsURLConnection) connection) + .setSSLSocketFactory(getTrustedFactory()); + return this; + } + + /** + * Configure HTTPS connection to trust all hosts using a custom + * {@link HostnameVerifier} that always returns true for each + * host verified + *

+ * This method does nothing if the current request is not a HTTPS request + * + * @return this request + */ + public HttpRequest trustAllHosts() { + final HttpURLConnection connection = getConnection(); + if (connection instanceof HttpsURLConnection) + ((HttpsURLConnection) connection) + .setHostnameVerifier(getTrustedVerifier()); + return this; + } + + /** + * Get the {@link URL} of this request's connection + * + * @return request URL + */ + public URL url() { + return getConnection().getURL(); + } + + /** + * Get the HTTP method of this request + * + * @return method + */ + public String method() { + return getConnection().getRequestMethod(); + } + + /** + * Configure an HTTP proxy on this connection. Use {{@link #proxyBasic(String, String)} if + * this proxy requires basic authentication. + * + * @param proxyHost + * @param proxyPort + * @return this request + */ + public HttpRequest useProxy(final String proxyHost, final int proxyPort) { + if (connection != null) + throw new IllegalStateException("The connection has already been created. This method must be called before reading or writing to the request."); + + this.httpProxyHost = proxyHost; + this.httpProxyPort = proxyPort; + return this; + } + + /** + * Set whether or not the underlying connection should follow redirects in + * the response. + * + * @param followRedirects - true fo follow redirects, false to not. + * @return this request + */ + public HttpRequest followRedirects(final boolean followRedirects) { + getConnection().setInstanceFollowRedirects(followRedirects); + return this; + } +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/http/HttpRequestException.java b/blade-kit/src/main/java/blade/kit/http/HttpRequestException.java new file mode 100644 index 000000000..52a2527c0 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/http/HttpRequestException.java @@ -0,0 +1,23 @@ +package blade.kit.http; + +import java.io.IOException; + +/** + * HTTP请求异常 + * + * @author biezhi + * @since 1.0 + */ +public class HttpRequestException extends RuntimeException { + + private static final long serialVersionUID = -1170466989781746231L; + + public HttpRequestException(final IOException cause) { + super(cause); + } + + @Override + public IOException getCause() { + return (IOException) super.getCause(); + } +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/http/HttpResponse.java b/blade-kit/src/main/java/blade/kit/http/HttpResponse.java deleted file mode 100644 index f62df60f8..000000000 --- a/blade-kit/src/main/java/blade/kit/http/HttpResponse.java +++ /dev/null @@ -1,86 +0,0 @@ -package blade.kit.http; - -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.Map; - -/** - * Http响应类 - *

- *

- * - * @author biezhi - * @since 1.0 - */ -public class HttpResponse extends HttpBase{ - - /** - * 响应状态码 - */ - private int statusCode; - - /** - * 请求对象 - */ - private HttpRequest httpRequest; - - public HttpResponse() { - } - - /** - * 获取状态码 - * @return - */ - public int getStatusCode() { - return statusCode; - } - - /** - * 设置状态码 - * @param statusCode - */ - public void setStatusCode(int statusCode) { - this.statusCode = statusCode; - } - - /** - * 读取响应流 - * @param in - * @return HttpResponse - * @throws IOException - */ - public static HttpResponse readResponse(InputStream in) throws IOException { - HttpResponse httpResponse = new HttpResponse(); - String body = httpResponse.readBody(in); - httpResponse.body = body; - return httpResponse; - } - - /** - * 获取请求对象 - * @return - */ - public HttpRequest getHttpRequest() { - return httpRequest; - } - - /** - * 设置请求对象 - * @param httpRequest - */ - public void setHttpRequest(HttpRequest httpRequest) { - this.httpRequest = httpRequest; - } - - /** - * 设置请求头 - * @param headerFields - */ - public void setHeader(Map> headerFields) { - for (Map.Entry> entry : headerFields.entrySet()) { - this.header(entry.getKey(), entry.getValue().get(0)); - } - } - -} diff --git a/blade-kit/src/main/java/blade/kit/http/MethodType.java b/blade-kit/src/main/java/blade/kit/http/MethodType.java new file mode 100644 index 000000000..1af683374 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/http/MethodType.java @@ -0,0 +1,51 @@ +package blade.kit.http; + +/** + * 请求方法类型 + * + * @author biezhi + * @since 1.0 + */ +public final class MethodType { + + /** + * 'DELETE' request method + */ + public static final String DELETE = "DELETE"; + + /** + * 'GET' request method + */ + public static final String GET = "GET"; + + /** + * 'HEAD' request method + */ + public static final String HEAD = "HEAD"; + + /** + * 'OPTIONS' options method + */ + public static final String OPTIONS = "OPTIONS"; + + /** + * 'POST' request method + */ + public static final String POST = "POST"; + + /** + * 'PUT' request method + */ + public static final String PUT = "PUT"; + + /** + * 'TRACE' request method + */ + public static final String TRACE = "TRACE"; + + /** + * 'CONNECT' request method + */ + public static final String CONNECT = "CONNECT"; + +} diff --git a/blade-kit/src/main/java/blade/kit/http/RequestOutputStream.java b/blade-kit/src/main/java/blade/kit/http/RequestOutputStream.java new file mode 100644 index 000000000..61d41238f --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/http/RequestOutputStream.java @@ -0,0 +1,48 @@ +package blade.kit.http; + +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; + +/** + * 请求输出流包装 + * + * @author biezhi + * @since 1.0 + */ +public class RequestOutputStream extends BufferedOutputStream { + + final CharsetEncoder encoder; + + /** + * Create request output stream + * + * @param stream + * @param charset + * @param bufferSize + */ + public RequestOutputStream(final OutputStream stream, final String charset, final int bufferSize) { + super(stream, bufferSize); + + encoder = Charset.forName(HttpRequest.getValidCharset(charset)).newEncoder(); + } + + /** + * Write string to stream + * + * @param value + * @return this stream + * @throws IOException + */ + public RequestOutputStream write(final String value) throws IOException { + final ByteBuffer bytes = encoder.encode(CharBuffer.wrap(value)); + + super.write(bytes.array(), 0, bytes.limit()); + + return this; + } +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/http/UploadProgress.java b/blade-kit/src/main/java/blade/kit/http/UploadProgress.java new file mode 100644 index 000000000..403a5dfd0 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/http/UploadProgress.java @@ -0,0 +1,22 @@ +package blade.kit.http; + +/** + * 上传进度回调接口 + * + * @author biezhi + * @since 1.0 + */ +public interface UploadProgress { + /** + * 上传数据的回调函数调用 + * + * @param uploaded 已经上传的字节数 + * @param total 字节总数 + */ + void onUpload(long uploaded, long total); + + UploadProgress DEFAULT = new UploadProgress() { + public void onUpload(long uploaded, long total) { + } + }; +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index e3093266d..f80bde36d 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.6-alpha + 1.2.6 From 83eedd2c66801f07b0f94a5fbbc482098b2bfa45 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 15:16:01 +0800 Subject: [PATCH 083/545] optimized code --- .../main/java/blade/kit/http/HttpRequest.java | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/http/HttpRequest.java b/blade-kit/src/main/java/blade/kit/http/HttpRequest.java index 6e9299ed8..23872dd0b 100644 --- a/blade-kit/src/main/java/blade/kit/http/HttpRequest.java +++ b/blade-kit/src/main/java/blade/kit/http/HttpRequest.java @@ -214,7 +214,7 @@ private static StringBuilder addParam(final Object key, Object value, } /** - * Specify the {@link ConnectionFactory} used to create new requests. + * 设置一个ConnectionFactory,用于创建新的请求 */ public static void setConnectionFactory(final ConnectionFactory connectionFactory) { if (connectionFactory == null) @@ -224,15 +224,14 @@ public static void setConnectionFactory(final ConnectionFactory connectionFactor } /** - * Operation that handles executing a callback once complete and handling - * nested exceptions + * 操作执行一个回调处理完成后和处理嵌套的异常 * * @param */ protected static abstract class Operation implements Callable { /** - * Run operation + * 执行操作 * * @return result * @throws HttpRequestException @@ -241,7 +240,7 @@ protected static abstract class Operation implements Callable { protected abstract V run() throws HttpRequestException, IOException; /** - * Operation complete callback + * 操作完成回调 * * @throws IOException */ @@ -269,8 +268,7 @@ public V call() throws HttpRequestException { } /** - * Class that ensures a {@link Closeable} gets closed with proper exception - * handling. + * 确保Closeable类关闭,使用适当的异常处理 * * @param */ @@ -281,13 +279,12 @@ protected static abstract class CloseOperation extends Operation { private final boolean ignoreCloseExceptions; /** - * Create closer for operation + * 创建一个关闭操作 * * @param closeable * @param ignoreCloseExceptions */ - protected CloseOperation(final Closeable closeable, - final boolean ignoreCloseExceptions) { + protected CloseOperation(final Closeable closeable, final boolean ignoreCloseExceptions) { this.closeable = closeable; this.ignoreCloseExceptions = ignoreCloseExceptions; } @@ -335,7 +332,7 @@ protected void done() throws IOException { /** - * Represents array of any type as list of objects so we can easily iterate over it + * 表示任何类型的数组的对象列表,让我们可以很容易地遍历 * @param array of elements * @return list with the same elements */ @@ -377,8 +374,7 @@ else if (array instanceof char[]) * @return encoded URL * @throws HttpRequestException */ - public static String encode(final String url) - throws HttpRequestException { + public static String encode(final String url) throws HttpRequestException { URL parsed; try { parsed = new URL(url.toString()); @@ -476,8 +472,8 @@ public static String append(final String url, final Object... params) { } /** - * GET请求 - * + * Start a 'GET' request to the given URL + * * @param url * @return request * @throws HttpRequestException @@ -488,8 +484,8 @@ public static HttpRequest get(final String url) } /** - * GET请求 - * + * Start a 'GET' request to the given URL + * * @param url * @return request * @throws HttpRequestException @@ -499,13 +495,21 @@ public static HttpRequest get(final URL url) throws HttpRequestException { } /** - * 带参数的GET请求 - * @see #append(String, Map) - * @see #encode(String) + * Start a 'GET' request to the given URL along with the query params + * + * @param baseUrl + * @param params + * The query parameters to include as part of the baseUrl + * @param encode + * true to encode the full URL + * + * @see #append(CharSequence, Map) + * @see #encode(CharSequence) * * @return request */ - public static HttpRequest get(final String baseUrl, final Map params, final boolean encode) { + public static HttpRequest get(final String baseUrl, + final Map params, final boolean encode) { String url = append(baseUrl, params); return get(encode ? encode(url) : url); } @@ -520,8 +524,8 @@ public static HttpRequest get(final String baseUrl, final Map params, fina * the name/value query parameter pairs to include as part of the * baseUrl * - * @see #append(String, Object...) - * @see #encode(String) + * @see #append(CharSequence, Object...) + * @see #encode(CharSequence) * * @return request */ @@ -537,8 +541,7 @@ public static HttpRequest get(final String baseUrl, final boolean encode, final * @return request * @throws HttpRequestException */ - public static HttpRequest post(final String url) - throws HttpRequestException { + public static HttpRequest post(final String url) throws HttpRequestException { return new HttpRequest(url, MethodType.POST); } From 56fcd895189632af9bbc53c83e2c3eb405340b32 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 15:20:29 +0800 Subject: [PATCH 084/545] update readme --- README.md | 11 +++++------ README_CN.md | 7 +++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f54c6988a..d9224396a 100644 --- a/README.md +++ b/README.md @@ -16,17 +16,16 @@ ## Features -* Simple MVC & interceptor -* RESTful +* Simple MVC +* Restful * Multiple routing configuration * Micro kernel IOC container -* Practical tools +* Utility class * Coding/JSON/configuration file * JDK1.6 + * Plug-in extension mechanism * Template engine Plugin * Cache Plugin -* ... ## Quick start First. Use maven to build a webapp, join dependency on the blade,Recommended for the [latest version](LAST_VERSION.md) @@ -35,7 +34,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.6-alpha + 1.2.6 ``` @@ -47,7 +46,7 @@ Second. Configuration in the `web.xml` Blade core filter initialization and set blade.BladeFilter applicationClass - blade.sample.App + hello.App diff --git a/README_CN.md b/README_CN.md index fa38c7777..f44f3c9ce 100644 --- a/README_CN.md +++ b/README_CN.md @@ -14,7 +14,7 @@ ## Blade特性 -* 简洁的MVC & 拦截器 +* 简洁的MVC * RESTful * 多种路由配置方式 * 微内核IOC容器 @@ -24,7 +24,6 @@ * 支持JDK1.6+ * 插件扩展机制 * 缓存支持 -* ... ## 快速入门 第一步、用maven构建一个webapp,加入blade的依赖,推荐获取[最新版本](LAST_VERSION.md) @@ -33,7 +32,7 @@ com.bladejava blade-core - 1.2.6-alpha + 1.2.6 ``` @@ -45,7 +44,7 @@ blade.BladeFilter applicationClass - blade.sample.App + hello.App From 3db4e2b8016c8a32d70d016d782002bbe48ad4dd Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 15:22:30 +0800 Subject: [PATCH 085/545] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d9224396a..6d1e569c1 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ## Introduction -**blade** Is a concise and powerful web development framework, it is built into the `IOC` administration, the interceptor configuration, `REST API` development and so on many mainstream web features, integrate the template engine, a cache plug-in, database operations, commonly used functions such as email, concise source deserves your reading. If you like it, can be `Star or Fork`, thanks! +**blade** Is a concise and powerful web development framework, it is built into the `IOC` administration, the interceptor configuration, `REST API` development and so on many mainstream web features, integrate the template engine, a cache plug-in, database operations, commonly used functions such as email, concise source deserves your reading. If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! ## Features From 2828e7532801810942772435f4c76ffc8d30e02d Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 15:34:11 +0800 Subject: [PATCH 086/545] update last_version --- LAST_VERSION.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 99f319dd1..9695bcc1d 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -5,7 +5,7 @@     com.bladejava     blade-kit -    1.2.6-alpha +    1.2.6 ``` @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.6-alpha +    1.2.6 ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) From 197eab73e08755f892630ce0ce7d8cd101df30b4 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 11 Aug 2015 18:41:16 +0800 Subject: [PATCH 087/545] fix ioc inject error --- .../src/main/java/blade/BladeFilter.java | 3 +- .../src/main/java/blade/IocApplication.java | 16 +-- .../main/java/blade/ioc/DefaultContainer.java | 114 +++++++++++------- .../java/blade/route/RouteMatcherBuilder.java | 6 +- 4 files changed, 81 insertions(+), 58 deletions(-) diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java index d268011a2..79be87cf7 100644 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ b/blade-core/src/main/java/blade/BladeFilter.java @@ -67,8 +67,9 @@ public void init(FilterConfig filterConfig) throws ServletException { application.contextInitialized(BladeWebContext.servletContext()); - LOGGER.info("blade init complete!"); BladeBase.init(); + + LOGGER.info("blade init complete!"); } } catch (Exception e) { LOGGER.error(e); diff --git a/blade-core/src/main/java/blade/IocApplication.java b/blade-core/src/main/java/blade/IocApplication.java index 2e57fbb2d..d5f056128 100644 --- a/blade-core/src/main/java/blade/IocApplication.java +++ b/blade-core/src/main/java/blade/IocApplication.java @@ -19,6 +19,7 @@ import blade.ioc.Container; import blade.ioc.DefaultContainer; +import blade.ioc.Scope; import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; @@ -49,7 +50,9 @@ public final class IocApplication { public static void init(){ // 初始化全局配置类 - initApp(); + if(null == container.getBean(BladeApplication.class, Scope.SINGLE)){ + container.registBean(Blade.application()); + } // 初始化ioc容器 initIOC(); @@ -62,10 +65,6 @@ public static void init(){ } } - private static void initApp(){ - container.registBean(Blade.application()); - } - /** * 初始化IOC容器,加载ioc包的对象 * 要配置符合ioc的注解的类才会被加载 @@ -102,13 +101,6 @@ private static void registerBean(String packageName) { container.registBean(clazz); } } - - if(Blade.debug()){ - Set beanNames = container.getBeanNames(); - for(String beanName : beanNames){ - LOGGER.debug("Load The Class:" + beanName); - } - } } /** diff --git a/blade-core/src/main/java/blade/ioc/DefaultContainer.java b/blade-core/src/main/java/blade/ioc/DefaultContainer.java index bbb57e3d2..9cb4e7e8c 100644 --- a/blade-core/src/main/java/blade/ioc/DefaultContainer.java +++ b/blade-core/src/main/java/blade/ioc/DefaultContainer.java @@ -22,8 +22,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import blade.Blade; import blade.annotation.Component; import blade.annotation.Inject; import blade.annotation.Path; @@ -168,6 +170,11 @@ public Object registBean(Class clazz) { if(null != clazz.getDeclaredAnnotations()){ putAnnotationMap(clazz, object); } + + if(Blade.debug()){ + LOGGER.info("register object:" + name + "=" + object); + } + } return object; } @@ -222,47 +229,53 @@ private void put(Class clazz, List listObject){ */ @Override public void initWired() throws RuntimeException { - Iterator it = BEAN_CONTAINER.values().iterator(); + Iterator> it = BEAN_CONTAINER.entrySet().iterator(); + try { - while (it.hasNext()) { - - Object obj = it.next(); - - // 所有字段 - Field[] fields = obj.getClass().getDeclaredFields(); - for (Field field : fields) { - - // 需要注入的字段 - Inject inject = field.getAnnotation(Inject.class); - if (null != inject) { - - // 要注入的字段 - Object injectField = this.getBean(field.getType(), Scope.SINGLE); - - // 指定装配的类 - if (inject.value() != Class.class) { - injectField = this.getBean(inject.value(), Scope.SINGLE); - // 容器有该类 - if (null == injectField) { - injectField = this.registBean(inject.value()); - } - } else{ - // 没有指定装配class, 容器没有该类,则创建一个对象放入容器 - if (null == injectField) { - injectField = this.registBean(field.getType()); - } - } - if (null == injectField) { - throw new BladeException("Unable to load " + field.getType().getCanonicalName() + "!"); - } - boolean accessible = field.isAccessible(); - field.setAccessible(true); - field.set(obj, injectField); - field.setAccessible(accessible); - } - } - } - } catch (SecurityException e) { + while (it.hasNext()) { + + Map.Entry entry = (Map.Entry) it.next(); + + Object obj = entry.getValue(); + + // 所有字段 + Field[] fields = obj.getClass().getDeclaredFields(); + + for (Field field : fields) { + + // 需要注入的字段 + Inject inject = field.getAnnotation(Inject.class); + if (null != inject ) { + + // 要注入的字段 + Object injectField = this.getBean(field.getType(), Scope.SINGLE); + injectField = null; + // 指定装配到哪个class + if(inject.value() != Class.class){ + // 指定装配的类 + injectField = this.getBean(inject.value(), Scope.SINGLE); + + if (null == injectField) { + injectField = recursiveAssembly(inject.value()); + } + + } else { + if (null == injectField) { + injectField = recursiveAssembly(field.getType()); + } + } + + if (null == injectField) { + throw new BladeException("Unable to load " + field.getType().getCanonicalName() + "!"); + } + boolean accessible = field.isAccessible(); + field.setAccessible(true); + field.set(obj, injectField); + field.setAccessible(accessible); + } + } + } + } catch (SecurityException e) { LOGGER.error(e.getMessage()); } catch (IllegalArgumentException e) { LOGGER.error(e.getMessage()); @@ -270,7 +283,23 @@ public void initWired() throws RuntimeException { LOGGER.error(e.getMessage()); } } - + + // 装配 + private Object recursiveAssembly(Class clazz){ + Object field = null; + if(null != clazz){ + // 是接口或者抽象类 + if(clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())){ + String implClassName = clazz.getPackage().getName() + ".impl." + clazz.getSimpleName() + "Impl"; + return ReflectKit.newInstance(implClassName); + } else { + field = this.registBean(clazz); + } + } + return field; + } + + /** * 判断是否是可以注册的bean * @@ -321,6 +350,9 @@ public void registBean(Set> classes) { public Object registBean(Object object) { String name = object.getClass().getName(); put(name, object); + if(Blade.debug()){ + LOGGER.info("register object:" + name + "=" + object); + } return object; } diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index 8d687c727..d86572483 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -74,10 +74,7 @@ private RouteMatcherBuilder() { * @return 返回构建路由后的构造器 */ public static synchronized void building() { - if(Blade.debug()){ - LOGGER.debug("creates RouteMatcher"); - } - + String basePackage = Blade.basePackage(); if(StringKit.isNotBlank(basePackage)){ @@ -94,6 +91,7 @@ public static synchronized void building() { buildInterceptor(interceptorPackage); } else { + // 路由 String[] routePackages = Blade.routes(); if(null != routePackages && routePackages.length > 0){ From e8cbabe49e257191aba6ae6ebf9feae5479745bf Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 12 Aug 2015 17:30:03 +0800 Subject: [PATCH 088/545] optimize blade-sql2o --- LAST_VERSION.md | 2 +- blade-sql2o/pom.xml | 2 +- .../main/java/blade/plugin/sql2o/Model.java | 171 +++++++++++------- .../plugin/sql2o/cache/SimpleSql2oCache.java | 44 +++-- .../blade/plugin/sql2o/cache/Sql2oCache.java | 29 +-- .../plugin/sql2o/cache/Sql2oCacheFactory.java | 7 +- 6 files changed, 155 insertions(+), 100 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 9695bcc1d..2013b2deb 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -22,7 +22,7 @@     com.bladejava     blade-sql2o -    1.2.5 +    1.2.6-alpha ``` diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index f9aeb2aaf..e3783b784 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - 1.2.5 + 1.2.6-alpha blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 7018e79a1..6433db353 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -26,10 +26,8 @@ * @author biezhi * @since 1.0 */ -public class Model implements Serializable { +public class Model { - private static final long serialVersionUID = -8227936256753441060L; - private static final Logger LOGGER = Logger.getLogger(Model.class); /** @@ -40,7 +38,7 @@ public class Model implements Serializable { /** * 缓存操作 */ - private static Sql2oCache sql2oCache = isOpenCache ? Sql2oCacheFactory.getSql2oCache() : null; + private static Sql2oCache sql2oCache = isOpenCache ? Sql2oCacheFactory.getSql2oCache() : null; /** * sql2o对象,操作数据库 @@ -50,31 +48,26 @@ public class Model implements Serializable { /** * 当前class实例 */ - private Class model; + private Class model; /** * 条件对象 */ private Condition condition; - private final String CACHE_KEY_LIST = this.getClass().getName() + ":list"; - private final String CACHE_KEY_COUNT = this.getClass().getName() + ":count"; - private final String CACHE_KEY_DETAIL = this.getClass().getName() + ":detail"; + private String CACHE_KEY_LIST; + private String CACHE_KEY_COUNT; + private String CACHE_KEY_DETAIL; - public static Model getModel(Class clazz){ - return new Model(clazz); - } - - public Model() { - this.model = this.getClass(); - this.condition = new Condition(this.table(), this.pk()); - } - - public Model(Class clazz) { + public Model(Class clazz) { this.model = clazz; this.condition = new Condition(table(), pk()); + + CACHE_KEY_LIST = model.getName() + ":list"; + CACHE_KEY_COUNT = model.getName() + ":count"; + CACHE_KEY_DETAIL = model.getName() + ":detail"; } - + public Sql2o getSql2o(){ return sql2o; } @@ -103,7 +96,7 @@ public boolean isCache(){ /** * @return 返回查询model对象,推荐方式 */ - public Model select(){ + public Model select(){ condition.select(); return this; } @@ -115,7 +108,7 @@ public Model select(){ * @param sql 要查询的sql语句 * @return 返回查询model对象 */ - public Model select(String sql){ + public Model select(String sql){ condition.select(sql); return this; } @@ -123,7 +116,7 @@ public Model select(String sql){ /** * @return 返回计算count */ - public Model count(){ + public Model count(){ condition.count(); return this; } @@ -134,7 +127,7 @@ public Model count(){ * @param sql 要查询的sql语句 * @return 返回查询model对象 */ - public Model count(String sql){ + public Model count(String sql){ condition.count(sql); return this; } @@ -142,7 +135,7 @@ public Model count(String sql){ /** * @return 返回更新model对象,推荐方式 */ - public Model update(){ + public Model update(){ condition.update(); return this; } @@ -153,7 +146,7 @@ public Model update(){ * @param sql 自定义更新语句 * @return 返回更新model对象 */ - public Model update(String sql){ + public Model update(String sql){ condition.update(sql); return this; } @@ -161,7 +154,7 @@ public Model update(String sql){ /** * @return 返回插入model对象,推荐方式 */ - public Model insert(){ + public Model insert(){ condition.insert(); return this; } @@ -171,7 +164,7 @@ public Model insert(){ * @param sql 自定义插入语句 * @return 返回插入model对象 */ - public Model insert(String sql){ + public Model insert(String sql){ condition.insert(sql); return this; } @@ -179,7 +172,7 @@ public Model insert(String sql){ /** * @return 返回删除model对象 */ - public Model delete(){ + public Model delete(){ condition.delete(); return this; } @@ -190,7 +183,7 @@ public Model delete(){ * @param sql 自定义删除语句 * @return 返回自定义删除model对象 */ - public Model delete(String sql){ + public Model delete(String sql){ condition.delete(sql); return this; } @@ -202,7 +195,7 @@ public Model delete(String sql){ * @param value 参数值 * @return 返回model对象 */ - public Model param(String name, Object value){ + public Model param(String name, Object value){ condition.param(name, value); return this; } @@ -214,7 +207,7 @@ public Model param(String name, Object value){ * @param value 参数值 * @return 返回model对象 */ - public Model where(String name, Object value){ + public Model where(String name, Object value){ condition.where(name, value); return this; } @@ -225,7 +218,7 @@ public Model where(String name, Object value){ * @param value * @return */ - public Model greater(String name, Object value){ + public Model greater(String name, Object value){ condition.greater(name, value); return this; } @@ -237,7 +230,7 @@ public Model greater(String name, Object value){ * @param value 参数值 * @return 返回model对象 */ - public Model greaterThan(String name, Object value){ + public Model greaterThan(String name, Object value){ condition.greaterThan(name, value); return this; } @@ -248,7 +241,7 @@ public Model greaterThan(String name, Object value){ * @param value 参数值 * @return 返回model对象 */ - public Model less(String name, Object value){ + public Model less(String name, Object value){ condition.less(name, value); return this; } @@ -259,7 +252,7 @@ public Model less(String name, Object value){ * @param value 参数值 * @return 返回model对象 */ - public Model lessThan(String name, Object value){ + public Model lessThan(String name, Object value){ condition.lessThan(name, value); return this; } @@ -270,7 +263,7 @@ public Model lessThan(String name, Object value){ * @param value * @return */ - public Model like(String name, String value){ + public Model like(String name, String value){ condition.like(name, value); return this; } @@ -281,7 +274,7 @@ public Model like(String name, String value){ * @param value * @return */ - public Model in(String name, Object... values){ + public Model in(String name, Object... values){ condition.in(name, values); return this; } @@ -292,7 +285,7 @@ public Model in(String name, Object... values){ * @param orderby 排序字段和排序规则,如:ordernum desc * @return 返回model对象 */ - public Model orderBy(String orderby){ + public Model orderBy(String orderby){ condition.orderby = orderby; return this; } @@ -512,14 +505,13 @@ private Long getPageCount(){ /** * @return 返回查询一个对象 */ - @SuppressWarnings("unchecked") - public M fetchOne(){ + public T fetchOne(){ if(condition.dmlType.equals(DmlType.SELECT)){ String sqlEnd = condition.getConditionSql(); - M res = null; + T res = null; String field = null; // 是否开启缓存查询 @@ -541,7 +533,7 @@ public M fetchOne(){ condition.printLog(); condition.clearMap(); - res = (M) query.executeAndFetchFirst(this.model); + res = (T) query.executeAndFetchFirst(this.model); // 重新放入缓存 if(isCache() && null != res){ @@ -555,9 +547,8 @@ public M fetchOne(){ return null; } - @SuppressWarnings("unchecked") - public M fetchByPk(Serializable pk){ - M res = null; + public T fetchByPk(Serializable pk){ + T res = null; if(null != pk){ @@ -584,7 +575,7 @@ public M fetchByPk(Serializable pk){ condition.printLog(); condition.clearMap(); - res = (M) query.executeAndFetchFirst(this.model); + res = (T) query.executeAndFetchFirst(this.model); if(isCache() && null != res){ sql2oCache.hset(CACHE_KEY_DETAIL, field, res); @@ -626,16 +617,16 @@ public M fetchColum(){ * @return 查询list数据 */ @SuppressWarnings("unchecked") - public List fetchList(){ + public List fetchList(){ if(condition.dmlType.equals(DmlType.SELECT)){ String field = null; - List result = null; + List result = null; // 开启缓存 if(isCache()){ field = MD5.create(getCacheKey(null)); - result = sql2oCache.hgetlist(CACHE_KEY_LIST, field); + result = (List) sql2oCache.hgetlist(CACHE_KEY_LIST, field); if(null != result){ return result; } @@ -657,7 +648,7 @@ public List fetchList(){ condition.printLog(); condition.clearMap(); - result = (List) query.executeAndFetch(this.model); + result = (List) query.executeAndFetch(this.model); if(isCache() && null != result){ sql2oCache.hsetlist(CACHE_KEY_LIST, field, result); @@ -671,6 +662,55 @@ public List fetchList(){ return null; } + + /** + * @return 查询list数据 + */ + public List executeAndFetch(Class clazz){ + if(condition.dmlType.equals(DmlType.SELECT)){ + + String field = null; + List result = null; + + // 开启缓存 + if(isCache()){ + field = MD5.create(getCacheKey(null)); + result = sql2oCache.hgetlists(CACHE_KEY_LIST, field); + if(null != result){ + return result; + } + } + + String sqlEnd = condition.getConditionSql(); + + if(null != condition.orderby){ + sqlEnd += " order by " + condition.orderby; + } + + try { + Connection conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd); + query = parseParams(query); + + LOGGER.debug("execute sql:" + query.toString()); + + condition.printLog(); + condition.clearMap(); + + result = query.executeAndFetch(clazz); + + if(isCache() && null != result){ + sql2oCache.hsetlists(CACHE_KEY_LIST, field, result); + } + + return result; + } catch (Exception e) { + LOGGER.error(e); + } + } + return null; + } + /** * @return 返回一个listmap类型的数据 */ @@ -678,7 +718,7 @@ public List> fetchListMap(){ if(condition.dmlType.equals(DmlType.SELECT)){ - List list = fetchList(); + List list = fetchList(); if(null != list && list.size() > 0){ List> result = BeanKit.toListMap(list); return result; @@ -694,8 +734,7 @@ public List> fetchListMap(){ * @param pageSize 每页条数 * @return 返回分页后的Page对象 */ - @SuppressWarnings("unchecked") - public Page fetchPage(Integer page, Integer pageSize){ + public Page fetchPage(Integer page, Integer pageSize){ if(null == page || page < 1){ page = 1; @@ -705,7 +744,7 @@ public Page fetchPage(Integer page, Integer pageSize){ pageSize = 1; } - Page pageModel = new Page(0, page, pageSize); + Page pageModel = new Page(0, page, pageSize); if(condition.dmlType.equals(DmlType.SELECT) && null != page && null != pageSize && page > 0 && pageSize > 0){ @@ -713,7 +752,7 @@ public Page fetchPage(Integer page, Integer pageSize){ long totalCount = getPageCount(); String field = null; - List results = null; + List results = null; // 开启缓存 if(isCache()){ @@ -723,10 +762,10 @@ public Page fetchPage(Integer page, Integer pageSize){ results = sql2oCache.hgetlist(CACHE_KEY_LIST, field); - pageModel = new Page(totalCount, page, pageSize); + pageModel = new Page(totalCount, page, pageSize); if(null != results && results.size() > 0){ - pageModel.setResults((List) results); + pageModel.setResults((List) results); return pageModel; } @@ -752,13 +791,13 @@ public Page fetchPage(Integer page, Integer pageSize){ LOGGER.debug("execute sql:" + query.toString()); condition.printLog(); - results = query.executeAndFetch(this.model); + results = (List) query.executeAndFetch(this.model); if(null != results && results.size() > 0){ if(isCache()){ sql2oCache.hsetlist(CACHE_KEY_LIST, field, results); } - pageModel.setResults((List) results); + pageModel.setResults((List) results); } return pageModel; @@ -793,13 +832,13 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ if(condition.dmlType.equals(DmlType.SELECT) && null != page && null != pageSize && page > 0 && pageSize > 0){ - Page pageModel = fetchPage(page, pageSize); + Page pageModel = fetchPage(page, pageSize); if(null != pageModel && null != pageModel.getResults()){ pageMap = new Page>(pageModel.getTotalCount(), page, pageSize); - List list = pageModel.getResults(); + List list = pageModel.getResults(); List> result = BeanKit.toListMap(list); pageMap.setResults(result); @@ -830,8 +869,8 @@ public Integer executeAndCommit() { * @return 返回主键 */ @SuppressWarnings("unchecked") - public T executeAndCommit(Class returnType) { - T key = null; + public V executeAndCommit(Class returnType) { + V key = null; Query query = null; try { // 插入 @@ -847,7 +886,7 @@ public T executeAndCommit(Class returnType) { if(null != returnType){ key = query.executeUpdate().getKey(returnType); } else { - key = (T) query.executeUpdate().getKey(); + key = (V) query.executeUpdate().getKey(); } } @@ -860,7 +899,7 @@ public T executeAndCommit(Class returnType) { sql2oCache.hdel(CACHE_KEY_DETAIL); sql2oCache.hdel(CACHE_KEY_LIST); } - key = (T) Integer.valueOf(query.executeUpdate().getResult()); + key = (V) Integer.valueOf(query.executeUpdate().getResult()); } // 删除 @@ -873,7 +912,7 @@ public T executeAndCommit(Class returnType) { sql2oCache.hdel(CACHE_KEY_LIST); sql2oCache.hdel(CACHE_KEY_DETAIL); } - key = (T) Integer.valueOf(query.executeUpdate().getResult()); + key = (V) Integer.valueOf(query.executeUpdate().getResult()); } condition.clearMap(); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java index 33b7a105d..d3c79a5c8 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java @@ -1,13 +1,13 @@ package blade.plugin.sql2o.cache; +import java.io.Serializable; import java.util.List; import blade.cache.Cache; import blade.cache.CacheManager; -import blade.plugin.sql2o.Model; @SuppressWarnings("unchecked") -public class SimpleSql2oCache implements Sql2oCache { +public class SimpleSql2oCache implements Sql2oCache { private CacheManager cm = CacheManager.getInstance(); @@ -22,35 +22,35 @@ public SimpleSql2oCache() { } @Override - public void set(String key, T value) { + public void set(String key, Serializable value) { cache.set(key, value); } @Override - public void set(String key, T value, long expire) { + public void set(String key, Serializable value, long expire) { cache.set(key, value, expire); } @Override - public void hset(String key, String field, T value) { + public void hset(String key, String field, Serializable value) { cache.hset(key, field, value); } @Override - public void hset(String key, String field, T value, long expire) { + public void hset(String key, String field, Serializable value, long expire) { cache.hset(key, field, value, expire); } @Override - public void hset(String key, String field, List value, long expire) { + public void hset(String key, String field, List value, long expire) { cache.hset(key, field, value, expire); } @Override - public T get(String key) { + public Serializable get(String key) { Object value = cache.get(key); if(null != value){ - return (T) value; + return (Serializable) value; } return null; } @@ -65,25 +65,34 @@ public V hgetV(String key, String field) { } @Override - public void hsetV(String key, String field, V value) { + public void hsetV(String key, String field, Serializable value) { cache.hset(key, field, value); } @Override - public M hget(String key, String field) { + public Serializable hget(String key, String field) { Object object = cache.hget(key, field); if(null != object){ - return (M) object; + return (Serializable) object; } return null; } @Override - public List hgetlist(String key, String field) { + public List hgetlist(String key, String field) { Object object = cache.hget(key, field); if(null != object){ - return (List) object; + return (List) object; + } + return null; + } + + @Override + public List hgetlists(String key, String field) { + Object object = cache.hget(key, field); + if(null != object){ + return (List) object; } return null; } @@ -99,7 +108,12 @@ public void hdel(String key, String field) { } @Override - public void hsetlist(String key, String field, List value) { + public void hsetlist(String key, String field, List value) { + cache.hset(key, field, value); + } + + @Override + public void hsetlists(String key, String field, List value) { cache.hset(key, field, value); } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java index f43f604a3..efff206c0 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java @@ -1,32 +1,35 @@ package blade.plugin.sql2o.cache; +import java.io.Serializable; import java.util.List; -import blade.plugin.sql2o.Model; +public interface Sql2oCache { -public interface Sql2oCache { - - void set(String key, T value); + void set(String key, Serializable value); + + void set(String key, Serializable value, long expire); - void set(String key, T value, long expire); + void hset(String key, String field, Serializable value); - void hset(String key, String field, T value); + void hsetV(String key, String field, Serializable value); - void hsetV(String key, String field, V value); + void hsetlist(String key, String field, List value); - void hsetlist(String key, String field, List value); + void hsetlists(String key, String field, List value); - void hset(String key, String field, T value, long expire); + void hset(String key, String field, Serializable value, long expire); - void hset(String key, String field, List value, long expire); + void hset(String key, String field, List value, long expire); - M get(String key); + Serializable get(String key); - M hget(String key, String field); + T hget(String key, String field); V hgetV(String key, String field); - List hgetlist(String key, String field); + List hgetlist(String key, String field); + + List hgetlists(String key, String field); void hdel(String key); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCacheFactory.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCacheFactory.java index 9629b97d4..689277f97 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCacheFactory.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCacheFactory.java @@ -1,6 +1,5 @@ package blade.plugin.sql2o.cache; -import blade.plugin.sql2o.Model; /** * 缓存获取工厂 @@ -10,9 +9,9 @@ */ public final class Sql2oCacheFactory { - private static Sql2oCache sql2oCache = new SimpleSql2oCache(); + private static Sql2oCache sql2oCache = new SimpleSql2oCache(); - public static Sql2oCache getSql2oCache(){ + public static Sql2oCache getSql2oCache(){ return sql2oCache; } @@ -21,7 +20,7 @@ public static Sql2oCache getSql2oCache(){ * * @param sql2oCache */ - public static void setSql2oCache(Sql2oCache sql2oCache){ + public static void setSql2oCache(Sql2oCache sql2oCache){ Sql2oCacheFactory.sql2oCache = sql2oCache; } From 50059d211d227c78258c0acde250134a09ebdc3f Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 17 Aug 2015 14:40:06 +0800 Subject: [PATCH 089/545] fix the IOC serious bugs --- .../src/main/java/blade/ioc/DefaultContainer.java | 15 +++++++-------- pom.xml | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/blade-core/src/main/java/blade/ioc/DefaultContainer.java b/blade-core/src/main/java/blade/ioc/DefaultContainer.java index 9cb4e7e8c..5ce7d204a 100644 --- a/blade-core/src/main/java/blade/ioc/DefaultContainer.java +++ b/blade-core/src/main/java/blade/ioc/DefaultContainer.java @@ -116,7 +116,7 @@ public Collection getBeans() { @Override public boolean hasBean(Class clz) { - if (null != this.getBean(clz, Scope.SINGLE)) { + if (null != single().getBean(clz, Scope.SINGLE)) { return true; } return false; @@ -124,7 +124,7 @@ public boolean hasBean(Class clz) { @Override public boolean hasBean(String name) { - if (null != this.getBean(name, Scope.SINGLE)) { + if (null != single().getBean(name, Scope.SINGLE)) { return true; } return false; @@ -207,7 +207,7 @@ private void putAnnotationMap(Class clazz, Object object){ listObject = CollectionKit.newArrayList(); } listObject.add(object); - this.put(annotation.annotationType(), listObject); + single().put(annotation.annotationType(), listObject); } } } @@ -248,12 +248,11 @@ public void initWired() throws RuntimeException { if (null != inject ) { // 要注入的字段 - Object injectField = this.getBean(field.getType(), Scope.SINGLE); - injectField = null; + Object injectField = single().getBean(field.getType(), Scope.SINGLE); // 指定装配到哪个class if(inject.value() != Class.class){ // 指定装配的类 - injectField = this.getBean(inject.value(), Scope.SINGLE); + injectField = single().getBean(inject.value(), Scope.SINGLE); if (null == injectField) { injectField = recursiveAssembly(inject.value()); @@ -293,7 +292,7 @@ private Object recursiveAssembly(Class clazz){ String implClassName = clazz.getPackage().getName() + ".impl." + clazz.getSimpleName() + "Impl"; return ReflectKit.newInstance(implClassName); } else { - field = this.registBean(clazz); + field = single().registBean(clazz); } } return field; @@ -341,7 +340,7 @@ public List getBeansByAnnotation(Class annotation) public void registBean(Set> classes) { if(!CollectionKit.isEmpty(classes)){ for(Class clazz : classes){ - this.registBean(clazz); + single().registBean(clazz); } } } diff --git a/pom.xml b/pom.xml index f80bde36d..02c41b0c1 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.6 + 1.2.7-alpha From 43020a9b95e691db84078867be4b50046ca03c63 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 17 Aug 2015 14:44:18 +0800 Subject: [PATCH 090/545] update version --- LAST_VERSION.md | 2 +- README.md | 2 +- README_CN.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 2013b2deb..fd310fa6b 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.6 +    1.2.7-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/README.md b/README.md index 6d1e569c1..1e467e9be 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.6 + 1.2.7-alpha ``` diff --git a/README_CN.md b/README_CN.md index f44f3c9ce..c9500cb81 100644 --- a/README_CN.md +++ b/README_CN.md @@ -32,7 +32,7 @@ com.bladejava blade-core - 1.2.6 + 1.2.7-alpha ``` From 903078f60533892a7169abb8ab420ef8b26e5f1b Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 17 Aug 2015 15:22:02 +0800 Subject: [PATCH 091/545] update readme --- README.md | 1 + README_CN.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 1e467e9be..445942634 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ * Plug-in extension mechanism * Template engine Plugin * Cache Plugin +* The source code of less than 100kb ## Quick start First. Use maven to build a webapp, join dependency on the blade,Recommended for the [latest version](LAST_VERSION.md) diff --git a/README_CN.md b/README_CN.md index c9500cb81..5eddb26f0 100644 --- a/README_CN.md +++ b/README_CN.md @@ -24,6 +24,7 @@ * 支持JDK1.6+ * 插件扩展机制 * 缓存支持 +* 不到100K的源码 ## 快速入门 第一步、用maven构建一个webapp,加入blade的依赖,推荐获取[最新版本](LAST_VERSION.md) From 77bc54284f18e41f5288448429e53647363dbc6e Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 20 Aug 2015 15:59:57 +0800 Subject: [PATCH 092/545] update readme and add test java file --- README.md | 2 +- README_CN.md | 2 +- .../src/test/java/blade/test/MailTest.java | 39 ++++++++++++------- .../src/test/java/blade/test/StringTest.java | 27 +++++++++---- 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 445942634..774835bcb 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for ``` -Second. Configuration in the `web.xml` Blade core filter initialization and set your class, and you can also not configuration(using jetty start) +Second. Configuration in the `web.xml` Blade core filter initialization and set your class ```xml diff --git a/README_CN.md b/README_CN.md index 5eddb26f0..935e191fc 100644 --- a/README_CN.md +++ b/README_CN.md @@ -37,7 +37,7 @@ ``` -第二步、在`web.xml`中配置Blade核心过滤器并设置你的初始化类,你也可以不配置(使用jetty启动) +第二步、在`web.xml`中配置Blade核心过滤器并设置你的初始化类 ```xml diff --git a/blade-kit/src/test/java/blade/test/MailTest.java b/blade-kit/src/test/java/blade/test/MailTest.java index 1a9ee9612..068919b6f 100644 --- a/blade-kit/src/test/java/blade/test/MailTest.java +++ b/blade-kit/src/test/java/blade/test/MailTest.java @@ -1,25 +1,36 @@ package blade.test; -import org.junit.Before; -import org.junit.Test; +import java.io.IOException; import blade.kit.MailKit; +import blade.kit.mail.MailTemplate; public class MailTest { - @Before - public void before(){ - MailKit.config(MailKit.SMTP_QQ, "", ""); - } - - @Test - public void testSendMail(){ - MailKit.send("xxx", "测试发送邮件", "hello"); - } - - @Test - public void testAsynSendMail(){ + public static void main(String[] args) { + // 发送方配置,邮箱帐号和密码 + MailKit.config(MailKit.SMTP_QQ, "921293209@qq.com", "helloworld"); + + // 测试给【xxx@qq.com】发送邮件 + MailKit.send("xxx@qq.com", "测试发送邮件", "hello"); + + // 测试异步发送邮件 MailKit.asynSend("xxx", "测试异步发送邮件", "hello"); + + // 测试给【xxx@qq.com】发送邮件并抄送给xoxo@qq.com + MailKit.sendAndCc("xxx@qq.com", "xoxo@qq.com", "测试发送邮件", "hello"); + + // 测试给【xxx@qq.com】发送邮件并带一个附件 + MailKit.send("xxx@qq.com", "测试发送邮件", "hello", "F:/aa.txt"); + + // 使用模板给【xxx@qq.com】发送邮件并带一个附件 + try { + MailTemplate template = new MailTemplate("F:/a.html", "xxx@qq.com", null); + MailKit.send(template, "新主题"); + } catch (IOException e) { + e.printStackTrace(); + } + } } diff --git a/blade-kit/src/test/java/blade/test/StringTest.java b/blade-kit/src/test/java/blade/test/StringTest.java index e0eb40f9e..b27d3b1f2 100644 --- a/blade-kit/src/test/java/blade/test/StringTest.java +++ b/blade-kit/src/test/java/blade/test/StringTest.java @@ -1,23 +1,36 @@ package blade.test; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import blade.kit.StringKit; + public class StringTest { public static void main(String[] args) { - String[] a = {"/aa/", "/aa/cc"}; - String bString= StringKit.join(a, "|"); - System.out.println(bString); + //判断是否为空 + String str = "hello"; + System.out.println(StringKit.isNotEmpty(str)); + + //分割字符串 + String[] arr = StringKit.split("1,2,3", ","); + System.out.println(Arrays.toString(arr)); + //生成5个随机字符串 + System.out.println(StringKit.random(5)); - List list = new ArrayList(); - list.add("aa2@qq.com"); - list.add("a3a@qq.com"); - list.add("aa4@qq.com"); + //将字符串20转换为long类型,如果为null或者空则给一个默认值10 + System.out.println(StringKit.toLong("20", 10)); + List list = new ArrayList(); + list.add(22); + list.add(30); + //将集合用指定字符分隔 + String listString = StringKit.join(list, "|"); + System.out.println(listString); } + } From cbe5414738aa6f47f07847baafd50c88a6455005 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 24 Aug 2015 11:03:44 +0800 Subject: [PATCH 093/545] remove filter add servlet --- UPDATE_LOG.md | 6 + blade-core/src/main/java/blade/BladeBase.java | 32 ++++- .../src/main/java/blade/BladeFilter.java | 130 ------------------ .../src/main/java/blade/IocApplication.java | 4 +- .../src/main/java/blade/RequestHandler.java | 27 ++-- .../src/main/java/blade/annotation/After.java | 6 + .../main/java/blade/annotation/Before.java | 6 + .../src/main/java/blade/annotation/Path.java | 8 +- .../src/main/java/blade/render/JspRender.java | 12 +- .../src/main/java/blade/render/Render.java | 8 +- .../java/blade/route/RouteMatcherBuilder.java | 13 ++ pom.xml | 2 +- 12 files changed, 93 insertions(+), 161 deletions(-) delete mode 100644 blade-core/src/main/java/blade/BladeFilter.java diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 898955d0e..bc0c5eba6 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,5 +1,11 @@ #Blade 更新日志 +### v1.2.7 + 1. 去除Filter改为Servlet方式 + 2. 优化500页面,错误在后台显示 + 3. 添加Path上带后缀 + 4. 优化多表联查返回数据 + ### v1.2.6 1. 添加多重路由配置方式 2. 添加函数式定义拦截器 diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index 9a570d477..e6f2be536 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -43,10 +43,10 @@ abstract class BladeBase { */ protected static boolean IS_INIT = false; - /** + /** * blade全局初始化对象,在web.xml中配置,必须 */ - protected static BladeApplication bladeApplication; + protected static Bootstrap bootstrap; /** * 全局配置对象 @@ -165,8 +165,8 @@ public static synchronized void staticFolder(final String ... folders) { * * @param bladeApplication 全局初始化bladeApplication */ - public static synchronized void app(BladeApplication bladeApplication){ - BladeBase.bladeApplication = bladeApplication; + public static synchronized void app(Bootstrap bootstrap){ + BladeBase.bootstrap = bootstrap; } /** @@ -318,6 +318,24 @@ public static synchronized void all(String path, RouteHandler routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.ALL); } + /** + * 拦截器before请求 + * @param path + * @param routeHandler + */ + public static synchronized void before(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.BEFORE); + } + + /** + * 拦截器after请求 + * @param path + * @param routeHandler + */ + public static synchronized void after(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.AFTER); + } + /** * 注册一个函数式的拦截器
*

@@ -441,10 +459,10 @@ public static String[] staticFolder(){ } /** - * @return 返回BladeApplication对象 + * @return 返回Bootstrap对象 */ - public static BladeApplication application(){ - return bladeApplication; + public static Bootstrap bootstrap(){ + return bootstrap; } /**--------------------GET CONST:END-------------------------*/ diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java deleted file mode 100644 index 79be87cf7..000000000 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade; - -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import blade.kit.log.Logger; -import blade.route.RouteMatcherBuilder; - -/** - * blade核心过滤器,mvc总线 - * 匹配所有请求过滤 - * - * @author biezhi - * @since 1.0 - */ -public class BladeFilter implements Filter { - - private static final Logger LOGGER = Logger.getLogger(BladeFilter.class); - - /** - * blade全局初始化类 - */ - private static final String APPLCATION_CLASS = "applicationClass"; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - - // 防止重复初始化 - try { - if(!Blade.IS_INIT){ - - BladeBase.webRoot(filterConfig.getServletContext().getRealPath("/")); - - BladeWebContext.servletContext(filterConfig.getServletContext()); - - final BladeApplication application = getApplication(filterConfig); - application.init(); - Blade.app(application); - - // 构建路由 - RouteMatcherBuilder.building(); - - IocApplication.init(); - - application.contextInitialized(BladeWebContext.servletContext()); - - BladeBase.init(); - - LOGGER.info("blade init complete!"); - } - } catch (Exception e) { - LOGGER.error(e); - System.exit(0); - } - - } - - /** - * 获取全局初始化对象,初始化应用 - * - * @param filterConfig 过滤器配置对象 - * @return 一个全局初始化对象 - * @throws ServletException - */ - private BladeApplication getApplication(FilterConfig filterConfig) throws ServletException { - BladeApplication bladeApplication = null; - try { - String applicationClassName = filterConfig.getInitParameter(APPLCATION_CLASS); - if(null != applicationClassName){ - Class applicationClass = Class.forName(applicationClassName); - if(null != applicationClass){ - bladeApplication = (BladeApplication) applicationClass.newInstance(); - } - } else { - throw new ServletException("applicationClass is null !"); - } - } catch (Exception e) { - throw new ServletException(e); - } - return bladeApplication; - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{ - - HttpServletRequest httpRequest = (HttpServletRequest) request; - HttpServletResponse httpResponse = (HttpServletResponse) response; - - httpRequest.setCharacterEncoding(BladeBase.encoding()); - httpResponse.setCharacterEncoding(BladeBase.encoding()); - - /** - * 是否被RequestHandler执行 - */ - boolean isHandler = RequestHandler.single().handler(httpRequest, httpResponse); - if(!isHandler && !httpResponse.isCommitted()){ - chain.doFilter(httpRequest, httpResponse); - } - } - - @Override - public void destroy() { - IocApplication.destroy(); - LOGGER.info("blade destroy!"); - } - -} diff --git a/blade-core/src/main/java/blade/IocApplication.java b/blade-core/src/main/java/blade/IocApplication.java index d5f056128..47bb6f5ea 100644 --- a/blade-core/src/main/java/blade/IocApplication.java +++ b/blade-core/src/main/java/blade/IocApplication.java @@ -50,8 +50,8 @@ public final class IocApplication { public static void init(){ // 初始化全局配置类 - if(null == container.getBean(BladeApplication.class, Scope.SINGLE)){ - container.registBean(Blade.application()); + if(null == container.getBean(Bootstrap.class, Scope.SINGLE)){ + container.registBean(Blade.bootstrap()); } // 初始化ioc容器 diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 5412cf0ae..bac187ca7 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -56,7 +56,8 @@ public class RequestHandler { /** * 服务器500错误时返回的HTML */ - private static final String INTERNAL_ERROR = "

500 Internal Error

"; + + private static final String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade 1.2.7-beta
"; private final static Container container = DefaultContainer.single(); @@ -106,8 +107,6 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse String acceptType = httpRequest.getHeader(ACCEPT_TYPE_REQUEST_MIME_HEADER); - // 响应体 - String bodyContent = null; Request request = null; // 构建一个包装后的response @@ -174,19 +173,21 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse response.render404(uri); } } catch (BladeException bex) { - LOGGER.error(bex.getMessage()); + LOGGER.error(bex); httpResponse.setStatus(500); - if (bex.getMessage() != null) { - bodyContent = bex.getMessage(); - } else { - bodyContent = INTERNAL_ERROR; - } - } - boolean consumed = bodyContent != null; - if (consumed) { // 写入内容到浏览器 if (!httpResponse.isCommitted()) { - response.render500(bodyContent); + response.render500(INTERNAL_ERROR); + return true; + } + } catch (Exception e) { + LOGGER.error(e.getStackTrace()[0]); + e.printStackTrace(); + LOGGER.error(e); + httpResponse.setStatus(500); + // 写入内容到浏览器 + if (!httpResponse.isCommitted()) { + response.render500(INTERNAL_ERROR); return true; } } diff --git a/blade-core/src/main/java/blade/annotation/After.java b/blade-core/src/main/java/blade/annotation/After.java index a18cfeba0..ed99a5e4c 100644 --- a/blade-core/src/main/java/blade/annotation/After.java +++ b/blade-core/src/main/java/blade/annotation/After.java @@ -40,6 +40,12 @@ */ String value() default ""; + /** + * 路由后缀 + * @return String + */ + String suffix() default ""; + /** * 允许的accept */ diff --git a/blade-core/src/main/java/blade/annotation/Before.java b/blade-core/src/main/java/blade/annotation/Before.java index 25a5b9726..f968dcf86 100644 --- a/blade-core/src/main/java/blade/annotation/Before.java +++ b/blade-core/src/main/java/blade/annotation/Before.java @@ -40,6 +40,12 @@ */ String value() default ""; + /** + * 路由后缀 + * @return String + */ + String suffix() default ""; + /** * 允许的accept */ diff --git a/blade-core/src/main/java/blade/annotation/Path.java b/blade-core/src/main/java/blade/annotation/Path.java index bd2010711..47623643d 100644 --- a/blade-core/src/main/java/blade/annotation/Path.java +++ b/blade-core/src/main/java/blade/annotation/Path.java @@ -36,5 +36,11 @@ * @return String */ String value() default "/"; - + + /** + * 路由后缀 + * @return String + */ + String suffix() default ""; + } \ No newline at end of file diff --git a/blade-core/src/main/java/blade/render/JspRender.java b/blade-core/src/main/java/blade/render/JspRender.java index bfb439a41..54beb6c83 100644 --- a/blade-core/src/main/java/blade/render/JspRender.java +++ b/blade-core/src/main/java/blade/render/JspRender.java @@ -25,6 +25,7 @@ import blade.Blade; import blade.BladeWebContext; +import blade.kit.log.Logger; /** * JSP渲染引擎,默认的渲染器 @@ -34,6 +35,8 @@ */ public final class JspRender extends Render { + private static final Logger LOGGER = Logger.getLogger(JspRender.class); + private JspRender() { } @@ -56,9 +59,9 @@ public Object render(final String view){ servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); } catch (ServletException e) { - e.printStackTrace(); + LOGGER.error(e); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } return null; } @@ -83,13 +86,12 @@ public Object render(ModelAndView modelAndView){ } servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); } catch (ServletException e) { - e.printStackTrace(); + LOGGER.error(e); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } return null; } - public static JspRender single() { return JspRenderHolder.single; diff --git a/blade-core/src/main/java/blade/render/Render.java b/blade-core/src/main/java/blade/render/Render.java index ae48dc9f8..b1f660fb2 100644 --- a/blade-core/src/main/java/blade/render/Render.java +++ b/blade-core/src/main/java/blade/render/Render.java @@ -25,6 +25,7 @@ import blade.Blade; import blade.BladeWebContext; +import blade.kit.log.Logger; import blade.servlet.Response; /** * 渲染器抽象类 @@ -34,6 +35,9 @@ */ public abstract class Render { + private static final Logger LOGGER = Logger.getLogger(Render.class); + + static final String VIEW_NOTFOUND = "

404 %s

"; public void render404(String viewName){ @@ -65,7 +69,7 @@ public void render404(Response response, String viewName){ outputStream.close(); } } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } } @@ -93,7 +97,7 @@ public void render500(String bodyContent){ outputStream.close(); } } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e); } } diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index d86572483..bfe96678f 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -261,19 +261,28 @@ private static void parseInterceptor(final Class interceptor){ if (null != before) { + String beforeSuffix = before.suffix(); + String path = before.value().startsWith("/") ? before.value() : "/" + before.value(); path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + path = path + beforeSuffix; + String acceptType = before.acceptType(); buildInterceptor(interceptor, method, path, HttpMethod.BEFORE, acceptType); } if (null != after) { + + String afterSuffix = after.suffix(); + String path = after.value().startsWith("/") ? after.value() : "/" + after.value(); path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + path = path + afterSuffix; + String acceptType = after.acceptType(); buildInterceptor(interceptor, method, path, HttpMethod.AFTER, acceptType); } @@ -296,6 +305,8 @@ private static void parseRouter(final Class router){ final String nameSpace = router.getAnnotation(Path.class).value(); + final String suffix = router.getAnnotation(Path.class).suffix(); + for (Method method : methods) { Route mapping = method.getAnnotation(Route.class); @@ -310,6 +321,8 @@ private static void parseRouter(final Class router){ path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + path = path + suffix; + HttpMethod methodType = mapping.method(); String acceptType = mapping.acceptType(); diff --git a/pom.xml b/pom.xml index 02c41b0c1..f5c0ac22a 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.7-alpha + 1.2.7-beta From 20acec18688c9209df1febfad89c2c96bf8b0e09 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 24 Aug 2015 11:04:56 +0800 Subject: [PATCH 094/545] add bootstrap --- blade-core/src/main/java/blade/Bootstrap.java | 36 ++++++ .../main/java/blade/DispatcherServlet.java | 112 ++++++++++++++++++ .../src/test/java/blade/test/HttpTest.java | 36 ++++++ .../src/test/java/blade/test/TaskTest.java | 35 ++++++ 4 files changed, 219 insertions(+) create mode 100644 blade-core/src/main/java/blade/Bootstrap.java create mode 100644 blade-core/src/main/java/blade/DispatcherServlet.java create mode 100644 blade-kit/src/test/java/blade/test/HttpTest.java create mode 100644 blade-kit/src/test/java/blade/test/TaskTest.java diff --git a/blade-core/src/main/java/blade/Bootstrap.java b/blade-core/src/main/java/blade/Bootstrap.java new file mode 100644 index 000000000..0da16a3c4 --- /dev/null +++ b/blade-core/src/main/java/blade/Bootstrap.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade; + +import javax.servlet.ServletContext; + +/** + * Blade全局初始化类,可以在应用启动的时候做一些操作 + * + * @author biezhi + * @since 1.0 + */ +public abstract class Bootstrap { + + /** + * 初始化方法,在应用启动的时候做一些初始化操作 + */ + public abstract void init(); + + public void contextInitialized(ServletContext servletContext){ + // + } +} diff --git a/blade-core/src/main/java/blade/DispatcherServlet.java b/blade-core/src/main/java/blade/DispatcherServlet.java new file mode 100644 index 000000000..9b061d475 --- /dev/null +++ b/blade-core/src/main/java/blade/DispatcherServlet.java @@ -0,0 +1,112 @@ +package blade; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import blade.kit.log.Logger; +import blade.route.RouteMatcherBuilder; + +/** + * blade核心调度器,mvc总线 + * 匹配所有Blade请求 + * + * @author biezhi + * @since 1.0 + */ +public class DispatcherServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + private static final Logger LOGGER = Logger.getLogger(DispatcherServlet.class); + + /** + * blade全局初始化类 + */ + private static final String APPLCATION_CLASS = "bootstrapClass"; + + @Override + public void init() throws ServletException { + super.init(); + // 防止重复初始化 + try { + if(!Blade.IS_INIT){ + + BladeBase.webRoot(this.getServletContext().getRealPath("/")); + + BladeWebContext.servletContext(this.getServletContext()); + + final Bootstrap application = getBootstrap(this.getInitParameter(APPLCATION_CLASS)); + application.init(); + Blade.app(application); + + // 构建路由 + RouteMatcherBuilder.building(); + + IocApplication.init(); + + application.contextInitialized(BladeWebContext.servletContext()); + + BladeBase.init(); + + LOGGER.info("blade init complete!"); + } + } catch (Exception e) { + LOGGER.error(e); + System.exit(0); + } + } + + /** + * 获取全局初始化对象,初始化应用 + * + * @param botstrapClassName 全局初始化类名 + * @return 一个全局初始化对象 + * @throws ServletException + */ + private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { + Bootstrap bootstrapClass = null; + try { + if(null != botstrapClassName){ + Class applicationClass = Class.forName(botstrapClassName); + if(null != applicationClass){ + bootstrapClass = (Bootstrap) applicationClass.newInstance(); + } + } else { + throw new ServletException("bootstrapClass is null !"); + } + } catch (Exception e) { + throw new ServletException(e); + } + return bootstrapClass; + } + + public DispatcherServlet() { + super(); + } + + @Override + protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) + throws ServletException, IOException { + + httpRequest.setCharacterEncoding(BladeBase.encoding()); + httpResponse.setCharacterEncoding(BladeBase.encoding()); + + /** + * 是否被RequestHandler执行 + */ + boolean isHandler = RequestHandler.single().handler(httpRequest, httpResponse); + if(!isHandler && !httpResponse.isCommitted()){ + super.service(httpRequest, httpResponse); + } + } + + @Override + public void destroy() { + IocApplication.destroy(); + LOGGER.info("blade destroy!"); + } +} diff --git a/blade-kit/src/test/java/blade/test/HttpTest.java b/blade-kit/src/test/java/blade/test/HttpTest.java new file mode 100644 index 000000000..d533abc7d --- /dev/null +++ b/blade-kit/src/test/java/blade/test/HttpTest.java @@ -0,0 +1,36 @@ +package blade.test; + +import java.io.File; + +import blade.kit.http.HttpRequest; + + + +public class HttpTest { + + public static void main(String[] args) { + + // 发送一个GET请求并获取内容 + String body = HttpRequest.get("http://bladejava.com").body(); + System.out.println(body); + + // 发送一个带heder的请求 + String res = HttpRequest.get("http://bladejava.com").accept("application/json") + .userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0").body(); + System.out.println(res); + + // 发送一个POST请求 + HttpRequest.post("http://www.example.com").part("id", 20).part("name", "jack").body(); + + // 带认证的请求 + int response = HttpRequest.get("http://google.com").basic("username", "p4ssw0rd").code(); + System.out.println(response); + + // 下载一个图片 + File file = new File("F:/a.png"); + HttpRequest.get("http://img.blog.csdn.net/20150601232126808").receive(file); + + + } + +} diff --git a/blade-kit/src/test/java/blade/test/TaskTest.java b/blade-kit/src/test/java/blade/test/TaskTest.java new file mode 100644 index 000000000..f20499806 --- /dev/null +++ b/blade-kit/src/test/java/blade/test/TaskTest.java @@ -0,0 +1,35 @@ +package blade.test; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +import blade.kit.TaskKit; + + +public class TaskTest { + + public static void main(String[] args) { + TaskKit.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + System.out.println("每隔两秒执行一次"); + } + }, 2); + + TaskKit.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + System.out.println("在指定的延时之后开始以固定的频率来运行任务。后续任务的启动时间不受前次任务延时影响。"); + } + }, 10, 3, TimeUnit.SECONDS); + + TaskKit.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + System.out.println("在指定的时间点启动,两次任务间保持固定的时间间隔"); + } + }, new Date(), 3, TimeUnit.SECONDS); + + } + +} From 741b19f65473a4742d2b1fa55e7e7cdef81956ca Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 24 Aug 2015 11:33:17 +0800 Subject: [PATCH 095/545] fix multi-table select bug --- .../main/java/blade/plugin/sql2o/Model.java | 83 ++++++++++++++++--- .../plugin/sql2o/cache/SimpleSql2oCache.java | 15 ++++ .../blade/plugin/sql2o/cache/Sql2oCache.java | 5 ++ 3 files changed, 90 insertions(+), 13 deletions(-) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 6433db353..a8065ef42 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -11,7 +11,6 @@ import org.sql2o.Query; import org.sql2o.Sql2o; -import blade.kit.BeanKit; import blade.kit.StringKit; import blade.kit.log.Logger; import blade.plugin.sql2o.Condition.DmlType; @@ -716,13 +715,46 @@ public List executeAndFetch(Class clazz){ */ public List> fetchListMap(){ - if(condition.dmlType.equals(DmlType.SELECT)){ + if(condition.dmlType.equals(DmlType.SELECT)){ + + String field = null; + List> result = null; + + // 开启缓存 + if(isCache()){ + field = MD5.create(getCacheKey(null)); + result = sql2oCache.hgetlistmap(CACHE_KEY_LIST, field); + if(null != result){ + return result; + } + } + + String sqlEnd = condition.getConditionSql(); - List list = fetchList(); - if(null != list && list.size() > 0){ - List> result = BeanKit.toListMap(list); - return result; + if(null != condition.orderby){ + sqlEnd += " order by " + condition.orderby; } + + try { + Connection conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd); + query = parseParams(query); + + LOGGER.debug("execute sql:" + query.toString()); + + condition.printLog(); + condition.clearMap(); + + result = query.executeAndFetchTable().asList(); + + if(isCache() && null != result){ + sql2oCache.hsetlistmap(CACHE_KEY_LIST, field, result); + } + + return result; + } catch (Exception e) { + LOGGER.error(e); + } } return null; } @@ -832,16 +864,41 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ if(condition.dmlType.equals(DmlType.SELECT) && null != page && null != pageSize && page > 0 && pageSize > 0){ - Page pageModel = fetchPage(page, pageSize); - - if(null != pageModel && null != pageModel.getResults()){ + // 查询总记录数 + long totalCount = getPageCount(); + + List> results = null; + + String sqlEnd = condition.getConditionSql(); + + if(null != condition.orderby){ + sqlEnd += " order by " + condition.orderby; + } + + sqlEnd += " limit :page, :pageSize"; + + condition.where("page", page - 1); + condition.where("pageSize", pageSize); + + try { + // 设置query + Connection conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd); + query = parseParams(query); - pageMap = new Page>(pageModel.getTotalCount(), page, pageSize); + LOGGER.debug("execute sql:" + query.toString()); + condition.printLog(); + + results = query.executeAndFetchTable().asList(); - List list = pageModel.getResults(); - List> result = BeanKit.toListMap(list); - pageMap.setResults(result); + pageMap = new Page>(totalCount, page, pageSize); + if(null != results && results.size() > 0){ + pageMap.setResults(results); + } + + } catch (Exception e) { + LOGGER.error(e); } condition.clearMap(); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java index d3c79a5c8..8bbb6d68e 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java @@ -2,6 +2,7 @@ import java.io.Serializable; import java.util.List; +import java.util.Map; import blade.cache.Cache; import blade.cache.CacheManager; @@ -88,6 +89,15 @@ public List hgetlist(String key, String field) { return null; } + @Override + public List> hgetlistmap(String key, String field) { + Object object = cache.hget(key, field); + if(null != object){ + return (List>) object; + } + return null; + } + @Override public List hgetlists(String key, String field) { Object object = cache.hget(key, field); @@ -112,6 +122,11 @@ public void hsetlist(String key, String field, List cache.hset(key, field, value); } + @Override + public void hsetlistmap(String key, String field, List> value) { + cache.hset(key, field, value); + } + @Override public void hsetlists(String key, String field, List value) { cache.hset(key, field, value); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java index efff206c0..fe2c30de9 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java @@ -2,6 +2,7 @@ import java.io.Serializable; import java.util.List; +import java.util.Map; public interface Sql2oCache { @@ -15,6 +16,8 @@ public interface Sql2oCache { void hsetlist(String key, String field, List value); + void hsetlistmap(String key, String field, List> value); + void hsetlists(String key, String field, List value); void hset(String key, String field, Serializable value, long expire); @@ -29,6 +32,8 @@ public interface Sql2oCache { List hgetlist(String key, String field); + List> hgetlistmap(String key, String field); + List hgetlists(String key, String field); void hdel(String key); From ba8e1649dd53b16b3b2db438de3c5d4f51ca04c6 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 24 Aug 2015 11:36:04 +0800 Subject: [PATCH 096/545] update readme --- README.md | 23 ++++++++++++----------- README_CN.md | 23 ++++++++++++----------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 774835bcb..0f3973dc5 100644 --- a/README.md +++ b/README.md @@ -35,32 +35,33 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.7-alpha + 1.2.7-beta ``` Second. Configuration in the `web.xml` Blade core filter initialization and set your class ```xml - - BladeFilter - blade.BladeFilter + + dispatcher + blade.DispatcherServlet - applicationClass - hello.App + bootstrapClass + blade.hello.App - + 1 + - - BladeFilter + + dispatcher /* - + ``` Third. Write App.java and routing file, here is an example ```java -public class App extends BladeApplication{ +public class App extends Bootstrap{ Logger logger = Logger.getLogger(App.class); @Override diff --git a/README_CN.md b/README_CN.md index 935e191fc..00fbb47c1 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,32 +33,33 @@ com.bladejava blade-core - 1.2.7-alpha + 1.2.7-beta ``` 第二步、在`web.xml`中配置Blade核心过滤器并设置你的初始化类 ```xml - - BladeFilter - blade.BladeFilter + + dispatcher + blade.DispatcherServlet - applicationClass - hello.App + bootstrapClass + blade.hello.App - + 1 + - - BladeFilter + + dispatcher /* - + ``` 第三步、编写App.java和路由文件,下面是一个示例 ```java -public class App extends BladeApplication{ +public class App extends Bootstrap{ Logger logger = Logger.getLogger(App.class); @Override From 32f3821bee82e51a1a8dec62b5ea3d545aa63f36 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 24 Aug 2015 11:40:44 +0800 Subject: [PATCH 097/545] update version --- LAST_VERSION.md | 4 ++-- blade-sql2o/pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index fd310fa6b..48f8eae1d 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.7-alpha +    1.2.7-beta ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -22,7 +22,7 @@     com.bladejava     blade-sql2o -    1.2.6-alpha +    1.2.6-beta ``` diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index e3783b784..ef91f5b40 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - 1.2.6-alpha + 1.2.6-beta blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o From 4da990a3017f22d8445c34ab708facec915e20d5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 24 Aug 2015 16:09:00 +0800 Subject: [PATCH 098/545] reback --- .../src/main/java/blade/BladeApplication.java | 36 ----- .../src/main/java/blade/BladeFilter.java | 129 ++++++++++++++++++ .../main/java/blade/DispatcherServlet.java | 1 + .../src/main/java/blade/RequestHandler.java | 4 +- 4 files changed, 131 insertions(+), 39 deletions(-) delete mode 100644 blade-core/src/main/java/blade/BladeApplication.java create mode 100644 blade-core/src/main/java/blade/BladeFilter.java diff --git a/blade-core/src/main/java/blade/BladeApplication.java b/blade-core/src/main/java/blade/BladeApplication.java deleted file mode 100644 index d75c4c04b..000000000 --- a/blade-core/src/main/java/blade/BladeApplication.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade; - -import javax.servlet.ServletContext; - -/** - * Blade全局初始化类,可以在应用启动的时候做一些操作 - * - * @author biezhi - * @since 1.0 - */ -public abstract class BladeApplication { - - /** - * 初始化方法,在应用启动的时候做一些初始化操作 - */ - public abstract void init(); - - public void contextInitialized(ServletContext servletContext){ - // - } -} diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java new file mode 100644 index 000000000..146319deb --- /dev/null +++ b/blade-core/src/main/java/blade/BladeFilter.java @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import blade.kit.log.Logger; +import blade.route.RouteMatcherBuilder; + +/** + * blade核心过滤器,mvc总线 + * 匹配所有请求过滤 + * + * @author biezhi + * @since 1.0 + */ +public class BladeFilter implements Filter { + + private static final Logger LOGGER = Logger.getLogger(BladeFilter.class); + + /** + * blade全局初始化类 + */ + private static final String APPLCATION_CLASS = "applicationClass"; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + // 防止重复初始化 + try { + if(!Blade.IS_INIT){ + + BladeBase.webRoot(filterConfig.getServletContext().getRealPath("/")); + + BladeWebContext.servletContext(filterConfig.getServletContext()); + + final Bootstrap bootstrap = getBootstrap(filterConfig.getInitParameter(APPLCATION_CLASS)); + bootstrap.init(); + Blade.app(bootstrap); + + // 构建路由 + RouteMatcherBuilder.building(); + + IocApplication.init(); + + bootstrap.contextInitialized(BladeWebContext.servletContext()); + + BladeBase.init(); + + LOGGER.info("blade init complete!"); + } + } catch (Exception e) { + LOGGER.error(e); + System.exit(0); + } + + } + + /** + * 获取全局初始化对象,初始化应用 + * + * @param botstrapClassName 全局初始化类名 + * @return 一个全局初始化对象 + * @throws ServletException + */ + private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { + Bootstrap bootstrapClass = null; + try { + if(null != botstrapClassName){ + Class applicationClass = Class.forName(botstrapClassName); + if(null != applicationClass){ + bootstrapClass = (Bootstrap) applicationClass.newInstance(); + } + } else { + throw new ServletException("bootstrapClass is null !"); + } + } catch (Exception e) { + throw new ServletException(e); + } + return bootstrapClass; + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{ + + HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; + + httpRequest.setCharacterEncoding(BladeBase.encoding()); + httpResponse.setCharacterEncoding(BladeBase.encoding()); + + /** + * 是否被RequestHandler执行 + */ + boolean isHandler = RequestHandler.single().handler(httpRequest, httpResponse); + if(!isHandler){ + chain.doFilter(httpRequest, httpResponse); + } + } + + @Override + public void destroy() { + IocApplication.destroy(); + LOGGER.info("blade destroy!"); + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/blade/DispatcherServlet.java b/blade-core/src/main/java/blade/DispatcherServlet.java index 9b061d475..535852acb 100644 --- a/blade-core/src/main/java/blade/DispatcherServlet.java +++ b/blade-core/src/main/java/blade/DispatcherServlet.java @@ -17,6 +17,7 @@ * @author biezhi * @since 1.0 */ +@Deprecated public class DispatcherServlet extends HttpServlet { private static final long serialVersionUID = 1L; diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index bac187ca7..e2103b803 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -173,7 +173,7 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse response.render404(uri); } } catch (BladeException bex) { - LOGGER.error(bex); + bex.printStackTrace(); httpResponse.setStatus(500); // 写入内容到浏览器 if (!httpResponse.isCommitted()) { @@ -181,9 +181,7 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse return true; } } catch (Exception e) { - LOGGER.error(e.getStackTrace()[0]); e.printStackTrace(); - LOGGER.error(e); httpResponse.setStatus(500); // 写入内容到浏览器 if (!httpResponse.isCommitted()) { From c99ebb72e07dbcee5053c7175518ddb2dd3ac2fa Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 24 Aug 2015 16:09:24 +0800 Subject: [PATCH 099/545] reback --- LAST_VERSION.md | 2 +- README.md | 26 ++++++++++++-------------- README_CN.md | 26 ++++++++++++-------------- UPDATE_LOG.md | 7 +++---- pom.xml | 2 +- 5 files changed, 29 insertions(+), 34 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 48f8eae1d..36e2cbbe5 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.7-beta +    1.2.7 ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/README.md b/README.md index 0f3973dc5..b5ec16714 100644 --- a/README.md +++ b/README.md @@ -35,27 +35,25 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.7-beta + 1.2.7 ``` Second. Configuration in the `web.xml` Blade core filter initialization and set your class ```xml - - dispatcher - blade.DispatcherServlet - - bootstrapClass + + BladeFilter + blade.BladeFilter + + bootstrapClass blade.hello.App - - 1 - - - - dispatcher - /* - + +
+ + BladeFilter + /* + ``` Third. Write App.java and routing file, here is an example diff --git a/README_CN.md b/README_CN.md index 00fbb47c1..eaccfea9e 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,27 +33,25 @@ com.bladejava blade-core - 1.2.7-beta + 1.2.7 ``` 第二步、在`web.xml`中配置Blade核心过滤器并设置你的初始化类 ```xml - - dispatcher - blade.DispatcherServlet - - bootstrapClass + + BladeFilter + blade.BladeFilter + + bootstrapClass blade.hello.App - - 1 - - - - dispatcher - /* - + +
+ + BladeFilter + /* + ``` 第三步、编写App.java和路由文件,下面是一个示例 diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index bc0c5eba6..d9dad53ac 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,10 +1,9 @@ #Blade 更新日志 ### v1.2.7 - 1. 去除Filter改为Servlet方式 - 2. 优化500页面,错误在后台显示 - 3. 添加Path上带后缀 - 4. 优化多表联查返回数据 + 1. 优化500页面,错误在后台显示 + 2. 添加Path上带后缀 + 3. 优化多表联查返回数据 ### v1.2.6 1. 添加多重路由配置方式 diff --git a/pom.xml b/pom.xml index f5c0ac22a..520885c22 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.7-beta + 1.2.7 From 9f02da6e41196175226514bb63f8fb1ff584e375 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 24 Aug 2015 16:48:28 +0800 Subject: [PATCH 100/545] fix sql2o update field count add one bug --- .../main/java/blade/DispatcherServlet.java | 113 ------------------ .../src/main/java/blade/servlet/Response.java | 22 +++- blade-sql2o/pom.xml | 2 +- .../java/blade/plugin/sql2o/Condition.java | 6 +- .../main/java/blade/plugin/sql2o/Model.java | 2 +- 5 files changed, 27 insertions(+), 118 deletions(-) delete mode 100644 blade-core/src/main/java/blade/DispatcherServlet.java diff --git a/blade-core/src/main/java/blade/DispatcherServlet.java b/blade-core/src/main/java/blade/DispatcherServlet.java deleted file mode 100644 index 535852acb..000000000 --- a/blade-core/src/main/java/blade/DispatcherServlet.java +++ /dev/null @@ -1,113 +0,0 @@ -package blade; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import blade.kit.log.Logger; -import blade.route.RouteMatcherBuilder; - -/** - * blade核心调度器,mvc总线 - * 匹配所有Blade请求 - * - * @author biezhi - * @since 1.0 - */ -@Deprecated -public class DispatcherServlet extends HttpServlet { - - private static final long serialVersionUID = 1L; - - private static final Logger LOGGER = Logger.getLogger(DispatcherServlet.class); - - /** - * blade全局初始化类 - */ - private static final String APPLCATION_CLASS = "bootstrapClass"; - - @Override - public void init() throws ServletException { - super.init(); - // 防止重复初始化 - try { - if(!Blade.IS_INIT){ - - BladeBase.webRoot(this.getServletContext().getRealPath("/")); - - BladeWebContext.servletContext(this.getServletContext()); - - final Bootstrap application = getBootstrap(this.getInitParameter(APPLCATION_CLASS)); - application.init(); - Blade.app(application); - - // 构建路由 - RouteMatcherBuilder.building(); - - IocApplication.init(); - - application.contextInitialized(BladeWebContext.servletContext()); - - BladeBase.init(); - - LOGGER.info("blade init complete!"); - } - } catch (Exception e) { - LOGGER.error(e); - System.exit(0); - } - } - - /** - * 获取全局初始化对象,初始化应用 - * - * @param botstrapClassName 全局初始化类名 - * @return 一个全局初始化对象 - * @throws ServletException - */ - private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { - Bootstrap bootstrapClass = null; - try { - if(null != botstrapClassName){ - Class applicationClass = Class.forName(botstrapClassName); - if(null != applicationClass){ - bootstrapClass = (Bootstrap) applicationClass.newInstance(); - } - } else { - throw new ServletException("bootstrapClass is null !"); - } - } catch (Exception e) { - throw new ServletException(e); - } - return bootstrapClass; - } - - public DispatcherServlet() { - super(); - } - - @Override - protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) - throws ServletException, IOException { - - httpRequest.setCharacterEncoding(BladeBase.encoding()); - httpResponse.setCharacterEncoding(BladeBase.encoding()); - - /** - * 是否被RequestHandler执行 - */ - boolean isHandler = RequestHandler.single().handler(httpRequest, httpResponse); - if(!isHandler && !httpResponse.isCommitted()){ - super.service(httpRequest, httpResponse); - } - } - - @Override - public void destroy() { - IocApplication.destroy(); - LOGGER.info("blade destroy!"); - } -} diff --git a/blade-core/src/main/java/blade/servlet/Response.java b/blade-core/src/main/java/blade/servlet/Response.java index bfac6849c..8f3ab2034 100644 --- a/blade-core/src/main/java/blade/servlet/Response.java +++ b/blade-core/src/main/java/blade/servlet/Response.java @@ -22,6 +22,8 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; +import blade.Blade; +import blade.BladeWebContext; import blade.kit.log.Logger; import blade.render.ModelAndView; import blade.render.Render; @@ -111,13 +113,31 @@ public HttpServletResponse servletResponse() { return response; } + /** + * 重定向到location + * + * @param location 重定向的location + */ + public void go(String path) { + if (Blade.debug()) { + LOGGER.debug("Redirecting ({} {} to {}", "Found", HttpServletResponse.SC_FOUND, path); + } + try { + String ctx = BladeWebContext.servletContext().getContextPath(); + String location = (ctx + path).replaceAll("//", "/"); + response.sendRedirect(location); + } catch (IOException ioException) { + LOGGER.warn("Redirect failure", ioException); + } + } + /** * 重定向到location * * @param location 重定向的location */ public void redirect(String location) { - if (LOGGER.isDebugEnabled()) { + if (Blade.debug()) { LOGGER.debug("Redirecting ({} {} to {}", "Found", HttpServletResponse.SC_FOUND, location); } try { diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index ef91f5b40..73c5ed84f 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - 1.2.6-beta + 1.2.6 blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java index 5078f5de1..4f2ab59ed 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java @@ -209,24 +209,26 @@ public void count(String sql){ this.orderby = null; } - public void update(){ + public Condition update(){ this.sql = "update " + this.tableName; clearMap(); this.params = CollectionKit.newLinkedHashMap(); this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.UPDATE; + return this; } /** * 自定义更新语句 * @param sql */ - public void update(String sql){ + public Condition update(String sql){ this.sql = sql; clearMap(); this.params = CollectionKit.newLinkedHashMap(); this.equalsParams = CollectionKit.newLinkedHashMap(); this.dmlType = DmlType.UPDATE; + return this; } public void insert(){ diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index a8065ef42..e27e90365 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -1124,7 +1124,7 @@ private Query updateCommit(Connection conn){ Query query = conn.createQuery(updateSql); query = parseParams(query); - query.executeUpdate(); +// query.executeUpdate(); LOGGER.debug("execute sql:" + query.toString()); LOGGER.debug("execute parameter:" + condition.params.values() + condition.equalsParams.values()); From 74f83d48d468c2386283433ab9861835d66b0a23 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 24 Aug 2015 18:07:20 +0800 Subject: [PATCH 101/545] update blade-sql2o version --- blade-sql2o/pom.xml | 18 ++--- .../main/java/blade/plugin/sql2o/Model.java | 74 +++++++++++-------- 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 73c5ed84f..2a6879999 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -16,6 +16,12 @@ https://github.com/biezhi/blade/tree/master/blade-sql2o + + org.sql2o + sql2o + 1.5.4 + + com.bladejava blade-core @@ -28,16 +34,6 @@ 1.2.2 provided - - mysql - mysql-connector-java - 5.1.35 - provided - - - org.sql2o - sql2o - 1.5.4 - + diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index e27e90365..3c8426a0c 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -340,7 +340,7 @@ private String getCacheKey(String sql){ private Query parseParams(Query query){ // insert、update参数 - if(null != condition.params && condition.params.size() > 0){ + if(null != condition.params){ Set keys = condition.params.keySet(); for(String name : keys){ query.addParameter(condition.filterKeyWord(name), condition.params.get(name)); @@ -348,7 +348,7 @@ private Query parseParams(Query query){ } // 基础equals条件 - if(null != condition.equalsParams && condition.equalsParams.size() > 0){ + if(null != condition.equalsParams){ Set keys = condition.equalsParams.keySet(); for(String name : keys){ query.addParameter(condition.filterKeyWord(name), condition.equalsParams.get(name)); @@ -356,7 +356,7 @@ private Query parseParams(Query query){ } // 大于条件 - if(null != condition.greaterParams && condition.greaterParams.size() > 0){ + if(null != condition.greaterParams){ Set keys = condition.greaterParams.keySet(); for(String name : keys){ query.addParameter(condition.filterKeyWord(name), condition.greaterParams.get(name)); @@ -364,7 +364,7 @@ private Query parseParams(Query query){ } // 小于条件 - if(null != condition.lessParams && condition.lessParams.size() > 0){ + if(null != condition.lessParams){ Set keys = condition.lessParams.keySet(); for(String name : keys){ query.addParameter(condition.filterKeyWord(name), condition.lessParams.get(name)); @@ -372,7 +372,7 @@ private Query parseParams(Query query){ } // 大于等于条件 - if(null != condition.greaterThanParams && condition.greaterThanParams.size() > 0){ + if(null != condition.greaterThanParams){ Set keys = condition.greaterThanParams.keySet(); for(String name : keys){ query.addParameter(condition.filterKeyWord(name), condition.greaterThanParams.get(name)); @@ -380,7 +380,7 @@ private Query parseParams(Query query){ } // 小于等于条件 - if(null != condition.lessThanParams && condition.lessThanParams.size() > 0){ + if(null != condition.lessThanParams){ Set keys = condition.lessThanParams.keySet(); for(String name : keys){ query.addParameter(condition.filterKeyWord(name), condition.lessThanParams.get(name)); @@ -388,7 +388,7 @@ private Query parseParams(Query query){ } // like条件 - if(null != condition.likeParams && condition.likeParams.size() > 0){ + if(null != condition.likeParams){ Set keys = condition.likeParams.keySet(); for(String name : keys){ query.addParameter(condition.filterKeyWord(name), condition.likeParams.get(name)); @@ -396,7 +396,7 @@ private Query parseParams(Query query){ } // in条件 - if(null != condition.inParams && condition.inParams.size() > 0){ + if(null != condition.inParams){ Set keys = condition.inParams.keySet(); for(String name : keys){ @@ -940,11 +940,16 @@ public V executeAndCommit(Class returnType) { sql2oCache.hdel(CACHE_KEY_LIST); } - if(null != returnType){ - key = query.executeUpdate().getKey(returnType); + if(null == query){ + LOGGER.error("query is null"); } else { - key = (V) query.executeUpdate().getKey(); + if(null != returnType){ + key = query.executeUpdate().getKey(returnType); + } else { + key = (V) query.executeUpdate().getKey(); + } } + } // 更新 @@ -956,7 +961,12 @@ public V executeAndCommit(Class returnType) { sql2oCache.hdel(CACHE_KEY_DETAIL); sql2oCache.hdel(CACHE_KEY_LIST); } - key = (V) Integer.valueOf(query.executeUpdate().getResult()); + + if(null == query){ + LOGGER.error("query is null"); + } else { + key = (V) ((Integer) query.executeUpdate().getResult()); + } } // 删除 @@ -969,13 +979,18 @@ public V executeAndCommit(Class returnType) { sql2oCache.hdel(CACHE_KEY_LIST); sql2oCache.hdel(CACHE_KEY_DETAIL); } - key = (V) Integer.valueOf(query.executeUpdate().getResult()); + if(null == query){ + LOGGER.error("query is null"); + } else { + key = (V) Integer.valueOf(query.executeUpdate().getResult()); + } + } condition.clearMap(); return key; } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } return null; } @@ -1055,7 +1070,7 @@ private Query insertCommit(Connection conn){ String insertSql = condition.sql; - if(!condition.params.isEmpty() && condition.params.size() > 0){ + if(null != condition.params){ StringBuffer paramBuf = new StringBuffer("("); StringBuffer valuesBuf = new StringBuffer(" values("); @@ -1091,7 +1106,7 @@ private Query insertCommit(Connection conn){ */ private Query updateCommit(Connection conn){ - if(null != condition.params && condition.params.size() > 0){ + if(null != condition.params){ StringBuffer setBuf = new StringBuffer(" set "); StringBuffer whereBuf = new StringBuffer("("); @@ -1114,22 +1129,19 @@ private Query updateCommit(Connection conn){ whereSql = whereBuf.substring(0, whereBuf.length() - 2); } - if(setSql.length() > 0){ - - String updateSql = condition.sql + setSql + whereSql; - - if(null == conn){ - conn = sql2o.open(); - } - - Query query = conn.createQuery(updateSql); - query = parseParams(query); -// query.executeUpdate(); - LOGGER.debug("execute sql:" + query.toString()); - LOGGER.debug("execute parameter:" + condition.params.values() + condition.equalsParams.values()); - - return query; + String updateSql = condition.sql + setSql + whereSql; + + if(null == conn){ + conn = sql2o.open(); } + + Query query = conn.createQuery(updateSql); + query = parseParams(query); +// query.executeUpdate(); + LOGGER.debug("execute sql:" + query.toString()); + LOGGER.debug("execute parameter:" + condition.params.values() + condition.equalsParams.values()); + + return query; } return null; } From 28ba2336b8af671b624e0241955a01ebb107fcb2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 24 Aug 2015 18:22:56 +0800 Subject: [PATCH 102/545] - --- LAST_VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 36e2cbbe5..908685b71 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -22,7 +22,7 @@     com.bladejava     blade-sql2o -    1.2.6-beta +    1.2.6 ``` From d90c52ab31b6fab474bfdb3b4a4e4bd5ad760074 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 25 Aug 2015 10:19:16 +0800 Subject: [PATCH 103/545] optimize the parameters for java --- blade-sql2o/pom.xml | 2 +- .../java/blade/plugin/sql2o/Condition.java | 54 ++++++- .../main/java/blade/plugin/sql2o/Model.java | 11 ++ .../java/blade/plugin/sql2o/WhereParam.java | 140 ++++++++++++++++++ 4 files changed, 201 insertions(+), 6 deletions(-) create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 2a6879999..5e20f4bf4 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - 1.2.6 + 1.2.7-alpha blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java index 4f2ab59ed..79c761f65 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java @@ -55,6 +55,14 @@ enum DmlType { public Condition(String tableName, String pkName) { this.tableName = tableName; this.pkName = pkName; + this.params = CollectionKit.newHashMap(); + this.equalsParams = CollectionKit.newHashMap(); + this.greaterParams = CollectionKit.newHashMap(); + this.greaterThanParams = CollectionKit.newHashMap(); + this.lessParams = CollectionKit.newHashMap(); + this.lessThanParams = CollectionKit.newHashMap(); + this.likeParams = CollectionKit.newHashMap(); + this.inParams = CollectionKit.newHashMap(); } public String getConditionSql() { @@ -122,27 +130,27 @@ public void clearMap() { if(null != this.params){ this.params.clear(); - this.params = null; +// this.params = null; } if(null != this.equalsParams){ this.equalsParams.clear(); - this.equalsParams = null; +// this.equalsParams = null; } if(null != this.greaterParams){ this.greaterParams.clear(); - this.greaterParams = null; +// this.greaterParams = null; } if(null != this.greaterThanParams){ this.greaterThanParams.clear(); - this.greaterThanParams = null; +// this.greaterThanParams = null; } if(null != this.lessParams){ this.lessParams.clear(); - this.lessParams = null; +// this.lessParams = null; } if(null != this.lessThanParams){ @@ -280,6 +288,42 @@ public void param(String name, Object value){ } } + public void where(WhereParam whereParam){ + if(null != whereParam){ + if(whereParam.equalsParams.size() > 0){ + this.equalsParams.putAll(whereParam.equalsParams); + } + + if(whereParam.greaterParams.size() > 0){ + this.greaterParams.putAll(whereParam.greaterParams); + } + + if(whereParam.greaterThanParams.size() > 0){ + this.greaterThanParams.putAll(whereParam.greaterThanParams); + } + + if(whereParam.lessParams.size() > 0){ + this.lessParams.putAll(whereParam.lessParams); + } + + if(whereParam.lessThanParams.size() > 0){ + this.lessThanParams.putAll(whereParam.lessThanParams); + } + + if(whereParam.likeParams.size() > 0){ + this.likeParams.putAll(whereParam.likeParams); + } + + if(whereParam.inParams.size() > 0){ + this.inParams.putAll(whereParam.inParams); + } + + if(whereParam.params.size() > 0){ + this.params.putAll(whereParam.params); + } + } + } + /** * 设置where参数列表,查询,更新,删除用到 * diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 3c8426a0c..8ada14637 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -211,6 +211,17 @@ public Model where(String name, Object value){ return this; } + /** + * 设置where参数列表,查询,更新,删除用到 + * + * @param whereParam 保存参数的对象 + * @return 返回model对象 + */ + public Model where(WhereParam whereParam){ + condition.where(whereParam); + return this; + } + /** * 大于 * @param name diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java new file mode 100644 index 000000000..1c1f777d4 --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java @@ -0,0 +1,140 @@ +package blade.plugin.sql2o; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import blade.kit.CollectionKit; +import blade.kit.StringKit; + + +/** + * 参数存储对象 + * @author biezhi + * @since 1.0 + * @param + */ +public class WhereParam { + + // 存储设置的参数,insert-update用 + Map params; + + // 存储where条件,select-update-delete用 + Map equalsParams; + + // 大于 + Map greaterParams; + // 大于等于 + Map greaterThanParams; + // 小于 + Map lessParams; + // 小于等于 + Map lessThanParams; + // like + Map likeParams; + // in + Map inParams; + + List logParams = new LinkedList(); + + public WhereParam() { + params = CollectionKit.newHashMap(); + equalsParams = CollectionKit.newHashMap(); + greaterParams = CollectionKit.newHashMap(); + greaterThanParams = CollectionKit.newHashMap(); + lessParams = CollectionKit.newHashMap(); + lessThanParams = CollectionKit.newHashMap(); + likeParams = CollectionKit.newHashMap(); + inParams = CollectionKit.newHashMap(); + } + + public static WhereParam me(){ + return new WhereParam(); + } + + public WhereParam eq(String field, Object value){ + if(StringKit.isNotBlank(field) && null != value){ + this.equalsParams.put(field, value); + this.logParams.add(value); + } + return this; + } + + public WhereParam like(String field, String value){ + if(StringKit.isNotBlank(field) && StringKit.isNotBlank(value) + && value.indexOf("%null")==-1 && value.indexOf("null%")==-1 && !value.equals("%%")){ + + if(null == this.likeParams){ + this.likeParams = CollectionKit.newLinkedHashMap(); + } + this.likeParams.put(field, value); + this.logParams.add(value); + } + return this; + } + + public WhereParam in(String field, Object... values){ + if(StringKit.isNotBlank(field) && null != values && values.length > 1){ + if(null == this.inParams){ + this.inParams = CollectionKit.newLinkedHashMap(); + } + this.inParams.put(field, values); + this.logParams.add(Arrays.toString(values)); + } + return this; + } + + public WhereParam less(String field, Object value){ + if(StringKit.isNotBlank(field) && null != value){ + if(null == this.lessParams){ + this.lessParams = CollectionKit.newLinkedHashMap(); + } + this.lessParams.put(field, value); + this.logParams.add(value); + } + return this; + } + + public WhereParam lessThan(String field, Object value){ + if(StringKit.isNotBlank(field) && null != value){ + + if(null == this.lessThanParams){ + this.lessThanParams = CollectionKit.newLinkedHashMap(); + } + this.lessThanParams.put(field, value); + this.logParams.add(value); + } + return this; + } + + public WhereParam greater(String field, Object value){ + if(StringKit.isNotBlank(field) && null != value){ + if(null == this.greaterParams){ + this.greaterParams = CollectionKit.newLinkedHashMap(); + } + this.greaterParams.put(field, value); + this.logParams.add(value); + } + return this; + } + + public WhereParam greaterThan(String field, Object value){ + if(StringKit.isNotBlank(field) && null != value){ + if(null == this.greaterThanParams){ + this.greaterThanParams = CollectionKit.newLinkedHashMap(); + } + this.greaterThanParams.put(field, value); + this.logParams.add(value); + } + return this; + } + + public WhereParam set(String field, Object value){ + if(StringKit.isNotBlank(field) && null != value){ + this.params.put(field, value); + this.logParams.add(value); + } + return this; + } +} From 347a867161213301ddd4da0d453432648143117e Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 25 Aug 2015 11:41:01 +0800 Subject: [PATCH 104/545] sql2o add return map data --- UPDATE_LOG.md | 2 + .../main/java/blade/plugin/sql2o/Model.java | 52 +++++++++++++++++++ .../plugin/sql2o/cache/SimpleSql2oCache.java | 2 +- .../blade/plugin/sql2o/cache/Sql2oCache.java | 2 +- 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index d9dad53ac..03b816a68 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -4,6 +4,8 @@ 1. 优化500页面,错误在后台显示 2. 添加Path上带后缀 3. 优化多表联查返回数据 + 4. 解决java多参数传递问题 + 5. 多表联查返回Map类型数据 ### v1.2.6 1. 添加多重路由配置方式 diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 8ada14637..3c78923c8 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -512,6 +512,7 @@ private Long getPageCount(){ } return 0L; } + /** * @return 返回查询一个对象 */ @@ -557,6 +558,57 @@ public T fetchOne(){ return null; } + /** + * @return 返回查询一个对象 + */ + @SuppressWarnings("unchecked") + public Map fetchMap(){ + + if(condition.dmlType.equals(DmlType.SELECT)){ + + String sqlEnd = condition.getConditionSql(); + + Map res = null; + String field = null; + + // 是否开启缓存查询 + if(isCache()){ + field = MD5.create(getCacheKey(null)); + + res = sql2oCache.hgetV(CACHE_KEY_DETAIL, field); + if(null != res){ + return res; + } + } + + try { + Connection conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd); + query = parseParams(query); + + LOGGER.debug("execute sql:" + query.toString()); + condition.printLog(); + condition.clearMap(); + + org.sql2o.data.Table table = query.executeAndFetchTable(); + if(null != table){ + if(null != table.asList()){ + res = (Map) table.asList().get(0); + } + } + + // 重新放入缓存 + if(isCache() && null != res){ + sql2oCache.hsetV(CACHE_KEY_DETAIL, field, res); + } + return res; + } catch (Exception e) { + LOGGER.error(e); + } + } + return null; + } + public T fetchByPk(Serializable pk){ T res = null; diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java index 8bbb6d68e..e1fa2edfd 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java @@ -66,7 +66,7 @@ public V hgetV(String key, String field) { } @Override - public void hsetV(String key, String field, Serializable value) { + public void hsetV(String key, String field, Object value) { cache.hset(key, field, value); } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java index fe2c30de9..696d6cfbb 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java @@ -12,7 +12,7 @@ public interface Sql2oCache { void hset(String key, String field, Serializable value); - void hsetV(String key, String field, Serializable value); + void hsetV(String key, String field, Object value); void hsetlist(String key, String field, List value); From 3c347fb4b084ff5ee714326a19142506ee7ac2e2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 26 Aug 2015 09:50:08 +0800 Subject: [PATCH 105/545] fix interceptor bug --- blade-core/src/main/java/blade/BladeBase.java | 4 ++-- .../java/blade/route/RouteMatcherBuilder.java | 11 +++++++++ .../java/blade/plugin/sql2o/Condition.java | 2 +- .../main/java/blade/plugin/sql2o/Model.java | 23 +++++++++++++++---- pom.xml | 2 +- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java index e6f2be536..b3bc3247f 100644 --- a/blade-core/src/main/java/blade/BladeBase.java +++ b/blade-core/src/main/java/blade/BladeBase.java @@ -324,7 +324,7 @@ public static synchronized void all(String path, RouteHandler routeHandler){ * @param routeHandler */ public static synchronized void before(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.BEFORE); + RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); } /** @@ -333,7 +333,7 @@ public static synchronized void before(String path, RouteHandler routeHandler){ * @param routeHandler */ public static synchronized void after(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.AFTER); + RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); } /** diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index bfe96678f..27215779f 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -151,6 +151,17 @@ public static void buildHandler(String path, RouteHandler routeHandler, HttpMeth } } + public static void buildInterceptor(String path, RouteHandler routeHandler, HttpMethod httpMethod){ + if(StringKit.isNotBlank(path) && null != routeHandler){ + Class clazz = RouteHandler.class; + container.registBean(routeHandler); + Method execMethod = ReflectKit.getMethodByName(clazz, "run"); + defaultRouteMatcher.addInterceptor(clazz, execMethod, path, httpMethod, "*/*"); + } else { + throw new BladeException("an unqualified configuration"); + } + } + /** * 函数式拦截器构建 */ diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java index 79c761f65..971660bc6 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java @@ -330,7 +330,7 @@ public void where(WhereParam whereParam){ * @param name * @param value */ - public void where(String name, Object value){ + public void eq(String name, Object value){ if(StringKit.isNotBlank(name) && null != value){ this.equalsParams.put(name, value); this.logParams.add(value); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 3c78923c8..facb050ac 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -206,8 +206,21 @@ public Model param(String name, Object value){ * @param value 参数值 * @return 返回model对象 */ + @Deprecated public Model where(String name, Object value){ - condition.where(name, value); + condition.eq(name, value); + return this; + } + + /** + * 设置equals参数列表,查询,更新,删除用到 + * + * @param name 参数键 + * @param value 参数值 + * @return 返回model对象 + */ + public Model eq(String name, Object value){ + condition.eq(name, value); return this; } @@ -874,8 +887,8 @@ public Page fetchPage(Integer page, Integer pageSize){ sqlEnd += " limit :page, :pageSize"; - condition.where("page", page - 1); - condition.where("pageSize", pageSize); + condition.eq("page", page - 1); + condition.eq("pageSize", pageSize); try { // 设置query @@ -940,8 +953,8 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ sqlEnd += " limit :page, :pageSize"; - condition.where("page", page - 1); - condition.where("pageSize", pageSize); + condition.eq("page", page - 1); + condition.eq("pageSize", pageSize); try { // 设置query diff --git a/pom.xml b/pom.xml index 520885c22..9a59b8000 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.7 + 1.2.8-alpha From b1e6eb9a7b62ac5d8a01bdbbae3031e6d4896b1d Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 26 Aug 2015 11:04:42 +0800 Subject: [PATCH 106/545] add set method --- .../src/main/java/blade/plugin/sql2o/Model.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index facb050ac..f7663fbcd 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -187,6 +187,18 @@ public Model delete(String sql){ return this; } + /** + * 设置参数列表,新增,更新用到 + * + * @param name 参数键 + * @param value 参数值 + * @return 返回model对象 + */ + public Model set(String name, Object value){ + condition.param(name, value); + return this; + } + /** * 设置参数列表,新增,更新用到 * From 403c48ac6df8e1f53d3ac26fd4cef3e6fbf87799 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 26 Aug 2015 13:15:27 +0800 Subject: [PATCH 107/545] update readme --- LAST_VERSION.md | 4 ++-- README.md | 2 +- README_CN.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 908685b71..6e20ee411 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.7 +    1.2.8-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -22,7 +22,7 @@     com.bladejava     blade-sql2o -    1.2.6 +    1.2.7-beta ``` diff --git a/README.md b/README.md index b5ec16714..97bceb800 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.7 + 1.2.8-alpha ``` diff --git a/README_CN.md b/README_CN.md index eaccfea9e..a91e819e9 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,7 +33,7 @@ com.bladejava blade-core - 1.2.7 + 1.2.8-alpha ``` From c8977d5f9a41d47a28dc6c64d757ab678b02e834 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 26 Aug 2015 15:18:01 +0800 Subject: [PATCH 108/545] sql2o map to hashmap --- .../src/main/java/blade/servlet/Response.java | 4 +- .../java/blade/plugin/sql2o/Condition.java | 4 ++ .../main/java/blade/plugin/sql2o/Model.java | 46 +++++++++++++------ 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/blade-core/src/main/java/blade/servlet/Response.java b/blade-core/src/main/java/blade/servlet/Response.java index 8f3ab2034..1df1078eb 100644 --- a/blade-core/src/main/java/blade/servlet/Response.java +++ b/blade-core/src/main/java/blade/servlet/Response.java @@ -120,7 +120,7 @@ public HttpServletResponse servletResponse() { */ public void go(String path) { if (Blade.debug()) { - LOGGER.debug("Redirecting ({} {} to {}", "Found", HttpServletResponse.SC_FOUND, path); + LOGGER.debug("Redirecting (%s %s to %s", "Found", HttpServletResponse.SC_FOUND, path); } try { String ctx = BladeWebContext.servletContext().getContextPath(); @@ -138,7 +138,7 @@ public void go(String path) { */ public void redirect(String location) { if (Blade.debug()) { - LOGGER.debug("Redirecting ({} {} to {}", "Found", HttpServletResponse.SC_FOUND, location); + LOGGER.debug("Redirecting (%s %s to %s", "Found", HttpServletResponse.SC_FOUND, location); } try { response.sendRedirect(location); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java index 971660bc6..bacc585b1 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java @@ -321,6 +321,10 @@ public void where(WhereParam whereParam){ if(whereParam.params.size() > 0){ this.params.putAll(whereParam.params); } + + if(whereParam.logParams.size() > 0){ + this.logParams.addAll(whereParam.logParams); + } } } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index f7663fbcd..b2dfa0ce9 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -329,8 +329,8 @@ public Model orderBy(String orderby){ private String getCacheCountKey(){ String cacheSql = getCacheKey(null); - if(cacheSql.indexOf("from") != -1 && cacheSql.indexOf("count(") == -1){ - int start = cacheSql.indexOf("from") + 4; + if(cacheSql.indexOf("from ") != -1 && cacheSql.indexOf("count(") == -1){ + int start = cacheSql.indexOf("from ") + 5; cacheSql = "selectcount(1)from " + cacheSql.substring(start); } cacheSql = cacheSql.replaceAll("\\s", ""); @@ -471,8 +471,8 @@ public long fetchCount(){ String sqlEnd = condition.getConditionSql(); - if(sqlEnd.indexOf("from") != -1 && sqlEnd.indexOf("count(") == -1){ - int start = sqlEnd.indexOf("from") + 4; + if(sqlEnd.indexOf("from ") != -1 && sqlEnd.indexOf("count(") == -1){ + int start = sqlEnd.indexOf("from ") + 5; sqlEnd = "select count(1) from " + sqlEnd.substring(start); } @@ -515,8 +515,8 @@ private Long getPageCount(){ String sqlEnd = condition.getConditionSql(); - if(sqlEnd.indexOf("from") != -1 && sqlEnd.indexOf("count(") == -1){ - int start = sqlEnd.indexOf("from") + 4; + if(sqlEnd.indexOf("from ") != -1 && sqlEnd.indexOf("count(") == -1){ + int start = sqlEnd.indexOf("from ") + 5; sqlEnd = "select count(1) from " + sqlEnd.substring(start); } @@ -586,14 +586,13 @@ public T fetchOne(){ /** * @return 返回查询一个对象 */ - @SuppressWarnings("unchecked") - public Map fetchMap(){ + public Map fetchMap(){ if(condition.dmlType.equals(DmlType.SELECT)){ String sqlEnd = condition.getConditionSql(); - Map res = null; + Map res = null; String field = null; // 是否开启缓存查询 @@ -617,8 +616,11 @@ public Map fetchMap(){ org.sql2o.data.Table table = query.executeAndFetchTable(); if(null != table){ - if(null != table.asList()){ - res = (Map) table.asList().get(0); + + List> list = tableAsList(table); + + if(null != list && list.size() > 0){ + res = list.get(0); } } @@ -977,7 +979,7 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ LOGGER.debug("execute sql:" + query.toString()); condition.printLog(); - results = query.executeAndFetchTable().asList(); + results = tableAsList(query.executeAndFetchTable()); pageMap = new Page>(totalCount, page, pageSize); @@ -1219,13 +1221,15 @@ private Query updateCommit(Connection conn){ String updateSql = condition.sql + setSql + whereSql; + updateSql = processUpdateSql(updateSql); + if(null == conn){ conn = sql2o.open(); } Query query = conn.createQuery(updateSql); query = parseParams(query); -// query.executeUpdate(); + LOGGER.debug("execute sql:" + query.toString()); LOGGER.debug("execute parameter:" + condition.params.values() + condition.equalsParams.values()); @@ -1234,7 +1238,21 @@ private Query updateCommit(Connection conn){ return null; } - /** + private String processUpdateSql(String updateSql) { + String[] sqlArr = updateSql.split(" set"); + StringBuffer s = new StringBuffer(sqlArr[0] + " set"); + int len = sqlArr.length; + for(int i=1; i Date: Thu, 27 Aug 2015 10:42:46 +0800 Subject: [PATCH 109/545] remove sql2o md5 class and optimize the cache --- UPDATE_LOG.md | 2 + .../main/java/blade/plugin/sql2o/Model.java | 253 +++++++++++++----- .../java/blade/plugin/sql2o/WhereParam.java | 49 ++++ .../main/java/blade/plugin/sql2o/kit/MD5.java | 89 ------ 4 files changed, 237 insertions(+), 156 deletions(-) delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/kit/MD5.java diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 03b816a68..65ac6c4e0 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -6,6 +6,8 @@ 3. 优化多表联查返回数据 4. 解决java多参数传递问题 5. 多表联查返回Map类型数据 + 6. 解决blade-sql2o连接未释放BUG + 7. 支持单次查询是否缓存设置 ### v1.2.6 1. 添加多重路由配置方式 diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index b2dfa0ce9..3df6dc589 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -11,13 +11,13 @@ import org.sql2o.Query; import org.sql2o.Sql2o; +import blade.kit.EncrypKit; import blade.kit.StringKit; import blade.kit.log.Logger; import blade.plugin.sql2o.Condition.DmlType; import blade.plugin.sql2o.cache.Sql2oCache; import blade.plugin.sql2o.cache.Sql2oCacheFactory; import blade.plugin.sql2o.ds.DataSourceManager; -import blade.plugin.sql2o.kit.MD5; /** * 实体对象基类 @@ -32,12 +32,12 @@ public class Model { /** * 是否开启缓存 */ - private static boolean isOpenCache = Sql2oPlugin.INSTANCE.isOpenCache(); + private boolean isOpenCache = Sql2oPlugin.INSTANCE.isOpenCache(); /** * 缓存操作 */ - private static Sql2oCache sql2oCache = isOpenCache ? Sql2oCacheFactory.getSql2oCache() : null; + public Sql2oCache sql2oCache = isOpenCache ? Sql2oCacheFactory.getSql2oCache() : null; /** * sql2o对象,操作数据库 @@ -49,6 +49,16 @@ public class Model { */ private Class model; + /** + * 本次查询是否开启缓存 + */ + private boolean cache = false; + + /** + * 是否在单次查询的时候开启缓存,如果开启,则忽略默认不开启缓存 + */ + private boolean queryIsOpen = false; + /** * 条件对象 */ @@ -88,26 +98,57 @@ public String pk(){ /** * @return 返回表是否需要缓存 */ - public boolean isCache(){ - return isOpenCache && model.getAnnotation(Table.class).isCache(); + private boolean isCache(){ + if(this.queryIsOpen){ + return true; + } + return isOpenCache && model.getAnnotation(Table.class).isCache() && this.cache; + } + + /** + * 设置当前执行方法不缓存 + */ + public Model cache(boolean cache){ + if(cache){ + if(null == sql2oCache){ + sql2oCache = Sql2oCacheFactory.getSql2oCache(); + } + this.queryIsOpen = true; + } + this.cache = cache; + return this; + } + + /** + * 初始化操作 + * 初始化是否缓存,每次查询都走一次 + */ + private void init(){ + this.queryIsOpen = false; + this.cache = isOpenCache; } /** * @return 返回查询model对象,推荐方式 */ public Model select(){ + init(); condition.select(); return this; } - - /** + public boolean isOpenCache() { + return isOpenCache; + } + + /** * 自定义sql返回查询model对象 * * @param sql 要查询的sql语句 * @return 返回查询model对象 */ public Model select(String sql){ + init(); condition.select(sql); return this; } @@ -116,6 +157,7 @@ public Model select(String sql){ * @return 返回计算count */ public Model count(){ + init(); condition.count(); return this; } @@ -127,6 +169,7 @@ public Model count(){ * @return 返回查询model对象 */ public Model count(String sql){ + init(); condition.count(sql); return this; } @@ -344,7 +387,6 @@ private String getCacheKey(String sql){ sqlEnd = sql; } - String cacheSql = SqlBuider.create(condition, sqlEnd) .appendEquals() .appendGreater() @@ -462,7 +504,7 @@ public long fetchCount(){ if(isCache()){ String cacheSql = getCacheCountKey(); - field = MD5.create(cacheSql); + field = EncrypKit.md5(cacheSql); count = sql2oCache.hgetV(CACHE_KEY_COUNT, field); if(null != count){ return count; @@ -475,21 +517,29 @@ public long fetchCount(){ int start = sqlEnd.indexOf("from ") + 5; sqlEnd = "select count(1) from " + sqlEnd.substring(start); } - - Connection conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - - count = query.executeScalar(Long.class); - - if(isCache()){ - sql2oCache.hsetV(CACHE_KEY_COUNT, field, count); - } - return count; + Connection conn = null; + try { + conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd); + + query = parseParams(query); + + LOGGER.debug("execute sql:" + query.toString()); + condition.printLog(); + + count = query.executeScalar(Long.class); + + if(isCache()){ + sql2oCache.hsetV(CACHE_KEY_COUNT, field, count); + } + return count; + } catch (Exception e) { + LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } + } } condition.clearMap(); @@ -506,7 +556,7 @@ private Long getPageCount(){ if(isCache()){ String cacheSql = getCacheCountKey(); - field = MD5.create(cacheSql); + field = EncrypKit.md5(cacheSql); count = sql2oCache.hgetV(CACHE_KEY_COUNT, field); if(null != count){ return count; @@ -520,19 +570,28 @@ private Long getPageCount(){ sqlEnd = "select count(1) from " + sqlEnd.substring(start); } - Connection conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - - count = query.executeScalar(Long.class); - // 是否开启缓存查询 - if(isCache()){ - sql2oCache.hsetV(CACHE_KEY_COUNT, field, count); - } + Connection conn = null; + try { + conn = sql2o.open(); + Query query = conn.createQuery(sqlEnd); + + query = parseParams(query); + + LOGGER.debug("execute sql:" + query.toString()); + condition.printLog(); + + count = query.executeScalar(Long.class); + // 是否开启缓存查询 + if(isCache()){ + sql2oCache.hsetV(CACHE_KEY_COUNT, field, count); + } + } catch (Exception e) { + LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } + } return count; } return 0L; @@ -552,16 +611,16 @@ public T fetchOne(){ // 是否开启缓存查询 if(isCache()){ - field = MD5.create(getCacheKey(null)); + field = EncrypKit.md5(getCacheKey(null)); res = sql2oCache.hget(CACHE_KEY_DETAIL, field); if(null != res){ return res; } } - + Connection conn = null; try { - Connection conn = sql2o.open(); + conn = sql2o.open(); Query query = conn.createQuery(sqlEnd); query = parseParams(query); @@ -578,6 +637,10 @@ public T fetchOne(){ return res; } catch (Exception e) { LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } } } return null; @@ -597,16 +660,16 @@ public Map fetchMap(){ // 是否开启缓存查询 if(isCache()){ - field = MD5.create(getCacheKey(null)); + field = EncrypKit.md5(getCacheKey(null)); res = sql2oCache.hgetV(CACHE_KEY_DETAIL, field); if(null != res){ return res; } } - + Connection conn = null; try { - Connection conn = sql2o.open(); + conn = sql2o.open(); Query query = conn.createQuery(sqlEnd); query = parseParams(query); @@ -631,6 +694,10 @@ public Map fetchMap(){ return res; } catch (Exception e) { LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } } } return null; @@ -647,7 +714,7 @@ public T fetchByPk(Serializable pk){ // 启用缓存 if(isCache()){ - field = MD5.create(getCacheKey(null)); + field = EncrypKit.md5(getCacheKey(null)); res = sql2oCache.hget(CACHE_KEY_DETAIL, field); if(null != res){ return res; @@ -655,9 +722,9 @@ public T fetchByPk(Serializable pk){ } String sqlEnd = condition.sql + " where " + pk() + " = :pk"; - + Connection conn = null; try { - Connection conn = sql2o.open(); + conn = sql2o.open(); Query query = conn.createQuery(sqlEnd).addParameter("pk", pk); LOGGER.debug("execute sql:" + query.toString()); @@ -671,6 +738,10 @@ public T fetchByPk(Serializable pk){ } } catch (Exception e) { LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } } } return res; @@ -684,9 +755,9 @@ public M fetchColum(){ if(condition.dmlType.equals(DmlType.SELECT)){ String sqlEnd = condition.getConditionSql(); - + Connection conn = null; try { - Connection conn = sql2o.open(); + conn = sql2o.open(); Query query = conn.createQuery(sqlEnd); query = parseParams(query); @@ -697,6 +768,10 @@ public M fetchColum(){ return (M) query.executeScalar(); } catch (Exception e) { LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } } } return null; @@ -714,7 +789,7 @@ public List fetchList(){ // 开启缓存 if(isCache()){ - field = MD5.create(getCacheKey(null)); + field = EncrypKit.md5(getCacheKey(null)); result = (List) sql2oCache.hgetlist(CACHE_KEY_LIST, field); if(null != result){ return result; @@ -726,9 +801,9 @@ public List fetchList(){ if(null != condition.orderby){ sqlEnd += " order by " + condition.orderby; } - + Connection conn = null; try { - Connection conn = sql2o.open(); + conn = sql2o.open(); Query query = conn.createQuery(sqlEnd); query = parseParams(query); @@ -742,10 +817,13 @@ public List fetchList(){ if(isCache() && null != result){ sql2oCache.hsetlist(CACHE_KEY_LIST, field, result); } - return result; } catch (Exception e) { LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } } } return null; @@ -763,7 +841,7 @@ public List executeAndFetch(Class clazz){ // 开启缓存 if(isCache()){ - field = MD5.create(getCacheKey(null)); + field = EncrypKit.md5(getCacheKey(null)); result = sql2oCache.hgetlists(CACHE_KEY_LIST, field); if(null != result){ return result; @@ -775,9 +853,9 @@ public List executeAndFetch(Class clazz){ if(null != condition.orderby){ sqlEnd += " order by " + condition.orderby; } - + Connection conn = null; try { - Connection conn = sql2o.open(); + conn = sql2o.open(); Query query = conn.createQuery(sqlEnd); query = parseParams(query); @@ -791,10 +869,13 @@ public List executeAndFetch(Class clazz){ if(isCache() && null != result){ sql2oCache.hsetlists(CACHE_KEY_LIST, field, result); } - return result; } catch (Exception e) { LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } } } return null; @@ -812,7 +893,7 @@ public List> fetchListMap(){ // 开启缓存 if(isCache()){ - field = MD5.create(getCacheKey(null)); + field = EncrypKit.md5(getCacheKey(null)); result = sql2oCache.hgetlistmap(CACHE_KEY_LIST, field); if(null != result){ return result; @@ -824,9 +905,9 @@ public List> fetchListMap(){ if(null != condition.orderby){ sqlEnd += " order by " + condition.orderby; } - + Connection conn = null; try { - Connection conn = sql2o.open(); + conn = sql2o.open(); Query query = conn.createQuery(sqlEnd); query = parseParams(query); @@ -844,6 +925,10 @@ public List> fetchListMap(){ return result; } catch (Exception e) { LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } } } return null; @@ -880,7 +965,7 @@ public Page fetchPage(Integer page, Integer pageSize){ if(isCache()){ String cacheSql = getCacheKey(null) + "limit"+ (page - 1) +"," + pageSize; cacheSql = cacheSql.replaceAll("\\s", ""); - field = MD5.create(cacheSql); + field = EncrypKit.md5(cacheSql); results = sql2oCache.hgetlist(CACHE_KEY_LIST, field); @@ -904,9 +989,10 @@ public Page fetchPage(Integer page, Integer pageSize){ condition.eq("page", page - 1); condition.eq("pageSize", pageSize); + Connection conn = null; try { // 设置query - Connection conn = sql2o.open(); + conn = sql2o.open(); Query query = conn.createQuery(sqlEnd); query = parseParams(query); @@ -925,6 +1011,10 @@ public Page fetchPage(Integer page, Integer pageSize){ return pageModel; } catch (Exception e) { LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } } } @@ -957,7 +1047,23 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ // 查询总记录数 long totalCount = getPageCount(); + String field = null; List> results = null; + // 开启缓存 + if(isCache()){ + String cacheSql = getCacheKey(null) + "limit"+ (page - 1) +"," + pageSize; + cacheSql = cacheSql.replaceAll("\\s", ""); + field = EncrypKit.md5(cacheSql); + + results = sql2oCache.hgetlistmap(CACHE_KEY_LIST, field); + + if(null != results && results.size() > 0){ + pageMap = new Page>(totalCount, page, pageSize); + pageMap.setResults(results); + return pageMap; + } + + } String sqlEnd = condition.getConditionSql(); @@ -969,10 +1075,10 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ condition.eq("page", page - 1); condition.eq("pageSize", pageSize); - + Connection conn = null; try { // 设置query - Connection conn = sql2o.open(); + conn = sql2o.open(); Query query = conn.createQuery(sqlEnd); query = parseParams(query); @@ -984,13 +1090,19 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ pageMap = new Page>(totalCount, page, pageSize); if(null != results && results.size() > 0){ + if(isCache()){ + sql2oCache.hsetlistmap(CACHE_KEY_LIST, field, results); + } pageMap.setResults(results); } } catch (Exception e) { LOGGER.error(e); + } finally{ + if(null != conn){ + conn.close(); + } } - condition.clearMap(); return pageMap; @@ -1015,7 +1127,7 @@ public Integer executeAndCommit() { * * @return 返回主键 */ - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "resource" }) public V executeAndCommit(Class returnType) { V key = null; Query query = null; @@ -1080,7 +1192,11 @@ public V executeAndCommit(Class returnType) { condition.clearMap(); return key; } catch (Exception e) { - e.printStackTrace(); + LOGGER.error(e); + } finally{ + if(null != query){ + query.close(); + } } return null; } @@ -1238,6 +1354,9 @@ private Query updateCommit(Connection conn){ return null; } + /** + * 处理更新语句 + */ private String processUpdateSql(String updateSql) { String[] sqlArr = updateSql.split(" set"); StringBuffer s = new StringBuffer(sqlArr[0] + " set"); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java index 1c1f777d4..15a6431c0 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java @@ -61,6 +61,55 @@ public WhereParam eq(String field, Object value){ return this; } + public Object eq(String field){ + if(StringKit.isNotBlank(field)){ + return this.equalsParams.get(field); + } + return null; + } + + public String like(String field){ + if(StringKit.isNotBlank(field)){ + return this.likeParams.get(field); + } + return null; + } + + public Object less(String field){ + if(StringKit.isNotBlank(field)){ + return this.lessParams.get(field); + } + return null; + } + + public Object lessThan(String field){ + if(StringKit.isNotBlank(field)){ + return this.lessThanParams.get(field); + } + return null; + } + + public Object greater(String field){ + if(StringKit.isNotBlank(field)){ + return this.greaterParams.get(field); + } + return null; + } + + public Object greaterThan(String field){ + if(StringKit.isNotBlank(field)){ + return this.greaterThanParams.get(field); + } + return null; + } + + public Object[] in(String field){ + if(StringKit.isNotBlank(field)){ + return this.inParams.get(field); + } + return null; + } + public WhereParam like(String field, String value){ if(StringKit.isNotBlank(field) && StringKit.isNotBlank(value) && value.indexOf("%null")==-1 && value.indexOf("null%")==-1 && !value.equals("%%")){ diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/kit/MD5.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/kit/MD5.java deleted file mode 100644 index 8bd3833c5..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/kit/MD5.java +++ /dev/null @@ -1,89 +0,0 @@ -package blade.plugin.sql2o.kit; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * MD5加密 - * - * @author biezhi - * @since 1.0 - */ -public class MD5 { - - /** 全局数组 **/ - private final static String[] strDigits = { "0", "1", "2", "3", "4", "5", - "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" }; - - /** - * 返回形式为数字跟字符串 - * - * @param bByte - * @return - */ - private static String byteAsArrayString(byte bByte) { - int iRet = bByte; - if (iRet < 0) { - iRet += 256; - } - int iD1 = iRet / 16; - int iD2 = iRet % 16; - return strDigits[iD1] + strDigits[iD2]; - } - - /** - * 转换字节数组为16进制字串 - * - * @param bByte - * @return - */ - private static String byteAsString(byte[] bByte) { - StringBuffer sBuffer = new StringBuffer(); - for (int i = 0; i < bByte.length; i++) { - sBuffer.append(byteAsArrayString(bByte[i])); - } - return sBuffer.toString(); - } - - /** - * MD5加密 - * - * @param str - * 待加密的字符串 - * @return - */ - public static String create(String str) { - String result = null; - try { - result = new String(str); - MessageDigest md = MessageDigest.getInstance("MD5"); - result = byteAsString(md.digest(str.getBytes())); - } catch (NoSuchAlgorithmException ex) { - ex.printStackTrace(); - } - return result; - } - - /** - * MD5加密 - * - * @param str 待加密的字符串 - * @param lowerCase 大小写 - * @return - */ - public static String create(String str, boolean lowerCase) { - String result = null; - try { - result = new String(str); - MessageDigest md = MessageDigest.getInstance("MD5"); - result = byteAsString(md.digest(str.getBytes())); - if (lowerCase) { - result = result.toLowerCase(); - } - } catch (NoSuchAlgorithmException ex) { - ex.printStackTrace(); - } - return result; - } - -} \ No newline at end of file From 4d7eb61c1716f98505cc736fc7a09c94f43bcd66 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 27 Aug 2015 15:25:50 +0800 Subject: [PATCH 110/545] optimize the map traverse --- blade-core/src/main/java/blade/ioc/DefaultContainer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/blade-core/src/main/java/blade/ioc/DefaultContainer.java b/blade-core/src/main/java/blade/ioc/DefaultContainer.java index 5ce7d204a..41ae57a14 100644 --- a/blade-core/src/main/java/blade/ioc/DefaultContainer.java +++ b/blade-core/src/main/java/blade/ioc/DefaultContainer.java @@ -86,9 +86,9 @@ public T getBean(String name, Scope scope) { @Override public T getBean(Class type, Scope scope) { - Iterator it = BEAN_CONTAINER.values().iterator(); - while (it.hasNext()) { - Object obj = it.next(); + Set keys = BEAN_CONTAINER.keySet(); + for(String key : keys){ + Object obj = BEAN_CONTAINER.get(key); if (type.isAssignableFrom(obj.getClass())) { if(null != scope && scope == Scope.PROTOTYPE){ try { From 840da40d42553fa50dd524b7f1594e1d6c6fa81d Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 27 Aug 2015 15:36:23 +0800 Subject: [PATCH 111/545] simplified bladebase --- blade-core/src/main/java/blade/Blade.java | 506 +++++++++++++++- blade-core/src/main/java/blade/BladeBase.java | 542 ------------------ .../src/main/java/blade/BladeFilter.java | 8 +- .../src/main/java/blade/IocApplication.java | 2 +- .../main/java/blade/route/RouteHandler.java | 10 - .../java/blade/route/RouteMatcherBuilder.java | 8 +- 6 files changed, 513 insertions(+), 563 deletions(-) delete mode 100644 blade-core/src/main/java/blade/BladeBase.java delete mode 100644 blade-core/src/main/java/blade/route/RouteHandler.java diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index fd66f1fb9..3f4e5f2d1 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -15,17 +15,519 @@ */ package blade; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import blade.ioc.Container; +import blade.ioc.DefaultContainer; +import blade.kit.IOKit; +import blade.kit.PropertyKit; +import blade.kit.json.JSONKit; +import blade.render.Render; +import blade.render.RenderFactory; +import blade.route.HttpMethod; +import blade.route.Route; +import blade.route.RouteMatcherBuilder; /** * Blade Core Class * * @author biezhi * @since 1.0 - * */ -public final class Blade extends BladeBase{ +public final class Blade { + + public static final String VERSION = "1.2.8-beta"; + /** + * 框架是否已经初始化 + */ + protected static boolean IS_INIT = false; + + /** + * blade全局初始化对象,在web.xml中配置,必须 + */ + protected static Bootstrap bootstrap; + + /** + * 全局配置对象 + */ + protected final static BladeConfig BLADE_CONFIG = new BladeConfig(); + /** + * IOC容器,存储路由到ioc中 + */ + private final static Container container = DefaultContainer.single(); + private Blade() { } + static synchronized void init() { + Blade.IS_INIT = true; + } + + /** + *
+	 * 手动注册一个对象到ioc容器中
+	 * 
+ * + * @param object 要注册的object + */ + public static synchronized void regObject(Object object){ + container.registBean(object); + } + + /** + *
+	 * Properties配置文件方式
+	 * 文件的路径基于classpath
+	 * 
+ * + * @param confName 配置文件路径 + */ + public static synchronized void config(String confName){ + Map configMap = PropertyKit.getPropertyMap(confName); + configuration(configMap); + } + + /** + *
+	 * JSON文件的配置
+	 * 文件的路径基于classpath
+	 * 
+ * + * @param jsonPath json文件路径 + */ + public static synchronized void configJsonPath(String jsonPath){ + InputStream inputStream = Blade.class.getResourceAsStream(jsonPath); + if(null != inputStream){ + try { + String json = IOKit.toString(inputStream); + Map configMap = JSONKit.toMap(json); + configuration(configMap); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + *
+	 * JSON格式的配置
+	 * 
+ * + * @param json json配置 + */ + public static synchronized void configJson(String json){ + Map configMap = JSONKit.toMap(json); + configuration(configMap); + } + + /** + *
+	 * 根据配置map保存配置
+	 * 
+ * + * @param configMap 存放配置的map + */ + private static void configuration(Map configMap){ + new BladeConfigurator(Blade.BLADE_CONFIG, configMap).run(); + } + + /** + * 设置路由包,如:com.baldejava.route + * 可传入多个包,所有的路由类都在该包下 + * + * @param packages 路由包路径 + */ + public static synchronized void routes(String...packages){ + if(null != packages && packages.length >0){ + BLADE_CONFIG.setRoutePackages(packages); + } + } + + /** + * 设置顶层包,框架自动寻找路由包和拦截器包,如:com.bladejava + * 如上规则,会超找com.bladejava.route、com.bladejava.interceptor下的路由和拦截器 + * + * @param basePackage 默认包路径 + */ + public static synchronized void defaultRoute(String basePackage){ + if(null != basePackage){ + BLADE_CONFIG.setBasePackage(basePackage); + } + } + + /** + * 设置拦截器所在的包路径,如:com.bladejava.interceptor + * + * @param packageName 拦截器所在的包 + */ + public static synchronized void interceptor(String packageName) { + if(null != packageName && packageName.length() >0){ + BLADE_CONFIG.setInterceptorPackage(packageName); + } + } + + /** + * 设置依赖注入包,如:com.bladejava.service + * + * @param packages 所有需要做注入的包,可传入多个 + */ + public static synchronized void ioc(String...packages){ + if(null != packages && packages.length >0){ + BLADE_CONFIG.setIocPackages(packages); + } + } + + /** + * 设置渲染引擎,默认是JSP引擎 + * + * @param render 渲染引擎对象 + */ + public static synchronized void viewEngin(Render render) { + RenderFactory.init(render); + } + + /** + * 设置默认视图前缀,默认为WEB_ROOT/WEB-INF目录 + * + * @param prefix 视图路径,如:/WEB-INF/views + */ + public static synchronized void viewPrefix(final String prefix) { + if(null != prefix && prefix.startsWith("/")){ + BLADE_CONFIG.setViewPrefix(prefix); + } + } + + /** + * 设置视图默认后缀名,默认为.jsp + * + * @param viewExt 视图后缀,如:.html .vm + */ + public static synchronized void viewSuffix(final String suffix) { + if(null != suffix && suffix.startsWith(".")){ + BLADE_CONFIG.setViewSuffix(suffix); + } + } + + /** + * 同事设置视图所在目录和视图后缀名 + * + * @param viewPath 视图路径,如:/WEB-INF/views + * @param viewExt 视图后缀,如:.html .vm + */ + public static synchronized void view(final String viewPath, final String viewExt) { + viewPrefix(viewPath); + viewSuffix(viewExt); + } + + /** + * 设置框架静态文件所在文件夹 + * + * @param folders + */ + public static synchronized void staticFolder(final String ... folders) { + BLADE_CONFIG.setStaticFolders(folders); + } + + /** + * 动态设置全局初始化类 + * + * @param bladeApplication 全局初始化bladeApplication + */ + public static synchronized void app(Bootstrap bootstrap){ + Blade.bootstrap = bootstrap; + } + + /** + * 设置404视图页面 + * + * @param view404 404视图页面 + */ + public static synchronized void view404(final String view404){ + BLADE_CONFIG.setView404(view404); + } + + /** + * 设置500视图页面 + * + * @param view500 500视图页面 + */ + public static synchronized void view500(final String view500){ + BLADE_CONFIG.setView500(view500); + } + + /** + * 设置web根目录 + * + * @param webRoot web根目录物理路径 + */ + public static synchronized void webRoot(final String webRoot){ + BLADE_CONFIG.setWebRoot(webRoot); + } + + /** + * 设置系统是否以debug方式运行 + * @param isdebug true:是,默认true;false:否 + */ + public static synchronized void debug(boolean isdebug){ + BLADE_CONFIG.setDebug(isdebug); + } + + /** + * 注册一个函数式的路由
+ *

+ * 方法上指定请求类型,如:post:signin + *

+ * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + */ + public static synchronized void regRoute(String path, Class clazz, String methodName){ + RouteMatcherBuilder.buildFunctional(path, clazz, methodName, null); + } + + /** + * 注册一个函数式的路由 + * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + * @param httpMethod 请求类型,GET/POST + */ + public static synchronized void regRoute(String path, Class clazz, String methodName, HttpMethod httpMethod){ + RouteMatcherBuilder.buildFunctional(path, clazz, methodName, httpMethod); + } + + /** + * get请求 + * @param path + * @param routeHandler + */ + public static synchronized void get(String path, Route routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.GET); + } + + /** + * post请求 + * @param path + * @param routeHandler + */ + public static synchronized void post(String path, Route routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.POST); + } + + /** + * delete请求 + * @param path + * @param routeHandler + */ + public static synchronized void delete(String path, Route routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.DELETE); + } + + /** + * put请求 + * @param path + * @param routeHandler + */ + public static synchronized void put(String path, Route routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.PUT); + } + + /** + * patch请求 + * @param path + * @param routeHandler + */ + public static synchronized void patch(String path, Route routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.PATCH); + } + + /** + * head请求 + * @param path + * @param routeHandler + */ + public static synchronized void head(String path, Route routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.HEAD); + } + + /** + * trace请求 + * @param path + * @param routeHandler + */ + public static synchronized void trace(String path, Route routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.TRACE); + } + + /** + * options请求 + * @param path + * @param routeHandler + */ + public static synchronized void options(String path, Route routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.OPTIONS); + } + + /** + * connect请求 + * @param path + * @param routeHandler + */ + public static synchronized void connect(String path, Route routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.CONNECT); + } + + /** + * 任意请求 + * @param path + * @param routeHandler + */ + public static synchronized void all(String path, Route routeHandler){ + RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.ALL); + } + + /** + * 拦截器before请求 + * @param path + * @param routeHandler + */ + public static synchronized void before(String path, Route routeHandler){ + RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); + } + + /** + * 拦截器after请求 + * @param path + * @param routeHandler + */ + public static synchronized void after(String path, Route routeHandler){ + RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); + } + + /** + * 注册一个函数式的拦截器
+ *

+ * 方法上指定请求类型,如:post:signin + *

+ * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + */ + public static synchronized void regInterceptor(String path, Class clazz, String methodName){ + RouteMatcherBuilder.buildInterceptor(path, clazz, methodName, null); + } + + /** + * 注册一个函数式的拦截器
+ *

+ * 方法上指定请求类型,如:post:signin + *

+ * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + * @param acceptType acceptType + */ + public static synchronized void regInterceptor(String path, Class clazz, String methodName, String acceptType){ + RouteMatcherBuilder.buildInterceptor(path, clazz, methodName, acceptType); + } + + + public static BladeConfig config(){ + return BLADE_CONFIG; + } + + /** + * @return 返回Blade要扫描的基础包 + */ + public static String basePackage(){ + return BLADE_CONFIG.getBasePackage(); + } + + /** + * @return 返回路由包数组 + */ + public static String[] routes(){ + return BLADE_CONFIG.getRoutePackages(); + } + + /** + * @return 返回IOC所有包 + */ + public static String[] iocs(){ + return BLADE_CONFIG.getIocPackages(); + } + + /** + * @return 返回拦截器包数组,只有一个元素 这里统一用String[] + */ + public static String interceptor(){ + return BLADE_CONFIG.getInterceptorPackage(); + } + + + /** + * @return 返回视图存放路径 + */ + public static String viewPrefix(){ + return BLADE_CONFIG.getViewPrefix(); + } + + /** + * @return 返回系统默认字符编码 + */ + public static String encoding(){ + return BLADE_CONFIG.getEncoding(); + } + + /** + * @return 返回balde启动端口 + */ + public static String viewSuffix(){ + return BLADE_CONFIG.getViewSuffix(); + } + + /** + * @return 返回404视图 + */ + public static String view404(){ + return BLADE_CONFIG.getView404(); + } + + /** + * @return 返回500视图 + */ + public static String view500(){ + return BLADE_CONFIG.getView500(); + } + + /** + * @return 返回webroot路径 + */ + public static String webRoot(){ + return BLADE_CONFIG.getWebRoot(); + } + + /** + * @return 返回系统是否以debug方式运行 + */ + public static boolean debug(){ + return BLADE_CONFIG.isDebug(); + } + + /** + * @return 返回静态资源目录 + */ + public static String[] staticFolder(){ + return BLADE_CONFIG.getStaticFolders(); + } + + /** + * @return 返回Bootstrap对象 + */ + public static Bootstrap bootstrap(){ + return bootstrap; + } } diff --git a/blade-core/src/main/java/blade/BladeBase.java b/blade-core/src/main/java/blade/BladeBase.java deleted file mode 100644 index b3bc3247f..000000000 --- a/blade-core/src/main/java/blade/BladeBase.java +++ /dev/null @@ -1,542 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; - -import blade.ioc.Container; -import blade.ioc.DefaultContainer; -import blade.kit.IOKit; -import blade.kit.PropertyKit; -import blade.kit.json.JSONKit; -import blade.render.Render; -import blade.render.RenderFactory; -import blade.route.HttpMethod; -import blade.route.RouteHandler; -import blade.route.RouteMatcherBuilder; - -/** - * Blade的基础类 - * - * @author biezhi - * @since 1.0 - */ -abstract class BladeBase { - - /** - * 框架是否已经初始化 - */ - protected static boolean IS_INIT = false; - - /** - * blade全局初始化对象,在web.xml中配置,必须 - */ - protected static Bootstrap bootstrap; - - /** - * 全局配置对象 - */ - private final static BladeConfig BLADE_CONFIG = new BladeConfig(); - - /** - * IOC容器,存储路由到ioc中 - */ - private final static Container container = DefaultContainer.single(); - - protected BladeBase() { - } - - /*--------------------SET CONST:START-------------------------*/ - - /** - * 设置路由包,如:com.baldejava.route - * 可传入多个包,所有的路由类都在该包下 - * - * @param packages 路由包路径 - */ - public static synchronized void routes(String...packages){ - if(null != packages && packages.length >0){ - BLADE_CONFIG.setRoutePackages(packages); - } - } - - /** - * 设置顶层包,框架自动寻找路由包和拦截器包,如:com.bladejava - * 如上规则,会超找com.bladejava.route、com.bladejava.interceptor下的路由和拦截器 - * - * @param basePackage 默认包路径 - */ - public static synchronized void defaultRoute(String basePackage){ - if(null != basePackage){ - BLADE_CONFIG.setBasePackage(basePackage); - } - } - - /** - * 设置拦截器所在的包路径,如:com.bladejava.interceptor - * - * @param packageName 拦截器所在的包 - */ - public static synchronized void interceptor(String packageName) { - if(null != packageName && packageName.length() >0){ - BLADE_CONFIG.setInterceptorPackage(packageName); - } - } - - /** - * 设置依赖注入包,如:com.bladejava.service - * - * @param packages 所有需要做注入的包,可传入多个 - */ - public static synchronized void ioc(String...packages){ - if(null != packages && packages.length >0){ - BLADE_CONFIG.setIocPackages(packages); - } - } - - /** - * 设置渲染引擎,默认是JSP引擎 - * - * @param render 渲染引擎对象 - */ - public static synchronized void viewEngin(Render render) { - RenderFactory.init(render); - } - - /** - * 设置默认视图前缀,默认为WEB_ROOT/WEB-INF目录 - * - * @param prefix 视图路径,如:/WEB-INF/views - */ - public static synchronized void viewPrefix(final String prefix) { - if(null != prefix && prefix.startsWith("/")){ - BLADE_CONFIG.setViewPrefix(prefix); - } - } - - /** - * 设置视图默认后缀名,默认为.jsp - * - * @param viewExt 视图后缀,如:.html .vm - */ - public static synchronized void viewSuffix(final String suffix) { - if(null != suffix && suffix.startsWith(".")){ - BLADE_CONFIG.setViewSuffix(suffix); - } - } - - /** - * 同事设置视图所在目录和视图后缀名 - * - * @param viewPath 视图路径,如:/WEB-INF/views - * @param viewExt 视图后缀,如:.html .vm - */ - public static synchronized void view(final String viewPath, final String viewExt) { - viewPrefix(viewPath); - viewSuffix(viewExt); - } - - /** - * 设置框架静态文件所在文件夹 - * - * @param folders - */ - public static synchronized void staticFolder(final String ... folders) { - BLADE_CONFIG.setStaticFolders(folders); - } - - /** - * 动态设置全局初始化类 - * - * @param bladeApplication 全局初始化bladeApplication - */ - public static synchronized void app(Bootstrap bootstrap){ - BladeBase.bootstrap = bootstrap; - } - - /** - * 设置404视图页面 - * - * @param view404 404视图页面 - */ - public static synchronized void view404(final String view404){ - BLADE_CONFIG.setView404(view404); - } - - /** - * 设置500视图页面 - * - * @param view500 500视图页面 - */ - public static synchronized void view500(final String view500){ - BLADE_CONFIG.setView500(view500); - } - - /** - * 设置web根目录 - * - * @param webRoot web根目录物理路径 - */ - public static synchronized void webRoot(final String webRoot){ - BLADE_CONFIG.setWebRoot(webRoot); - } - - /** - * 设置系统是否以debug方式运行 - * @param isdebug true:是,默认true;false:否 - */ - public static synchronized void debug(boolean isdebug){ - BLADE_CONFIG.setDebug(isdebug); - } - - /** - * 注册一个函数式的路由
- *

- * 方法上指定请求类型,如:post:signin - *

- * @param path 路由url - * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 - */ - public static synchronized void regRoute(String path, Class clazz, String methodName){ - RouteMatcherBuilder.buildFunctional(path, clazz, methodName, null); - } - - /** - * 注册一个函数式的路由 - * @param path 路由url - * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 - * @param httpMethod 请求类型,GET/POST - */ - public static synchronized void regRoute(String path, Class clazz, String methodName, HttpMethod httpMethod){ - RouteMatcherBuilder.buildFunctional(path, clazz, methodName, httpMethod); - } - - /** - * get请求 - * @param path - * @param routeHandler - */ - public static synchronized void get(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.GET); - } - - /** - * post请求 - * @param path - * @param routeHandler - */ - public static synchronized void post(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.POST); - } - - /** - * delete请求 - * @param path - * @param routeHandler - */ - public static synchronized void delete(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.DELETE); - } - - /** - * put请求 - * @param path - * @param routeHandler - */ - public static synchronized void put(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.PUT); - } - - /** - * patch请求 - * @param path - * @param routeHandler - */ - public static synchronized void patch(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.PATCH); - } - - /** - * head请求 - * @param path - * @param routeHandler - */ - public static synchronized void head(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.HEAD); - } - - /** - * trace请求 - * @param path - * @param routeHandler - */ - public static synchronized void trace(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.TRACE); - } - - /** - * options请求 - * @param path - * @param routeHandler - */ - public static synchronized void options(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.OPTIONS); - } - - /** - * connect请求 - * @param path - * @param routeHandler - */ - public static synchronized void connect(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.CONNECT); - } - - /** - * 任意请求 - * @param path - * @param routeHandler - */ - public static synchronized void all(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.ALL); - } - - /** - * 拦截器before请求 - * @param path - * @param routeHandler - */ - public static synchronized void before(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); - } - - /** - * 拦截器after请求 - * @param path - * @param routeHandler - */ - public static synchronized void after(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); - } - - /** - * 注册一个函数式的拦截器
- *

- * 方法上指定请求类型,如:post:signin - *

- * @param path 路由url - * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 - */ - public static synchronized void regInterceptor(String path, Class clazz, String methodName){ - RouteMatcherBuilder.buildInterceptor(path, clazz, methodName, null); - } - - /** - * 注册一个函数式的拦截器
- *

- * 方法上指定请求类型,如:post:signin - *

- * @param path 路由url - * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 - * @param acceptType acceptType - */ - public static synchronized void regInterceptor(String path, Class clazz, String methodName, String acceptType){ - RouteMatcherBuilder.buildInterceptor(path, clazz, methodName, acceptType); - } - - /**--------------------SET CONST:END-------------------------*/ - - - - /**--------------------GET CONST:START-------------------------*/ - - public static BladeConfig config(){ - return BLADE_CONFIG; - } - - /** - * @return 返回Blade要扫描的基础包 - */ - public static String basePackage(){ - return BLADE_CONFIG.getBasePackage(); - } - - /** - * @return 返回路由包数组 - */ - public static String[] routes(){ - return BLADE_CONFIG.getRoutePackages(); - } - - /** - * @return 返回IOC所有包 - */ - public static String[] iocs(){ - return BLADE_CONFIG.getIocPackages(); - } - - /** - * @return 返回拦截器包数组,只有一个元素 这里统一用String[] - */ - public static String interceptor(){ - return BLADE_CONFIG.getInterceptorPackage(); - } - - - /** - * @return 返回视图存放路径 - */ - public static String viewPrefix(){ - return BLADE_CONFIG.getViewPrefix(); - } - - /** - * @return 返回系统默认字符编码 - */ - public static String encoding(){ - return BLADE_CONFIG.getEncoding(); - } - - /** - * @return 返回balde启动端口 - */ - public static String viewSuffix(){ - return BLADE_CONFIG.getViewSuffix(); - } - - /** - * @return 返回404视图 - */ - public static String view404(){ - return BLADE_CONFIG.getView404(); - } - - /** - * @return 返回500视图 - */ - public static String view500(){ - return BLADE_CONFIG.getView500(); - } - - /** - * @return 返回webroot路径 - */ - public static String webRoot(){ - return BLADE_CONFIG.getWebRoot(); - } - - /** - * @return 返回系统是否以debug方式运行 - */ - public static boolean debug(){ - return BLADE_CONFIG.isDebug(); - } - - /** - * @return 返回静态资源目录 - */ - public static String[] staticFolder(){ - return BLADE_CONFIG.getStaticFolders(); - } - - /** - * @return 返回Bootstrap对象 - */ - public static Bootstrap bootstrap(){ - return bootstrap; - } - - /**--------------------GET CONST:END-------------------------*/ - - /** - *
-	 * 手动注册一个对象到ioc容器中
-	 * 
- * - * @param object 要注册的object - */ - public static synchronized void regObject(Object object){ - container.registBean(object); - } - - /** - *
-	 * Properties配置文件方式
-	 * 文件的路径基于classpath
-	 * 
- * - * @param confName 配置文件路径 - */ - public static synchronized void config(String confName){ - Map configMap = PropertyKit.getPropertyMap(confName); - configuration(configMap); - } - - /** - *
-	 * JSON文件的配置
-	 * 文件的路径基于classpath
-	 * 
- * - * @param jsonPath json文件路径 - */ - public static synchronized void configJsonPath(String jsonPath){ - InputStream inputStream = BladeBase.class.getResourceAsStream(jsonPath); - if(null != inputStream){ - try { - String json = IOKit.toString(inputStream); - Map configMap = JSONKit.toMap(json); - configuration(configMap); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - /** - *
-	 * JSON格式的配置
-	 * 
- * - * @param json json配置 - */ - public static synchronized void configJson(String json){ - Map configMap = JSONKit.toMap(json); - configuration(configMap); - } - - /** - *
-	 * 根据配置map保存配置
-	 * 
- * - * @param configMap 存放配置的map - */ - private static void configuration(Map configMap){ - new BladeConfigurator(BladeBase.BLADE_CONFIG, configMap).run(); - } - - static synchronized void init() { - BladeBase.IS_INIT = true; - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java index 146319deb..eb0540574 100644 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ b/blade-core/src/main/java/blade/BladeFilter.java @@ -52,7 +52,7 @@ public void init(FilterConfig filterConfig) throws ServletException { try { if(!Blade.IS_INIT){ - BladeBase.webRoot(filterConfig.getServletContext().getRealPath("/")); + Blade.webRoot(filterConfig.getServletContext().getRealPath("/")); BladeWebContext.servletContext(filterConfig.getServletContext()); @@ -67,7 +67,7 @@ public void init(FilterConfig filterConfig) throws ServletException { bootstrap.contextInitialized(BladeWebContext.servletContext()); - BladeBase.init(); + Blade.init(); LOGGER.info("blade init complete!"); } @@ -108,8 +108,8 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; - httpRequest.setCharacterEncoding(BladeBase.encoding()); - httpResponse.setCharacterEncoding(BladeBase.encoding()); + httpRequest.setCharacterEncoding(Blade.encoding()); + httpResponse.setCharacterEncoding(Blade.encoding()); /** * 是否被RequestHandler执行 diff --git a/blade-core/src/main/java/blade/IocApplication.java b/blade-core/src/main/java/blade/IocApplication.java index 47bb6f5ea..73f2edc69 100644 --- a/blade-core/src/main/java/blade/IocApplication.java +++ b/blade-core/src/main/java/blade/IocApplication.java @@ -71,7 +71,7 @@ public static void init(){ * */ private static void initIOC() { - String[] iocPackages = BladeBase.iocs(); + String[] iocPackages = Blade.iocs(); if(null != iocPackages && iocPackages.length > 0){ for(String packageName : iocPackages){ registerBean(packageName); diff --git a/blade-core/src/main/java/blade/route/RouteHandler.java b/blade-core/src/main/java/blade/route/RouteHandler.java deleted file mode 100644 index b06081e2b..000000000 --- a/blade-core/src/main/java/blade/route/RouteHandler.java +++ /dev/null @@ -1,10 +0,0 @@ -package blade.route; - -import blade.servlet.Request; -import blade.servlet.Response; - -public interface RouteHandler { - - public String run(Request request, Response response); - -} diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index 27215779f..92c561c48 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -140,9 +140,9 @@ public static void buildFunctional(String path, Class clazz, String methodNam /** * Handler路由构建 */ - public static void buildHandler(String path, RouteHandler routeHandler, HttpMethod httpMethod){ + public static void buildHandler(String path, blade.route.Route routeHandler, HttpMethod httpMethod){ if(StringKit.isNotBlank(path) && null != routeHandler){ - Class clazz = RouteHandler.class; + Class clazz = blade.route.Route.class; container.registBean(routeHandler); Method execMethod = ReflectKit.getMethodByName(clazz, "run"); defaultRouteMatcher.addRoute(clazz, execMethod, path, httpMethod, "*/*"); @@ -151,9 +151,9 @@ public static void buildHandler(String path, RouteHandler routeHandler, HttpMeth } } - public static void buildInterceptor(String path, RouteHandler routeHandler, HttpMethod httpMethod){ + public static void buildInterceptor(String path, blade.route.Route routeHandler, HttpMethod httpMethod){ if(StringKit.isNotBlank(path) && null != routeHandler){ - Class clazz = RouteHandler.class; + Class clazz = blade.route.Route.class; container.registBean(routeHandler); Method execMethod = ReflectKit.getMethodByName(clazz, "run"); defaultRouteMatcher.addInterceptor(clazz, execMethod, path, httpMethod, "*/*"); From e3cecc326d8ac6c203cbf9fdde478559ea794a11 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 27 Aug 2015 16:20:30 +0800 Subject: [PATCH 112/545] optimize the code --- README.md | 4 +- README_CN.md | 4 +- UPDATE_LOG.md | 3 +- blade-core/src/main/java/blade/Blade.java | 29 +++--- .../src/main/java/blade/RequestHandler.java | 99 ++++++++++++------- .../java/blade/route/DefaultRouteMatcher.java | 48 +++++++++ .../main/java/blade/route/RouteMatcher.java | 6 ++ .../java/blade/route/RouteMatcherBuilder.java | 23 +++-- .../src/main/java/blade/servlet/Request.java | 12 +-- .../java/blade/wrapper/RequestWrapper.java | 8 ++ pom.xml | 2 +- 11 files changed, 163 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index 97bceb800..1f507eb9a 100644 --- a/README.md +++ b/README.md @@ -68,9 +68,9 @@ public class App extends Bootstrap{ Blade.regRoute("/hello", SayHi.class, "hello"); // anonymous router,java8 so simple - Blade.get("/get", new RouteHandler() { + Blade.get("/get", new Router() { @Override - public String run(Request request, Response response) { + public String handler(Request request, Response response) { System.out.println("come get!!"); System.out.println(request.query("name")); return "get"; diff --git a/README_CN.md b/README_CN.md index a91e819e9..8516a6896 100644 --- a/README_CN.md +++ b/README_CN.md @@ -66,9 +66,9 @@ public class App extends Bootstrap{ Blade.regRoute("/hello", SayHi.class, "hello"); // 匿名路由,java8方式更简化 - Blade.get("/get", new RouteHandler() { + Blade.get("/get", new Router() { @Override - public String run(Request request, Response response) { + public String handler(Request request, Response response) { System.out.println("进入get!!"); System.out.println(request.query("name")); return "get"; diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 65ac6c4e0..715b55686 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,6 +1,6 @@ #Blade 更新日志 -### v1.2.7 +### v1.2.8 1. 优化500页面,错误在后台显示 2. 添加Path上带后缀 3. 优化多表联查返回数据 @@ -8,6 +8,7 @@ 5. 多表联查返回Map类型数据 6. 解决blade-sql2o连接未释放BUG 7. 支持单次查询是否缓存设置 + 8. 精简BladeBase ### v1.2.6 1. 添加多重路由配置方式 diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index 3f4e5f2d1..6d2f5e073 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -27,7 +27,7 @@ import blade.render.Render; import blade.render.RenderFactory; import blade.route.HttpMethod; -import blade.route.Route; +import blade.route.Router; import blade.route.RouteMatcherBuilder; /** @@ -304,7 +304,7 @@ public static synchronized void regRoute(String path, Class clazz, String met * @param path * @param routeHandler */ - public static synchronized void get(String path, Route routeHandler){ + public static synchronized void get(String path, Router routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.GET); } @@ -313,7 +313,7 @@ public static synchronized void get(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void post(String path, Route routeHandler){ + public static synchronized void post(String path, Router routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.POST); } @@ -322,7 +322,7 @@ public static synchronized void post(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void delete(String path, Route routeHandler){ + public static synchronized void delete(String path, Router routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.DELETE); } @@ -331,7 +331,7 @@ public static synchronized void delete(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void put(String path, Route routeHandler){ + public static synchronized void put(String path, Router routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.PUT); } @@ -340,7 +340,7 @@ public static synchronized void put(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void patch(String path, Route routeHandler){ + public static synchronized void patch(String path, Router routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.PATCH); } @@ -349,7 +349,7 @@ public static synchronized void patch(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void head(String path, Route routeHandler){ + public static synchronized void head(String path, Router routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.HEAD); } @@ -358,7 +358,7 @@ public static synchronized void head(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void trace(String path, Route routeHandler){ + public static synchronized void trace(String path, Router routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.TRACE); } @@ -367,7 +367,7 @@ public static synchronized void trace(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void options(String path, Route routeHandler){ + public static synchronized void options(String path, Router routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.OPTIONS); } @@ -376,7 +376,7 @@ public static synchronized void options(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void connect(String path, Route routeHandler){ + public static synchronized void connect(String path, Router routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.CONNECT); } @@ -385,7 +385,7 @@ public static synchronized void connect(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void all(String path, Route routeHandler){ + public static synchronized void all(String path, Router routeHandler){ RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.ALL); } @@ -394,7 +394,7 @@ public static synchronized void all(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void before(String path, Route routeHandler){ + public static synchronized void before(String path, Router routeHandler){ RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); } @@ -403,7 +403,7 @@ public static synchronized void before(String path, Route routeHandler){ * @param path * @param routeHandler */ - public static synchronized void after(String path, Route routeHandler){ + public static synchronized void after(String path, Router routeHandler){ RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); } @@ -434,8 +434,7 @@ public static synchronized void regInterceptor(String path, Class clazz, Stri RouteMatcherBuilder.buildInterceptor(path, clazz, methodName, acceptType); } - - public static BladeConfig config(){ + public final static BladeConfig config(){ return BLADE_CONFIG; } diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index e2103b803..866e9161d 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -32,6 +32,7 @@ import blade.route.DefaultRouteMatcher; import blade.route.HttpMethod; import blade.route.RouteMatcher; +import blade.route.Router; import blade.servlet.Request; import blade.servlet.Response; import blade.wrapper.RequestResponseBuilder; @@ -104,11 +105,8 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse return false; } } - String acceptType = httpRequest.getHeader(ACCEPT_TYPE_REQUEST_MIME_HEADER); - Request request = null; - // 构建一个包装后的response Response response = RequestResponseBuilder.build(httpResponse); @@ -124,54 +122,29 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse boolean isHandler = true; try { - // 执行before拦截 isHandler = before(requestWrapper, responseWrapper, httpRequest, uri, acceptType); - if(!isHandler){ return false; } // 查找用户请求的uri RouteMatcher match = defaultRouteMatcher.findRouteMatcher(httpMethod, uri, acceptType); - // 如果找到 if (match != null) { - - Class target = match.getTarget(); - - Object targetObject = container.getBean(target, Scope.SINGLE); - - // 要执行的路由方法 - Method execMethod = match.getExecMethod(); - - if(null != requestWrapper.getDelegate()){ - request = requestWrapper.getDelegate(); - request.initRequest(match); - } else { - request = RequestResponseBuilder.build(match, httpRequest); - } - requestWrapper.setDelegate(request); - - BladeWebContext.init(requestWrapper, responseWrapper); - - // 执行route方法 - Object result = executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); - + // 实际执行方法 + Object result = realHandler(httpRequest, requestWrapper, responseWrapper, match); // 执行after拦截 isHandler = after(requestWrapper, responseWrapper, httpRequest, uri, acceptType); - if(!isHandler){ - return false; - } - - if(null != result){ - render(responseWrapper, result); - } + if (!isHandler) + return false; + if (null != result) + render(responseWrapper, result); return true; - } else { - // 没有找到 - response.render404(uri); } + + // 没有找到 + response.render404(uri); } catch (BladeException bex) { bex.printStackTrace(); httpResponse.setStatus(500); @@ -193,6 +166,56 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse } + /** + * + * 实际的路由方法执行 + * @param httpRequest http请求对象 + * @param requestWrapper request包装对象 + * @param responseWrapper response包装对象 + * @param match 路由匹配对象 + * @return object + */ + private Object realHandler(HttpServletRequest httpRequest, RequestWrapper requestWrapper, ResponseWrapper responseWrapper, RouteMatcher match){ + Object result = null; + Router router = match.getRouter(); + if(null != router){ + if (requestWrapper.getDelegate() == null) { + Request request = RequestResponseBuilder.build(match, httpRequest); + requestWrapper.setDelegate(request); + } else { + requestWrapper.initRequest(match); + } + + // 初始化context + BladeWebContext.init(requestWrapper, responseWrapper); + + result = router.handler(requestWrapper, responseWrapper); + + } else { + Class target = match.getTarget(); + + Object targetObject = container.getBean(target, Scope.SINGLE); + + // 要执行的路由方法 + Method execMethod = match.getExecMethod(); + + if (requestWrapper.getDelegate() == null) { + Request request = RequestResponseBuilder.build(match, httpRequest); + requestWrapper.setDelegate(request); + } else { + requestWrapper.initRequest(match); + } + + // 初始化context + BladeWebContext.init(requestWrapper, responseWrapper); + + // 执行route方法 + result = executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); + } + + return result; + } + /** * 前置事件,在route执行前执行 * 这里如果执行则Request和Response都会被创建好 @@ -308,7 +331,7 @@ private Object[] getArgs(Request request, Response response, Class[] params){ private Object executeMethod(Object object, Method method, RequestWrapper requestWrapper, ResponseWrapper responseWrapper){ int len = method.getParameterTypes().length; if(len > 0){ - Object[] args = getArgs(requestWrapper.getDelegate(), responseWrapper.getDelegate(), method.getParameterTypes()); + Object[] args = getArgs(requestWrapper, responseWrapper, method.getParameterTypes()); return ReflectKit.invokeMehod(object, method, args); } else { return ReflectKit.invokeMehod(object, method); diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index 595843533..11011b1bf 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -208,6 +208,54 @@ public void addInterceptor(Class target, Method execMethod, String url, HttpM interceptors.add(entry); } + /** + * 添加一个路由对象 + * + * @param router 执行的匿名类 + * @param url 路由url + * @param method 路由http方法 + * @param acceptType 路由acceptType + */ + public void addRoute(Router router, Method execMethod, String url, HttpMethod method, String acceptType) { + RouteMatcher entry = new RouteMatcher(); + entry.router = router; + entry.httpMethod = method; + entry.path = url; + entry.requestURI = url; + entry.acceptType = acceptType; + + if(Blade.debug()){ + LOGGER.debug("Add Route:" + entry); + } + + // 添加到路由集合 + routes.add(entry); + } + + /** + * 添加一个拦截器对象 + * + * @param router 执行的匿名类 + * @param url 路由url + * @param method 路由http方法 + * @param acceptType 路由acceptType + */ + public void addInterceptor(Router router, String url, HttpMethod method, String acceptType) { + RouteMatcher entry = new RouteMatcher(); + entry.router = router; + entry.httpMethod = method; + entry.path = url; + entry.requestURI = url; + entry.acceptType = acceptType; + + if(Blade.debug()){ + LOGGER.debug("Add Interceptor:" + entry); + } + + // 添加到路由集合 + interceptors.add(entry); + } + private Map getAcceptedMimeTypes(List routes) { Map acceptedTypes = CollectionKit.newHashMap(); diff --git a/blade-core/src/main/java/blade/route/RouteMatcher.java b/blade-core/src/main/java/blade/route/RouteMatcher.java index ab7600dd3..1afb0fd97 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/blade/route/RouteMatcher.java @@ -33,6 +33,8 @@ public class RouteMatcher { */ Class target; + Router router; + /** * 要运行的方法对象 */ @@ -95,6 +97,10 @@ public Class getTarget() { return target; } + public Router getRouter() { + return router; + } + /** * 根据http方法和path进行匹配 * diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index 92c561c48..538e6b253 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -140,22 +140,25 @@ public static void buildFunctional(String path, Class clazz, String methodNam /** * Handler路由构建 */ - public static void buildHandler(String path, blade.route.Route routeHandler, HttpMethod httpMethod){ - if(StringKit.isNotBlank(path) && null != routeHandler){ - Class clazz = blade.route.Route.class; - container.registBean(routeHandler); - Method execMethod = ReflectKit.getMethodByName(clazz, "run"); + public static void buildHandler(String path, Router router, HttpMethod httpMethod){ + if(StringKit.isNotBlank(path) && null != router){ + Class clazz = blade.route.Router.class; + container.registBean(router); + Method execMethod = ReflectKit.getMethodByName(clazz, "handler"); defaultRouteMatcher.addRoute(clazz, execMethod, path, httpMethod, "*/*"); } else { throw new BladeException("an unqualified configuration"); } } - public static void buildInterceptor(String path, blade.route.Route routeHandler, HttpMethod httpMethod){ - if(StringKit.isNotBlank(path) && null != routeHandler){ - Class clazz = blade.route.Route.class; - container.registBean(routeHandler); - Method execMethod = ReflectKit.getMethodByName(clazz, "run"); + /** + * 函数式构建拦截器 + */ + public static void buildInterceptor(String path, Router router, HttpMethod httpMethod){ + if(StringKit.isNotBlank(path) && null != router){ + Class clazz = blade.route.Router.class; + container.registBean(router); + Method execMethod = ReflectKit.getMethodByName(clazz, "handler"); defaultRouteMatcher.addInterceptor(clazz, execMethod, path, httpMethod, "*/*"); } else { throw new BladeException("an unqualified configuration"); diff --git a/blade-core/src/main/java/blade/servlet/Request.java b/blade-core/src/main/java/blade/servlet/Request.java index 82c895ff3..3b3f9146f 100644 --- a/blade-core/src/main/java/blade/servlet/Request.java +++ b/blade-core/src/main/java/blade/servlet/Request.java @@ -49,8 +49,8 @@ public class Request { private static final String USER_AGENT = "user-agent"; - private Map pathParams; - private List splat; + protected Map pathParams; + protected List splat; private QueryParamsMap queryMap; private HttpServletRequest servletRequest; @@ -113,9 +113,9 @@ public String pathParam(String param) { } if (param.startsWith(":")) { - return this.pathParams.get(param.toLowerCase()); + return pathParams.get(param.toLowerCase()); } else { - return this.pathParams.get(":" + param.toLowerCase()); + return pathParams.get(":" + param.toLowerCase()); } } @@ -523,7 +523,7 @@ public String protocol() { return servletRequest.getProtocol(); } - private static Map getPathParams(List request, List matched) { + protected static Map getPathParams(List request, List matched) { Map params = CollectionKit.newHashMap(); @@ -540,7 +540,7 @@ private static Map getPathParams(List request, List getSplat(List request, List matched) { + protected static List getSplat(List request, List matched) { int nbrOfRequestParts = request.size(); int nbrOfMatchedParts = matched.size(); diff --git a/blade-core/src/main/java/blade/wrapper/RequestWrapper.java b/blade-core/src/main/java/blade/wrapper/RequestWrapper.java index 4caf4b9cf..a53aee36f 100644 --- a/blade-core/src/main/java/blade/wrapper/RequestWrapper.java +++ b/blade-core/src/main/java/blade/wrapper/RequestWrapper.java @@ -20,6 +20,7 @@ import javax.servlet.http.HttpServletRequest; +import blade.route.RouteMatcher; import blade.servlet.QueryParamsMap; import blade.servlet.Request; import blade.servlet.Session; @@ -34,6 +35,9 @@ public final class RequestWrapper extends Request { private Request delegate; + public RequestWrapper() { + } + public void setDelegate(Request delegate) { this.delegate = delegate; } @@ -226,4 +230,8 @@ public Map cookies() { public String cookie(String name) { return delegate.cookie(name); } + + public void initRequest(RouteMatcher match) { + delegate.initRequest(match); + } } diff --git a/pom.xml b/pom.xml index 9a59b8000..03c7edc05 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.8-alpha + 1.2.8-beta From d0a06ff1ee2a74bba03738ed035db0c73efe88f9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 27 Aug 2015 16:27:04 +0800 Subject: [PATCH 113/545] update version --- LAST_VERSION.md | 4 ++-- README.md | 2 +- README_CN.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 6e20ee411..5fd2beb77 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.8-alpha +    1.2.8-beta ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -22,7 +22,7 @@     com.bladejava     blade-sql2o -    1.2.7-beta +    1.2.7 ``` diff --git a/README.md b/README.md index 1f507eb9a..68ef265c8 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.8-alpha + 1.2.8-beta ``` diff --git a/README_CN.md b/README_CN.md index 8516a6896..30e1174ae 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,7 +33,7 @@ com.bladejava blade-core - 1.2.8-alpha + 1.2.8-beta ``` From 02e6cf364872a458602854f3318a51224c87e701 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 29 Aug 2015 11:42:24 +0800 Subject: [PATCH 114/545] fix Response is null --- .../src/main/java/blade/RequestHandler.java | 92 +++++++------------ .../src/main/java/blade/route/Router.java | 10 ++ .../java/blade/wrapper/ResponseWrapper.java | 5 +- pom.xml | 2 +- 4 files changed, 49 insertions(+), 60 deletions(-) create mode 100644 blade-core/src/main/java/blade/route/Router.java diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 866e9161d..fab6442f0 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -107,35 +107,41 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse } String acceptType = httpRequest.getHeader(ACCEPT_TYPE_REQUEST_MIME_HEADER); - // 构建一个包装后的response - Response response = RequestResponseBuilder.build(httpResponse); - // 创建RequestWrapper And RequestWrapper RequestWrapper requestWrapper = new RequestWrapper(); - ResponseWrapper responseWrapper = new ResponseWrapper(response); + ResponseWrapper responseWrapper = new ResponseWrapper(); if(Blade.debug()){ LOGGER.debug("Request : " + method + "\t" + uri); } + // 构建一个包装后的response + Response response = RequestResponseBuilder.build(httpResponse); + HttpMethod httpMethod = HttpMethod.valueOf(method); boolean isHandler = true; - + Object result = null; try { - // 执行before拦截 - isHandler = before(requestWrapper, responseWrapper, httpRequest, uri, acceptType); - if(!isHandler){ - return false; - } + responseWrapper.setDelegate(response); // 查找用户请求的uri RouteMatcher match = defaultRouteMatcher.findRouteMatcher(httpMethod, uri, acceptType); // 如果找到 if (match != null) { + // 执行before拦截 + isHandler = before(httpRequest, requestWrapper, responseWrapper, uri, acceptType); + + if(!isHandler){ + return false; + } + // 实际执行方法 - Object result = realHandler(httpRequest, requestWrapper, responseWrapper, match); + responseWrapper.setDelegate(response); + result = realHandler(httpRequest, requestWrapper, responseWrapper, match); + // 执行after拦截 - isHandler = after(requestWrapper, responseWrapper, httpRequest, uri, acceptType); + responseWrapper.setDelegate(response); + isHandler = after(httpRequest, requestWrapper, responseWrapper, uri, acceptType); if (!isHandler) return false; if (null != result) @@ -178,16 +184,18 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse private Object realHandler(HttpServletRequest httpRequest, RequestWrapper requestWrapper, ResponseWrapper responseWrapper, RouteMatcher match){ Object result = null; Router router = match.getRouter(); + + if (requestWrapper.getDelegate() == null) { + Request request = RequestResponseBuilder.build(match, httpRequest); + requestWrapper.setDelegate(request); + } else { + requestWrapper.initRequest(match); + } + + // 初始化context + BladeWebContext.init(requestWrapper, responseWrapper); + if(null != router){ - if (requestWrapper.getDelegate() == null) { - Request request = RequestResponseBuilder.build(match, httpRequest); - requestWrapper.setDelegate(request); - } else { - requestWrapper.initRequest(match); - } - - // 初始化context - BladeWebContext.init(requestWrapper, responseWrapper); result = router.handler(requestWrapper, responseWrapper); @@ -199,16 +207,6 @@ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper reques // 要执行的路由方法 Method execMethod = match.getExecMethod(); - if (requestWrapper.getDelegate() == null) { - Request request = RequestResponseBuilder.build(match, httpRequest); - requestWrapper.setDelegate(request); - } else { - requestWrapper.initRequest(match); - } - - // 初始化context - BladeWebContext.init(requestWrapper, responseWrapper); - // 执行route方法 result = executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); } @@ -226,7 +224,7 @@ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper reques * @param uri 请求的URI * @param acceptType 请求头过滤 */ - private boolean before(RequestWrapper requestWrapper, ResponseWrapper responseWrapper, HttpServletRequest httpRequest, final String uri, final String acceptType){ + private boolean before(HttpServletRequest httpRequest, RequestWrapper requestWrapper, ResponseWrapper responseWrapper, final String uri, final String acceptType){ List matchSet = defaultRouteMatcher.findInterceptor(HttpMethod.BEFORE, uri, acceptType); @@ -234,16 +232,7 @@ private boolean before(RequestWrapper requestWrapper, ResponseWrapper responseWr for (RouteMatcher filterMatch : matchSet) { - Class target = filterMatch.getTarget(); - - Object targetObject = container.getBean(target, Scope.SINGLE); - - Method execMethod = filterMatch.getExecMethod(); - - Request request = RequestResponseBuilder.build(filterMatch, httpRequest); - requestWrapper.setDelegate(request); - - Object object = executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); + Object object = realHandler(httpRequest, requestWrapper, responseWrapper, filterMatch); if(null != object && object instanceof Boolean){ isHandler = (Boolean) object; @@ -258,32 +247,19 @@ private boolean before(RequestWrapper requestWrapper, ResponseWrapper responseWr /** * 后置事件,在route执行后执行 * + * @param httpRequest HttpServletRequest请求对象,用于构建Request * @param requestWrapper RequestWrapper对象,包装了Request对象 * @param responseWrapper ResponseWrapper对象,包装了Response对象 - * @param httpRequest HttpServletRequest请求对象,用于构建Request * @param uri 请求的URI * @param acceptType 请求头过滤 */ - private boolean after(RequestWrapper requestWrapper, ResponseWrapper responseWrapper, HttpServletRequest httpRequest, final String uri, final String acceptType){ + private boolean after(HttpServletRequest httpRequest, RequestWrapper requestWrapper, ResponseWrapper responseWrapper, final String uri, final String acceptType){ List matchSet = defaultRouteMatcher.findInterceptor(HttpMethod.AFTER, uri, acceptType); boolean isHandler = true; for (RouteMatcher filterMatch : matchSet) { - Class target = filterMatch.getTarget(); - - Object targetObject = container.getBean(target, Scope.SINGLE); - - Method execMethod = filterMatch.getExecMethod(); - - if (requestWrapper.getDelegate() == null) { - Request request = RequestResponseBuilder.build(filterMatch, httpRequest); - requestWrapper.setDelegate(request); - } else { - requestWrapper.initRequest(filterMatch); - } - - Object object = executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); + Object object = realHandler(httpRequest, requestWrapper, responseWrapper, filterMatch); if(null != object && object instanceof Boolean){ isHandler = (Boolean) object; if(!isHandler){ diff --git a/blade-core/src/main/java/blade/route/Router.java b/blade-core/src/main/java/blade/route/Router.java new file mode 100644 index 000000000..08b13a136 --- /dev/null +++ b/blade-core/src/main/java/blade/route/Router.java @@ -0,0 +1,10 @@ +package blade.route; + +import blade.servlet.Request; +import blade.servlet.Response; + +public interface Router { + + public Object handler(Request request, Response response); + +} diff --git a/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java b/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java index 48ad7835d..b73a88a74 100644 --- a/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java +++ b/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java @@ -30,7 +30,10 @@ public class ResponseWrapper extends Response { private Response delegate; private boolean redirected = false; - + + public ResponseWrapper() { + // TODO Auto-generated constructor stub + } public ResponseWrapper(Response delegate) { this.delegate = delegate; diff --git a/pom.xml b/pom.xml index 03c7edc05..763cf88f5 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.8-beta + 1.2.8 From 90ad1d5e62c0802e2c8521bd55799d44fc755a6f Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 29 Aug 2015 11:57:54 +0800 Subject: [PATCH 115/545] fix response.go --- .../java/blade/wrapper/ResponseWrapper.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java b/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java index b73a88a74..611f523f7 100644 --- a/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java +++ b/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java @@ -17,6 +17,7 @@ import javax.servlet.http.HttpServletResponse; +import blade.render.ModelAndView; import blade.servlet.Response; /** @@ -77,6 +78,10 @@ public HttpServletResponse servletResponse() { return delegate.servletResponse(); } + public void go(String path) { + delegate.go(path); + } + @Override public void redirect(String location) { redirected = true; @@ -135,4 +140,78 @@ public void cookie(String path, String name, String value, int maxAge, boolean s public void removeCookie(String name) { delegate.removeCookie(name); } + + /** + * 渲染一个视图 + * @param view + */ + public void render(String view){ + delegate.render(view); + } + + /** + * 根据ModelAndView进行渲染 + * @param modelAndView + */ + public void render(ModelAndView modelAndView){ + delegate.render(modelAndView); + } + + /** + * 返回文字格式 + * @param text + */ + public void text(String text){ + delegate.text(text); + } + + /** + * 返回json格式 + * @param json + */ + public void json(String json){ + delegate.json(json); + } + + /** + * 返回xml格式 + * @param xml + */ + public void xml(String xml){ + delegate.xml(xml); + } + + /** + * 返回js格式 + * @param javascript + */ + public void javascript(String javascript){ + delegate.javascript(javascript); + } + + /** + * 返回html格式 + * @param html + */ + public void html(String html){ + delegate.html(html); + } + + /** + * 404默认视图 + * + * @param viewName + */ + public void render404(String viewName){ + delegate.render404(viewName); + } + + /** + * 500默认视图 + * + * @param bodyContent + */ + public void render500(String bodyContent){ + delegate.render500(bodyContent); + } } From 1ee70be0db6af0db348c0997e5731df99de23747 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 29 Aug 2015 12:02:52 +0800 Subject: [PATCH 116/545] update version --- LAST_VERSION.md | 2 +- README.md | 2 +- README_CN.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 5fd2beb77..6fa0d4eb3 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.8-beta +    1.2.8 ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/README.md b/README.md index 68ef265c8..1e93e823a 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.8-beta + 1.2.8 ``` diff --git a/README_CN.md b/README_CN.md index 30e1174ae..2194b4be3 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,7 +33,7 @@ com.bladejava blade-core - 1.2.8-beta + 1.2.8 ``` From cd13807022ed79f895f33d90d11dea4861421d46 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 31 Aug 2015 10:45:13 +0800 Subject: [PATCH 117/545] blade sql2o add conntion pool --- .../java/blade/plugin/sql2o/DBConfig.java | 40 - .../java/blade/plugin/sql2o/Sql2oPlugin.java | 131 +++- .../plugin/sql2o/ds/DataSourceManager.java | 65 +- .../plugin/sql2o/exception/PoolException.java | 27 + .../plugin/sql2o/pool/ConnectionPool.java | 306 ++++++++ .../sql2o/pool/ConnectionPoolManager.java | 116 +++ .../blade/plugin/sql2o/pool/Constant.java | 129 ++++ .../blade/plugin/sql2o/pool/DatabaseType.java | 95 +++ .../plugin/sql2o/pool/InitPoolConfig.java | 23 + .../blade/plugin/sql2o/pool/PoolConfig.java | 218 ++++++ .../src/main/java/org/sql2o/Connection.java | 309 ++++++++ .../sql2o/DefaultResultSetHandlerFactory.java | 187 +++++ ...DefaultResultSetHandlerFactoryBuilder.java | 65 ++ .../org/sql2o/DelegatingResultSetHandler.java | 23 + .../java/org/sql2o/GenericDatasource.java | 98 +++ .../main/java/org/sql2o/JndiDataSource.java | 42 + .../java/org/sql2o/PojoResultSetIterator.java | 38 + .../src/main/java/org/sql2o/Query.java | 722 ++++++++++++++++++ .../main/java/org/sql2o/ResultSetHandler.java | 13 + .../org/sql2o/ResultSetHandlerFactory.java | 13 + .../sql2o/ResultSetHandlerFactoryBuilder.java | 36 + .../java/org/sql2o/ResultSetIterable.java | 15 + .../java/org/sql2o/ResultSetIteratorBase.java | 107 +++ .../src/main/java/org/sql2o/Sql2o.java | 378 +++++++++ .../main/java/org/sql2o/Sql2oException.java | 22 + .../java/org/sql2o/StatementRunnable.java | 11 + .../sql2o/StatementRunnableWithResult.java | 11 + .../converters/AbstractDateConverter.java | 44 ++ .../sql2o/converters/BigDecimalConverter.java | 33 + .../sql2o/converters/BooleanConverter.java | 37 + .../sql2o/converters/ByteArrayConverter.java | 54 ++ .../org/sql2o/converters/ByteConverter.java | 26 + .../java/org/sql2o/converters/Convert.java | 158 ++++ .../java/org/sql2o/converters/Converter.java | 17 + .../org/sql2o/converters/ConverterBase.java | 12 + .../sql2o/converters/ConverterException.java | 15 + .../sql2o/converters/ConvertersProvider.java | 14 + .../org/sql2o/converters/DateConverter.java | 19 + .../DefaultEnumConverterFactory.java | 32 + .../org/sql2o/converters/DoubleConverter.java | 26 + .../converters/EnumConverterFactory.java | 8 + .../org/sql2o/converters/FloatConverter.java | 26 + .../converters/InputStreamConverter.java | 22 + .../sql2o/converters/IntegerConverter.java | 26 + .../org/sql2o/converters/LongConverter.java | 26 + .../org/sql2o/converters/NumberConverter.java | 47 ++ .../org/sql2o/converters/ShortConverter.java | 26 + .../org/sql2o/converters/StringConverter.java | 57 ++ .../org/sql2o/converters/UUIDConverter.java | 25 + .../converters/joda/DateTimeConverter.java | 46 ++ .../converters/joda/LocalTimeConverter.java | 31 + .../org/sql2o/converters/package-info.java | 5 + .../src/main/java/org/sql2o/data/Column.java | 34 + .../main/java/org/sql2o/data/LazyTable.java | 42 + .../src/main/java/org/sql2o/data/Row.java | 194 +++++ .../src/main/java/org/sql2o/data/Table.java | 45 ++ .../sql2o/data/TableResultSetIterator.java | 51 ++ .../java/org/sql2o/data/package-info.java | 4 + .../org/sql2o/logging/LocalLoggerFactory.java | 19 + .../main/java/org/sql2o/logging/Logger.java | 12 + .../java/org/sql2o/logging/Slf4jLogger.java | 29 + .../java/org/sql2o/logging/SysOutLogger.java | 62 ++ .../src/main/java/org/sql2o/package-info.java | 4 + .../main/java/org/sql2o/quirks/Db2Quirks.java | 28 + .../main/java/org/sql2o/quirks/NoQuirks.java | 123 +++ .../java/org/sql2o/quirks/OracleQuirks.java | 36 + .../java/org/sql2o/quirks/PostgresQuirks.java | 24 + .../main/java/org/sql2o/quirks/Quirks.java | 54 ++ .../java/org/sql2o/quirks/QuirksDetector.java | 34 + .../java/org/sql2o/quirks/QuirksProvider.java | 11 + .../SqlParameterParsingStrategy.java | 11 + .../impl/AbstractCommentParser.java | 23 + .../parameterparsing/impl/CharParser.java | 9 + .../parameterparsing/impl/DefaultParser.java | 18 + .../DefaultSqlParameterParsingStrategy.java | 44 ++ .../impl/DoubleHyphensCommentParser.java | 17 + .../impl/ForwardSlashCommentParser.java | 26 + .../impl/ParameterParser.java | 44 ++ .../parameterparsing/impl/QuoteParser.java | 26 + .../sql2o/quirks/spi/QuirksProviderImpl.java | 40 + .../org/sql2o/reflection/FactoryFacade.java | 60 ++ .../org/sql2o/reflection/FieldSetter.java | 34 + .../sql2o/reflection/FieldSetterFactory.java | 14 + .../reflection/MethodAccessorsGenerator.java | 164 ++++ .../org/sql2o/reflection/MethodSetter.java | 38 + .../sql2o/reflection/MethodSetterFactory.java | 14 + .../sql2o/reflection/ObjectConstructor.java | 12 + .../reflection/ObjectConstructorFactory.java | 12 + .../main/java/org/sql2o/reflection/Pojo.java | 84 ++ .../sql2o/reflection/PojoIntrospector.java | 118 +++ .../org/sql2o/reflection/PojoMetadata.java | 188 +++++ .../ReflectionFieldSetterFactory.java | 16 + .../ReflectionMethodSetterFactory.java | 16 + .../ReflectionObjectConstructorFactory.java | 30 + .../java/org/sql2o/reflection/Setter.java | 10 + .../reflection/UnsafeFieldSetterFactory.java | 260 +++++++ .../org/sql2o/reflection/package-info.java | 4 + .../java/org/sql2o/tools/AbstractCache.java | 60 ++ .../main/java/org/sql2o/tools/ClassUtils.java | 30 + .../java/org/sql2o/tools/FeatureDetector.java | 67 ++ .../main/java/org/sql2o/tools/IOUtils.java | 39 + .../sql2o/tools/UnderscoreToCamelCase.java | 37 + .../java/org/sql2o/tools/package-info.java | 4 + 103 files changed, 6347 insertions(+), 100 deletions(-) delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/exception/PoolException.java create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/DatabaseType.java create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/InitPoolConfig.java create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/Connection.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactoryBuilder.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/DelegatingResultSetHandler.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/GenericDatasource.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/PojoResultSetIterator.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/Query.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/ResultSetHandler.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactoryBuilder.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/ResultSetIterable.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/ResultSetIteratorBase.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/Sql2o.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/Sql2oException.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/StatementRunnable.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/StatementRunnableWithResult.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/AbstractDateConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/BigDecimalConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/BooleanConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ByteConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/Convert.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/Converter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ConverterBase.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ConverterException.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ConvertersProvider.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/DateConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/DefaultEnumConverterFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/DoubleConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/EnumConverterFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/FloatConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/InputStreamConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/IntegerConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/LongConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/NumberConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ShortConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/UUIDConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/joda/DateTimeConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/joda/LocalTimeConverter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/package-info.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/data/Column.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/data/LazyTable.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/data/Row.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/data/Table.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/data/TableResultSetIterator.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/data/package-info.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/logging/LocalLoggerFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/logging/Logger.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/logging/Slf4jLogger.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/logging/SysOutLogger.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/package-info.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/Db2Quirks.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/NoQuirks.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/OracleQuirks.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/PostgresQuirks.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/Quirks.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/QuirksDetector.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/QuirksProvider.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/SqlParameterParsingStrategy.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/AbstractCommentParser.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/CharParser.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultParser.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultSqlParameterParsingStrategy.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DoubleHyphensCommentParser.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ForwardSlashCommentParser.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ParameterParser.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/QuoteParser.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/spi/QuirksProviderImpl.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetterFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetterFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructor.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructorFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionFieldSetterFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionMethodSetterFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionObjectConstructorFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/package-info.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/AbstractCache.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/ClassUtils.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/IOUtils.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java create mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/package-info.java diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java deleted file mode 100644 index e7035d750..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java +++ /dev/null @@ -1,40 +0,0 @@ -package blade.plugin.sql2o; - -/** - * 用于保存数据库元信息 - * - * @author biezhi - * @since 1.0 - */ -public class DBConfig { - - private String drive; - private String url; - private String user; - private String password; - - public DBConfig(String drive, String url, String user, String password) { - super(); - this.drive = drive; - this.url = url; - this.user = user; - this.password = password; - } - - public String getDrive() { - return drive; - } - - public String getUrl() { - return url; - } - - public String getUser() { - return user; - } - - public String getPassword() { - return password; - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index 022a2720a..3162b4c86 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -1,12 +1,18 @@ package blade.plugin.sql2o; +import java.util.Properties; + import javax.sql.DataSource; import blade.Blade; +import blade.kit.PropertyKit; import blade.kit.StringKit; import blade.kit.log.Logger; import blade.plugin.Plugin; import blade.plugin.sql2o.ds.DataSourceManager; +import blade.plugin.sql2o.pool.ConnectionPool; +import blade.plugin.sql2o.pool.Constant; +import blade.plugin.sql2o.pool.PoolConfig; /** * sql2o数据库插件 @@ -20,7 +26,7 @@ public enum Sql2oPlugin implements Plugin { private Logger LOGGER = Logger.getLogger(Sql2oPlugin.class); - private DBConfig dbConfig; + private PoolConfig poolConfig; private boolean openCache; @@ -32,23 +38,100 @@ private Sql2oPlugin() { * * @param dbConfig 数据库配置 */ - public Sql2oPlugin autoConfig(){ - String drive = Blade.config().getDbDriver(); - String url = Blade.config().getDbUrl(); - String user = Blade.config().getDbUser(); - String password = Blade.config().getDbPass(); - INSTANCE.dbConfig = new DBConfig(drive, url, user, password); + public Sql2oPlugin load(String filePath){ + + Properties configProperties = PropertyKit.getProperty(filePath); + String drive = configProperties.getProperty(Constant.DRIVE); + String url = configProperties.getProperty(Constant.URL); + String username = configProperties.getProperty(Constant.USERNAME); + String password = configProperties.getProperty(Constant.PASSWORD); + String keepAliveSql = configProperties.getProperty(Constant.KEEPALIVESQL); + String minConn = configProperties.getProperty(Constant.MIN_CONN); + String maxConn = configProperties.getProperty(Constant.MAX_CONN); + String initConn = configProperties.getProperty(Constant.INIT_CONN); + String maxActiveConn = configProperties.getProperty(Constant.MAX_ACTIVE_CONN); + String connWaitTime = configProperties.getProperty(Constant.CONN_WAIT_TIME); + String connTimeOut = configProperties.getProperty(Constant.CONN_TIME_OUT); + String isCheakPool = configProperties.getProperty(Constant.IS_CHECK_POOL); + String periodCheck = configProperties.getProperty(Constant.PERIOD_CHECK); + String lazyCheck = configProperties.getProperty(Constant.LAZY_CHECK); + String poolName = configProperties.getProperty(Constant.POOL_NAME); + + PoolConfig poolConfig = new PoolConfig(); + + if(StringKit.isNotBlank(drive)){ + poolConfig.setDriverName(drive); + } + + if(StringKit.isNotBlank(url)){ + poolConfig.setUrl(url); + } + + if(StringKit.isNotBlank(username)){ + poolConfig.setUserName(username); + } + + if(StringKit.isNotBlank(password)){ + poolConfig.setPassWord(password); + } + + if(StringKit.isNotBlank(keepAliveSql)){ + poolConfig.setKeepAliveSql(keepAliveSql); + } + + if(StringKit.isNotBlank(minConn) && StringKit.isNumber(minConn.trim())){ + poolConfig.setMinConn(Integer.valueOf(minConn.trim())); + } + + if(StringKit.isNotBlank(maxConn) && StringKit.isNumber(maxConn.trim())){ + poolConfig.setMaxConn(Integer.valueOf(maxConn.trim())); + } + + if(StringKit.isNotBlank(initConn) && StringKit.isNumber(initConn.trim())){ + poolConfig.setInitConn(Integer.valueOf(initConn.trim())); + } + + if(StringKit.isNotBlank(maxActiveConn) && StringKit.isNumber(maxActiveConn.trim())){ + poolConfig.setMaxActiveConn(Integer.valueOf(maxActiveConn.trim())); + } + + if(StringKit.isNotBlank(connTimeOut) && StringKit.isNumber(connTimeOut.trim())){ + poolConfig.setConnTimeOut(Long.valueOf(connTimeOut.trim())); + } + + if(StringKit.isNotBlank(connWaitTime) && StringKit.isNumber(connWaitTime.trim())){ + poolConfig.setConnWaitTime(Long.valueOf(connWaitTime.trim())); + } + + if(StringKit.isNotBlank(isCheakPool)){ + poolConfig.setCheakPool(Boolean.valueOf(isCheakPool.trim())); + } + + if(StringKit.isNotBlank(periodCheck) && StringKit.isNumber(periodCheck.trim())){ + poolConfig.setPeriodCheck(Long.valueOf(periodCheck.trim())); + } + + if(StringKit.isNotBlank(lazyCheck) && StringKit.isNumber(lazyCheck.trim())){ + poolConfig.setInitDelay(Long.valueOf(lazyCheck.trim())); + } + + if(StringKit.isNotBlank(poolName)){ + poolConfig.setPoolName(poolName); + } + + INSTANCE.poolConfig = poolConfig; INSTANCE.openCache = Blade.config().isOpenCache(); + return INSTANCE; } - + /** * 设置数据库配置 * * @param dbConfig 数据库配置 */ - public Sql2oPlugin config(DBConfig dbConfig){ - INSTANCE.dbConfig = dbConfig; + public Sql2oPlugin config(PoolConfig poolConfig){ + INSTANCE.poolConfig = poolConfig; return INSTANCE; } @@ -60,13 +143,19 @@ public Sql2oPlugin config(DBConfig dbConfig){ * @param user * @param pass */ - public Sql2oPlugin config(String url, String driver, String user, String pass){ + public Sql2oPlugin config(String url, String user, String pass){ - if(StringKit.isNotEmpty(url) && StringKit.isNotEmpty(driver) - && StringKit.isNotEmpty(user) && StringKit.isNotEmpty(pass)){ + return config(null, url, user, pass); + } + + public Sql2oPlugin config(String driver, String url, String user, String pass){ - INSTANCE.dbConfig = new DBConfig(driver, url, user, pass); - } + PoolConfig poolConfig = new PoolConfig(); + poolConfig.setDriverName(driver); + poolConfig.setUrl(url); + poolConfig.setUserName(user); + poolConfig.setPassWord(pass); + INSTANCE.poolConfig = poolConfig; return INSTANCE; } @@ -80,17 +169,19 @@ public boolean isOpenCache() { return INSTANCE.openCache; } - public DBConfig dbConfig(){ - return INSTANCE.dbConfig; + public PoolConfig poolConfig(){ + return INSTANCE.poolConfig; } @Override public void run() { DataSource dataSource = DataSourceManager.getDataSource(); - if(null != dataSource){ - LOGGER.debug("数据库插件配置成功..."); - } else { + ConnectionPool connectionPool = DataSourceManager.getConnectionPool(); + + if(null == dataSource && null == connectionPool){ LOGGER.error("数据库插件配置失败"); + } else { + LOGGER.debug("数据库插件配置成功..."); } } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java index 5b852af87..d805e51e7 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java @@ -1,18 +1,18 @@ package blade.plugin.sql2o.ds; -import java.sql.Connection; -import java.sql.SQLException; - import javax.sql.DataSource; import org.sql2o.Sql2o; import blade.ioc.AbstractBeanFactory; import blade.ioc.SingleBean; -import blade.plugin.sql2o.DBConfig; import blade.plugin.sql2o.Sql2oPlugin; -import blade.plugin.sql2o.connection.SingleThreadConnectionHolder; import blade.plugin.sql2o.exception.DataSourceException; +import blade.plugin.sql2o.exception.PoolException; +import blade.plugin.sql2o.pool.ConnectionPool; +import blade.plugin.sql2o.pool.ConnectionPoolManager; +import blade.plugin.sql2o.pool.InitPoolConfig; +import blade.plugin.sql2o.pool.PoolConfig; /** * 数据源连接管理器 @@ -23,6 +23,8 @@ public final class DataSourceManager { private static DataSource dataSource; + private static ConnectionPool connectionPool; + private static Sql2o sql2o = null; private static final AbstractBeanFactory beanFactory = new SingleBean(); @@ -39,19 +41,35 @@ private DataSourceManager() { throw new DataSourceException("数据源初始化失败!"); } } else { - // jdbc - DataSourceManager.dataSource = getJdbcDataSource(); + // 内部连接池 + DataSourceManager.connectionPool = getConnectionPool(); } if(null != DataSourceManager.dataSource){ sql2o = new Sql2o(DataSourceManager.dataSource); } + + if(null != DataSourceManager.connectionPool){ + sql2o = new Sql2o(connectionPool); + } } public static Sql2o getSql2o(){ return sql2o; } + public static ConnectionPool getConnectionPool() { + if(null == connectionPool){ + PoolConfig poolConfig = Sql2oPlugin.INSTANCE.poolConfig(); + if(null == poolConfig){ + throw new PoolException("数据库配置失败"); + } + InitPoolConfig.add(poolConfig); + return ConnectionPoolManager.me().getPool(poolConfig.getPoolName()); + } + return connectionPool; + } + /** * 提供动态注入datasource * @param dataSource_ @@ -67,37 +85,4 @@ public static DataSource getDataSource(){ return dataSource; } - /** - * 获取jdbc数据源 - * @return JdbcDataSource - */ - private static DataSource getJdbcDataSource(){ - DBConfig dbConfig = Sql2oPlugin.INSTANCE.dbConfig(); - if(null == dbConfig){ - throw new DataSourceException("没有配置数据库"); - } - String url = dbConfig.getUrl(); - String driver = dbConfig.getDrive(); - String username = dbConfig.getUser(); - String password = dbConfig.getPassword(); - dataSource = new JdbcDataSource(url, driver, username, password); - return dataSource; - } - - /** - * 获取数据库链接 - * @return connection对象 - */ - public static Connection getConnection() { - try { - if(null != dataSource){ - return SingleThreadConnectionHolder.getConnection(dataSource); - } - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - return null; - } - } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/exception/PoolException.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/exception/PoolException.java new file mode 100644 index 000000000..eb12b06c5 --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/exception/PoolException.java @@ -0,0 +1,27 @@ +package blade.plugin.sql2o.exception; + + +/** + * PoolException + *

+ *

+ * + * @author biezhi + * @since 1.0 + */ +public class PoolException extends RuntimeException{ + + private static final long serialVersionUID = 4566581404090220394L; + + public PoolException() { + throw new RuntimeException(); + } + + public PoolException(String e) { + throw new RuntimeException(e); + } + + public PoolException(Exception e) { + throw new RuntimeException(e); + } +} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java new file mode 100644 index 000000000..57b4f8265 --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java @@ -0,0 +1,306 @@ +package blade.plugin.sql2o.pool; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.TimerTask; +import java.util.Vector; +import java.util.concurrent.TimeUnit; + +import blade.kit.StringKit; +import blade.kit.TaskKit; +import blade.kit.log.Logger; + +/** + * 数据库连接池 + * @author biezhi + * + */ +public class ConnectionPool { + + private static final Logger LOGGER = Logger.getLogger(ConnectionPool.class); + + /** + * 连接池活动状态 + */ + private boolean isActive = false; + + /** + * 连接池配置对象 + */ + private PoolConfig poolConfig; + + /** + * 创建的连接数 + */ + private int totalConn; + + /** + * 空闲连接 + */ + private List freeConnections = new Vector(); + + /** + * 活动连接 + */ + private List activeConnections = new Vector(); + + /** + * 将线程和连接绑定,保证事务能统一执行 + */ + ThreadLocal threadLocal = new ThreadLocal(); + + /** + * 构造方法,初始化连接池 + * + * @param poolConfig + */ + public ConnectionPool(PoolConfig poolConfig) { + super(); + this.poolConfig = poolConfig; + createConnectionPool(); + checkConnectionPool(); + + } + + private void createConnectionPool() { + try { + Class.forName(poolConfig.getDriverName()); + int initNum = poolConfig.getInitConn(); + for (int i = 0; i < initNum; i++) { + Connection conn = createConn(); + freeConnections.add(conn); + } + isActive = true; + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + protected void sendCheckSQL() throws SQLException { + Statement statement = null; + Connection internalConnection = null; + try { + internalConnection = obtainInternalConnection(); + String keepAliveSQL = poolConfig.getKeepAliveSql(); + if (StringKit.isEmpty(keepAliveSQL)) { + internalConnection.getMetaData().getTables(null, null, "connpool_keepalive", new String[] { "TABLE" }); + } else { + statement = internalConnection.createStatement(); + statement.execute(keepAliveSQL); + } + LOGGER.debug("连接测试语句执行成功"); + } catch (SQLException e) { + LOGGER.error("连接测试语句执行失败", e); + throw e; + } finally { + closeConnection(internalConnection); + } + } + + private Connection obtainInternalConnection() throws SQLException { + return DriverManager.getConnection(poolConfig.getUrl(), poolConfig.getUserName(), poolConfig.getPassWord()); + } + + private synchronized Connection createConn() throws ClassNotFoundException, SQLException { + Connection conn = null; + if (null != poolConfig) { + Class.forName(poolConfig.getDriverName()); + conn = DriverManager.getConnection(poolConfig.getUrl(), + poolConfig.getUserName(), poolConfig.getPassWord()); + totalConn++; + } + + return conn; + } + + /** + * 获得连接 + * + * @return + */ + public synchronized Connection getConnection() { + + Connection conn = null; + + try { + + if (null == poolConfig) { + return conn; + } + // 如果已经创建的连接数小于数据库的最大连接数而且小于连接池最大的连接数,那么再创建连接数 + if (totalConn < poolConfig.getMaxActiveConn() + && totalConn < poolConfig.getMaxActiveConn()) { + + if (freeConnections.size() > 0) {// 如果还有空闲连接 + conn = freeConnections.get(0); + if (null != conn) { + threadLocal.set(conn); + freeConnections.remove(0); + + } + } else { + conn = createConn(); + } + + } else { + // 等待一段时间后再去获得连接 + wait(poolConfig.getConnWaitTime()); + conn = getConnection(); + } + + if (isValid(conn)) { + activeConnections.add(conn); + } + + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (SQLException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + return conn; + } + + private boolean isValid(Connection conn) { + try { + if (conn.isClosed()) { + return false; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return true; + } + + /** + * 获得当前连接 + * + * @return + */ + public Connection getCurrentConnection() { + // 默认从线程中取出连接 + Connection conn = threadLocal.get(); + if (!isValid(conn)) { + conn = getConnection(); + } + return conn; + } + + /** + * 释放连接 + * + * @param conn + */ + public synchronized void releaseConnection(Connection conn) throws SQLException { + + if (isValid(conn)) { + freeConnections.add(conn); + activeConnections.remove(conn); + threadLocal.remove(); + // 唤醒所有正待等待的线程,去抢连接 + notifyAll(); + } + + } + + /** + * 关闭连接 + * + * @param conn + * @throws SQLException + */ + public synchronized void closeConnection(Connection conn) throws SQLException { + + conn.close(); + freeConnections.remove(conn); + activeConnections.remove(conn); + threadLocal.remove(); + } + + /** + * 销毁连接 + */ + public synchronized void destroy() { + for (Connection conn : freeConnections) { + try { + if (isValid(conn)) { + conn.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + for (Connection conn : activeConnections) { + try { + if (isValid(conn)) { + conn.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + isActive = false; + totalConn = 0; + + TaskKit.depose(); + } + + /** + * 判断该连接池是否可用 + * + * @return + */ + public boolean isActive() { + return isActive; + } + + /** + * 获得活动的连接数 + * + * @return + */ + public int getActiveConnNum() { + return activeConnections.size(); + } + + /** + * 获得空闲的连接数 + * + * @return + */ + public int getFreeConnNum() { + return freeConnections.size(); + } + + private void checkConnectionPool() { + + if(StringKit.isNotBlank(poolConfig.getKeepAliveSql())){ + try { + sendCheckSQL(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + if (poolConfig.isCheakPool()) { + TaskKit.scheduleWithFixedDelay(new TimerTask() { + @Override + public void run() { + LOGGER.debug("空线池连接数:" + freeConnections.size()); + LOGGER.debug("活动连接数:" + activeConnections.size()); + LOGGER.debug("总的连接数:" + totalConn); + LOGGER.debug("连接池活动状态:" + isActive); + } + }, poolConfig.getInitDelay(), poolConfig.getPeriodCheck(), TimeUnit.SECONDS); + } + + } + +} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java new file mode 100644 index 000000000..d35f49d48 --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java @@ -0,0 +1,116 @@ +package blade.plugin.sql2o.pool; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Hashtable; +import java.util.List; + +/** + * 数据连接池管理器 + * @author biezhi + * + */ +public class ConnectionPoolManager { + + private static ConnectionPoolManager connectionPoolManager; + + /** + * 连接池存放 + */ + private Hashtable pools; + + /** + * 总的连接数 + */ + private static int clients; + + private ConnectionPoolManager() { + connectionPoolManager = this; + pools = new Hashtable(); + init(); + } + + private void init() { + + List poolConfigs = InitPoolConfig.poolConfigList; + + for(PoolConfig config : poolConfigs){ + ConnectionPool pool = new ConnectionPool(config); + if (pool != null) { + pools.put(config.getPoolName(), pool); + } + } + + } + + /** + * 获得连接池管理器实例 + * + * @return + */ + public static synchronized ConnectionPoolManager me() { + if (null == connectionPoolManager) { + connectionPoolManager = new ConnectionPoolManager(); + } + clients++; + return connectionPoolManager; + } + + /** + * 获得连接池 + * + * @return + */ + public ConnectionPool getPool(String poolName) { + return pools.get(poolName); + } + + /** + * 获得数据库链接 + * + * @return + */ + public Connection getConnection(String poolName) { + Connection conn = null; + conn = getPool(poolName).getConnection(); + return conn; + } + + /** + * 释放连接 + */ + public void releaseConnection(String poolName, Connection conn) { + + try { + ConnectionPool pool = getPool(poolName); + if (null != null) { + pool.releaseConnection(conn); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * 清空连接池 + * + * @param poolName + */ + public void destory(String poolName) { + ConnectionPool pool = getPool(poolName); + if (null != null) { + pool.destroy(); + } + } + + /** + * 获得连接数 + * @return + */ + public static int getClients() { + return clients; + } + + + +} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java new file mode 100644 index 000000000..e7be8403e --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java @@ -0,0 +1,129 @@ +package blade.plugin.sql2o.pool; + +/** + * 连接池常量 + */ +public final class Constant { + + /** + * 数据库驱动 + */ + public static final String DRIVE = "blade.db.drive"; + + /** + * 数据库URL + */ + public static final String URL = "blade.db.url"; + + /** + * 用户名 + */ + public static final String USERNAME = "blade.db.username"; + + /** + * 密码 + */ + public static final String PASSWORD = "blade.db.password"; + + /** + * 测试SQL语句 + */ + public static final String KEEPALIVESQL = "blade.db.keepAliveSql"; + + /** + * 最小连接 + */ + public static final String MIN_CONN = "blade.db.minConn"; + + /** + * 最大连接 + */ + public static final String MAX_CONN = "blade.db.maxConn"; + + /** + * 初始连接数 + */ + public static final String INIT_CONN = "blade.db.initConn"; + + /** + * 最大活动连接 + */ + public static final String MAX_ACTIVE_CONN = "blade.db.maxActiveConn"; + + /** + * 连接等待时间 + */ + public static final String CONN_WAIT_TIME = "blade.db.connWaitTime"; + + /** + * 连接超时时间 + */ + public static final String CONN_TIME_OUT = "blade.db.connTimeOut"; + + /** + * 是否检查连接池 + */ + public static final String IS_CHECK_POOL = "blade.db.isCheakPool"; + + /** + * 检查频率 + */ + public static final String PERIOD_CHECK = "blade.db.periodCheck"; + + /** + * 初始延时检查 + */ + public static final String LAZY_CHECK = "blade.db.initDelay"; + + /** + * 连接池名称 + */ + public static final String POOL_NAME = "blade.db.poolName"; + + /** + * 默认连接池名称 + */ + public static final String DEFAULT_POOL_NAME = "blade_sql2o_pool"; + + /** + * 默认初始连接数 + */ + public static final int DEFAULT_INIT_CONN = 5; + + /** + * 默认最小连接数 + */ + public static final int DEFAULT_MIN_CONN = 1; + + /** + * 默认最大连接数 + */ + public static final int DEFAULT_MAX_CONN = 20; + + /** + * 默认最大活动连接数 + */ + public static final int DEFAULT_MAX_ACTIVE_CONN = 100; + + /** + * 默认最大连接等待时长 + */ + public static final long DEFAULT_CONN_WAIT_TIME = 1000; + + /** + * 默认连接超时时间 + */ + public static final long DEFAULT_CONN_TIME_OUT = 1200; + + /** + * 默认检查频率 + */ + public static final long DEFAULT_PERIOD_CHECK = 3600; + + /** + * 默认初始化延迟检查时间 + */ + public static final long DEFAULT_INIT_DELAY = 1200; + + +} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/DatabaseType.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/DatabaseType.java new file mode 100644 index 000000000..d554c6bc2 --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/DatabaseType.java @@ -0,0 +1,95 @@ +package blade.plugin.sql2o.pool; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * 定义数据库类型 + * @author biezhi + * + */ +public class DatabaseType { + + public final static int UNKNOW = 0; + public final static int ORACLE = 1; + public final static int MYSQL = 2; + public final static int POSTGRESQL = 3; + public final static int SQLSERVER = 4; + public final static int HSQL = 5; + public final static int DB2 = 6; + + public final static String ORACLE_NAME = "ORACLE"; + public final static String MYSQL_NAME = "MYSQL"; + public final static String POSTGRESQL_NAME = "POSTGRESQL"; + public final static String SQLSERVER_NAME = "SQLSERVER"; + public final static String HSQL_NAME = "HSQL"; + public final static String DB2_NAME = "DB2"; + + /** + * 获得数据库类型 + * + * @param conn + * 数据库链接 + * @return int型的数据库类型(如:DatabaseType.ORACLE) + */ + public static int getDbType(Connection conn) { + + String dbName = null; + int dbType = 0; + + try { + dbName = conn.getMetaData().getDatabaseProductName(); + if (dbName.toUpperCase().indexOf(ORACLE_NAME) > -1) { + dbType = ORACLE; + } else if (dbName.toUpperCase().indexOf(MYSQL_NAME) > -1) { + dbType = MYSQL; + } else if (dbName.toUpperCase().indexOf(POSTGRESQL_NAME) > -1) { + dbType = POSTGRESQL; + } else if (dbName.toUpperCase().indexOf(SQLSERVER_NAME) > -1) { + dbType = SQLSERVER; + } else if (dbName.toUpperCase().indexOf(HSQL_NAME) > -1) { + dbType = HSQL; + } else if (dbName.toUpperCase().indexOf(DB2_NAME) > -1) { + dbType = DB2; + } else { + dbType = UNKNOW; + } + + } catch (SQLException e) { + e.printStackTrace(); + } + + return dbType; + } + + /** + * 获得数据库类型 + * + * @param driverName + * 驱动字符串 + * @return int型的数据库类型(如:DatabaseType.ORACLE) + */ + public static int getDbType(String driverName) { + + int dbType = 0; + + if (driverName.toUpperCase().indexOf(ORACLE_NAME) > -1) { + dbType = ORACLE; + } else if (driverName.toUpperCase().indexOf(MYSQL_NAME) > -1) { + dbType = MYSQL; + } else if (driverName.toUpperCase().indexOf(POSTGRESQL_NAME) > -1) { + dbType = POSTGRESQL; + } else if (driverName.toUpperCase().indexOf(SQLSERVER_NAME) > -1) { + dbType = SQLSERVER; + } else if (driverName.toUpperCase().indexOf(HSQL_NAME) > -1) { + dbType = HSQL; + } else if (driverName.toUpperCase().indexOf(DB2_NAME) > -1) { + dbType = DB2; + } else { + dbType = UNKNOW; + } + + return dbType; + } + +} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/InitPoolConfig.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/InitPoolConfig.java new file mode 100644 index 000000000..10ff227b8 --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/InitPoolConfig.java @@ -0,0 +1,23 @@ +package blade.plugin.sql2o.pool; + +import java.util.ArrayList; +import java.util.List; + +/** + * 初始化数据连接池配置 + * @author biezhi + * + */ +public class InitPoolConfig { + + static List poolConfigList; + + static{ + poolConfigList = new ArrayList(); + } + + public static void add(PoolConfig poolConfig){ + poolConfigList.add(poolConfig); + } + +} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java new file mode 100644 index 000000000..b9fa8f1b2 --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java @@ -0,0 +1,218 @@ +package blade.plugin.sql2o.pool; + +/** + * 数据库连接池参数 + * @author biezhi + * + */ +public class PoolConfig { + + /** + * 驱动名称 + */ + private String driverName; + + /** + * 连接地址 + */ + private String url; + + /** + * 用户名 + */ + private String userName; + + /** + * 密码 + */ + private String passWord; + + /** + * 连接测试语句 + */ + private String keepAliveSql; + + /** + * 最小连接数 + */ + private int minConn = Constant.DEFAULT_MIN_CONN; + + /** + * 最大连接数 + */ + private int maxConn = Constant.DEFAULT_MAX_CONN; + + /** + * 初始化时连接数 + */ + private int initConn = Constant.DEFAULT_INIT_CONN; + + /** + * 数据库最大的连接数 + */ + private int maxActiveConn = Constant.DEFAULT_MAX_ACTIVE_CONN; + + /** + * 重复去获得连接的频率 + */ + private long connWaitTime = Constant.DEFAULT_CONN_WAIT_TIME; + + /** + * 连接超时时间,默认20分钟 + */ + private long connTimeOut = Constant.DEFAULT_CONN_TIME_OUT; + + /** + * 是否定时检查连接池 + */ + private boolean isCheakPool = true; + + /** + * 检查频率/秒 + */ + private long periodCheck = Constant.DEFAULT_PERIOD_CHECK; + + /** + * 延迟多少时间后开始 检查/秒 + */ + private long initDelay = Constant.DEFAULT_INIT_DELAY; + + /** + * 数据库连接池的名称 + */ + private String poolName = Constant.DEFAULT_POOL_NAME; + + public PoolConfig() { + // TODO Auto-generated constructor stub + } + + public String getPoolName() { + return poolName; + } + + public void setPoolName(String poolName) { + this.poolName = poolName; + } + + public String getDriverName() { + return driverName; + } + + public void setDriverName(String driverName) { + this.driverName = driverName; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + public int getMinConn() { + return minConn; + } + + public void setMinConn(int minConn) { + this.minConn = minConn; + } + + public int getMaxConn() { + return maxConn; + } + + public void setMaxConn(int maxConn) { + this.maxConn = maxConn; + } + + + public long getConnWaitTime() { + return connWaitTime; + } + + public void setConnWaitTime(long connWaitTime) { + this.connWaitTime = connWaitTime; + } + + + public int getInitConn() { + return initConn; + } + + public void setInitConn(int initConn) { + this.initConn = initConn; + } + + public int getMaxActiveConn() { + return maxActiveConn; + } + + public void setMaxActiveConn(int maxActiveConn) { + this.maxActiveConn = maxActiveConn; + } + + public long getConnTimeOut() { + return connTimeOut; + } + + public void setConnTimeOut(long connTimeOut) { + this.connTimeOut = connTimeOut; + } + + public boolean isCheakPool() { + return isCheakPool; + } + + public void setCheakPool(boolean isCheakPool) { + this.isCheakPool = isCheakPool; + } + + public long getPeriodCheck() { + return periodCheck; + } + + public void setPeriodCheck(long periodCheck) { + this.periodCheck = periodCheck; + } + + public long getInitDelay() { + return initDelay; + } + + public void setInitDelay(long initDelay) { + this.initDelay = initDelay; + } + + public String getKeepAliveSql() { + return keepAliveSql; + } + + public void setKeepAliveSql(String keepAliveSql) { + this.keepAliveSql = keepAliveSql; + } + + @Override + public String toString() { + return "PoolConfig [maxConn=" + maxConn + ", minConn=" + minConn + + ", initConn=" + initConn + ", connTimeOut=" + connTimeOut + + ", keepAliveSql=" + keepAliveSql + ",driverName=" + driverName + ", url=" + + url + ", username=" + userName + ", password=" + passWord + "]"; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/Connection.java b/blade-sql2o/src/main/java/org/sql2o/Connection.java new file mode 100644 index 000000000..4154b21b7 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/Connection.java @@ -0,0 +1,309 @@ +package org.sql2o; + +import org.sql2o.converters.Converter; +import org.sql2o.converters.ConverterException; +import org.sql2o.logging.LocalLoggerFactory; +import org.sql2o.logging.Logger; +import org.sql2o.quirks.Quirks; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.sql2o.converters.Convert.throwIfNull; + +/** + * Represents a connection to the database with a transaction. + */ +public class Connection implements AutoCloseable { + + private final static Logger logger = LocalLoggerFactory.getLogger(Connection.class); + + private java.sql.Connection jdbcConnection; + private Sql2o sql2o; + + private Integer result = null; + private int[] batchResult = null; + private List keys; + private boolean canGetKeys; + + private boolean rollbackOnException = true; + + public boolean isRollbackOnException() { + return rollbackOnException; + } + + public Connection setRollbackOnException(boolean rollbackOnException) { + this.rollbackOnException = rollbackOnException; + return this; + } + + final boolean autoClose; + + Connection(Sql2o sql2o, boolean autoClose) { + + this.autoClose = autoClose; + this.sql2o = sql2o; + createConnection(); + } + + void onException() { + if (isRollbackOnException()) { + rollback(this.autoClose); + } + } + + public java.sql.Connection getJdbcConnection() { + return jdbcConnection; + } + + public Sql2o getSql2o() { + return sql2o; + } + + public Query createQuery(String queryText, String name){ + boolean returnGeneratedKeys = this.sql2o.getQuirks().returnGeneratedKeysByDefault(); + return createQuery(queryText, name, returnGeneratedKeys); + } + + public Query createQuery(String queryText, String name, boolean returnGeneratedKeys){ + + try { + if (jdbcConnection.isClosed()){ + createConnection(); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + + return new Query(this, queryText, name, returnGeneratedKeys); + } + + public Query createQueryWithParams(String queryText, Object... paramValues){ + Query query = createQuery(queryText, null); + boolean destroy = true; + try { + query.withParams(paramValues); + destroy = false; + return query; + } finally { + // instead of re-wrapping exception + // just keep it as-is + // but kill a query + if(destroy) query.close(); + } + } + + public Query createQuery(String queryText){ + return createQuery(queryText, null); + } + + public Query createQuery(String queryText, boolean returnGeneratedKeys) { + return createQuery(queryText, null, returnGeneratedKeys); + } + + public Sql2o rollback(){ + return this.rollback(true).sql2o; + } + + public Connection rollback(boolean closeConnection){ + try { + jdbcConnection.rollback(); + } + catch (SQLException e) { + logger.warn("Could not roll back transaction. message: {}", e); + } + finally { + if(closeConnection) this.closeJdbcConnection(); + } + return this; + } + + public Sql2o commit(){ + return this.commit(true).sql2o; + } + + public Connection commit(boolean closeConnection){ + try { + jdbcConnection.commit(); + } + catch (SQLException e) { + throw new Sql2oException(e); + } + finally { + if(closeConnection) + this.closeJdbcConnection(); + } + return this; + } + + public int getResult(){ + if (this.result == null){ + throw new Sql2oException("It is required to call executeUpdate() method before calling getResult()."); + } + return this.result; + } + + void setResult(int result){ + this.result = result; + } + + public int[] getBatchResult() { + if (this.batchResult == null){ + throw new Sql2oException("It is required to call executeBatch() method before calling getBatchResult()."); + } + return this.batchResult; + } + + void setBatchResult(int[] value) { + this.batchResult = value; + } + + void setKeys(ResultSet rs) throws SQLException { + if (rs == null){ + this.keys = null; + return; + } + this.keys = new ArrayList(); + while(rs.next()){ + this.keys.add(rs.getObject(1)); + } + } + + public Object getKey(){ + if (!this.canGetKeys){ + throw new Sql2oException("Keys where not fetched from database. Please call executeUpdate(true) to fetch keys"); + } + if (this.keys != null && this.keys.size() > 0){ + return keys.get(0); + } + return null; + } + + @SuppressWarnings("unchecked") // need to change Convert + public V getKey(Class returnType){ + final Quirks quirks = this.sql2o.getQuirks(); + Object key = getKey(); + try { + Converter converter = throwIfNull(returnType, quirks.converterOf(returnType)); + return converter.convert(key); + } catch (ConverterException e) { + throw new Sql2oException("Exception occurred while converting value from database to type " + returnType.toString(), e); + } + } + + public Object[] getKeys(){ + if (!this.canGetKeys){ + throw new Sql2oException("Keys where not fetched from database. Please set the returnGeneratedKeys parameter in the createQuery() method to enable fetching of generated keys."); + } + if (this.keys != null){ + return this.keys.toArray(); + } + return null; + } + + @SuppressWarnings("unchecked") // need to change Convert + public List getKeys(Class returnType) { + final Quirks quirks = sql2o.getQuirks(); + if (!this.canGetKeys) { + throw new Sql2oException("Keys where not fetched from database. Please set the returnGeneratedKeys parameter in the createQuery() method to enable fetching of generated keys."); + } + + if (this.keys != null) { + try { + Converter converter = throwIfNull(returnType, quirks.converterOf(returnType)); + + List convertedKeys = new ArrayList(this.keys.size()); + + for (Object key : this.keys) { + convertedKeys.add(converter.convert(key)); + } + + return convertedKeys; + } + catch (ConverterException e) { + throw new Sql2oException("Exception occurred while converting value from database to type " + returnType.toString(), e); + } + } + + return null; + } + + void setCanGetKeys(boolean canGetKeys) { + this.canGetKeys = canGetKeys; + } + + private final Set statements = new HashSet(); + + void registerStatement(Statement statement){ + statements.add(statement); + } + void removeStatement(Statement statement){ + statements.remove(statement); + } + + public void close() { + boolean connectionIsClosed; + try { + connectionIsClosed = jdbcConnection.isClosed(); + } catch (SQLException e) { + throw new Sql2oException("Sql2o encountered a problem while trying to determine whether the connection is closed.", e); + } + + if (!connectionIsClosed) { + + for (Statement statement : statements) { + try { + getSql2o().getQuirks().closeStatement(statement); + } catch (Throwable e) { + logger.warn("Could not close statement.", e); + } + } + statements.clear(); + + boolean autoCommit = false; + try { + autoCommit = jdbcConnection.getAutoCommit(); + } + catch (SQLException e) { + logger.warn("Could not determine connection auto commit mode.", e); + } + + // if in transaction, rollback, otherwise just close + if (autoCommit) { + this.closeJdbcConnection(); + } + else { + this.rollback(true); + } + } + } + + private void createConnection(){ + try{ + if(this.getSql2o().getDataSource() == null && this.getSql2o().getConnectionPool() == null) + throw new Sql2oException("DataSource can't be null"); + else if(this.getSql2o().getDataSource() != null) { + this.jdbcConnection = this.getSql2o().getDataSource().getConnection(); + }else if(this.getSql2o().getConnectionPool() != null) { //Get Connection Object from PooledConnection + this.jdbcConnection = this.getSql2o().getConnectionPool().getConnection(); + } + } + catch(Exception ex){ + throw new RuntimeException(String.format("Could not aquire a connection from DataSource - ", ex.getMessage()), ex); + } + } + + private void closeJdbcConnection() { + try { + jdbcConnection.close(); + } + catch (SQLException e) { + logger.warn("Could not close connection. message: {}", e); + } + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactory.java b/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactory.java new file mode 100644 index 000000000..8a73a72a8 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactory.java @@ -0,0 +1,187 @@ +package org.sql2o; + +import org.sql2o.converters.Converter; +import org.sql2o.converters.ConverterException; +import org.sql2o.quirks.Quirks; +import org.sql2o.reflection.Pojo; +import org.sql2o.reflection.PojoMetadata; +import org.sql2o.reflection.Setter; +import org.sql2o.tools.AbstractCache; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; + + +public class DefaultResultSetHandlerFactory implements ResultSetHandlerFactory { + private final PojoMetadata metadata; + private final Quirks quirks; + + public DefaultResultSetHandlerFactory(PojoMetadata pojoMetadata, Quirks quirks) { + this.metadata = pojoMetadata; + this.quirks = quirks; + } + + @SuppressWarnings("unchecked") + private static Setter getSetter( + final Quirks quirks, + final String propertyPath, + final PojoMetadata metadata) { + int index = propertyPath.indexOf('.'); + if (index <= 0) { + // Simple path - fast way + final Setter setter = metadata.getPropertySetterIfExists(propertyPath); + // behavior change: do not throw if POJO contains less properties + if (setter == null) return null; + final Converter converter = quirks.converterOf(setter.getType()); + // setter without converter + if (converter == null) return setter; + return new Setter() { + public void setProperty(Object obj, Object value) { + try { + setter.setProperty(obj, converter.convert(value)); + } catch (ConverterException e) { + throw new Sql2oException("Error trying to convert column " + propertyPath + " to type " + setter.getType(), e); + } + } + + public Class getType() { + return setter.getType(); + } + }; + } + // dot path - long way + // i'm too lazy now to rewrite this case so I just call old unoptimized code... + // TODO: rewrite, get rid of POJO class + return new Setter() { + public void setProperty(Object obj, Object value) { + Pojo pojo = new Pojo(metadata, metadata.isCaseSensitive(), obj); + pojo.setProperty(propertyPath, value, quirks); + } + + public Class getType() { + // doesn't used anyway + return Object.class; + } + }; + } + + private static class Key { + final String stringKey; + final DefaultResultSetHandlerFactory f; + + DefaultResultSetHandlerFactory factory(){ + return f; + } + + private PojoMetadata getMetadata() { + return f.metadata; + } + + private Quirks getQuirksMode() { + return f.quirks; + } + + private Key(String stringKey, DefaultResultSetHandlerFactory f) { + this.stringKey = stringKey; + this.f = f; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Key key = (Key) o; + + return f.metadata.equals(key.getMetadata()) + && f.quirks == key.getQuirksMode() + && stringKey.equals(key.stringKey); + + } + + @Override + public int hashCode() { + int result = f.metadata.hashCode(); + result = 31 * result + f.quirks.hashCode(); + result = 31 * result + stringKey.hashCode(); + return result; + } + } + + + private static final AbstractCache + c = new AbstractCache() { + @Override + protected ResultSetHandler evaluate(Key key, ResultSetMetaData param) { + try { + return key.factory().newResultSetHandler0(param); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + }; + + @SuppressWarnings("unchecked") + public ResultSetHandler newResultSetHandler(final ResultSetMetaData meta) throws SQLException { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 1; i <= meta.getColumnCount(); i++) { + stringBuilder.append(quirks.getColumnName(meta,i)).append("\n"); + } + return c.get(new Key(stringBuilder.toString(), this),meta); + + } + + + @SuppressWarnings("unchecked") + private ResultSetHandler newResultSetHandler0(final ResultSetMetaData meta) throws SQLException { + final Setter[] setters; + final Converter converter; + final boolean useExecuteScalar; + //TODO: it's possible to cache converter/setters + // cache key is ResultSetMetadata + Bean type + + converter = quirks.converterOf(metadata.getType()); + final int columnCount = meta.getColumnCount(); + + setters = new Setter[columnCount + 1]; // setters[0] is always null + for (int i = 1; i <= columnCount; i++) { + String colName = quirks.getColumnName(meta, i); + + setters[i] = getSetter(quirks, colName, metadata); + + // If more than 1 column is fetched (we cannot fall back to executeScalar), + // and the setter doesn't exist, throw exception. + if (this.metadata.throwOnMappingFailure && setters[i] == null && columnCount > 1) { + throw new Sql2oException("Could not map " + colName + " to any property."); + } + } + /** + * Fallback to executeScalar if converter exists, + * we're selecting 1 column, and no property setter exists for the column. + */ + useExecuteScalar = converter != null && columnCount == 1 && setters[1] == null; + return new ResultSetHandler() { + @SuppressWarnings("unchecked") + public T handle(ResultSet resultSet) throws SQLException { + if (useExecuteScalar) { + try { + return (T) converter.convert(quirks.getRSVal(resultSet, 1)); + } catch (ConverterException e) { + throw new Sql2oException("Error occurred while converting value from database to type " + metadata.getType(), e); + } + } + + // otherwise we want executeAndFetch with object mapping + Object pojo = metadata.getObjectConstructor().newInstance(); + for (int colIdx = 1; colIdx <= columnCount; colIdx++) { + Setter setter = setters[colIdx]; + if (setter == null) continue; + setter.setProperty(pojo, quirks.getRSVal(resultSet, colIdx)); + } + + return (T) pojo; + } + }; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactoryBuilder.java b/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactoryBuilder.java new file mode 100644 index 000000000..5f97fd9ed --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactoryBuilder.java @@ -0,0 +1,65 @@ +package org.sql2o; + +import org.sql2o.quirks.Quirks; +import org.sql2o.reflection.PojoMetadata; + +import java.util.Map; + +public class DefaultResultSetHandlerFactoryBuilder implements ResultSetHandlerFactoryBuilder { + private boolean caseSensitive; + private boolean autoDeriveColumnNames; + private boolean throwOnMappingError; + private Map columnMappings; + private Quirks quirks; + + public boolean isCaseSensitive() { + return caseSensitive; + } + + public void setCaseSensitive(boolean caseSensitive) { + this.caseSensitive = caseSensitive; + } + + public boolean isAutoDeriveColumnNames() { + return autoDeriveColumnNames; + } + + public void setAutoDeriveColumnNames(boolean autoDeriveColumnNames) { + this.autoDeriveColumnNames = autoDeriveColumnNames; + } + + @Override + public boolean isThrowOnMappingError() { + return throwOnMappingError; + } + + @Override + public void throwOnMappingError(boolean throwOnMappingError) { + this.throwOnMappingError = throwOnMappingError; + } + + public Map getColumnMappings() { + return columnMappings; + } + + public void setColumnMappings(Map columnMappings) { + this.columnMappings = columnMappings; + } + + public Quirks getQuirks() { + return quirks; + } + + public void setQuirks(Quirks quirks) { + this.quirks = quirks; + } + + + + @SuppressWarnings("unchecked") + public ResultSetHandlerFactory newFactory(Class clazz) { + PojoMetadata pojoMetadata = new PojoMetadata(clazz, caseSensitive, autoDeriveColumnNames, columnMappings, throwOnMappingError); + return new DefaultResultSetHandlerFactory(pojoMetadata, quirks); + } + +} diff --git a/blade-sql2o/src/main/java/org/sql2o/DelegatingResultSetHandler.java b/blade-sql2o/src/main/java/org/sql2o/DelegatingResultSetHandler.java new file mode 100644 index 000000000..6d46011b5 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/DelegatingResultSetHandler.java @@ -0,0 +1,23 @@ +package org.sql2o; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * User: dimzon + * Date: 4/7/14 + * Time: 11:06 PM + */ +public class DelegatingResultSetHandler implements ResultSetHandler { + private volatile ResultSetHandler inner = null; + private final ResultSetHandlerFactory factory; + + public DelegatingResultSetHandler(ResultSetHandlerFactory factory) { + this.factory = factory; + } + + public E handle(ResultSet resultSet) throws SQLException { + if(inner==null) inner = factory.newResultSetHandler(resultSet.getMetaData()); + return inner.handle(resultSet); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/GenericDatasource.java b/blade-sql2o/src/main/java/org/sql2o/GenericDatasource.java new file mode 100644 index 000000000..db73f8ebb --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/GenericDatasource.java @@ -0,0 +1,98 @@ +package org.sql2o; + +import javax.sql.DataSource; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.Properties; + +/** + * Used internally by sql2o, if the {@link Sql2o#Sql2o(String, String, String)} constructor overload. + */ +public class GenericDatasource implements DataSource { + + private final String url; + private final Properties properties; + + public GenericDatasource(String url, String user, String password) { + + if (!url.startsWith("jdbc")){ + url = "jdbc:" + url; + } + + this.url = url; + this.properties = new Properties(); + set(properties,user,password); + } + + private void set(Properties info, String user, String password) { + if (user != null) { + info.put("user", user); + } + if (password != null) { + info.put("password", password); + } + } + + public GenericDatasource(String url, Properties properties) { + + if (!url.startsWith("jdbc")){ + url = "jdbc:" + url; + } + + this.url = url; + this.properties = properties; + } + + public String getUrl() { + return url; + } + + public String getUser() { + return properties.getProperty("user"); + } + + public String getPassword() { + return properties.getProperty("password"); + } + + public Connection getConnection() throws SQLException { + return DriverManager.getConnection(this.getUrl(), properties); + } + + public Connection getConnection(String username, String password) throws SQLException { + Properties info = new Properties(this.properties); + set(info,username,password); + return DriverManager.getConnection(this.getUrl(), info); + } + + public PrintWriter getLogWriter() throws SQLException { + return DriverManager.getLogWriter(); + } + + public void setLogWriter(PrintWriter printWriter) throws SQLException { + DriverManager.setLogWriter(printWriter); + } + + public void setLoginTimeout(int i) throws SQLException { + DriverManager.setLoginTimeout(i); + } + + public int getLoginTimeout() throws SQLException { + return DriverManager.getLoginTimeout(); + } + + public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { + throw new SQLFeatureNotSupportedException(); + } + + public T unwrap(Class tClass) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + public boolean isWrapperFor(Class aClass) throws SQLException { + return false; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java b/blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java new file mode 100644 index 000000000..c09ae8ad7 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java @@ -0,0 +1,42 @@ +package org.sql2o; + +import org.sql2o.logging.LocalLoggerFactory; +import org.sql2o.logging.Logger; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.sql.DataSource; + +/** + * Created by lars on 16.09.2014. + */ +public class JndiDataSource { + + private final static Logger logger = LocalLoggerFactory.getLogger(JndiDataSource.class); + + static DataSource getJndiDatasource(String jndiLookup) { + Context ctx = null; + DataSource datasource = null; + + try { + ctx = new InitialContext(); + datasource = (DataSource) ctx.lookup(jndiLookup); + } + catch (NamingException e) { + throw new RuntimeException(e); + } + finally { + if (ctx != null) { + try { + ctx.close(); + } + catch (Throwable e) { + logger.warn("error closing context", e); + } + } + } + + return datasource; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/PojoResultSetIterator.java b/blade-sql2o/src/main/java/org/sql2o/PojoResultSetIterator.java new file mode 100644 index 000000000..b9bf695ba --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/PojoResultSetIterator.java @@ -0,0 +1,38 @@ +package org.sql2o; + +import org.sql2o.quirks.Quirks; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * Iterator for a {@link java.sql.ResultSet}. Tricky part here is getting {@link #hasNext()} + * to work properly, meaning it can be called multiple times without calling {@link #next()}. + * + * @author aldenquimby@gmail.com + */ +public class PojoResultSetIterator extends ResultSetIteratorBase { + private ResultSetHandler handler; + + @SuppressWarnings("unchecked") + public PojoResultSetIterator(ResultSet rs, boolean isCaseSensitive, Quirks quirks, ResultSetHandlerFactory factory) { + super(rs, isCaseSensitive, quirks); + try { + this.handler = factory.newResultSetHandler(rs.getMetaData()); + } catch (SQLException e) { + throw new Sql2oException("Database error: " + e.getMessage(), e); + } + } + + public PojoResultSetIterator(ResultSet rs, boolean isCaseSensitive, Quirks quirks, ResultSetHandler handler) { + super(rs, isCaseSensitive, quirks); + this.handler = handler; + } + + @Override + protected T readNext() throws SQLException { + return handler.handle(rs); + + } + +} diff --git a/blade-sql2o/src/main/java/org/sql2o/Query.java b/blade-sql2o/src/main/java/org/sql2o/Query.java new file mode 100644 index 000000000..8ea0e298b --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/Query.java @@ -0,0 +1,722 @@ +package org.sql2o; + +import static org.sql2o.converters.Convert.throwIfNull; + +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.sql2o.converters.Converter; +import org.sql2o.converters.ConverterException; +import org.sql2o.data.LazyTable; +import org.sql2o.data.Row; +import org.sql2o.data.Table; +import org.sql2o.data.TableResultSetIterator; +import org.sql2o.logging.LocalLoggerFactory; +import org.sql2o.logging.Logger; +import org.sql2o.quirks.Quirks; +import org.sql2o.reflection.PojoIntrospector; + +/** + * Represents a sql2o statement. With sql2o, all statements are instances of the Query class. + */ +@SuppressWarnings("UnusedDeclaration") +public class Query implements AutoCloseable { + + private final static Logger logger = LocalLoggerFactory.getLogger(Query.class); + + private Connection connection; + private Map caseSensitiveColumnMappings; + private Map columnMappings; + private final PreparedStatement statement; + private boolean caseSensitive; + private boolean autoDeriveColumnNames; + private boolean throwOnMappingFailure = true; + private String name; + private boolean returnGeneratedKeys; + private final Map> paramNameToIdxMap; + private final Set addedParameters; + private final String parsedQuery; + + private ResultSetHandlerFactoryBuilder resultSetHandlerFactoryBuilder; + + @Override + public String toString() { + return parsedQuery; + } + + public Query(Connection connection, String queryText, String name, boolean returnGeneratedKeys) { + this.connection = connection; + this.name = name; + this.returnGeneratedKeys = returnGeneratedKeys; + this.setColumnMappings(connection.getSql2o().getDefaultColumnMappings()); + this.caseSensitive = connection.getSql2o().isDefaultCaseSensitive(); + + paramNameToIdxMap = new HashMap>(); + addedParameters = new HashSet(); + + parsedQuery = connection.getSql2o().getQuirks().getSqlParameterParsingStrategy().parseSql(queryText, paramNameToIdxMap); + try { + if (returnGeneratedKeys) { + statement = connection.getJdbcConnection().prepareStatement(parsedQuery, Statement.RETURN_GENERATED_KEYS); + } else { + statement = connection.getJdbcConnection().prepareStatement(parsedQuery); + } + } catch(SQLException ex) { + throw new Sql2oException(String.format("Error preparing statement - %s", ex.getMessage()), ex); + } + connection.registerStatement(statement); + + } + + // ------------------------------------------------ + // ------------- Getter/Setters ------------------- + // ------------------------------------------------ + + public boolean isCaseSensitive() { + return caseSensitive; + } + + public Query setCaseSensitive(boolean caseSensitive) { + this.caseSensitive = caseSensitive; + return this; + } + + public boolean isAutoDeriveColumnNames() { + return autoDeriveColumnNames; + } + + public Query setAutoDeriveColumnNames(boolean autoDeriveColumnNames) { + this.autoDeriveColumnNames = autoDeriveColumnNames; + return this; + } + + public Query throwOnMappingFailure(boolean throwOnMappingFailure) { + this.throwOnMappingFailure = throwOnMappingFailure; + return this; + } + + public boolean isThrowOnMappingFailure() { + return throwOnMappingFailure; + } + + public Connection getConnection(){ + return this.connection; + } + + public String getName() { + return name; + } + + public ResultSetHandlerFactoryBuilder getResultSetHandlerFactoryBuilder() { + if (resultSetHandlerFactoryBuilder == null) { + resultSetHandlerFactoryBuilder = new DefaultResultSetHandlerFactoryBuilder(); + } + return resultSetHandlerFactoryBuilder; + } + + public void setResultSetHandlerFactoryBuilder(ResultSetHandlerFactoryBuilder resultSetHandlerFactoryBuilder) { + this.resultSetHandlerFactoryBuilder = resultSetHandlerFactoryBuilder; + } + + public Map> getParamNameToIdxMap() { + return paramNameToIdxMap; + } + + // ------------------------------------------------ + // ------------- Add Parameters ------------------- + // ------------------------------------------------ + + private void addParameterInternal(String name, ParameterSetter parameterSetter) { + addedParameters.add(name); + for (int paramIdx : this.getParamNameToIdxMap().get(name)) { + try { + parameterSetter.setParameter(paramIdx); + } catch (SQLException e) { + throw new RuntimeException(String.format("Error adding parameter '%s' - %s", name, e.getMessage()), e); + } + } + } + + @SuppressWarnings("unchecked") + private Object convertParameter(Object value) { + if (value == null) { + return null; + } + Converter converter = getQuirks().converterOf(value.getClass()); + if (converter == null) { + // let's try to add parameter AS IS + return value; + } + return converter.toDatabaseParam(value); + } + + public Query addParameter(String name, Class parameterClass, T value){ + //TODO: must cover most of types: BigDecimal,Boolean,SmallInt,Double,Float,byte[] + if(InputStream.class.isAssignableFrom(parameterClass)) + return addParameter(name, (InputStream)value); + if(Integer.class==parameterClass) + return addParameter(name, (Integer)value); + if(Long.class==parameterClass) + return addParameter(name, (Long)value); + if(String.class==parameterClass) + return addParameter(name, (String)value); + if(Timestamp.class==parameterClass) + return addParameter(name, (Timestamp)value); + if(Time.class==parameterClass) + return addParameter(name, (Time)value); + + + final Object convertedValue = convertParameter(value); + + addParameterInternal(name, new ParameterSetter() { + public void setParameter(int paramIdx) throws SQLException { + getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, convertedValue); + } + }); + + return this; + } + + public Query withParams(Object... paramValues){ + int i=0; + for (Object paramValue : paramValues) { + addParameter("p" + (++i), paramValue); + } + return this; + } + + @SuppressWarnings("unchecked") + public Query addParameter(String name, Object value) { + return value == null + ? addParameter(name, Object.class, value) + : addParameter(name, + (Class) value.getClass(), + value); + } + + public Query addParameter(String name, final InputStream value){ + addParameterInternal(name, new ParameterSetter() { + public void setParameter(int paramIdx) throws SQLException { + getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); + } + }); + + return this; + } + + public Query addParameter(String name, final int value){ + addParameterInternal(name, new ParameterSetter() { + public void setParameter(int paramIdx) throws SQLException { + getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); + } + }); + + return this; + } + + public Query addParameter(String name, final Integer value) { + addParameterInternal(name, new ParameterSetter() { + public void setParameter(int paramIdx) throws SQLException { + getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); + } + }); + + return this; + } + + public Query addParameter(String name, final long value){ + addParameterInternal(name, new ParameterSetter() { + public void setParameter(int paramIdx) throws SQLException { + getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); + } + }); + + return this; + } + + public Query addParameter(String name, final Long value){ + addParameterInternal(name, new ParameterSetter() { + public void setParameter(int paramIdx) throws SQLException { + getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); + } + }); + + return this; + } + + public Query addParameter(String name, final String value) { + addParameterInternal(name, new ParameterSetter() { + public void setParameter(int paramIdx) throws SQLException { + getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); + } + }); + + return this; + } + + public Query addParameter(String name, final Timestamp value){ + addParameterInternal(name, new ParameterSetter() { + public void setParameter(int paramIdx) throws SQLException { + getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); + } + }); + + return this; + } + + public Query addParameter(String name, final Time value) { + addParameterInternal(name, new ParameterSetter() { + public void setParameter(int paramIdx) throws SQLException { + getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); + } + }); + + return this; + } + + public Query bind(final Object pojo) { + Class clazz = pojo.getClass(); + Map propertyMap = PojoIntrospector.readableProperties(clazz); + for (PojoIntrospector.ReadableProperty property : propertyMap.values()) { + if (addedParameters.contains( property.name )) continue; + try { + if( this.getParamNameToIdxMap().containsKey(property.name)) { + + @SuppressWarnings("unchecked") + final Class type = (Class) property.type; + this.addParameter(property.name, type, property.get(pojo)); + } + } + catch(IllegalArgumentException ex) { + logger.debug("Ignoring Illegal Arguments", ex); + } + catch(IllegalAccessException ex) { + throw new RuntimeException(ex); + } + catch(InvocationTargetException ex) { + throw new RuntimeException(ex); + } + } + return this; + } + + public void close() { + connection.removeStatement(statement); + try { + this.getQuirks().closeStatement(statement); + } catch (Throwable ex){ + logger.warn("Could not close statement.", ex); + } + } + + // ------------------------------------------------ + // -------------------- Execute ------------------- + // ------------------------------------------------ + + /** + * Iterable {@link java.sql.ResultSet} that wraps {@link PojoResultSetIterator}. + */ + private abstract class ResultSetIterableBase implements ResultSetIterable { + private long start; + private long afterExecQuery; + protected ResultSet rs; + + boolean autoCloseConnection = false; + + public ResultSetIterableBase() { + try { + start = System.currentTimeMillis(); + rs = statement.executeQuery(); + afterExecQuery = System.currentTimeMillis(); + } + catch (SQLException ex) { + throw new Sql2oException("Database error: " + ex.getMessage(), ex); + } + } + + @Override + public void close() { + try { + if (rs != null) { + rs.close(); + + // log the query + long afterClose = System.currentTimeMillis(); + logger.debug("total: {} ms, execution: {} ms, reading and parsing: {} ms; executed [{}]", new Object[]{ + afterClose - start, + afterExecQuery-start, + afterClose - afterExecQuery, + name + }); + + rs = null; + } + } + catch (SQLException ex) { + throw new Sql2oException("Error closing ResultSet.", ex); + } + finally { + if (this.isAutoCloseConnection()){ + connection.close(); + } else { + closeConnectionIfNecessary(); + } + } + } + + @Override + public boolean isAutoCloseConnection() { + return this.autoCloseConnection; + } + + @Override + public void setAutoCloseConnection(boolean autoCloseConnection) { + this.autoCloseConnection = autoCloseConnection; + } + } + + /** + * Read a collection lazily. Generally speaking, this should only be used if you are reading MANY + * results and keeping them all in a Collection would cause memory issues. You MUST call + * {@link org.sql2o.ResultSetIterable#close()} when you are done iterating. + * + * @param returnType type of each row + * @return iterable results + */ + public ResultSetIterable executeAndFetchLazy(final Class returnType) { + final ResultSetHandlerFactory resultSetHandlerFactory = newResultSetHandlerFactory(returnType); + return executeAndFetchLazy(resultSetHandlerFactory); + } + + private ResultSetHandlerFactory newResultSetHandlerFactory(Class returnType) { + final Quirks quirks = getConnection().getSql2o().getQuirks(); + ResultSetHandlerFactoryBuilder builder = getResultSetHandlerFactoryBuilder(); + if(builder==null) builder=new DefaultResultSetHandlerFactoryBuilder(); + builder.setAutoDeriveColumnNames(this.autoDeriveColumnNames); + builder.setCaseSensitive(this.caseSensitive); + builder.setColumnMappings(this.columnMappings); + builder.setQuirks(quirks); + builder.throwOnMappingError(this.throwOnMappingFailure); + return builder.newFactory(returnType); + } + + /** + * Read a collection lazily. Generally speaking, this should only be used if you are reading MANY + * results and keeping them all in a Collection would cause memory issues. You MUST call + * {@link org.sql2o.ResultSetIterable#close()} when you are done iterating. + * + * @param resultSetHandlerFactory factory to provide ResultSetHandler + * @return iterable results + */ + public ResultSetIterable executeAndFetchLazy(final ResultSetHandlerFactory resultSetHandlerFactory) { + final Quirks quirks = getConnection().getSql2o().getQuirks(); + return new ResultSetIterableBase() { + public Iterator iterator() { + return new PojoResultSetIterator(rs, isCaseSensitive(), quirks, resultSetHandlerFactory); + } + }; + } + + /** + * Read a collection lazily. Generally speaking, this should only be used if you are reading MANY + * results and keeping them all in a Collection would cause memory issues. You MUST call + * {@link org.sql2o.ResultSetIterable#close()} when you are done iterating. + * + * @param resultSetHandler ResultSetHandler + * @return iterable results + */ + public ResultSetIterable executeAndFetchLazy(final ResultSetHandler resultSetHandler) { + final ResultSetHandlerFactory factory = newResultSetHandlerFactory(resultSetHandler); + return executeAndFetchLazy(factory); + } + + private static ResultSetHandlerFactory newResultSetHandlerFactory(final ResultSetHandler resultSetHandler) { + return new ResultSetHandlerFactory() { + public ResultSetHandler newResultSetHandler(ResultSetMetaData resultSetMetaData) throws SQLException { + return resultSetHandler; + } + }; + } + + public List executeAndFetch(Class returnType){ + return executeAndFetch(newResultSetHandlerFactory(returnType)); + } + + public List executeAndFetch(ResultSetHandler resultSetHandler){ + return executeAndFetch(newResultSetHandlerFactory(resultSetHandler)); + } + + public List executeAndFetch(ResultSetHandlerFactory factory){ + List list = new ArrayList(); + + // if sql2o moves to java 7 at some point, this could be much cleaner using try-with-resources + ResultSetIterable iterable = null; + try { + iterable = executeAndFetchLazy(factory); + for (T item : iterable) { + list.add(item); + } + } + finally { + if (iterable != null) { + iterable.close(); + } + } + + return list; + } + + public T executeAndFetchFirst(Class returnType){ + return executeAndFetchFirst(newResultSetHandlerFactory(returnType)); + } + + public T executeAndFetchFirst(ResultSetHandler resultSetHandler){ + return executeAndFetchFirst(newResultSetHandlerFactory(resultSetHandler)); + } + + public T executeAndFetchFirst(ResultSetHandlerFactory resultSetHandlerFactory){ + // if sql2o moves to java 7 at some point, this could be much cleaner using try-with-resources + ResultSetIterable iterable = null; + try { + iterable = executeAndFetchLazy(resultSetHandlerFactory); + Iterator iterator = iterable.iterator(); + return iterator.hasNext() ? iterator.next() : null; + } + finally { + if (iterable != null) { + iterable.close(); + } + } + } + + public LazyTable executeAndFetchTableLazy() { + final LazyTable lt = new LazyTable(); + + lt.setRows(new ResultSetIterableBase() { + public Iterator iterator() { + return new TableResultSetIterator(rs, isCaseSensitive(), getConnection().getSql2o().getQuirks(), lt); + } + }); + + return lt; + } + + public Table executeAndFetchTable() { + LazyTable lt = executeAndFetchTableLazy(); + List rows = new ArrayList(); + try { + for (Row item : lt.rows()) { + rows.add(item); + } + } + finally { + lt.close(); + } + // lt==null is always false + return new Table(lt.getName(), rows, lt.columns()); + } + + public Connection executeUpdate(){ + long start = System.currentTimeMillis(); + try{ + this.connection.setResult(statement.executeUpdate()); + this.connection.setKeys(this.returnGeneratedKeys ? statement.getGeneratedKeys() : null); + connection.setCanGetKeys(this.returnGeneratedKeys); + } + catch(SQLException ex){ + this.connection.onException(); + throw new Sql2oException("Error in executeUpdate, " + ex.getMessage(), ex); + } + finally { + closeConnectionIfNecessary(); + } + + long end = System.currentTimeMillis(); + logger.debug("total: {} ms; executed update [{}]", new Object[]{ + end - start, + this.getName() == null ? "No name" : this.getName() + }); + + return this.connection; + } + + public Object executeScalar(){ + long start = System.currentTimeMillis(); + try { + ResultSet rs = this.statement.executeQuery(); + if (rs.next()){ + Object o = getQuirks().getRSVal(rs, 1); + long end = System.currentTimeMillis(); + logger.debug("total: {} ms; executed scalar [{}]", new Object[]{ + end - start, + this.getName() == null ? "No name" : this.getName() + }); + return o; + } + else{ + return null; + } + + } + catch (SQLException e) { + this.connection.onException(); + throw new Sql2oException("Database error occurred while running executeScalar: " + e.getMessage(), e); + } + finally{ + closeConnectionIfNecessary(); + } + + } + + private Quirks getQuirks() { + return this.connection.getSql2o().getQuirks(); + } + + public V executeScalar(Class returnType){ + try { + Converter converter; + //noinspection unchecked + converter = throwIfNull(returnType, getQuirks().converterOf(returnType)); + //noinspection unchecked + return executeScalar(converter); + } catch (ConverterException e) { + throw new Sql2oException("Error occured while converting value from database to type " + returnType, e); + } + } + + public V executeScalar(Converter converter){ + try { + //noinspection unchecked + return converter.convert(executeScalar()); + } catch (ConverterException e) { + throw new Sql2oException("Error occured while converting value from database", e); + } + } + + + + public List executeScalarList(final Class returnType){ + return executeAndFetch(newScalarResultSetHandler(returnType)); + } + + private ResultSetHandler newScalarResultSetHandler(final Class returnType) { + final Quirks quirks = getQuirks(); + try { + final Converter converter = throwIfNull(returnType, quirks.converterOf(returnType)); + return new ResultSetHandler() { + public T handle(ResultSet resultSet) throws SQLException { + Object value = quirks.getRSVal(resultSet, 1); + try { + return (converter.convert(value)); + } catch (ConverterException e) { + throw new Sql2oException("Error occurred while converting value from database to type " + returnType, e); + } + } + }; + } catch (ConverterException e) { + throw new Sql2oException("Can't get converter for type " + returnType, e); + } + } + + /************** batch stuff *******************/ + + public Query addToBatch(){ + try { + statement.addBatch(); + } catch (SQLException e) { + throw new Sql2oException("Error while adding statement to batch", e); + } + + return this; + } + + public Connection executeBatch() throws Sql2oException { + long start = System.currentTimeMillis(); + try { + connection.setBatchResult(statement.executeBatch()); + try { + connection.setKeys(this.returnGeneratedKeys ? statement.getGeneratedKeys() : null); + connection.setCanGetKeys(this.returnGeneratedKeys); + } catch (SQLException sqlex) { + throw new Sql2oException("Error while trying to fetch generated keys from database. If you are not expecting any generated keys, fix this error by setting the fetchGeneratedKeys parameter in the createQuery() method to 'false'", sqlex); + } + } + catch (Throwable e) { + this.connection.onException(); + throw new Sql2oException("Error while executing batch operation: " + e.getMessage(), e); + } + finally { + closeConnectionIfNecessary(); + } + + long end = System.currentTimeMillis(); + logger.debug("total: {} ms; executed batch [{}]", new Object[]{ + end - start, + this.getName() == null ? "No name" : this.getName() + }); + + return this.connection; + } + + /*********** column mapping ****************/ + + public Map getColumnMappings() { + if (this.isCaseSensitive()){ + return this.caseSensitiveColumnMappings; + } + else{ + return this.columnMappings; + } + } + + public Query setColumnMappings(Map mappings){ + + this.caseSensitiveColumnMappings = new HashMap(); + this.columnMappings = new HashMap(); + + for (Map.Entry entry : mappings.entrySet()){ + this.caseSensitiveColumnMappings.put(entry.getKey(), entry.getValue()); + this.columnMappings.put(entry.getKey().toLowerCase(), entry.getValue().toLowerCase()); + } + + return this; + } + + public Query addColumnMapping(String columnName, String propertyName){ + this.caseSensitiveColumnMappings.put(columnName, propertyName); + this.columnMappings.put(columnName.toLowerCase(), propertyName.toLowerCase()); + + return this; + } + + /************** private stuff ***************/ + + private void closeConnectionIfNecessary(){ + try{ + if (connection.autoClose){ + connection.close(); + } + } + catch (Exception ex){ + throw new Sql2oException("Error while attempting to close connection", ex); + } + } + + private interface ParameterSetter{ + void setParameter(int paramIdx) throws SQLException; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/ResultSetHandler.java b/blade-sql2o/src/main/java/org/sql2o/ResultSetHandler.java new file mode 100644 index 000000000..1e6d3fd5e --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/ResultSetHandler.java @@ -0,0 +1,13 @@ +package org.sql2o; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * User: dimzon + * Date: 4/7/14 + * Time: 12:01 AM + */ +public interface ResultSetHandler { + T handle(ResultSet resultSet) throws SQLException; +} diff --git a/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactory.java b/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactory.java new file mode 100644 index 000000000..7620551f0 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactory.java @@ -0,0 +1,13 @@ +package org.sql2o; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; + +/** + * User: dimzon + * Date: 4/7/14 + * Time: 12:02 AM + */ +public interface ResultSetHandlerFactory { + ResultSetHandler newResultSetHandler(ResultSetMetaData resultSetMetaData) throws SQLException; +} diff --git a/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactoryBuilder.java b/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactoryBuilder.java new file mode 100644 index 000000000..9d07ad545 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactoryBuilder.java @@ -0,0 +1,36 @@ +package org.sql2o; + +import org.sql2o.quirks.Quirks; + +import java.util.Map; + +/** + * Created with IntelliJ IDEA. + * User: dimzon + * Date: 4/7/14 + * Time: 4:28 AM + * To change this template use File | Settings | File Templates. + */ +public interface ResultSetHandlerFactoryBuilder { + boolean isCaseSensitive(); + + void setCaseSensitive(boolean caseSensitive); + + boolean isAutoDeriveColumnNames(); + + void setAutoDeriveColumnNames(boolean autoDeriveColumnNames); + + boolean isThrowOnMappingError(); + + void throwOnMappingError(boolean throwOnMappingError); + + Map getColumnMappings(); + + void setColumnMappings(Map columnMappings); + + Quirks getQuirks(); + + void setQuirks(Quirks quirksMode); + + ResultSetHandlerFactory newFactory(Class clazz); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/ResultSetIterable.java b/blade-sql2o/src/main/java/org/sql2o/ResultSetIterable.java new file mode 100644 index 000000000..4be7b76bd --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/ResultSetIterable.java @@ -0,0 +1,15 @@ +package org.sql2o; + +/** + * Iterable {@link java.sql.ResultSet}. Needs to be closeable, because allowing manual + * iteration means it's impossible to know when to close the ResultSet and Connection. + * + * @author aldenquimby@gmail.com + */ +public interface ResultSetIterable extends Iterable, AutoCloseable { + // override close to not throw + void close(); + + boolean isAutoCloseConnection(); + void setAutoCloseConnection(boolean autoCloseConnection); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/ResultSetIteratorBase.java b/blade-sql2o/src/main/java/org/sql2o/ResultSetIteratorBase.java new file mode 100644 index 000000000..0d1c1d156 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/ResultSetIteratorBase.java @@ -0,0 +1,107 @@ +package org.sql2o; + +import org.sql2o.quirks.Quirks; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Iterator for a {@link java.sql.ResultSet}. Tricky part here is getting {@link #hasNext()} + * to work properly, meaning it can be called multiple times without calling {@link #next()}. + * + * @author aldenquimby@gmail.com + */ +public abstract class ResultSetIteratorBase implements Iterator { + // fields needed to read result set + protected ResultSet rs; + protected boolean isCaseSensitive; + protected Quirks quirks; + protected ResultSetMetaData meta; + + public ResultSetIteratorBase(ResultSet rs, boolean isCaseSensitive, Quirks quirks) { + this.rs = rs; + this.isCaseSensitive = isCaseSensitive; + this.quirks = quirks; + try { + meta = rs.getMetaData(); + } + catch(SQLException ex) { + throw new Sql2oException("Database error: " + ex.getMessage(), ex); + } + } + + // fields needed to properly implement + private ResultSetValue next; // keep track of next item in case hasNext() is called multiple times + private boolean resultSetFinished; // used to note when result set exhausted + + public boolean hasNext() { + // check if we already fetched next item + if (next != null) { + return true; + } + + // check if result set already finished + if (resultSetFinished) { + return false; + } + + // now fetch next item + next = safeReadNext(); + + // check if we got something + if (next != null) { + return true; + } + + // no more items + resultSetFinished = true; + + return false; + } + + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + + T result = next.value; + + next = null; + + return result; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + private ResultSetValue safeReadNext() + { + try { + if (!rs.next()) + return null; + + return new ResultSetValue(readNext()); + } + catch (SQLException ex) { + throw new Sql2oException("Database error: " + ex.getMessage(), ex); + } + } + + protected abstract T readNext() throws SQLException; + + protected String getColumnName(int colIdx) throws SQLException { + return quirks.getColumnName(meta, colIdx); + } + + private final class ResultSetValue { + public final T value; + + public ResultSetValue(T value){ + this.value = value; + } + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/Sql2o.java b/blade-sql2o/src/main/java/org/sql2o/Sql2o.java new file mode 100644 index 000000000..e9747e179 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/Sql2o.java @@ -0,0 +1,378 @@ +package org.sql2o; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +import javax.sql.ConnectionPoolDataSource; +import javax.sql.DataSource; + +import org.sql2o.quirks.Quirks; +import org.sql2o.quirks.QuirksDetector; + +import blade.plugin.sql2o.pool.ConnectionPool; + +/** + * Sql2o is the main class for the sql2o library. + *

+ * An Sql2o instance represents a way of connecting to one specific database. + * To create a new instance, one need to specify either jdbc-url, username and password for the database or a data source. + *

+ * Internally the Sql2o instance uses a data source to create jdbc connections to the database. If url, username and password + * was specified in the constructor, a simple data source is created, which works as a simple wrapper around the jdbc + * driver. + *

+ * Some jdbc implementations have quirks, therefore it may be necessary to use a constructor with the quirks parameter. + * When quirks are specified, Sql2o will use workarounds to avoid these quirks. + * @author Lars Aaberg + */ +public class Sql2o { + final Quirks quirks; + private final DataSource dataSource; + private final ConnectionPool connectionPool; + private Map defaultColumnMappings; + private boolean defaultCaseSensitive; + + public Sql2o(String jndiLookup) { + this(JndiDataSource.getJndiDatasource(jndiLookup)); + } + + /** + * Creates a new instance of the Sql2o class. Internally this constructor will create a {@link GenericDatasource}, + * and call the {@link Sql2o#Sql2o(javax.sql.DataSource)} constructor which takes a DataSource as parameter. + * @param url JDBC database url + * @param user database username + * @param pass database password + */ + public Sql2o(String url, String user, String pass){ + this(url, user, pass, QuirksDetector.forURL(url)); + } + + /** + * Created a new instance of the Sql2o class. Internally this constructor will create a {@link GenericDatasource}, + * and call the {@link Sql2o#Sql2o(javax.sql.DataSource)} constructor which takes a DataSource as parameter. + * @param url JDBC database url + * @param user database username + * @param pass database password + * @param quirks {@link org.sql2o.quirks.Quirks} allows sql2o to work around known quirks and issues in different JDBC drivers. + */ + public Sql2o(String url, String user, String pass, Quirks quirks) { + this(new GenericDatasource(url, user, pass), quirks); + } + + /** + * Creates a new instance of the Sql2o class, which uses the given DataSource to acquire connections to the database. + * @param dataSource The DataSource Sql2o uses to acquire connections to the database. + */ + public Sql2o(DataSource dataSource) { + this(dataSource, QuirksDetector.forObject(dataSource)); + } + + /** + * Creates a new instance of the Sql2o class, which uses the given DataSource to acquire connections to the database. + * @param dataSource The DataSource Sql2o uses to acquire connections to the database. + * @param quirks {@link org.sql2o.quirks.Quirks} allows sql2o to work around known quirks and issues in different JDBC drivers. + */ + public Sql2o(DataSource dataSource, Quirks quirks){ + this.dataSource = dataSource; + this.quirks=quirks; + this.defaultColumnMappings = new HashMap(); + this.connectionPool = null; + } + + /** + * extended by sean + * Creates a new instance of the Sql2o class, which uses the given ConnectionPoolDataSource to acquire connections to the database. + * @param poolDataSource The DataSource Sql2o uses to acquire connections to the database. + */ + public Sql2o(ConnectionPoolDataSource poolDataSource) { + this(poolDataSource, null); + } + + /** + * * extended by sean + * Creates a new instance of the Sql2o class, which uses the given ConnectionPoolDataSource to acquire connections to the database. + * @param poolDataSource The DataSource Sql2o uses to acquire connections to the database. + * @param quirksMode @{link QuirksMode} allows sql2o to work around known quirks and issues in different JDBC drivers. + */ + public Sql2o(ConnectionPoolDataSource poolDataSource, Quirks quirks){ + this(null, poolDataSource, quirks); + } + + /** + * extended by sean + * Add ConnectionPoolDataSource, get connection from pool. + * @param dataSource + * @param poolDataSource + * @param quirksMode + */ + private Sql2o(DataSource dataSource, ConnectionPoolDataSource poolDataSource, Quirks quirks) { + this.dataSource = dataSource; + this.quirks = quirks; + this.connectionPool = null; + this.defaultColumnMappings = new HashMap(); + } + + /** + * extended by sean + * Add ConnectionPoolDataSource, get connection from pool. + * @param dataSource + * @param poolDataSource + * @param quirksMode + */ + public Sql2o(ConnectionPool connectionPool) { + this(connectionPool, QuirksDetector.forObject(connectionPool)); + } + + /** + * extended by sean + * Add ConnectionPoolDataSource, get connection from pool. + * @param dataSource + * @param poolDataSource + * @param quirksMode + */ + public Sql2o(ConnectionPool connectionPool, Quirks quirks) { + this.connectionPool = connectionPool; + this.quirks = quirks; + this.dataSource = null; + this.defaultColumnMappings = new HashMap(); + } + + public Quirks getQuirks() { + return quirks; + } + + /** + * Gets the DataSource that Sql2o uses internally to acquire database connections. + * @return The DataSource instance + */ + public DataSource getDataSource() { + return dataSource; + } + + /** + * 返回连接池 + * @return + */ + public ConnectionPool getConnectionPool() { + return connectionPool; + } + + /** + * Gets the default column mappings Map. column mappings added to this Map are always available when Sql2o attempts + * to map between result sets and object instances. + * @return The {@link Map} instance, which Sql2o internally uses to map column names with property + * names. + */ + public Map getDefaultColumnMappings() { + return defaultColumnMappings; + } + + /** + * Sets the default column mappings Map. + * @param defaultColumnMappings A {@link Map} instance Sql2o uses internally to map between column names and + * property names. + */ + public void setDefaultColumnMappings(Map defaultColumnMappings) { + this.defaultColumnMappings = defaultColumnMappings; + } + + /** + * Gets value indicating if this instance of Sql2o is case sensitive when mapping between columns names and property + * names. + * @return + */ + public boolean isDefaultCaseSensitive() { + return defaultCaseSensitive; + } + + /** + * Sets a value indicating if this instance of Sql2o is case sensitive when mapping between columns names and property + * names. This should almost always be false, because most relational databases are not case sensitive. + * @param defaultCaseSensitive + */ + public void setDefaultCaseSensitive(boolean defaultCaseSensitive) { + this.defaultCaseSensitive = defaultCaseSensitive; + } + + /** + * Opens a connection to the database + * @return instance of the {@link org.sql2o.Connection} class. + */ + public Connection open() { + return new Connection(this, false); + } + + /** + * Invokes the run method on the {@link org.sql2o.StatementRunnableWithResult} instance. This method guarantees that + * the connection is closed properly, when either the run method completes or if an exception occurs. + * @param runnable + * @param argument + * @param + * @return + */ + @SuppressWarnings("unchecked") + public V withConnection(StatementRunnableWithResult runnable, Object argument) { + Connection connection = null; + try{ + connection = open(); + return (V)runnable.run(connection, argument); + } catch (Throwable t) { + throw new Sql2oException("An error occurred while executing StatementRunnable", t); + } finally { + if (connection != null) { + connection.close(); + } + } + } + + /** + * Invokes the run method on the {@link org.sql2o.StatementRunnableWithResult} instance. This method guarantees that + * the connection is closed properly, when either the run method completes or if an exception occurs. + * @param runnable + * @param + * @return + */ + public V withConnection(StatementRunnableWithResult runnable) { + return withConnection(runnable, null); + } + + /** + * Invokes the run method on the {@link org.sql2o.StatementRunnableWithResult} instance. This method guarantees that + * the connection is closed properly, when either the run method completes or if an exception occurs. + * @param runnable + */ + public void withConnection(StatementRunnable runnable) { + withConnection(runnable, null); + } + + /** + * Invokes the run method on the {@link org.sql2o.StatementRunnableWithResult} instance. This method guarantees that + * the connection is closed properly, when either the run method completes or if an exception occurs. + * @param runnable + * @param argument + */ + public void withConnection(StatementRunnable runnable, Object argument) { + Connection connection = null; + try{ + connection = open(); + + runnable.run(connection, argument); + } catch (Throwable t) { + throw new Sql2oException("An error occurred while executing StatementRunnable", t); + } finally{ + if (connection != null) { + connection.close(); + } + } + } + + /** + * Begins a transaction with the given isolation level. Every statement executed on the return {@link Connection} + * instance, will be executed in the transaction. It is very important to always call either the {@link org.sql2o.Connection#commit()} + * method or the {@link org.sql2o.Connection#rollback()} method to close the transaction. Use proper try-catch logic. + * @param isolationLevel the isolation level of the transaction + * @return the {@link Connection} instance to use to run statements in the transaction. + */ + public Connection beginTransaction(int isolationLevel){ + + Connection connection = new Connection(this, false); + + try { + connection.getJdbcConnection().setAutoCommit(false); + connection.getJdbcConnection().setTransactionIsolation(isolationLevel); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + return connection; + } + + /** + * Begins a transaction with isolation level {@link java.sql.Connection#TRANSACTION_READ_COMMITTED}. Every statement executed on the return {@link Connection} + * instance, will be executed in the transaction. It is very important to always call either the {@link org.sql2o.Connection#commit()} + * method or the {@link org.sql2o.Connection#rollback()} method to close the transaction. Use proper try-catch logic. + * @return the {@link Connection} instance to use to run statements in the transaction. + */ + public Connection beginTransaction(){ + return this.beginTransaction(java.sql.Connection.TRANSACTION_READ_COMMITTED); + } + + /** + * Calls the {@link StatementRunnable#run(Connection, Object)} method on the {@link StatementRunnable} parameter. All statements + * run on the {@link Connection} instance in the {@link StatementRunnable#run(Connection, Object) run} method will be + * executed in a transaction. The transaction will automatically be committed if the {@link StatementRunnable#run(Connection, Object) run} + * method finishes without throwing an exception. If an exception is thrown within the {@link StatementRunnable#run(Connection, Object) run} method, + * the transaction will automatically be rolled back. + * + * The isolation level of the transaction will be set to {@link java.sql.Connection#TRANSACTION_READ_COMMITTED} + * @param runnable The {@link StatementRunnable} instance. + */ + public void runInTransaction(StatementRunnable runnable){ + runInTransaction(runnable, null); + } + + /** + * Calls the {@link StatementRunnable#run(Connection, Object)} method on the {@link StatementRunnable} parameter. All statements + * run on the {@link Connection} instance in the {@link StatementRunnable#run(Connection, Object) run} method will be + * executed in a transaction. The transaction will automatically be committed if the {@link StatementRunnable#run(Connection, Object) run} + * method finishes without throwing an exception. If an exception is thrown within the {@link StatementRunnable#run(Connection, Object) run} method, + * the transaction will automatically be rolled back. + * + * The isolation level of the transaction will be set to {@link java.sql.Connection#TRANSACTION_READ_COMMITTED} + * @param runnable The {@link StatementRunnable} instance. + * @param argument An argument which will be forwarded to the {@link StatementRunnable#run(Connection, Object) run} method + */ + public void runInTransaction(StatementRunnable runnable, Object argument){ + runInTransaction(runnable, argument, java.sql.Connection.TRANSACTION_READ_COMMITTED); + } + + /** + * Calls the {@link StatementRunnable#run(Connection, Object)} method on the {@link StatementRunnable} parameter. All statements + * run on the {@link Connection} instance in the {@link StatementRunnable#run(Connection, Object) run} method will be + * executed in a transaction. The transaction will automatically be committed if the {@link StatementRunnable#run(Connection, Object) run} + * method finishes without throwing an exception. If an exception is thrown within the {@link StatementRunnable#run(Connection, Object) run} method, + * the transaction will automatically be rolled back. + * @param runnable The {@link StatementRunnable} instance. + * @param argument An argument which will be forwarded to the {@link StatementRunnable#run(Connection, Object) run} method + * @param isolationLevel The isolation level of the transaction + */ + public void runInTransaction(StatementRunnable runnable, Object argument, int isolationLevel){ + + Connection connection = this.beginTransaction(isolationLevel); + connection.setRollbackOnException(false); + + try { + runnable.run(connection, argument); + } catch (Throwable throwable) { + connection.rollback(); + throw new Sql2oException("An error occurred while executing StatementRunnable. Transaction is rolled back.", throwable); + } + connection.commit(); + } + + public V runInTransaction(StatementRunnableWithResult runnableWithResult){ + return runInTransaction(runnableWithResult, null); + } + + public V runInTransaction(StatementRunnableWithResult runnableWithResult, Object argument){ + return runInTransaction(runnableWithResult, argument, java.sql.Connection.TRANSACTION_READ_COMMITTED); + } + + @SuppressWarnings("unchecked") + public V runInTransaction(StatementRunnableWithResult runnableWithResult, Object argument, int isolationLevel){ + Connection connection = this.beginTransaction(isolationLevel); + Object result; + + try{ + result = runnableWithResult.run(connection, argument); + } catch (Throwable throwable) { + connection.rollback(); + throw new Sql2oException("An error occurred while executing StatementRunnableWithResult. Transaction rolled back.", throwable); + } + + connection.commit(); + return (V)result; + } + +} diff --git a/blade-sql2o/src/main/java/org/sql2o/Sql2oException.java b/blade-sql2o/src/main/java/org/sql2o/Sql2oException.java new file mode 100644 index 000000000..643fe64d3 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/Sql2oException.java @@ -0,0 +1,22 @@ +package org.sql2o; + +/** + * Represents an exception thrown by Sql2o. + */ +public class Sql2oException extends RuntimeException { + + public Sql2oException() { + } + + public Sql2oException(String message) { + super(message); + } + + public Sql2oException(String message, Throwable cause) { + super(message, cause); + } + + public Sql2oException(Throwable cause) { + super(cause); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/StatementRunnable.java b/blade-sql2o/src/main/java/org/sql2o/StatementRunnable.java new file mode 100644 index 000000000..83665e38c --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/StatementRunnable.java @@ -0,0 +1,11 @@ +package org.sql2o; + +/** + * Represents a method with a {@link Connection} and an optional argument. Implementations of this interface be used as + * a parameter to one of the {@link Sql2o#runInTransaction(StatementRunnable) Sql2o.runInTransaction} overloads, to run + * code safely in a transaction. + */ +public interface StatementRunnable { + + void run(Connection connection, Object argument) throws Throwable; +} diff --git a/blade-sql2o/src/main/java/org/sql2o/StatementRunnableWithResult.java b/blade-sql2o/src/main/java/org/sql2o/StatementRunnableWithResult.java new file mode 100644 index 000000000..9997f42d3 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/StatementRunnableWithResult.java @@ -0,0 +1,11 @@ +package org.sql2o; + +/** + * Represents a method with a {@link Connection} and an optional argument. Implementations of this interface be used as + * a parameter to one of the {@link Sql2o#runInTransaction(StatementRunnableWithResult)} Sql2o.runInTransaction} overloads, + * to run code safely in a transaction. + */ +public interface StatementRunnableWithResult { + + Object run(Connection connection, Object argument) throws Throwable; +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/AbstractDateConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/AbstractDateConverter.java new file mode 100644 index 000000000..04922438e --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/AbstractDateConverter.java @@ -0,0 +1,44 @@ +package org.sql2o.converters; + +import java.sql.Timestamp; +import java.util.Date; + +/** + * Used by sql2o to convert a value from the database into a {@link Date}. + */ +public abstract class AbstractDateConverter implements Converter { + private final Class classOfDate; + protected AbstractDateConverter(Class classOfDate) { + this.classOfDate = classOfDate; + } + + protected abstract E fromMilliseconds(long millisecond); + + @SuppressWarnings("unchecked") + public E convert(Object val) throws ConverterException { + if (val == null){ + return null; + } + + if (classOfDate.isInstance(val)){ + return (E) val; + } + + if(val instanceof java.util.Date){ + return fromMilliseconds(((Date) val).getTime()); + } + + if (val instanceof Number){ + return fromMilliseconds(((Number) val).longValue()); + } + + throw new ConverterException("Cannot convert type " + val.getClass().toString() + " to java.util.Date"); + } + + public Timestamp toDatabaseParam(Date val) { + if(val==null) return null; + return (val instanceof Timestamp) + ? (Timestamp) val + :new Timestamp(val.getTime()); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/BigDecimalConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/BigDecimalConverter.java new file mode 100644 index 000000000..7dd2a464a --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/BigDecimalConverter.java @@ -0,0 +1,33 @@ +package org.sql2o.converters; + +import java.math.BigDecimal; + +/** + * Used by sql2o to convert a value from the database into a {@link BigDecimal}. + */ +public class BigDecimalConverter extends NumberConverter{ + + public BigDecimalConverter() { + super(false); + } + + @Override + protected BigDecimal convertNumberValue(Number val) { + if (val instanceof BigDecimal){ + return (BigDecimal)val; + } + else{ + return BigDecimal.valueOf(val.doubleValue()); + } + } + + @Override + protected BigDecimal convertStringValue(String val) { + return BigDecimal.valueOf(Double.parseDouble(val)); + } + + @Override + protected String getTypeDescription() { + return BigDecimal.class.toString(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/BooleanConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/BooleanConverter.java new file mode 100644 index 000000000..dd8116e97 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/BooleanConverter.java @@ -0,0 +1,37 @@ +package org.sql2o.converters; + +/** + * Created with IntelliJ IDEA. + * User: lars + * Date: 6/1/13 + * Time: 10:54 PM + * To change this template use File | Settings | File Templates. + */ +public class BooleanConverter extends ConverterBase { + + public Boolean convert(Object val) throws ConverterException { + if (val == null) return null; + + if (val instanceof Boolean) { + return (Boolean) val; + } + + if (val instanceof Number) { + return ((Number)val).intValue() != 0; + } + + if (val instanceof Character) { + // cast to char is required to compile with java 8 + char c = (Character) val; + return c == 'Y' || c == 'T' || c == 'J'; + } + + if (val instanceof String) { + String strVal = ((String)val).trim(); + return "Y".equalsIgnoreCase(strVal) || "YES".equalsIgnoreCase(strVal) || "TRUE".equalsIgnoreCase(strVal) || + "T".equalsIgnoreCase(strVal) || "J".equalsIgnoreCase(strVal); + } + + throw new ConverterException("Don't know how to convert type " + val.getClass().getName() + " to " + Boolean.class.getName()); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java new file mode 100644 index 000000000..6edce531e --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java @@ -0,0 +1,54 @@ +package org.sql2o.converters; + +import org.sql2o.tools.IOUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.sql.Blob; +import java.sql.SQLException; + +/** + * User: lars + * Date: 6/13/13 + * Time: 11:36 PM + */ +public class ByteArrayConverter extends ConverterBase { + + public byte[] convert(Object val) throws ConverterException { + if (val == null) return null; + + if (val instanceof Blob) { + Blob b = (Blob)val; + InputStream stream=null; + try { + try { + stream = b.getBinaryStream(); + return IOUtils.toByteArray(stream); + } finally { + if(stream!=null) { + try { + stream.close(); + } catch (Throwable ignore){ + // ignore stream.close errors + } + } + try { + b.free(); + } catch (Throwable ignore){ + // ignore blob.free errors + } + } + } catch (SQLException e) { + throw new ConverterException("Error converting Blob to byte[]", e); + } catch (IOException e) { + throw new ConverterException("Error converting Blob to byte[]", e); + } + } + + if (val instanceof byte[]){ + return (byte[])val; + } + + throw new RuntimeException("could not convert " + val.getClass().getName() + " to byte[]"); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ByteConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/ByteConverter.java new file mode 100644 index 000000000..7b32677dc --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/ByteConverter.java @@ -0,0 +1,26 @@ +package org.sql2o.converters; + +/** + * Used by sql2o to convert a value from the database into a {@link Byte}. + */ +public class ByteConverter extends NumberConverter { + + public ByteConverter(boolean primitive) { + super(primitive); + } + + @Override + protected Byte convertNumberValue(Number val) { + return val.byteValue(); + } + + @Override + protected Byte convertStringValue(String val) { + return Byte.parseByte(val); + } + + @Override + protected String getTypeDescription() { + return Byte.class.toString(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/Convert.java b/blade-sql2o/src/main/java/org/sql2o/converters/Convert.java new file mode 100644 index 000000000..13544f775 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/Convert.java @@ -0,0 +1,158 @@ +package org.sql2o.converters; + +import org.joda.time.DateTime; +import org.joda.time.LocalTime; +import org.sql2o.converters.joda.DateTimeConverter; +import org.sql2o.converters.joda.LocalTimeConverter; +import org.sql2o.tools.FeatureDetector; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.math.BigDecimal; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.UUID; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Static class used to register new converters. + * Also used internally by sql2o to lookup a converter. + */ +@SuppressWarnings("unchecked") +public class Convert { + + private static final ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock(); + private static final ReentrantReadWriteLock.ReadLock rl = rrwl.readLock(); + private static volatile EnumConverterFactory registeredEnumConverterFactory = new DefaultEnumConverterFactory(); + private static Map, Converter> registeredConverters = new HashMap, Converter>(); + + private static void processProvider(ConvertersProvider convertersProvider) { + convertersProvider.fill(registeredConverters); + } + + private static void fillDefaults(Map, Converter> mapToFill) { + mapToFill.put(Integer.class, new IntegerConverter(false)); + mapToFill.put(int.class, new IntegerConverter(true)); + + mapToFill.put(Double.class, new DoubleConverter(false)); + mapToFill.put(double.class, new DoubleConverter(true)); + + mapToFill.put(Float.class, new FloatConverter(false)); + mapToFill.put(float.class, new FloatConverter(true)); + + mapToFill.put(Long.class, new LongConverter(false)); + mapToFill.put(long.class, new LongConverter(true)); + + mapToFill.put(Short.class, new ShortConverter(false)); + mapToFill.put(short.class, new ShortConverter(true)); + + mapToFill.put(Byte.class, new ByteConverter(false)); + mapToFill.put(byte.class, new ByteConverter(true)); + + mapToFill.put(BigDecimal.class, new BigDecimalConverter()); + + mapToFill.put(String.class, new StringConverter()); + + mapToFill.put(java.util.Date.class,DateConverter.instance); + mapToFill.put(java.sql.Date.class, + new AbstractDateConverter(java.sql.Date.class) { + @Override + protected java.sql.Date fromMilliseconds(long millisecond) { + return new java.sql.Date(millisecond); + } + + @Override + public Object toDatabaseParam(Date val) { + return null; + } + }); + mapToFill.put(java.sql.Time.class, + new AbstractDateConverter(java.sql.Time.class) { + @Override + protected java.sql.Time fromMilliseconds(long millisecond) { + return new java.sql.Time(millisecond); + } + + @Override + public Object toDatabaseParam(Time val) { + return null; + } + }); + mapToFill.put(java.sql.Timestamp.class, + new AbstractDateConverter(java.sql.Timestamp.class) { + @Override + protected java.sql.Timestamp fromMilliseconds(long millisecond) { + return new java.sql.Timestamp(millisecond); + } + + @Override + public Object toDatabaseParam(Timestamp val) { + return null; + } + }); + + BooleanConverter booleanConverter = new BooleanConverter(); + mapToFill.put(Boolean.class, booleanConverter); + mapToFill.put(boolean.class, booleanConverter); + + ByteArrayConverter byteArrayConverter = new ByteArrayConverter(); + //it's impossible to cast Byte[].class <-> byte[].class + // and I'm too lazy to implement converter for Byte[].class + // since it's really doesn't wide-used + // otherwise someone already detect this error + //mapToFill.put(Byte[].class, byteArrayConverter); + mapToFill.put(byte[].class, byteArrayConverter); + + InputStreamConverter inputStreamConverter = new InputStreamConverter(); + mapToFill.put(InputStream.class, inputStreamConverter); + mapToFill.put(ByteArrayInputStream.class, inputStreamConverter); + + mapToFill.put(UUID.class, new UUIDConverter()); + + if (FeatureDetector.isJodaTimeAvailable()) { + mapToFill.put(DateTime.class, new DateTimeConverter()); + mapToFill.put(LocalTime.class, new LocalTimeConverter()); + } + } + + + static { + fillDefaults(registeredConverters); + ServiceLoader loader = ServiceLoader.load(ConvertersProvider.class); + for (ConvertersProvider provider : loader) { + processProvider(provider); + } + } + + public static Converter throwIfNull(Class clazz, Converter converter) throws ConverterException { + if (converter == null) { + throw new ConverterException("No converter registered for class: " + clazz.getName()); + } + return converter; + } + + public static Converter getConverterIfExists(Class clazz) { + Converter c; + rl.lock(); + try { + c = registeredConverters.get(clazz); + } finally { + rl.unlock(); + } + if (c != null) return c; + + if (clazz.isEnum()) { + return registeredEnumConverterFactory.newConverter((Class) clazz); + } + return null; + } + + public static void registerEnumConverter(EnumConverterFactory enumConverterFactory) { + if (enumConverterFactory == null) throw new IllegalArgumentException(); + registeredEnumConverterFactory = enumConverterFactory; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/Converter.java b/blade-sql2o/src/main/java/org/sql2o/converters/Converter.java new file mode 100644 index 000000000..fb05a9ab6 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/Converter.java @@ -0,0 +1,17 @@ +package org.sql2o.converters; + +/** + * Represents a converter. + */ +public interface Converter { + + /** + * Conversion from SQL to Java. + */ + T convert(Object val) throws ConverterException; + + /** + * Conversion from Java to SQL. + */ + Object toDatabaseParam(T val); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ConverterBase.java b/blade-sql2o/src/main/java/org/sql2o/converters/ConverterBase.java new file mode 100644 index 000000000..91443dccb --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/ConverterBase.java @@ -0,0 +1,12 @@ +package org.sql2o.converters; + +/** + * @author aldenquimby@gmail.com + * @since 4/6/14 + */ +abstract class ConverterBase implements Converter { + + public Object toDatabaseParam(T val) { + return val; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ConverterException.java b/blade-sql2o/src/main/java/org/sql2o/converters/ConverterException.java new file mode 100644 index 000000000..8cfceb864 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/ConverterException.java @@ -0,0 +1,15 @@ +package org.sql2o.converters; + +/** + * Represents an exception thrown from a converter. + */ +public class ConverterException extends Exception{ + + public ConverterException(String message) { + super(message); + } + + public ConverterException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ConvertersProvider.java b/blade-sql2o/src/main/java/org/sql2o/converters/ConvertersProvider.java new file mode 100644 index 000000000..e21213fb9 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/ConvertersProvider.java @@ -0,0 +1,14 @@ +package org.sql2o.converters; + +import org.sql2o.Sql2oException; + +import java.util.Map; + +/** + * User: dimzon + * Date: 4/24/14 + * Time: 12:53 AM + */ +public interface ConvertersProvider { + void fill(Map,Converter> mapToFill); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/DateConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/DateConverter.java new file mode 100644 index 000000000..9a8d773f6 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/DateConverter.java @@ -0,0 +1,19 @@ +package org.sql2o.converters; + +import java.util.Date; + +/** + * Used by sql2o to convert a value from the database into a {@link Date}. + */ +public class DateConverter extends AbstractDateConverter { + public static final DateConverter instance = new DateConverter(); + + public DateConverter() { + super(Date.class); + } + + @Override + protected Date fromMilliseconds(long millisecond) { + return new Date(millisecond); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/DefaultEnumConverterFactory.java b/blade-sql2o/src/main/java/org/sql2o/converters/DefaultEnumConverterFactory.java new file mode 100644 index 000000000..34b426a39 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/DefaultEnumConverterFactory.java @@ -0,0 +1,32 @@ +package org.sql2o.converters; + +/** + * Default implementation of {@link EnumConverterFactory}, + * used by sql2o to convert a value from the database into an {@link Enum}. + */ +public class DefaultEnumConverterFactory implements EnumConverterFactory { + public Converter newConverter(final Class enumType) { + return new Converter() { + @SuppressWarnings("unchecked") + public E convert(Object val) throws ConverterException { + if (val == null) { + return null; + } + try { + if (val instanceof String){ + return (E)Enum.valueOf(enumType, val.toString()); + } else if (val instanceof Number){ + return enumType.getEnumConstants()[((Number)val).intValue()]; + } + } catch (Throwable t) { + throw new ConverterException("Error converting value '" + val.toString() + "' to " + enumType.getName(), t); + } + throw new ConverterException("Cannot convert type '" + val.getClass().getName() + "' to an Enum"); + } + + public Object toDatabaseParam(Enum val) { + return val.toString(); + } + }; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/DoubleConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/DoubleConverter.java new file mode 100644 index 000000000..5a3688577 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/DoubleConverter.java @@ -0,0 +1,26 @@ +package org.sql2o.converters; + +/** + * Used by sql2o to convert a value from the database into a {@link Double}. + */ +public class DoubleConverter extends NumberConverter { + + public DoubleConverter(boolean primitive) { + super(primitive); + } + + @Override + protected Double convertNumberValue(Number val) { + return val.doubleValue(); + } + + @Override + protected Double convertStringValue(String val) { + return Double.parseDouble(val); + } + + @Override + protected String getTypeDescription() { + return Double.class.toString(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/EnumConverterFactory.java b/blade-sql2o/src/main/java/org/sql2o/converters/EnumConverterFactory.java new file mode 100644 index 000000000..76da53d00 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/EnumConverterFactory.java @@ -0,0 +1,8 @@ +package org.sql2o.converters; + +/** + * Used by sql2o to convert a value from the database into an {@link Enum}. + */ +public interface EnumConverterFactory { + Converter newConverter(Class enumClass); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/FloatConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/FloatConverter.java new file mode 100644 index 000000000..1dea719a7 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/FloatConverter.java @@ -0,0 +1,26 @@ +package org.sql2o.converters; + +/** + * Used by sql2o to convert a value from the database into a {@link Float}. + */ +public class FloatConverter extends NumberConverter { + + public FloatConverter(boolean primitive) { + super(primitive); + } + + @Override + protected Float convertNumberValue(Number val) { + return val.floatValue(); + } + + @Override + protected Float convertStringValue(String val) { + return Float.parseFloat(val); + } + + @Override + protected String getTypeDescription() { + return Float.class.toString(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/InputStreamConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/InputStreamConverter.java new file mode 100644 index 000000000..daf388cf3 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/InputStreamConverter.java @@ -0,0 +1,22 @@ +package org.sql2o.converters; + +import java.io.ByteArrayInputStream; + +/** + * Created with IntelliJ IDEA. + * User: lars + * Date: 6/13/13 + * Time: 11:40 PM + * To change this template use File | Settings | File Templates. + */ +public class InputStreamConverter extends ConverterBase { + public ByteArrayInputStream convert(Object val) throws ConverterException { + if (val == null) return null; + + try { + return new ByteArrayInputStream( new ByteArrayConverter().convert(val) ); + } catch( ConverterException e) { + throw new ConverterException("Error converting Blob to InputSteam"); + } + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/IntegerConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/IntegerConverter.java new file mode 100644 index 000000000..6f24d4c1c --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/IntegerConverter.java @@ -0,0 +1,26 @@ +package org.sql2o.converters; + +/** + * Used by sql2o to convert a value from the database into an {@link Integer}. + */ +public class IntegerConverter extends NumberConverter{ + + public IntegerConverter(boolean primitive) { + super(primitive); + } + + @Override + protected Integer convertNumberValue(Number val) { + return val.intValue(); + } + + @Override + protected Integer convertStringValue(String val) { + return Integer.parseInt(val); + } + + @Override + protected String getTypeDescription() { + return Integer.class.toString(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/LongConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/LongConverter.java new file mode 100644 index 000000000..d5b210a5f --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/LongConverter.java @@ -0,0 +1,26 @@ +package org.sql2o.converters; + +/** + * Used by sql2o to convert a value from the database into a {@link Long}. + */ +public class LongConverter extends NumberConverter { + + public LongConverter(boolean primitive) { + super(primitive); + } + + @Override + protected Long convertNumberValue(Number val) { + return val.longValue(); + } + + @Override + protected Long convertStringValue(String val) { + return Long.parseLong(val); + } + + @Override + protected String getTypeDescription() { + return Long.class.toString(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/NumberConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/NumberConverter.java new file mode 100644 index 000000000..a20f023ff --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/NumberConverter.java @@ -0,0 +1,47 @@ +package org.sql2o.converters; + +/** + * Base class for numeric converters. + */ +public abstract class NumberConverter extends ConverterBase { + + private boolean isPrimitive; + + public NumberConverter(boolean primitive) { + isPrimitive = primitive; + } + + public V convert(Object val) { + if (val == null) { + return isPrimitive ? convertNumberValue(0) : null; + } + + // val.getClass().isPrimitive() is ALWAYS false + // since boxing (i.e. Object val=(int)1;) + // changes type from Integet.TYPE to Integer.class + // learn 2 java :) + + else if (/*val.getClass().isPrimitive() || */val instanceof Number ) { + return convertNumberValue((Number)val); + } + else if (val instanceof String){ + String stringVal = ((String)val).trim(); + stringVal = stringVal.isEmpty() ? null : stringVal; + + if (stringVal == null) { + return isPrimitive ? convertNumberValue(0) : null; + } + + return convertStringValue(stringVal); + } + else{ + throw new IllegalArgumentException("Cannot convert type " + val.getClass().toString() + " to " + getTypeDescription()); + } + } + + protected abstract V convertNumberValue(Number val); + + protected abstract V convertStringValue(String val); + + protected abstract String getTypeDescription(); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ShortConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/ShortConverter.java new file mode 100644 index 000000000..468136303 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/ShortConverter.java @@ -0,0 +1,26 @@ +package org.sql2o.converters; + +/** + * Used by sql2o to convert a value from the database into a {@link Short}. + */ +public class ShortConverter extends NumberConverter { + + public ShortConverter(boolean primitive) { + super(primitive); + } + + @Override + protected Short convertNumberValue(Number val) { + return val.shortValue(); + } + + @Override + protected Short convertStringValue(String val) { + return Short.parseShort(val); + } + + @Override + protected String getTypeDescription() { + return Short.class.toString(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java new file mode 100644 index 000000000..3a23d965f --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java @@ -0,0 +1,57 @@ +package org.sql2o.converters; + +import org.sql2o.tools.IOUtils; + +import java.io.IOException; +import java.io.Reader; +import java.sql.Clob; +import java.sql.SQLException; + +/** + * Used by sql2o to convert a value from the database into a {@link String}. + */ +public class StringConverter extends ConverterBase { + + public String convert(Object val) throws ConverterException { + if (val == null){ + return null; + } + + if (val instanceof Clob) { + Clob clobVal = (Clob)val; + try + { + try { + return clobVal.getSubString(1, (int)clobVal.length()); + } catch (SQLException e) { + throw new ConverterException("error converting clob to String", e); + } + } finally { + try { + clobVal.free(); + } catch (Throwable ignore) { + //ignore + } + } + } + + if(val instanceof Reader){ + Reader reader = (Reader) val; + try { + try { + return IOUtils.toString(reader); + } catch (IOException e) { + throw new ConverterException("error converting reader to String", e); + } + } finally { + try { + reader.close(); + } catch (Throwable ignore) { + // ignore + } + } + } + + return val.toString().trim(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/UUIDConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/UUIDConverter.java new file mode 100644 index 000000000..8ad6c4c77 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/UUIDConverter.java @@ -0,0 +1,25 @@ +package org.sql2o.converters; + +import java.util.UUID; + +/** + * Used by sql2o to convert a value from the database into a {@link UUID}. + */ +public class UUIDConverter extends ConverterBase { + public UUID convert(Object val) throws ConverterException { + if (val == null){ + return null; + } + + if (val instanceof UUID){ + return (UUID)val; + } + + if(val instanceof String){ + return UUID.fromString((String) val); + } + + throw new ConverterException("Cannot convert type " + val.getClass() + " " + UUID.class); + } +} + diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/joda/DateTimeConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/joda/DateTimeConverter.java new file mode 100644 index 000000000..1b5a00698 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/joda/DateTimeConverter.java @@ -0,0 +1,46 @@ +package org.sql2o.converters.joda; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.LocalDateTime; +import org.joda.time.LocalTime; +import org.sql2o.converters.Converter; +import org.sql2o.converters.ConverterException; + +import java.sql.Timestamp; + +/** + * Used by sql2o to convert a value from the database into a {@link DateTime} instance. + */ +public class DateTimeConverter implements Converter { + + private final DateTimeZone timeZone; + + // it's possible to create instance for other timezone + // and re-register converter + public DateTimeConverter(DateTimeZone timeZone) { + this.timeZone = timeZone; + } + + public DateTimeConverter() { + this(DateTimeZone.UTC); + } + + public DateTime convert(Object val) throws ConverterException { + if (val == null){ + return null; + } + try { + // Joda has it's own pluggable converters infrastructure + // it will throw IllegalArgumentException if can't convert + // look @ org.joda.time.convert.ConverterManager + return new LocalDateTime(val).toDateTime(timeZone); + } catch (IllegalArgumentException ex) { + throw new ConverterException("Error while converting type " + val.getClass().toString() + " to jodatime", ex); + } + } + + public Object toDatabaseParam(DateTime val) { + return new Timestamp(val.getMillis()); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/joda/LocalTimeConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/joda/LocalTimeConverter.java new file mode 100644 index 000000000..1cc4052f0 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/joda/LocalTimeConverter.java @@ -0,0 +1,31 @@ +package org.sql2o.converters.joda; + +import org.joda.time.LocalTime; +import org.sql2o.converters.Converter; +import org.sql2o.converters.ConverterException; + +import java.sql.Timestamp; + +/** + * Created by lars on 12/18/13. + */ +public class LocalTimeConverter implements Converter { + + public LocalTime convert(Object val) throws ConverterException { + if (val == null) { + return null; + } + try { + // Joda has it's own pluggable converters infrastructure + // it will throw IllegalArgumentException if can't convert + // look @ org.joda.time.convert.ConverterManager + return new LocalTime(val); + } catch (IllegalArgumentException ex) { + throw new ConverterException("Don't know how to convert from type '" + val.getClass().getName() + "' to type '" + LocalTime.class.getName() + "'", ex); + } + } + + public Object toDatabaseParam(LocalTime val) { + return new Timestamp(val.toDateTimeToday().getMillis()); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/package-info.java b/blade-sql2o/src/main/java/org/sql2o/converters/package-info.java new file mode 100644 index 000000000..83d35dedd --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/converters/package-info.java @@ -0,0 +1,5 @@ +/** + * Provides all converters used by sql2o. These converters are used to convert values from the database to the expected + * data types. + */ +package org.sql2o.converters; \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/data/Column.java b/blade-sql2o/src/main/java/org/sql2o/data/Column.java new file mode 100644 index 000000000..824327839 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/data/Column.java @@ -0,0 +1,34 @@ +package org.sql2o.data; + +/** + * Represents a result set column + */ +public class Column { + + private String name; + private Integer index; + private String type; + + public Column(String name, Integer index, String type) { + this.name = name; + this.index = index; + this.type = type; + } + + public String getName() { + return name; + } + + public Integer getIndex() { + return index; + } + + public String getType() { + return type; + } + + @Override + public String toString() { + return getName() + " (" + getType() + ")"; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/data/LazyTable.java b/blade-sql2o/src/main/java/org/sql2o/data/LazyTable.java new file mode 100644 index 000000000..552b05bd4 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/data/LazyTable.java @@ -0,0 +1,42 @@ +package org.sql2o.data; + +import org.sql2o.ResultSetIterable; + +import java.util.List; + +/** + * @author aldenquimby@gmail.com + */ +public class LazyTable implements AutoCloseable { + private String name; + private ResultSetIterable rows; + private List columns; + + public String getName() { + return name; + } + + void setName(String name) { + this.name = name; + } + + public Iterable rows() { + return rows; + } + + public void setRows(ResultSetIterable rows) { + this.rows = rows; + } + + public List columns() { + return columns; + } + + void setColumns(List columns) { + this.columns = columns; + } + + public void close() { + this.rows.close(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/data/Row.java b/blade-sql2o/src/main/java/org/sql2o/data/Row.java new file mode 100644 index 000000000..db7614590 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/data/Row.java @@ -0,0 +1,194 @@ +package org.sql2o.data; + +import org.sql2o.Sql2oException; +import org.sql2o.converters.*; +import org.sql2o.quirks.Quirks; + +import java.math.BigDecimal; +import java.util.*; + +import static java.util.Arrays.asList; +import static org.sql2o.converters.Convert.throwIfNull; + +/** + * Represents a result set row. + */ +@SuppressWarnings({"UnusedDeclaration", "RedundantTypeArguments"}) +public class Row { + + private final Object[] values; + private final boolean isCaseSensitive; + private final Quirks quirks; + private final Map columnNameToIdxMap; + + public Row(Map columnNameToIdxMap, int columnCnt, boolean isCaseSensitive, Quirks quirks) { + this.columnNameToIdxMap = columnNameToIdxMap; + this.isCaseSensitive = isCaseSensitive; + this.quirks = quirks; + // lol. array works better + this.values = new Object[columnCnt]; + } + + void addValue(int columnIndex, Object value){ + values[columnIndex]=value; + } + + public Object getObject(int columnIndex){ + return values[columnIndex]; + } + + public Object getObject(String columnName){ + Integer index = columnNameToIdxMap.get( + isCaseSensitive?columnName + :columnName.toLowerCase()); + if(index!=null) return getObject(index); + throw new Sql2oException(String.format("Column with name '%s' does not exist", columnName)); + } + + @SuppressWarnings("unchecked") + public V getObject(int columnIndex, Class clazz){ + try{ + return (V) throwIfNull(clazz, quirks.converterOf(clazz)).convert(getObject(columnIndex)); + } catch (ConverterException ex){ + throw new Sql2oException("Error converting value", ex); + } + } + + @SuppressWarnings("unchecked") + public V getObject(String columnName, Class clazz) { + try{ + return (V) throwIfNull(clazz, quirks.converterOf(clazz)).convert(getObject(columnName)); + } catch (ConverterException ex){ + throw new Sql2oException("Error converting value", ex); + } + } + + public BigDecimal getBigDecimal(int columnIndex){ + return this.getObject(columnIndex, BigDecimal.class); + } + + public BigDecimal getBigDecimal(String columnName){ + return this.getObject(columnName, BigDecimal.class); + } + + public Double getDouble(int columnIndex){ + return this.getObject(columnIndex, Double.class); + } + + public Double getDouble(String columnName){ + return this.getObject(columnName, Double.class); + } + + public Float getFloat(int columnIndex){ + return this.getObject(columnIndex, Float.class); + } + + public Float getFloat(String columnName){ + return this.getObject(columnName, Float.class); + } + + public Long getLong(int columnIndex){ + return this.getObject(columnIndex, Long.class); + } + + public Long getLong(String columnName){ + return this.getObject(columnName, Long.class); + } + + public Integer getInteger(int columnIndex){ + return this.getObject(columnIndex, Integer.class); + } + + public Integer getInteger(String columnName){ + return this.getObject(columnName, Integer.class); + } + + public Short getShort(int columnIndex){ + return this.getObject(columnIndex, Short.class); + } + + public Short getShort(String columnName){ + return this.getObject(columnName, Short.class); + } + + public Byte getByte(int columnIndex){ + return this.getObject(columnIndex, Byte.class); + } + + public Byte getByte(String columnName){ + return this.getObject(columnName, Byte.class); + } + + public Date getDate(int columnIndex){ + return this.getObject(columnIndex, Date.class); + } + + public Date getDate(String columnName){ + return this.getObject(columnName, Date.class); + } + + public String getString(int columnIndex){ + return this.getObject(columnIndex, String.class); + } + + public String getString(String columnName){ + return this.getObject(columnName, String.class); + } + + /** + * View row as a simple map. + */ + @SuppressWarnings("NullableProblems") + public Map asMap() + { final List listOfValues = asList(values); + return new Map() { + public int size() { + return values.length; + } + + public boolean isEmpty() { + return size()==0; + } + + public boolean containsKey(Object key) { + return columnNameToIdxMap.containsKey(key); + } + + public boolean containsValue(Object value) { + return listOfValues.contains(value); + } + + public Object get(Object key) { + return values[columnNameToIdxMap.get(key)]; + } + + public Object put(String key, Object value) { + throw new UnsupportedOperationException("Row map is immutable."); + } + + public Object remove(Object key) { + throw new UnsupportedOperationException("Row map is immutable."); + } + + public void putAll(Map m) { + throw new UnsupportedOperationException("Row map is immutable."); + } + + public void clear() { + throw new UnsupportedOperationException("Row map is immutable."); + } + + public Set keySet() { + return columnNameToIdxMap.keySet(); + } + + public Collection values() { + return listOfValues; + } + + public Set> entrySet() { + throw new UnsupportedOperationException("Row map does not support entrySet."); + } + }; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/data/Table.java b/blade-sql2o/src/main/java/org/sql2o/data/Table.java new file mode 100644 index 000000000..0697f94e6 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/data/Table.java @@ -0,0 +1,45 @@ +package org.sql2o.data; + +import java.util.*; + +/** + * Represents an offline result set with columns and rows and data. + */ +public class Table { + private String name; + private List rows; + private List columns; + + public Table(String name, List rows, List columns) { + this.name = name; + this.rows = rows; + this.columns = columns; + } + + public String getName() { + return name; + } + + public List rows() { + return rows; + } + + public List columns() { + return columns; + } + + public List> asList() + { + return new AbstractList>() { + @Override + public Map get(int index) { + return rows.get(index).asMap(); + } + + @Override + public int size() { + return rows.size(); + } + }; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/data/TableResultSetIterator.java b/blade-sql2o/src/main/java/org/sql2o/data/TableResultSetIterator.java new file mode 100644 index 000000000..e093a0af6 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/data/TableResultSetIterator.java @@ -0,0 +1,51 @@ +package org.sql2o.data; + +import org.sql2o.ResultSetIteratorBase; +import org.sql2o.Sql2oException; +import org.sql2o.quirks.Quirks; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; + +/** + * @author aldenquimby@gmail.com + */ +public class TableResultSetIterator extends ResultSetIteratorBase { + private Map columnNameToIdxMap; + private List columns; + + public TableResultSetIterator(ResultSet rs, boolean isCaseSensitive, Quirks quirks, LazyTable lt) { + super(rs, isCaseSensitive, quirks); + + this.columnNameToIdxMap = new HashMap(); + this.columns = new ArrayList(); + + try { + lt.setName(meta.getTableName(1)); + + for (int colIdx = 1; colIdx <= meta.getColumnCount(); colIdx++){ + String colName = getColumnName(colIdx); + String colType = meta.getColumnTypeName(colIdx); + columns.add(new Column(colName, colIdx - 1, colType)); + + String colMapName = isCaseSensitive ? colName : colName.toLowerCase(); + columnNameToIdxMap.put(colMapName, colIdx - 1); + } + } + catch (SQLException e) { + throw new Sql2oException("Error while reading metadata from database", e); + } + + lt.setColumns(columns); + } + + @Override + protected Row readNext() throws SQLException { + Row row = new Row(columnNameToIdxMap, columns.size(), isCaseSensitive,this.quirks); + for (Column column : columns) { + row.addValue(column.getIndex(), quirks.getRSVal(rs, column.getIndex() + 1)); + } + return row; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/data/package-info.java b/blade-sql2o/src/main/java/org/sql2o/data/package-info.java new file mode 100644 index 000000000..078d8a9a2 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/data/package-info.java @@ -0,0 +1,4 @@ +/** + * Provides the model used by sql2o to represent a raw result set. + */ +package org.sql2o.data; \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/logging/LocalLoggerFactory.java b/blade-sql2o/src/main/java/org/sql2o/logging/LocalLoggerFactory.java new file mode 100644 index 000000000..e1281d5d9 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/logging/LocalLoggerFactory.java @@ -0,0 +1,19 @@ +package org.sql2o.logging; + +import org.slf4j.LoggerFactory; +import org.sql2o.tools.FeatureDetector; + +/** + * Created by lars on 2/9/14. + */ +public class LocalLoggerFactory { + // this is thread-safe since static initializer is thread-safe + private static final boolean slf4jAvailable = FeatureDetector.isSlf4jAvailable(); + + public static Logger getLogger(Class clazz) { + return slf4jAvailable + ? new Slf4jLogger(LoggerFactory.getLogger(clazz)) + : SysOutLogger.instance; + + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/logging/Logger.java b/blade-sql2o/src/main/java/org/sql2o/logging/Logger.java new file mode 100644 index 000000000..700279508 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/logging/Logger.java @@ -0,0 +1,12 @@ +package org.sql2o.logging; + +/** + * Created by lars on 2/9/14. + */ +public interface Logger { + + public void debug(String format, Object[] argArray); + public void debug(String format, Object arg); + public void warn(String format); + public void warn(String format, Throwable exception); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/logging/Slf4jLogger.java b/blade-sql2o/src/main/java/org/sql2o/logging/Slf4jLogger.java new file mode 100644 index 000000000..0827cb905 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/logging/Slf4jLogger.java @@ -0,0 +1,29 @@ +package org.sql2o.logging; + +/** + * Created by lars on 2/9/14. + */ +public class Slf4jLogger implements Logger { + + private final org.slf4j.Logger slf4jLogger; + + public Slf4jLogger(org.slf4j.Logger slf4jLogger) { + this.slf4jLogger = slf4jLogger; + } + + public void debug(String format, Object[] argArray) { + slf4jLogger.debug(format, argArray); + } + + public void debug(String format, Object arg) { + slf4jLogger.debug(format, arg); + } + + public void warn(String format) { + slf4jLogger.warn(format); + } + + public void warn(String format, Throwable exception) { + slf4jLogger.warn(format, exception); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/logging/SysOutLogger.java b/blade-sql2o/src/main/java/org/sql2o/logging/SysOutLogger.java new file mode 100644 index 000000000..de5a61c64 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/logging/SysOutLogger.java @@ -0,0 +1,62 @@ +package org.sql2o.logging; + +/** + * Created by lars on 2/9/14. + */ +public class SysOutLogger implements Logger { + + public static Logger instance = new SysOutLogger(); + + //private final Class clazz; // don't used + private final static long startTime = System.currentTimeMillis(); + public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + private static String WARN_LVL = "WARN"; + // private static String ERROR_LVL = "ERROR"; // don't used + + public SysOutLogger() { + // this.clazz = clazz; + } + + public void debug(String format, Object[] argArray) { + // Don't log debug messages with the SysOutLogger + } + + public void debug(String format, Object arg) { + // Don't log debug messages with the SysOutLogger + } + + public void warn(String format) { + this.log(format, WARN_LVL, null); + } + + public void warn(String format, Throwable exception) { + this.log(format, WARN_LVL, exception); + } + + private void log(String msg, String level, Throwable exception) { + StringBuilder buffer = new StringBuilder(); // bit faster + + long millis = System.currentTimeMillis(); + buffer.append(millis - startTime); + + buffer.append(" ["); + buffer.append(Thread.currentThread().getName()); + buffer.append("] "); + + buffer.append(level); + buffer.append(" "); + + buffer.append(this.getClass().getName()); + buffer.append(" - "); + + buffer.append(msg); + + buffer.append(LINE_SEPARATOR); + + System.err.print(buffer.toString()); + if (exception != null) { + exception.printStackTrace(System.err); + } + System.err.flush(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/package-info.java b/blade-sql2o/src/main/java/org/sql2o/package-info.java new file mode 100644 index 000000000..64f2f6128 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/package-info.java @@ -0,0 +1,4 @@ +/** + * Provides the main api for sql2o. + */ +package org.sql2o; \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/Db2Quirks.java b/blade-sql2o/src/main/java/org/sql2o/quirks/Db2Quirks.java new file mode 100644 index 000000000..ca4753e05 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/Db2Quirks.java @@ -0,0 +1,28 @@ +package org.sql2o.quirks; + +import org.sql2o.converters.Converter; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.Map; + +/** + * @author aldenquimby@gmail.com + * @since 4/6/14 + */ +public class Db2Quirks extends NoQuirks { + public Db2Quirks() { + super(); + } + + public Db2Quirks(Map converters) { + super(converters); + } + // Db2 works perfect with java.sql.Timestamp + // checked on DATE|TIME|TIMESTAMP column types + + @Override + public String getColumnName(ResultSetMetaData meta, int colIdx) throws SQLException { + return meta.getColumnName(colIdx); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/NoQuirks.java b/blade-sql2o/src/main/java/org/sql2o/quirks/NoQuirks.java new file mode 100644 index 000000000..50ba7832a --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/NoQuirks.java @@ -0,0 +1,123 @@ +package org.sql2o.quirks; + +import org.sql2o.converters.Convert; +import org.sql2o.converters.Converter; +import org.sql2o.quirks.parameterparsing.impl.DefaultSqlParameterParsingStrategy; +import org.sql2o.quirks.parameterparsing.SqlParameterParsingStrategy; + +import java.io.InputStream; +import java.sql.*; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author aldenquimby@gmail.com + * @since 4/6/14 + */ +public class NoQuirks implements Quirks { + protected final Map converters; + private final SqlParameterParsingStrategy sqlParameterParsingStrategy = new DefaultSqlParameterParsingStrategy(); + + public NoQuirks(Map converters) { + // protective copy + // to avoid someone change this collection outside + // so this makes converters thread-safe + this.converters = new HashMap(converters); + } + + public NoQuirks() { + this(Collections.emptyMap()); + } + + @SuppressWarnings("unchecked") + public Converter converterOf(Class ofClass) { + // if nobody change this collection outside constructor + // it's thread-safe + Converter c = converters.get(ofClass); + // if no "local" converter let's look in global + return c!=null?c:Convert.getConverterIfExists(ofClass); + + } + + public String getColumnName(ResultSetMetaData meta, int colIdx) throws SQLException { + return meta.getColumnLabel(colIdx); + } + + public boolean returnGeneratedKeysByDefault() { + return true; + } + + public void setParameter(PreparedStatement statement, int paramIdx, Object value) throws SQLException { + statement.setObject(paramIdx, value); + } + + public void setParameter(PreparedStatement statement, int paramIdx, InputStream value) throws SQLException { + statement.setBinaryStream(paramIdx, value); + } + + public void setParameter(PreparedStatement statement, int paramIdx, int value) throws SQLException { + statement.setInt(paramIdx, value); + } + + public void setParameter(PreparedStatement statement, int paramIdx, Integer value) throws SQLException { + if (value == null) { + statement.setNull(paramIdx, Types.INTEGER); + } else { + statement.setInt(paramIdx, value); + } + } + + public void setParameter(PreparedStatement statement, int paramIdx, long value) throws SQLException { + statement.setLong(paramIdx, value); + } + + public void setParameter(PreparedStatement statement, int paramIdx, Long value) throws SQLException { + if (value == null) { + statement.setNull(paramIdx, Types.BIGINT); + } else { + statement.setLong(paramIdx, value); + } + } + + public void setParameter(PreparedStatement statement, int paramIdx, String value) throws SQLException { + if (value == null) { + statement.setNull(paramIdx, Types.VARCHAR); + } else { + statement.setString(paramIdx, value); + } + } + + public void setParameter(PreparedStatement statement, int paramIdx, Timestamp value) throws SQLException { + if (value == null) { + statement.setNull(paramIdx, Types.TIMESTAMP); + } else { + statement.setTimestamp(paramIdx, value); + } + } + + public void setParameter(PreparedStatement statement, int paramIdx, Time value) throws SQLException { + if (value == null) { + statement.setNull(paramIdx, Types.TIME); + } else { + statement.setTime(paramIdx, value); + } + } + + public Object getRSVal(ResultSet rs, int idx) throws SQLException { + return rs.getObject(idx); + } + + @Override + public void closeStatement(Statement statement) throws SQLException { + statement.close(); + } + + @Override + public SqlParameterParsingStrategy getSqlParameterParsingStrategy() { + return this.sqlParameterParsingStrategy; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/OracleQuirks.java b/blade-sql2o/src/main/java/org/sql2o/quirks/OracleQuirks.java new file mode 100644 index 000000000..f5a34ced8 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/OracleQuirks.java @@ -0,0 +1,36 @@ +package org.sql2o.quirks; + + +import org.sql2o.converters.Converter; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; + +public class OracleQuirks extends NoQuirks { + public OracleQuirks() { + super(); + } + + public OracleQuirks(Map converters) { + super(converters); + } + + @Override + public Object getRSVal(ResultSet rs, int idx) throws SQLException { + Object o = super.getRSVal(rs, idx); + // oracle timestamps are not always convertible to a java Date. If ResultSet.getTimestamp is used instead of + // ResultSet.getObject, a normal java.sql.Timestamp instance is returnd. + if (o != null && o.getClass().getCanonicalName().startsWith("oracle.sql.TIMESTAMP")){ + //TODO: move to sql2o-oracle + //TODO: use TIMESTAMP.dateValue + o = rs.getTimestamp(idx); + } + return o; + } + + @Override + public boolean returnGeneratedKeysByDefault() { + return false; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/PostgresQuirks.java b/blade-sql2o/src/main/java/org/sql2o/quirks/PostgresQuirks.java new file mode 100644 index 000000000..a27e24445 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/PostgresQuirks.java @@ -0,0 +1,24 @@ +package org.sql2o.quirks; + +import org.sql2o.converters.Converter; + +import java.util.Map; + +/** + * @author aldenquimby@gmail.com + * @since 4/6/14 + */ +public class PostgresQuirks extends NoQuirks { + public PostgresQuirks() { + super(); + } + + public PostgresQuirks(Map converters) { + super(converters); + } + + @Override + public boolean returnGeneratedKeysByDefault() { + return false; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/Quirks.java b/blade-sql2o/src/main/java/org/sql2o/quirks/Quirks.java new file mode 100644 index 000000000..25672a59f --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/Quirks.java @@ -0,0 +1,54 @@ +package org.sql2o.quirks; + +import org.sql2o.converters.Converter; +import org.sql2o.quirks.parameterparsing.SqlParameterParsingStrategy; + +import java.io.InputStream; +import java.sql.*; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; + +/** + * Interface for JDBC driver specific quirks. + * See {@link org.sql2o.quirks.NoQuirks} for defaults. + * + * @author aldenquimby@gmail.com + * @since 4/6/14 + */ +public interface Quirks { + /** + * @param ofClass + * @param + * @return converter for class + */ + + Converter converterOf(Class ofClass); + + + /** + * @return name of column at index {@code colIdx} for result set {@code meta} + */ + String getColumnName(ResultSetMetaData meta, int colIdx) throws SQLException; + + /** + * @return true if queries should return generated keys by default, false otherwise + */ + boolean returnGeneratedKeysByDefault(); + + void setParameter(PreparedStatement statement, int paramIdx, Object value) throws SQLException; + void setParameter(PreparedStatement statement, int paramIdx, InputStream value) throws SQLException; + void setParameter(PreparedStatement statement, int paramIdx, int value) throws SQLException; + void setParameter(PreparedStatement statement, int paramIdx, Integer value) throws SQLException; + void setParameter(PreparedStatement statement, int paramIdx, long value) throws SQLException; + void setParameter(PreparedStatement statement, int paramIdx, Long value) throws SQLException; + void setParameter(PreparedStatement statement, int paramIdx, String value) throws SQLException; + void setParameter(PreparedStatement statement, int paramIdx, Timestamp value) throws SQLException; + void setParameter(PreparedStatement statement, int paramIdx, Time value) throws SQLException; + + Object getRSVal(ResultSet rs, int idx) throws SQLException; + + void closeStatement(Statement statement) throws SQLException; + + SqlParameterParsingStrategy getSqlParameterParsingStrategy(); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksDetector.java b/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksDetector.java new file mode 100644 index 000000000..63e55ff50 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksDetector.java @@ -0,0 +1,34 @@ +package org.sql2o.quirks; + +import org.sql2o.GenericDatasource; + +import java.util.ServiceLoader; + +/** + * User: dimzon + * Date: 4/24/14 + * Time: 9:39 AM + */ +public class QuirksDetector{ + static final ServiceLoader providers = ServiceLoader.load(QuirksProvider.class); + + public static Quirks forURL(String jdbcUrl) { + Quirks quirks; + for (QuirksProvider provider : providers) { + quirks=provider.forURL(jdbcUrl); + if(quirks!=null) return quirks; + } + return new NoQuirks(); + } + + public static Quirks forObject(Object jdbcObject) { + if(jdbcObject instanceof GenericDatasource) + return forURL(((GenericDatasource) jdbcObject).getUrl()); + Quirks quirks; + for (QuirksProvider provider : providers) { + quirks=provider.forObject(jdbcObject); + if(quirks!=null) return quirks; + } + return new NoQuirks(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksProvider.java b/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksProvider.java new file mode 100644 index 000000000..5a18657a9 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksProvider.java @@ -0,0 +1,11 @@ +package org.sql2o.quirks; + +/** + * User: dimzon + * Date: 4/24/14 + * Time: 9:31 AM + */ +public interface QuirksProvider { + Quirks forURL(String jdbcUrl); + Quirks forObject(Object jdbcObject); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/SqlParameterParsingStrategy.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/SqlParameterParsingStrategy.java new file mode 100644 index 000000000..2240d3788 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/SqlParameterParsingStrategy.java @@ -0,0 +1,11 @@ +package org.sql2o.quirks.parameterparsing; + +import java.util.List; +import java.util.Map; + +/** + * Created by lars on 11.04.14. + */ +public interface SqlParameterParsingStrategy { + String parseSql(String sqlToParse, Map> mapToFill); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/AbstractCommentParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/AbstractCommentParser.java new file mode 100644 index 000000000..b3081b393 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/AbstractCommentParser.java @@ -0,0 +1,23 @@ +package org.sql2o.quirks.parameterparsing.impl; + +/** + * Created by lars on 22.09.2014. + */ +public abstract class AbstractCommentParser implements CharParser { + + protected void init(){}; + + @Override + public int parse(char c, int idx, StringBuilder parsedSql, String sql, int length) { + init(); + do { + parsedSql.append(c); + if (++idx == length) return idx; + c = sql.charAt(idx); + } while(!isEndComment(c)); + parsedSql.append(c); + return idx; + } + + public abstract boolean isEndComment(char c); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/CharParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/CharParser.java new file mode 100644 index 000000000..a3696cf65 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/CharParser.java @@ -0,0 +1,9 @@ +package org.sql2o.quirks.parameterparsing.impl; + +/** + * Created by lars on 22.09.2014. + */ +public interface CharParser { + boolean canParse(char c, String sql, int idx); + int parse(char c, int idx, StringBuilder parsedSql, String sql, int length); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultParser.java new file mode 100644 index 000000000..3c28cab92 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultParser.java @@ -0,0 +1,18 @@ +package org.sql2o.quirks.parameterparsing.impl; + +/** + * Created by lars on 22.09.2014. + */ +public class DefaultParser implements CharParser { + + @Override + public boolean canParse(char c, String sql, int idx) { + return true; + } + + @Override + public int parse(char c, int idx, StringBuilder parsedSql, String sql, int length) { + parsedSql.append(c); + return idx; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultSqlParameterParsingStrategy.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultSqlParameterParsingStrategy.java new file mode 100644 index 000000000..fbd0c543d --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultSqlParameterParsingStrategy.java @@ -0,0 +1,44 @@ +package org.sql2o.quirks.parameterparsing.impl; + +import org.sql2o.quirks.parameterparsing.SqlParameterParsingStrategy; +import org.sql2o.tools.AbstractCache; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by lars on 11.04.14. + */ +public class DefaultSqlParameterParsingStrategy implements SqlParameterParsingStrategy { + + public CharParser[] getCharParsers(Map> paramMap) { + return new CharParser[]{ + new QuoteParser(), + new DoubleHyphensCommentParser(), + new ForwardSlashCommentParser(), + new ParameterParser(paramMap), + new DefaultParser() + }; + } + + @SuppressWarnings("ConstantConditions") + public String parseSql(String statement, Map> paramMap) { + final int length = statement.length(); + final StringBuilder parsedQuery = new StringBuilder(length); + + final CharParser[] charParsers = getCharParsers(paramMap); + + for (int idx = 0; idx < length; idx++) { + for (CharParser parser : charParsers) { + char c = statement.charAt(idx); + if (parser.canParse(c, statement, idx)){ + idx = parser.parse(c, idx, parsedQuery, statement, length); + break; + } + } + } + + return parsedQuery.toString(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DoubleHyphensCommentParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DoubleHyphensCommentParser.java new file mode 100644 index 000000000..ce650d73c --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DoubleHyphensCommentParser.java @@ -0,0 +1,17 @@ +package org.sql2o.quirks.parameterparsing.impl; + +/** + * Created by lars on 22.09.2014. + */ +public class DoubleHyphensCommentParser extends AbstractCommentParser { + + @Override + public boolean canParse(char c, String sql, int idx) { + return sql.length() > idx + 1 && c == '-' && sql.charAt(idx + 1) == '-'; + } + + @Override + public boolean isEndComment(char c) { + return c == '\n'; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ForwardSlashCommentParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ForwardSlashCommentParser.java new file mode 100644 index 000000000..d76c4a66a --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ForwardSlashCommentParser.java @@ -0,0 +1,26 @@ +package org.sql2o.quirks.parameterparsing.impl; + +/** + * Created by lars on 22.09.2014. + */ +public class ForwardSlashCommentParser extends AbstractCommentParser { + + private boolean commentAlmostEnded; + + @Override + protected void init() { + commentAlmostEnded = false; + } + + @Override + public boolean canParse(char c, String sql, int idx) { + return sql.length() > idx + 1 && c == '/' && sql.charAt(idx + 1) == '*'; + } + + @Override + public boolean isEndComment(char c) { + if (commentAlmostEnded && c == '/') return true; + commentAlmostEnded = c == '*'; + return false; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ParameterParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ParameterParser.java new file mode 100644 index 000000000..4a8330524 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ParameterParser.java @@ -0,0 +1,44 @@ +package org.sql2o.quirks.parameterparsing.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by lars on 22.09.2014. + */ +public class ParameterParser implements CharParser{ + + private final Map> parameterMap; + int paramIdx = 1; + + public ParameterParser(Map> parameterMap) { + this.parameterMap = parameterMap; + } + + @Override + public boolean canParse(char c, String sql, int idx) { + return sql.length() > idx + 1 && c == ':' && Character.isJavaIdentifierStart( sql.charAt(idx + 1) ) && sql.charAt(idx-1) != ':'; + } + + @Override + public int parse(char c, int idx, StringBuilder parsedSql, String sql, int length) { + int startIdx = idx; + idx += 1; + + while (idx + 1 < length && Character.isJavaIdentifierPart(sql.charAt(idx + 1))) { + idx += 1; + } + + String name = sql.substring(startIdx + 1, idx + 1); + List indices = parameterMap.get(name); + if (indices == null) { + indices = new ArrayList(); + parameterMap.put(name, indices); + } + indices.add(paramIdx++); + parsedSql.append("?"); + + return idx; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/QuoteParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/QuoteParser.java new file mode 100644 index 000000000..6587613d4 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/QuoteParser.java @@ -0,0 +1,26 @@ +package org.sql2o.quirks.parameterparsing.impl; + +/** + * Created by lars on 22.09.2014. + */ +public class QuoteParser implements CharParser { + + @Override + public boolean canParse(char c, String sql, int idx) { + return c == '\'' || c == '"'; + } + + @Override + public int parse(char c, int idx, StringBuilder parsedSql, String sql, int length) { + char quoteChar = c; + + do { + parsedSql.append(c); + if (++idx == length) return idx; + c = sql.charAt(idx); + + } while(c != quoteChar); + parsedSql.append(c); + return idx; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/spi/QuirksProviderImpl.java b/blade-sql2o/src/main/java/org/sql2o/quirks/spi/QuirksProviderImpl.java new file mode 100644 index 000000000..fd0332da4 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/quirks/spi/QuirksProviderImpl.java @@ -0,0 +1,40 @@ +package org.sql2o.quirks.spi; + +import org.sql2o.quirks.*; + +/** + * User: dimzon + * Date: 4/24/14 + * Time: 9:35 AM + */ +public class QuirksProviderImpl implements QuirksProvider { + public Quirks forURL(String jdbcUrl) { + if (jdbcUrl.startsWith("jdbc:oracle:")) return oracleQuirks.q; + if (jdbcUrl.startsWith("jdbc:db2:")) return db2Quirks.q; + if (jdbcUrl.startsWith("jdbc:db2j:net:")) return db2Quirks.q; + if (jdbcUrl.startsWith("jdbc:db2os390")) return db2Quirks.q; + if (jdbcUrl.startsWith("jdbc:postgresql:")) return postgresQuirks.q; + return null; + } + + public Quirks forObject(Object jdbcObject) { + String className = jdbcObject.getClass().getCanonicalName(); + if (className.startsWith("oracle.jdbc.")) return oracleQuirks.q; + if (className.startsWith("oracle.sql.")) return oracleQuirks.q; + if (className.startsWith("com.ibm.db2.jcc.DB2")) return db2Quirks.q; + if (className.startsWith("org.postgresql.")) return postgresQuirks.q; + return null; + } + + private static class oracleQuirks { + static final Quirks q = new OracleQuirks(); + } + + private static class db2Quirks { + static final Quirks q = new Db2Quirks(); + } + + private static class postgresQuirks { + static final Quirks q = new PostgresQuirks(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java b/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java new file mode 100644 index 000000000..bcdd855ba --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java @@ -0,0 +1,60 @@ +package org.sql2o.reflection; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +@SuppressWarnings("Unsafe") +public class FactoryFacade { + private final static FactoryFacade instance; + + static { + MethodSetterFactory m; + ObjectConstructorFactory o; + try { + m = (MethodSetterFactory) Class + .forName("org.sql2o.reflection.MethodAccessorsGenerator") + .newInstance(); + o = (ObjectConstructorFactory) m; + } catch (Throwable ex) { + m = new ReflectionMethodSetterFactory(); + o = null; + } + FieldSetterFactory f; + try { + Class cls = Class.forName("org.sql2o.reflection.UnsafeFieldSetterFactory"); + f = (FieldSetterFactory) cls.newInstance(); + if(o==null) o = (ObjectConstructorFactory) f; + } catch (Throwable ex) { + f = new ReflectionFieldSetterFactory(); + o = new ReflectionObjectConstructorFactory(); + } + instance = new FactoryFacade(f, m, o); + } + + private final FieldSetterFactory fieldSetterFactory; + private final MethodSetterFactory methodSetterFactory; + private final ObjectConstructorFactory objectConstructorFactory; + + public FactoryFacade(FieldSetterFactory fieldSetterFactory, MethodSetterFactory methodSetterFactory, ObjectConstructorFactory objectConstructorFactory) { + this.fieldSetterFactory = fieldSetterFactory; + this.methodSetterFactory = methodSetterFactory; + this.objectConstructorFactory = objectConstructorFactory; + } + + public static FactoryFacade getInstance() { + return instance; + } + + public Setter newSetter(Field field) { + return fieldSetterFactory.newSetter(field); + } + + public Setter newSetter(Method method) { + return methodSetterFactory.newSetter(method); + } + + public ObjectConstructor newConstructor(Class cls) { + return objectConstructorFactory.newConstructor(cls); + } +} + diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java new file mode 100644 index 000000000..31af9d97f --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java @@ -0,0 +1,34 @@ +package org.sql2o.reflection; + +import org.sql2o.Sql2oException; + +import java.lang.reflect.Field; + +/** + * used internally to set property values directly into the field. Only used if no setter method is found. + */ +public class FieldSetter implements Setter{ + + private Field field; + + public FieldSetter(Field field) { + this.field = field; + this.field.setAccessible(true); + } + + public void setProperty(Object obj, Object value) { + if (value == null && this.field.getType().isPrimitive()){ + return; // dont try set null to a primitive field + } + + try { + this.field.set(obj, value); + } catch (IllegalAccessException e) { + throw new Sql2oException("could not set field " + this.field.getName() + " on class " + obj.getClass().toString(), e); + } + } + + public Class getType() { + return field.getType(); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetterFactory.java new file mode 100644 index 000000000..cf00bdbc9 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetterFactory.java @@ -0,0 +1,14 @@ +package org.sql2o.reflection; + +import java.lang.reflect.Field; + +/** + * Created with IntelliJ IDEA. + * User: dimzon + * Date: 4/6/14 + * Time: 12:39 AM + * To change this template use File | Settings | File Templates. + */ +public interface FieldSetterFactory { + Setter newSetter(Field field); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java new file mode 100644 index 000000000..913be05b7 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java @@ -0,0 +1,164 @@ +package org.sql2o.reflection; + +import org.sql2o.Sql2oException; +import sun.reflect.ConstructorAccessor; +import sun.reflect.FieldAccessor; +import sun.reflect.MethodAccessor; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +@SuppressWarnings("UnusedDeclaration") +public class MethodAccessorsGenerator implements MethodSetterFactory, ObjectConstructorFactory { + private static final ThreadLocal generatorObjectHolder; + private static final MethodAccessor generateMethod; + private static final MethodAccessor generateConstructor; + private static final MethodAccessor generateSerializationConstructor; + private static final MethodAccessor newFieldAccessor; + + static { + try { + Class aClass = Class.forName("sun.reflect.MethodAccessorGenerator"); + Constructor[] declaredConstructors = aClass.getDeclaredConstructors(); + Constructor declaredConstructor = declaredConstructors[0]; + declaredConstructor.setAccessible(true); + Object generatorObject = declaredConstructor.newInstance(); + Method bar = aClass.getMethod("generateMethod", Class.class, String.class, Class[].class, Class.class, Class[].class, Integer.TYPE); + bar.setAccessible(true); + generateMethod = (MethodAccessor) bar.invoke( + generatorObject, + bar.getDeclaringClass(), + bar.getName(), + bar.getParameterTypes(), + bar.getReturnType(), + bar.getExceptionTypes(), + bar.getModifiers()); + bar = aClass.getMethod("generateConstructor", Class.class, Class[].class, Class[].class, Integer.TYPE); + generateConstructor = newMethodAccessor(generatorObject, bar); + bar = aClass.getMethod("generateSerializationConstructor", Class.class, Class[].class, Class[].class, Integer.TYPE, Class.class); + final ConstructorAccessor goc = newConstructorAccessor(generatorObject, declaredConstructor); + generatorObjectHolder = new ThreadLocal() { + @Override + protected Object initialValue() { + try { + return goc.newInstance(null); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + }; + generateSerializationConstructor = newMethodAccessor(generatorObject, bar); + aClass = Class.forName("sun.reflect.UnsafeFieldAccessorFactory"); + bar = aClass.getDeclaredMethod("newFieldAccessor", Field.class, Boolean.TYPE); + newFieldAccessor = newMethodAccessor(generatorObject, bar); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + public static FieldAccessor newFieldAccessor(Field field, boolean overrideFinalCheck) { + try { + return (FieldAccessor) newFieldAccessor.invoke(null, new Object[]{field, overrideFinalCheck}); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public static MethodAccessor newMethodAccessor(Method bar) { + try { + return newMethodAccessor(generatorObjectHolder.get(), bar); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private static MethodAccessor newMethodAccessor(Object generatorObject, Method bar) throws InvocationTargetException { + return (MethodAccessor) generateMethod.invoke( + generatorObject, new Object[]{ + bar.getDeclaringClass(), + bar.getName(), + bar.getParameterTypes(), + bar.getReturnType(), + bar.getExceptionTypes(), + bar.getModifiers()}); + } + + public static ConstructorAccessor newConstructorAccessor(Constructor bar) { + try { + return newConstructorAccessor(generatorObjectHolder.get(), bar); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private static ConstructorAccessor newConstructorAccessor(Object generatorObject, Constructor bar) throws InvocationTargetException { + return (ConstructorAccessor) generateConstructor.invoke( + generatorObject, new Object[]{ + bar.getDeclaringClass(), + bar.getParameterTypes(), + bar.getExceptionTypes(), + bar.getModifiers()}); + } + + public static ConstructorAccessor newConstructorAccessor(Constructor bar, Class targetClass) { + try { + return (ConstructorAccessor) generateSerializationConstructor.invoke( + generatorObjectHolder.get(), new Object[]{ + targetClass, + bar.getParameterTypes(), + bar.getExceptionTypes(), + bar.getModifiers(), + bar.getDeclaringClass()}); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public Setter newSetter(final Method method) { + final Class type = method.getParameterTypes()[0]; + final MethodAccessor methodAccessor = newMethodAccessor(method); + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null && type.isPrimitive()) return; + try { + methodAccessor.invoke(obj, new Object[]{value}); + } catch (InvocationTargetException e) { + throw new Sql2oException("error while calling setter method with name " + method.getName() + " on class " + obj.getClass().toString(), e); + } + } + + public Class getType() { + return type; + } + }; + } + + @Override + public ObjectConstructor newConstructor(final Class cls) { + for (Class cls0 = cls; cls != Object.class; cls0 = cls0.getSuperclass()) { + try { + Constructor ctor = cls0.getDeclaredConstructor(); + final ConstructorAccessor constructorAccessor = (cls0 == cls) + ? newConstructorAccessor(ctor) + : newConstructorAccessor(ctor, cls); + return new ObjectConstructor() { + @Override + public Object newInstance() { + try { + return constructorAccessor.newInstance(null); + } catch (InstantiationException e) { + throw new Sql2oException("Could not create a new instance of class " + cls, e); + } catch (InvocationTargetException e) { + throw new Sql2oException("Could not create a new instance of class " + cls, e); + } + } + }; + } catch (NoSuchMethodException e) { + // ignore + } + } + return UnsafeFieldSetterFactory.getConstructor(cls); + } +} \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java new file mode 100644 index 000000000..e27043199 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java @@ -0,0 +1,38 @@ +package org.sql2o.reflection; + +import org.sql2o.Sql2oException; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * used internally to set property values via its setter method. + */ +public class MethodSetter implements Setter{ + + private Method method; + private Class type; + + public MethodSetter(Method method) { + this.method = method; + this.method.setAccessible(true); + type = method.getParameterTypes()[0]; + } + + public void setProperty(Object obj, Object value) { + if (value == null && type.isPrimitive()){ + return; // dont try to set null to a setter to a primitive type. + } + try { + this.method.invoke(obj, value); + } catch (IllegalAccessException e) { + throw new Sql2oException("error while calling setter method with name " + method.getName() + " on class " + obj.getClass().toString(), e); + } catch (InvocationTargetException e) { + throw new Sql2oException("error while calling setter method with name " + method.getName() + " on class " + obj.getClass().toString(), e); + } + } + + public Class getType() { + return type; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetterFactory.java new file mode 100644 index 000000000..d1afc6534 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetterFactory.java @@ -0,0 +1,14 @@ +package org.sql2o.reflection; + +import java.lang.reflect.Method; + +/** + * Created with IntelliJ IDEA. + * User: dimzon + * Date: 4/6/14 + * Time: 12:42 AM + * To change this template use File | Settings | File Templates. + */ +public interface MethodSetterFactory { + Setter newSetter(Method method); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructor.java b/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructor.java new file mode 100644 index 000000000..5538a47d1 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructor.java @@ -0,0 +1,12 @@ +package org.sql2o.reflection; + +/** + * Created with IntelliJ IDEA. + * User: dimzon + * Date: 4/6/14 + * Time: 1:26 AM + * To change this template use File | Settings | File Templates. + */ +public interface ObjectConstructor { + Object newInstance(); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructorFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructorFactory.java new file mode 100644 index 000000000..82180f4dd --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructorFactory.java @@ -0,0 +1,12 @@ +package org.sql2o.reflection; + +/** + * Created with IntelliJ IDEA. + * User: dimzon + * Date: 4/6/14 + * Time: 1:27 AM + * To change this template use File | Settings | File Templates. + */ +public interface ObjectConstructorFactory { + ObjectConstructor newConstructor(Class cls); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java b/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java new file mode 100644 index 000000000..389303f19 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java @@ -0,0 +1,84 @@ +package org.sql2o.reflection; + +import org.sql2o.Sql2oException; +import org.sql2o.converters.Converter; +import org.sql2o.converters.ConverterException; +import org.sql2o.quirks.Quirks; + +import static org.sql2o.converters.Convert.throwIfNull; + +/** + * Used internally to represent a plain old java object. + */ +public class Pojo { + + private PojoMetadata metadata; + private boolean caseSensitive; + private Object object; + + public Pojo(PojoMetadata metadata, boolean caseSensitive, Object object){ + this.caseSensitive = caseSensitive; + this.metadata = metadata; + this.object = object; + } + + public Pojo(PojoMetadata metadata, boolean caseSensitive){ + this.caseSensitive = caseSensitive; + this.metadata = metadata; + ObjectConstructor objectConstructor = metadata.getObjectConstructor(); + object = objectConstructor.newInstance(); + } + + @SuppressWarnings("unchecked") + public void setProperty(String propertyPath, Object value, Quirks quirks){ + // String.split uses RegularExpression + // this is overkill for every column for every row + int index = propertyPath.indexOf('.'); + Setter setter; + if (index > 0){ + final String substring = propertyPath.substring(0, index); + setter = metadata.getPropertySetter(substring); + String newPath = propertyPath.substring(index+1); + + Object subValue = this.metadata.getValueOfProperty(substring, this.object); + if (subValue == null){ + try { + subValue = setter.getType().newInstance(); + } catch (InstantiationException e) { + throw new Sql2oException("Could not instantiate a new instance of class "+ setter.getType().toString(), e); + } catch (IllegalAccessException e) { + throw new Sql2oException("Could not instantiate a new instance of class "+ setter.getType().toString(), e); + } + setter.setProperty(this.object, subValue); + } + + PojoMetadata subMetadata = new PojoMetadata(setter.getType(), this.caseSensitive, this.metadata.isAutoDeriveColumnNames(), this.metadata.getColumnMappings(), this.metadata.throwOnMappingFailure); + Pojo subPojo = new Pojo(subMetadata, this.caseSensitive, subValue); + subPojo.setProperty(newPath, value, quirks); + } + else{ + setter = metadata.getPropertySetter(propertyPath); + Converter converter; + try { + converter = throwIfNull(setter.getType(), quirks.converterOf(setter.getType())); + } catch (ConverterException e) { + throw new Sql2oException("Cannot convert column " + propertyPath + " to type " + setter.getType(), e); + } + + try { + setter.setProperty(this.object, converter.convert( value )); + } catch (ConverterException e) { + throw new Sql2oException("Error trying to convert column " + propertyPath + " to type " + setter.getType(), e); + } + } + + + } + + + + public Object getObject(){ + return this.object; + } + +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java new file mode 100644 index 000000000..bfb1faa2b --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java @@ -0,0 +1,118 @@ +package org.sql2o.reflection; + +import org.sql2o.tools.AbstractCache; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.*; + +import static java.beans.Introspector.decapitalize; +import static java.lang.reflect.Modifier.isPrivate; +import static java.lang.reflect.Modifier.isStatic; + +/** + * User: dimzon + * Date: 4/9/14 + * Time: 1:10 AM + */ + +// TODO: move introspection code from PojoMetadata to PojoIntrospector + +@SuppressWarnings("UnusedDeclaration") +public class PojoIntrospector { + private static final AbstractCache, Map, Void> rpCache = + new AbstractCache, Map, Void>() { + @Override + protected Map evaluate(Class key, Void param) { + return collectReadableProperties(key); + } + }; + + private static Map collectReadableProperties(Class cls) { + Map map = new HashMap(); + List> classList = classInheritanceHierarhy(cls, Object.class); + for (Class aClass : classList) { + collectPropertyGetters(map, aClass); + } + for (Class aClass : classList) { + collectReadableFields(map, aClass); + } + return Collections.unmodifiableMap(map); + } + + public static Map readableProperties(Class ofClass) { + return rpCache.get(ofClass, null); + } + + private static void collectReadableFields(Map map, Class cls) { + for (final Field m : cls.getDeclaredFields()) { + if (isStaticOrPrivate(m)) continue; + String propName = m.getName(); + if (map.containsKey(propName)) continue; + Class returnType = m.getType(); + m.setAccessible(true); + ReadableProperty rp = new ReadableProperty(propName, returnType) { + @Override + public Object get(Object instance) throws InvocationTargetException, IllegalAccessException { + return m.get(instance); + } + }; + map.put(propName, rp); + } + } + + private static boolean isStaticOrPrivate(Member m) { + final int modifiers = m.getModifiers(); + return isStatic(modifiers) || isPrivate(modifiers); + } + + private static void collectPropertyGetters(Map map, Class cls) { + for (final Method m : cls.getDeclaredMethods()) { + if (isStatic(m.getModifiers())) continue; + if (isPrivate(m.getModifiers())) continue; + if (0 != m.getParameterTypes().length) continue; + Class returnType = m.getReturnType(); + if (returnType == Void.TYPE || returnType == Void.class) continue; + String name = m.getName(); + String propName = null; + if (name.startsWith("get") && name.length() > 3) { + propName = decapitalize(name.substring(3)); + } else if (name.startsWith("is") && name.length() > 2 && returnType == Boolean.TYPE) { + propName = decapitalize(name.substring(2)); + } + if (propName == null) continue; + if (map.containsKey(propName)) continue; + m.setAccessible(true); + ReadableProperty rp = new ReadableProperty(propName, returnType) { + @Override + public Object get(Object instance) throws InvocationTargetException, IllegalAccessException { + return m.invoke(instance, (Object[]) null); + } + }; + map.put(propName, rp); + } + } + + private static List> classInheritanceHierarhy(Class cls, Class stopAt) { + ArrayList> list = new ArrayList>(); + while (cls != null && cls != stopAt) { + list.add(cls); + cls = cls.getSuperclass(); + } + return list; + } + + public abstract static class ReadableProperty { + public final String name; + public final Class type; + + private ReadableProperty(String name, Class type) { + this.name = name; + this.type = type; + } + + public abstract Object get(Object instance) throws InvocationTargetException, IllegalAccessException; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java new file mode 100644 index 000000000..2f9db165c --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java @@ -0,0 +1,188 @@ +package org.sql2o.reflection; + +import org.sql2o.Sql2oException; +import org.sql2o.tools.AbstractCache; +import org.sql2o.tools.UnderscoreToCamelCase; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Stores metadata for a POJO. + */ +public class PojoMetadata { + + private static final Cache caseSensitiveFalse = new Cache(); + private static final Cache caseSensitiveTrue = new Cache(); + private final PropertyAndFieldInfo propertyInfo; + private final Map columnMappings; + private final FactoryFacade factoryFacade = FactoryFacade.getInstance(); + + private boolean caseSensitive; + private boolean autoDeriveColumnNames; + public final boolean throwOnMappingFailure; + private Class clazz; + + public boolean isCaseSensitive() { + return caseSensitive; + } + + public boolean isAutoDeriveColumnNames() { + return autoDeriveColumnNames; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PojoMetadata that = (PojoMetadata) o; + + return autoDeriveColumnNames == that.autoDeriveColumnNames + && caseSensitive == that.caseSensitive + && clazz.equals(that.clazz) + && columnMappings.equals(that.columnMappings) + && propertyInfo.equals(that.propertyInfo); + + } + + @Override + public int hashCode() { + int result = (caseSensitive ? 1 : 0); + result = 31 * result + clazz.hashCode(); + return result; + } + + public PojoMetadata(Class clazz, boolean caseSensitive, boolean autoDeriveColumnNames, Map columnMappings, boolean throwOnMappingError) { + this.caseSensitive = caseSensitive; + this.autoDeriveColumnNames = autoDeriveColumnNames; + this.clazz = clazz; + this.columnMappings = columnMappings == null ? Collections.emptyMap() : columnMappings; + + this.propertyInfo = getPropertyInfoThroughCache(); + this.throwOnMappingFailure = throwOnMappingError; + + } + + public ObjectConstructor getObjectConstructor() { + return propertyInfo.objectConstructor; + } + + private PropertyAndFieldInfo getPropertyInfoThroughCache() { + return (caseSensitive + ? caseSensitiveTrue + : caseSensitiveFalse) + .get(clazz, this); + } + + private PropertyAndFieldInfo initializePropertyInfo() { + + HashMap propertySetters = new HashMap(); + HashMap fields = new HashMap(); + + Class theClass = clazz; + ObjectConstructor objectConstructor = factoryFacade.newConstructor(theClass); + do { + for (Field f : theClass.getDeclaredFields()) { + String propertyName = f.getName(); + propertyName = caseSensitive ? propertyName : propertyName.toLowerCase(); + propertySetters.put(propertyName, factoryFacade.newSetter(f)); + fields.put(propertyName, f); + } + + // prepare methods. Methods will override fields, if both exists. + for (Method m : theClass.getDeclaredMethods()) { + if (m.getParameterTypes().length!=1) continue; + if (m.getName().startsWith("set")) { + String propertyName = m.getName().substring(3); + if (caseSensitive) { + propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); + } else { + propertyName = propertyName.toLowerCase(); + } + + propertySetters.put(propertyName, factoryFacade.newSetter(m)); + } + } + theClass = theClass.getSuperclass(); + } while (!theClass.equals(Object.class)); + + return new PropertyAndFieldInfo(propertySetters, fields, objectConstructor); + + } + + public Map getColumnMappings() { + return columnMappings; + } + + public Setter getPropertySetter(String propertyName) { + + Setter setter = getPropertySetterIfExists(propertyName); + + if (setter != null) { + return setter; + } else { + String errorMsg = "Property with name '" + propertyName + "' not found on class " + this.clazz.toString(); + if (this.caseSensitive) { + errorMsg += " (You have turned on case sensitive property search. Is this intentional?)"; + } + throw new Sql2oException(errorMsg); + } + } + + public Setter getPropertySetterIfExists(String propertyName) { + + String name = this.caseSensitive ? propertyName : propertyName.toLowerCase(); + + if (this.columnMappings.containsKey(name)) { + name = this.columnMappings.get(name); + } + + if (autoDeriveColumnNames) { + name = UnderscoreToCamelCase.convert(name); + if (!this.caseSensitive) name = name.toLowerCase(); + } + + return propertyInfo.propertySetters.get(name); + } + + public Class getType() { + return this.clazz; + } + + public Object getValueOfProperty(String propertyName, Object object) { + String name = this.caseSensitive ? propertyName : propertyName.toLowerCase(); + + Field field = this.propertyInfo.fields.get(name); + try { + return field.get(object); + } catch (IllegalAccessException e) { + throw new Sql2oException("could not read value of field " + field.getName() + " on class " + object.getClass().toString(), e); + } + } + + private static class Cache extends AbstractCache { + @Override + protected PropertyAndFieldInfo evaluate(Class key, PojoMetadata param) { + return param.initializePropertyInfo(); + } + } + + private static class PropertyAndFieldInfo { + // since this class is private we can just use field access + // to make HotSpot a little less work for inlining + public final Map propertySetters; + public final Map fields; + public final ObjectConstructor objectConstructor; + + private PropertyAndFieldInfo(Map propertySetters, Map fields, ObjectConstructor objectConstructor) { + this.propertySetters = propertySetters; + this.fields = fields; + this.objectConstructor = objectConstructor; + } + } +} + diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionFieldSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionFieldSetterFactory.java new file mode 100644 index 000000000..724544339 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionFieldSetterFactory.java @@ -0,0 +1,16 @@ +package org.sql2o.reflection; + +import java.lang.reflect.Field; + +/** + * Created with IntelliJ IDEA. + * User: dimzon + * Date: 4/6/14 + * Time: 12:40 AM + * To change this template use File | Settings | File Templates. + */ +public class ReflectionFieldSetterFactory implements FieldSetterFactory { + public Setter newSetter(Field field) { + return new FieldSetter(field); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionMethodSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionMethodSetterFactory.java new file mode 100644 index 000000000..3115228f8 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionMethodSetterFactory.java @@ -0,0 +1,16 @@ +package org.sql2o.reflection; + +import java.lang.reflect.Method; + +/** + * Created with IntelliJ IDEA. + * User: dimzon + * Date: 4/6/14 + * Time: 12:43 AM + * To change this template use File | Settings | File Templates. + */ +public class ReflectionMethodSetterFactory implements MethodSetterFactory { + public Setter newSetter(Method method) { + return new MethodSetter(method); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionObjectConstructorFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionObjectConstructorFactory.java new file mode 100644 index 000000000..d8f33e3bf --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionObjectConstructorFactory.java @@ -0,0 +1,30 @@ +package org.sql2o.reflection; + +import org.sql2o.Sql2oException; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +public class ReflectionObjectConstructorFactory implements ObjectConstructorFactory { + public ObjectConstructor newConstructor(final Class clazz) { + try { + final Constructor ctor = clazz.getDeclaredConstructor(); + ctor.setAccessible(true); + return new ObjectConstructor() { + public Object newInstance() { + try { + return ctor.newInstance((Object[])null); + } catch (InstantiationException e) { + throw new Sql2oException("Could not create a new instance of class " + clazz, e); + } catch (IllegalAccessException e) { + throw new Sql2oException("Could not create a new instance of class " + clazz, e); + } catch (InvocationTargetException e) { + throw new Sql2oException("Could not create a new instance of class " + clazz, e); + } + } + }; + } catch (Throwable e) { + throw new Sql2oException("Could not find parameter-less constructor of class " + clazz, e); + } + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java new file mode 100644 index 000000000..b7da73fe1 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java @@ -0,0 +1,10 @@ +package org.sql2o.reflection; + +/** + * The Setter interface is used by sql2o to set property values when doing automatic column to property mapping + */ +public interface Setter { + + void setProperty(Object obj, Object value); + Class getType(); +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java new file mode 100644 index 000000000..c6b068c7d --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java @@ -0,0 +1,260 @@ +package org.sql2o.reflection; + +import org.sql2o.Sql2oException; +import sun.misc.Unsafe; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +@SuppressWarnings("Unsafe") +public class UnsafeFieldSetterFactory implements FieldSetterFactory, ObjectConstructorFactory { + private final static Unsafe theUnsafe; + static { + try { + Class unsafeClass = Class.forName("sun.misc.Unsafe"); + Field declaredField = unsafeClass.getDeclaredField("theUnsafe"); + declaredField.setAccessible(true); + theUnsafe = (Unsafe) declaredField.get(null); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + public Setter newSetter(final Field field) { + final Class type = field.getType(); + final boolean isStatic = Modifier.isStatic(field.getModifiers()); + + final long offset = isStatic + ? theUnsafe.staticFieldOffset(field) + : theUnsafe.objectFieldOffset(field); + + if (!Modifier.isVolatile(field.getModifiers())) { + if (type == Boolean.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putBoolean(obj, offset, (Boolean) value); + } + + public Class getType() { + return Boolean.TYPE; + } + }; + } + if (type == Character.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putChar(obj, offset, (Character) value); + } + + public Class getType() { + return Character.TYPE; + } + }; + } + if (type == Byte.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putByte(obj, offset, ((Number) value).byteValue()); + } + + public Class getType() { + return Byte.TYPE; + } + }; + } + if (type == Short.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putShort(obj, offset, ((Number) value).shortValue()); + } + + public Class getType() { + return Short.TYPE; + } + }; + } + if (type == Integer.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putInt(obj, offset, ((Number) value).intValue()); + } + + public Class getType() { + return Integer.TYPE; + } + }; + } + if (type == Long.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putLong(obj, offset, ((Number) value).longValue()); + } + + public Class getType() { + return Long.TYPE; + } + }; + } + if (type == Float.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putFloat(obj, offset, ((Number) value).floatValue()); + } + + public Class getType() { + return Float.TYPE; + } + }; + } + if (type == Double.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putDouble(obj, offset, ((Number) value).doubleValue()); + } + + public Class getType() { + return Double.TYPE; + } + }; + } + return new Setter() { + public void setProperty(Object obj, Object value) { + theUnsafe.putObject(obj, offset, value); + } + + public Class getType() { + return type; + } + }; + } + + if (type == Boolean.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putBooleanVolatile(obj, offset, (Boolean) value); + } + + public Class getType() { + return Boolean.TYPE; + } + }; + } + if (type == Character.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putCharVolatile(obj, offset, (Character) value); + } + + public Class getType() { + return Character.TYPE; + } + }; + } + if (type == Byte.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putByteVolatile(obj, offset, ((Number) value).byteValue()); + } + + public Class getType() { + return Byte.TYPE; + } + }; + } + if (type == Short.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putShortVolatile(obj, offset, ((Number) value).shortValue()); + } + + public Class getType() { + return Short.TYPE; + } + }; + } + if (type == Integer.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putIntVolatile(obj, offset, ((Number) value).intValue()); + } + + public Class getType() { + return Integer.TYPE; + } + }; + } + if (type == Long.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putLongVolatile(obj, offset, ((Number) value).longValue()); + } + + public Class getType() { + return Long.TYPE; + } + }; + } + if (type == Float.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putFloatVolatile(obj, offset, ((Number) value).floatValue()); + } + + public Class getType() { + return Float.TYPE; + } + }; + } + if (type == Double.TYPE) { + return new Setter() { + public void setProperty(Object obj, Object value) { + if (value == null) return; + theUnsafe.putDoubleVolatile(obj, offset, ((Number) value).doubleValue()); + } + + public Class getType() { + return Double.TYPE; + } + }; + } + return new Setter() { + public void setProperty(Object obj, Object value) { + theUnsafe.putObjectVolatile(obj, offset, value); + } + + public Class getType() { + return type; + } + }; + } + + public ObjectConstructor newConstructor(final Class clazz) { + return getConstructor(clazz); + } + public static ObjectConstructor getConstructor(final Class clazz) { + return new ObjectConstructor() { + public Object newInstance() { + try { + return theUnsafe.allocateInstance(clazz); + } catch (InstantiationException e) { + throw new Sql2oException("Could not create a new instance of class " + clazz, e); + } + } + }; + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/package-info.java b/blade-sql2o/src/main/java/org/sql2o/reflection/package-info.java new file mode 100644 index 000000000..b3e497f59 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/package-info.java @@ -0,0 +1,4 @@ +/** + * Provides the internal functionality used by sql2o to accomplish the automatic row to property mapping. + */ +package org.sql2o.reflection; \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/AbstractCache.java b/blade-sql2o/src/main/java/org/sql2o/tools/AbstractCache.java new file mode 100644 index 000000000..5319b802e --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/tools/AbstractCache.java @@ -0,0 +1,60 @@ +package org.sql2o.tools; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * just inherit and implement evaluate + * User: dimzon + * Date: 4/6/14 + * Time: 10:35 PM + */ +public abstract class AbstractCache { + private final Map map; + private final Lock rl; + private final Lock wl; + /*** + * @param map - allows to define your own map implementation + */ + public AbstractCache(Map map) { + this.map = map; + ReadWriteLock rrwl = new ReentrantReadWriteLock(); + rl = rrwl.readLock(); + wl = rrwl.writeLock(); + } + + public AbstractCache(){ + this(new HashMap()); + } + + public V get(K key,E param){ + V value; + + try { + // let's take read lock first + rl.lock(); + value = map.get(key); + } finally { + rl.unlock(); + } + if(value!=null) return value; + + try { + wl.lock(); + value = map.get(key); + if(value==null){ + value = evaluate(key, param); + map.put(key,value); + } + } finally { + wl.unlock(); + } + return value; + } + + protected abstract V evaluate(K key, E param); + +} diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/ClassUtils.java b/blade-sql2o/src/main/java/org/sql2o/tools/ClassUtils.java new file mode 100644 index 000000000..3f92a3963 --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/tools/ClassUtils.java @@ -0,0 +1,30 @@ +package org.sql2o.tools; + +/** + * @author Alden Quimby + */ +public final class ClassUtils { + +// private static ClassLoader getClassLoader() { +// return Thread.currentThread().getContextClassLoader(); +// } + + /** + * Check whether the {@link Class} identified by the supplied name is present. + * + * @param className the name of the class to check + * @return true if class is present, false otherwise + */ + public static boolean isPresent(String className) { + try { + // what's wrong with old plain Class.forName + // this code supposed to work everywhere including containers + Class.forName(className); + // getClassLoader().loadClass(className); + return true; + } + catch (Throwable ex) { + return false; + } + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java b/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java new file mode 100644 index 000000000..8a3a4d76d --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java @@ -0,0 +1,67 @@ +package org.sql2o.tools; + +/** + * Detects whether optional sql2o features are available. + * + * @author Alden Quimby + */ +@SuppressWarnings("UnusedDeclaration") +public final class FeatureDetector { + + private FeatureDetector() + {} + + static { + setCacheUnderscoreToCamelcaseEnabled(true); // enabled by default + } + + private static Boolean jodaTimeAvailable; + private static Boolean slf4jAvailable; + private static Boolean oracleAvailable; + private static boolean cacheUnderscoreToCamelcaseEnabled; + + /** + * @return {@code true} if Joda-Time is available, {@code false} otherwise. + */ + public static boolean isJodaTimeAvailable() { + if (jodaTimeAvailable == null) { + jodaTimeAvailable = ClassUtils.isPresent("org.joda.time.DateTime"); + } + return jodaTimeAvailable; + } + + /** + * @return {@code true} if Slf4j is available, {@code false} otherwise. + */ + public static boolean isSlf4jAvailable() { + if (slf4jAvailable == null) { + slf4jAvailable = ClassUtils.isPresent("org.slf4j.Logger"); + } + return slf4jAvailable; + } + + /** + * @return {@code true} if oracle.sql is available, {@code false} otherwise. + */ + public static boolean isOracleAvailable() { + if (oracleAvailable == null) { + oracleAvailable = ClassUtils.isPresent("oracle.sql.TIMESTAMP"); + } + return oracleAvailable; + } + + /** + * + * @return {@code true} if caching of underscore to camelcase is enabled. + */ + public static boolean isCacheUnderscoreToCamelcaseEnabled() { + return cacheUnderscoreToCamelcaseEnabled; + } + + /** + * Turn caching of underscore to camelcase on or off. + */ + public static void setCacheUnderscoreToCamelcaseEnabled(boolean cacheUnderscoreToCamelcaseEnabled) { + FeatureDetector.cacheUnderscoreToCamelcaseEnabled = cacheUnderscoreToCamelcaseEnabled; + } +} \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/IOUtils.java b/blade-sql2o/src/main/java/org/sql2o/tools/IOUtils.java new file mode 100644 index 000000000..92a44e09f --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/tools/IOUtils.java @@ -0,0 +1,39 @@ +package org.sql2o.tools; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +/** + * User: lars + * Date: 6/14/13 + * Time: 12:02 AM + */ +public class IOUtils { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + int n; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + } + return output.toByteArray(); + } + + public static String toString(Reader input) throws IOException { + StringBuilder output = new StringBuilder(); + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + int n; + while (EOF != (n = input.read(buffer))) { + output.append(buffer, 0, n); + } + return output.toString(); + } + + +} diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java b/blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java new file mode 100644 index 000000000..ddaac441d --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java @@ -0,0 +1,37 @@ +package org.sql2o.tools; + +import java.util.HashMap; +import java.util.Map; + +/** + * Takes a string formatted like: 'my_string_variable' and returns it as: 'myStringVariable' + * + * @author ryancarlson + * @author dimzon - complete rewrite + */ +public class UnderscoreToCamelCase { + public static String convert(String underscore){ + if(underscore==null || underscore.isEmpty()) return underscore; + return convert00(underscore); + } + + private static String convert00(String underscore){ + char[] chars = underscore.toCharArray(); + int write=-1,len=chars.length; + boolean upper=false; + for (int read = 0; read < len; ++read) { + char c = chars[read]; + if('_'==c){ + upper = true; + continue; + } + if(upper){ + upper = false; + chars[++write]=Character.toUpperCase(c); + } else { + chars[++write]=Character.toLowerCase(c); + } + } + return new String(chars, 0, ++write); + } +} diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/package-info.java b/blade-sql2o/src/main/java/org/sql2o/tools/package-info.java new file mode 100644 index 000000000..4c2218e1a --- /dev/null +++ b/blade-sql2o/src/main/java/org/sql2o/tools/package-info.java @@ -0,0 +1,4 @@ +/** + * internal tools. + */ +package org.sql2o.tools; \ No newline at end of file From 5f3926d061356994293536f10d3a823e29316c38 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 31 Aug 2015 12:53:44 +0800 Subject: [PATCH 118/545] refactor the code --- blade-core/pom.xml | 2 +- blade-core/src/main/java/blade/Blade.java | 9 ++ .../src/main/java/blade/BladeConfig.java | 50 --------- .../main/java/blade/BladeConfigurator.java | 23 ---- .../src/main/java/blade/BladeFilter.java | 2 +- .../src/main/java/blade/ioc/Container.java | 8 +- .../main/java/blade/ioc/DefaultContainer.java | 101 +++++++++--------- .../java/blade/route/DefaultRouteMatcher.java | 2 +- .../java/blade/route/RouteMatcherBuilder.java | 10 +- blade-sql2o/pom.xml | 26 +++-- .../java/blade/plugin/sql2o/Sql2oPlugin.java | 63 ++++++----- .../sql2o/connection/ConnectionHolder.java | 27 ----- .../SingleThreadConnectionHolder.java | 28 ----- .../plugin/sql2o/ds/DataSourceManager.java | 3 +- .../blade/plugin/sql2o/pool/Constant.java | 5 + .../blade/plugin/sql2o/pool/PoolConfig.java | 10 ++ pom.xml | 2 +- 17 files changed, 139 insertions(+), 232 deletions(-) delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/connection/ConnectionHolder.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/connection/SingleThreadConnectionHolder.java diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 46be761ad..eaa01c691 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -19,7 +19,7 @@ com.bladejava blade-kit - 1.2.6 + 1.2.7-alpha javax.servlet diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index 6d2f5e073..0be268f0a 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -27,6 +27,7 @@ import blade.render.Render; import blade.render.RenderFactory; import blade.route.HttpMethod; +import blade.route.RouteBase; import blade.route.Router; import blade.route.RouteMatcherBuilder; @@ -275,6 +276,14 @@ public static synchronized void debug(boolean isdebug){ BLADE_CONFIG.setDebug(isdebug); } + /** + * 加载一个Route + * @param route + */ + public static synchronized void load(Class route){ + //Object object = Class + } + /** * 注册一个函数式的路由
*

diff --git a/blade-core/src/main/java/blade/BladeConfig.java b/blade-core/src/main/java/blade/BladeConfig.java index a2acce6f3..5520ee7c6 100644 --- a/blade-core/src/main/java/blade/BladeConfig.java +++ b/blade-core/src/main/java/blade/BladeConfig.java @@ -54,16 +54,6 @@ public class BladeConfig { private String view404; // 500视图位置 private String view500; - // 数据库URL - private String dbUrl; - // 数据库驱动 - private String dbDriver; - // 数据库登录名 - private String dbUser; - // 数据库登录密码 - private String dbPass; - // 是否开启数据库缓存 - private boolean isOpenCache = false; // 是否是DEBUG模式 private boolean isDebug = true; @@ -142,46 +132,6 @@ public void setStaticFolders(String ... packages) { staticFolders.addAll(Arrays.asList(packages)); } - public String getDbUrl() { - return dbUrl; - } - - public void setDbUrl(String dbUrl) { - this.dbUrl = dbUrl; - } - - public String getDbDriver() { - return dbDriver; - } - - public void setDbDriver(String dbDriver) { - this.dbDriver = dbDriver; - } - - public String getDbUser() { - return dbUser; - } - - public void setDbUser(String dbUser) { - this.dbUser = dbUser; - } - - public String getDbPass() { - return dbPass; - } - - public void setDbPass(String dbPass) { - this.dbPass = dbPass; - } - - public boolean isOpenCache() { - return isOpenCache; - } - - public void setOpenCache(boolean isOpenCache) { - this.isOpenCache = isOpenCache; - } - public String getView404() { return view404; } diff --git a/blade-core/src/main/java/blade/BladeConfigurator.java b/blade-core/src/main/java/blade/BladeConfigurator.java index 68f6edeaf..d5d3135b7 100644 --- a/blade-core/src/main/java/blade/BladeConfigurator.java +++ b/blade-core/src/main/java/blade/BladeConfigurator.java @@ -45,11 +45,6 @@ public BladeConfigurator(BladeConfig bladeConfig, private static final String BLADE_PREFIX = "blade.prefix"; private static final String BLADE_SUFFIX = "blade.suffix"; private static final String BLADE_FILTER_FOLDER = "blade.filter_folder"; - private static final String BLADE_DBURL = "blade.dburl"; - private static final String BLADE_DBDRIVER = "blade.dbdriver"; - private static final String BLADE_DBUSER = "blade.dbuser"; - private static final String BLADE_DBPASS = "blade.dbpass"; - private static final String BLADE_OPENCACHE = "blade.opencache"; private static final String BLADE_ENCODING = "blade.encoding"; private static final String BLADE_VIEW_404 = "blade.view404"; private static final String BLADE_VIEW_500 = "blade.view500"; @@ -66,11 +61,6 @@ public void run() { String prefix = configMap.get(BLADE_PREFIX); String suffix = configMap.get(BLADE_SUFFIX); String filter_folder = configMap.get(BLADE_FILTER_FOLDER); - String dburl = configMap.get(BLADE_DBURL); - String dbdriver = configMap.get(BLADE_DBDRIVER); - String dbuser = configMap.get(BLADE_DBUSER); - String dbpass = configMap.get(BLADE_DBPASS); - String opencache = configMap.get(BLADE_OPENCACHE); String encoding = configMap.get(BLADE_ENCODING); String view404 = configMap.get(BLADE_VIEW_404); String view500 = configMap.get(BLADE_VIEW_500); @@ -103,19 +93,6 @@ public void run() { bladeConfig.setViewSuffix(suffix); } - if (StringKit.isNotBlank(dburl) && StringKit.isNotBlank(dbdriver) && - StringKit.isNotBlank(dbuser) && StringKit.isNotBlank(dbpass)) { - bladeConfig.setDbUrl(dburl); - bladeConfig.setDbDriver(dbdriver); - bladeConfig.setDbUser(dbuser); - bladeConfig.setDbPass(dbpass); - - if (StringKit.isNotBlank(opencache)) { - Boolean opencacheBool = Boolean.valueOf(opencache); - bladeConfig.setOpenCache(opencacheBool); - } - } - if (StringKit.isNotBlank(encoding)) { bladeConfig.setEncoding(encoding); } diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java index eb0540574..d478b1974 100644 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ b/blade-core/src/main/java/blade/BladeFilter.java @@ -72,7 +72,7 @@ public void init(FilterConfig filterConfig) throws ServletException { LOGGER.info("blade init complete!"); } } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); System.exit(0); } diff --git a/blade-core/src/main/java/blade/ioc/Container.java b/blade-core/src/main/java/blade/ioc/Container.java index 2246cbc3c..64cacc7c3 100644 --- a/blade-core/src/main/java/blade/ioc/Container.java +++ b/blade-core/src/main/java/blade/ioc/Container.java @@ -145,7 +145,13 @@ public interface Container { * 初始化IOC */ void initWired(); - + + /** + * 注入一个类 + * @param object + */ + void injection(Object object); + /** * @return 返回ioc容器中的所有bean对象的K,V */ diff --git a/blade-core/src/main/java/blade/ioc/DefaultContainer.java b/blade-core/src/main/java/blade/ioc/DefaultContainer.java index 41ae57a14..efbe4c13f 100644 --- a/blade-core/src/main/java/blade/ioc/DefaultContainer.java +++ b/blade-core/src/main/java/blade/ioc/DefaultContainer.java @@ -230,57 +230,11 @@ private void put(Class clazz, List listObject){ @Override public void initWired() throws RuntimeException { Iterator> it = BEAN_CONTAINER.entrySet().iterator(); - - try { - while (it.hasNext()) { - - Map.Entry entry = (Map.Entry) it.next(); - - Object obj = entry.getValue(); - - // 所有字段 - Field[] fields = obj.getClass().getDeclaredFields(); - - for (Field field : fields) { - - // 需要注入的字段 - Inject inject = field.getAnnotation(Inject.class); - if (null != inject ) { - - // 要注入的字段 - Object injectField = single().getBean(field.getType(), Scope.SINGLE); - // 指定装配到哪个class - if(inject.value() != Class.class){ - // 指定装配的类 - injectField = single().getBean(inject.value(), Scope.SINGLE); - - if (null == injectField) { - injectField = recursiveAssembly(inject.value()); - } - - } else { - if (null == injectField) { - injectField = recursiveAssembly(field.getType()); - } - } - - if (null == injectField) { - throw new BladeException("Unable to load " + field.getType().getCanonicalName() + "!"); - } - boolean accessible = field.isAccessible(); - field.setAccessible(true); - field.set(obj, injectField); - field.setAccessible(accessible); - } - } - } - } catch (SecurityException e) { - LOGGER.error(e.getMessage()); - } catch (IllegalArgumentException e) { - LOGGER.error(e.getMessage()); - } catch (IllegalAccessException e) { - LOGGER.error(e.getMessage()); - } + while (it.hasNext()) { + Map.Entry entry = (Map.Entry) it.next(); + Object object = entry.getValue(); + injection(object); + } } // 装配 @@ -362,4 +316,49 @@ public boolean removeAll() { return true; } + @Override + public void injection(Object object) { + // 所有字段 + try { + Field[] fields = object.getClass().getDeclaredFields(); + for (Field field : fields) { + // 需要注入的字段 + Inject inject = field.getAnnotation(Inject.class); + if (null != inject ) { + + // 要注入的字段 + Object injectField = single().getBean(field.getType(), Scope.SINGLE); + // 指定装配到哪个class + if(inject.value() != Class.class){ + // 指定装配的类 + injectField = single().getBean(inject.value(), Scope.SINGLE); + + if (null == injectField) { + injectField = recursiveAssembly(inject.value()); + } + + } else { + if (null == injectField) { + injectField = recursiveAssembly(field.getType()); + } + } + + if (null == injectField) { + throw new BladeException("Unable to load " + field.getType().getCanonicalName() + "!"); + } + boolean accessible = field.isAccessible(); + field.setAccessible(true); + field.set(object, injectField); + field.setAccessible(accessible); + } + } + } catch (SecurityException e) { + LOGGER.error(e); + } catch (IllegalArgumentException e) { + LOGGER.error(e); + } catch (IllegalAccessException e) { + LOGGER.error(e); + } + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index 11011b1bf..e457d5c38 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -216,7 +216,7 @@ public void addInterceptor(Class target, Method execMethod, String url, HttpM * @param method 路由http方法 * @param acceptType 路由acceptType */ - public void addRoute(Router router, Method execMethod, String url, HttpMethod method, String acceptType) { + public void addRoute(Router router, String url, HttpMethod method, String acceptType) { RouteMatcher entry = new RouteMatcher(); entry.router = router; entry.httpMethod = method; diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index 538e6b253..54a7806f1 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -142,10 +142,7 @@ public static void buildFunctional(String path, Class clazz, String methodNam */ public static void buildHandler(String path, Router router, HttpMethod httpMethod){ if(StringKit.isNotBlank(path) && null != router){ - Class clazz = blade.route.Router.class; - container.registBean(router); - Method execMethod = ReflectKit.getMethodByName(clazz, "handler"); - defaultRouteMatcher.addRoute(clazz, execMethod, path, httpMethod, "*/*"); + defaultRouteMatcher.addRoute(router, path, httpMethod, "*/*"); } else { throw new BladeException("an unqualified configuration"); } @@ -156,10 +153,7 @@ public static void buildHandler(String path, Router router, HttpMethod httpMetho */ public static void buildInterceptor(String path, Router router, HttpMethod httpMethod){ if(StringKit.isNotBlank(path) && null != router){ - Class clazz = blade.route.Router.class; - container.registBean(router); - Method execMethod = ReflectKit.getMethodByName(clazz, "handler"); - defaultRouteMatcher.addInterceptor(clazz, execMethod, path, httpMethod, "*/*"); + defaultRouteMatcher.addInterceptor(router, path, httpMethod, "*/*"); } else { throw new BladeException("an unqualified configuration"); } diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 5e20f4bf4..6cb9ae685 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,29 +11,35 @@ blade-sql2o jar - 1.2.7-alpha + 1.2.8-alpha blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o - - org.sql2o - sql2o - 1.5.4 - - com.bladejava blade-core ${blade.version} - provided + compile com.bladejava blade-cache 1.2.2 - provided + true + + + joda-time + joda-time + 2.8.2 + true - + + org.slf4j + slf4j-api + 1.6.4 + true + + diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index 3162b4c86..d1a7e1d7a 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -4,7 +4,6 @@ import javax.sql.DataSource; -import blade.Blade; import blade.kit.PropertyKit; import blade.kit.StringKit; import blade.kit.log.Logger; @@ -28,8 +27,6 @@ public enum Sql2oPlugin implements Plugin { private PoolConfig poolConfig; - private boolean openCache; - private Sql2oPlugin() { } @@ -55,72 +52,76 @@ public Sql2oPlugin load(String filePath){ String isCheakPool = configProperties.getProperty(Constant.IS_CHECK_POOL); String periodCheck = configProperties.getProperty(Constant.PERIOD_CHECK); String lazyCheck = configProperties.getProperty(Constant.LAZY_CHECK); + String openCache = configProperties.getProperty(Constant.OPEN_CACHE); String poolName = configProperties.getProperty(Constant.POOL_NAME); - PoolConfig poolConfig = new PoolConfig(); + if(null == INSTANCE.poolConfig){ + INSTANCE.poolConfig = new PoolConfig(); + } if(StringKit.isNotBlank(drive)){ - poolConfig.setDriverName(drive); + INSTANCE.poolConfig.setDriverName(drive); } if(StringKit.isNotBlank(url)){ - poolConfig.setUrl(url); + INSTANCE.poolConfig.setUrl(url); } if(StringKit.isNotBlank(username)){ - poolConfig.setUserName(username); + INSTANCE.poolConfig.setUserName(username); } if(StringKit.isNotBlank(password)){ - poolConfig.setPassWord(password); + INSTANCE.poolConfig.setPassWord(password); } if(StringKit.isNotBlank(keepAliveSql)){ - poolConfig.setKeepAliveSql(keepAliveSql); + INSTANCE.poolConfig.setKeepAliveSql(keepAliveSql); } if(StringKit.isNotBlank(minConn) && StringKit.isNumber(minConn.trim())){ - poolConfig.setMinConn(Integer.valueOf(minConn.trim())); + INSTANCE.poolConfig.setMinConn(Integer.valueOf(minConn.trim())); } if(StringKit.isNotBlank(maxConn) && StringKit.isNumber(maxConn.trim())){ - poolConfig.setMaxConn(Integer.valueOf(maxConn.trim())); + INSTANCE.poolConfig.setMaxConn(Integer.valueOf(maxConn.trim())); } if(StringKit.isNotBlank(initConn) && StringKit.isNumber(initConn.trim())){ - poolConfig.setInitConn(Integer.valueOf(initConn.trim())); + INSTANCE.poolConfig.setInitConn(Integer.valueOf(initConn.trim())); } if(StringKit.isNotBlank(maxActiveConn) && StringKit.isNumber(maxActiveConn.trim())){ - poolConfig.setMaxActiveConn(Integer.valueOf(maxActiveConn.trim())); + INSTANCE.poolConfig.setMaxActiveConn(Integer.valueOf(maxActiveConn.trim())); } if(StringKit.isNotBlank(connTimeOut) && StringKit.isNumber(connTimeOut.trim())){ - poolConfig.setConnTimeOut(Long.valueOf(connTimeOut.trim())); + INSTANCE.poolConfig.setConnTimeOut(Long.valueOf(connTimeOut.trim())); } if(StringKit.isNotBlank(connWaitTime) && StringKit.isNumber(connWaitTime.trim())){ - poolConfig.setConnWaitTime(Long.valueOf(connWaitTime.trim())); + INSTANCE.poolConfig.setConnWaitTime(Long.valueOf(connWaitTime.trim())); } if(StringKit.isNotBlank(isCheakPool)){ - poolConfig.setCheakPool(Boolean.valueOf(isCheakPool.trim())); + INSTANCE.poolConfig.setCheakPool(Boolean.valueOf(isCheakPool.trim())); } if(StringKit.isNotBlank(periodCheck) && StringKit.isNumber(periodCheck.trim())){ - poolConfig.setPeriodCheck(Long.valueOf(periodCheck.trim())); + INSTANCE.poolConfig.setPeriodCheck(Long.valueOf(periodCheck.trim())); } if(StringKit.isNotBlank(lazyCheck) && StringKit.isNumber(lazyCheck.trim())){ - poolConfig.setInitDelay(Long.valueOf(lazyCheck.trim())); + INSTANCE.poolConfig.setInitDelay(Long.valueOf(lazyCheck.trim())); } - if(StringKit.isNotBlank(poolName)){ - poolConfig.setPoolName(poolName); + if(StringKit.isNotBlank(openCache)){ + INSTANCE.poolConfig.setIsopenCache(Boolean.valueOf(openCache.trim())); } - INSTANCE.poolConfig = poolConfig; - INSTANCE.openCache = Blade.config().isOpenCache(); + if(StringKit.isNotBlank(poolName)){ + INSTANCE.poolConfig.setPoolName(poolName); + } return INSTANCE; } @@ -135,6 +136,14 @@ public Sql2oPlugin config(PoolConfig poolConfig){ return INSTANCE; } + public Sql2oPlugin openCache(){ + if(null == INSTANCE.poolConfig){ + INSTANCE.poolConfig = new PoolConfig(); + INSTANCE.poolConfig.setIsopenCache(true); + } + return INSTANCE; + } + /** * 设置数据库配置 * @@ -160,13 +169,8 @@ public Sql2oPlugin config(String driver, String url, String user, String pass){ return INSTANCE; } - public Sql2oPlugin openCache(){ - INSTANCE.openCache = true; - return INSTANCE; - } - public boolean isOpenCache() { - return INSTANCE.openCache; + return INSTANCE.poolConfig.isIsopenCache(); } public PoolConfig poolConfig(){ @@ -175,6 +179,9 @@ public PoolConfig poolConfig(){ @Override public void run() { + + DataSourceManager.run(); + DataSource dataSource = DataSourceManager.getDataSource(); ConnectionPool connectionPool = DataSourceManager.getConnectionPool(); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/connection/ConnectionHolder.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/connection/ConnectionHolder.java deleted file mode 100644 index 3aef7b8cb..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/connection/ConnectionHolder.java +++ /dev/null @@ -1,27 +0,0 @@ -package blade.plugin.sql2o.connection; - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; - -import javax.sql.DataSource; - -public class ConnectionHolder { - - private Map connectionMap = new HashMap(); - - public Connection getConnection(DataSource dataSource) throws SQLException { - Connection connection = connectionMap.get(dataSource); - if (connection == null || connection.isClosed()) { - connection = dataSource.getConnection(); - connectionMap.put(dataSource, connection); - } - - return connection; - } - - public void removeConnection(DataSource dataSource) { - connectionMap.remove(dataSource); - } -} \ No newline at end of file diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/connection/SingleThreadConnectionHolder.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/connection/SingleThreadConnectionHolder.java deleted file mode 100644 index f3741c0b4..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/connection/SingleThreadConnectionHolder.java +++ /dev/null @@ -1,28 +0,0 @@ -package blade.plugin.sql2o.connection; - -import java.sql.Connection; -import java.sql.SQLException; - -import javax.sql.DataSource; - -public class SingleThreadConnectionHolder { - - private static ThreadLocal localConnectionHolder = new ThreadLocal(); - - public static Connection getConnection(DataSource dataSource) throws SQLException { - return getConnectionHolder().getConnection(dataSource); - } - - public static void removeConnection(DataSource dataSource) { - getConnectionHolder().removeConnection(dataSource); - } - - private static ConnectionHolder getConnectionHolder() { - ConnectionHolder connectionHolder = localConnectionHolder.get(); - if (connectionHolder == null) { - connectionHolder = new ConnectionHolder(); - localConnectionHolder.set(connectionHolder); - } - return connectionHolder; - } -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java index d805e51e7..38d83f2a7 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java @@ -32,8 +32,7 @@ public final class DataSourceManager { private DataSourceManager() { } - static{ - + public static void run(){ Object dsFactoryObj = beanFactory.getBean(AbstractDataSource.class); if(null != dsFactoryObj && dsFactoryObj instanceof AbstractDataSource){ DataSourceManager.dataSource = ((AbstractDataSource) dsFactoryObj).getDataSource(); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java index e7be8403e..81f44ccd9 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java @@ -79,6 +79,11 @@ public final class Constant { * 连接池名称 */ public static final String POOL_NAME = "blade.db.poolName"; + + /** + * 是否开启缓存 + */ + public static final String OPEN_CACHE = "blade.db.opencache"; /** * 默认连接池名称 diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java index b9fa8f1b2..d12cfd5b4 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java @@ -77,6 +77,8 @@ public class PoolConfig { */ private long initDelay = Constant.DEFAULT_INIT_DELAY; + private boolean isopenCache = false; + /** * 数据库连接池的名称 */ @@ -208,6 +210,14 @@ public void setKeepAliveSql(String keepAliveSql) { this.keepAliveSql = keepAliveSql; } + public boolean isIsopenCache() { + return isopenCache; + } + + public void setIsopenCache(boolean isopenCache) { + this.isopenCache = isopenCache; + } + @Override public String toString() { return "PoolConfig [maxConn=" + maxConn + ", minConn=" + minConn diff --git a/pom.xml b/pom.xml index 763cf88f5..83387955f 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.8 + 1.2.9-alpha From 4811a156b97aea307e26281a752cfc716d0cb7e8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 31 Aug 2015 13:08:01 +0800 Subject: [PATCH 119/545] refactor the code --- blade-core/src/main/java/blade/Blade.java | 7 +++- .../java/blade/plugin/sql2o/Sql2oPlugin.java | 3 ++ .../sql2o/converters/ByteArrayConverter.java | 6 +-- .../org/sql2o/converters/StringConverter.java | 6 +-- .../org/sql2o/reflection/FactoryFacade.java | 3 +- .../org/sql2o/reflection/FieldSetter.java | 2 +- .../reflection/MethodAccessorsGenerator.java | 20 +++++----- .../org/sql2o/reflection/MethodSetter.java | 2 +- .../main/java/org/sql2o/reflection/Pojo.java | 2 +- .../sql2o/reflection/PojoIntrospector.java | 1 - .../org/sql2o/reflection/PojoMetadata.java | 12 +++--- .../java/org/sql2o/reflection/Setter.java | 3 +- .../reflection/UnsafeFieldSetterFactory.java | 14 ++++--- .../main/java/org/sql2o/tools/ClassUtils.java | 30 -------------- .../java/org/sql2o/tools/FeatureDetector.java | 9 +++-- .../main/java/org/sql2o/tools/IOUtils.java | 39 ------------------- .../sql2o/tools/UnderscoreToCamelCase.java | 3 -- 17 files changed, 51 insertions(+), 111 deletions(-) delete mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/ClassUtils.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/IOUtils.java diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index 0be268f0a..d1f7f7bd9 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -23,6 +23,7 @@ import blade.ioc.DefaultContainer; import blade.kit.IOKit; import blade.kit.PropertyKit; +import blade.kit.ReflectKit; import blade.kit.json.JSONKit; import blade.render.Render; import blade.render.RenderFactory; @@ -281,7 +282,11 @@ public static synchronized void debug(boolean isdebug){ * @param route */ public static synchronized void load(Class route){ - //Object object = Class + Object object = ReflectKit.newInstance(route); + if(null != object){ + container.injection(object); + ReflectKit.invokeMehodByName(object, "run"); + } } /** diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index d1a7e1d7a..5b3fa160d 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -170,6 +170,9 @@ public Sql2oPlugin config(String driver, String url, String user, String pass){ } public boolean isOpenCache() { + if(null == INSTANCE.poolConfig){ + return false; + } return INSTANCE.poolConfig.isIsopenCache(); } diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java index 6edce531e..6270ca5e5 100644 --- a/blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java +++ b/blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java @@ -1,12 +1,12 @@ package org.sql2o.converters; -import org.sql2o.tools.IOUtils; - import java.io.IOException; import java.io.InputStream; import java.sql.Blob; import java.sql.SQLException; +import blade.kit.IOKit; + /** * User: lars * Date: 6/13/13 @@ -23,7 +23,7 @@ public byte[] convert(Object val) throws ConverterException { try { try { stream = b.getBinaryStream(); - return IOUtils.toByteArray(stream); + return IOKit.toByteArray(stream); } finally { if(stream!=null) { try { diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java index 3a23d965f..e17f4409d 100644 --- a/blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java +++ b/blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java @@ -1,12 +1,12 @@ package org.sql2o.converters; -import org.sql2o.tools.IOUtils; - import java.io.IOException; import java.io.Reader; import java.sql.Clob; import java.sql.SQLException; +import blade.kit.IOKit; + /** * Used by sql2o to convert a value from the database into a {@link String}. */ @@ -39,7 +39,7 @@ public String convert(Object val) throws ConverterException { Reader reader = (Reader) val; try { try { - return IOUtils.toString(reader); + return IOKit.toString(reader); } catch (IOException e) { throw new ConverterException("error converting reader to String", e); } diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java b/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java index bcdd855ba..121b1adc0 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java @@ -3,7 +3,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; -@SuppressWarnings("Unsafe") public class FactoryFacade { private final static FactoryFacade instance; @@ -21,7 +20,7 @@ public class FactoryFacade { } FieldSetterFactory f; try { - Class cls = Class.forName("org.sql2o.reflection.UnsafeFieldSetterFactory"); + Class cls = Class.forName("org.sql2o.reflection.UnsafeFieldSetterFactory"); f = (FieldSetterFactory) cls.newInstance(); if(o==null) o = (ObjectConstructorFactory) f; } catch (Throwable ex) { diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java index 31af9d97f..706c57136 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java @@ -28,7 +28,7 @@ public void setProperty(Object obj, Object value) { } } - public Class getType() { + public Class getType() { return field.getType(); } } diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java index 913be05b7..cbe5b6625 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java @@ -1,19 +1,21 @@ package org.sql2o.reflection; -import org.sql2o.Sql2oException; -import sun.reflect.ConstructorAccessor; -import sun.reflect.FieldAccessor; -import sun.reflect.MethodAccessor; - import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -@SuppressWarnings("UnusedDeclaration") +import org.sql2o.Sql2oException; + +import sun.reflect.ConstructorAccessor; +import sun.reflect.FieldAccessor; +import sun.reflect.MethodAccessor; + +@SuppressWarnings("restriction") public class MethodAccessorsGenerator implements MethodSetterFactory, ObjectConstructorFactory { private static final ThreadLocal generatorObjectHolder; - private static final MethodAccessor generateMethod; + + private static final MethodAccessor generateMethod; private static final MethodAccessor generateConstructor; private static final MethodAccessor generateSerializationConstructor; private static final MethodAccessor newFieldAccessor; @@ -117,7 +119,7 @@ public static ConstructorAccessor newConstructorAccessor(Constructor bar, Cla } public Setter newSetter(final Method method) { - final Class type = method.getParameterTypes()[0]; + final Class type = method.getParameterTypes()[0]; final MethodAccessor methodAccessor = newMethodAccessor(method); return new Setter() { public void setProperty(Object obj, Object value) { @@ -129,7 +131,7 @@ public void setProperty(Object obj, Object value) { } } - public Class getType() { + public Class getType() { return type; } }; diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java index e27043199..02ab2b6c6 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java @@ -32,7 +32,7 @@ public void setProperty(Object obj, Object value) { } } - public Class getType() { + public Class getType() { return type; } } diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java b/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java index 389303f19..575f6401c 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java @@ -29,7 +29,7 @@ public Pojo(PojoMetadata metadata, boolean caseSensitive){ object = objectConstructor.newInstance(); } - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "rawtypes" }) public void setProperty(String propertyPath, Object value, Quirks quirks){ // String.split uses RegularExpression // this is overkill for every column for every row diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java index bfb1faa2b..9879de8ef 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java @@ -20,7 +20,6 @@ // TODO: move introspection code from PojoMetadata to PojoIntrospector -@SuppressWarnings("UnusedDeclaration") public class PojoIntrospector { private static final AbstractCache, Map, Void> rpCache = new AbstractCache, Map, Void>() { diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java index 2f9db165c..aa02af2bf 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java @@ -24,7 +24,7 @@ public class PojoMetadata { private boolean caseSensitive; private boolean autoDeriveColumnNames; public final boolean throwOnMappingFailure; - private Class clazz; + private Class clazz; public boolean isCaseSensitive() { return caseSensitive; @@ -56,7 +56,7 @@ public int hashCode() { return result; } - public PojoMetadata(Class clazz, boolean caseSensitive, boolean autoDeriveColumnNames, Map columnMappings, boolean throwOnMappingError) { + public PojoMetadata(Class clazz, boolean caseSensitive, boolean autoDeriveColumnNames, Map columnMappings, boolean throwOnMappingError) { this.caseSensitive = caseSensitive; this.autoDeriveColumnNames = autoDeriveColumnNames; this.clazz = clazz; @@ -83,7 +83,7 @@ private PropertyAndFieldInfo initializePropertyInfo() { HashMap propertySetters = new HashMap(); HashMap fields = new HashMap(); - Class theClass = clazz; + Class theClass = clazz; ObjectConstructor objectConstructor = factoryFacade.newConstructor(theClass); do { for (Field f : theClass.getDeclaredFields()) { @@ -149,7 +149,7 @@ public Setter getPropertySetterIfExists(String propertyName) { return propertyInfo.propertySetters.get(name); } - public Class getType() { + public Class getType() { return this.clazz; } @@ -164,9 +164,9 @@ public Object getValueOfProperty(String propertyName, Object object) { } } - private static class Cache extends AbstractCache { + private static class Cache extends AbstractCache, PropertyAndFieldInfo, PojoMetadata> { @Override - protected PropertyAndFieldInfo evaluate(Class key, PojoMetadata param) { + protected PropertyAndFieldInfo evaluate(Class key, PojoMetadata param) { return param.initializePropertyInfo(); } } diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java index b7da73fe1..caf9e3f1e 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java @@ -6,5 +6,6 @@ public interface Setter { void setProperty(Object obj, Object value); - Class getType(); + @SuppressWarnings("rawtypes") + Class getType(); } diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java index c6b068c7d..93d5ae1e2 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java @@ -1,17 +1,19 @@ package org.sql2o.reflection; -import org.sql2o.Sql2oException; -import sun.misc.Unsafe; - import java.lang.reflect.Field; import java.lang.reflect.Modifier; -@SuppressWarnings("Unsafe") +import org.sql2o.Sql2oException; + +import sun.misc.Unsafe; + +@SuppressWarnings("restriction") public class UnsafeFieldSetterFactory implements FieldSetterFactory, ObjectConstructorFactory { - private final static Unsafe theUnsafe; + + private final static Unsafe theUnsafe; static { try { - Class unsafeClass = Class.forName("sun.misc.Unsafe"); + Class unsafeClass = Class.forName("sun.misc.Unsafe"); Field declaredField = unsafeClass.getDeclaredField("theUnsafe"); declaredField.setAccessible(true); theUnsafe = (Unsafe) declaredField.get(null); diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/ClassUtils.java b/blade-sql2o/src/main/java/org/sql2o/tools/ClassUtils.java deleted file mode 100644 index 3f92a3963..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/tools/ClassUtils.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.sql2o.tools; - -/** - * @author Alden Quimby - */ -public final class ClassUtils { - -// private static ClassLoader getClassLoader() { -// return Thread.currentThread().getContextClassLoader(); -// } - - /** - * Check whether the {@link Class} identified by the supplied name is present. - * - * @param className the name of the class to check - * @return true if class is present, false otherwise - */ - public static boolean isPresent(String className) { - try { - // what's wrong with old plain Class.forName - // this code supposed to work everywhere including containers - Class.forName(className); - // getClassLoader().loadClass(className); - return true; - } - catch (Throwable ex) { - return false; - } - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java b/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java index 8a3a4d76d..0097309f3 100644 --- a/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java +++ b/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java @@ -1,11 +1,12 @@ package org.sql2o.tools; +import blade.kit.ReflectKit; + /** * Detects whether optional sql2o features are available. * * @author Alden Quimby */ -@SuppressWarnings("UnusedDeclaration") public final class FeatureDetector { private FeatureDetector() @@ -25,7 +26,7 @@ private FeatureDetector() */ public static boolean isJodaTimeAvailable() { if (jodaTimeAvailable == null) { - jodaTimeAvailable = ClassUtils.isPresent("org.joda.time.DateTime"); + jodaTimeAvailable = ReflectKit.isPresent("org.joda.time.DateTime"); } return jodaTimeAvailable; } @@ -35,7 +36,7 @@ public static boolean isJodaTimeAvailable() { */ public static boolean isSlf4jAvailable() { if (slf4jAvailable == null) { - slf4jAvailable = ClassUtils.isPresent("org.slf4j.Logger"); + slf4jAvailable = ReflectKit.isPresent("org.slf4j.Logger"); } return slf4jAvailable; } @@ -45,7 +46,7 @@ public static boolean isSlf4jAvailable() { */ public static boolean isOracleAvailable() { if (oracleAvailable == null) { - oracleAvailable = ClassUtils.isPresent("oracle.sql.TIMESTAMP"); + oracleAvailable = ReflectKit.isPresent("oracle.sql.TIMESTAMP"); } return oracleAvailable; } diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/IOUtils.java b/blade-sql2o/src/main/java/org/sql2o/tools/IOUtils.java deleted file mode 100644 index 92a44e09f..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/tools/IOUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.sql2o.tools; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; - -/** - * User: lars - * Date: 6/14/13 - * Time: 12:02 AM - */ -public class IOUtils { - - private static final int EOF = -1; - private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; - - public static byte[] toByteArray(InputStream input) throws IOException { - ByteArrayOutputStream output = new ByteArrayOutputStream(); - byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; - int n; - while (EOF != (n = input.read(buffer))) { - output.write(buffer, 0, n); - } - return output.toByteArray(); - } - - public static String toString(Reader input) throws IOException { - StringBuilder output = new StringBuilder(); - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - int n; - while (EOF != (n = input.read(buffer))) { - output.append(buffer, 0, n); - } - return output.toString(); - } - - -} diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java b/blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java index ddaac441d..76777af66 100644 --- a/blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java +++ b/blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java @@ -1,8 +1,5 @@ package org.sql2o.tools; -import java.util.HashMap; -import java.util.Map; - /** * Takes a string formatted like: 'my_string_variable' and returns it as: 'myStringVariable' * From 64feb5ec2b34d829ffa78d85074a4643840c9faa Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 31 Aug 2015 17:10:54 +0800 Subject: [PATCH 120/545] add route base interface --- UPDATE_LOG.md | 4 ++++ blade-core/src/main/java/blade/Blade.java | 2 +- blade-core/src/main/java/blade/route/RouteBase.java | 7 +++++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 blade-core/src/main/java/blade/route/RouteBase.java diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 715b55686..f81cd3a91 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,5 +1,9 @@ #Blade 更新日志 +### v1.2.9 + 1. 添加数据库连接池 + 2. 优化路由配置 + ### v1.2.8 1. 优化500页面,错误在后台显示 2. 添加Path上带后缀 diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index d1f7f7bd9..56ec8c572 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -40,7 +40,7 @@ */ public final class Blade { - public static final String VERSION = "1.2.8-beta"; + public static final String VERSION = "1.2.9-alpha"; /** * 框架是否已经初始化 */ diff --git a/blade-core/src/main/java/blade/route/RouteBase.java b/blade-core/src/main/java/blade/route/RouteBase.java new file mode 100644 index 000000000..c8eb5801c --- /dev/null +++ b/blade-core/src/main/java/blade/route/RouteBase.java @@ -0,0 +1,7 @@ +package blade.route; + +public interface RouteBase { + + public void run(); + +} From 72820812c759be930fa4eda7d6929e9aa351bcb2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 31 Aug 2015 18:41:56 +0800 Subject: [PATCH 121/545] fix route injection and update version --- LAST_VERSION.md | 6 +-- blade-core/src/main/java/blade/Blade.java | 9 +--- .../src/main/java/blade/IocApplication.java | 22 +++++++- .../src/main/java/blade/RequestHandler.java | 52 +++++++++++-------- .../java/blade/ioc/AbstractBeanFactory.java | 8 ++- .../src/main/java/blade/render/Render.java | 6 +-- .../java/blade/route/DefaultRouteMatcher.java | 3 +- .../main/java/blade/route/RouteMatcher.java | 7 ++- .../src/main/java/blade/servlet/Request.java | 16 ++++++ .../java/blade/wrapper/RequestWrapper.java | 9 ++++ 10 files changed, 97 insertions(+), 41 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 6fa0d4eb3..e182b349b 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.8 +    1.2.9-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -22,7 +22,7 @@     com.bladejava     blade-sql2o -    1.2.7 +    1.2.8-alpha ``` @@ -31,7 +31,7 @@     com.bladejava     blade-jetbrick -    1.2.3 +    1.2.4 ``` diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index 56ec8c572..76dd8106f 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -23,14 +23,13 @@ import blade.ioc.DefaultContainer; import blade.kit.IOKit; import blade.kit.PropertyKit; -import blade.kit.ReflectKit; import blade.kit.json.JSONKit; import blade.render.Render; import blade.render.RenderFactory; import blade.route.HttpMethod; import blade.route.RouteBase; -import blade.route.Router; import blade.route.RouteMatcherBuilder; +import blade.route.Router; /** * Blade Core Class @@ -282,11 +281,7 @@ public static synchronized void debug(boolean isdebug){ * @param route */ public static synchronized void load(Class route){ - Object object = ReflectKit.newInstance(route); - if(null != object){ - container.injection(object); - ReflectKit.invokeMehodByName(object, "run"); - } + IocApplication.addRouteClass(route); } /** diff --git a/blade-core/src/main/java/blade/IocApplication.java b/blade-core/src/main/java/blade/IocApplication.java index 73f2edc69..e99402766 100644 --- a/blade-core/src/main/java/blade/IocApplication.java +++ b/blade-core/src/main/java/blade/IocApplication.java @@ -15,14 +15,18 @@ */ package blade; +import java.util.List; import java.util.Set; import blade.ioc.Container; import blade.ioc.DefaultContainer; import blade.ioc.Scope; +import blade.kit.CollectionKit; +import blade.kit.ReflectKit; import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; +import blade.route.RouteBase; /** * IOC容器初始化类 @@ -47,6 +51,11 @@ public final class IocApplication { */ static final ClassReader classReader = new ClassPathClassReader(); + /** + * 存放路由类 + */ + static final List> ROUTE_CLASS_LIST = CollectionKit.newArrayList(); + public static void init(){ // 初始化全局配置类 @@ -60,6 +69,14 @@ public static void init(){ // 初始化注入 try { container.initWired(); + + for(Class clazz : ROUTE_CLASS_LIST){ + Object object = ReflectKit.newInstance(clazz); + if(null != object){ + container.injection(object); + ReflectKit.invokeMehodByName(object, "run"); + } + } } catch (Exception e) { LOGGER.error(e); } @@ -78,7 +95,10 @@ private static void initIOC() { } } } - + + public static void addRouteClass(Class clazz){ + ROUTE_CLASS_LIST.add(clazz); + } /** * 注册一个包下的所有对象 * diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index fab6442f0..2e6a2f441 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -58,7 +58,8 @@ public class RequestHandler { * 服务器500错误时返回的HTML */ - private static final String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade 1.2.7-beta
"; + private static final String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + + Blade.VERSION +"
"; private final static Container container = DefaultContainer.single(); @@ -119,7 +120,6 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse Response response = RequestResponseBuilder.build(httpResponse); HttpMethod httpMethod = HttpMethod.valueOf(method); - boolean isHandler = true; Object result = null; try { responseWrapper.setDelegate(response); @@ -129,10 +129,27 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse // 如果找到 if (match != null) { // 执行before拦截 - isHandler = before(httpRequest, requestWrapper, responseWrapper, uri, acceptType); + result = before(httpRequest, requestWrapper, responseWrapper, uri, acceptType); + if(result instanceof Boolean){ + boolean isHandler = (Boolean) result; + if(!isHandler){ + return false; + } + } - if(!isHandler){ - return false; + if(result instanceof String){ + String res = result.toString(); + if(res.startsWith("redirect.")){ + response.go(res.substring(9)); + } else { + render(responseWrapper, res); + } + return true; + } + + if(result instanceof ModelAndView){ + render(responseWrapper, result); + return true; } // 实际执行方法 @@ -141,9 +158,8 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse // 执行after拦截 responseWrapper.setDelegate(response); - isHandler = after(httpRequest, requestWrapper, responseWrapper, uri, acceptType); - if (!isHandler) - return false; + after(httpRequest, requestWrapper, responseWrapper, uri, acceptType); + if (null != result) render(responseWrapper, result); return true; @@ -151,6 +167,7 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse // 没有找到 response.render404(uri); + return true; } catch (BladeException bex) { bex.printStackTrace(); httpResponse.setStatus(500); @@ -224,24 +241,18 @@ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper reques * @param uri 请求的URI * @param acceptType 请求头过滤 */ - private boolean before(HttpServletRequest httpRequest, RequestWrapper requestWrapper, ResponseWrapper responseWrapper, final String uri, final String acceptType){ + private Object before(HttpServletRequest httpRequest, RequestWrapper requestWrapper, ResponseWrapper responseWrapper, final String uri, final String acceptType){ List matchSet = defaultRouteMatcher.findInterceptor(HttpMethod.BEFORE, uri, acceptType); - boolean isHandler = true; - for (RouteMatcher filterMatch : matchSet) { - Object object = realHandler(httpRequest, requestWrapper, responseWrapper, filterMatch); - - if(null != object && object instanceof Boolean){ - isHandler = (Boolean) object; - if(!isHandler){ - return false; - } + if(null != object){ + return object; } } - return isHandler; + + return true; } /** @@ -321,13 +332,12 @@ private Object executeMethod(Object object, Method method, RequestWrapper reques * @param result * @return */ - private Object render(Response response, Object result){ + private void render(Response response, Object result){ if(result instanceof String){ response.render(result.toString()); } else if(result instanceof ModelAndView){ response.render( (ModelAndView) result ); } - return null; } private boolean filterStaticFolder(String uri){ diff --git a/blade-core/src/main/java/blade/ioc/AbstractBeanFactory.java b/blade-core/src/main/java/blade/ioc/AbstractBeanFactory.java index 6b8e551df..cb80bb1e9 100644 --- a/blade-core/src/main/java/blade/ioc/AbstractBeanFactory.java +++ b/blade-core/src/main/java/blade/ioc/AbstractBeanFactory.java @@ -20,6 +20,8 @@ import java.util.List; import java.util.Set; +import blade.kit.log.Logger; + /** * 抽象bean工厂,用于注册和获取bean对象 * @@ -28,14 +30,16 @@ */ public abstract class AbstractBeanFactory { + private static final Logger LOGGER = Logger.getLogger(AbstractBeanFactory.class); + protected Container container = DefaultContainer.single(); public abstract Object getBean(String className); public abstract Object getBean(Class clazz); - public boolean resetBean(Class clazz, Object object){ - System.out.println("resetBean object=" + object); + public boolean resetBean(Class clazz, Object object){ + LOGGER.info("resetBean object=" + object); if(null != clazz.getInterfaces() && null != object){ container.removeBean(clazz); container.getBeanMap().put(clazz.getName(), object); diff --git a/blade-core/src/main/java/blade/render/Render.java b/blade-core/src/main/java/blade/render/Render.java index b1f660fb2..b5ecad3e0 100644 --- a/blade-core/src/main/java/blade/render/Render.java +++ b/blade-core/src/main/java/blade/render/Render.java @@ -37,8 +37,8 @@ public abstract class Render { private static final Logger LOGGER = Logger.getLogger(Render.class); - - static final String VIEW_NOTFOUND = "

404 %s

"; + static final String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + + Blade.VERSION +"
"; public void render404(String viewName){ render404(null, viewName); @@ -64,7 +64,7 @@ public void render404(Response response, String viewName){ response.contentType("text/html; charset=utf-8"); response.status(404); ServletOutputStream outputStream = response.outputStream(); - outputStream.print(String.format(VIEW_NOTFOUND, viewName + " Not Found")); + outputStream.print(String.format(VIEW_NOTFOUND, viewName)); outputStream.flush(); outputStream.close(); } diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index e457d5c38..e03517816 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -74,7 +74,7 @@ public RouteMatcher findRouteMatcher(HttpMethod httpMethod, String uri, String a RouteMatcher entry = findTargetWithGivenAcceptType(routeEntries, acceptType); - return entry != null ? new RouteMatcher(entry.target, entry.execMethod, entry.httpMethod, entry.path, uri, acceptType) : null; + return entry != null ? new RouteMatcher(entry.router, entry.target, entry.execMethod, entry.httpMethod, entry.path, uri, acceptType) : null; } private void giveMatch(final String uri, List routeEntries) { @@ -87,7 +87,6 @@ public int compare(RouteMatcher o1, RouteMatcher o2) { return -1; } }); -// System.out.println(routeEntries.toString()); } /** diff --git a/blade-core/src/main/java/blade/route/RouteMatcher.java b/blade-core/src/main/java/blade/route/RouteMatcher.java index 1afb0fd97..a1ac786db 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/blade/route/RouteMatcher.java @@ -33,6 +33,9 @@ public class RouteMatcher { */ Class target; + /** + * 执行的类实例 + */ Router router; /** @@ -63,8 +66,8 @@ public class RouteMatcher { public RouteMatcher() { } - public RouteMatcher(Class target, Method execMethod, HttpMethod httpMethod, String path, String requestUri, String acceptType) { - super(); + public RouteMatcher(Router router, Class target, Method execMethod, HttpMethod httpMethod, String path, String requestUri, String acceptType) { + this.router = router; this.target = target; this.execMethod = execMethod; this.httpMethod = httpMethod; diff --git a/blade-core/src/main/java/blade/servlet/Request.java b/blade-core/src/main/java/blade/servlet/Request.java index 3b3f9146f..af10f8142 100644 --- a/blade-core/src/main/java/blade/servlet/Request.java +++ b/blade-core/src/main/java/blade/servlet/Request.java @@ -567,4 +567,20 @@ protected static List getSplat(List request, List matche return Collections.unmodifiableList(splat); } + /** + * 继续执行 + * @return + */ + public Object invoke(){ + return true; + } + + /** + * 跳转到一个页面 + * @param locaiton + * @return + */ + public Object invoke(String locaiton) { + return "redirect." + locaiton; + } } diff --git a/blade-core/src/main/java/blade/wrapper/RequestWrapper.java b/blade-core/src/main/java/blade/wrapper/RequestWrapper.java index a53aee36f..4e0bd8767 100644 --- a/blade-core/src/main/java/blade/wrapper/RequestWrapper.java +++ b/blade-core/src/main/java/blade/wrapper/RequestWrapper.java @@ -231,7 +231,16 @@ public String cookie(String name) { return delegate.cookie(name); } + public Object invoke(){ + return delegate.invoke(); + } + + public Object invoke(String locaiton) { + return delegate.invoke(locaiton); + } + public void initRequest(RouteMatcher match) { delegate.initRequest(match); } + } From 3bbbf0a350b15f2c1f8afc2559a5ff574da15b54 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 1 Sep 2015 15:36:23 +0800 Subject: [PATCH 122/545] remove sql2o logger --- LAST_VERSION.md | 2 +- .../src/main/java/org/sql2o/Connection.java | 19 +++--- .../main/java/org/sql2o/JndiDataSource.java | 7 +-- .../src/main/java/org/sql2o/Query.java | 15 +++-- .../org/sql2o/logging/LocalLoggerFactory.java | 19 ------ .../main/java/org/sql2o/logging/Logger.java | 12 ---- .../java/org/sql2o/logging/Slf4jLogger.java | 29 --------- .../java/org/sql2o/logging/SysOutLogger.java | 62 ------------------- 8 files changed, 21 insertions(+), 144 deletions(-) delete mode 100644 blade-sql2o/src/main/java/org/sql2o/logging/LocalLoggerFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/logging/Logger.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/logging/Slf4jLogger.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/logging/SysOutLogger.java diff --git a/LAST_VERSION.md b/LAST_VERSION.md index e182b349b..585f9ea98 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -5,7 +5,7 @@     com.bladejava     blade-kit -    1.2.6 +    1.2.7-alpha ``` diff --git a/blade-sql2o/src/main/java/org/sql2o/Connection.java b/blade-sql2o/src/main/java/org/sql2o/Connection.java index 4154b21b7..e9321d8a6 100644 --- a/blade-sql2o/src/main/java/org/sql2o/Connection.java +++ b/blade-sql2o/src/main/java/org/sql2o/Connection.java @@ -1,10 +1,6 @@ package org.sql2o; -import org.sql2o.converters.Converter; -import org.sql2o.converters.ConverterException; -import org.sql2o.logging.LocalLoggerFactory; -import org.sql2o.logging.Logger; -import org.sql2o.quirks.Quirks; +import static org.sql2o.converters.Convert.throwIfNull; import java.sql.ResultSet; import java.sql.SQLException; @@ -14,14 +10,19 @@ import java.util.List; import java.util.Set; -import static org.sql2o.converters.Convert.throwIfNull; +import org.sql2o.converters.Converter; +import org.sql2o.converters.ConverterException; +import org.sql2o.quirks.Quirks; + +import blade.kit.log.Logger; /** * Represents a connection to the database with a transaction. */ public class Connection implements AutoCloseable { - private final static Logger logger = LocalLoggerFactory.getLogger(Connection.class); +// private final static Logger logger = LocalLoggerFactory.getLogger(Connection.class); + private final static Logger logger = Logger.getLogger(Connection.class); private java.sql.Connection jdbcConnection; private Sql2o sql2o; @@ -115,7 +116,7 @@ public Connection rollback(boolean closeConnection){ jdbcConnection.rollback(); } catch (SQLException e) { - logger.warn("Could not roll back transaction. message: {}", e); + logger.warn("Could not roll back transaction.", e); } finally { if(closeConnection) this.closeJdbcConnection(); @@ -303,7 +304,7 @@ private void closeJdbcConnection() { jdbcConnection.close(); } catch (SQLException e) { - logger.warn("Could not close connection. message: {}", e); + logger.warn("Could not close connection.", e); } } } diff --git a/blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java b/blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java index c09ae8ad7..4d5671e65 100644 --- a/blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java +++ b/blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java @@ -1,19 +1,18 @@ package org.sql2o; -import org.sql2o.logging.LocalLoggerFactory; -import org.sql2o.logging.Logger; - import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; +import blade.kit.log.Logger; + /** * Created by lars on 16.09.2014. */ public class JndiDataSource { - private final static Logger logger = LocalLoggerFactory.getLogger(JndiDataSource.class); + private final static Logger logger = Logger.getLogger(JndiDataSource.class); static DataSource getJndiDatasource(String jndiLookup) { Context ctx = null; diff --git a/blade-sql2o/src/main/java/org/sql2o/Query.java b/blade-sql2o/src/main/java/org/sql2o/Query.java index 8ea0e298b..a29ea5bd9 100644 --- a/blade-sql2o/src/main/java/org/sql2o/Query.java +++ b/blade-sql2o/src/main/java/org/sql2o/Query.java @@ -25,18 +25,17 @@ import org.sql2o.data.Row; import org.sql2o.data.Table; import org.sql2o.data.TableResultSetIterator; -import org.sql2o.logging.LocalLoggerFactory; -import org.sql2o.logging.Logger; import org.sql2o.quirks.Quirks; import org.sql2o.reflection.PojoIntrospector; +import blade.kit.log.Logger; + /** * Represents a sql2o statement. With sql2o, all statements are instances of the Query class. */ -@SuppressWarnings("UnusedDeclaration") public class Query implements AutoCloseable { - private final static Logger logger = LocalLoggerFactory.getLogger(Query.class); + private final static Logger logger = Logger.getLogger(Query.class); private Connection connection; private Map caseSensitiveColumnMappings; @@ -356,7 +355,7 @@ public void close() { // log the query long afterClose = System.currentTimeMillis(); - logger.debug("total: {} ms, execution: {} ms, reading and parsing: {} ms; executed [{}]", new Object[]{ + logger.debug("total: %s ms, execution: %s ms, reading and parsing: %s ms; executed [%s]", new Object[]{ afterClose - start, afterExecQuery-start, afterClose - afterExecQuery, @@ -546,7 +545,7 @@ public Connection executeUpdate(){ } long end = System.currentTimeMillis(); - logger.debug("total: {} ms; executed update [{}]", new Object[]{ + logger.debug("total: %s ms; executed update [%s]", new Object[]{ end - start, this.getName() == null ? "No name" : this.getName() }); @@ -561,7 +560,7 @@ public Object executeScalar(){ if (rs.next()){ Object o = getQuirks().getRSVal(rs, 1); long end = System.currentTimeMillis(); - logger.debug("total: {} ms; executed scalar [{}]", new Object[]{ + logger.debug("total: %s ms; executed scalar [%s]", new Object[]{ end - start, this.getName() == null ? "No name" : this.getName() }); @@ -664,7 +663,7 @@ public Connection executeBatch() throws Sql2oException { } long end = System.currentTimeMillis(); - logger.debug("total: {} ms; executed batch [{}]", new Object[]{ + logger.debug("total: %s ms; executed batch [%s]", new Object[]{ end - start, this.getName() == null ? "No name" : this.getName() }); diff --git a/blade-sql2o/src/main/java/org/sql2o/logging/LocalLoggerFactory.java b/blade-sql2o/src/main/java/org/sql2o/logging/LocalLoggerFactory.java deleted file mode 100644 index e1281d5d9..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/logging/LocalLoggerFactory.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.sql2o.logging; - -import org.slf4j.LoggerFactory; -import org.sql2o.tools.FeatureDetector; - -/** - * Created by lars on 2/9/14. - */ -public class LocalLoggerFactory { - // this is thread-safe since static initializer is thread-safe - private static final boolean slf4jAvailable = FeatureDetector.isSlf4jAvailable(); - - public static Logger getLogger(Class clazz) { - return slf4jAvailable - ? new Slf4jLogger(LoggerFactory.getLogger(clazz)) - : SysOutLogger.instance; - - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/logging/Logger.java b/blade-sql2o/src/main/java/org/sql2o/logging/Logger.java deleted file mode 100644 index 700279508..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/logging/Logger.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.sql2o.logging; - -/** - * Created by lars on 2/9/14. - */ -public interface Logger { - - public void debug(String format, Object[] argArray); - public void debug(String format, Object arg); - public void warn(String format); - public void warn(String format, Throwable exception); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/logging/Slf4jLogger.java b/blade-sql2o/src/main/java/org/sql2o/logging/Slf4jLogger.java deleted file mode 100644 index 0827cb905..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/logging/Slf4jLogger.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.sql2o.logging; - -/** - * Created by lars on 2/9/14. - */ -public class Slf4jLogger implements Logger { - - private final org.slf4j.Logger slf4jLogger; - - public Slf4jLogger(org.slf4j.Logger slf4jLogger) { - this.slf4jLogger = slf4jLogger; - } - - public void debug(String format, Object[] argArray) { - slf4jLogger.debug(format, argArray); - } - - public void debug(String format, Object arg) { - slf4jLogger.debug(format, arg); - } - - public void warn(String format) { - slf4jLogger.warn(format); - } - - public void warn(String format, Throwable exception) { - slf4jLogger.warn(format, exception); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/logging/SysOutLogger.java b/blade-sql2o/src/main/java/org/sql2o/logging/SysOutLogger.java deleted file mode 100644 index de5a61c64..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/logging/SysOutLogger.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.sql2o.logging; - -/** - * Created by lars on 2/9/14. - */ -public class SysOutLogger implements Logger { - - public static Logger instance = new SysOutLogger(); - - //private final Class clazz; // don't used - private final static long startTime = System.currentTimeMillis(); - public static final String LINE_SEPARATOR = System.getProperty("line.separator"); - private static String WARN_LVL = "WARN"; - // private static String ERROR_LVL = "ERROR"; // don't used - - public SysOutLogger() { - // this.clazz = clazz; - } - - public void debug(String format, Object[] argArray) { - // Don't log debug messages with the SysOutLogger - } - - public void debug(String format, Object arg) { - // Don't log debug messages with the SysOutLogger - } - - public void warn(String format) { - this.log(format, WARN_LVL, null); - } - - public void warn(String format, Throwable exception) { - this.log(format, WARN_LVL, exception); - } - - private void log(String msg, String level, Throwable exception) { - StringBuilder buffer = new StringBuilder(); // bit faster - - long millis = System.currentTimeMillis(); - buffer.append(millis - startTime); - - buffer.append(" ["); - buffer.append(Thread.currentThread().getName()); - buffer.append("] "); - - buffer.append(level); - buffer.append(" "); - - buffer.append(this.getClass().getName()); - buffer.append(" - "); - - buffer.append(msg); - - buffer.append(LINE_SEPARATOR); - - System.err.print(buffer.toString()); - if (exception != null) { - exception.printStackTrace(System.err); - } - System.err.flush(); - } -} From 882d7aeca6e8c6dde91bae66f76838735258e445 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 2 Sep 2015 14:53:20 +0800 Subject: [PATCH 123/545] - --- blade-sql2o/pom.xml | 7 ------ .../org/sql2o/reflection/FactoryFacade.java | 3 ++- .../org/sql2o/reflection/FieldSetter.java | 2 +- .../reflection/MethodAccessorsGenerator.java | 22 +++++++++---------- .../org/sql2o/reflection/MethodSetter.java | 2 +- .../main/java/org/sql2o/reflection/Pojo.java | 2 +- .../sql2o/reflection/PojoIntrospector.java | 1 + .../org/sql2o/reflection/PojoMetadata.java | 12 +++++----- .../java/org/sql2o/reflection/Setter.java | 3 +-- .../reflection/UnsafeFieldSetterFactory.java | 14 +++++------- 10 files changed, 29 insertions(+), 39 deletions(-) diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 6cb9ae685..026f2b926 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -34,12 +34,5 @@ 2.8.2 true - - org.slf4j - slf4j-api - 1.6.4 - true - - diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java b/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java index 121b1adc0..bcdd855ba 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java @@ -3,6 +3,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; +@SuppressWarnings("Unsafe") public class FactoryFacade { private final static FactoryFacade instance; @@ -20,7 +21,7 @@ public class FactoryFacade { } FieldSetterFactory f; try { - Class cls = Class.forName("org.sql2o.reflection.UnsafeFieldSetterFactory"); + Class cls = Class.forName("org.sql2o.reflection.UnsafeFieldSetterFactory"); f = (FieldSetterFactory) cls.newInstance(); if(o==null) o = (ObjectConstructorFactory) f; } catch (Throwable ex) { diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java index 706c57136..31af9d97f 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java @@ -28,7 +28,7 @@ public void setProperty(Object obj, Object value) { } } - public Class getType() { + public Class getType() { return field.getType(); } } diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java index cbe5b6625..fbc132200 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java @@ -1,21 +1,19 @@ package org.sql2o.reflection; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - import org.sql2o.Sql2oException; - import sun.reflect.ConstructorAccessor; import sun.reflect.FieldAccessor; import sun.reflect.MethodAccessor; -@SuppressWarnings("restriction") +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +@SuppressWarnings("UnusedDeclaration") public class MethodAccessorsGenerator implements MethodSetterFactory, ObjectConstructorFactory { private static final ThreadLocal generatorObjectHolder; - - private static final MethodAccessor generateMethod; + private static final MethodAccessor generateMethod; private static final MethodAccessor generateConstructor; private static final MethodAccessor generateSerializationConstructor; private static final MethodAccessor newFieldAccessor; @@ -119,7 +117,7 @@ public static ConstructorAccessor newConstructorAccessor(Constructor bar, Cla } public Setter newSetter(final Method method) { - final Class type = method.getParameterTypes()[0]; + final Class type = method.getParameterTypes()[0]; final MethodAccessor methodAccessor = newMethodAccessor(method); return new Setter() { public void setProperty(Object obj, Object value) { @@ -131,7 +129,7 @@ public void setProperty(Object obj, Object value) { } } - public Class getType() { + public Class getType() { return type; } }; @@ -152,7 +150,7 @@ public Object newInstance() { return constructorAccessor.newInstance(null); } catch (InstantiationException e) { throw new Sql2oException("Could not create a new instance of class " + cls, e); - } catch (InvocationTargetException e) { + }catch (InvocationTargetException e) { throw new Sql2oException("Could not create a new instance of class " + cls, e); } } diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java index 02ab2b6c6..e27043199 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java @@ -32,7 +32,7 @@ public void setProperty(Object obj, Object value) { } } - public Class getType() { + public Class getType() { return type; } } diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java b/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java index 575f6401c..389303f19 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java @@ -29,7 +29,7 @@ public Pojo(PojoMetadata metadata, boolean caseSensitive){ object = objectConstructor.newInstance(); } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings("unchecked") public void setProperty(String propertyPath, Object value, Quirks quirks){ // String.split uses RegularExpression // this is overkill for every column for every row diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java index 9879de8ef..bfb1faa2b 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java @@ -20,6 +20,7 @@ // TODO: move introspection code from PojoMetadata to PojoIntrospector +@SuppressWarnings("UnusedDeclaration") public class PojoIntrospector { private static final AbstractCache, Map, Void> rpCache = new AbstractCache, Map, Void>() { diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java index aa02af2bf..2f9db165c 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java @@ -24,7 +24,7 @@ public class PojoMetadata { private boolean caseSensitive; private boolean autoDeriveColumnNames; public final boolean throwOnMappingFailure; - private Class clazz; + private Class clazz; public boolean isCaseSensitive() { return caseSensitive; @@ -56,7 +56,7 @@ public int hashCode() { return result; } - public PojoMetadata(Class clazz, boolean caseSensitive, boolean autoDeriveColumnNames, Map columnMappings, boolean throwOnMappingError) { + public PojoMetadata(Class clazz, boolean caseSensitive, boolean autoDeriveColumnNames, Map columnMappings, boolean throwOnMappingError) { this.caseSensitive = caseSensitive; this.autoDeriveColumnNames = autoDeriveColumnNames; this.clazz = clazz; @@ -83,7 +83,7 @@ private PropertyAndFieldInfo initializePropertyInfo() { HashMap propertySetters = new HashMap(); HashMap fields = new HashMap(); - Class theClass = clazz; + Class theClass = clazz; ObjectConstructor objectConstructor = factoryFacade.newConstructor(theClass); do { for (Field f : theClass.getDeclaredFields()) { @@ -149,7 +149,7 @@ public Setter getPropertySetterIfExists(String propertyName) { return propertyInfo.propertySetters.get(name); } - public Class getType() { + public Class getType() { return this.clazz; } @@ -164,9 +164,9 @@ public Object getValueOfProperty(String propertyName, Object object) { } } - private static class Cache extends AbstractCache, PropertyAndFieldInfo, PojoMetadata> { + private static class Cache extends AbstractCache { @Override - protected PropertyAndFieldInfo evaluate(Class key, PojoMetadata param) { + protected PropertyAndFieldInfo evaluate(Class key, PojoMetadata param) { return param.initializePropertyInfo(); } } diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java index caf9e3f1e..b7da73fe1 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java @@ -6,6 +6,5 @@ public interface Setter { void setProperty(Object obj, Object value); - @SuppressWarnings("rawtypes") - Class getType(); + Class getType(); } diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java index 93d5ae1e2..c6b068c7d 100644 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java +++ b/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java @@ -1,19 +1,17 @@ package org.sql2o.reflection; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - import org.sql2o.Sql2oException; - import sun.misc.Unsafe; -@SuppressWarnings("restriction") +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +@SuppressWarnings("Unsafe") public class UnsafeFieldSetterFactory implements FieldSetterFactory, ObjectConstructorFactory { - - private final static Unsafe theUnsafe; + private final static Unsafe theUnsafe; static { try { - Class unsafeClass = Class.forName("sun.misc.Unsafe"); + Class unsafeClass = Class.forName("sun.misc.Unsafe"); Field declaredField = unsafeClass.getDeclaredField("theUnsafe"); declaredField.setAccessible(true); theUnsafe = (Unsafe) declaredField.get(null); From 6a0ddf049bb272e84fb4e04c319782dc56730f7b Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 2 Sep 2015 14:54:56 +0800 Subject: [PATCH 124/545] update version --- README.md | 2 +- README_CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1e93e823a..24bacab32 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.8 + 1.2.9-alpha ``` diff --git a/README_CN.md b/README_CN.md index 2194b4be3..71b3507ef 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,7 +33,7 @@ com.bladejava blade-core - 1.2.8 + 1.2.9-alpha ``` From e14fba3ba8482fed7757d6a74a89b8c324372185 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 2 Sep 2015 17:20:59 +0800 Subject: [PATCH 125/545] update readme --- LAST_VERSION.md | 2 +- README.md | 6 +++--- README_CN.md | 6 +++--- blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java | 9 +++++++++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 585f9ea98..5577466e0 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -22,7 +22,7 @@     com.bladejava     blade-sql2o -    1.2.8-alpha +    1.2.8-beta ``` diff --git a/README.md b/README.md index 24bacab32..dac7d76e1 100644 --- a/README.md +++ b/README.md @@ -139,9 +139,9 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ## Plan 1. Improve the document - 2. Single user blog system development - 3. web chat system - 4. Optimize the code performance + 2. Add configurable log + 3. To optimize the database query, connection pool + 4. Complete the Java China BBS ## Update diff --git a/README_CN.md b/README_CN.md index 71b3507ef..6384e6e7b 100644 --- a/README_CN.md +++ b/README_CN.md @@ -136,9 +136,9 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ### 计划 1. 完善文档 - 2. 单用户博客系统 - 3. web聊天系统 - 4. 优化代码性能 + 2. 添加可配置日志 + 3. 优化数据库查询、连接池 + 4. 完成java中国论坛 ## 更新日志 diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 3df6dc589..537655b79 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -126,6 +126,9 @@ public Model cache(boolean cache){ private void init(){ this.queryIsOpen = false; this.cache = isOpenCache; + if(null == this.sql2o){ + this.sql2o = DataSourceManager.getSql2o(); + } } /** @@ -178,6 +181,7 @@ public Model count(String sql){ * @return 返回更新model对象,推荐方式 */ public Model update(){ + init(); condition.update(); return this; } @@ -189,6 +193,7 @@ public Model update(){ * @return 返回更新model对象 */ public Model update(String sql){ + init(); condition.update(sql); return this; } @@ -197,6 +202,7 @@ public Model update(String sql){ * @return 返回插入model对象,推荐方式 */ public Model insert(){ + init(); condition.insert(); return this; } @@ -207,6 +213,7 @@ public Model insert(){ * @return 返回插入model对象 */ public Model insert(String sql){ + init(); condition.insert(sql); return this; } @@ -215,6 +222,7 @@ public Model insert(String sql){ * @return 返回删除model对象 */ public Model delete(){ + init(); condition.delete(); return this; } @@ -226,6 +234,7 @@ public Model delete(){ * @return 返回自定义删除model对象 */ public Model delete(String sql){ + init(); condition.delete(sql); return this; } From 235a5f8d3975d85b9555971a8b83c422eecf8008 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 2 Sep 2015 18:49:57 +0800 Subject: [PATCH 126/545] remove stop check thread --- .../plugin/sql2o/pool/ConnectionPool.java | 64 +++++++++++++------ .../sql2o/pool/ConnectionPoolManager.java | 27 +++++--- .../java/org/sql2o/tools/FeatureDetector.java | 11 ---- 3 files changed, 62 insertions(+), 40 deletions(-) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java index 57b4f8265..5720a5e58 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java @@ -65,6 +65,9 @@ public ConnectionPool(PoolConfig poolConfig) { } + /** + * 创建连接池 + */ private void createConnectionPool() { try { Class.forName(poolConfig.getDriverName()); @@ -81,6 +84,10 @@ private void createConnectionPool() { } } + /** + * 检查sql测试语句 + * @throws SQLException + */ protected void sendCheckSQL() throws SQLException { Statement statement = null; Connection internalConnection = null; @@ -93,48 +100,54 @@ protected void sendCheckSQL() throws SQLException { statement = internalConnection.createStatement(); statement.execute(keepAliveSQL); } - LOGGER.debug("连接测试语句执行成功"); + LOGGER.debug("keepalive test success!"); } catch (SQLException e) { - LOGGER.error("连接测试语句执行失败", e); + LOGGER.error("keepalive test error!", e); throw e; } finally { - closeConnection(internalConnection); + internalConnection.close(); } } + /** + * 创建一个连接 + * @return + * @throws SQLException + */ private Connection obtainInternalConnection() throws SQLException { return DriverManager.getConnection(poolConfig.getUrl(), poolConfig.getUserName(), poolConfig.getPassWord()); } + /** + * 连接池创建一个连接 + * @return + * @throws ClassNotFoundException + * @throws SQLException + */ private synchronized Connection createConn() throws ClassNotFoundException, SQLException { Connection conn = null; if (null != poolConfig) { - Class.forName(poolConfig.getDriverName()); conn = DriverManager.getConnection(poolConfig.getUrl(), poolConfig.getUserName(), poolConfig.getPassWord()); totalConn++; } - return conn; } /** * 获得连接 - * * @return */ public synchronized Connection getConnection() { Connection conn = null; - try { - if (null == poolConfig) { return conn; } + // 如果已经创建的连接数小于数据库的最大连接数而且小于连接池最大的连接数,那么再创建连接数 - if (totalConn < poolConfig.getMaxActiveConn() - && totalConn < poolConfig.getMaxActiveConn()) { + if (totalConn < poolConfig.getMaxActiveConn() && totalConn < poolConfig.getMaxActiveConn()) { if (freeConnections.size() > 0) {// 如果还有空闲连接 conn = freeConnections.get(0); @@ -152,7 +165,7 @@ public synchronized Connection getConnection() { wait(poolConfig.getConnWaitTime()); conn = getConnection(); } - + if (isValid(conn)) { activeConnections.add(conn); } @@ -170,13 +183,13 @@ public synchronized Connection getConnection() { private boolean isValid(Connection conn) { try { - if (conn.isClosed()) { + if (conn == null || conn.isClosed()) { return false; } } catch (SQLException e) { e.printStackTrace(); } - return true; + return true; } /** @@ -200,10 +213,11 @@ public Connection getCurrentConnection() { */ public synchronized void releaseConnection(Connection conn) throws SQLException { - if (isValid(conn)) { + if (isValid(conn) && !(freeConnections.size() > poolConfig.getMaxConn())) { freeConnections.add(conn); activeConnections.remove(conn); threadLocal.remove(); + totalConn--; // 唤醒所有正待等待的线程,去抢连接 notifyAll(); } @@ -217,7 +231,6 @@ public synchronized void releaseConnection(Connection conn) throws SQLException * @throws SQLException */ public synchronized void closeConnection(Connection conn) throws SQLException { - conn.close(); freeConnections.remove(conn); activeConnections.remove(conn); @@ -249,7 +262,11 @@ public synchronized void destroy() { isActive = false; totalConn = 0; - TaskKit.depose(); + // 停止监控线程 + /*if(null != scheduledFuture){ + scheduledFuture.cancel(false); + TaskKit.reset(); + }*/ } /** @@ -279,8 +296,12 @@ public int getFreeConnNum() { return freeConnections.size(); } + /** + * 定时检查连接池 + */ private void checkConnectionPool() { + // 测试语句 if(StringKit.isNotBlank(poolConfig.getKeepAliveSql())){ try { sendCheckSQL(); @@ -290,15 +311,18 @@ private void checkConnectionPool() { } if (poolConfig.isCheakPool()) { + TaskKit.scheduleWithFixedDelay(new TimerTask() { @Override public void run() { - LOGGER.debug("空线池连接数:" + freeConnections.size()); - LOGGER.debug("活动连接数:" + activeConnections.size()); - LOGGER.debug("总的连接数:" + totalConn); - LOGGER.debug("连接池活动状态:" + isActive); + LOGGER.debug("idle connection count:" + freeConnections.size()); + LOGGER.debug("active connection count:" + activeConnections.size()); + LOGGER.debug("total connection count:" + totalConn); + LOGGER.debug("pool active status:" + isActive); } }, poolConfig.getInitDelay(), poolConfig.getPeriodCheck(), TimeUnit.SECONDS); + + } } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java index d35f49d48..dd096580a 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java @@ -5,20 +5,25 @@ import java.util.Hashtable; import java.util.List; +import blade.kit.log.Logger; + /** * 数据连接池管理器 + * * @author biezhi * */ public class ConnectionPoolManager { + private static final Logger LOGGER = Logger.getLogger(ConnectionPoolManager.class); + private static ConnectionPoolManager connectionPoolManager; - + /** * 连接池存放 */ private Hashtable pools; - + /** * 总的连接数 */ @@ -33,14 +38,15 @@ private ConnectionPoolManager() { private void init() { List poolConfigs = InitPoolConfig.poolConfigList; - - for(PoolConfig config : poolConfigs){ + + for (PoolConfig config : poolConfigs) { ConnectionPool pool = new ConnectionPool(config); if (pool != null) { pools.put(config.getPoolName(), pool); + LOGGER.info("Init connection successed -> " + config.getPoolName()); } } - + } /** @@ -72,7 +78,11 @@ public ConnectionPool getPool(String poolName) { */ public Connection getConnection(String poolName) { Connection conn = null; - conn = getPool(poolName).getConnection(); + if (pools.size() > 0 && pools.containsKey(poolName)) { + conn = getPool(poolName).getConnection(); + } else { + LOGGER.error("Can't find this connecion pool -> " + poolName); + } return conn; } @@ -80,13 +90,13 @@ public Connection getConnection(String poolName) { * 释放连接 */ public void releaseConnection(String poolName, Connection conn) { - try { ConnectionPool pool = getPool(poolName); if (null != null) { pool.releaseConnection(conn); } } catch (SQLException e) { + LOGGER.warn("connection is release"); e.printStackTrace(); } } @@ -105,12 +115,11 @@ public void destory(String poolName) { /** * 获得连接数 + * * @return */ public static int getClients() { return clients; } - - } diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java b/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java index 0097309f3..ccd5df08c 100644 --- a/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java +++ b/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java @@ -17,7 +17,6 @@ private FeatureDetector() } private static Boolean jodaTimeAvailable; - private static Boolean slf4jAvailable; private static Boolean oracleAvailable; private static boolean cacheUnderscoreToCamelcaseEnabled; @@ -31,16 +30,6 @@ public static boolean isJodaTimeAvailable() { return jodaTimeAvailable; } - /** - * @return {@code true} if Slf4j is available, {@code false} otherwise. - */ - public static boolean isSlf4jAvailable() { - if (slf4jAvailable == null) { - slf4jAvailable = ReflectKit.isPresent("org.slf4j.Logger"); - } - return slf4jAvailable; - } - /** * @return {@code true} if oracle.sql is available, {@code false} otherwise. */ From bbee53df00c3bb5f718b814503f51fd138c23440 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 6 Sep 2015 09:50:34 +0800 Subject: [PATCH 127/545] refactor the code --- .../java/blade/plugin/sql2o/Condition.java | 8 - .../java/blade/plugin/sql2o/Constant.java | 33 + .../java/blade/plugin/sql2o/DBConfig.java | 67 ++ .../main/java/blade/plugin/sql2o/Model.java | 19 +- .../java/blade/plugin/sql2o/Sql2oPlugin.java | 133 +--- .../java/blade/plugin/sql2o/WhereParam.java | 2 +- .../plugin/sql2o/ds/AbstractDataSource.java | 15 - .../plugin/sql2o/ds/DataSourceManager.java | 74 +- .../blade/plugin/sql2o/ds/JdbcDataSource.java | 78 -- .../plugin/sql2o/exception/PoolException.java | 27 - .../plugin/sql2o/pool/ConnectionPool.java | 330 -------- .../sql2o/pool/ConnectionPoolManager.java | 125 --- .../blade/plugin/sql2o/pool/Constant.java | 134 ---- .../blade/plugin/sql2o/pool/DatabaseType.java | 95 --- .../plugin/sql2o/pool/InitPoolConfig.java | 23 - .../blade/plugin/sql2o/pool/PoolConfig.java | 228 ------ .../src/main/java/org/sql2o/Connection.java | 310 -------- .../sql2o/DefaultResultSetHandlerFactory.java | 187 ----- ...DefaultResultSetHandlerFactoryBuilder.java | 65 -- .../org/sql2o/DelegatingResultSetHandler.java | 23 - .../java/org/sql2o/GenericDatasource.java | 98 --- .../main/java/org/sql2o/JndiDataSource.java | 41 - .../java/org/sql2o/PojoResultSetIterator.java | 38 - .../src/main/java/org/sql2o/Query.java | 721 ------------------ .../main/java/org/sql2o/ResultSetHandler.java | 13 - .../org/sql2o/ResultSetHandlerFactory.java | 13 - .../sql2o/ResultSetHandlerFactoryBuilder.java | 36 - .../java/org/sql2o/ResultSetIterable.java | 15 - .../java/org/sql2o/ResultSetIteratorBase.java | 107 --- .../src/main/java/org/sql2o/Sql2o.java | 378 --------- .../main/java/org/sql2o/Sql2oException.java | 22 - .../java/org/sql2o/StatementRunnable.java | 11 - .../sql2o/StatementRunnableWithResult.java | 11 - .../converters/AbstractDateConverter.java | 44 -- .../sql2o/converters/BigDecimalConverter.java | 33 - .../sql2o/converters/BooleanConverter.java | 37 - .../sql2o/converters/ByteArrayConverter.java | 54 -- .../org/sql2o/converters/ByteConverter.java | 26 - .../java/org/sql2o/converters/Convert.java | 158 ---- .../java/org/sql2o/converters/Converter.java | 17 - .../org/sql2o/converters/ConverterBase.java | 12 - .../sql2o/converters/ConverterException.java | 15 - .../sql2o/converters/ConvertersProvider.java | 14 - .../org/sql2o/converters/DateConverter.java | 19 - .../DefaultEnumConverterFactory.java | 32 - .../org/sql2o/converters/DoubleConverter.java | 26 - .../converters/EnumConverterFactory.java | 8 - .../org/sql2o/converters/FloatConverter.java | 26 - .../converters/InputStreamConverter.java | 22 - .../sql2o/converters/IntegerConverter.java | 26 - .../org/sql2o/converters/LongConverter.java | 26 - .../org/sql2o/converters/NumberConverter.java | 47 -- .../org/sql2o/converters/ShortConverter.java | 26 - .../org/sql2o/converters/StringConverter.java | 57 -- .../org/sql2o/converters/UUIDConverter.java | 25 - .../converters/joda/DateTimeConverter.java | 46 -- .../converters/joda/LocalTimeConverter.java | 31 - .../org/sql2o/converters/package-info.java | 5 - .../src/main/java/org/sql2o/data/Column.java | 34 - .../main/java/org/sql2o/data/LazyTable.java | 42 - .../src/main/java/org/sql2o/data/Row.java | 194 ----- .../src/main/java/org/sql2o/data/Table.java | 45 -- .../sql2o/data/TableResultSetIterator.java | 51 -- .../java/org/sql2o/data/package-info.java | 4 - .../src/main/java/org/sql2o/package-info.java | 4 - .../main/java/org/sql2o/quirks/Db2Quirks.java | 28 - .../main/java/org/sql2o/quirks/NoQuirks.java | 123 --- .../java/org/sql2o/quirks/OracleQuirks.java | 36 - .../java/org/sql2o/quirks/PostgresQuirks.java | 24 - .../main/java/org/sql2o/quirks/Quirks.java | 54 -- .../java/org/sql2o/quirks/QuirksDetector.java | 34 - .../java/org/sql2o/quirks/QuirksProvider.java | 11 - .../SqlParameterParsingStrategy.java | 11 - .../impl/AbstractCommentParser.java | 23 - .../parameterparsing/impl/CharParser.java | 9 - .../parameterparsing/impl/DefaultParser.java | 18 - .../DefaultSqlParameterParsingStrategy.java | 44 -- .../impl/DoubleHyphensCommentParser.java | 17 - .../impl/ForwardSlashCommentParser.java | 26 - .../impl/ParameterParser.java | 44 -- .../parameterparsing/impl/QuoteParser.java | 26 - .../sql2o/quirks/spi/QuirksProviderImpl.java | 40 - .../org/sql2o/reflection/FactoryFacade.java | 60 -- .../org/sql2o/reflection/FieldSetter.java | 34 - .../sql2o/reflection/FieldSetterFactory.java | 14 - .../reflection/MethodAccessorsGenerator.java | 164 ---- .../org/sql2o/reflection/MethodSetter.java | 38 - .../sql2o/reflection/MethodSetterFactory.java | 14 - .../sql2o/reflection/ObjectConstructor.java | 12 - .../reflection/ObjectConstructorFactory.java | 12 - .../main/java/org/sql2o/reflection/Pojo.java | 84 -- .../sql2o/reflection/PojoIntrospector.java | 118 --- .../org/sql2o/reflection/PojoMetadata.java | 188 ----- .../ReflectionFieldSetterFactory.java | 16 - .../ReflectionMethodSetterFactory.java | 16 - .../ReflectionObjectConstructorFactory.java | 30 - .../java/org/sql2o/reflection/Setter.java | 10 - .../reflection/UnsafeFieldSetterFactory.java | 260 ------- .../org/sql2o/reflection/package-info.java | 4 - .../java/org/sql2o/tools/AbstractCache.java | 60 -- .../java/org/sql2o/tools/FeatureDetector.java | 57 -- .../sql2o/tools/UnderscoreToCamelCase.java | 34 - .../java/org/sql2o/tools/package-info.java | 4 - 103 files changed, 175 insertions(+), 6308 deletions(-) create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/Constant.java create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/ds/AbstractDataSource.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/ds/JdbcDataSource.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/exception/PoolException.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/DatabaseType.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/InitPoolConfig.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/Connection.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactoryBuilder.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/DelegatingResultSetHandler.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/GenericDatasource.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/PojoResultSetIterator.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/Query.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/ResultSetHandler.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactoryBuilder.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/ResultSetIterable.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/ResultSetIteratorBase.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/Sql2o.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/Sql2oException.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/StatementRunnable.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/StatementRunnableWithResult.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/AbstractDateConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/BigDecimalConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/BooleanConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ByteConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/Convert.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/Converter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ConverterBase.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ConverterException.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ConvertersProvider.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/DateConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/DefaultEnumConverterFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/DoubleConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/EnumConverterFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/FloatConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/InputStreamConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/IntegerConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/LongConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/NumberConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/ShortConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/UUIDConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/joda/DateTimeConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/joda/LocalTimeConverter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/converters/package-info.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/data/Column.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/data/LazyTable.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/data/Row.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/data/Table.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/data/TableResultSetIterator.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/data/package-info.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/package-info.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/Db2Quirks.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/NoQuirks.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/OracleQuirks.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/PostgresQuirks.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/Quirks.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/QuirksDetector.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/QuirksProvider.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/SqlParameterParsingStrategy.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/AbstractCommentParser.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/CharParser.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultParser.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultSqlParameterParsingStrategy.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DoubleHyphensCommentParser.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ForwardSlashCommentParser.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ParameterParser.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/QuoteParser.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/quirks/spi/QuirksProviderImpl.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetterFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetterFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructor.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructorFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionFieldSetterFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionMethodSetterFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionObjectConstructorFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/reflection/package-info.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/AbstractCache.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java delete mode 100644 blade-sql2o/src/main/java/org/sql2o/tools/package-info.java diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java index bacc585b1..1b755ad4a 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java @@ -130,42 +130,34 @@ public void clearMap() { if(null != this.params){ this.params.clear(); -// this.params = null; } if(null != this.equalsParams){ this.equalsParams.clear(); -// this.equalsParams = null; } if(null != this.greaterParams){ this.greaterParams.clear(); -// this.greaterParams = null; } if(null != this.greaterThanParams){ this.greaterThanParams.clear(); -// this.greaterThanParams = null; } if(null != this.lessParams){ this.lessParams.clear(); -// this.lessParams = null; } if(null != this.lessThanParams){ this.lessThanParams.clear(); - this.lessThanParams = null; } if(null != this.likeParams){ this.likeParams.clear(); - this.likeParams = null; } if(null != this.inParams){ this.inParams.clear(); - this.inParams = null; } if(null != this.logParams){ diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Constant.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Constant.java new file mode 100644 index 000000000..be3a41714 --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Constant.java @@ -0,0 +1,33 @@ +package blade.plugin.sql2o; + +/** + * 连接池常量 + */ +public final class Constant { + + /** + * 数据库驱动 + */ + public static final String DRIVE = "blade.db.drive"; + + /** + * 数据库URL + */ + public static final String URL = "blade.db.url"; + + /** + * 用户名 + */ + public static final String USERNAME = "blade.db.username"; + + /** + * 密码 + */ + public static final String PASSWORD = "blade.db.password"; + + /** + * 是否开启缓存 + */ + public static final String OPEN_CACHE = "blade.db.opencache"; + +} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java new file mode 100644 index 000000000..b88b37ab7 --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java @@ -0,0 +1,67 @@ +package blade.plugin.sql2o; + +public class DBConfig { + + /** + * 驱动名称 + */ + private String driverName; + + /** + * 连接地址 + */ + private String url; + + /** + * 用户名 + */ + private String userName; + + /** + * 密码 + */ + private String passWord; + + public DBConfig() { + // TODO Auto-generated constructor stub + } + + public String getDriverName() { + return driverName; + } + + public void setDriverName(String driverName) { + this.driverName = driverName; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + @Override + public String toString() { + return "DBConfig [driverName=" + driverName + ", url=" + url + + ", userName=" + userName + ", passWord=" + passWord + "]"; + } + +} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 537655b79..b3867777c 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -30,19 +30,14 @@ public class Model { private static final Logger LOGGER = Logger.getLogger(Model.class); /** - * 是否开启缓存 + * 缓存对象 */ - private boolean isOpenCache = Sql2oPlugin.INSTANCE.isOpenCache(); - - /** - * 缓存操作 - */ - public Sql2oCache sql2oCache = isOpenCache ? Sql2oCacheFactory.getSql2oCache() : null; + public Sql2oCache sql2oCache = Sql2oCacheFactory.getSql2oCache(); /** * sql2o对象,操作数据库 */ - private Sql2o sql2o = DataSourceManager.getSql2o(); + private Sql2o sql2o = DataSourceManager.me().getSql2o(); /** * 当前class实例 @@ -102,7 +97,7 @@ private boolean isCache(){ if(this.queryIsOpen){ return true; } - return isOpenCache && model.getAnnotation(Table.class).isCache() && this.cache; + return Sql2oPlugin.INSTANCE.isOpenCache() && model.getAnnotation(Table.class).isCache() && this.cache; } /** @@ -125,9 +120,9 @@ public Model cache(boolean cache){ */ private void init(){ this.queryIsOpen = false; - this.cache = isOpenCache; + this.cache = Sql2oPlugin.INSTANCE.isOpenCache(); if(null == this.sql2o){ - this.sql2o = DataSourceManager.getSql2o(); + this.sql2o = DataSourceManager.me().getSql2o(); } } @@ -141,7 +136,7 @@ public Model select(){ } public boolean isOpenCache() { - return isOpenCache; + return Sql2oPlugin.INSTANCE.isOpenCache(); } /** diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index 5b3fa160d..01df0463d 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -4,14 +4,12 @@ import javax.sql.DataSource; +import blade.Blade; import blade.kit.PropertyKit; import blade.kit.StringKit; import blade.kit.log.Logger; import blade.plugin.Plugin; import blade.plugin.sql2o.ds.DataSourceManager; -import blade.plugin.sql2o.pool.ConnectionPool; -import blade.plugin.sql2o.pool.Constant; -import blade.plugin.sql2o.pool.PoolConfig; /** * sql2o数据库插件 @@ -25,7 +23,9 @@ public enum Sql2oPlugin implements Plugin { private Logger LOGGER = Logger.getLogger(Sql2oPlugin.class); - private PoolConfig poolConfig; + private DBConfig dbConfig; + + private boolean isOpenCache = false; private Sql2oPlugin() { } @@ -42,87 +42,31 @@ public Sql2oPlugin load(String filePath){ String url = configProperties.getProperty(Constant.URL); String username = configProperties.getProperty(Constant.USERNAME); String password = configProperties.getProperty(Constant.PASSWORD); - String keepAliveSql = configProperties.getProperty(Constant.KEEPALIVESQL); - String minConn = configProperties.getProperty(Constant.MIN_CONN); - String maxConn = configProperties.getProperty(Constant.MAX_CONN); - String initConn = configProperties.getProperty(Constant.INIT_CONN); - String maxActiveConn = configProperties.getProperty(Constant.MAX_ACTIVE_CONN); - String connWaitTime = configProperties.getProperty(Constant.CONN_WAIT_TIME); - String connTimeOut = configProperties.getProperty(Constant.CONN_TIME_OUT); - String isCheakPool = configProperties.getProperty(Constant.IS_CHECK_POOL); - String periodCheck = configProperties.getProperty(Constant.PERIOD_CHECK); - String lazyCheck = configProperties.getProperty(Constant.LAZY_CHECK); String openCache = configProperties.getProperty(Constant.OPEN_CACHE); - String poolName = configProperties.getProperty(Constant.POOL_NAME); - if(null == INSTANCE.poolConfig){ - INSTANCE.poolConfig = new PoolConfig(); + if(null == INSTANCE.dbConfig){ + INSTANCE.dbConfig = new DBConfig(); } if(StringKit.isNotBlank(drive)){ - INSTANCE.poolConfig.setDriverName(drive); + INSTANCE.dbConfig.setDriverName(drive); } if(StringKit.isNotBlank(url)){ - INSTANCE.poolConfig.setUrl(url); + INSTANCE.dbConfig.setUrl(url); } if(StringKit.isNotBlank(username)){ - INSTANCE.poolConfig.setUserName(username); + INSTANCE.dbConfig.setUserName(username); } if(StringKit.isNotBlank(password)){ - INSTANCE.poolConfig.setPassWord(password); - } - - if(StringKit.isNotBlank(keepAliveSql)){ - INSTANCE.poolConfig.setKeepAliveSql(keepAliveSql); - } - - if(StringKit.isNotBlank(minConn) && StringKit.isNumber(minConn.trim())){ - INSTANCE.poolConfig.setMinConn(Integer.valueOf(minConn.trim())); - } - - if(StringKit.isNotBlank(maxConn) && StringKit.isNumber(maxConn.trim())){ - INSTANCE.poolConfig.setMaxConn(Integer.valueOf(maxConn.trim())); - } - - if(StringKit.isNotBlank(initConn) && StringKit.isNumber(initConn.trim())){ - INSTANCE.poolConfig.setInitConn(Integer.valueOf(initConn.trim())); - } - - if(StringKit.isNotBlank(maxActiveConn) && StringKit.isNumber(maxActiveConn.trim())){ - INSTANCE.poolConfig.setMaxActiveConn(Integer.valueOf(maxActiveConn.trim())); - } - - if(StringKit.isNotBlank(connTimeOut) && StringKit.isNumber(connTimeOut.trim())){ - INSTANCE.poolConfig.setConnTimeOut(Long.valueOf(connTimeOut.trim())); - } - - if(StringKit.isNotBlank(connWaitTime) && StringKit.isNumber(connWaitTime.trim())){ - INSTANCE.poolConfig.setConnWaitTime(Long.valueOf(connWaitTime.trim())); - } - - if(StringKit.isNotBlank(isCheakPool)){ - INSTANCE.poolConfig.setCheakPool(Boolean.valueOf(isCheakPool.trim())); - } - - if(StringKit.isNotBlank(periodCheck) && StringKit.isNumber(periodCheck.trim())){ - INSTANCE.poolConfig.setPeriodCheck(Long.valueOf(periodCheck.trim())); - } - - if(StringKit.isNotBlank(lazyCheck) && StringKit.isNumber(lazyCheck.trim())){ - INSTANCE.poolConfig.setInitDelay(Long.valueOf(lazyCheck.trim())); + INSTANCE.dbConfig.setPassWord(password); } if(StringKit.isNotBlank(openCache)){ - INSTANCE.poolConfig.setIsopenCache(Boolean.valueOf(openCache.trim())); + isOpenCache = Boolean.valueOf(openCache.trim()); } - - if(StringKit.isNotBlank(poolName)){ - INSTANCE.poolConfig.setPoolName(poolName); - } - return INSTANCE; } @@ -131,16 +75,26 @@ public Sql2oPlugin load(String filePath){ * * @param dbConfig 数据库配置 */ - public Sql2oPlugin config(PoolConfig poolConfig){ - INSTANCE.poolConfig = poolConfig; + public Sql2oPlugin config(DBConfig dbConfig){ + INSTANCE.dbConfig = dbConfig; return INSTANCE; } - public Sql2oPlugin openCache(){ - if(null == INSTANCE.poolConfig){ - INSTANCE.poolConfig = new PoolConfig(); - INSTANCE.poolConfig.setIsopenCache(true); + /** + * 设置数据源 + * @param dataSource 数据源对象 + */ + public Sql2oPlugin config(DataSource dataSource){ + String opencache = Blade.config().get("blade.db.opencache"); + if(StringKit.isNotBlank(opencache)){ + isOpenCache = Boolean.valueOf(opencache); } + DataSourceManager.me().setDataSource(dataSource); + return INSTANCE; + } + + public Sql2oPlugin openCache(){ + isOpenCache = true; return INSTANCE; } @@ -158,37 +112,30 @@ public Sql2oPlugin config(String url, String user, String pass){ } public Sql2oPlugin config(String driver, String url, String user, String pass){ - - PoolConfig poolConfig = new PoolConfig(); - poolConfig.setDriverName(driver); - poolConfig.setUrl(url); - poolConfig.setUserName(user); - poolConfig.setPassWord(pass); - INSTANCE.poolConfig = poolConfig; - + if(null == dbConfig){ + dbConfig = new DBConfig(); + } + dbConfig.setDriverName(driver); + dbConfig.setUrl(url); + dbConfig.setUserName(user); + dbConfig.setPassWord(pass); return INSTANCE; } public boolean isOpenCache() { - if(null == INSTANCE.poolConfig){ - return false; - } - return INSTANCE.poolConfig.isIsopenCache(); + return isOpenCache; } - public PoolConfig poolConfig(){ - return INSTANCE.poolConfig; + public DBConfig dbConfig(){ + return dbConfig; } @Override public void run() { - DataSourceManager.run(); - - DataSource dataSource = DataSourceManager.getDataSource(); - ConnectionPool connectionPool = DataSourceManager.getConnectionPool(); - - if(null == dataSource && null == connectionPool){ + DataSourceManager.me().run(); + DataSource dataSource = DataSourceManager.me().getDataSource(); + if(null == dataSource){ LOGGER.error("数据库插件配置失败"); } else { LOGGER.debug("数据库插件配置成功..."); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java index 15a6431c0..cd6ed2107 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java @@ -124,7 +124,7 @@ public WhereParam like(String field, String value){ } public WhereParam in(String field, Object... values){ - if(StringKit.isNotBlank(field) && null != values && values.length > 1){ + if(StringKit.isNotBlank(field) && null != values && values.length > 0){ if(null == this.inParams){ this.inParams = CollectionKit.newLinkedHashMap(); } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/AbstractDataSource.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/AbstractDataSource.java deleted file mode 100644 index 5cf7a0b20..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/AbstractDataSource.java +++ /dev/null @@ -1,15 +0,0 @@ -package blade.plugin.sql2o.ds; - -import javax.sql.DataSource; - -/** - * 抽象数据源 - * - * @author biezhi - * @since 1.0 - */ -public interface AbstractDataSource{ - - DataSource getDataSource(); - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java index 38d83f2a7..8a805b4c7 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java @@ -4,15 +4,9 @@ import org.sql2o.Sql2o; -import blade.ioc.AbstractBeanFactory; -import blade.ioc.SingleBean; +import blade.plugin.sql2o.DBConfig; import blade.plugin.sql2o.Sql2oPlugin; import blade.plugin.sql2o.exception.DataSourceException; -import blade.plugin.sql2o.exception.PoolException; -import blade.plugin.sql2o.pool.ConnectionPool; -import blade.plugin.sql2o.pool.ConnectionPoolManager; -import blade.plugin.sql2o.pool.InitPoolConfig; -import blade.plugin.sql2o.pool.PoolConfig; /** * 数据源连接管理器 @@ -21,66 +15,52 @@ */ public final class DataSourceManager { - private static DataSource dataSource; + private static final DataSourceManager DATA_SOURCE_MANAGER = new DataSourceManager(); - private static ConnectionPool connectionPool; + private DataSource dataSource; - private static Sql2o sql2o = null; - - private static final AbstractBeanFactory beanFactory = new SingleBean(); + private Sql2o sql2o = null; private DataSourceManager() { } - public static void run(){ - Object dsFactoryObj = beanFactory.getBean(AbstractDataSource.class); - if(null != dsFactoryObj && dsFactoryObj instanceof AbstractDataSource){ - DataSourceManager.dataSource = ((AbstractDataSource) dsFactoryObj).getDataSource(); - if(null == DataSourceManager.dataSource){ - throw new DataSourceException("数据源初始化失败!"); - } + public static DataSourceManager me(){ + return DATA_SOURCE_MANAGER; + } + + public void run(){ + if(null != this.dataSource){ + sql2o = new Sql2o(this.dataSource); } else { - // 内部连接池 - DataSourceManager.connectionPool = getConnectionPool(); - } - - if(null != DataSourceManager.dataSource){ - sql2o = new Sql2o(DataSourceManager.dataSource); - } - - if(null != DataSourceManager.connectionPool){ - sql2o = new Sql2o(connectionPool); + DBConfig dbConfig = Sql2oPlugin.INSTANCE.dbConfig(); + if(null == dbConfig){ + throw new DataSourceException("数据库配置失败"); + } + try { + Class.forName(dbConfig.getDriverName()); + sql2o = new Sql2o(dbConfig.getUrl(), dbConfig.getUserName(), dbConfig.getPassWord()); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } } } - public static Sql2o getSql2o(){ + public synchronized Sql2o getSql2o(){ return sql2o; } - public static ConnectionPool getConnectionPool() { - if(null == connectionPool){ - PoolConfig poolConfig = Sql2oPlugin.INSTANCE.poolConfig(); - if(null == poolConfig){ - throw new PoolException("数据库配置失败"); - } - InitPoolConfig.add(poolConfig); - return ConnectionPoolManager.me().getPool(poolConfig.getPoolName()); - } - return connectionPool; - } - /** * 提供动态注入datasource * @param dataSource_ */ - public static void setDataSource(DataSource dataSource){ - DataSourceManager.dataSource = dataSource; - if(null != DataSourceManager.dataSource){ - sql2o = new Sql2o(DataSourceManager.dataSource); + public void setDataSource(DataSource dataSource){ + this.dataSource = dataSource; + if(null != this.dataSource){ + sql2o = new Sql2o(this.dataSource); } } - public static DataSource getDataSource(){ + public DataSource getDataSource(){ return dataSource; } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/JdbcDataSource.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/JdbcDataSource.java deleted file mode 100644 index 1605d1e03..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/JdbcDataSource.java +++ /dev/null @@ -1,78 +0,0 @@ -package blade.plugin.sql2o.ds; - -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.util.logging.Logger; - -import javax.sql.DataSource; - -public class JdbcDataSource implements DataSource { - - private String url; - private String driver; - private String username; - private String password; - - public JdbcDataSource(String url, String driver, String username, - String password) { - super(); - this.url = url; - this.driver = driver; - this.username = username; - this.password = password; - } - - @Override - public PrintWriter getLogWriter() throws SQLException { - return null; - } - - @Override - public void setLogWriter(PrintWriter out) throws SQLException { - } - - @Override - public void setLoginTimeout(int seconds) throws SQLException { - } - - @Override - public int getLoginTimeout() throws SQLException { - return 0; - } - - @Override - public Logger getParentLogger() throws SQLFeatureNotSupportedException { - return null; - } - - @Override - public T unwrap(Class iface) throws SQLException { - return null; - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return false; - } - - @Override - public Connection getConnection() throws SQLException { - try { - Class.forName(this.driver) ; - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - Connection conn = DriverManager.getConnection(this.url, this.username, this.password) ; - return conn; - } - - @Override - public Connection getConnection(String username, String password) - throws SQLException { - return null; - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/exception/PoolException.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/exception/PoolException.java deleted file mode 100644 index eb12b06c5..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/exception/PoolException.java +++ /dev/null @@ -1,27 +0,0 @@ -package blade.plugin.sql2o.exception; - - -/** - * PoolException - *

- *

- * - * @author biezhi - * @since 1.0 - */ -public class PoolException extends RuntimeException{ - - private static final long serialVersionUID = 4566581404090220394L; - - public PoolException() { - throw new RuntimeException(); - } - - public PoolException(String e) { - throw new RuntimeException(e); - } - - public PoolException(Exception e) { - throw new RuntimeException(e); - } -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java deleted file mode 100644 index 5720a5e58..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPool.java +++ /dev/null @@ -1,330 +0,0 @@ -package blade.plugin.sql2o.pool; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; -import java.util.TimerTask; -import java.util.Vector; -import java.util.concurrent.TimeUnit; - -import blade.kit.StringKit; -import blade.kit.TaskKit; -import blade.kit.log.Logger; - -/** - * 数据库连接池 - * @author biezhi - * - */ -public class ConnectionPool { - - private static final Logger LOGGER = Logger.getLogger(ConnectionPool.class); - - /** - * 连接池活动状态 - */ - private boolean isActive = false; - - /** - * 连接池配置对象 - */ - private PoolConfig poolConfig; - - /** - * 创建的连接数 - */ - private int totalConn; - - /** - * 空闲连接 - */ - private List freeConnections = new Vector(); - - /** - * 活动连接 - */ - private List activeConnections = new Vector(); - - /** - * 将线程和连接绑定,保证事务能统一执行 - */ - ThreadLocal threadLocal = new ThreadLocal(); - - /** - * 构造方法,初始化连接池 - * - * @param poolConfig - */ - public ConnectionPool(PoolConfig poolConfig) { - super(); - this.poolConfig = poolConfig; - createConnectionPool(); - checkConnectionPool(); - - } - - /** - * 创建连接池 - */ - private void createConnectionPool() { - try { - Class.forName(poolConfig.getDriverName()); - int initNum = poolConfig.getInitConn(); - for (int i = 0; i < initNum; i++) { - Connection conn = createConn(); - freeConnections.add(conn); - } - isActive = true; - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - /** - * 检查sql测试语句 - * @throws SQLException - */ - protected void sendCheckSQL() throws SQLException { - Statement statement = null; - Connection internalConnection = null; - try { - internalConnection = obtainInternalConnection(); - String keepAliveSQL = poolConfig.getKeepAliveSql(); - if (StringKit.isEmpty(keepAliveSQL)) { - internalConnection.getMetaData().getTables(null, null, "connpool_keepalive", new String[] { "TABLE" }); - } else { - statement = internalConnection.createStatement(); - statement.execute(keepAliveSQL); - } - LOGGER.debug("keepalive test success!"); - } catch (SQLException e) { - LOGGER.error("keepalive test error!", e); - throw e; - } finally { - internalConnection.close(); - } - } - - /** - * 创建一个连接 - * @return - * @throws SQLException - */ - private Connection obtainInternalConnection() throws SQLException { - return DriverManager.getConnection(poolConfig.getUrl(), poolConfig.getUserName(), poolConfig.getPassWord()); - } - - /** - * 连接池创建一个连接 - * @return - * @throws ClassNotFoundException - * @throws SQLException - */ - private synchronized Connection createConn() throws ClassNotFoundException, SQLException { - Connection conn = null; - if (null != poolConfig) { - conn = DriverManager.getConnection(poolConfig.getUrl(), - poolConfig.getUserName(), poolConfig.getPassWord()); - totalConn++; - } - return conn; - } - - /** - * 获得连接 - * @return - */ - public synchronized Connection getConnection() { - - Connection conn = null; - try { - if (null == poolConfig) { - return conn; - } - - // 如果已经创建的连接数小于数据库的最大连接数而且小于连接池最大的连接数,那么再创建连接数 - if (totalConn < poolConfig.getMaxActiveConn() && totalConn < poolConfig.getMaxActiveConn()) { - - if (freeConnections.size() > 0) {// 如果还有空闲连接 - conn = freeConnections.get(0); - if (null != conn) { - threadLocal.set(conn); - freeConnections.remove(0); - - } - } else { - conn = createConn(); - } - - } else { - // 等待一段时间后再去获得连接 - wait(poolConfig.getConnWaitTime()); - conn = getConnection(); - } - - if (isValid(conn)) { - activeConnections.add(conn); - } - - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (SQLException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - return conn; - } - - private boolean isValid(Connection conn) { - try { - if (conn == null || conn.isClosed()) { - return false; - } - } catch (SQLException e) { - e.printStackTrace(); - } - return true; - } - - /** - * 获得当前连接 - * - * @return - */ - public Connection getCurrentConnection() { - // 默认从线程中取出连接 - Connection conn = threadLocal.get(); - if (!isValid(conn)) { - conn = getConnection(); - } - return conn; - } - - /** - * 释放连接 - * - * @param conn - */ - public synchronized void releaseConnection(Connection conn) throws SQLException { - - if (isValid(conn) && !(freeConnections.size() > poolConfig.getMaxConn())) { - freeConnections.add(conn); - activeConnections.remove(conn); - threadLocal.remove(); - totalConn--; - // 唤醒所有正待等待的线程,去抢连接 - notifyAll(); - } - - } - - /** - * 关闭连接 - * - * @param conn - * @throws SQLException - */ - public synchronized void closeConnection(Connection conn) throws SQLException { - conn.close(); - freeConnections.remove(conn); - activeConnections.remove(conn); - threadLocal.remove(); - } - - /** - * 销毁连接 - */ - public synchronized void destroy() { - for (Connection conn : freeConnections) { - try { - if (isValid(conn)) { - conn.close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } - for (Connection conn : activeConnections) { - try { - if (isValid(conn)) { - conn.close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } - isActive = false; - totalConn = 0; - - // 停止监控线程 - /*if(null != scheduledFuture){ - scheduledFuture.cancel(false); - TaskKit.reset(); - }*/ - } - - /** - * 判断该连接池是否可用 - * - * @return - */ - public boolean isActive() { - return isActive; - } - - /** - * 获得活动的连接数 - * - * @return - */ - public int getActiveConnNum() { - return activeConnections.size(); - } - - /** - * 获得空闲的连接数 - * - * @return - */ - public int getFreeConnNum() { - return freeConnections.size(); - } - - /** - * 定时检查连接池 - */ - private void checkConnectionPool() { - - // 测试语句 - if(StringKit.isNotBlank(poolConfig.getKeepAliveSql())){ - try { - sendCheckSQL(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - if (poolConfig.isCheakPool()) { - - TaskKit.scheduleWithFixedDelay(new TimerTask() { - @Override - public void run() { - LOGGER.debug("idle connection count:" + freeConnections.size()); - LOGGER.debug("active connection count:" + activeConnections.size()); - LOGGER.debug("total connection count:" + totalConn); - LOGGER.debug("pool active status:" + isActive); - } - }, poolConfig.getInitDelay(), poolConfig.getPeriodCheck(), TimeUnit.SECONDS); - - - } - - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java deleted file mode 100644 index dd096580a..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/ConnectionPoolManager.java +++ /dev/null @@ -1,125 +0,0 @@ -package blade.plugin.sql2o.pool; - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Hashtable; -import java.util.List; - -import blade.kit.log.Logger; - -/** - * 数据连接池管理器 - * - * @author biezhi - * - */ -public class ConnectionPoolManager { - - private static final Logger LOGGER = Logger.getLogger(ConnectionPoolManager.class); - - private static ConnectionPoolManager connectionPoolManager; - - /** - * 连接池存放 - */ - private Hashtable pools; - - /** - * 总的连接数 - */ - private static int clients; - - private ConnectionPoolManager() { - connectionPoolManager = this; - pools = new Hashtable(); - init(); - } - - private void init() { - - List poolConfigs = InitPoolConfig.poolConfigList; - - for (PoolConfig config : poolConfigs) { - ConnectionPool pool = new ConnectionPool(config); - if (pool != null) { - pools.put(config.getPoolName(), pool); - LOGGER.info("Init connection successed -> " + config.getPoolName()); - } - } - - } - - /** - * 获得连接池管理器实例 - * - * @return - */ - public static synchronized ConnectionPoolManager me() { - if (null == connectionPoolManager) { - connectionPoolManager = new ConnectionPoolManager(); - } - clients++; - return connectionPoolManager; - } - - /** - * 获得连接池 - * - * @return - */ - public ConnectionPool getPool(String poolName) { - return pools.get(poolName); - } - - /** - * 获得数据库链接 - * - * @return - */ - public Connection getConnection(String poolName) { - Connection conn = null; - if (pools.size() > 0 && pools.containsKey(poolName)) { - conn = getPool(poolName).getConnection(); - } else { - LOGGER.error("Can't find this connecion pool -> " + poolName); - } - return conn; - } - - /** - * 释放连接 - */ - public void releaseConnection(String poolName, Connection conn) { - try { - ConnectionPool pool = getPool(poolName); - if (null != null) { - pool.releaseConnection(conn); - } - } catch (SQLException e) { - LOGGER.warn("connection is release"); - e.printStackTrace(); - } - } - - /** - * 清空连接池 - * - * @param poolName - */ - public void destory(String poolName) { - ConnectionPool pool = getPool(poolName); - if (null != null) { - pool.destroy(); - } - } - - /** - * 获得连接数 - * - * @return - */ - public static int getClients() { - return clients; - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java deleted file mode 100644 index 81f44ccd9..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/Constant.java +++ /dev/null @@ -1,134 +0,0 @@ -package blade.plugin.sql2o.pool; - -/** - * 连接池常量 - */ -public final class Constant { - - /** - * 数据库驱动 - */ - public static final String DRIVE = "blade.db.drive"; - - /** - * 数据库URL - */ - public static final String URL = "blade.db.url"; - - /** - * 用户名 - */ - public static final String USERNAME = "blade.db.username"; - - /** - * 密码 - */ - public static final String PASSWORD = "blade.db.password"; - - /** - * 测试SQL语句 - */ - public static final String KEEPALIVESQL = "blade.db.keepAliveSql"; - - /** - * 最小连接 - */ - public static final String MIN_CONN = "blade.db.minConn"; - - /** - * 最大连接 - */ - public static final String MAX_CONN = "blade.db.maxConn"; - - /** - * 初始连接数 - */ - public static final String INIT_CONN = "blade.db.initConn"; - - /** - * 最大活动连接 - */ - public static final String MAX_ACTIVE_CONN = "blade.db.maxActiveConn"; - - /** - * 连接等待时间 - */ - public static final String CONN_WAIT_TIME = "blade.db.connWaitTime"; - - /** - * 连接超时时间 - */ - public static final String CONN_TIME_OUT = "blade.db.connTimeOut"; - - /** - * 是否检查连接池 - */ - public static final String IS_CHECK_POOL = "blade.db.isCheakPool"; - - /** - * 检查频率 - */ - public static final String PERIOD_CHECK = "blade.db.periodCheck"; - - /** - * 初始延时检查 - */ - public static final String LAZY_CHECK = "blade.db.initDelay"; - - /** - * 连接池名称 - */ - public static final String POOL_NAME = "blade.db.poolName"; - - /** - * 是否开启缓存 - */ - public static final String OPEN_CACHE = "blade.db.opencache"; - - /** - * 默认连接池名称 - */ - public static final String DEFAULT_POOL_NAME = "blade_sql2o_pool"; - - /** - * 默认初始连接数 - */ - public static final int DEFAULT_INIT_CONN = 5; - - /** - * 默认最小连接数 - */ - public static final int DEFAULT_MIN_CONN = 1; - - /** - * 默认最大连接数 - */ - public static final int DEFAULT_MAX_CONN = 20; - - /** - * 默认最大活动连接数 - */ - public static final int DEFAULT_MAX_ACTIVE_CONN = 100; - - /** - * 默认最大连接等待时长 - */ - public static final long DEFAULT_CONN_WAIT_TIME = 1000; - - /** - * 默认连接超时时间 - */ - public static final long DEFAULT_CONN_TIME_OUT = 1200; - - /** - * 默认检查频率 - */ - public static final long DEFAULT_PERIOD_CHECK = 3600; - - /** - * 默认初始化延迟检查时间 - */ - public static final long DEFAULT_INIT_DELAY = 1200; - - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/DatabaseType.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/DatabaseType.java deleted file mode 100644 index d554c6bc2..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/DatabaseType.java +++ /dev/null @@ -1,95 +0,0 @@ -package blade.plugin.sql2o.pool; - -import java.sql.Connection; -import java.sql.SQLException; - -/** - * 定义数据库类型 - * @author biezhi - * - */ -public class DatabaseType { - - public final static int UNKNOW = 0; - public final static int ORACLE = 1; - public final static int MYSQL = 2; - public final static int POSTGRESQL = 3; - public final static int SQLSERVER = 4; - public final static int HSQL = 5; - public final static int DB2 = 6; - - public final static String ORACLE_NAME = "ORACLE"; - public final static String MYSQL_NAME = "MYSQL"; - public final static String POSTGRESQL_NAME = "POSTGRESQL"; - public final static String SQLSERVER_NAME = "SQLSERVER"; - public final static String HSQL_NAME = "HSQL"; - public final static String DB2_NAME = "DB2"; - - /** - * 获得数据库类型 - * - * @param conn - * 数据库链接 - * @return int型的数据库类型(如:DatabaseType.ORACLE) - */ - public static int getDbType(Connection conn) { - - String dbName = null; - int dbType = 0; - - try { - dbName = conn.getMetaData().getDatabaseProductName(); - if (dbName.toUpperCase().indexOf(ORACLE_NAME) > -1) { - dbType = ORACLE; - } else if (dbName.toUpperCase().indexOf(MYSQL_NAME) > -1) { - dbType = MYSQL; - } else if (dbName.toUpperCase().indexOf(POSTGRESQL_NAME) > -1) { - dbType = POSTGRESQL; - } else if (dbName.toUpperCase().indexOf(SQLSERVER_NAME) > -1) { - dbType = SQLSERVER; - } else if (dbName.toUpperCase().indexOf(HSQL_NAME) > -1) { - dbType = HSQL; - } else if (dbName.toUpperCase().indexOf(DB2_NAME) > -1) { - dbType = DB2; - } else { - dbType = UNKNOW; - } - - } catch (SQLException e) { - e.printStackTrace(); - } - - return dbType; - } - - /** - * 获得数据库类型 - * - * @param driverName - * 驱动字符串 - * @return int型的数据库类型(如:DatabaseType.ORACLE) - */ - public static int getDbType(String driverName) { - - int dbType = 0; - - if (driverName.toUpperCase().indexOf(ORACLE_NAME) > -1) { - dbType = ORACLE; - } else if (driverName.toUpperCase().indexOf(MYSQL_NAME) > -1) { - dbType = MYSQL; - } else if (driverName.toUpperCase().indexOf(POSTGRESQL_NAME) > -1) { - dbType = POSTGRESQL; - } else if (driverName.toUpperCase().indexOf(SQLSERVER_NAME) > -1) { - dbType = SQLSERVER; - } else if (driverName.toUpperCase().indexOf(HSQL_NAME) > -1) { - dbType = HSQL; - } else if (driverName.toUpperCase().indexOf(DB2_NAME) > -1) { - dbType = DB2; - } else { - dbType = UNKNOW; - } - - return dbType; - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/InitPoolConfig.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/InitPoolConfig.java deleted file mode 100644 index 10ff227b8..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/InitPoolConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package blade.plugin.sql2o.pool; - -import java.util.ArrayList; -import java.util.List; - -/** - * 初始化数据连接池配置 - * @author biezhi - * - */ -public class InitPoolConfig { - - static List poolConfigList; - - static{ - poolConfigList = new ArrayList(); - } - - public static void add(PoolConfig poolConfig){ - poolConfigList.add(poolConfig); - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java deleted file mode 100644 index d12cfd5b4..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/pool/PoolConfig.java +++ /dev/null @@ -1,228 +0,0 @@ -package blade.plugin.sql2o.pool; - -/** - * 数据库连接池参数 - * @author biezhi - * - */ -public class PoolConfig { - - /** - * 驱动名称 - */ - private String driverName; - - /** - * 连接地址 - */ - private String url; - - /** - * 用户名 - */ - private String userName; - - /** - * 密码 - */ - private String passWord; - - /** - * 连接测试语句 - */ - private String keepAliveSql; - - /** - * 最小连接数 - */ - private int minConn = Constant.DEFAULT_MIN_CONN; - - /** - * 最大连接数 - */ - private int maxConn = Constant.DEFAULT_MAX_CONN; - - /** - * 初始化时连接数 - */ - private int initConn = Constant.DEFAULT_INIT_CONN; - - /** - * 数据库最大的连接数 - */ - private int maxActiveConn = Constant.DEFAULT_MAX_ACTIVE_CONN; - - /** - * 重复去获得连接的频率 - */ - private long connWaitTime = Constant.DEFAULT_CONN_WAIT_TIME; - - /** - * 连接超时时间,默认20分钟 - */ - private long connTimeOut = Constant.DEFAULT_CONN_TIME_OUT; - - /** - * 是否定时检查连接池 - */ - private boolean isCheakPool = true; - - /** - * 检查频率/秒 - */ - private long periodCheck = Constant.DEFAULT_PERIOD_CHECK; - - /** - * 延迟多少时间后开始 检查/秒 - */ - private long initDelay = Constant.DEFAULT_INIT_DELAY; - - private boolean isopenCache = false; - - /** - * 数据库连接池的名称 - */ - private String poolName = Constant.DEFAULT_POOL_NAME; - - public PoolConfig() { - // TODO Auto-generated constructor stub - } - - public String getPoolName() { - return poolName; - } - - public void setPoolName(String poolName) { - this.poolName = poolName; - } - - public String getDriverName() { - return driverName; - } - - public void setDriverName(String driverName) { - this.driverName = driverName; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassWord() { - return passWord; - } - - public void setPassWord(String passWord) { - this.passWord = passWord; - } - - public int getMinConn() { - return minConn; - } - - public void setMinConn(int minConn) { - this.minConn = minConn; - } - - public int getMaxConn() { - return maxConn; - } - - public void setMaxConn(int maxConn) { - this.maxConn = maxConn; - } - - - public long getConnWaitTime() { - return connWaitTime; - } - - public void setConnWaitTime(long connWaitTime) { - this.connWaitTime = connWaitTime; - } - - - public int getInitConn() { - return initConn; - } - - public void setInitConn(int initConn) { - this.initConn = initConn; - } - - public int getMaxActiveConn() { - return maxActiveConn; - } - - public void setMaxActiveConn(int maxActiveConn) { - this.maxActiveConn = maxActiveConn; - } - - public long getConnTimeOut() { - return connTimeOut; - } - - public void setConnTimeOut(long connTimeOut) { - this.connTimeOut = connTimeOut; - } - - public boolean isCheakPool() { - return isCheakPool; - } - - public void setCheakPool(boolean isCheakPool) { - this.isCheakPool = isCheakPool; - } - - public long getPeriodCheck() { - return periodCheck; - } - - public void setPeriodCheck(long periodCheck) { - this.periodCheck = periodCheck; - } - - public long getInitDelay() { - return initDelay; - } - - public void setInitDelay(long initDelay) { - this.initDelay = initDelay; - } - - public String getKeepAliveSql() { - return keepAliveSql; - } - - public void setKeepAliveSql(String keepAliveSql) { - this.keepAliveSql = keepAliveSql; - } - - public boolean isIsopenCache() { - return isopenCache; - } - - public void setIsopenCache(boolean isopenCache) { - this.isopenCache = isopenCache; - } - - @Override - public String toString() { - return "PoolConfig [maxConn=" + maxConn + ", minConn=" + minConn - + ", initConn=" + initConn + ", connTimeOut=" + connTimeOut - + ", keepAliveSql=" + keepAliveSql + ",driverName=" + driverName + ", url=" - + url + ", username=" + userName + ", password=" + passWord + "]"; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/Connection.java b/blade-sql2o/src/main/java/org/sql2o/Connection.java deleted file mode 100644 index e9321d8a6..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/Connection.java +++ /dev/null @@ -1,310 +0,0 @@ -package org.sql2o; - -import static org.sql2o.converters.Convert.throwIfNull; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.sql2o.converters.Converter; -import org.sql2o.converters.ConverterException; -import org.sql2o.quirks.Quirks; - -import blade.kit.log.Logger; - -/** - * Represents a connection to the database with a transaction. - */ -public class Connection implements AutoCloseable { - -// private final static Logger logger = LocalLoggerFactory.getLogger(Connection.class); - private final static Logger logger = Logger.getLogger(Connection.class); - - private java.sql.Connection jdbcConnection; - private Sql2o sql2o; - - private Integer result = null; - private int[] batchResult = null; - private List keys; - private boolean canGetKeys; - - private boolean rollbackOnException = true; - - public boolean isRollbackOnException() { - return rollbackOnException; - } - - public Connection setRollbackOnException(boolean rollbackOnException) { - this.rollbackOnException = rollbackOnException; - return this; - } - - final boolean autoClose; - - Connection(Sql2o sql2o, boolean autoClose) { - - this.autoClose = autoClose; - this.sql2o = sql2o; - createConnection(); - } - - void onException() { - if (isRollbackOnException()) { - rollback(this.autoClose); - } - } - - public java.sql.Connection getJdbcConnection() { - return jdbcConnection; - } - - public Sql2o getSql2o() { - return sql2o; - } - - public Query createQuery(String queryText, String name){ - boolean returnGeneratedKeys = this.sql2o.getQuirks().returnGeneratedKeysByDefault(); - return createQuery(queryText, name, returnGeneratedKeys); - } - - public Query createQuery(String queryText, String name, boolean returnGeneratedKeys){ - - try { - if (jdbcConnection.isClosed()){ - createConnection(); - } - } catch (SQLException e) { - throw new RuntimeException(e); - } - - return new Query(this, queryText, name, returnGeneratedKeys); - } - - public Query createQueryWithParams(String queryText, Object... paramValues){ - Query query = createQuery(queryText, null); - boolean destroy = true; - try { - query.withParams(paramValues); - destroy = false; - return query; - } finally { - // instead of re-wrapping exception - // just keep it as-is - // but kill a query - if(destroy) query.close(); - } - } - - public Query createQuery(String queryText){ - return createQuery(queryText, null); - } - - public Query createQuery(String queryText, boolean returnGeneratedKeys) { - return createQuery(queryText, null, returnGeneratedKeys); - } - - public Sql2o rollback(){ - return this.rollback(true).sql2o; - } - - public Connection rollback(boolean closeConnection){ - try { - jdbcConnection.rollback(); - } - catch (SQLException e) { - logger.warn("Could not roll back transaction.", e); - } - finally { - if(closeConnection) this.closeJdbcConnection(); - } - return this; - } - - public Sql2o commit(){ - return this.commit(true).sql2o; - } - - public Connection commit(boolean closeConnection){ - try { - jdbcConnection.commit(); - } - catch (SQLException e) { - throw new Sql2oException(e); - } - finally { - if(closeConnection) - this.closeJdbcConnection(); - } - return this; - } - - public int getResult(){ - if (this.result == null){ - throw new Sql2oException("It is required to call executeUpdate() method before calling getResult()."); - } - return this.result; - } - - void setResult(int result){ - this.result = result; - } - - public int[] getBatchResult() { - if (this.batchResult == null){ - throw new Sql2oException("It is required to call executeBatch() method before calling getBatchResult()."); - } - return this.batchResult; - } - - void setBatchResult(int[] value) { - this.batchResult = value; - } - - void setKeys(ResultSet rs) throws SQLException { - if (rs == null){ - this.keys = null; - return; - } - this.keys = new ArrayList(); - while(rs.next()){ - this.keys.add(rs.getObject(1)); - } - } - - public Object getKey(){ - if (!this.canGetKeys){ - throw new Sql2oException("Keys where not fetched from database. Please call executeUpdate(true) to fetch keys"); - } - if (this.keys != null && this.keys.size() > 0){ - return keys.get(0); - } - return null; - } - - @SuppressWarnings("unchecked") // need to change Convert - public V getKey(Class returnType){ - final Quirks quirks = this.sql2o.getQuirks(); - Object key = getKey(); - try { - Converter converter = throwIfNull(returnType, quirks.converterOf(returnType)); - return converter.convert(key); - } catch (ConverterException e) { - throw new Sql2oException("Exception occurred while converting value from database to type " + returnType.toString(), e); - } - } - - public Object[] getKeys(){ - if (!this.canGetKeys){ - throw new Sql2oException("Keys where not fetched from database. Please set the returnGeneratedKeys parameter in the createQuery() method to enable fetching of generated keys."); - } - if (this.keys != null){ - return this.keys.toArray(); - } - return null; - } - - @SuppressWarnings("unchecked") // need to change Convert - public List getKeys(Class returnType) { - final Quirks quirks = sql2o.getQuirks(); - if (!this.canGetKeys) { - throw new Sql2oException("Keys where not fetched from database. Please set the returnGeneratedKeys parameter in the createQuery() method to enable fetching of generated keys."); - } - - if (this.keys != null) { - try { - Converter converter = throwIfNull(returnType, quirks.converterOf(returnType)); - - List convertedKeys = new ArrayList(this.keys.size()); - - for (Object key : this.keys) { - convertedKeys.add(converter.convert(key)); - } - - return convertedKeys; - } - catch (ConverterException e) { - throw new Sql2oException("Exception occurred while converting value from database to type " + returnType.toString(), e); - } - } - - return null; - } - - void setCanGetKeys(boolean canGetKeys) { - this.canGetKeys = canGetKeys; - } - - private final Set statements = new HashSet(); - - void registerStatement(Statement statement){ - statements.add(statement); - } - void removeStatement(Statement statement){ - statements.remove(statement); - } - - public void close() { - boolean connectionIsClosed; - try { - connectionIsClosed = jdbcConnection.isClosed(); - } catch (SQLException e) { - throw new Sql2oException("Sql2o encountered a problem while trying to determine whether the connection is closed.", e); - } - - if (!connectionIsClosed) { - - for (Statement statement : statements) { - try { - getSql2o().getQuirks().closeStatement(statement); - } catch (Throwable e) { - logger.warn("Could not close statement.", e); - } - } - statements.clear(); - - boolean autoCommit = false; - try { - autoCommit = jdbcConnection.getAutoCommit(); - } - catch (SQLException e) { - logger.warn("Could not determine connection auto commit mode.", e); - } - - // if in transaction, rollback, otherwise just close - if (autoCommit) { - this.closeJdbcConnection(); - } - else { - this.rollback(true); - } - } - } - - private void createConnection(){ - try{ - if(this.getSql2o().getDataSource() == null && this.getSql2o().getConnectionPool() == null) - throw new Sql2oException("DataSource can't be null"); - else if(this.getSql2o().getDataSource() != null) { - this.jdbcConnection = this.getSql2o().getDataSource().getConnection(); - }else if(this.getSql2o().getConnectionPool() != null) { //Get Connection Object from PooledConnection - this.jdbcConnection = this.getSql2o().getConnectionPool().getConnection(); - } - } - catch(Exception ex){ - throw new RuntimeException(String.format("Could not aquire a connection from DataSource - ", ex.getMessage()), ex); - } - } - - private void closeJdbcConnection() { - try { - jdbcConnection.close(); - } - catch (SQLException e) { - logger.warn("Could not close connection.", e); - } - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactory.java b/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactory.java deleted file mode 100644 index 8a73a72a8..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactory.java +++ /dev/null @@ -1,187 +0,0 @@ -package org.sql2o; - -import org.sql2o.converters.Converter; -import org.sql2o.converters.ConverterException; -import org.sql2o.quirks.Quirks; -import org.sql2o.reflection.Pojo; -import org.sql2o.reflection.PojoMetadata; -import org.sql2o.reflection.Setter; -import org.sql2o.tools.AbstractCache; - -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; - - -public class DefaultResultSetHandlerFactory implements ResultSetHandlerFactory { - private final PojoMetadata metadata; - private final Quirks quirks; - - public DefaultResultSetHandlerFactory(PojoMetadata pojoMetadata, Quirks quirks) { - this.metadata = pojoMetadata; - this.quirks = quirks; - } - - @SuppressWarnings("unchecked") - private static Setter getSetter( - final Quirks quirks, - final String propertyPath, - final PojoMetadata metadata) { - int index = propertyPath.indexOf('.'); - if (index <= 0) { - // Simple path - fast way - final Setter setter = metadata.getPropertySetterIfExists(propertyPath); - // behavior change: do not throw if POJO contains less properties - if (setter == null) return null; - final Converter converter = quirks.converterOf(setter.getType()); - // setter without converter - if (converter == null) return setter; - return new Setter() { - public void setProperty(Object obj, Object value) { - try { - setter.setProperty(obj, converter.convert(value)); - } catch (ConverterException e) { - throw new Sql2oException("Error trying to convert column " + propertyPath + " to type " + setter.getType(), e); - } - } - - public Class getType() { - return setter.getType(); - } - }; - } - // dot path - long way - // i'm too lazy now to rewrite this case so I just call old unoptimized code... - // TODO: rewrite, get rid of POJO class - return new Setter() { - public void setProperty(Object obj, Object value) { - Pojo pojo = new Pojo(metadata, metadata.isCaseSensitive(), obj); - pojo.setProperty(propertyPath, value, quirks); - } - - public Class getType() { - // doesn't used anyway - return Object.class; - } - }; - } - - private static class Key { - final String stringKey; - final DefaultResultSetHandlerFactory f; - - DefaultResultSetHandlerFactory factory(){ - return f; - } - - private PojoMetadata getMetadata() { - return f.metadata; - } - - private Quirks getQuirksMode() { - return f.quirks; - } - - private Key(String stringKey, DefaultResultSetHandlerFactory f) { - this.stringKey = stringKey; - this.f = f; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Key key = (Key) o; - - return f.metadata.equals(key.getMetadata()) - && f.quirks == key.getQuirksMode() - && stringKey.equals(key.stringKey); - - } - - @Override - public int hashCode() { - int result = f.metadata.hashCode(); - result = 31 * result + f.quirks.hashCode(); - result = 31 * result + stringKey.hashCode(); - return result; - } - } - - - private static final AbstractCache - c = new AbstractCache() { - @Override - protected ResultSetHandler evaluate(Key key, ResultSetMetaData param) { - try { - return key.factory().newResultSetHandler0(param); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - }; - - @SuppressWarnings("unchecked") - public ResultSetHandler newResultSetHandler(final ResultSetMetaData meta) throws SQLException { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 1; i <= meta.getColumnCount(); i++) { - stringBuilder.append(quirks.getColumnName(meta,i)).append("\n"); - } - return c.get(new Key(stringBuilder.toString(), this),meta); - - } - - - @SuppressWarnings("unchecked") - private ResultSetHandler newResultSetHandler0(final ResultSetMetaData meta) throws SQLException { - final Setter[] setters; - final Converter converter; - final boolean useExecuteScalar; - //TODO: it's possible to cache converter/setters - // cache key is ResultSetMetadata + Bean type - - converter = quirks.converterOf(metadata.getType()); - final int columnCount = meta.getColumnCount(); - - setters = new Setter[columnCount + 1]; // setters[0] is always null - for (int i = 1; i <= columnCount; i++) { - String colName = quirks.getColumnName(meta, i); - - setters[i] = getSetter(quirks, colName, metadata); - - // If more than 1 column is fetched (we cannot fall back to executeScalar), - // and the setter doesn't exist, throw exception. - if (this.metadata.throwOnMappingFailure && setters[i] == null && columnCount > 1) { - throw new Sql2oException("Could not map " + colName + " to any property."); - } - } - /** - * Fallback to executeScalar if converter exists, - * we're selecting 1 column, and no property setter exists for the column. - */ - useExecuteScalar = converter != null && columnCount == 1 && setters[1] == null; - return new ResultSetHandler() { - @SuppressWarnings("unchecked") - public T handle(ResultSet resultSet) throws SQLException { - if (useExecuteScalar) { - try { - return (T) converter.convert(quirks.getRSVal(resultSet, 1)); - } catch (ConverterException e) { - throw new Sql2oException("Error occurred while converting value from database to type " + metadata.getType(), e); - } - } - - // otherwise we want executeAndFetch with object mapping - Object pojo = metadata.getObjectConstructor().newInstance(); - for (int colIdx = 1; colIdx <= columnCount; colIdx++) { - Setter setter = setters[colIdx]; - if (setter == null) continue; - setter.setProperty(pojo, quirks.getRSVal(resultSet, colIdx)); - } - - return (T) pojo; - } - }; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactoryBuilder.java b/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactoryBuilder.java deleted file mode 100644 index 5f97fd9ed..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/DefaultResultSetHandlerFactoryBuilder.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.sql2o; - -import org.sql2o.quirks.Quirks; -import org.sql2o.reflection.PojoMetadata; - -import java.util.Map; - -public class DefaultResultSetHandlerFactoryBuilder implements ResultSetHandlerFactoryBuilder { - private boolean caseSensitive; - private boolean autoDeriveColumnNames; - private boolean throwOnMappingError; - private Map columnMappings; - private Quirks quirks; - - public boolean isCaseSensitive() { - return caseSensitive; - } - - public void setCaseSensitive(boolean caseSensitive) { - this.caseSensitive = caseSensitive; - } - - public boolean isAutoDeriveColumnNames() { - return autoDeriveColumnNames; - } - - public void setAutoDeriveColumnNames(boolean autoDeriveColumnNames) { - this.autoDeriveColumnNames = autoDeriveColumnNames; - } - - @Override - public boolean isThrowOnMappingError() { - return throwOnMappingError; - } - - @Override - public void throwOnMappingError(boolean throwOnMappingError) { - this.throwOnMappingError = throwOnMappingError; - } - - public Map getColumnMappings() { - return columnMappings; - } - - public void setColumnMappings(Map columnMappings) { - this.columnMappings = columnMappings; - } - - public Quirks getQuirks() { - return quirks; - } - - public void setQuirks(Quirks quirks) { - this.quirks = quirks; - } - - - - @SuppressWarnings("unchecked") - public ResultSetHandlerFactory newFactory(Class clazz) { - PojoMetadata pojoMetadata = new PojoMetadata(clazz, caseSensitive, autoDeriveColumnNames, columnMappings, throwOnMappingError); - return new DefaultResultSetHandlerFactory(pojoMetadata, quirks); - } - -} diff --git a/blade-sql2o/src/main/java/org/sql2o/DelegatingResultSetHandler.java b/blade-sql2o/src/main/java/org/sql2o/DelegatingResultSetHandler.java deleted file mode 100644 index 6d46011b5..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/DelegatingResultSetHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.sql2o; - -import java.sql.ResultSet; -import java.sql.SQLException; - -/** - * User: dimzon - * Date: 4/7/14 - * Time: 11:06 PM - */ -public class DelegatingResultSetHandler implements ResultSetHandler { - private volatile ResultSetHandler inner = null; - private final ResultSetHandlerFactory factory; - - public DelegatingResultSetHandler(ResultSetHandlerFactory factory) { - this.factory = factory; - } - - public E handle(ResultSet resultSet) throws SQLException { - if(inner==null) inner = factory.newResultSetHandler(resultSet.getMetaData()); - return inner.handle(resultSet); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/GenericDatasource.java b/blade-sql2o/src/main/java/org/sql2o/GenericDatasource.java deleted file mode 100644 index db73f8ebb..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/GenericDatasource.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.sql2o; - -import javax.sql.DataSource; -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.util.Properties; - -/** - * Used internally by sql2o, if the {@link Sql2o#Sql2o(String, String, String)} constructor overload. - */ -public class GenericDatasource implements DataSource { - - private final String url; - private final Properties properties; - - public GenericDatasource(String url, String user, String password) { - - if (!url.startsWith("jdbc")){ - url = "jdbc:" + url; - } - - this.url = url; - this.properties = new Properties(); - set(properties,user,password); - } - - private void set(Properties info, String user, String password) { - if (user != null) { - info.put("user", user); - } - if (password != null) { - info.put("password", password); - } - } - - public GenericDatasource(String url, Properties properties) { - - if (!url.startsWith("jdbc")){ - url = "jdbc:" + url; - } - - this.url = url; - this.properties = properties; - } - - public String getUrl() { - return url; - } - - public String getUser() { - return properties.getProperty("user"); - } - - public String getPassword() { - return properties.getProperty("password"); - } - - public Connection getConnection() throws SQLException { - return DriverManager.getConnection(this.getUrl(), properties); - } - - public Connection getConnection(String username, String password) throws SQLException { - Properties info = new Properties(this.properties); - set(info,username,password); - return DriverManager.getConnection(this.getUrl(), info); - } - - public PrintWriter getLogWriter() throws SQLException { - return DriverManager.getLogWriter(); - } - - public void setLogWriter(PrintWriter printWriter) throws SQLException { - DriverManager.setLogWriter(printWriter); - } - - public void setLoginTimeout(int i) throws SQLException { - DriverManager.setLoginTimeout(i); - } - - public int getLoginTimeout() throws SQLException { - return DriverManager.getLoginTimeout(); - } - - public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { - throw new SQLFeatureNotSupportedException(); - } - - public T unwrap(Class tClass) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - public boolean isWrapperFor(Class aClass) throws SQLException { - return false; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java b/blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java deleted file mode 100644 index 4d5671e65..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/JndiDataSource.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.sql2o; - -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; -import javax.sql.DataSource; - -import blade.kit.log.Logger; - -/** - * Created by lars on 16.09.2014. - */ -public class JndiDataSource { - - private final static Logger logger = Logger.getLogger(JndiDataSource.class); - - static DataSource getJndiDatasource(String jndiLookup) { - Context ctx = null; - DataSource datasource = null; - - try { - ctx = new InitialContext(); - datasource = (DataSource) ctx.lookup(jndiLookup); - } - catch (NamingException e) { - throw new RuntimeException(e); - } - finally { - if (ctx != null) { - try { - ctx.close(); - } - catch (Throwable e) { - logger.warn("error closing context", e); - } - } - } - - return datasource; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/PojoResultSetIterator.java b/blade-sql2o/src/main/java/org/sql2o/PojoResultSetIterator.java deleted file mode 100644 index b9bf695ba..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/PojoResultSetIterator.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.sql2o; - -import org.sql2o.quirks.Quirks; - -import java.sql.ResultSet; -import java.sql.SQLException; - -/** - * Iterator for a {@link java.sql.ResultSet}. Tricky part here is getting {@link #hasNext()} - * to work properly, meaning it can be called multiple times without calling {@link #next()}. - * - * @author aldenquimby@gmail.com - */ -public class PojoResultSetIterator extends ResultSetIteratorBase { - private ResultSetHandler handler; - - @SuppressWarnings("unchecked") - public PojoResultSetIterator(ResultSet rs, boolean isCaseSensitive, Quirks quirks, ResultSetHandlerFactory factory) { - super(rs, isCaseSensitive, quirks); - try { - this.handler = factory.newResultSetHandler(rs.getMetaData()); - } catch (SQLException e) { - throw new Sql2oException("Database error: " + e.getMessage(), e); - } - } - - public PojoResultSetIterator(ResultSet rs, boolean isCaseSensitive, Quirks quirks, ResultSetHandler handler) { - super(rs, isCaseSensitive, quirks); - this.handler = handler; - } - - @Override - protected T readNext() throws SQLException { - return handler.handle(rs); - - } - -} diff --git a/blade-sql2o/src/main/java/org/sql2o/Query.java b/blade-sql2o/src/main/java/org/sql2o/Query.java deleted file mode 100644 index a29ea5bd9..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/Query.java +++ /dev/null @@ -1,721 +0,0 @@ -package org.sql2o; - -import static org.sql2o.converters.Convert.throwIfNull; - -import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.sql2o.converters.Converter; -import org.sql2o.converters.ConverterException; -import org.sql2o.data.LazyTable; -import org.sql2o.data.Row; -import org.sql2o.data.Table; -import org.sql2o.data.TableResultSetIterator; -import org.sql2o.quirks.Quirks; -import org.sql2o.reflection.PojoIntrospector; - -import blade.kit.log.Logger; - -/** - * Represents a sql2o statement. With sql2o, all statements are instances of the Query class. - */ -public class Query implements AutoCloseable { - - private final static Logger logger = Logger.getLogger(Query.class); - - private Connection connection; - private Map caseSensitiveColumnMappings; - private Map columnMappings; - private final PreparedStatement statement; - private boolean caseSensitive; - private boolean autoDeriveColumnNames; - private boolean throwOnMappingFailure = true; - private String name; - private boolean returnGeneratedKeys; - private final Map> paramNameToIdxMap; - private final Set addedParameters; - private final String parsedQuery; - - private ResultSetHandlerFactoryBuilder resultSetHandlerFactoryBuilder; - - @Override - public String toString() { - return parsedQuery; - } - - public Query(Connection connection, String queryText, String name, boolean returnGeneratedKeys) { - this.connection = connection; - this.name = name; - this.returnGeneratedKeys = returnGeneratedKeys; - this.setColumnMappings(connection.getSql2o().getDefaultColumnMappings()); - this.caseSensitive = connection.getSql2o().isDefaultCaseSensitive(); - - paramNameToIdxMap = new HashMap>(); - addedParameters = new HashSet(); - - parsedQuery = connection.getSql2o().getQuirks().getSqlParameterParsingStrategy().parseSql(queryText, paramNameToIdxMap); - try { - if (returnGeneratedKeys) { - statement = connection.getJdbcConnection().prepareStatement(parsedQuery, Statement.RETURN_GENERATED_KEYS); - } else { - statement = connection.getJdbcConnection().prepareStatement(parsedQuery); - } - } catch(SQLException ex) { - throw new Sql2oException(String.format("Error preparing statement - %s", ex.getMessage()), ex); - } - connection.registerStatement(statement); - - } - - // ------------------------------------------------ - // ------------- Getter/Setters ------------------- - // ------------------------------------------------ - - public boolean isCaseSensitive() { - return caseSensitive; - } - - public Query setCaseSensitive(boolean caseSensitive) { - this.caseSensitive = caseSensitive; - return this; - } - - public boolean isAutoDeriveColumnNames() { - return autoDeriveColumnNames; - } - - public Query setAutoDeriveColumnNames(boolean autoDeriveColumnNames) { - this.autoDeriveColumnNames = autoDeriveColumnNames; - return this; - } - - public Query throwOnMappingFailure(boolean throwOnMappingFailure) { - this.throwOnMappingFailure = throwOnMappingFailure; - return this; - } - - public boolean isThrowOnMappingFailure() { - return throwOnMappingFailure; - } - - public Connection getConnection(){ - return this.connection; - } - - public String getName() { - return name; - } - - public ResultSetHandlerFactoryBuilder getResultSetHandlerFactoryBuilder() { - if (resultSetHandlerFactoryBuilder == null) { - resultSetHandlerFactoryBuilder = new DefaultResultSetHandlerFactoryBuilder(); - } - return resultSetHandlerFactoryBuilder; - } - - public void setResultSetHandlerFactoryBuilder(ResultSetHandlerFactoryBuilder resultSetHandlerFactoryBuilder) { - this.resultSetHandlerFactoryBuilder = resultSetHandlerFactoryBuilder; - } - - public Map> getParamNameToIdxMap() { - return paramNameToIdxMap; - } - - // ------------------------------------------------ - // ------------- Add Parameters ------------------- - // ------------------------------------------------ - - private void addParameterInternal(String name, ParameterSetter parameterSetter) { - addedParameters.add(name); - for (int paramIdx : this.getParamNameToIdxMap().get(name)) { - try { - parameterSetter.setParameter(paramIdx); - } catch (SQLException e) { - throw new RuntimeException(String.format("Error adding parameter '%s' - %s", name, e.getMessage()), e); - } - } - } - - @SuppressWarnings("unchecked") - private Object convertParameter(Object value) { - if (value == null) { - return null; - } - Converter converter = getQuirks().converterOf(value.getClass()); - if (converter == null) { - // let's try to add parameter AS IS - return value; - } - return converter.toDatabaseParam(value); - } - - public Query addParameter(String name, Class parameterClass, T value){ - //TODO: must cover most of types: BigDecimal,Boolean,SmallInt,Double,Float,byte[] - if(InputStream.class.isAssignableFrom(parameterClass)) - return addParameter(name, (InputStream)value); - if(Integer.class==parameterClass) - return addParameter(name, (Integer)value); - if(Long.class==parameterClass) - return addParameter(name, (Long)value); - if(String.class==parameterClass) - return addParameter(name, (String)value); - if(Timestamp.class==parameterClass) - return addParameter(name, (Timestamp)value); - if(Time.class==parameterClass) - return addParameter(name, (Time)value); - - - final Object convertedValue = convertParameter(value); - - addParameterInternal(name, new ParameterSetter() { - public void setParameter(int paramIdx) throws SQLException { - getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, convertedValue); - } - }); - - return this; - } - - public Query withParams(Object... paramValues){ - int i=0; - for (Object paramValue : paramValues) { - addParameter("p" + (++i), paramValue); - } - return this; - } - - @SuppressWarnings("unchecked") - public Query addParameter(String name, Object value) { - return value == null - ? addParameter(name, Object.class, value) - : addParameter(name, - (Class) value.getClass(), - value); - } - - public Query addParameter(String name, final InputStream value){ - addParameterInternal(name, new ParameterSetter() { - public void setParameter(int paramIdx) throws SQLException { - getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); - } - }); - - return this; - } - - public Query addParameter(String name, final int value){ - addParameterInternal(name, new ParameterSetter() { - public void setParameter(int paramIdx) throws SQLException { - getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); - } - }); - - return this; - } - - public Query addParameter(String name, final Integer value) { - addParameterInternal(name, new ParameterSetter() { - public void setParameter(int paramIdx) throws SQLException { - getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); - } - }); - - return this; - } - - public Query addParameter(String name, final long value){ - addParameterInternal(name, new ParameterSetter() { - public void setParameter(int paramIdx) throws SQLException { - getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); - } - }); - - return this; - } - - public Query addParameter(String name, final Long value){ - addParameterInternal(name, new ParameterSetter() { - public void setParameter(int paramIdx) throws SQLException { - getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); - } - }); - - return this; - } - - public Query addParameter(String name, final String value) { - addParameterInternal(name, new ParameterSetter() { - public void setParameter(int paramIdx) throws SQLException { - getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); - } - }); - - return this; - } - - public Query addParameter(String name, final Timestamp value){ - addParameterInternal(name, new ParameterSetter() { - public void setParameter(int paramIdx) throws SQLException { - getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); - } - }); - - return this; - } - - public Query addParameter(String name, final Time value) { - addParameterInternal(name, new ParameterSetter() { - public void setParameter(int paramIdx) throws SQLException { - getConnection().getSql2o().getQuirks().setParameter(statement, paramIdx, value); - } - }); - - return this; - } - - public Query bind(final Object pojo) { - Class clazz = pojo.getClass(); - Map propertyMap = PojoIntrospector.readableProperties(clazz); - for (PojoIntrospector.ReadableProperty property : propertyMap.values()) { - if (addedParameters.contains( property.name )) continue; - try { - if( this.getParamNameToIdxMap().containsKey(property.name)) { - - @SuppressWarnings("unchecked") - final Class type = (Class) property.type; - this.addParameter(property.name, type, property.get(pojo)); - } - } - catch(IllegalArgumentException ex) { - logger.debug("Ignoring Illegal Arguments", ex); - } - catch(IllegalAccessException ex) { - throw new RuntimeException(ex); - } - catch(InvocationTargetException ex) { - throw new RuntimeException(ex); - } - } - return this; - } - - public void close() { - connection.removeStatement(statement); - try { - this.getQuirks().closeStatement(statement); - } catch (Throwable ex){ - logger.warn("Could not close statement.", ex); - } - } - - // ------------------------------------------------ - // -------------------- Execute ------------------- - // ------------------------------------------------ - - /** - * Iterable {@link java.sql.ResultSet} that wraps {@link PojoResultSetIterator}. - */ - private abstract class ResultSetIterableBase implements ResultSetIterable { - private long start; - private long afterExecQuery; - protected ResultSet rs; - - boolean autoCloseConnection = false; - - public ResultSetIterableBase() { - try { - start = System.currentTimeMillis(); - rs = statement.executeQuery(); - afterExecQuery = System.currentTimeMillis(); - } - catch (SQLException ex) { - throw new Sql2oException("Database error: " + ex.getMessage(), ex); - } - } - - @Override - public void close() { - try { - if (rs != null) { - rs.close(); - - // log the query - long afterClose = System.currentTimeMillis(); - logger.debug("total: %s ms, execution: %s ms, reading and parsing: %s ms; executed [%s]", new Object[]{ - afterClose - start, - afterExecQuery-start, - afterClose - afterExecQuery, - name - }); - - rs = null; - } - } - catch (SQLException ex) { - throw new Sql2oException("Error closing ResultSet.", ex); - } - finally { - if (this.isAutoCloseConnection()){ - connection.close(); - } else { - closeConnectionIfNecessary(); - } - } - } - - @Override - public boolean isAutoCloseConnection() { - return this.autoCloseConnection; - } - - @Override - public void setAutoCloseConnection(boolean autoCloseConnection) { - this.autoCloseConnection = autoCloseConnection; - } - } - - /** - * Read a collection lazily. Generally speaking, this should only be used if you are reading MANY - * results and keeping them all in a Collection would cause memory issues. You MUST call - * {@link org.sql2o.ResultSetIterable#close()} when you are done iterating. - * - * @param returnType type of each row - * @return iterable results - */ - public ResultSetIterable executeAndFetchLazy(final Class returnType) { - final ResultSetHandlerFactory resultSetHandlerFactory = newResultSetHandlerFactory(returnType); - return executeAndFetchLazy(resultSetHandlerFactory); - } - - private ResultSetHandlerFactory newResultSetHandlerFactory(Class returnType) { - final Quirks quirks = getConnection().getSql2o().getQuirks(); - ResultSetHandlerFactoryBuilder builder = getResultSetHandlerFactoryBuilder(); - if(builder==null) builder=new DefaultResultSetHandlerFactoryBuilder(); - builder.setAutoDeriveColumnNames(this.autoDeriveColumnNames); - builder.setCaseSensitive(this.caseSensitive); - builder.setColumnMappings(this.columnMappings); - builder.setQuirks(quirks); - builder.throwOnMappingError(this.throwOnMappingFailure); - return builder.newFactory(returnType); - } - - /** - * Read a collection lazily. Generally speaking, this should only be used if you are reading MANY - * results and keeping them all in a Collection would cause memory issues. You MUST call - * {@link org.sql2o.ResultSetIterable#close()} when you are done iterating. - * - * @param resultSetHandlerFactory factory to provide ResultSetHandler - * @return iterable results - */ - public ResultSetIterable executeAndFetchLazy(final ResultSetHandlerFactory resultSetHandlerFactory) { - final Quirks quirks = getConnection().getSql2o().getQuirks(); - return new ResultSetIterableBase() { - public Iterator iterator() { - return new PojoResultSetIterator(rs, isCaseSensitive(), quirks, resultSetHandlerFactory); - } - }; - } - - /** - * Read a collection lazily. Generally speaking, this should only be used if you are reading MANY - * results and keeping them all in a Collection would cause memory issues. You MUST call - * {@link org.sql2o.ResultSetIterable#close()} when you are done iterating. - * - * @param resultSetHandler ResultSetHandler - * @return iterable results - */ - public ResultSetIterable executeAndFetchLazy(final ResultSetHandler resultSetHandler) { - final ResultSetHandlerFactory factory = newResultSetHandlerFactory(resultSetHandler); - return executeAndFetchLazy(factory); - } - - private static ResultSetHandlerFactory newResultSetHandlerFactory(final ResultSetHandler resultSetHandler) { - return new ResultSetHandlerFactory() { - public ResultSetHandler newResultSetHandler(ResultSetMetaData resultSetMetaData) throws SQLException { - return resultSetHandler; - } - }; - } - - public List executeAndFetch(Class returnType){ - return executeAndFetch(newResultSetHandlerFactory(returnType)); - } - - public List executeAndFetch(ResultSetHandler resultSetHandler){ - return executeAndFetch(newResultSetHandlerFactory(resultSetHandler)); - } - - public List executeAndFetch(ResultSetHandlerFactory factory){ - List list = new ArrayList(); - - // if sql2o moves to java 7 at some point, this could be much cleaner using try-with-resources - ResultSetIterable iterable = null; - try { - iterable = executeAndFetchLazy(factory); - for (T item : iterable) { - list.add(item); - } - } - finally { - if (iterable != null) { - iterable.close(); - } - } - - return list; - } - - public T executeAndFetchFirst(Class returnType){ - return executeAndFetchFirst(newResultSetHandlerFactory(returnType)); - } - - public T executeAndFetchFirst(ResultSetHandler resultSetHandler){ - return executeAndFetchFirst(newResultSetHandlerFactory(resultSetHandler)); - } - - public T executeAndFetchFirst(ResultSetHandlerFactory resultSetHandlerFactory){ - // if sql2o moves to java 7 at some point, this could be much cleaner using try-with-resources - ResultSetIterable iterable = null; - try { - iterable = executeAndFetchLazy(resultSetHandlerFactory); - Iterator iterator = iterable.iterator(); - return iterator.hasNext() ? iterator.next() : null; - } - finally { - if (iterable != null) { - iterable.close(); - } - } - } - - public LazyTable executeAndFetchTableLazy() { - final LazyTable lt = new LazyTable(); - - lt.setRows(new ResultSetIterableBase() { - public Iterator iterator() { - return new TableResultSetIterator(rs, isCaseSensitive(), getConnection().getSql2o().getQuirks(), lt); - } - }); - - return lt; - } - - public Table executeAndFetchTable() { - LazyTable lt = executeAndFetchTableLazy(); - List rows = new ArrayList(); - try { - for (Row item : lt.rows()) { - rows.add(item); - } - } - finally { - lt.close(); - } - // lt==null is always false - return new Table(lt.getName(), rows, lt.columns()); - } - - public Connection executeUpdate(){ - long start = System.currentTimeMillis(); - try{ - this.connection.setResult(statement.executeUpdate()); - this.connection.setKeys(this.returnGeneratedKeys ? statement.getGeneratedKeys() : null); - connection.setCanGetKeys(this.returnGeneratedKeys); - } - catch(SQLException ex){ - this.connection.onException(); - throw new Sql2oException("Error in executeUpdate, " + ex.getMessage(), ex); - } - finally { - closeConnectionIfNecessary(); - } - - long end = System.currentTimeMillis(); - logger.debug("total: %s ms; executed update [%s]", new Object[]{ - end - start, - this.getName() == null ? "No name" : this.getName() - }); - - return this.connection; - } - - public Object executeScalar(){ - long start = System.currentTimeMillis(); - try { - ResultSet rs = this.statement.executeQuery(); - if (rs.next()){ - Object o = getQuirks().getRSVal(rs, 1); - long end = System.currentTimeMillis(); - logger.debug("total: %s ms; executed scalar [%s]", new Object[]{ - end - start, - this.getName() == null ? "No name" : this.getName() - }); - return o; - } - else{ - return null; - } - - } - catch (SQLException e) { - this.connection.onException(); - throw new Sql2oException("Database error occurred while running executeScalar: " + e.getMessage(), e); - } - finally{ - closeConnectionIfNecessary(); - } - - } - - private Quirks getQuirks() { - return this.connection.getSql2o().getQuirks(); - } - - public V executeScalar(Class returnType){ - try { - Converter converter; - //noinspection unchecked - converter = throwIfNull(returnType, getQuirks().converterOf(returnType)); - //noinspection unchecked - return executeScalar(converter); - } catch (ConverterException e) { - throw new Sql2oException("Error occured while converting value from database to type " + returnType, e); - } - } - - public V executeScalar(Converter converter){ - try { - //noinspection unchecked - return converter.convert(executeScalar()); - } catch (ConverterException e) { - throw new Sql2oException("Error occured while converting value from database", e); - } - } - - - - public List executeScalarList(final Class returnType){ - return executeAndFetch(newScalarResultSetHandler(returnType)); - } - - private ResultSetHandler newScalarResultSetHandler(final Class returnType) { - final Quirks quirks = getQuirks(); - try { - final Converter converter = throwIfNull(returnType, quirks.converterOf(returnType)); - return new ResultSetHandler() { - public T handle(ResultSet resultSet) throws SQLException { - Object value = quirks.getRSVal(resultSet, 1); - try { - return (converter.convert(value)); - } catch (ConverterException e) { - throw new Sql2oException("Error occurred while converting value from database to type " + returnType, e); - } - } - }; - } catch (ConverterException e) { - throw new Sql2oException("Can't get converter for type " + returnType, e); - } - } - - /************** batch stuff *******************/ - - public Query addToBatch(){ - try { - statement.addBatch(); - } catch (SQLException e) { - throw new Sql2oException("Error while adding statement to batch", e); - } - - return this; - } - - public Connection executeBatch() throws Sql2oException { - long start = System.currentTimeMillis(); - try { - connection.setBatchResult(statement.executeBatch()); - try { - connection.setKeys(this.returnGeneratedKeys ? statement.getGeneratedKeys() : null); - connection.setCanGetKeys(this.returnGeneratedKeys); - } catch (SQLException sqlex) { - throw new Sql2oException("Error while trying to fetch generated keys from database. If you are not expecting any generated keys, fix this error by setting the fetchGeneratedKeys parameter in the createQuery() method to 'false'", sqlex); - } - } - catch (Throwable e) { - this.connection.onException(); - throw new Sql2oException("Error while executing batch operation: " + e.getMessage(), e); - } - finally { - closeConnectionIfNecessary(); - } - - long end = System.currentTimeMillis(); - logger.debug("total: %s ms; executed batch [%s]", new Object[]{ - end - start, - this.getName() == null ? "No name" : this.getName() - }); - - return this.connection; - } - - /*********** column mapping ****************/ - - public Map getColumnMappings() { - if (this.isCaseSensitive()){ - return this.caseSensitiveColumnMappings; - } - else{ - return this.columnMappings; - } - } - - public Query setColumnMappings(Map mappings){ - - this.caseSensitiveColumnMappings = new HashMap(); - this.columnMappings = new HashMap(); - - for (Map.Entry entry : mappings.entrySet()){ - this.caseSensitiveColumnMappings.put(entry.getKey(), entry.getValue()); - this.columnMappings.put(entry.getKey().toLowerCase(), entry.getValue().toLowerCase()); - } - - return this; - } - - public Query addColumnMapping(String columnName, String propertyName){ - this.caseSensitiveColumnMappings.put(columnName, propertyName); - this.columnMappings.put(columnName.toLowerCase(), propertyName.toLowerCase()); - - return this; - } - - /************** private stuff ***************/ - - private void closeConnectionIfNecessary(){ - try{ - if (connection.autoClose){ - connection.close(); - } - } - catch (Exception ex){ - throw new Sql2oException("Error while attempting to close connection", ex); - } - } - - private interface ParameterSetter{ - void setParameter(int paramIdx) throws SQLException; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/ResultSetHandler.java b/blade-sql2o/src/main/java/org/sql2o/ResultSetHandler.java deleted file mode 100644 index 1e6d3fd5e..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/ResultSetHandler.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.sql2o; - -import java.sql.ResultSet; -import java.sql.SQLException; - -/** - * User: dimzon - * Date: 4/7/14 - * Time: 12:01 AM - */ -public interface ResultSetHandler { - T handle(ResultSet resultSet) throws SQLException; -} diff --git a/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactory.java b/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactory.java deleted file mode 100644 index 7620551f0..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactory.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.sql2o; - -import java.sql.ResultSetMetaData; -import java.sql.SQLException; - -/** - * User: dimzon - * Date: 4/7/14 - * Time: 12:02 AM - */ -public interface ResultSetHandlerFactory { - ResultSetHandler newResultSetHandler(ResultSetMetaData resultSetMetaData) throws SQLException; -} diff --git a/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactoryBuilder.java b/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactoryBuilder.java deleted file mode 100644 index 9d07ad545..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/ResultSetHandlerFactoryBuilder.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.sql2o; - -import org.sql2o.quirks.Quirks; - -import java.util.Map; - -/** - * Created with IntelliJ IDEA. - * User: dimzon - * Date: 4/7/14 - * Time: 4:28 AM - * To change this template use File | Settings | File Templates. - */ -public interface ResultSetHandlerFactoryBuilder { - boolean isCaseSensitive(); - - void setCaseSensitive(boolean caseSensitive); - - boolean isAutoDeriveColumnNames(); - - void setAutoDeriveColumnNames(boolean autoDeriveColumnNames); - - boolean isThrowOnMappingError(); - - void throwOnMappingError(boolean throwOnMappingError); - - Map getColumnMappings(); - - void setColumnMappings(Map columnMappings); - - Quirks getQuirks(); - - void setQuirks(Quirks quirksMode); - - ResultSetHandlerFactory newFactory(Class clazz); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/ResultSetIterable.java b/blade-sql2o/src/main/java/org/sql2o/ResultSetIterable.java deleted file mode 100644 index 4be7b76bd..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/ResultSetIterable.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.sql2o; - -/** - * Iterable {@link java.sql.ResultSet}. Needs to be closeable, because allowing manual - * iteration means it's impossible to know when to close the ResultSet and Connection. - * - * @author aldenquimby@gmail.com - */ -public interface ResultSetIterable extends Iterable, AutoCloseable { - // override close to not throw - void close(); - - boolean isAutoCloseConnection(); - void setAutoCloseConnection(boolean autoCloseConnection); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/ResultSetIteratorBase.java b/blade-sql2o/src/main/java/org/sql2o/ResultSetIteratorBase.java deleted file mode 100644 index 0d1c1d156..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/ResultSetIteratorBase.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.sql2o; - -import org.sql2o.quirks.Quirks; - -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Iterator for a {@link java.sql.ResultSet}. Tricky part here is getting {@link #hasNext()} - * to work properly, meaning it can be called multiple times without calling {@link #next()}. - * - * @author aldenquimby@gmail.com - */ -public abstract class ResultSetIteratorBase implements Iterator { - // fields needed to read result set - protected ResultSet rs; - protected boolean isCaseSensitive; - protected Quirks quirks; - protected ResultSetMetaData meta; - - public ResultSetIteratorBase(ResultSet rs, boolean isCaseSensitive, Quirks quirks) { - this.rs = rs; - this.isCaseSensitive = isCaseSensitive; - this.quirks = quirks; - try { - meta = rs.getMetaData(); - } - catch(SQLException ex) { - throw new Sql2oException("Database error: " + ex.getMessage(), ex); - } - } - - // fields needed to properly implement - private ResultSetValue next; // keep track of next item in case hasNext() is called multiple times - private boolean resultSetFinished; // used to note when result set exhausted - - public boolean hasNext() { - // check if we already fetched next item - if (next != null) { - return true; - } - - // check if result set already finished - if (resultSetFinished) { - return false; - } - - // now fetch next item - next = safeReadNext(); - - // check if we got something - if (next != null) { - return true; - } - - // no more items - resultSetFinished = true; - - return false; - } - - public T next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - T result = next.value; - - next = null; - - return result; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - private ResultSetValue safeReadNext() - { - try { - if (!rs.next()) - return null; - - return new ResultSetValue(readNext()); - } - catch (SQLException ex) { - throw new Sql2oException("Database error: " + ex.getMessage(), ex); - } - } - - protected abstract T readNext() throws SQLException; - - protected String getColumnName(int colIdx) throws SQLException { - return quirks.getColumnName(meta, colIdx); - } - - private final class ResultSetValue { - public final T value; - - public ResultSetValue(T value){ - this.value = value; - } - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/Sql2o.java b/blade-sql2o/src/main/java/org/sql2o/Sql2o.java deleted file mode 100644 index e9747e179..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/Sql2o.java +++ /dev/null @@ -1,378 +0,0 @@ -package org.sql2o; - -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; - -import javax.sql.ConnectionPoolDataSource; -import javax.sql.DataSource; - -import org.sql2o.quirks.Quirks; -import org.sql2o.quirks.QuirksDetector; - -import blade.plugin.sql2o.pool.ConnectionPool; - -/** - * Sql2o is the main class for the sql2o library. - *

- * An Sql2o instance represents a way of connecting to one specific database. - * To create a new instance, one need to specify either jdbc-url, username and password for the database or a data source. - *

- * Internally the Sql2o instance uses a data source to create jdbc connections to the database. If url, username and password - * was specified in the constructor, a simple data source is created, which works as a simple wrapper around the jdbc - * driver. - *

- * Some jdbc implementations have quirks, therefore it may be necessary to use a constructor with the quirks parameter. - * When quirks are specified, Sql2o will use workarounds to avoid these quirks. - * @author Lars Aaberg - */ -public class Sql2o { - final Quirks quirks; - private final DataSource dataSource; - private final ConnectionPool connectionPool; - private Map defaultColumnMappings; - private boolean defaultCaseSensitive; - - public Sql2o(String jndiLookup) { - this(JndiDataSource.getJndiDatasource(jndiLookup)); - } - - /** - * Creates a new instance of the Sql2o class. Internally this constructor will create a {@link GenericDatasource}, - * and call the {@link Sql2o#Sql2o(javax.sql.DataSource)} constructor which takes a DataSource as parameter. - * @param url JDBC database url - * @param user database username - * @param pass database password - */ - public Sql2o(String url, String user, String pass){ - this(url, user, pass, QuirksDetector.forURL(url)); - } - - /** - * Created a new instance of the Sql2o class. Internally this constructor will create a {@link GenericDatasource}, - * and call the {@link Sql2o#Sql2o(javax.sql.DataSource)} constructor which takes a DataSource as parameter. - * @param url JDBC database url - * @param user database username - * @param pass database password - * @param quirks {@link org.sql2o.quirks.Quirks} allows sql2o to work around known quirks and issues in different JDBC drivers. - */ - public Sql2o(String url, String user, String pass, Quirks quirks) { - this(new GenericDatasource(url, user, pass), quirks); - } - - /** - * Creates a new instance of the Sql2o class, which uses the given DataSource to acquire connections to the database. - * @param dataSource The DataSource Sql2o uses to acquire connections to the database. - */ - public Sql2o(DataSource dataSource) { - this(dataSource, QuirksDetector.forObject(dataSource)); - } - - /** - * Creates a new instance of the Sql2o class, which uses the given DataSource to acquire connections to the database. - * @param dataSource The DataSource Sql2o uses to acquire connections to the database. - * @param quirks {@link org.sql2o.quirks.Quirks} allows sql2o to work around known quirks and issues in different JDBC drivers. - */ - public Sql2o(DataSource dataSource, Quirks quirks){ - this.dataSource = dataSource; - this.quirks=quirks; - this.defaultColumnMappings = new HashMap(); - this.connectionPool = null; - } - - /** - * extended by sean - * Creates a new instance of the Sql2o class, which uses the given ConnectionPoolDataSource to acquire connections to the database. - * @param poolDataSource The DataSource Sql2o uses to acquire connections to the database. - */ - public Sql2o(ConnectionPoolDataSource poolDataSource) { - this(poolDataSource, null); - } - - /** - * * extended by sean - * Creates a new instance of the Sql2o class, which uses the given ConnectionPoolDataSource to acquire connections to the database. - * @param poolDataSource The DataSource Sql2o uses to acquire connections to the database. - * @param quirksMode @{link QuirksMode} allows sql2o to work around known quirks and issues in different JDBC drivers. - */ - public Sql2o(ConnectionPoolDataSource poolDataSource, Quirks quirks){ - this(null, poolDataSource, quirks); - } - - /** - * extended by sean - * Add ConnectionPoolDataSource, get connection from pool. - * @param dataSource - * @param poolDataSource - * @param quirksMode - */ - private Sql2o(DataSource dataSource, ConnectionPoolDataSource poolDataSource, Quirks quirks) { - this.dataSource = dataSource; - this.quirks = quirks; - this.connectionPool = null; - this.defaultColumnMappings = new HashMap(); - } - - /** - * extended by sean - * Add ConnectionPoolDataSource, get connection from pool. - * @param dataSource - * @param poolDataSource - * @param quirksMode - */ - public Sql2o(ConnectionPool connectionPool) { - this(connectionPool, QuirksDetector.forObject(connectionPool)); - } - - /** - * extended by sean - * Add ConnectionPoolDataSource, get connection from pool. - * @param dataSource - * @param poolDataSource - * @param quirksMode - */ - public Sql2o(ConnectionPool connectionPool, Quirks quirks) { - this.connectionPool = connectionPool; - this.quirks = quirks; - this.dataSource = null; - this.defaultColumnMappings = new HashMap(); - } - - public Quirks getQuirks() { - return quirks; - } - - /** - * Gets the DataSource that Sql2o uses internally to acquire database connections. - * @return The DataSource instance - */ - public DataSource getDataSource() { - return dataSource; - } - - /** - * 返回连接池 - * @return - */ - public ConnectionPool getConnectionPool() { - return connectionPool; - } - - /** - * Gets the default column mappings Map. column mappings added to this Map are always available when Sql2o attempts - * to map between result sets and object instances. - * @return The {@link Map} instance, which Sql2o internally uses to map column names with property - * names. - */ - public Map getDefaultColumnMappings() { - return defaultColumnMappings; - } - - /** - * Sets the default column mappings Map. - * @param defaultColumnMappings A {@link Map} instance Sql2o uses internally to map between column names and - * property names. - */ - public void setDefaultColumnMappings(Map defaultColumnMappings) { - this.defaultColumnMappings = defaultColumnMappings; - } - - /** - * Gets value indicating if this instance of Sql2o is case sensitive when mapping between columns names and property - * names. - * @return - */ - public boolean isDefaultCaseSensitive() { - return defaultCaseSensitive; - } - - /** - * Sets a value indicating if this instance of Sql2o is case sensitive when mapping between columns names and property - * names. This should almost always be false, because most relational databases are not case sensitive. - * @param defaultCaseSensitive - */ - public void setDefaultCaseSensitive(boolean defaultCaseSensitive) { - this.defaultCaseSensitive = defaultCaseSensitive; - } - - /** - * Opens a connection to the database - * @return instance of the {@link org.sql2o.Connection} class. - */ - public Connection open() { - return new Connection(this, false); - } - - /** - * Invokes the run method on the {@link org.sql2o.StatementRunnableWithResult} instance. This method guarantees that - * the connection is closed properly, when either the run method completes or if an exception occurs. - * @param runnable - * @param argument - * @param - * @return - */ - @SuppressWarnings("unchecked") - public V withConnection(StatementRunnableWithResult runnable, Object argument) { - Connection connection = null; - try{ - connection = open(); - return (V)runnable.run(connection, argument); - } catch (Throwable t) { - throw new Sql2oException("An error occurred while executing StatementRunnable", t); - } finally { - if (connection != null) { - connection.close(); - } - } - } - - /** - * Invokes the run method on the {@link org.sql2o.StatementRunnableWithResult} instance. This method guarantees that - * the connection is closed properly, when either the run method completes or if an exception occurs. - * @param runnable - * @param - * @return - */ - public V withConnection(StatementRunnableWithResult runnable) { - return withConnection(runnable, null); - } - - /** - * Invokes the run method on the {@link org.sql2o.StatementRunnableWithResult} instance. This method guarantees that - * the connection is closed properly, when either the run method completes or if an exception occurs. - * @param runnable - */ - public void withConnection(StatementRunnable runnable) { - withConnection(runnable, null); - } - - /** - * Invokes the run method on the {@link org.sql2o.StatementRunnableWithResult} instance. This method guarantees that - * the connection is closed properly, when either the run method completes or if an exception occurs. - * @param runnable - * @param argument - */ - public void withConnection(StatementRunnable runnable, Object argument) { - Connection connection = null; - try{ - connection = open(); - - runnable.run(connection, argument); - } catch (Throwable t) { - throw new Sql2oException("An error occurred while executing StatementRunnable", t); - } finally{ - if (connection != null) { - connection.close(); - } - } - } - - /** - * Begins a transaction with the given isolation level. Every statement executed on the return {@link Connection} - * instance, will be executed in the transaction. It is very important to always call either the {@link org.sql2o.Connection#commit()} - * method or the {@link org.sql2o.Connection#rollback()} method to close the transaction. Use proper try-catch logic. - * @param isolationLevel the isolation level of the transaction - * @return the {@link Connection} instance to use to run statements in the transaction. - */ - public Connection beginTransaction(int isolationLevel){ - - Connection connection = new Connection(this, false); - - try { - connection.getJdbcConnection().setAutoCommit(false); - connection.getJdbcConnection().setTransactionIsolation(isolationLevel); - } catch (SQLException e) { - throw new RuntimeException(e); - } - - return connection; - } - - /** - * Begins a transaction with isolation level {@link java.sql.Connection#TRANSACTION_READ_COMMITTED}. Every statement executed on the return {@link Connection} - * instance, will be executed in the transaction. It is very important to always call either the {@link org.sql2o.Connection#commit()} - * method or the {@link org.sql2o.Connection#rollback()} method to close the transaction. Use proper try-catch logic. - * @return the {@link Connection} instance to use to run statements in the transaction. - */ - public Connection beginTransaction(){ - return this.beginTransaction(java.sql.Connection.TRANSACTION_READ_COMMITTED); - } - - /** - * Calls the {@link StatementRunnable#run(Connection, Object)} method on the {@link StatementRunnable} parameter. All statements - * run on the {@link Connection} instance in the {@link StatementRunnable#run(Connection, Object) run} method will be - * executed in a transaction. The transaction will automatically be committed if the {@link StatementRunnable#run(Connection, Object) run} - * method finishes without throwing an exception. If an exception is thrown within the {@link StatementRunnable#run(Connection, Object) run} method, - * the transaction will automatically be rolled back. - * - * The isolation level of the transaction will be set to {@link java.sql.Connection#TRANSACTION_READ_COMMITTED} - * @param runnable The {@link StatementRunnable} instance. - */ - public void runInTransaction(StatementRunnable runnable){ - runInTransaction(runnable, null); - } - - /** - * Calls the {@link StatementRunnable#run(Connection, Object)} method on the {@link StatementRunnable} parameter. All statements - * run on the {@link Connection} instance in the {@link StatementRunnable#run(Connection, Object) run} method will be - * executed in a transaction. The transaction will automatically be committed if the {@link StatementRunnable#run(Connection, Object) run} - * method finishes without throwing an exception. If an exception is thrown within the {@link StatementRunnable#run(Connection, Object) run} method, - * the transaction will automatically be rolled back. - * - * The isolation level of the transaction will be set to {@link java.sql.Connection#TRANSACTION_READ_COMMITTED} - * @param runnable The {@link StatementRunnable} instance. - * @param argument An argument which will be forwarded to the {@link StatementRunnable#run(Connection, Object) run} method - */ - public void runInTransaction(StatementRunnable runnable, Object argument){ - runInTransaction(runnable, argument, java.sql.Connection.TRANSACTION_READ_COMMITTED); - } - - /** - * Calls the {@link StatementRunnable#run(Connection, Object)} method on the {@link StatementRunnable} parameter. All statements - * run on the {@link Connection} instance in the {@link StatementRunnable#run(Connection, Object) run} method will be - * executed in a transaction. The transaction will automatically be committed if the {@link StatementRunnable#run(Connection, Object) run} - * method finishes without throwing an exception. If an exception is thrown within the {@link StatementRunnable#run(Connection, Object) run} method, - * the transaction will automatically be rolled back. - * @param runnable The {@link StatementRunnable} instance. - * @param argument An argument which will be forwarded to the {@link StatementRunnable#run(Connection, Object) run} method - * @param isolationLevel The isolation level of the transaction - */ - public void runInTransaction(StatementRunnable runnable, Object argument, int isolationLevel){ - - Connection connection = this.beginTransaction(isolationLevel); - connection.setRollbackOnException(false); - - try { - runnable.run(connection, argument); - } catch (Throwable throwable) { - connection.rollback(); - throw new Sql2oException("An error occurred while executing StatementRunnable. Transaction is rolled back.", throwable); - } - connection.commit(); - } - - public V runInTransaction(StatementRunnableWithResult runnableWithResult){ - return runInTransaction(runnableWithResult, null); - } - - public V runInTransaction(StatementRunnableWithResult runnableWithResult, Object argument){ - return runInTransaction(runnableWithResult, argument, java.sql.Connection.TRANSACTION_READ_COMMITTED); - } - - @SuppressWarnings("unchecked") - public V runInTransaction(StatementRunnableWithResult runnableWithResult, Object argument, int isolationLevel){ - Connection connection = this.beginTransaction(isolationLevel); - Object result; - - try{ - result = runnableWithResult.run(connection, argument); - } catch (Throwable throwable) { - connection.rollback(); - throw new Sql2oException("An error occurred while executing StatementRunnableWithResult. Transaction rolled back.", throwable); - } - - connection.commit(); - return (V)result; - } - -} diff --git a/blade-sql2o/src/main/java/org/sql2o/Sql2oException.java b/blade-sql2o/src/main/java/org/sql2o/Sql2oException.java deleted file mode 100644 index 643fe64d3..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/Sql2oException.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.sql2o; - -/** - * Represents an exception thrown by Sql2o. - */ -public class Sql2oException extends RuntimeException { - - public Sql2oException() { - } - - public Sql2oException(String message) { - super(message); - } - - public Sql2oException(String message, Throwable cause) { - super(message, cause); - } - - public Sql2oException(Throwable cause) { - super(cause); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/StatementRunnable.java b/blade-sql2o/src/main/java/org/sql2o/StatementRunnable.java deleted file mode 100644 index 83665e38c..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/StatementRunnable.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.sql2o; - -/** - * Represents a method with a {@link Connection} and an optional argument. Implementations of this interface be used as - * a parameter to one of the {@link Sql2o#runInTransaction(StatementRunnable) Sql2o.runInTransaction} overloads, to run - * code safely in a transaction. - */ -public interface StatementRunnable { - - void run(Connection connection, Object argument) throws Throwable; -} diff --git a/blade-sql2o/src/main/java/org/sql2o/StatementRunnableWithResult.java b/blade-sql2o/src/main/java/org/sql2o/StatementRunnableWithResult.java deleted file mode 100644 index 9997f42d3..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/StatementRunnableWithResult.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.sql2o; - -/** - * Represents a method with a {@link Connection} and an optional argument. Implementations of this interface be used as - * a parameter to one of the {@link Sql2o#runInTransaction(StatementRunnableWithResult)} Sql2o.runInTransaction} overloads, - * to run code safely in a transaction. - */ -public interface StatementRunnableWithResult { - - Object run(Connection connection, Object argument) throws Throwable; -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/AbstractDateConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/AbstractDateConverter.java deleted file mode 100644 index 04922438e..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/AbstractDateConverter.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.sql2o.converters; - -import java.sql.Timestamp; -import java.util.Date; - -/** - * Used by sql2o to convert a value from the database into a {@link Date}. - */ -public abstract class AbstractDateConverter implements Converter { - private final Class classOfDate; - protected AbstractDateConverter(Class classOfDate) { - this.classOfDate = classOfDate; - } - - protected abstract E fromMilliseconds(long millisecond); - - @SuppressWarnings("unchecked") - public E convert(Object val) throws ConverterException { - if (val == null){ - return null; - } - - if (classOfDate.isInstance(val)){ - return (E) val; - } - - if(val instanceof java.util.Date){ - return fromMilliseconds(((Date) val).getTime()); - } - - if (val instanceof Number){ - return fromMilliseconds(((Number) val).longValue()); - } - - throw new ConverterException("Cannot convert type " + val.getClass().toString() + " to java.util.Date"); - } - - public Timestamp toDatabaseParam(Date val) { - if(val==null) return null; - return (val instanceof Timestamp) - ? (Timestamp) val - :new Timestamp(val.getTime()); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/BigDecimalConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/BigDecimalConverter.java deleted file mode 100644 index 7dd2a464a..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/BigDecimalConverter.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.sql2o.converters; - -import java.math.BigDecimal; - -/** - * Used by sql2o to convert a value from the database into a {@link BigDecimal}. - */ -public class BigDecimalConverter extends NumberConverter{ - - public BigDecimalConverter() { - super(false); - } - - @Override - protected BigDecimal convertNumberValue(Number val) { - if (val instanceof BigDecimal){ - return (BigDecimal)val; - } - else{ - return BigDecimal.valueOf(val.doubleValue()); - } - } - - @Override - protected BigDecimal convertStringValue(String val) { - return BigDecimal.valueOf(Double.parseDouble(val)); - } - - @Override - protected String getTypeDescription() { - return BigDecimal.class.toString(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/BooleanConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/BooleanConverter.java deleted file mode 100644 index dd8116e97..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/BooleanConverter.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.sql2o.converters; - -/** - * Created with IntelliJ IDEA. - * User: lars - * Date: 6/1/13 - * Time: 10:54 PM - * To change this template use File | Settings | File Templates. - */ -public class BooleanConverter extends ConverterBase { - - public Boolean convert(Object val) throws ConverterException { - if (val == null) return null; - - if (val instanceof Boolean) { - return (Boolean) val; - } - - if (val instanceof Number) { - return ((Number)val).intValue() != 0; - } - - if (val instanceof Character) { - // cast to char is required to compile with java 8 - char c = (Character) val; - return c == 'Y' || c == 'T' || c == 'J'; - } - - if (val instanceof String) { - String strVal = ((String)val).trim(); - return "Y".equalsIgnoreCase(strVal) || "YES".equalsIgnoreCase(strVal) || "TRUE".equalsIgnoreCase(strVal) || - "T".equalsIgnoreCase(strVal) || "J".equalsIgnoreCase(strVal); - } - - throw new ConverterException("Don't know how to convert type " + val.getClass().getName() + " to " + Boolean.class.getName()); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java deleted file mode 100644 index 6270ca5e5..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/ByteArrayConverter.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.sql2o.converters; - -import java.io.IOException; -import java.io.InputStream; -import java.sql.Blob; -import java.sql.SQLException; - -import blade.kit.IOKit; - -/** - * User: lars - * Date: 6/13/13 - * Time: 11:36 PM - */ -public class ByteArrayConverter extends ConverterBase { - - public byte[] convert(Object val) throws ConverterException { - if (val == null) return null; - - if (val instanceof Blob) { - Blob b = (Blob)val; - InputStream stream=null; - try { - try { - stream = b.getBinaryStream(); - return IOKit.toByteArray(stream); - } finally { - if(stream!=null) { - try { - stream.close(); - } catch (Throwable ignore){ - // ignore stream.close errors - } - } - try { - b.free(); - } catch (Throwable ignore){ - // ignore blob.free errors - } - } - } catch (SQLException e) { - throw new ConverterException("Error converting Blob to byte[]", e); - } catch (IOException e) { - throw new ConverterException("Error converting Blob to byte[]", e); - } - } - - if (val instanceof byte[]){ - return (byte[])val; - } - - throw new RuntimeException("could not convert " + val.getClass().getName() + " to byte[]"); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ByteConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/ByteConverter.java deleted file mode 100644 index 7b32677dc..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/ByteConverter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.sql2o.converters; - -/** - * Used by sql2o to convert a value from the database into a {@link Byte}. - */ -public class ByteConverter extends NumberConverter { - - public ByteConverter(boolean primitive) { - super(primitive); - } - - @Override - protected Byte convertNumberValue(Number val) { - return val.byteValue(); - } - - @Override - protected Byte convertStringValue(String val) { - return Byte.parseByte(val); - } - - @Override - protected String getTypeDescription() { - return Byte.class.toString(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/Convert.java b/blade-sql2o/src/main/java/org/sql2o/converters/Convert.java deleted file mode 100644 index 13544f775..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/Convert.java +++ /dev/null @@ -1,158 +0,0 @@ -package org.sql2o.converters; - -import org.joda.time.DateTime; -import org.joda.time.LocalTime; -import org.sql2o.converters.joda.DateTimeConverter; -import org.sql2o.converters.joda.LocalTimeConverter; -import org.sql2o.tools.FeatureDetector; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.math.BigDecimal; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.HashMap; -import java.util.Map; -import java.util.ServiceLoader; -import java.util.UUID; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * Static class used to register new converters. - * Also used internally by sql2o to lookup a converter. - */ -@SuppressWarnings("unchecked") -public class Convert { - - private static final ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock(); - private static final ReentrantReadWriteLock.ReadLock rl = rrwl.readLock(); - private static volatile EnumConverterFactory registeredEnumConverterFactory = new DefaultEnumConverterFactory(); - private static Map, Converter> registeredConverters = new HashMap, Converter>(); - - private static void processProvider(ConvertersProvider convertersProvider) { - convertersProvider.fill(registeredConverters); - } - - private static void fillDefaults(Map, Converter> mapToFill) { - mapToFill.put(Integer.class, new IntegerConverter(false)); - mapToFill.put(int.class, new IntegerConverter(true)); - - mapToFill.put(Double.class, new DoubleConverter(false)); - mapToFill.put(double.class, new DoubleConverter(true)); - - mapToFill.put(Float.class, new FloatConverter(false)); - mapToFill.put(float.class, new FloatConverter(true)); - - mapToFill.put(Long.class, new LongConverter(false)); - mapToFill.put(long.class, new LongConverter(true)); - - mapToFill.put(Short.class, new ShortConverter(false)); - mapToFill.put(short.class, new ShortConverter(true)); - - mapToFill.put(Byte.class, new ByteConverter(false)); - mapToFill.put(byte.class, new ByteConverter(true)); - - mapToFill.put(BigDecimal.class, new BigDecimalConverter()); - - mapToFill.put(String.class, new StringConverter()); - - mapToFill.put(java.util.Date.class,DateConverter.instance); - mapToFill.put(java.sql.Date.class, - new AbstractDateConverter(java.sql.Date.class) { - @Override - protected java.sql.Date fromMilliseconds(long millisecond) { - return new java.sql.Date(millisecond); - } - - @Override - public Object toDatabaseParam(Date val) { - return null; - } - }); - mapToFill.put(java.sql.Time.class, - new AbstractDateConverter(java.sql.Time.class) { - @Override - protected java.sql.Time fromMilliseconds(long millisecond) { - return new java.sql.Time(millisecond); - } - - @Override - public Object toDatabaseParam(Time val) { - return null; - } - }); - mapToFill.put(java.sql.Timestamp.class, - new AbstractDateConverter(java.sql.Timestamp.class) { - @Override - protected java.sql.Timestamp fromMilliseconds(long millisecond) { - return new java.sql.Timestamp(millisecond); - } - - @Override - public Object toDatabaseParam(Timestamp val) { - return null; - } - }); - - BooleanConverter booleanConverter = new BooleanConverter(); - mapToFill.put(Boolean.class, booleanConverter); - mapToFill.put(boolean.class, booleanConverter); - - ByteArrayConverter byteArrayConverter = new ByteArrayConverter(); - //it's impossible to cast Byte[].class <-> byte[].class - // and I'm too lazy to implement converter for Byte[].class - // since it's really doesn't wide-used - // otherwise someone already detect this error - //mapToFill.put(Byte[].class, byteArrayConverter); - mapToFill.put(byte[].class, byteArrayConverter); - - InputStreamConverter inputStreamConverter = new InputStreamConverter(); - mapToFill.put(InputStream.class, inputStreamConverter); - mapToFill.put(ByteArrayInputStream.class, inputStreamConverter); - - mapToFill.put(UUID.class, new UUIDConverter()); - - if (FeatureDetector.isJodaTimeAvailable()) { - mapToFill.put(DateTime.class, new DateTimeConverter()); - mapToFill.put(LocalTime.class, new LocalTimeConverter()); - } - } - - - static { - fillDefaults(registeredConverters); - ServiceLoader loader = ServiceLoader.load(ConvertersProvider.class); - for (ConvertersProvider provider : loader) { - processProvider(provider); - } - } - - public static Converter throwIfNull(Class clazz, Converter converter) throws ConverterException { - if (converter == null) { - throw new ConverterException("No converter registered for class: " + clazz.getName()); - } - return converter; - } - - public static Converter getConverterIfExists(Class clazz) { - Converter c; - rl.lock(); - try { - c = registeredConverters.get(clazz); - } finally { - rl.unlock(); - } - if (c != null) return c; - - if (clazz.isEnum()) { - return registeredEnumConverterFactory.newConverter((Class) clazz); - } - return null; - } - - public static void registerEnumConverter(EnumConverterFactory enumConverterFactory) { - if (enumConverterFactory == null) throw new IllegalArgumentException(); - registeredEnumConverterFactory = enumConverterFactory; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/Converter.java b/blade-sql2o/src/main/java/org/sql2o/converters/Converter.java deleted file mode 100644 index fb05a9ab6..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/Converter.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.sql2o.converters; - -/** - * Represents a converter. - */ -public interface Converter { - - /** - * Conversion from SQL to Java. - */ - T convert(Object val) throws ConverterException; - - /** - * Conversion from Java to SQL. - */ - Object toDatabaseParam(T val); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ConverterBase.java b/blade-sql2o/src/main/java/org/sql2o/converters/ConverterBase.java deleted file mode 100644 index 91443dccb..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/ConverterBase.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.sql2o.converters; - -/** - * @author aldenquimby@gmail.com - * @since 4/6/14 - */ -abstract class ConverterBase implements Converter { - - public Object toDatabaseParam(T val) { - return val; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ConverterException.java b/blade-sql2o/src/main/java/org/sql2o/converters/ConverterException.java deleted file mode 100644 index 8cfceb864..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/ConverterException.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.sql2o.converters; - -/** - * Represents an exception thrown from a converter. - */ -public class ConverterException extends Exception{ - - public ConverterException(String message) { - super(message); - } - - public ConverterException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ConvertersProvider.java b/blade-sql2o/src/main/java/org/sql2o/converters/ConvertersProvider.java deleted file mode 100644 index e21213fb9..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/ConvertersProvider.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.sql2o.converters; - -import org.sql2o.Sql2oException; - -import java.util.Map; - -/** - * User: dimzon - * Date: 4/24/14 - * Time: 12:53 AM - */ -public interface ConvertersProvider { - void fill(Map,Converter> mapToFill); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/DateConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/DateConverter.java deleted file mode 100644 index 9a8d773f6..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/DateConverter.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.sql2o.converters; - -import java.util.Date; - -/** - * Used by sql2o to convert a value from the database into a {@link Date}. - */ -public class DateConverter extends AbstractDateConverter { - public static final DateConverter instance = new DateConverter(); - - public DateConverter() { - super(Date.class); - } - - @Override - protected Date fromMilliseconds(long millisecond) { - return new Date(millisecond); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/DefaultEnumConverterFactory.java b/blade-sql2o/src/main/java/org/sql2o/converters/DefaultEnumConverterFactory.java deleted file mode 100644 index 34b426a39..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/DefaultEnumConverterFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.sql2o.converters; - -/** - * Default implementation of {@link EnumConverterFactory}, - * used by sql2o to convert a value from the database into an {@link Enum}. - */ -public class DefaultEnumConverterFactory implements EnumConverterFactory { - public Converter newConverter(final Class enumType) { - return new Converter() { - @SuppressWarnings("unchecked") - public E convert(Object val) throws ConverterException { - if (val == null) { - return null; - } - try { - if (val instanceof String){ - return (E)Enum.valueOf(enumType, val.toString()); - } else if (val instanceof Number){ - return enumType.getEnumConstants()[((Number)val).intValue()]; - } - } catch (Throwable t) { - throw new ConverterException("Error converting value '" + val.toString() + "' to " + enumType.getName(), t); - } - throw new ConverterException("Cannot convert type '" + val.getClass().getName() + "' to an Enum"); - } - - public Object toDatabaseParam(Enum val) { - return val.toString(); - } - }; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/DoubleConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/DoubleConverter.java deleted file mode 100644 index 5a3688577..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/DoubleConverter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.sql2o.converters; - -/** - * Used by sql2o to convert a value from the database into a {@link Double}. - */ -public class DoubleConverter extends NumberConverter { - - public DoubleConverter(boolean primitive) { - super(primitive); - } - - @Override - protected Double convertNumberValue(Number val) { - return val.doubleValue(); - } - - @Override - protected Double convertStringValue(String val) { - return Double.parseDouble(val); - } - - @Override - protected String getTypeDescription() { - return Double.class.toString(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/EnumConverterFactory.java b/blade-sql2o/src/main/java/org/sql2o/converters/EnumConverterFactory.java deleted file mode 100644 index 76da53d00..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/EnumConverterFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.sql2o.converters; - -/** - * Used by sql2o to convert a value from the database into an {@link Enum}. - */ -public interface EnumConverterFactory { - Converter newConverter(Class enumClass); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/FloatConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/FloatConverter.java deleted file mode 100644 index 1dea719a7..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/FloatConverter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.sql2o.converters; - -/** - * Used by sql2o to convert a value from the database into a {@link Float}. - */ -public class FloatConverter extends NumberConverter { - - public FloatConverter(boolean primitive) { - super(primitive); - } - - @Override - protected Float convertNumberValue(Number val) { - return val.floatValue(); - } - - @Override - protected Float convertStringValue(String val) { - return Float.parseFloat(val); - } - - @Override - protected String getTypeDescription() { - return Float.class.toString(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/InputStreamConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/InputStreamConverter.java deleted file mode 100644 index daf388cf3..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/InputStreamConverter.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.sql2o.converters; - -import java.io.ByteArrayInputStream; - -/** - * Created with IntelliJ IDEA. - * User: lars - * Date: 6/13/13 - * Time: 11:40 PM - * To change this template use File | Settings | File Templates. - */ -public class InputStreamConverter extends ConverterBase { - public ByteArrayInputStream convert(Object val) throws ConverterException { - if (val == null) return null; - - try { - return new ByteArrayInputStream( new ByteArrayConverter().convert(val) ); - } catch( ConverterException e) { - throw new ConverterException("Error converting Blob to InputSteam"); - } - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/IntegerConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/IntegerConverter.java deleted file mode 100644 index 6f24d4c1c..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/IntegerConverter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.sql2o.converters; - -/** - * Used by sql2o to convert a value from the database into an {@link Integer}. - */ -public class IntegerConverter extends NumberConverter{ - - public IntegerConverter(boolean primitive) { - super(primitive); - } - - @Override - protected Integer convertNumberValue(Number val) { - return val.intValue(); - } - - @Override - protected Integer convertStringValue(String val) { - return Integer.parseInt(val); - } - - @Override - protected String getTypeDescription() { - return Integer.class.toString(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/LongConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/LongConverter.java deleted file mode 100644 index d5b210a5f..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/LongConverter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.sql2o.converters; - -/** - * Used by sql2o to convert a value from the database into a {@link Long}. - */ -public class LongConverter extends NumberConverter { - - public LongConverter(boolean primitive) { - super(primitive); - } - - @Override - protected Long convertNumberValue(Number val) { - return val.longValue(); - } - - @Override - protected Long convertStringValue(String val) { - return Long.parseLong(val); - } - - @Override - protected String getTypeDescription() { - return Long.class.toString(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/NumberConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/NumberConverter.java deleted file mode 100644 index a20f023ff..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/NumberConverter.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.sql2o.converters; - -/** - * Base class for numeric converters. - */ -public abstract class NumberConverter extends ConverterBase { - - private boolean isPrimitive; - - public NumberConverter(boolean primitive) { - isPrimitive = primitive; - } - - public V convert(Object val) { - if (val == null) { - return isPrimitive ? convertNumberValue(0) : null; - } - - // val.getClass().isPrimitive() is ALWAYS false - // since boxing (i.e. Object val=(int)1;) - // changes type from Integet.TYPE to Integer.class - // learn 2 java :) - - else if (/*val.getClass().isPrimitive() || */val instanceof Number ) { - return convertNumberValue((Number)val); - } - else if (val instanceof String){ - String stringVal = ((String)val).trim(); - stringVal = stringVal.isEmpty() ? null : stringVal; - - if (stringVal == null) { - return isPrimitive ? convertNumberValue(0) : null; - } - - return convertStringValue(stringVal); - } - else{ - throw new IllegalArgumentException("Cannot convert type " + val.getClass().toString() + " to " + getTypeDescription()); - } - } - - protected abstract V convertNumberValue(Number val); - - protected abstract V convertStringValue(String val); - - protected abstract String getTypeDescription(); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/ShortConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/ShortConverter.java deleted file mode 100644 index 468136303..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/ShortConverter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.sql2o.converters; - -/** - * Used by sql2o to convert a value from the database into a {@link Short}. - */ -public class ShortConverter extends NumberConverter { - - public ShortConverter(boolean primitive) { - super(primitive); - } - - @Override - protected Short convertNumberValue(Number val) { - return val.shortValue(); - } - - @Override - protected Short convertStringValue(String val) { - return Short.parseShort(val); - } - - @Override - protected String getTypeDescription() { - return Short.class.toString(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java deleted file mode 100644 index e17f4409d..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/StringConverter.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.sql2o.converters; - -import java.io.IOException; -import java.io.Reader; -import java.sql.Clob; -import java.sql.SQLException; - -import blade.kit.IOKit; - -/** - * Used by sql2o to convert a value from the database into a {@link String}. - */ -public class StringConverter extends ConverterBase { - - public String convert(Object val) throws ConverterException { - if (val == null){ - return null; - } - - if (val instanceof Clob) { - Clob clobVal = (Clob)val; - try - { - try { - return clobVal.getSubString(1, (int)clobVal.length()); - } catch (SQLException e) { - throw new ConverterException("error converting clob to String", e); - } - } finally { - try { - clobVal.free(); - } catch (Throwable ignore) { - //ignore - } - } - } - - if(val instanceof Reader){ - Reader reader = (Reader) val; - try { - try { - return IOKit.toString(reader); - } catch (IOException e) { - throw new ConverterException("error converting reader to String", e); - } - } finally { - try { - reader.close(); - } catch (Throwable ignore) { - // ignore - } - } - } - - return val.toString().trim(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/UUIDConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/UUIDConverter.java deleted file mode 100644 index 8ad6c4c77..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/UUIDConverter.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.sql2o.converters; - -import java.util.UUID; - -/** - * Used by sql2o to convert a value from the database into a {@link UUID}. - */ -public class UUIDConverter extends ConverterBase { - public UUID convert(Object val) throws ConverterException { - if (val == null){ - return null; - } - - if (val instanceof UUID){ - return (UUID)val; - } - - if(val instanceof String){ - return UUID.fromString((String) val); - } - - throw new ConverterException("Cannot convert type " + val.getClass() + " " + UUID.class); - } -} - diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/joda/DateTimeConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/joda/DateTimeConverter.java deleted file mode 100644 index 1b5a00698..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/joda/DateTimeConverter.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.sql2o.converters.joda; - -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.joda.time.LocalDateTime; -import org.joda.time.LocalTime; -import org.sql2o.converters.Converter; -import org.sql2o.converters.ConverterException; - -import java.sql.Timestamp; - -/** - * Used by sql2o to convert a value from the database into a {@link DateTime} instance. - */ -public class DateTimeConverter implements Converter { - - private final DateTimeZone timeZone; - - // it's possible to create instance for other timezone - // and re-register converter - public DateTimeConverter(DateTimeZone timeZone) { - this.timeZone = timeZone; - } - - public DateTimeConverter() { - this(DateTimeZone.UTC); - } - - public DateTime convert(Object val) throws ConverterException { - if (val == null){ - return null; - } - try { - // Joda has it's own pluggable converters infrastructure - // it will throw IllegalArgumentException if can't convert - // look @ org.joda.time.convert.ConverterManager - return new LocalDateTime(val).toDateTime(timeZone); - } catch (IllegalArgumentException ex) { - throw new ConverterException("Error while converting type " + val.getClass().toString() + " to jodatime", ex); - } - } - - public Object toDatabaseParam(DateTime val) { - return new Timestamp(val.getMillis()); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/joda/LocalTimeConverter.java b/blade-sql2o/src/main/java/org/sql2o/converters/joda/LocalTimeConverter.java deleted file mode 100644 index 1cc4052f0..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/joda/LocalTimeConverter.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.sql2o.converters.joda; - -import org.joda.time.LocalTime; -import org.sql2o.converters.Converter; -import org.sql2o.converters.ConverterException; - -import java.sql.Timestamp; - -/** - * Created by lars on 12/18/13. - */ -public class LocalTimeConverter implements Converter { - - public LocalTime convert(Object val) throws ConverterException { - if (val == null) { - return null; - } - try { - // Joda has it's own pluggable converters infrastructure - // it will throw IllegalArgumentException if can't convert - // look @ org.joda.time.convert.ConverterManager - return new LocalTime(val); - } catch (IllegalArgumentException ex) { - throw new ConverterException("Don't know how to convert from type '" + val.getClass().getName() + "' to type '" + LocalTime.class.getName() + "'", ex); - } - } - - public Object toDatabaseParam(LocalTime val) { - return new Timestamp(val.toDateTimeToday().getMillis()); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/converters/package-info.java b/blade-sql2o/src/main/java/org/sql2o/converters/package-info.java deleted file mode 100644 index 83d35dedd..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/converters/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Provides all converters used by sql2o. These converters are used to convert values from the database to the expected - * data types. - */ -package org.sql2o.converters; \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/data/Column.java b/blade-sql2o/src/main/java/org/sql2o/data/Column.java deleted file mode 100644 index 824327839..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/data/Column.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.sql2o.data; - -/** - * Represents a result set column - */ -public class Column { - - private String name; - private Integer index; - private String type; - - public Column(String name, Integer index, String type) { - this.name = name; - this.index = index; - this.type = type; - } - - public String getName() { - return name; - } - - public Integer getIndex() { - return index; - } - - public String getType() { - return type; - } - - @Override - public String toString() { - return getName() + " (" + getType() + ")"; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/data/LazyTable.java b/blade-sql2o/src/main/java/org/sql2o/data/LazyTable.java deleted file mode 100644 index 552b05bd4..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/data/LazyTable.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.sql2o.data; - -import org.sql2o.ResultSetIterable; - -import java.util.List; - -/** - * @author aldenquimby@gmail.com - */ -public class LazyTable implements AutoCloseable { - private String name; - private ResultSetIterable rows; - private List columns; - - public String getName() { - return name; - } - - void setName(String name) { - this.name = name; - } - - public Iterable rows() { - return rows; - } - - public void setRows(ResultSetIterable rows) { - this.rows = rows; - } - - public List columns() { - return columns; - } - - void setColumns(List columns) { - this.columns = columns; - } - - public void close() { - this.rows.close(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/data/Row.java b/blade-sql2o/src/main/java/org/sql2o/data/Row.java deleted file mode 100644 index db7614590..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/data/Row.java +++ /dev/null @@ -1,194 +0,0 @@ -package org.sql2o.data; - -import org.sql2o.Sql2oException; -import org.sql2o.converters.*; -import org.sql2o.quirks.Quirks; - -import java.math.BigDecimal; -import java.util.*; - -import static java.util.Arrays.asList; -import static org.sql2o.converters.Convert.throwIfNull; - -/** - * Represents a result set row. - */ -@SuppressWarnings({"UnusedDeclaration", "RedundantTypeArguments"}) -public class Row { - - private final Object[] values; - private final boolean isCaseSensitive; - private final Quirks quirks; - private final Map columnNameToIdxMap; - - public Row(Map columnNameToIdxMap, int columnCnt, boolean isCaseSensitive, Quirks quirks) { - this.columnNameToIdxMap = columnNameToIdxMap; - this.isCaseSensitive = isCaseSensitive; - this.quirks = quirks; - // lol. array works better - this.values = new Object[columnCnt]; - } - - void addValue(int columnIndex, Object value){ - values[columnIndex]=value; - } - - public Object getObject(int columnIndex){ - return values[columnIndex]; - } - - public Object getObject(String columnName){ - Integer index = columnNameToIdxMap.get( - isCaseSensitive?columnName - :columnName.toLowerCase()); - if(index!=null) return getObject(index); - throw new Sql2oException(String.format("Column with name '%s' does not exist", columnName)); - } - - @SuppressWarnings("unchecked") - public V getObject(int columnIndex, Class clazz){ - try{ - return (V) throwIfNull(clazz, quirks.converterOf(clazz)).convert(getObject(columnIndex)); - } catch (ConverterException ex){ - throw new Sql2oException("Error converting value", ex); - } - } - - @SuppressWarnings("unchecked") - public V getObject(String columnName, Class clazz) { - try{ - return (V) throwIfNull(clazz, quirks.converterOf(clazz)).convert(getObject(columnName)); - } catch (ConverterException ex){ - throw new Sql2oException("Error converting value", ex); - } - } - - public BigDecimal getBigDecimal(int columnIndex){ - return this.getObject(columnIndex, BigDecimal.class); - } - - public BigDecimal getBigDecimal(String columnName){ - return this.getObject(columnName, BigDecimal.class); - } - - public Double getDouble(int columnIndex){ - return this.getObject(columnIndex, Double.class); - } - - public Double getDouble(String columnName){ - return this.getObject(columnName, Double.class); - } - - public Float getFloat(int columnIndex){ - return this.getObject(columnIndex, Float.class); - } - - public Float getFloat(String columnName){ - return this.getObject(columnName, Float.class); - } - - public Long getLong(int columnIndex){ - return this.getObject(columnIndex, Long.class); - } - - public Long getLong(String columnName){ - return this.getObject(columnName, Long.class); - } - - public Integer getInteger(int columnIndex){ - return this.getObject(columnIndex, Integer.class); - } - - public Integer getInteger(String columnName){ - return this.getObject(columnName, Integer.class); - } - - public Short getShort(int columnIndex){ - return this.getObject(columnIndex, Short.class); - } - - public Short getShort(String columnName){ - return this.getObject(columnName, Short.class); - } - - public Byte getByte(int columnIndex){ - return this.getObject(columnIndex, Byte.class); - } - - public Byte getByte(String columnName){ - return this.getObject(columnName, Byte.class); - } - - public Date getDate(int columnIndex){ - return this.getObject(columnIndex, Date.class); - } - - public Date getDate(String columnName){ - return this.getObject(columnName, Date.class); - } - - public String getString(int columnIndex){ - return this.getObject(columnIndex, String.class); - } - - public String getString(String columnName){ - return this.getObject(columnName, String.class); - } - - /** - * View row as a simple map. - */ - @SuppressWarnings("NullableProblems") - public Map asMap() - { final List listOfValues = asList(values); - return new Map() { - public int size() { - return values.length; - } - - public boolean isEmpty() { - return size()==0; - } - - public boolean containsKey(Object key) { - return columnNameToIdxMap.containsKey(key); - } - - public boolean containsValue(Object value) { - return listOfValues.contains(value); - } - - public Object get(Object key) { - return values[columnNameToIdxMap.get(key)]; - } - - public Object put(String key, Object value) { - throw new UnsupportedOperationException("Row map is immutable."); - } - - public Object remove(Object key) { - throw new UnsupportedOperationException("Row map is immutable."); - } - - public void putAll(Map m) { - throw new UnsupportedOperationException("Row map is immutable."); - } - - public void clear() { - throw new UnsupportedOperationException("Row map is immutable."); - } - - public Set keySet() { - return columnNameToIdxMap.keySet(); - } - - public Collection values() { - return listOfValues; - } - - public Set> entrySet() { - throw new UnsupportedOperationException("Row map does not support entrySet."); - } - }; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/data/Table.java b/blade-sql2o/src/main/java/org/sql2o/data/Table.java deleted file mode 100644 index 0697f94e6..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/data/Table.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.sql2o.data; - -import java.util.*; - -/** - * Represents an offline result set with columns and rows and data. - */ -public class Table { - private String name; - private List rows; - private List columns; - - public Table(String name, List rows, List columns) { - this.name = name; - this.rows = rows; - this.columns = columns; - } - - public String getName() { - return name; - } - - public List rows() { - return rows; - } - - public List columns() { - return columns; - } - - public List> asList() - { - return new AbstractList>() { - @Override - public Map get(int index) { - return rows.get(index).asMap(); - } - - @Override - public int size() { - return rows.size(); - } - }; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/data/TableResultSetIterator.java b/blade-sql2o/src/main/java/org/sql2o/data/TableResultSetIterator.java deleted file mode 100644 index e093a0af6..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/data/TableResultSetIterator.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.sql2o.data; - -import org.sql2o.ResultSetIteratorBase; -import org.sql2o.Sql2oException; -import org.sql2o.quirks.Quirks; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.*; - -/** - * @author aldenquimby@gmail.com - */ -public class TableResultSetIterator extends ResultSetIteratorBase { - private Map columnNameToIdxMap; - private List columns; - - public TableResultSetIterator(ResultSet rs, boolean isCaseSensitive, Quirks quirks, LazyTable lt) { - super(rs, isCaseSensitive, quirks); - - this.columnNameToIdxMap = new HashMap(); - this.columns = new ArrayList(); - - try { - lt.setName(meta.getTableName(1)); - - for (int colIdx = 1; colIdx <= meta.getColumnCount(); colIdx++){ - String colName = getColumnName(colIdx); - String colType = meta.getColumnTypeName(colIdx); - columns.add(new Column(colName, colIdx - 1, colType)); - - String colMapName = isCaseSensitive ? colName : colName.toLowerCase(); - columnNameToIdxMap.put(colMapName, colIdx - 1); - } - } - catch (SQLException e) { - throw new Sql2oException("Error while reading metadata from database", e); - } - - lt.setColumns(columns); - } - - @Override - protected Row readNext() throws SQLException { - Row row = new Row(columnNameToIdxMap, columns.size(), isCaseSensitive,this.quirks); - for (Column column : columns) { - row.addValue(column.getIndex(), quirks.getRSVal(rs, column.getIndex() + 1)); - } - return row; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/data/package-info.java b/blade-sql2o/src/main/java/org/sql2o/data/package-info.java deleted file mode 100644 index 078d8a9a2..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/data/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Provides the model used by sql2o to represent a raw result set. - */ -package org.sql2o.data; \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/package-info.java b/blade-sql2o/src/main/java/org/sql2o/package-info.java deleted file mode 100644 index 64f2f6128..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Provides the main api for sql2o. - */ -package org.sql2o; \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/Db2Quirks.java b/blade-sql2o/src/main/java/org/sql2o/quirks/Db2Quirks.java deleted file mode 100644 index ca4753e05..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/Db2Quirks.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.sql2o.quirks; - -import org.sql2o.converters.Converter; - -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.util.Map; - -/** - * @author aldenquimby@gmail.com - * @since 4/6/14 - */ -public class Db2Quirks extends NoQuirks { - public Db2Quirks() { - super(); - } - - public Db2Quirks(Map converters) { - super(converters); - } - // Db2 works perfect with java.sql.Timestamp - // checked on DATE|TIME|TIMESTAMP column types - - @Override - public String getColumnName(ResultSetMetaData meta, int colIdx) throws SQLException { - return meta.getColumnName(colIdx); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/NoQuirks.java b/blade-sql2o/src/main/java/org/sql2o/quirks/NoQuirks.java deleted file mode 100644 index 50ba7832a..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/NoQuirks.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.sql2o.quirks; - -import org.sql2o.converters.Convert; -import org.sql2o.converters.Converter; -import org.sql2o.quirks.parameterparsing.impl.DefaultSqlParameterParsingStrategy; -import org.sql2o.quirks.parameterparsing.SqlParameterParsingStrategy; - -import java.io.InputStream; -import java.sql.*; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * @author aldenquimby@gmail.com - * @since 4/6/14 - */ -public class NoQuirks implements Quirks { - protected final Map converters; - private final SqlParameterParsingStrategy sqlParameterParsingStrategy = new DefaultSqlParameterParsingStrategy(); - - public NoQuirks(Map converters) { - // protective copy - // to avoid someone change this collection outside - // so this makes converters thread-safe - this.converters = new HashMap(converters); - } - - public NoQuirks() { - this(Collections.emptyMap()); - } - - @SuppressWarnings("unchecked") - public Converter converterOf(Class ofClass) { - // if nobody change this collection outside constructor - // it's thread-safe - Converter c = converters.get(ofClass); - // if no "local" converter let's look in global - return c!=null?c:Convert.getConverterIfExists(ofClass); - - } - - public String getColumnName(ResultSetMetaData meta, int colIdx) throws SQLException { - return meta.getColumnLabel(colIdx); - } - - public boolean returnGeneratedKeysByDefault() { - return true; - } - - public void setParameter(PreparedStatement statement, int paramIdx, Object value) throws SQLException { - statement.setObject(paramIdx, value); - } - - public void setParameter(PreparedStatement statement, int paramIdx, InputStream value) throws SQLException { - statement.setBinaryStream(paramIdx, value); - } - - public void setParameter(PreparedStatement statement, int paramIdx, int value) throws SQLException { - statement.setInt(paramIdx, value); - } - - public void setParameter(PreparedStatement statement, int paramIdx, Integer value) throws SQLException { - if (value == null) { - statement.setNull(paramIdx, Types.INTEGER); - } else { - statement.setInt(paramIdx, value); - } - } - - public void setParameter(PreparedStatement statement, int paramIdx, long value) throws SQLException { - statement.setLong(paramIdx, value); - } - - public void setParameter(PreparedStatement statement, int paramIdx, Long value) throws SQLException { - if (value == null) { - statement.setNull(paramIdx, Types.BIGINT); - } else { - statement.setLong(paramIdx, value); - } - } - - public void setParameter(PreparedStatement statement, int paramIdx, String value) throws SQLException { - if (value == null) { - statement.setNull(paramIdx, Types.VARCHAR); - } else { - statement.setString(paramIdx, value); - } - } - - public void setParameter(PreparedStatement statement, int paramIdx, Timestamp value) throws SQLException { - if (value == null) { - statement.setNull(paramIdx, Types.TIMESTAMP); - } else { - statement.setTimestamp(paramIdx, value); - } - } - - public void setParameter(PreparedStatement statement, int paramIdx, Time value) throws SQLException { - if (value == null) { - statement.setNull(paramIdx, Types.TIME); - } else { - statement.setTime(paramIdx, value); - } - } - - public Object getRSVal(ResultSet rs, int idx) throws SQLException { - return rs.getObject(idx); - } - - @Override - public void closeStatement(Statement statement) throws SQLException { - statement.close(); - } - - @Override - public SqlParameterParsingStrategy getSqlParameterParsingStrategy() { - return this.sqlParameterParsingStrategy; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/OracleQuirks.java b/blade-sql2o/src/main/java/org/sql2o/quirks/OracleQuirks.java deleted file mode 100644 index f5a34ced8..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/OracleQuirks.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.sql2o.quirks; - - -import org.sql2o.converters.Converter; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Map; - -public class OracleQuirks extends NoQuirks { - public OracleQuirks() { - super(); - } - - public OracleQuirks(Map converters) { - super(converters); - } - - @Override - public Object getRSVal(ResultSet rs, int idx) throws SQLException { - Object o = super.getRSVal(rs, idx); - // oracle timestamps are not always convertible to a java Date. If ResultSet.getTimestamp is used instead of - // ResultSet.getObject, a normal java.sql.Timestamp instance is returnd. - if (o != null && o.getClass().getCanonicalName().startsWith("oracle.sql.TIMESTAMP")){ - //TODO: move to sql2o-oracle - //TODO: use TIMESTAMP.dateValue - o = rs.getTimestamp(idx); - } - return o; - } - - @Override - public boolean returnGeneratedKeysByDefault() { - return false; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/PostgresQuirks.java b/blade-sql2o/src/main/java/org/sql2o/quirks/PostgresQuirks.java deleted file mode 100644 index a27e24445..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/PostgresQuirks.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.sql2o.quirks; - -import org.sql2o.converters.Converter; - -import java.util.Map; - -/** - * @author aldenquimby@gmail.com - * @since 4/6/14 - */ -public class PostgresQuirks extends NoQuirks { - public PostgresQuirks() { - super(); - } - - public PostgresQuirks(Map converters) { - super(converters); - } - - @Override - public boolean returnGeneratedKeysByDefault() { - return false; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/Quirks.java b/blade-sql2o/src/main/java/org/sql2o/quirks/Quirks.java deleted file mode 100644 index 25672a59f..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/Quirks.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.sql2o.quirks; - -import org.sql2o.converters.Converter; -import org.sql2o.quirks.parameterparsing.SqlParameterParsingStrategy; - -import java.io.InputStream; -import java.sql.*; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; - -/** - * Interface for JDBC driver specific quirks. - * See {@link org.sql2o.quirks.NoQuirks} for defaults. - * - * @author aldenquimby@gmail.com - * @since 4/6/14 - */ -public interface Quirks { - /** - * @param ofClass - * @param - * @return converter for class - */ - - Converter converterOf(Class ofClass); - - - /** - * @return name of column at index {@code colIdx} for result set {@code meta} - */ - String getColumnName(ResultSetMetaData meta, int colIdx) throws SQLException; - - /** - * @return true if queries should return generated keys by default, false otherwise - */ - boolean returnGeneratedKeysByDefault(); - - void setParameter(PreparedStatement statement, int paramIdx, Object value) throws SQLException; - void setParameter(PreparedStatement statement, int paramIdx, InputStream value) throws SQLException; - void setParameter(PreparedStatement statement, int paramIdx, int value) throws SQLException; - void setParameter(PreparedStatement statement, int paramIdx, Integer value) throws SQLException; - void setParameter(PreparedStatement statement, int paramIdx, long value) throws SQLException; - void setParameter(PreparedStatement statement, int paramIdx, Long value) throws SQLException; - void setParameter(PreparedStatement statement, int paramIdx, String value) throws SQLException; - void setParameter(PreparedStatement statement, int paramIdx, Timestamp value) throws SQLException; - void setParameter(PreparedStatement statement, int paramIdx, Time value) throws SQLException; - - Object getRSVal(ResultSet rs, int idx) throws SQLException; - - void closeStatement(Statement statement) throws SQLException; - - SqlParameterParsingStrategy getSqlParameterParsingStrategy(); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksDetector.java b/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksDetector.java deleted file mode 100644 index 63e55ff50..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksDetector.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.sql2o.quirks; - -import org.sql2o.GenericDatasource; - -import java.util.ServiceLoader; - -/** - * User: dimzon - * Date: 4/24/14 - * Time: 9:39 AM - */ -public class QuirksDetector{ - static final ServiceLoader providers = ServiceLoader.load(QuirksProvider.class); - - public static Quirks forURL(String jdbcUrl) { - Quirks quirks; - for (QuirksProvider provider : providers) { - quirks=provider.forURL(jdbcUrl); - if(quirks!=null) return quirks; - } - return new NoQuirks(); - } - - public static Quirks forObject(Object jdbcObject) { - if(jdbcObject instanceof GenericDatasource) - return forURL(((GenericDatasource) jdbcObject).getUrl()); - Quirks quirks; - for (QuirksProvider provider : providers) { - quirks=provider.forObject(jdbcObject); - if(quirks!=null) return quirks; - } - return new NoQuirks(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksProvider.java b/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksProvider.java deleted file mode 100644 index 5a18657a9..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/QuirksProvider.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.sql2o.quirks; - -/** - * User: dimzon - * Date: 4/24/14 - * Time: 9:31 AM - */ -public interface QuirksProvider { - Quirks forURL(String jdbcUrl); - Quirks forObject(Object jdbcObject); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/SqlParameterParsingStrategy.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/SqlParameterParsingStrategy.java deleted file mode 100644 index 2240d3788..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/SqlParameterParsingStrategy.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.sql2o.quirks.parameterparsing; - -import java.util.List; -import java.util.Map; - -/** - * Created by lars on 11.04.14. - */ -public interface SqlParameterParsingStrategy { - String parseSql(String sqlToParse, Map> mapToFill); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/AbstractCommentParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/AbstractCommentParser.java deleted file mode 100644 index b3081b393..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/AbstractCommentParser.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.sql2o.quirks.parameterparsing.impl; - -/** - * Created by lars on 22.09.2014. - */ -public abstract class AbstractCommentParser implements CharParser { - - protected void init(){}; - - @Override - public int parse(char c, int idx, StringBuilder parsedSql, String sql, int length) { - init(); - do { - parsedSql.append(c); - if (++idx == length) return idx; - c = sql.charAt(idx); - } while(!isEndComment(c)); - parsedSql.append(c); - return idx; - } - - public abstract boolean isEndComment(char c); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/CharParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/CharParser.java deleted file mode 100644 index a3696cf65..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/CharParser.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.sql2o.quirks.parameterparsing.impl; - -/** - * Created by lars on 22.09.2014. - */ -public interface CharParser { - boolean canParse(char c, String sql, int idx); - int parse(char c, int idx, StringBuilder parsedSql, String sql, int length); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultParser.java deleted file mode 100644 index 3c28cab92..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultParser.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.sql2o.quirks.parameterparsing.impl; - -/** - * Created by lars on 22.09.2014. - */ -public class DefaultParser implements CharParser { - - @Override - public boolean canParse(char c, String sql, int idx) { - return true; - } - - @Override - public int parse(char c, int idx, StringBuilder parsedSql, String sql, int length) { - parsedSql.append(c); - return idx; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultSqlParameterParsingStrategy.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultSqlParameterParsingStrategy.java deleted file mode 100644 index fbd0c543d..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DefaultSqlParameterParsingStrategy.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.sql2o.quirks.parameterparsing.impl; - -import org.sql2o.quirks.parameterparsing.SqlParameterParsingStrategy; -import org.sql2o.tools.AbstractCache; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Created by lars on 11.04.14. - */ -public class DefaultSqlParameterParsingStrategy implements SqlParameterParsingStrategy { - - public CharParser[] getCharParsers(Map> paramMap) { - return new CharParser[]{ - new QuoteParser(), - new DoubleHyphensCommentParser(), - new ForwardSlashCommentParser(), - new ParameterParser(paramMap), - new DefaultParser() - }; - } - - @SuppressWarnings("ConstantConditions") - public String parseSql(String statement, Map> paramMap) { - final int length = statement.length(); - final StringBuilder parsedQuery = new StringBuilder(length); - - final CharParser[] charParsers = getCharParsers(paramMap); - - for (int idx = 0; idx < length; idx++) { - for (CharParser parser : charParsers) { - char c = statement.charAt(idx); - if (parser.canParse(c, statement, idx)){ - idx = parser.parse(c, idx, parsedQuery, statement, length); - break; - } - } - } - - return parsedQuery.toString(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DoubleHyphensCommentParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DoubleHyphensCommentParser.java deleted file mode 100644 index ce650d73c..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/DoubleHyphensCommentParser.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.sql2o.quirks.parameterparsing.impl; - -/** - * Created by lars on 22.09.2014. - */ -public class DoubleHyphensCommentParser extends AbstractCommentParser { - - @Override - public boolean canParse(char c, String sql, int idx) { - return sql.length() > idx + 1 && c == '-' && sql.charAt(idx + 1) == '-'; - } - - @Override - public boolean isEndComment(char c) { - return c == '\n'; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ForwardSlashCommentParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ForwardSlashCommentParser.java deleted file mode 100644 index d76c4a66a..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ForwardSlashCommentParser.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.sql2o.quirks.parameterparsing.impl; - -/** - * Created by lars on 22.09.2014. - */ -public class ForwardSlashCommentParser extends AbstractCommentParser { - - private boolean commentAlmostEnded; - - @Override - protected void init() { - commentAlmostEnded = false; - } - - @Override - public boolean canParse(char c, String sql, int idx) { - return sql.length() > idx + 1 && c == '/' && sql.charAt(idx + 1) == '*'; - } - - @Override - public boolean isEndComment(char c) { - if (commentAlmostEnded && c == '/') return true; - commentAlmostEnded = c == '*'; - return false; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ParameterParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ParameterParser.java deleted file mode 100644 index 4a8330524..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/ParameterParser.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.sql2o.quirks.parameterparsing.impl; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Created by lars on 22.09.2014. - */ -public class ParameterParser implements CharParser{ - - private final Map> parameterMap; - int paramIdx = 1; - - public ParameterParser(Map> parameterMap) { - this.parameterMap = parameterMap; - } - - @Override - public boolean canParse(char c, String sql, int idx) { - return sql.length() > idx + 1 && c == ':' && Character.isJavaIdentifierStart( sql.charAt(idx + 1) ) && sql.charAt(idx-1) != ':'; - } - - @Override - public int parse(char c, int idx, StringBuilder parsedSql, String sql, int length) { - int startIdx = idx; - idx += 1; - - while (idx + 1 < length && Character.isJavaIdentifierPart(sql.charAt(idx + 1))) { - idx += 1; - } - - String name = sql.substring(startIdx + 1, idx + 1); - List indices = parameterMap.get(name); - if (indices == null) { - indices = new ArrayList(); - parameterMap.put(name, indices); - } - indices.add(paramIdx++); - parsedSql.append("?"); - - return idx; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/QuoteParser.java b/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/QuoteParser.java deleted file mode 100644 index 6587613d4..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/parameterparsing/impl/QuoteParser.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.sql2o.quirks.parameterparsing.impl; - -/** - * Created by lars on 22.09.2014. - */ -public class QuoteParser implements CharParser { - - @Override - public boolean canParse(char c, String sql, int idx) { - return c == '\'' || c == '"'; - } - - @Override - public int parse(char c, int idx, StringBuilder parsedSql, String sql, int length) { - char quoteChar = c; - - do { - parsedSql.append(c); - if (++idx == length) return idx; - c = sql.charAt(idx); - - } while(c != quoteChar); - parsedSql.append(c); - return idx; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/quirks/spi/QuirksProviderImpl.java b/blade-sql2o/src/main/java/org/sql2o/quirks/spi/QuirksProviderImpl.java deleted file mode 100644 index fd0332da4..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/quirks/spi/QuirksProviderImpl.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.sql2o.quirks.spi; - -import org.sql2o.quirks.*; - -/** - * User: dimzon - * Date: 4/24/14 - * Time: 9:35 AM - */ -public class QuirksProviderImpl implements QuirksProvider { - public Quirks forURL(String jdbcUrl) { - if (jdbcUrl.startsWith("jdbc:oracle:")) return oracleQuirks.q; - if (jdbcUrl.startsWith("jdbc:db2:")) return db2Quirks.q; - if (jdbcUrl.startsWith("jdbc:db2j:net:")) return db2Quirks.q; - if (jdbcUrl.startsWith("jdbc:db2os390")) return db2Quirks.q; - if (jdbcUrl.startsWith("jdbc:postgresql:")) return postgresQuirks.q; - return null; - } - - public Quirks forObject(Object jdbcObject) { - String className = jdbcObject.getClass().getCanonicalName(); - if (className.startsWith("oracle.jdbc.")) return oracleQuirks.q; - if (className.startsWith("oracle.sql.")) return oracleQuirks.q; - if (className.startsWith("com.ibm.db2.jcc.DB2")) return db2Quirks.q; - if (className.startsWith("org.postgresql.")) return postgresQuirks.q; - return null; - } - - private static class oracleQuirks { - static final Quirks q = new OracleQuirks(); - } - - private static class db2Quirks { - static final Quirks q = new Db2Quirks(); - } - - private static class postgresQuirks { - static final Quirks q = new PostgresQuirks(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java b/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java deleted file mode 100644 index bcdd855ba..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/FactoryFacade.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.sql2o.reflection; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -@SuppressWarnings("Unsafe") -public class FactoryFacade { - private final static FactoryFacade instance; - - static { - MethodSetterFactory m; - ObjectConstructorFactory o; - try { - m = (MethodSetterFactory) Class - .forName("org.sql2o.reflection.MethodAccessorsGenerator") - .newInstance(); - o = (ObjectConstructorFactory) m; - } catch (Throwable ex) { - m = new ReflectionMethodSetterFactory(); - o = null; - } - FieldSetterFactory f; - try { - Class cls = Class.forName("org.sql2o.reflection.UnsafeFieldSetterFactory"); - f = (FieldSetterFactory) cls.newInstance(); - if(o==null) o = (ObjectConstructorFactory) f; - } catch (Throwable ex) { - f = new ReflectionFieldSetterFactory(); - o = new ReflectionObjectConstructorFactory(); - } - instance = new FactoryFacade(f, m, o); - } - - private final FieldSetterFactory fieldSetterFactory; - private final MethodSetterFactory methodSetterFactory; - private final ObjectConstructorFactory objectConstructorFactory; - - public FactoryFacade(FieldSetterFactory fieldSetterFactory, MethodSetterFactory methodSetterFactory, ObjectConstructorFactory objectConstructorFactory) { - this.fieldSetterFactory = fieldSetterFactory; - this.methodSetterFactory = methodSetterFactory; - this.objectConstructorFactory = objectConstructorFactory; - } - - public static FactoryFacade getInstance() { - return instance; - } - - public Setter newSetter(Field field) { - return fieldSetterFactory.newSetter(field); - } - - public Setter newSetter(Method method) { - return methodSetterFactory.newSetter(method); - } - - public ObjectConstructor newConstructor(Class cls) { - return objectConstructorFactory.newConstructor(cls); - } -} - diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java deleted file mode 100644 index 31af9d97f..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetter.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.sql2o.reflection; - -import org.sql2o.Sql2oException; - -import java.lang.reflect.Field; - -/** - * used internally to set property values directly into the field. Only used if no setter method is found. - */ -public class FieldSetter implements Setter{ - - private Field field; - - public FieldSetter(Field field) { - this.field = field; - this.field.setAccessible(true); - } - - public void setProperty(Object obj, Object value) { - if (value == null && this.field.getType().isPrimitive()){ - return; // dont try set null to a primitive field - } - - try { - this.field.set(obj, value); - } catch (IllegalAccessException e) { - throw new Sql2oException("could not set field " + this.field.getName() + " on class " + obj.getClass().toString(), e); - } - } - - public Class getType() { - return field.getType(); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetterFactory.java deleted file mode 100644 index cf00bdbc9..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/FieldSetterFactory.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.sql2o.reflection; - -import java.lang.reflect.Field; - -/** - * Created with IntelliJ IDEA. - * User: dimzon - * Date: 4/6/14 - * Time: 12:39 AM - * To change this template use File | Settings | File Templates. - */ -public interface FieldSetterFactory { - Setter newSetter(Field field); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java deleted file mode 100644 index fbc132200..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodAccessorsGenerator.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.sql2o.reflection; - -import org.sql2o.Sql2oException; -import sun.reflect.ConstructorAccessor; -import sun.reflect.FieldAccessor; -import sun.reflect.MethodAccessor; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -@SuppressWarnings("UnusedDeclaration") -public class MethodAccessorsGenerator implements MethodSetterFactory, ObjectConstructorFactory { - private static final ThreadLocal generatorObjectHolder; - private static final MethodAccessor generateMethod; - private static final MethodAccessor generateConstructor; - private static final MethodAccessor generateSerializationConstructor; - private static final MethodAccessor newFieldAccessor; - - static { - try { - Class aClass = Class.forName("sun.reflect.MethodAccessorGenerator"); - Constructor[] declaredConstructors = aClass.getDeclaredConstructors(); - Constructor declaredConstructor = declaredConstructors[0]; - declaredConstructor.setAccessible(true); - Object generatorObject = declaredConstructor.newInstance(); - Method bar = aClass.getMethod("generateMethod", Class.class, String.class, Class[].class, Class.class, Class[].class, Integer.TYPE); - bar.setAccessible(true); - generateMethod = (MethodAccessor) bar.invoke( - generatorObject, - bar.getDeclaringClass(), - bar.getName(), - bar.getParameterTypes(), - bar.getReturnType(), - bar.getExceptionTypes(), - bar.getModifiers()); - bar = aClass.getMethod("generateConstructor", Class.class, Class[].class, Class[].class, Integer.TYPE); - generateConstructor = newMethodAccessor(generatorObject, bar); - bar = aClass.getMethod("generateSerializationConstructor", Class.class, Class[].class, Class[].class, Integer.TYPE, Class.class); - final ConstructorAccessor goc = newConstructorAccessor(generatorObject, declaredConstructor); - generatorObjectHolder = new ThreadLocal() { - @Override - protected Object initialValue() { - try { - return goc.newInstance(null); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - }; - generateSerializationConstructor = newMethodAccessor(generatorObject, bar); - aClass = Class.forName("sun.reflect.UnsafeFieldAccessorFactory"); - bar = aClass.getDeclaredMethod("newFieldAccessor", Field.class, Boolean.TYPE); - newFieldAccessor = newMethodAccessor(generatorObject, bar); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - public static FieldAccessor newFieldAccessor(Field field, boolean overrideFinalCheck) { - try { - return (FieldAccessor) newFieldAccessor.invoke(null, new Object[]{field, overrideFinalCheck}); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - public static MethodAccessor newMethodAccessor(Method bar) { - try { - return newMethodAccessor(generatorObjectHolder.get(), bar); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - private static MethodAccessor newMethodAccessor(Object generatorObject, Method bar) throws InvocationTargetException { - return (MethodAccessor) generateMethod.invoke( - generatorObject, new Object[]{ - bar.getDeclaringClass(), - bar.getName(), - bar.getParameterTypes(), - bar.getReturnType(), - bar.getExceptionTypes(), - bar.getModifiers()}); - } - - public static ConstructorAccessor newConstructorAccessor(Constructor bar) { - try { - return newConstructorAccessor(generatorObjectHolder.get(), bar); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - private static ConstructorAccessor newConstructorAccessor(Object generatorObject, Constructor bar) throws InvocationTargetException { - return (ConstructorAccessor) generateConstructor.invoke( - generatorObject, new Object[]{ - bar.getDeclaringClass(), - bar.getParameterTypes(), - bar.getExceptionTypes(), - bar.getModifiers()}); - } - - public static ConstructorAccessor newConstructorAccessor(Constructor bar, Class targetClass) { - try { - return (ConstructorAccessor) generateSerializationConstructor.invoke( - generatorObjectHolder.get(), new Object[]{ - targetClass, - bar.getParameterTypes(), - bar.getExceptionTypes(), - bar.getModifiers(), - bar.getDeclaringClass()}); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - public Setter newSetter(final Method method) { - final Class type = method.getParameterTypes()[0]; - final MethodAccessor methodAccessor = newMethodAccessor(method); - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null && type.isPrimitive()) return; - try { - methodAccessor.invoke(obj, new Object[]{value}); - } catch (InvocationTargetException e) { - throw new Sql2oException("error while calling setter method with name " + method.getName() + " on class " + obj.getClass().toString(), e); - } - } - - public Class getType() { - return type; - } - }; - } - - @Override - public ObjectConstructor newConstructor(final Class cls) { - for (Class cls0 = cls; cls != Object.class; cls0 = cls0.getSuperclass()) { - try { - Constructor ctor = cls0.getDeclaredConstructor(); - final ConstructorAccessor constructorAccessor = (cls0 == cls) - ? newConstructorAccessor(ctor) - : newConstructorAccessor(ctor, cls); - return new ObjectConstructor() { - @Override - public Object newInstance() { - try { - return constructorAccessor.newInstance(null); - } catch (InstantiationException e) { - throw new Sql2oException("Could not create a new instance of class " + cls, e); - }catch (InvocationTargetException e) { - throw new Sql2oException("Could not create a new instance of class " + cls, e); - } - } - }; - } catch (NoSuchMethodException e) { - // ignore - } - } - return UnsafeFieldSetterFactory.getConstructor(cls); - } -} \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java deleted file mode 100644 index e27043199..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetter.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.sql2o.reflection; - -import org.sql2o.Sql2oException; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * used internally to set property values via its setter method. - */ -public class MethodSetter implements Setter{ - - private Method method; - private Class type; - - public MethodSetter(Method method) { - this.method = method; - this.method.setAccessible(true); - type = method.getParameterTypes()[0]; - } - - public void setProperty(Object obj, Object value) { - if (value == null && type.isPrimitive()){ - return; // dont try to set null to a setter to a primitive type. - } - try { - this.method.invoke(obj, value); - } catch (IllegalAccessException e) { - throw new Sql2oException("error while calling setter method with name " + method.getName() + " on class " + obj.getClass().toString(), e); - } catch (InvocationTargetException e) { - throw new Sql2oException("error while calling setter method with name " + method.getName() + " on class " + obj.getClass().toString(), e); - } - } - - public Class getType() { - return type; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetterFactory.java deleted file mode 100644 index d1afc6534..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/MethodSetterFactory.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.sql2o.reflection; - -import java.lang.reflect.Method; - -/** - * Created with IntelliJ IDEA. - * User: dimzon - * Date: 4/6/14 - * Time: 12:42 AM - * To change this template use File | Settings | File Templates. - */ -public interface MethodSetterFactory { - Setter newSetter(Method method); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructor.java b/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructor.java deleted file mode 100644 index 5538a47d1..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructor.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.sql2o.reflection; - -/** - * Created with IntelliJ IDEA. - * User: dimzon - * Date: 4/6/14 - * Time: 1:26 AM - * To change this template use File | Settings | File Templates. - */ -public interface ObjectConstructor { - Object newInstance(); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructorFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructorFactory.java deleted file mode 100644 index 82180f4dd..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/ObjectConstructorFactory.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.sql2o.reflection; - -/** - * Created with IntelliJ IDEA. - * User: dimzon - * Date: 4/6/14 - * Time: 1:27 AM - * To change this template use File | Settings | File Templates. - */ -public interface ObjectConstructorFactory { - ObjectConstructor newConstructor(Class cls); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java b/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java deleted file mode 100644 index 389303f19..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/Pojo.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.sql2o.reflection; - -import org.sql2o.Sql2oException; -import org.sql2o.converters.Converter; -import org.sql2o.converters.ConverterException; -import org.sql2o.quirks.Quirks; - -import static org.sql2o.converters.Convert.throwIfNull; - -/** - * Used internally to represent a plain old java object. - */ -public class Pojo { - - private PojoMetadata metadata; - private boolean caseSensitive; - private Object object; - - public Pojo(PojoMetadata metadata, boolean caseSensitive, Object object){ - this.caseSensitive = caseSensitive; - this.metadata = metadata; - this.object = object; - } - - public Pojo(PojoMetadata metadata, boolean caseSensitive){ - this.caseSensitive = caseSensitive; - this.metadata = metadata; - ObjectConstructor objectConstructor = metadata.getObjectConstructor(); - object = objectConstructor.newInstance(); - } - - @SuppressWarnings("unchecked") - public void setProperty(String propertyPath, Object value, Quirks quirks){ - // String.split uses RegularExpression - // this is overkill for every column for every row - int index = propertyPath.indexOf('.'); - Setter setter; - if (index > 0){ - final String substring = propertyPath.substring(0, index); - setter = metadata.getPropertySetter(substring); - String newPath = propertyPath.substring(index+1); - - Object subValue = this.metadata.getValueOfProperty(substring, this.object); - if (subValue == null){ - try { - subValue = setter.getType().newInstance(); - } catch (InstantiationException e) { - throw new Sql2oException("Could not instantiate a new instance of class "+ setter.getType().toString(), e); - } catch (IllegalAccessException e) { - throw new Sql2oException("Could not instantiate a new instance of class "+ setter.getType().toString(), e); - } - setter.setProperty(this.object, subValue); - } - - PojoMetadata subMetadata = new PojoMetadata(setter.getType(), this.caseSensitive, this.metadata.isAutoDeriveColumnNames(), this.metadata.getColumnMappings(), this.metadata.throwOnMappingFailure); - Pojo subPojo = new Pojo(subMetadata, this.caseSensitive, subValue); - subPojo.setProperty(newPath, value, quirks); - } - else{ - setter = metadata.getPropertySetter(propertyPath); - Converter converter; - try { - converter = throwIfNull(setter.getType(), quirks.converterOf(setter.getType())); - } catch (ConverterException e) { - throw new Sql2oException("Cannot convert column " + propertyPath + " to type " + setter.getType(), e); - } - - try { - setter.setProperty(this.object, converter.convert( value )); - } catch (ConverterException e) { - throw new Sql2oException("Error trying to convert column " + propertyPath + " to type " + setter.getType(), e); - } - } - - - } - - - - public Object getObject(){ - return this.object; - } - -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java deleted file mode 100644 index bfb1faa2b..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoIntrospector.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.sql2o.reflection; - -import org.sql2o.tools.AbstractCache; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.util.*; - -import static java.beans.Introspector.decapitalize; -import static java.lang.reflect.Modifier.isPrivate; -import static java.lang.reflect.Modifier.isStatic; - -/** - * User: dimzon - * Date: 4/9/14 - * Time: 1:10 AM - */ - -// TODO: move introspection code from PojoMetadata to PojoIntrospector - -@SuppressWarnings("UnusedDeclaration") -public class PojoIntrospector { - private static final AbstractCache, Map, Void> rpCache = - new AbstractCache, Map, Void>() { - @Override - protected Map evaluate(Class key, Void param) { - return collectReadableProperties(key); - } - }; - - private static Map collectReadableProperties(Class cls) { - Map map = new HashMap(); - List> classList = classInheritanceHierarhy(cls, Object.class); - for (Class aClass : classList) { - collectPropertyGetters(map, aClass); - } - for (Class aClass : classList) { - collectReadableFields(map, aClass); - } - return Collections.unmodifiableMap(map); - } - - public static Map readableProperties(Class ofClass) { - return rpCache.get(ofClass, null); - } - - private static void collectReadableFields(Map map, Class cls) { - for (final Field m : cls.getDeclaredFields()) { - if (isStaticOrPrivate(m)) continue; - String propName = m.getName(); - if (map.containsKey(propName)) continue; - Class returnType = m.getType(); - m.setAccessible(true); - ReadableProperty rp = new ReadableProperty(propName, returnType) { - @Override - public Object get(Object instance) throws InvocationTargetException, IllegalAccessException { - return m.get(instance); - } - }; - map.put(propName, rp); - } - } - - private static boolean isStaticOrPrivate(Member m) { - final int modifiers = m.getModifiers(); - return isStatic(modifiers) || isPrivate(modifiers); - } - - private static void collectPropertyGetters(Map map, Class cls) { - for (final Method m : cls.getDeclaredMethods()) { - if (isStatic(m.getModifiers())) continue; - if (isPrivate(m.getModifiers())) continue; - if (0 != m.getParameterTypes().length) continue; - Class returnType = m.getReturnType(); - if (returnType == Void.TYPE || returnType == Void.class) continue; - String name = m.getName(); - String propName = null; - if (name.startsWith("get") && name.length() > 3) { - propName = decapitalize(name.substring(3)); - } else if (name.startsWith("is") && name.length() > 2 && returnType == Boolean.TYPE) { - propName = decapitalize(name.substring(2)); - } - if (propName == null) continue; - if (map.containsKey(propName)) continue; - m.setAccessible(true); - ReadableProperty rp = new ReadableProperty(propName, returnType) { - @Override - public Object get(Object instance) throws InvocationTargetException, IllegalAccessException { - return m.invoke(instance, (Object[]) null); - } - }; - map.put(propName, rp); - } - } - - private static List> classInheritanceHierarhy(Class cls, Class stopAt) { - ArrayList> list = new ArrayList>(); - while (cls != null && cls != stopAt) { - list.add(cls); - cls = cls.getSuperclass(); - } - return list; - } - - public abstract static class ReadableProperty { - public final String name; - public final Class type; - - private ReadableProperty(String name, Class type) { - this.name = name; - this.type = type; - } - - public abstract Object get(Object instance) throws InvocationTargetException, IllegalAccessException; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java b/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java deleted file mode 100644 index 2f9db165c..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/PojoMetadata.java +++ /dev/null @@ -1,188 +0,0 @@ -package org.sql2o.reflection; - -import org.sql2o.Sql2oException; -import org.sql2o.tools.AbstractCache; -import org.sql2o.tools.UnderscoreToCamelCase; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * Stores metadata for a POJO. - */ -public class PojoMetadata { - - private static final Cache caseSensitiveFalse = new Cache(); - private static final Cache caseSensitiveTrue = new Cache(); - private final PropertyAndFieldInfo propertyInfo; - private final Map columnMappings; - private final FactoryFacade factoryFacade = FactoryFacade.getInstance(); - - private boolean caseSensitive; - private boolean autoDeriveColumnNames; - public final boolean throwOnMappingFailure; - private Class clazz; - - public boolean isCaseSensitive() { - return caseSensitive; - } - - public boolean isAutoDeriveColumnNames() { - return autoDeriveColumnNames; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - PojoMetadata that = (PojoMetadata) o; - - return autoDeriveColumnNames == that.autoDeriveColumnNames - && caseSensitive == that.caseSensitive - && clazz.equals(that.clazz) - && columnMappings.equals(that.columnMappings) - && propertyInfo.equals(that.propertyInfo); - - } - - @Override - public int hashCode() { - int result = (caseSensitive ? 1 : 0); - result = 31 * result + clazz.hashCode(); - return result; - } - - public PojoMetadata(Class clazz, boolean caseSensitive, boolean autoDeriveColumnNames, Map columnMappings, boolean throwOnMappingError) { - this.caseSensitive = caseSensitive; - this.autoDeriveColumnNames = autoDeriveColumnNames; - this.clazz = clazz; - this.columnMappings = columnMappings == null ? Collections.emptyMap() : columnMappings; - - this.propertyInfo = getPropertyInfoThroughCache(); - this.throwOnMappingFailure = throwOnMappingError; - - } - - public ObjectConstructor getObjectConstructor() { - return propertyInfo.objectConstructor; - } - - private PropertyAndFieldInfo getPropertyInfoThroughCache() { - return (caseSensitive - ? caseSensitiveTrue - : caseSensitiveFalse) - .get(clazz, this); - } - - private PropertyAndFieldInfo initializePropertyInfo() { - - HashMap propertySetters = new HashMap(); - HashMap fields = new HashMap(); - - Class theClass = clazz; - ObjectConstructor objectConstructor = factoryFacade.newConstructor(theClass); - do { - for (Field f : theClass.getDeclaredFields()) { - String propertyName = f.getName(); - propertyName = caseSensitive ? propertyName : propertyName.toLowerCase(); - propertySetters.put(propertyName, factoryFacade.newSetter(f)); - fields.put(propertyName, f); - } - - // prepare methods. Methods will override fields, if both exists. - for (Method m : theClass.getDeclaredMethods()) { - if (m.getParameterTypes().length!=1) continue; - if (m.getName().startsWith("set")) { - String propertyName = m.getName().substring(3); - if (caseSensitive) { - propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); - } else { - propertyName = propertyName.toLowerCase(); - } - - propertySetters.put(propertyName, factoryFacade.newSetter(m)); - } - } - theClass = theClass.getSuperclass(); - } while (!theClass.equals(Object.class)); - - return new PropertyAndFieldInfo(propertySetters, fields, objectConstructor); - - } - - public Map getColumnMappings() { - return columnMappings; - } - - public Setter getPropertySetter(String propertyName) { - - Setter setter = getPropertySetterIfExists(propertyName); - - if (setter != null) { - return setter; - } else { - String errorMsg = "Property with name '" + propertyName + "' not found on class " + this.clazz.toString(); - if (this.caseSensitive) { - errorMsg += " (You have turned on case sensitive property search. Is this intentional?)"; - } - throw new Sql2oException(errorMsg); - } - } - - public Setter getPropertySetterIfExists(String propertyName) { - - String name = this.caseSensitive ? propertyName : propertyName.toLowerCase(); - - if (this.columnMappings.containsKey(name)) { - name = this.columnMappings.get(name); - } - - if (autoDeriveColumnNames) { - name = UnderscoreToCamelCase.convert(name); - if (!this.caseSensitive) name = name.toLowerCase(); - } - - return propertyInfo.propertySetters.get(name); - } - - public Class getType() { - return this.clazz; - } - - public Object getValueOfProperty(String propertyName, Object object) { - String name = this.caseSensitive ? propertyName : propertyName.toLowerCase(); - - Field field = this.propertyInfo.fields.get(name); - try { - return field.get(object); - } catch (IllegalAccessException e) { - throw new Sql2oException("could not read value of field " + field.getName() + " on class " + object.getClass().toString(), e); - } - } - - private static class Cache extends AbstractCache { - @Override - protected PropertyAndFieldInfo evaluate(Class key, PojoMetadata param) { - return param.initializePropertyInfo(); - } - } - - private static class PropertyAndFieldInfo { - // since this class is private we can just use field access - // to make HotSpot a little less work for inlining - public final Map propertySetters; - public final Map fields; - public final ObjectConstructor objectConstructor; - - private PropertyAndFieldInfo(Map propertySetters, Map fields, ObjectConstructor objectConstructor) { - this.propertySetters = propertySetters; - this.fields = fields; - this.objectConstructor = objectConstructor; - } - } -} - diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionFieldSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionFieldSetterFactory.java deleted file mode 100644 index 724544339..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionFieldSetterFactory.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.sql2o.reflection; - -import java.lang.reflect.Field; - -/** - * Created with IntelliJ IDEA. - * User: dimzon - * Date: 4/6/14 - * Time: 12:40 AM - * To change this template use File | Settings | File Templates. - */ -public class ReflectionFieldSetterFactory implements FieldSetterFactory { - public Setter newSetter(Field field) { - return new FieldSetter(field); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionMethodSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionMethodSetterFactory.java deleted file mode 100644 index 3115228f8..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionMethodSetterFactory.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.sql2o.reflection; - -import java.lang.reflect.Method; - -/** - * Created with IntelliJ IDEA. - * User: dimzon - * Date: 4/6/14 - * Time: 12:43 AM - * To change this template use File | Settings | File Templates. - */ -public class ReflectionMethodSetterFactory implements MethodSetterFactory { - public Setter newSetter(Method method) { - return new MethodSetter(method); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionObjectConstructorFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionObjectConstructorFactory.java deleted file mode 100644 index d8f33e3bf..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/ReflectionObjectConstructorFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.sql2o.reflection; - -import org.sql2o.Sql2oException; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; - -public class ReflectionObjectConstructorFactory implements ObjectConstructorFactory { - public ObjectConstructor newConstructor(final Class clazz) { - try { - final Constructor ctor = clazz.getDeclaredConstructor(); - ctor.setAccessible(true); - return new ObjectConstructor() { - public Object newInstance() { - try { - return ctor.newInstance((Object[])null); - } catch (InstantiationException e) { - throw new Sql2oException("Could not create a new instance of class " + clazz, e); - } catch (IllegalAccessException e) { - throw new Sql2oException("Could not create a new instance of class " + clazz, e); - } catch (InvocationTargetException e) { - throw new Sql2oException("Could not create a new instance of class " + clazz, e); - } - } - }; - } catch (Throwable e) { - throw new Sql2oException("Could not find parameter-less constructor of class " + clazz, e); - } - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java b/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java deleted file mode 100644 index b7da73fe1..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/Setter.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.sql2o.reflection; - -/** - * The Setter interface is used by sql2o to set property values when doing automatic column to property mapping - */ -public interface Setter { - - void setProperty(Object obj, Object value); - Class getType(); -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java b/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java deleted file mode 100644 index c6b068c7d..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/UnsafeFieldSetterFactory.java +++ /dev/null @@ -1,260 +0,0 @@ -package org.sql2o.reflection; - -import org.sql2o.Sql2oException; -import sun.misc.Unsafe; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -@SuppressWarnings("Unsafe") -public class UnsafeFieldSetterFactory implements FieldSetterFactory, ObjectConstructorFactory { - private final static Unsafe theUnsafe; - static { - try { - Class unsafeClass = Class.forName("sun.misc.Unsafe"); - Field declaredField = unsafeClass.getDeclaredField("theUnsafe"); - declaredField.setAccessible(true); - theUnsafe = (Unsafe) declaredField.get(null); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - public Setter newSetter(final Field field) { - final Class type = field.getType(); - final boolean isStatic = Modifier.isStatic(field.getModifiers()); - - final long offset = isStatic - ? theUnsafe.staticFieldOffset(field) - : theUnsafe.objectFieldOffset(field); - - if (!Modifier.isVolatile(field.getModifiers())) { - if (type == Boolean.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putBoolean(obj, offset, (Boolean) value); - } - - public Class getType() { - return Boolean.TYPE; - } - }; - } - if (type == Character.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putChar(obj, offset, (Character) value); - } - - public Class getType() { - return Character.TYPE; - } - }; - } - if (type == Byte.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putByte(obj, offset, ((Number) value).byteValue()); - } - - public Class getType() { - return Byte.TYPE; - } - }; - } - if (type == Short.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putShort(obj, offset, ((Number) value).shortValue()); - } - - public Class getType() { - return Short.TYPE; - } - }; - } - if (type == Integer.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putInt(obj, offset, ((Number) value).intValue()); - } - - public Class getType() { - return Integer.TYPE; - } - }; - } - if (type == Long.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putLong(obj, offset, ((Number) value).longValue()); - } - - public Class getType() { - return Long.TYPE; - } - }; - } - if (type == Float.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putFloat(obj, offset, ((Number) value).floatValue()); - } - - public Class getType() { - return Float.TYPE; - } - }; - } - if (type == Double.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putDouble(obj, offset, ((Number) value).doubleValue()); - } - - public Class getType() { - return Double.TYPE; - } - }; - } - return new Setter() { - public void setProperty(Object obj, Object value) { - theUnsafe.putObject(obj, offset, value); - } - - public Class getType() { - return type; - } - }; - } - - if (type == Boolean.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putBooleanVolatile(obj, offset, (Boolean) value); - } - - public Class getType() { - return Boolean.TYPE; - } - }; - } - if (type == Character.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putCharVolatile(obj, offset, (Character) value); - } - - public Class getType() { - return Character.TYPE; - } - }; - } - if (type == Byte.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putByteVolatile(obj, offset, ((Number) value).byteValue()); - } - - public Class getType() { - return Byte.TYPE; - } - }; - } - if (type == Short.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putShortVolatile(obj, offset, ((Number) value).shortValue()); - } - - public Class getType() { - return Short.TYPE; - } - }; - } - if (type == Integer.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putIntVolatile(obj, offset, ((Number) value).intValue()); - } - - public Class getType() { - return Integer.TYPE; - } - }; - } - if (type == Long.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putLongVolatile(obj, offset, ((Number) value).longValue()); - } - - public Class getType() { - return Long.TYPE; - } - }; - } - if (type == Float.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putFloatVolatile(obj, offset, ((Number) value).floatValue()); - } - - public Class getType() { - return Float.TYPE; - } - }; - } - if (type == Double.TYPE) { - return new Setter() { - public void setProperty(Object obj, Object value) { - if (value == null) return; - theUnsafe.putDoubleVolatile(obj, offset, ((Number) value).doubleValue()); - } - - public Class getType() { - return Double.TYPE; - } - }; - } - return new Setter() { - public void setProperty(Object obj, Object value) { - theUnsafe.putObjectVolatile(obj, offset, value); - } - - public Class getType() { - return type; - } - }; - } - - public ObjectConstructor newConstructor(final Class clazz) { - return getConstructor(clazz); - } - public static ObjectConstructor getConstructor(final Class clazz) { - return new ObjectConstructor() { - public Object newInstance() { - try { - return theUnsafe.allocateInstance(clazz); - } catch (InstantiationException e) { - throw new Sql2oException("Could not create a new instance of class " + clazz, e); - } - } - }; - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/reflection/package-info.java b/blade-sql2o/src/main/java/org/sql2o/reflection/package-info.java deleted file mode 100644 index b3e497f59..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/reflection/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Provides the internal functionality used by sql2o to accomplish the automatic row to property mapping. - */ -package org.sql2o.reflection; \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/AbstractCache.java b/blade-sql2o/src/main/java/org/sql2o/tools/AbstractCache.java deleted file mode 100644 index 5319b802e..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/tools/AbstractCache.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.sql2o.tools; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * just inherit and implement evaluate - * User: dimzon - * Date: 4/6/14 - * Time: 10:35 PM - */ -public abstract class AbstractCache { - private final Map map; - private final Lock rl; - private final Lock wl; - /*** - * @param map - allows to define your own map implementation - */ - public AbstractCache(Map map) { - this.map = map; - ReadWriteLock rrwl = new ReentrantReadWriteLock(); - rl = rrwl.readLock(); - wl = rrwl.writeLock(); - } - - public AbstractCache(){ - this(new HashMap()); - } - - public V get(K key,E param){ - V value; - - try { - // let's take read lock first - rl.lock(); - value = map.get(key); - } finally { - rl.unlock(); - } - if(value!=null) return value; - - try { - wl.lock(); - value = map.get(key); - if(value==null){ - value = evaluate(key, param); - map.put(key,value); - } - } finally { - wl.unlock(); - } - return value; - } - - protected abstract V evaluate(K key, E param); - -} diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java b/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java deleted file mode 100644 index ccd5df08c..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/tools/FeatureDetector.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.sql2o.tools; - -import blade.kit.ReflectKit; - -/** - * Detects whether optional sql2o features are available. - * - * @author Alden Quimby - */ -public final class FeatureDetector { - - private FeatureDetector() - {} - - static { - setCacheUnderscoreToCamelcaseEnabled(true); // enabled by default - } - - private static Boolean jodaTimeAvailable; - private static Boolean oracleAvailable; - private static boolean cacheUnderscoreToCamelcaseEnabled; - - /** - * @return {@code true} if Joda-Time is available, {@code false} otherwise. - */ - public static boolean isJodaTimeAvailable() { - if (jodaTimeAvailable == null) { - jodaTimeAvailable = ReflectKit.isPresent("org.joda.time.DateTime"); - } - return jodaTimeAvailable; - } - - /** - * @return {@code true} if oracle.sql is available, {@code false} otherwise. - */ - public static boolean isOracleAvailable() { - if (oracleAvailable == null) { - oracleAvailable = ReflectKit.isPresent("oracle.sql.TIMESTAMP"); - } - return oracleAvailable; - } - - /** - * - * @return {@code true} if caching of underscore to camelcase is enabled. - */ - public static boolean isCacheUnderscoreToCamelcaseEnabled() { - return cacheUnderscoreToCamelcaseEnabled; - } - - /** - * Turn caching of underscore to camelcase on or off. - */ - public static void setCacheUnderscoreToCamelcaseEnabled(boolean cacheUnderscoreToCamelcaseEnabled) { - FeatureDetector.cacheUnderscoreToCamelcaseEnabled = cacheUnderscoreToCamelcaseEnabled; - } -} \ No newline at end of file diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java b/blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java deleted file mode 100644 index 76777af66..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/tools/UnderscoreToCamelCase.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.sql2o.tools; - -/** - * Takes a string formatted like: 'my_string_variable' and returns it as: 'myStringVariable' - * - * @author ryancarlson - * @author dimzon - complete rewrite - */ -public class UnderscoreToCamelCase { - public static String convert(String underscore){ - if(underscore==null || underscore.isEmpty()) return underscore; - return convert00(underscore); - } - - private static String convert00(String underscore){ - char[] chars = underscore.toCharArray(); - int write=-1,len=chars.length; - boolean upper=false; - for (int read = 0; read < len; ++read) { - char c = chars[read]; - if('_'==c){ - upper = true; - continue; - } - if(upper){ - upper = false; - chars[++write]=Character.toUpperCase(c); - } else { - chars[++write]=Character.toLowerCase(c); - } - } - return new String(chars, 0, ++write); - } -} diff --git a/blade-sql2o/src/main/java/org/sql2o/tools/package-info.java b/blade-sql2o/src/main/java/org/sql2o/tools/package-info.java deleted file mode 100644 index 4c2218e1a..000000000 --- a/blade-sql2o/src/main/java/org/sql2o/tools/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * internal tools. - */ -package org.sql2o.tools; \ No newline at end of file From 763fe1f97a383bf4b70079e3d4edb9cb08692f77 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 6 Sep 2015 13:13:29 +0800 Subject: [PATCH 128/545] optimized code --- LAST_VERSION.md | 6 +- README.md | 2 +- README_CN.md | 2 +- UPDATE_LOG.md | 5 +- blade-core/src/main/java/blade/Blade.java | 16 ++ .../src/main/java/blade/BladeFilter.java | 5 +- .../src/main/java/blade/BladeWebContext.java | 5 + .../src/main/java/blade/IocApplication.java | 20 +- .../src/main/java/blade/plugin/Plugin.java | 4 + blade-sql2o/pom.xml | 13 +- .../main/java/blade/plugin/sql2o/Model.java | 172 ++++++++++++++---- .../java/blade/plugin/sql2o/Sql2oPlugin.java | 55 ++++-- .../blade/plugin/sql2o/cache/CacheType.java | 7 + .../plugin/sql2o/cache/SimpleSql2oCache.java | 53 ++---- .../blade/plugin/sql2o/cache/Sql2oCache.java | 16 +- .../plugin/sql2o/ds/DataSourceManager.java | 3 +- pom.xml | 2 +- 17 files changed, 265 insertions(+), 121 deletions(-) create mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/cache/CacheType.java diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 5577466e0..9b22a79f1 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.9-alpha +    1.2.9 ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -22,7 +22,7 @@     com.bladejava     blade-sql2o -    1.2.8-beta +    1.2.8 ``` @@ -58,7 +58,7 @@     com.bladejava     blade-cache -    1.2.2 +    1.2.3 ``` diff --git a/README.md b/README.md index dac7d76e1..002e2ce1b 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.9-alpha + 1.2.9 ``` diff --git a/README_CN.md b/README_CN.md index 6384e6e7b..bd4350e01 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,7 +33,7 @@ com.bladejava blade-core - 1.2.9-alpha + 1.2.9 ``` diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index f81cd3a91..0a3b984b0 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,8 +1,9 @@ #Blade 更新日志 ### v1.2.9 - 1. 添加数据库连接池 - 2. 优化路由配置 + 1. 优化路由配置 + 2. 优化数据库缓存操作 + 3. 添加插件释放资源 ### v1.2.8 1. 优化500页面,错误在后台显示 diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index 76dd8106f..248be665c 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -24,6 +24,7 @@ import blade.kit.IOKit; import blade.kit.PropertyKit; import blade.kit.json.JSONKit; +import blade.plugin.Plugin; import blade.render.Render; import blade.render.RenderFactory; import blade.route.HttpMethod; @@ -538,4 +539,19 @@ public static String[] staticFolder(){ public static Bootstrap bootstrap(){ return bootstrap; } + + /** + * 返回插件对象 + * @param pluginClazz 插件class + * @return + */ + @SuppressWarnings("unchecked") + public static T plugin(Class pluginClazz){ + Object object = IocApplication.getPlugin(pluginClazz); + if(null == object){ + object = IocApplication.registerPlugin(pluginClazz); + } + return (T) object; + } + } diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java index d478b1974..6fbfe8a4c 100644 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ b/blade-core/src/main/java/blade/BladeFilter.java @@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import blade.kit.TaskKit; import blade.kit.log.Logger; import blade.route.RouteMatcherBuilder; @@ -122,8 +123,10 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha @Override public void destroy() { - IocApplication.destroy(); LOGGER.info("blade destroy!"); + BladeWebContext.remove(); + IocApplication.destroy(); + TaskKit.depose(); } } \ No newline at end of file diff --git a/blade-core/src/main/java/blade/BladeWebContext.java b/blade-core/src/main/java/blade/BladeWebContext.java index 51f79ea1f..834e3f827 100644 --- a/blade-core/src/main/java/blade/BladeWebContext.java +++ b/blade-core/src/main/java/blade/BladeWebContext.java @@ -136,4 +136,9 @@ public static void remove(){ currentResponse.remove(); } + public static void destroy(){ + remove(); + currentRequest = null; + currentResponse = null; + } } \ No newline at end of file diff --git a/blade-core/src/main/java/blade/IocApplication.java b/blade-core/src/main/java/blade/IocApplication.java index e99402766..455984c72 100644 --- a/blade-core/src/main/java/blade/IocApplication.java +++ b/blade-core/src/main/java/blade/IocApplication.java @@ -26,6 +26,7 @@ import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; +import blade.plugin.Plugin; import blade.route.RouteBase; /** @@ -51,6 +52,8 @@ public final class IocApplication { */ static final ClassReader classReader = new ClassPathClassReader(); + static final List PLUGINS = CollectionKit.newArrayList(); + /** * 存放路由类 */ @@ -80,6 +83,7 @@ public static void init(){ } catch (Exception e) { LOGGER.error(e); } + } /** @@ -96,6 +100,18 @@ private static void initIOC() { } } + @SuppressWarnings("unchecked") + public static T registerPlugin(Class pluginClazz){ + Object object = container.registBean(pluginClazz); + T plugin = (T) object; + PLUGINS.add(plugin); + return plugin; + } + + public static T getPlugin(Class pluginClazz){ + return container.getBean(pluginClazz, Scope.SINGLE); + } + public static void addRouteClass(Class clazz){ ROUTE_CLASS_LIST.add(clazz); } @@ -129,6 +145,8 @@ private static void registerBean(String packageName) { public static void destroy() { // 清空ioc容器 container.removeAll(); + for(Plugin plugin : PLUGINS){ + plugin.destroy(); + } } - } \ No newline at end of file diff --git a/blade-core/src/main/java/blade/plugin/Plugin.java b/blade-core/src/main/java/blade/plugin/Plugin.java index c194a60b4..c5bdf05d7 100644 --- a/blade-core/src/main/java/blade/plugin/Plugin.java +++ b/blade-core/src/main/java/blade/plugin/Plugin.java @@ -28,4 +28,8 @@ public interface Plugin { */ void run(); + /** + * 销毁,释放资源 + */ + void destroy(); } diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 026f2b926..a6c4007a7 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - 1.2.8-alpha + 1.2.8 blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o @@ -20,19 +20,18 @@ com.bladejava blade-core ${blade.version} - compile + provided com.bladejava blade-cache - 1.2.2 + 1.2.3 true - joda-time - joda-time - 2.8.2 - true + org.sql2o + sql2o + 1.5.4 diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index b3867777c..242e93dd3 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -11,10 +11,12 @@ import org.sql2o.Query; import org.sql2o.Sql2o; +import blade.Blade; import blade.kit.EncrypKit; import blade.kit.StringKit; import blade.kit.log.Logger; import blade.plugin.sql2o.Condition.DmlType; +import blade.plugin.sql2o.cache.CacheType; import blade.plugin.sql2o.cache.Sql2oCache; import blade.plugin.sql2o.cache.Sql2oCacheFactory; import blade.plugin.sql2o.ds.DataSourceManager; @@ -39,6 +41,8 @@ public class Model { */ private Sql2o sql2o = DataSourceManager.me().getSql2o(); + private static final Sql2oPlugin SQL2O_PLUGIN = Blade.plugin(Sql2oPlugin.class); + /** * 当前class实例 */ @@ -62,14 +66,18 @@ public class Model { private String CACHE_KEY_LIST; private String CACHE_KEY_COUNT; private String CACHE_KEY_DETAIL; + // 自定义sql + private String CACHE_KEY_SQL_LIST; + private String CACHE_KEY_SQL_COUNT; + private String CACHE_KEY_SQL_DETAIL; public Model(Class clazz) { this.model = clazz; this.condition = new Condition(table(), pk()); - CACHE_KEY_LIST = model.getName() + ":list"; - CACHE_KEY_COUNT = model.getName() + ":count"; - CACHE_KEY_DETAIL = model.getName() + ":detail"; + CACHE_KEY_LIST = model.getName() + ":" + CacheType.list.toString(); + CACHE_KEY_COUNT = model.getName() + ":" + CacheType.count.toString(); + CACHE_KEY_DETAIL = model.getName() + ":" + CacheType.detail.toString(); } public Sql2o getSql2o(){ @@ -97,7 +105,7 @@ private boolean isCache(){ if(this.queryIsOpen){ return true; } - return Sql2oPlugin.INSTANCE.isOpenCache() && model.getAnnotation(Table.class).isCache() && this.cache; + return SQL2O_PLUGIN.isOpenCache() && model.getAnnotation(Table.class).isCache() && this.cache; } /** @@ -120,7 +128,7 @@ public Model cache(boolean cache){ */ private void init(){ this.queryIsOpen = false; - this.cache = Sql2oPlugin.INSTANCE.isOpenCache(); + this.cache = SQL2O_PLUGIN.isOpenCache(); if(null == this.sql2o){ this.sql2o = DataSourceManager.me().getSql2o(); } @@ -136,7 +144,7 @@ public Model select(){ } public boolean isOpenCache() { - return Sql2oPlugin.INSTANCE.isOpenCache(); + return SQL2O_PLUGIN.isOpenCache(); } /** @@ -147,6 +155,8 @@ public boolean isOpenCache() { */ public Model select(String sql){ init(); + CACHE_KEY_SQL_LIST = model.getName() + ":" + CacheType.sqllist.toString(); + CACHE_KEY_SQL_DETAIL = model.getName() + ":" + CacheType.sqldetail.toString(); condition.select(sql); return this; } @@ -168,6 +178,7 @@ public Model count(){ */ public Model count(String sql){ init(); + CACHE_KEY_SQL_COUNT = model.getName() + ":" + CacheType.sqlcount.toString(); condition.count(sql); return this; } @@ -538,7 +549,7 @@ public long fetchCount(){ } return count; } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -561,7 +572,8 @@ private Long getPageCount(){ String cacheSql = getCacheCountKey(); field = EncrypKit.md5(cacheSql); - count = sql2oCache.hgetV(CACHE_KEY_COUNT, field); + String key = (null == CACHE_KEY_COUNT) ? CACHE_KEY_SQL_COUNT : CACHE_KEY_COUNT; + count = sql2oCache.hgetV(key, field); if(null != count){ return count; } @@ -587,10 +599,11 @@ private Long getPageCount(){ count = query.executeScalar(Long.class); // 是否开启缓存查询 if(isCache()){ - sql2oCache.hsetV(CACHE_KEY_COUNT, field, count); + String key = (null == CACHE_KEY_COUNT) ? CACHE_KEY_SQL_COUNT : CACHE_KEY_COUNT; + sql2oCache.hsetV(key, field, count); } } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -616,8 +629,8 @@ public T fetchOne(){ // 是否开启缓存查询 if(isCache()){ field = EncrypKit.md5(getCacheKey(null)); - - res = sql2oCache.hget(CACHE_KEY_DETAIL, field); + String key = (null == CACHE_KEY_SQL_DETAIL) ? CACHE_KEY_DETAIL : CACHE_KEY_SQL_DETAIL; + res = sql2oCache.hget(key, field); if(null != res){ return res; } @@ -636,11 +649,12 @@ public T fetchOne(){ // 重新放入缓存 if(isCache() && null != res){ - sql2oCache.hset(CACHE_KEY_DETAIL, field, res); + String key = (null == CACHE_KEY_SQL_DETAIL) ? CACHE_KEY_DETAIL : CACHE_KEY_SQL_DETAIL; + sql2oCache.hset(key, field, res); } return res; } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -650,6 +664,69 @@ public T fetchOne(){ return null; } + /** + * 刷新缓存 + */ + public void cleanCache(CacheType cacheType){ + if(null != cacheType){ + String key = model.getName() + ":" + cacheType; + sql2oCache.hdel(key); + } + } + + /** + * 刷新缓存 + */ + public void cleanCache(CacheType cacheType, Class modelClazz){ + if(null != cacheType && null != modelClazz){ + String key = modelClazz.getName() + ":" + cacheType; + sql2oCache.hdel(key); + } + } + + /** + * 刷新缓存 + */ + public void cleanAll(){ + + LOGGER.debug("更新缓存:" + model.getName() + " -> count,list,detail,sqlcount,sqllist,sqldetail"); + sql2oCache.hdel(CACHE_KEY_COUNT); + sql2oCache.hdel(CACHE_KEY_LIST); + sql2oCache.hdel(CACHE_KEY_DETAIL); + + String countkey = model.getName() + ":" + CacheType.sqlcount.toString(); + String listkey = model.getName() + ":" + CacheType.sqllist.toString(); + String detailkey = model.getName() + ":" + CacheType.sqldetail.toString(); + + sql2oCache.hdel(countkey); + sql2oCache.hdel(listkey); + sql2oCache.hdel(detailkey); + } + + /** + * 刷新缓存 + */ + public void cleanAll(Class modelClazz){ + + LOGGER.debug("更新缓存:" + modelClazz.getName() + " -> count,list,detail,sqlcount,sqllist,sqldetail"); + + String countkey = modelClazz.getName() + ":" + CacheType.count.toString(); + String listkey = modelClazz.getName() + ":" + CacheType.list.toString(); + String detailkey = modelClazz.getName() + ":" + CacheType.detail.toString(); + + String sqlcountkey = modelClazz.getName() + ":" + CacheType.sqlcount.toString(); + String sqllistkey = modelClazz.getName() + ":" + CacheType.sqllist.toString(); + String sqldetailkey = modelClazz.getName() + ":" + CacheType.sqldetail.toString(); + + sql2oCache.hdel(countkey); + sql2oCache.hdel(listkey); + sql2oCache.hdel(detailkey); + + sql2oCache.hdel(sqlcountkey); + sql2oCache.hdel(sqllistkey); + sql2oCache.hdel(sqldetailkey); + } + /** * @return 返回查询一个对象 */ @@ -666,7 +743,9 @@ public Map fetchMap(){ if(isCache()){ field = EncrypKit.md5(getCacheKey(null)); - res = sql2oCache.hgetV(CACHE_KEY_DETAIL, field); + String key = (null == CACHE_KEY_SQL_DETAIL) ? CACHE_KEY_DETAIL : CACHE_KEY_SQL_DETAIL; + + res = sql2oCache.hgetV(key, field); if(null != res){ return res; } @@ -693,11 +772,12 @@ public Map fetchMap(){ // 重新放入缓存 if(isCache() && null != res){ - sql2oCache.hsetV(CACHE_KEY_DETAIL, field, res); + String key = (null == CACHE_KEY_SQL_DETAIL) ? CACHE_KEY_DETAIL : CACHE_KEY_SQL_DETAIL; + sql2oCache.hsetV(key, field, res); } return res; } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -717,9 +797,9 @@ public T fetchByPk(Serializable pk){ String field = null; // 启用缓存 if(isCache()){ - field = EncrypKit.md5(getCacheKey(null)); - res = sql2oCache.hget(CACHE_KEY_DETAIL, field); + String key = (null == CACHE_KEY_SQL_DETAIL) ? CACHE_KEY_DETAIL : CACHE_KEY_SQL_DETAIL; + res = sql2oCache.hget(key, field); if(null != res){ return res; } @@ -738,10 +818,11 @@ public T fetchByPk(Serializable pk){ res = (T) query.executeAndFetchFirst(this.model); if(isCache() && null != res){ - sql2oCache.hset(CACHE_KEY_DETAIL, field, res); + String key = (null == CACHE_KEY_SQL_DETAIL) ? CACHE_KEY_DETAIL : CACHE_KEY_SQL_DETAIL; + sql2oCache.hset(key, field, res); } } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -771,7 +852,7 @@ public M fetchColum(){ return (M) query.executeScalar(); } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -794,7 +875,8 @@ public List fetchList(){ // 开启缓存 if(isCache()){ field = EncrypKit.md5(getCacheKey(null)); - result = (List) sql2oCache.hgetlist(CACHE_KEY_LIST, field); + String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; + result = (List) sql2oCache.hgetlist(key, field); if(null != result){ return result; } @@ -819,11 +901,12 @@ public List fetchList(){ result = (List) query.executeAndFetch(this.model); if(isCache() && null != result){ - sql2oCache.hsetlist(CACHE_KEY_LIST, field, result); + String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; + sql2oCache.hsetlist(key, field, result); } return result; } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -846,7 +929,8 @@ public List executeAndFetch(Class clazz){ // 开启缓存 if(isCache()){ field = EncrypKit.md5(getCacheKey(null)); - result = sql2oCache.hgetlists(CACHE_KEY_LIST, field); + String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; + result = sql2oCache.hgetlists(key, field); if(null != result){ return result; } @@ -871,11 +955,12 @@ public List executeAndFetch(Class clazz){ result = query.executeAndFetch(clazz); if(isCache() && null != result){ - sql2oCache.hsetlists(CACHE_KEY_LIST, field, result); + String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; + sql2oCache.hsetlists(key, field, result); } return result; } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -898,7 +983,8 @@ public List> fetchListMap(){ // 开启缓存 if(isCache()){ field = EncrypKit.md5(getCacheKey(null)); - result = sql2oCache.hgetlistmap(CACHE_KEY_LIST, field); + String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; + result = sql2oCache.hgetlistmap(key, field); if(null != result){ return result; } @@ -923,12 +1009,13 @@ public List> fetchListMap(){ result = query.executeAndFetchTable().asList(); if(isCache() && null != result){ - sql2oCache.hsetlistmap(CACHE_KEY_LIST, field, result); + String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; + sql2oCache.hsetlistmap(key, field, result); } return result; } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -971,7 +1058,9 @@ public Page fetchPage(Integer page, Integer pageSize){ cacheSql = cacheSql.replaceAll("\\s", ""); field = EncrypKit.md5(cacheSql); - results = sql2oCache.hgetlist(CACHE_KEY_LIST, field); + String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; + + results = sql2oCache.hgetlist(key, field); pageModel = new Page(totalCount, page, pageSize); @@ -1007,14 +1096,15 @@ public Page fetchPage(Integer page, Integer pageSize){ if(null != results && results.size() > 0){ if(isCache()){ - sql2oCache.hsetlist(CACHE_KEY_LIST, field, results); + String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; + sql2oCache.hsetlist(key, field, results); } pageModel.setResults((List) results); } return pageModel; } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -1055,11 +1145,14 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ List> results = null; // 开启缓存 if(isCache()){ + String cacheSql = getCacheKey(null) + "limit"+ (page - 1) +"," + pageSize; cacheSql = cacheSql.replaceAll("\\s", ""); field = EncrypKit.md5(cacheSql); - results = sql2oCache.hgetlistmap(CACHE_KEY_LIST, field); + String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; + + results = sql2oCache.hgetlistmap(key, field); if(null != results && results.size() > 0){ pageMap = new Page>(totalCount, page, pageSize); @@ -1095,13 +1188,14 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ if(null != results && results.size() > 0){ if(isCache()){ - sql2oCache.hsetlistmap(CACHE_KEY_LIST, field, results); + String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; + sql2oCache.hsetlistmap(key, field, results); } pageMap.setResults(results); } } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != conn){ conn.close(); @@ -1196,7 +1290,7 @@ public V executeAndCommit(Class returnType) { condition.clearMap(); return key; } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } finally{ if(null != query){ query.close(); @@ -1247,7 +1341,7 @@ public Connection execute(Connection connection){ return query.getConnection(); } } catch (Exception e) { - LOGGER.error(e); + e.printStackTrace(); } return null; } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index 01df0463d..89014e7af 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -1,14 +1,18 @@ package blade.plugin.sql2o; +import java.sql.DriverManager; import java.util.Properties; import javax.sql.DataSource; import blade.Blade; +import blade.cache.CacheException; import blade.kit.PropertyKit; import blade.kit.StringKit; import blade.kit.log.Logger; import blade.plugin.Plugin; +import blade.plugin.sql2o.cache.Sql2oCache; +import blade.plugin.sql2o.cache.Sql2oCacheFactory; import blade.plugin.sql2o.ds.DataSourceManager; /** @@ -17,9 +21,7 @@ * @author biezhi * @since 1.0 */ -public enum Sql2oPlugin implements Plugin { - - INSTANCE; +public class Sql2oPlugin implements Plugin { private Logger LOGGER = Logger.getLogger(Sql2oPlugin.class); @@ -27,7 +29,7 @@ public enum Sql2oPlugin implements Plugin { private boolean isOpenCache = false; - private Sql2oPlugin() { + public Sql2oPlugin() { } /** @@ -44,30 +46,30 @@ public Sql2oPlugin load(String filePath){ String password = configProperties.getProperty(Constant.PASSWORD); String openCache = configProperties.getProperty(Constant.OPEN_CACHE); - if(null == INSTANCE.dbConfig){ - INSTANCE.dbConfig = new DBConfig(); + if(null == dbConfig){ + dbConfig = new DBConfig(); } if(StringKit.isNotBlank(drive)){ - INSTANCE.dbConfig.setDriverName(drive); + dbConfig.setDriverName(drive); } if(StringKit.isNotBlank(url)){ - INSTANCE.dbConfig.setUrl(url); + dbConfig.setUrl(url); } if(StringKit.isNotBlank(username)){ - INSTANCE.dbConfig.setUserName(username); + dbConfig.setUserName(username); } if(StringKit.isNotBlank(password)){ - INSTANCE.dbConfig.setPassWord(password); + dbConfig.setPassWord(password); } if(StringKit.isNotBlank(openCache)){ isOpenCache = Boolean.valueOf(openCache.trim()); } - return INSTANCE; + return this; } /** @@ -76,8 +78,8 @@ public Sql2oPlugin load(String filePath){ * @param dbConfig 数据库配置 */ public Sql2oPlugin config(DBConfig dbConfig){ - INSTANCE.dbConfig = dbConfig; - return INSTANCE; + this.dbConfig = dbConfig; + return this; } /** @@ -90,12 +92,12 @@ public Sql2oPlugin config(DataSource dataSource){ isOpenCache = Boolean.valueOf(opencache); } DataSourceManager.me().setDataSource(dataSource); - return INSTANCE; + return this; } public Sql2oPlugin openCache(){ isOpenCache = true; - return INSTANCE; + return this; } /** @@ -119,7 +121,7 @@ public Sql2oPlugin config(String driver, String url, String user, String pass){ dbConfig.setUrl(url); dbConfig.setUserName(user); dbConfig.setPassWord(pass); - return INSTANCE; + return this; } public boolean isOpenCache() { @@ -142,4 +144,25 @@ public void run() { } } + @Override + public void destroy() { + + LOGGER.debug("sql2o destroy!"); + + // 卸载数据库驱动 + try { + DriverManager.deregisterDriver(DriverManager.getDrivers().nextElement()); + // 清理缓存处理线程 + if(isOpenCache){ + Sql2oCache sql2oCache = Sql2oCacheFactory.getSql2oCache(); + sql2oCache.destroy(); + } + } catch (CacheException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/CacheType.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/CacheType.java new file mode 100644 index 000000000..ed6b2b0f9 --- /dev/null +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/CacheType.java @@ -0,0 +1,7 @@ +package blade.plugin.sql2o.cache; + +public enum CacheType { + + list, count, detail, sqllist, sqlcount, sqldetail + +} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java index e1fa2edfd..3275c1727 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java @@ -3,14 +3,18 @@ import java.io.Serializable; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutionException; import blade.cache.Cache; +import blade.cache.CacheException; import blade.cache.CacheManager; @SuppressWarnings("unchecked") public class SimpleSql2oCache implements Sql2oCache { - private CacheManager cm = CacheManager.getInstance(); + private CacheManager cm = CacheManager.me(); + + private static final String CACHE_ID = "sql2o_cache"; private Cache cache; @@ -19,42 +23,13 @@ public SimpleSql2oCache() { long cleanTime = 1000 * 3600 * 300; cm.setCleanInterval(cleanTime); // 存放1000个缓存,超过即自动清除 - cache = cm.newLRUCache("sql2o_cache").cacheSize(1000); + cache = cm.newLRUCache(CACHE_ID).cacheSize(1000); } - @Override - public void set(String key, Serializable value) { - cache.set(key, value); - } - - @Override - public void set(String key, Serializable value, long expire) { - cache.set(key, value, expire); - } - @Override public void hset(String key, String field, Serializable value) { cache.hset(key, field, value); } - - @Override - public void hset(String key, String field, Serializable value, long expire) { - cache.hset(key, field, value, expire); - } - - @Override - public void hset(String key, String field, List value, long expire) { - cache.hset(key, field, value, expire); - } - - @Override - public Serializable get(String key) { - Object value = cache.get(key); - if(null != value){ - return (Serializable) value; - } - return null; - } @Override public V hgetV(String key, String field) { @@ -112,11 +87,6 @@ public void hdel(String key) { cache.hdel(key); } - @Override - public void hdel(String key, String field) { - cache.del(key, field); - } - @Override public void hsetlist(String key, String field, List value) { cache.hset(key, field, value); @@ -137,4 +107,15 @@ public void clean() { cache.clear(); } + @Override + public void destroy() throws CacheException { + try { + CacheManager.me().destroy(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java index 696d6cfbb..7e4afb8b5 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java @@ -4,12 +4,10 @@ import java.util.List; import java.util.Map; +import blade.cache.CacheException; + public interface Sql2oCache { - void set(String key, Serializable value); - - void set(String key, Serializable value, long expire); - void hset(String key, String field, Serializable value); void hsetV(String key, String field, Object value); @@ -20,12 +18,6 @@ public interface Sql2oCache { void hsetlists(String key, String field, List value); - void hset(String key, String field, Serializable value, long expire); - - void hset(String key, String field, List value, long expire); - - Serializable get(String key); - T hget(String key, String field); V hgetV(String key, String field); @@ -38,7 +30,7 @@ public interface Sql2oCache { void hdel(String key); - void hdel(String key, String field); - void clean(); + + void destroy() throws CacheException; } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java index 8a805b4c7..6df231dbc 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java @@ -4,6 +4,7 @@ import org.sql2o.Sql2o; +import blade.Blade; import blade.plugin.sql2o.DBConfig; import blade.plugin.sql2o.Sql2oPlugin; import blade.plugin.sql2o.exception.DataSourceException; @@ -32,7 +33,7 @@ public void run(){ if(null != this.dataSource){ sql2o = new Sql2o(this.dataSource); } else { - DBConfig dbConfig = Sql2oPlugin.INSTANCE.dbConfig(); + DBConfig dbConfig = Blade.plugin(Sql2oPlugin.class).dbConfig(); if(null == dbConfig){ throw new DataSourceException("数据库配置失败"); } diff --git a/pom.xml b/pom.xml index 83387955f..c78bbdaa1 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.9-alpha + 1.2.9 From f5cf50edd1f2ec2c62ee7c4204d49d283dd406d4 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 6 Sep 2015 13:34:40 +0800 Subject: [PATCH 129/545] optimized code --- LAST_VERSION.md | 2 +- README.md | 2 +- README_CN.md | 2 +- blade-core/src/main/java/blade/Blade.java | 2 +- blade-core/src/main/java/blade/RequestHandler.java | 1 + .../main/java/blade/plugin/sql2o/Sql2oPlugin.java | 12 ++++++++---- pom.xml | 2 +- 7 files changed, 14 insertions(+), 9 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 9b22a79f1..004fc616a 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.9 +    1.2.9-beta ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/README.md b/README.md index 002e2ce1b..c2e8fef4a 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ First. Use maven to build a webapp, join dependency on the blade,Recommended for com.bladejava blade-core - 1.2.9 + 1.2.9-beta ``` diff --git a/README_CN.md b/README_CN.md index bd4350e01..32d7b6bd8 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,7 +33,7 @@ com.bladejava blade-core - 1.2.9 + 1.2.9-beta ``` diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index 248be665c..1d3581c50 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -40,7 +40,7 @@ */ public final class Blade { - public static final String VERSION = "1.2.9-alpha"; + public static final String VERSION = "1.2.9-beta"; /** * 框架是否已经初始化 */ diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 2e6a2f441..2b4101157 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -317,6 +317,7 @@ private Object[] getArgs(Request request, Response response, Class[] params){ */ private Object executeMethod(Object object, Method method, RequestWrapper requestWrapper, ResponseWrapper responseWrapper){ int len = method.getParameterTypes().length; + method.setAccessible(true); if(len > 0){ Object[] args = getArgs(requestWrapper, responseWrapper, method.getParameterTypes()); return ReflectKit.invokeMehod(object, method, args); diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index 89014e7af..f695bf7a5 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -1,6 +1,8 @@ package blade.plugin.sql2o; +import java.sql.Driver; import java.sql.DriverManager; +import java.util.Enumeration; import java.util.Properties; import javax.sql.DataSource; @@ -134,13 +136,12 @@ public DBConfig dbConfig(){ @Override public void run() { - DataSourceManager.me().run(); DataSource dataSource = DataSourceManager.me().getDataSource(); if(null == dataSource){ - LOGGER.error("数据库插件配置失败"); + LOGGER.error("blade sql2o config fail!"); } else { - LOGGER.debug("数据库插件配置成功..."); + LOGGER.debug("blade sql2o config success!"); } } @@ -151,7 +152,10 @@ public void destroy() { // 卸载数据库驱动 try { - DriverManager.deregisterDriver(DriverManager.getDrivers().nextElement()); + Enumeration em = DriverManager.getDrivers(); + if(null != em && em.hasMoreElements()){ + DriverManager.deregisterDriver(em.nextElement()); + } // 清理缓存处理线程 if(isOpenCache){ Sql2oCache sql2oCache = Sql2oCacheFactory.getSql2oCache(); diff --git a/pom.xml b/pom.xml index c78bbdaa1..e465a4f20 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.9 + 1.2.9-beta From b7599fd53890dec41c82ea05a203fd9a2bbc1707 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 6 Sep 2015 13:50:10 +0800 Subject: [PATCH 130/545] add set cache method --- .../src/main/java/blade/plugin/sql2o/Sql2oPlugin.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index f695bf7a5..7eeb3a714 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -168,5 +168,10 @@ public void destroy() { } } + + public Sql2oPlugin cache(Boolean cache) { + this.isOpenCache = cache; + return this; + } } From a8b159a700f18046c5458eff33addd525de5156e Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 7 Sep 2015 17:47:39 +0800 Subject: [PATCH 131/545] multiple routing --- README.md | 55 +----- README_CN.md | 57 +------ UPDATE_LOG.md | 1 + blade-core/src/main/java/blade/Blade.java | 160 +++++++++++++++--- .../java/blade/route/DefaultRouteMatcher.java | 61 +------ .../main/java/blade/route/RouteMatcher.java | 74 +++++--- .../main/java/blade/plugin/sql2o/Model.java | 10 +- pom.xml | 2 +- 8 files changed, 217 insertions(+), 203 deletions(-) diff --git a/README.md b/README.md index c2e8fef4a..6c6606d16 100644 --- a/README.md +++ b/README.md @@ -76,54 +76,15 @@ public class App extends Bootstrap{ return "get"; } }); - } - -} -``` - -#### Functional router -```java -public class SayHi { - - public String hello(Request request, Response response){ - System.out.println("come hello~"); - request.attribute("name", "rose baby"); - return "hi"; - } -} -``` - -#### Annotations router -```java -@Path("/") -public class Hello { - - @Route("hello") - public String hello() { - System.out.println("hello"); - return "hello.jsp"; - } - - @Route(value = "post", method = HttpMethod.POST) - public void post(Request request) { - String name = request.query("name"); - System.out.println("name = " + name); - } - - @Route("users/:name") - public ModelAndView users(Request request, Response response) { - System.out.println("users"); - String name = request.pathParam(":name"); - ModelAndView modelAndView = new ModelAndView("users"); - modelAndView.add("name", name); - return modelAndView; - } - - @Route("index") - public String index(Request request) { - request.attribute("name", "jack"); - return "index.jsp"; + // multiple routing + Blade.get("/", "/index").run(new Router() { + @Override + public String handler(Request request, Response response) { + System.out.println("come index!!"); + return "index"; + } + }); } } diff --git a/README_CN.md b/README_CN.md index 32d7b6bd8..3053e5884 100644 --- a/README_CN.md +++ b/README_CN.md @@ -63,7 +63,7 @@ public class App extends Bootstrap{ @Override public void init() { // 注册函数式路由 - Blade.regRoute("/hello", SayHi.class, "hello"); + Blade.register("/hello", SayHi.class, "hello"); // 匿名路由,java8方式更简化 Blade.get("/get", new Router() { @@ -74,55 +74,16 @@ public class App extends Bootstrap{ return "get"; } }); - } -} -``` - -#### 函数式路由 -```java -public class SayHi { - - public String hello(Request request, Response response){ - System.out.println("进入hello~"); - request.attribute("name", "rose baby"); - return "hi"; - } -} -``` - -#### 注解路由 -```java -@Path("/") -public class Hello { - - @Route("hello") - public String hello() { - System.out.println("hello"); - return "hello.jsp"; - } - - @Route(value = "post", method = HttpMethod.POST) - public void post(Request request) { - String name = request.query("name"); - System.out.println("name = " + name); - } - - @Route("users/:name") - public ModelAndView users(Request request, Response response) { - System.out.println("users"); - String name = request.pathParam(":name"); - ModelAndView modelAndView = new ModelAndView("users"); - modelAndView.add("name", name); - return modelAndView; - } - - @Route("index") - public String index(Request request) { - request.attribute("name", "jack"); - return "index.jsp"; + // 多个路由 + Blade.get("/", "/index").run(new Router() { + @Override + public String handler(Request request, Response response) { + System.out.println("进入index!!"); + return "index"; + } + }); } - } ``` diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 0a3b984b0..213d4cde0 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -4,6 +4,7 @@ 1. 优化路由配置 2. 优化数据库缓存操作 3. 添加插件释放资源 + 4. 支持多路由配置 ### v1.2.8 1. 优化500页面,错误在后台显示 diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index 1d3581c50..0e11b3006 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -31,6 +31,7 @@ import blade.route.RouteBase; import blade.route.RouteMatcherBuilder; import blade.route.Router; +import blade.route.RouterExecutor; /** * Blade Core Class @@ -40,7 +41,7 @@ */ public final class Blade { - public static final String VERSION = "1.2.9-beta"; + public static final String VERSION = "1.2.9"; /** * 框架是否已经初始化 */ @@ -294,7 +295,7 @@ public static synchronized void load(Class route){ * @param clazz 路由处理类 * @param methodName 路由处理方法名称 */ - public static synchronized void regRoute(String path, Class clazz, String methodName){ + public static synchronized void register(String path, Class clazz, String methodName){ RouteMatcherBuilder.buildFunctional(path, clazz, methodName, null); } @@ -305,7 +306,7 @@ public static synchronized void regRoute(String path, Class clazz, String met * @param methodName 路由处理方法名称 * @param httpMethod 请求类型,GET/POST */ - public static synchronized void regRoute(String path, Class clazz, String methodName, HttpMethod httpMethod){ + public static synchronized void register(String path, Class clazz, String methodName, HttpMethod httpMethod){ RouteMatcherBuilder.buildFunctional(path, clazz, methodName, httpMethod); } @@ -314,8 +315,19 @@ public static synchronized void regRoute(String path, Class clazz, String met * @param path * @param routeHandler */ - public static synchronized void get(String path, Router routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.GET); + public static synchronized void get(String path, Router router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.GET); + } + + /** + * get请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor get(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.GET); + } + return null; } /** @@ -323,8 +335,19 @@ public static synchronized void get(String path, Router routeHandler){ * @param path * @param routeHandler */ - public static synchronized void post(String path, Router routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.POST); + public static synchronized void post(String path, Router router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.POST); + } + + /** + * post请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor post(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.POST); + } + return null; } /** @@ -332,17 +355,38 @@ public static synchronized void post(String path, Router routeHandler){ * @param path * @param routeHandler */ - public static synchronized void delete(String path, Router routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.DELETE); + public static synchronized void delete(String path, Router router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.DELETE); + } + + /** + * delete请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor delete(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.DELETE); + } + return null; } /** * put请求 - * @param path - * @param routeHandler + * @param paths */ - public static synchronized void put(String path, Router routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.PUT); + public static synchronized void put(String path, Router router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PUT); + } + + /** + * put请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor put(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.PUT); + } + return null; } /** @@ -350,8 +394,19 @@ public static synchronized void put(String path, Router routeHandler){ * @param path * @param routeHandler */ - public static synchronized void patch(String path, Router routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.PATCH); + public static synchronized void patch(String path, Router router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PATCH); + } + + /** + * patch请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor patch(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.PATCH); + } + return null; } /** @@ -359,8 +414,19 @@ public static synchronized void patch(String path, Router routeHandler){ * @param path * @param routeHandler */ - public static synchronized void head(String path, Router routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.HEAD); + public static synchronized void head(String path, Router router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.HEAD); + } + + /** + * head请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor head(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.HEAD); + } + return null; } /** @@ -368,8 +434,19 @@ public static synchronized void head(String path, Router routeHandler){ * @param path * @param routeHandler */ - public static synchronized void trace(String path, Router routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.TRACE); + public static synchronized void trace(String path, Router router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.TRACE); + } + + /** + * trace请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor trace(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.TRACE); + } + return null; } /** @@ -377,8 +454,19 @@ public static synchronized void trace(String path, Router routeHandler){ * @param path * @param routeHandler */ - public static synchronized void options(String path, Router routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.OPTIONS); + public static synchronized void options(String path, Router router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.OPTIONS); + } + + /** + * options请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor options(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.OPTIONS); + } + return null; } /** @@ -386,8 +474,19 @@ public static synchronized void options(String path, Router routeHandler){ * @param path * @param routeHandler */ - public static synchronized void connect(String path, Router routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.CONNECT); + public static synchronized void connect(String path, Router router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.CONNECT); + } + + /** + * connect请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor connect(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.CONNECT); + } + return null; } /** @@ -395,8 +494,19 @@ public static synchronized void connect(String path, Router routeHandler){ * @param path * @param routeHandler */ - public static synchronized void all(String path, Router routeHandler){ - RouteMatcherBuilder.buildHandler(path, routeHandler, HttpMethod.ALL); + public static synchronized void all(String path, Router router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.ALL); + } + + /** + * all请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor all(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.ALL); + } + return null; } /** diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index e03517816..f2649b55a 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -16,15 +16,12 @@ package blade.route; import java.lang.reflect.Method; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Map; import blade.Blade; import blade.kit.CollectionKit; -import blade.kit.MimeParse; import blade.kit.StringKit; import blade.kit.log.Logger; @@ -72,7 +69,7 @@ public RouteMatcher findRouteMatcher(HttpMethod httpMethod, String uri, String a // 优先匹配原则 giveMatch(uri, routeEntries); - RouteMatcher entry = findTargetWithGivenAcceptType(routeEntries, acceptType); + RouteMatcher entry = routeEntries.size() > 0 ? routeEntries.get(0) : null; return entry != null ? new RouteMatcher(entry.router, entry.target, entry.execMethod, entry.httpMethod, entry.path, uri, acceptType) : null; } @@ -105,16 +102,7 @@ public List findInterceptor(HttpMethod httpMethod, String uri, Str List routeEntries = DEFAULT_ROUTE_MATCHER.findInterceptor(httpMethod, uri); for (RouteMatcher routeEntry : routeEntries) { - if (acceptType != null) { - - String bestMatch = MimeParse.bestMatch(Arrays.asList(routeEntry.acceptType), acceptType); - - if (routeWithGivenAcceptType(bestMatch)) { - matchSet.add(routeEntry); - } - } else { - matchSet.add(routeEntry); - } + matchSet.add(routeEntry); } return matchSet; @@ -171,7 +159,6 @@ public void addRoute(Class target, Method execMethod, String url, HttpMethod entry.httpMethod = method; entry.path = url; entry.requestURI = url; - entry.acceptType = acceptType; if(Blade.debug()){ LOGGER.debug("Add Route:" + entry); @@ -197,7 +184,6 @@ public void addInterceptor(Class target, Method execMethod, String url, HttpM entry.httpMethod = method; entry.path = url; entry.requestURI = url; - entry.acceptType = acceptType; if(Blade.debug()){ LOGGER.debug("Add Interceptor:" + entry); @@ -221,7 +207,6 @@ public void addRoute(Router router, String url, HttpMethod method, String accept entry.httpMethod = method; entry.path = url; entry.requestURI = url; - entry.acceptType = acceptType; if(Blade.debug()){ LOGGER.debug("Add Route:" + entry); @@ -245,7 +230,6 @@ public void addInterceptor(Router router, String url, HttpMethod method, String entry.httpMethod = method; entry.path = url; entry.requestURI = url; - entry.acceptType = acceptType; if(Blade.debug()){ LOGGER.debug("Add Interceptor:" + entry); @@ -255,22 +239,6 @@ public void addInterceptor(Router router, String url, HttpMethod method, String interceptors.add(entry); } - private Map getAcceptedMimeTypes(List routes) { - Map acceptedTypes = CollectionKit.newHashMap(); - - for (RouteMatcher routeEntry : routes) { - if (!acceptedTypes.containsKey(routeEntry.acceptType)) { - acceptedTypes.put(routeEntry.acceptType, routeEntry); - } - } - - return acceptedTypes; - } - - private boolean routeWithGivenAcceptType(String bestMatch) { - return !MimeParse.NO_MIME_TYPE.equals(bestMatch); - } - /** * 查找所有匹配HttpMethod和path的路由 * @@ -307,31 +275,6 @@ private List findInterceptor(HttpMethod httpMethod, String path) { return matchSet; } - /** - * 查找符合请求头的路由 - * @param routeMatches - * @param acceptType - * @return - */ - private RouteMatcher findTargetWithGivenAcceptType(List routeMatches, String acceptType) { - if (acceptType != null && routeMatches.size() > 0) { - Map acceptedMimeTypes = getAcceptedMimeTypes(routeMatches); - String bestMatch = MimeParse.bestMatch(acceptedMimeTypes.keySet(), acceptType); - - if (routeWithGivenAcceptType(bestMatch)) { - return acceptedMimeTypes.get(bestMatch); - } else { - return null; - } - } else { - if (routeMatches.size() > 0) { - return routeMatches.get(0); - } - } - - return null; - } - private boolean removeRoute(HttpMethod httpMethod, String path) { List forRemoval = CollectionKit.newArrayList(); diff --git a/blade-core/src/main/java/blade/route/RouteMatcher.java b/blade-core/src/main/java/blade/route/RouteMatcher.java index a1ac786db..86dcca0fb 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/blade/route/RouteMatcher.java @@ -58,11 +58,6 @@ public class RouteMatcher { */ String requestURI; - /** - * 允许的acceptType - */ - String acceptType; - public RouteMatcher() { } @@ -73,13 +68,8 @@ public RouteMatcher(Router router, Class target, Method execMethod, HttpMetho this.httpMethod = httpMethod; this.path = path; this.requestURI = requestUri; - this.acceptType = acceptType; } - - public String getAcceptType() { - return acceptType; - } - + public HttpMethod getHttpMethod() { return httpMethod; } @@ -201,16 +191,58 @@ private boolean matchPath(String uri) { } @Override - public boolean equals(Object obj) { - if(obj instanceof RouteMatcher){ - RouteMatcher r = (RouteMatcher) obj; - return this.httpMethod == r.httpMethod && this.execMethod.getName().equals(r.execMethod.getName()) - && this.path.equals(r.path) && this.acceptType.equals(r.acceptType); - } - return false; - } - - @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((execMethod == null) ? 0 : execMethod.hashCode()); + result = prime * result + ((httpMethod == null) ? 0 : httpMethod.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + ((requestURI == null) ? 0 : requestURI.hashCode()); + result = prime * result + ((router == null) ? 0 : router.hashCode()); + result = prime * result + ((target == null) ? 0 : target.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RouteMatcher other = (RouteMatcher) obj; + if (execMethod == null) { + if (other.execMethod != null) + return false; + } else if (!execMethod.equals(other.execMethod)) + return false; + if (httpMethod != other.httpMethod) + return false; + if (path == null) { + if (other.path != null) + return false; + } else if (!path.equals(other.path)) + return false; + if (requestURI == null) { + if (other.requestURI != null) + return false; + } else if (!requestURI.equals(other.requestURI)) + return false; + if (router == null) { + if (other.router != null) + return false; + } else if (!router.equals(other.router)) + return false; + if (target == null) { + if (other.target != null) + return false; + } else if (!target.equals(other.target)) + return false; + return true; + } + + @Override public String toString() { return httpMethod.name() + ":" + path; } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 242e93dd3..7efde412a 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -1225,7 +1225,7 @@ public Integer executeAndCommit() { * * @return 返回主键 */ - @SuppressWarnings({ "unchecked", "resource" }) + @SuppressWarnings({ "unchecked"}) public V executeAndCommit(Class returnType) { V key = null; Query query = null; @@ -1293,7 +1293,10 @@ public V executeAndCommit(Class returnType) { e.printStackTrace(); } finally{ if(null != query){ - query.close(); + Connection connection = query.getConnection(); + if(null != connection){ + connection.close(); + } } } return null; @@ -1447,6 +1450,9 @@ private Query updateCommit(Connection conn){ LOGGER.debug("execute sql:" + query.toString()); LOGGER.debug("execute parameter:" + condition.params.values() + condition.equalsParams.values()); + if(null != conn){ + conn.close(); + } return query; } return null; diff --git a/pom.xml b/pom.xml index e465a4f20..c78bbdaa1 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.9-beta + 1.2.9 From 2bf8175f1ad0aa8214b736abecf216ed6c89abc9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 7 Sep 2015 17:49:04 +0800 Subject: [PATCH 132/545] multiple routing --- .../main/java/blade/route/RouterExecutor.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 blade-core/src/main/java/blade/route/RouterExecutor.java diff --git a/blade-core/src/main/java/blade/route/RouterExecutor.java b/blade-core/src/main/java/blade/route/RouterExecutor.java new file mode 100644 index 000000000..2457aa895 --- /dev/null +++ b/blade-core/src/main/java/blade/route/RouterExecutor.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.route; + +/** + * 多个路由的执行器 + * + * @author biezhi + * @since 1.0 + */ +public class RouterExecutor{ + + private String[] paths; + + private HttpMethod httpMethod; + + public RouterExecutor(String[] paths, HttpMethod httpMethod) { + this.paths = paths; + this.httpMethod = httpMethod; + } + + public void run(Router router) { + for(String path : paths){ + RouteMatcherBuilder.buildHandler(path, router, httpMethod); + } + } + +} From 873aa687b9f6f91fe3995eebd2e82e6cc72bf6c6 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 7 Sep 2015 17:53:29 +0800 Subject: [PATCH 133/545] all request to create a handler --- .../src/main/java/blade/BladeFilter.java | 2 +- .../src/main/java/blade/RequestHandler.java | 21 ++++--------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java index 6fbfe8a4c..88ac708c0 100644 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ b/blade-core/src/main/java/blade/BladeFilter.java @@ -115,7 +115,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha /** * 是否被RequestHandler执行 */ - boolean isHandler = RequestHandler.single().handler(httpRequest, httpResponse); + boolean isHandler = new RequestHandler().handler(httpRequest, httpResponse); if(!isHandler){ chain.doFilter(httpRequest, httpResponse); } diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 2b4101157..7b138c00b 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -66,24 +66,11 @@ public class RequestHandler { /** * 路由处理器,查找请求过来的URL */ - private static DefaultRouteMatcher defaultRouteMatcher = DefaultRouteMatcher.instance(); + private static final DefaultRouteMatcher defaultRouteMatcher = DefaultRouteMatcher.instance(); - private RequestHandler(){} - - public static RequestHandler single() { - return RequestHandlerHolder.single; - } - - /** - * 单例的RequestHandler - * - * @author biezhi - * @since 1.0 - * - */ - private static class RequestHandlerHolder { - private static final RequestHandler single = new RequestHandler(); - } + public RequestHandler(){ + + } /** * handler执行方法 From ffb4cac2be1c2201bfb607b49b3a2dc7f8929d53 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 7 Sep 2015 18:03:26 +0800 Subject: [PATCH 134/545] simplify the code --- .../src/main/java/blade/RequestHandler.java | 73 +++++++------------ .../java/blade/route/DefaultRouteMatcher.java | 65 ++--------------- .../main/java/blade/route/RouteMatcher.java | 2 +- 3 files changed, 33 insertions(+), 107 deletions(-) diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 7b138c00b..967fb619c 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -52,8 +52,6 @@ public class RequestHandler { private static final Logger LOGGER = Logger.getLogger(RequestHandler.class); - private static final String ACCEPT_TYPE_REQUEST_MIME_HEADER = "Accept"; - /** * 服务器500错误时返回的HTML */ @@ -61,12 +59,15 @@ public class RequestHandler { private static final String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + Blade.VERSION +"
"; + /** + * IOC容器 + */ private final static Container container = DefaultContainer.single(); /** * 路由处理器,查找请求过来的URL */ - private static final DefaultRouteMatcher defaultRouteMatcher = DefaultRouteMatcher.instance(); + private static final DefaultRouteMatcher DEFAULT_ROUTE_MATCHER = DefaultRouteMatcher.instance(); public RequestHandler(){ @@ -93,16 +94,15 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse return false; } } - String acceptType = httpRequest.getHeader(ACCEPT_TYPE_REQUEST_MIME_HEADER); - - // 创建RequestWrapper And RequestWrapper - RequestWrapper requestWrapper = new RequestWrapper(); - ResponseWrapper responseWrapper = new ResponseWrapper(); if(Blade.debug()){ LOGGER.debug("Request : " + method + "\t" + uri); } + // 创建RequestWrapper And RequestWrapper + RequestWrapper requestWrapper = new RequestWrapper(); + ResponseWrapper responseWrapper = new ResponseWrapper(); + // 构建一个包装后的response Response response = RequestResponseBuilder.build(httpResponse); @@ -112,11 +112,11 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse responseWrapper.setDelegate(response); // 查找用户请求的uri - RouteMatcher match = defaultRouteMatcher.findRouteMatcher(httpMethod, uri, acceptType); + RouteMatcher match = DEFAULT_ROUTE_MATCHER.findRoute(httpMethod, uri); // 如果找到 if (match != null) { // 执行before拦截 - result = before(httpRequest, requestWrapper, responseWrapper, uri, acceptType); + result = intercept(httpRequest, requestWrapper, responseWrapper, uri, HttpMethod.BEFORE); if(result instanceof Boolean){ boolean isHandler = (Boolean) result; if(!isHandler){ @@ -145,8 +145,8 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse // 执行after拦截 responseWrapper.setDelegate(response); - after(httpRequest, requestWrapper, responseWrapper, uri, acceptType); - + intercept(httpRequest, requestWrapper, responseWrapper, uri, HttpMethod.AFTER); + if (null != result) render(responseWrapper, result); return true; @@ -219,53 +219,25 @@ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper reques } /** - * 前置事件,在route执行前执行 - * 这里如果执行则Request和Response都会被创建好 + * 拦截器事件 * + * @param httpRequest HttpServletRequest请求对象,用于构建Request * @param requestWrapper RequestWrapper对象,包装了Request对象 * @param responseWrapper ResponseWrapper对象,包装了Response对象 - * @param httpRequest HttpServletRequest请求对象,用于构建Request * @param uri 请求的URI - * @param acceptType 请求头过滤 */ - private Object before(HttpServletRequest httpRequest, RequestWrapper requestWrapper, ResponseWrapper responseWrapper, final String uri, final String acceptType){ - - List matchSet = defaultRouteMatcher.findInterceptor(HttpMethod.BEFORE, uri, acceptType); - - for (RouteMatcher filterMatch : matchSet) { + private Object intercept(HttpServletRequest httpRequest, RequestWrapper requestWrapper, + ResponseWrapper responseWrapper, String uri, HttpMethod httpMethod){ + List matchSet = DEFAULT_ROUTE_MATCHER.findInterceptor(httpMethod, uri); + + for (RouteMatcher filterMatch : matchSet) { Object object = realHandler(httpRequest, requestWrapper, responseWrapper, filterMatch); if(null != object){ return object; } } - return true; - } - - /** - * 后置事件,在route执行后执行 - * - * @param httpRequest HttpServletRequest请求对象,用于构建Request - * @param requestWrapper RequestWrapper对象,包装了Request对象 - * @param responseWrapper ResponseWrapper对象,包装了Response对象 - * @param uri 请求的URI - * @param acceptType 请求头过滤 - */ - private boolean after(HttpServletRequest httpRequest, RequestWrapper requestWrapper, ResponseWrapper responseWrapper, final String uri, final String acceptType){ - List matchSet = defaultRouteMatcher.findInterceptor(HttpMethod.AFTER, uri, acceptType); - - boolean isHandler = true; - - for (RouteMatcher filterMatch : matchSet) { - Object object = realHandler(httpRequest, requestWrapper, responseWrapper, filterMatch); - if(null != object && object instanceof Boolean){ - isHandler = (Boolean) object; - if(!isHandler){ - return false; - } - } - } - return isHandler; + return true; } /** @@ -328,6 +300,11 @@ private void render(Response response, Object result){ } } + /** + * 要过滤掉的目录 + * @param uri + * @return + */ private boolean filterStaticFolder(String uri){ int len = Blade.staticFolder().length; for(int i=0; i 1 && uri.endsWith("/")) ? uri.substring(0, uri.length() - 1) : uri; - List routeEntries = DEFAULT_ROUTE_MATCHER.findRouteMatcher(httpMethod, uri); + List routeEntries = this.findRouteMatcher(httpMethod, uri); // 优先匹配原则 giveMatch(uri, routeEntries); RouteMatcher entry = routeEntries.size() > 0 ? routeEntries.get(0) : null; - return entry != null ? new RouteMatcher(entry.router, entry.target, entry.execMethod, entry.httpMethod, entry.path, uri, acceptType) : null; + return entry != null ? new RouteMatcher(entry.router, entry.target, entry.execMethod, entry.httpMethod, entry.path, uri) : null; } private void giveMatch(final String uri, List routeEntries) { @@ -94,12 +93,12 @@ public int compare(RouteMatcher o1, RouteMatcher o2) { * @param acceptType 请求的acceptType * @return 返回一个路由匹配对象集合 */ - public List findInterceptor(HttpMethod httpMethod, String uri, String acceptType) { + public List findInterceptor(HttpMethod httpMethod, String uri) { if(uri.length() > 1){ uri = uri.endsWith("/") ? uri.substring(0, uri.length() - 1) : uri; } List matchSet = CollectionKit.newArrayList(); - List routeEntries = DEFAULT_ROUTE_MATCHER.findInterceptor(httpMethod, uri); + List routeEntries = this.searchInterceptor(httpMethod, uri); for (RouteMatcher routeEntry : routeEntries) { matchSet.add(routeEntry); @@ -115,34 +114,6 @@ public void clearRoutes() { routes.clear(); } - /** - * 移除一个路由 - * - * @param path 移除路由的路径 - * @param httpMethod 移除路由的方法 - * @return true:移除成功,false:移除失败 - */ - public boolean removeRoute(String path, String httpMethod) { - if (StringKit.isEmpty(path)) { - throw new IllegalArgumentException("path cannot be null or blank"); - } - - if (StringKit.isEmpty(httpMethod)) { - throw new IllegalArgumentException("httpMethod cannot be null or blank"); - } - - HttpMethod method = HttpMethod.valueOf(httpMethod); - - return removeRoute(method, path); - } - - public boolean removeRoute(String path) { - if (StringKit.isEmpty(path)) { - throw new IllegalArgumentException("path cannot be null or blank"); - } - return removeRoute((HttpMethod)null, path); - } - /** * 添加一个路由对象 * @@ -265,7 +236,7 @@ private List findRouteMatcher(HttpMethod httpMethod, String path) * @param path 路由路径 * @return 返回匹配的所有路由集合 */ - private List findInterceptor(HttpMethod httpMethod, String path) { + private List searchInterceptor(HttpMethod httpMethod, String path) { List matchSet = CollectionKit.newArrayList(); for (RouteMatcher entry : interceptors) { if (entry.matches(httpMethod, path)) { @@ -275,27 +246,5 @@ private List findInterceptor(HttpMethod httpMethod, String path) { return matchSet; } - private boolean removeRoute(HttpMethod httpMethod, String path) { - List forRemoval = CollectionKit.newArrayList(); - - for (RouteMatcher routeEntry : routes) { - HttpMethod httpMethodToMatch = httpMethod; - - if (httpMethod == null) { - // Use the routeEntry's HTTP method if none was given, so that only path is used to match. - httpMethodToMatch = routeEntry.httpMethod; - } - - if (routeEntry.matches(httpMethodToMatch, path)) { - - if(Blade.debug()){ - LOGGER.debug("Removing path {}", path, httpMethod == null ? "" : " with HTTP method " + httpMethod); - } - - forRemoval.add(routeEntry); - } - } - - return routes.removeAll(forRemoval); - } + } diff --git a/blade-core/src/main/java/blade/route/RouteMatcher.java b/blade-core/src/main/java/blade/route/RouteMatcher.java index 86dcca0fb..f68ed8246 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/blade/route/RouteMatcher.java @@ -61,7 +61,7 @@ public class RouteMatcher { public RouteMatcher() { } - public RouteMatcher(Router router, Class target, Method execMethod, HttpMethod httpMethod, String path, String requestUri, String acceptType) { + public RouteMatcher(Router router, Class target, Method execMethod, HttpMethod httpMethod, String path, String requestUri) { this.router = router; this.target = target; this.execMethod = execMethod; From ee5236179df0d95800cf3755626ede96b6675484 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 7 Sep 2015 18:31:50 +0800 Subject: [PATCH 135/545] multi-route --- blade-core/src/main/java/blade/Blade.java | 41 ++++---- .../src/main/java/blade/annotation/After.java | 5 +- .../main/java/blade/annotation/Before.java | 6 +- .../src/main/java/blade/annotation/Route.java | 4 +- .../java/blade/route/DefaultRouteMatcher.java | 4 +- .../java/blade/route/RouteMatcherBuilder.java | 93 +++++++++++-------- .../main/java/blade/route/RouterExecutor.java | 12 ++- 7 files changed, 94 insertions(+), 71 deletions(-) diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index 0e11b3006..c4e0f16b8 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -517,6 +517,17 @@ public static synchronized RouterExecutor all(String... paths){ public static synchronized void before(String path, Router routeHandler){ RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); } + + /** + * before请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor before(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.BEFORE); + } + return null; + } /** * 拦截器after请求 @@ -528,30 +539,14 @@ public static synchronized void after(String path, Router routeHandler){ } /** - * 注册一个函数式的拦截器
- *

- * 方法上指定请求类型,如:post:signin - *

- * @param path 路由url - * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 - */ - public static synchronized void regInterceptor(String path, Class clazz, String methodName){ - RouteMatcherBuilder.buildInterceptor(path, clazz, methodName, null); - } - - /** - * 注册一个函数式的拦截器
- *

- * 方法上指定请求类型,如:post:signin - *

- * @param path 路由url - * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 - * @param acceptType acceptType + * after请求,多个路由 + * @param paths */ - public static synchronized void regInterceptor(String path, Class clazz, String methodName, String acceptType){ - RouteMatcherBuilder.buildInterceptor(path, clazz, methodName, acceptType); + public static synchronized RouterExecutor after(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.AFTER); + } + return null; } public final static BladeConfig config(){ diff --git a/blade-core/src/main/java/blade/annotation/After.java b/blade-core/src/main/java/blade/annotation/After.java index ed99a5e4c..249386c16 100644 --- a/blade-core/src/main/java/blade/annotation/After.java +++ b/blade-core/src/main/java/blade/annotation/After.java @@ -47,7 +47,8 @@ String suffix() default ""; /** - * 允许的accept + * 多个前置拦截 + * @return */ - String acceptType() default "*/*"; + String[] values() default {}; } \ No newline at end of file diff --git a/blade-core/src/main/java/blade/annotation/Before.java b/blade-core/src/main/java/blade/annotation/Before.java index f968dcf86..b699c0363 100644 --- a/blade-core/src/main/java/blade/annotation/Before.java +++ b/blade-core/src/main/java/blade/annotation/Before.java @@ -47,8 +47,8 @@ String suffix() default ""; /** - * 允许的accept + * 多个后置拦截 + * @return */ - String acceptType() default "*/*"; - + String[] values() default {}; } \ No newline at end of file diff --git a/blade-core/src/main/java/blade/annotation/Route.java b/blade-core/src/main/java/blade/annotation/Route.java index f63c73ea4..dce2c2096 100644 --- a/blade-core/src/main/java/blade/annotation/Route.java +++ b/blade-core/src/main/java/blade/annotation/Route.java @@ -57,8 +57,8 @@ HttpMethod method() default HttpMethod.ALL; /** - * @return 需要拦截的acceptType + * @return 多个请求 */ - String acceptType() default "*/*"; + String[] values() default {}; } \ No newline at end of file diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index 201d0bb11..75cec2514 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -123,7 +123,7 @@ public void clearRoutes() { * @param method 路由http方法 * @param acceptType 路由acceptType */ - public void addRoute(Class target, Method execMethod, String url, HttpMethod method, String acceptType) { + public void addRoute(Class target, Method execMethod, String url, HttpMethod method) { RouteMatcher entry = new RouteMatcher(); entry.target = target; entry.execMethod = execMethod; @@ -148,7 +148,7 @@ public void addRoute(Class target, Method execMethod, String url, HttpMethod * @param method 路由http方法 * @param acceptType 路由acceptType */ - public void addInterceptor(Class target, Method execMethod, String url, HttpMethod method, String acceptType) { + public void addInterceptor(Class target, Method execMethod, String url, HttpMethod method) { RouteMatcher entry = new RouteMatcher(); entry.target = target; entry.execMethod = execMethod; diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index 54a7806f1..acd6edd62 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -131,7 +131,12 @@ public static void buildFunctional(String path, Class clazz, String methodNam Method execMethod = ReflectKit.getMethodByName(clazz, methodName); - defaultRouteMatcher.addRoute(clazz, execMethod, path, httpMethod, "*/*"); + // 拦截器 + if(httpMethod == HttpMethod.AFTER || httpMethod == HttpMethod.BEFORE){ + defaultRouteMatcher.addInterceptor(clazz, execMethod, path, httpMethod); + } else { + defaultRouteMatcher.addRoute(clazz, execMethod, path, httpMethod); + } } else { throw new BladeException("an unqualified configuration"); } @@ -162,20 +167,15 @@ public static void buildInterceptor(String path, Router router, HttpMethod httpM /** * 函数式拦截器构建 */ - public static void buildInterceptor(String path, Class clazz, String methodName, String acceptType){ + public static void buildInterceptor(String path, Class clazz, String methodName){ if(StringKit.isNotBlank(path) && null != clazz && StringKit.isNotBlank(methodName)){ - // 字符串上写请求 */*:hello + // 字符串上写请求 hello if(methodName.indexOf(":") != -1){ String[] methodArr = StringKit.split(methodName, ":"); - acceptType = methodArr[0]; methodName = methodArr[1]; } - if(null == acceptType){ - acceptType = "*/*"; - } - // 查找 Object target = container.getBean(clazz, null); if(null == target){ @@ -184,7 +184,7 @@ public static void buildInterceptor(String path, Class clazz, String methodNa Method execMethod = ReflectKit.getMethodByName(clazz, methodName); - defaultRouteMatcher.addInterceptor(clazz, execMethod, path, HttpMethod.BEFORE, acceptType); + defaultRouteMatcher.addInterceptor(clazz, execMethod, path, HttpMethod.BEFORE); } else { throw new BladeException("an unqualified configuration"); } @@ -269,30 +269,36 @@ private static void parseInterceptor(final Class interceptor){ if (null != before) { - String beforeSuffix = before.suffix(); - - String path = before.value().startsWith("/") ? before.value() : "/" + before.value(); + String suffix = before.suffix(); - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + String path = getRoutePath(before.value(), "", suffix); - path = path + beforeSuffix; + buildInterceptor(path, interceptor, method, HttpMethod.BEFORE); - String acceptType = before.acceptType(); - buildInterceptor(interceptor, method, path, HttpMethod.BEFORE, acceptType); + String[] paths = before.values(); + if(null != paths && paths.length > 0){ + for(String value : paths){ + String pathV = getRoutePath(value, "", suffix); + buildInterceptor(pathV, interceptor, method, HttpMethod.BEFORE); + } + } } if (null != after) { - String afterSuffix = after.suffix(); + String suffix = after.suffix(); - String path = after.value().startsWith("/") ? after.value() : "/" + after.value(); + String path = getRoutePath(after.value(), "", suffix); - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + buildInterceptor(path, interceptor, method, HttpMethod.AFTER); - path = path + afterSuffix; - - String acceptType = after.acceptType(); - buildInterceptor(interceptor, method, path, HttpMethod.AFTER, acceptType); + String[] paths = before.values(); + if(null != paths && paths.length > 0){ + for(String value : paths){ + String pathV = getRoutePath(value, "", suffix); + buildInterceptor(pathV, interceptor, method, HttpMethod.AFTER); + } + } } } } @@ -323,23 +329,36 @@ private static void parseRouter(final Class router){ if (null != mapping) { ////构建路由 - String path = mapping.value().startsWith("/") ? mapping.value() : "/" + mapping.value(); - path = nameSpace + path; - path = path.replaceAll("[/]+", "/"); - - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - - path = path + suffix; + String path = getRoutePath(mapping.value(), nameSpace, suffix); HttpMethod methodType = mapping.method(); - String acceptType = mapping.acceptType(); + buildRoute(router, method, path, methodType); - buildRoute(router, method, path, methodType, acceptType); + // 构建多个路由 + String[] paths = mapping.values(); + if(null != paths && paths.length > 0){ + for(String value : paths){ + String pathV = getRoutePath(value, nameSpace, suffix); + buildRoute(router, method, pathV, methodType); + } + } } } } + private static String getRoutePath(String value, String nameSpace, String suffix){ + String path = value.startsWith("/") ? value : "/" + value; + path = nameSpace + path; + path = path.replaceAll("[/]+", "/"); + + path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + + path = path + suffix; + + return path; + } + /** * 构建一个路由 * @@ -349,21 +368,21 @@ private static void parseRouter(final Class router){ * @param method 路由http方法 * @param acceptType 路由acceptType */ - private static void buildRoute(Class target, Method execMethod, String path, HttpMethod method, String acceptType){ - defaultRouteMatcher.addRoute(target, execMethod, path, method, acceptType); + private static void buildRoute(Class target, Method execMethod, String path, HttpMethod method){ + defaultRouteMatcher.addRoute(target, execMethod, path, method); } /** * 构建一个路由 * + * @param path 路由url * @param target 路由目标执行的class * @param execMethod 路由执行方法 - * @param path 路由url * @param method 路由http方法 * @param acceptType 路由acceptType */ - private static void buildInterceptor(Class target, Method execMethod, String path, HttpMethod method, String acceptType){ - defaultRouteMatcher.addInterceptor(target, execMethod, path, method, acceptType); + private static void buildInterceptor(String path, Class target, Method execMethod, HttpMethod method){ + defaultRouteMatcher.addInterceptor(target, execMethod, path, method); } private static HttpMethod getHttpMethod(String name){ diff --git a/blade-core/src/main/java/blade/route/RouterExecutor.java b/blade-core/src/main/java/blade/route/RouterExecutor.java index 2457aa895..5b4fc7244 100644 --- a/blade-core/src/main/java/blade/route/RouterExecutor.java +++ b/blade-core/src/main/java/blade/route/RouterExecutor.java @@ -33,8 +33,16 @@ public RouterExecutor(String[] paths, HttpMethod httpMethod) { } public void run(Router router) { - for(String path : paths){ - RouteMatcherBuilder.buildHandler(path, router, httpMethod); + // 拦截器 + if(this.httpMethod == HttpMethod.BEFORE || this.httpMethod == HttpMethod.AFTER){ + for(String path : paths){ + RouteMatcherBuilder.buildInterceptor(path, router, httpMethod); + } + } else { + // 路由 + for(String path : paths){ + RouteMatcherBuilder.buildHandler(path, router, httpMethod); + } } } From 9e603521f865149eb4bd08c72e196fbf351553ea Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 7 Sep 2015 18:46:07 +0800 Subject: [PATCH 136/545] update readme --- README.md | 38 +++++++++++++++++++------------------- README_CN.md | 38 ++++++++++++++++++++------------------ 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 6c6606d16..b37cc9135 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,32 @@ -#Blade - [![a concise and powerful web development framework](http://i1.tietuku.com/0c4b9726253b6268.png "a concise and powerful web development framework")](http://bladejava.com) -[中文](https://github.com/biezhi/blade/blob/master/README_CN.md) - [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) -[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -## Introduction +[中文](https://github.com/biezhi/blade/blob/master/README_CN.md) + +## What Is Blade? **blade** Is a concise and powerful web development framework, it is built into the `IOC` administration, the interceptor configuration, `REST API` development and so on many mainstream web features, integrate the template engine, a cache plug-in, database operations, commonly used functions such as email, concise source deserves your reading. If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! -## Features - -* Simple MVC -* Restful -* Multiple routing configuration -* Micro kernel IOC container -* Utility class -* Coding/JSON/configuration file -* JDK1.6 + -* Plug-in extension mechanism -* Template engine Plugin -* Cache Plugin -* The source code of less than 100kb +- __Simple MVC__ +use Java language to complete the MVC more concise +- __Restful__ +provide a Restful style routing interface +- __Multiple routing configuration__ +routing configuration in the form of more functional routing, annotations routing, routing reflection way +- __Coding/JSON/configuration file__ +blade offers a variety of configurations, including JSON, the Properties file, hard coding +- __Plug-in extension mechanism__ +blade extensions support you use third party components, modular development of more convenient +- __Template engine Plugin__ +support access to mainstream template engine, there are beetl, jetbrick, velocity engine +- __Support JDK1.6 +__ +Support jdk1.6 or higher version +- __The source code of less than 100kb__ +the source code of the blade framework is less than 100 KB, learn easy, get started quickly, the code is simple ## Quick start First. Use maven to build a webapp, join dependency on the blade,Recommended for the [latest version](LAST_VERSION.md) diff --git a/README_CN.md b/README_CN.md index 3053e5884..2ff0315a6 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,30 +1,32 @@ -#Blade - [![简洁强大的JavaWeb框架](http://i1.tietuku.com/0c4b9726253b6268.png "简洁强大的JavaWeb框架")](http://bladejava.com) -[English](https://github.com/biezhi/blade/blob/master/README.md) - [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) -[![Circle CI](https://circleci.com/gh/biezhi/blade/tree/master.svg?style=svg)](https://circleci.com/gh/biezhi/blade/tree/master) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[English](https://github.com/biezhi/blade/blob/master/README.md) + +## Blade是什么? + **blade** 是一个简洁强大的web框架,它内置了`IOC`管理,拦截器配置,`REST API`开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送等常用功能,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! -## Blade特性 - -* 简洁的MVC -* RESTful -* 多种路由配置方式 -* 微内核IOC容器 -* 实用工具类 -* 编码/JSON/配置文件 -* 模板引擎支持 -* 支持JDK1.6+ -* 插件扩展机制 -* 缓存支持 -* 不到100K的源码 +- __简洁的MVC__ +使用java语言完成mvc更加简洁 +- __RESTful__ +提供Restful风格的路由接口 +- __多种路由配置方式__ +更多方式进行路由的配置,函数式路由,注解路由,反射方式路由 +- __编码/JSON/配置文件__ +blade提供多种配置方式,包括JSON、Properties文件,硬编码 +- __插件扩展机制__ +blade支持你使用第三方的组件进行扩展,更方便的积木式开发 +- __模板引擎支持__ +支持主流模板引擎接入,目前已经有beetl、jetbrick、velocity引擎 +- __支持JDK1.6+__ +支持jdk1.6或者更高版本 +- __不到100K的源码__ +目前blade框架的源代码不到100kb,学习简单,上手快速,代码简洁 ## 快速入门 第一步、用maven构建一个webapp,加入blade的依赖,推荐获取[最新版本](LAST_VERSION.md) From 025a5216d9ffd0db3d5bd6122ab83b8446ea3942 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 7 Sep 2015 18:47:02 +0800 Subject: [PATCH 137/545] update readme --- README.md | 7 +++++++ README_CN.md | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/README.md b/README.md index b37cc9135..bae389cca 100644 --- a/README.md +++ b/README.md @@ -13,18 +13,25 @@ - __Simple MVC__ use Java language to complete the MVC more concise + - __Restful__ provide a Restful style routing interface + - __Multiple routing configuration__ routing configuration in the form of more functional routing, annotations routing, routing reflection way + - __Coding/JSON/configuration file__ blade offers a variety of configurations, including JSON, the Properties file, hard coding + - __Plug-in extension mechanism__ blade extensions support you use third party components, modular development of more convenient + - __Template engine Plugin__ support access to mainstream template engine, there are beetl, jetbrick, velocity engine + - __Support JDK1.6 +__ Support jdk1.6 or higher version + - __The source code of less than 100kb__ the source code of the blade framework is less than 100 KB, learn easy, get started quickly, the code is simple diff --git a/README_CN.md b/README_CN.md index 2ff0315a6..41b2382b1 100644 --- a/README_CN.md +++ b/README_CN.md @@ -13,18 +13,25 @@ - __简洁的MVC__ 使用java语言完成mvc更加简洁 + - __RESTful__ 提供Restful风格的路由接口 + - __多种路由配置方式__ 更多方式进行路由的配置,函数式路由,注解路由,反射方式路由 + - __编码/JSON/配置文件__ blade提供多种配置方式,包括JSON、Properties文件,硬编码 + - __插件扩展机制__ blade支持你使用第三方的组件进行扩展,更方便的积木式开发 + - __模板引擎支持__ 支持主流模板引擎接入,目前已经有beetl、jetbrick、velocity引擎 + - __支持JDK1.6+__ 支持jdk1.6或者更高版本 + - __不到100K的源码__ 目前blade框架的源代码不到100kb,学习简单,上手快速,代码简洁 From 9b6b92ecc7ef914426e4e2df36aaa1b36dde4e41 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 7 Sep 2015 18:47:52 +0800 Subject: [PATCH 138/545] update readme --- README.md | 8 ++++++++ README_CN.md | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/README.md b/README.md index bae389cca..66b6efaa9 100644 --- a/README.md +++ b/README.md @@ -12,27 +12,35 @@ **blade** Is a concise and powerful web development framework, it is built into the `IOC` administration, the interceptor configuration, `REST API` development and so on many mainstream web features, integrate the template engine, a cache plug-in, database operations, commonly used functions such as email, concise source deserves your reading. If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! - __Simple MVC__ + use Java language to complete the MVC more concise - __Restful__ + provide a Restful style routing interface - __Multiple routing configuration__ + routing configuration in the form of more functional routing, annotations routing, routing reflection way - __Coding/JSON/configuration file__ + blade offers a variety of configurations, including JSON, the Properties file, hard coding - __Plug-in extension mechanism__ + blade extensions support you use third party components, modular development of more convenient - __Template engine Plugin__ + support access to mainstream template engine, there are beetl, jetbrick, velocity engine - __Support JDK1.6 +__ + Support jdk1.6 or higher version - __The source code of less than 100kb__ + the source code of the blade framework is less than 100 KB, learn easy, get started quickly, the code is simple ## Quick start diff --git a/README_CN.md b/README_CN.md index 41b2382b1..cc388ff54 100644 --- a/README_CN.md +++ b/README_CN.md @@ -12,27 +12,35 @@ **blade** 是一个简洁强大的web框架,它内置了`IOC`管理,拦截器配置,`REST API`开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送等常用功能,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! - __简洁的MVC__ + 使用java语言完成mvc更加简洁 - __RESTful__ + 提供Restful风格的路由接口 - __多种路由配置方式__ + 更多方式进行路由的配置,函数式路由,注解路由,反射方式路由 - __编码/JSON/配置文件__ + blade提供多种配置方式,包括JSON、Properties文件,硬编码 - __插件扩展机制__ + blade支持你使用第三方的组件进行扩展,更方便的积木式开发 - __模板引擎支持__ + 支持主流模板引擎接入,目前已经有beetl、jetbrick、velocity引擎 - __支持JDK1.6+__ + 支持jdk1.6或者更高版本 - __不到100K的源码__ + 目前blade框架的源代码不到100kb,学习简单,上手快速,代码简洁 ## 快速入门 From a9aac9a43d687b33e83a446a8daf7052208b96be Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Sep 2015 09:51:43 +0800 Subject: [PATCH 139/545] update readme --- README.md | 93 +++++++++++++++------------------------------------- README_CN.md | 73 ++++++++++------------------------------- 2 files changed, 44 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index 66b6efaa9..3e2bda72a 100644 --- a/README.md +++ b/README.md @@ -9,69 +9,33 @@ ## What Is Blade? -**blade** Is a concise and powerful web development framework, it is built into the `IOC` administration, the interceptor configuration, `REST API` development and so on many mainstream web features, integrate the template engine, a cache plug-in, database operations, commonly used functions such as email, concise source deserves your reading. If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! +**blade** Is a concise and powerful web development framework. If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! -- __Simple MVC__ +- __Simple MVC__ +Use Java language to complete the MVC more concise. -use Java language to complete the MVC more concise +- __Restful__ +Provide a Restful style routing interface. -- __Restful__ +- __Multiple routing configuration__ +Routing configuration in the form of more functional routing, annotations routing, routing reflection way. -provide a Restful style routing interface +- __Coding/JSON/configuration file__ +Blade offers a variety of configurations, including JSON, the Properties file, hard coding. -- __Multiple routing configuration__ +- __Plug-in extension mechanism__ +Blade extensions support you use third party components, modular development of more convenient. -routing configuration in the form of more functional routing, annotations routing, routing reflection way +- __Template engine Plugin__ +Support access to mainstream template engine, there are beetl, jetbrick, velocity engine. -- __Coding/JSON/configuration file__ +- __Support JDK1.6 +__ +Support jdk1.6 or higher version. -blade offers a variety of configurations, including JSON, the Properties file, hard coding +- __The source code of less than 100kb__ +The source code of the blade framework is less than 100 KB, learn easy, get started quickly, the code is simple. -- __Plug-in extension mechanism__ - -blade extensions support you use third party components, modular development of more convenient - -- __Template engine Plugin__ - -support access to mainstream template engine, there are beetl, jetbrick, velocity engine - -- __Support JDK1.6 +__ - -Support jdk1.6 or higher version - -- __The source code of less than 100kb__ - -the source code of the blade framework is less than 100 KB, learn easy, get started quickly, the code is simple - -## Quick start -First. Use maven to build a webapp, join dependency on the blade,Recommended for the [latest version](LAST_VERSION.md) - -```xml - - com.bladejava - blade-core - 1.2.9-beta - -``` - -Second. Configuration in the `web.xml` Blade core filter initialization and set your class - -```xml - - BladeFilter - blade.BladeFilter - - bootstrapClass - blade.hello.App - - - - BladeFilter - /* - -``` - -Third. Write App.java and routing file, here is an example +## Example ```java public class App extends Bootstrap{ @@ -80,7 +44,7 @@ public class App extends Bootstrap{ @Override public void init() { // register router - Blade.regRoute("/hello", SayHi.class, "hello"); + Blade.regsiter("/hello", SayHi.class, "hello"); // anonymous router,java8 so simple Blade.get("/get", new Router() { @@ -92,13 +56,10 @@ public class App extends Bootstrap{ } }); - // multiple routing - Blade.get("/", "/index").run(new Router() { - @Override - public String handler(Request request, Response response) { - System.out.println("come index!!"); - return "index"; - } + // multiple routing, java8 syntax + Blade.get("/", "/index").run(request, response) -> { + System.out.println("come index!!"); + return "index"; }); } @@ -116,13 +77,13 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex 1. Improve the document 2. Add configurable log - 3. To optimize the database query, connection pool - 4. Complete the Java China BBS + 3. Complete the Java China BBS + 4. Maintain and optimize the code ## Update [update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - + ## licenses Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) @@ -133,4 +94,4 @@ OSC Blog:[http://my.oschina.net/biezhi](http://my.oschina.net/biezhi) Mail: biezhi.me#gmail.com -QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) \ No newline at end of file +QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) diff --git a/README_CN.md b/README_CN.md index cc388ff54..8ff774b61 100644 --- a/README_CN.md +++ b/README_CN.md @@ -9,69 +9,33 @@ ## Blade是什么? -**blade** 是一个简洁强大的web框架,它内置了`IOC`管理,拦截器配置,`REST API`开发等众多主流web特性,集成了模板引擎,缓存插件,数据库操作,邮件发送等常用功能,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! - -- __简洁的MVC__ +**blade** 是一个简洁强大的web框架,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! +- __简洁的MVC__ 使用java语言完成mvc更加简洁 -- __RESTful__ - +- __RESTful__ 提供Restful风格的路由接口 -- __多种路由配置方式__ - +- __多种路由配置方式__ 更多方式进行路由的配置,函数式路由,注解路由,反射方式路由 -- __编码/JSON/配置文件__ - +- __编码/JSON/配置文件__ blade提供多种配置方式,包括JSON、Properties文件,硬编码 -- __插件扩展机制__ - +- __插件扩展机制__ blade支持你使用第三方的组件进行扩展,更方便的积木式开发 -- __模板引擎支持__ - +- __模板引擎支持__ 支持主流模板引擎接入,目前已经有beetl、jetbrick、velocity引擎 -- __支持JDK1.6+__ - +- __支持JDK1.6+__ 支持jdk1.6或者更高版本 -- __不到100K的源码__ - +- __不到100K的源码__ 目前blade框架的源代码不到100kb,学习简单,上手快速,代码简洁 -## 快速入门 -第一步、用maven构建一个webapp,加入blade的依赖,推荐获取[最新版本](LAST_VERSION.md) - -```xml - - com.bladejava - blade-core - 1.2.9-beta - -``` - -第二步、在`web.xml`中配置Blade核心过滤器并设置你的初始化类 - -```xml - - BladeFilter - blade.BladeFilter - - bootstrapClass - blade.hello.App - - - - BladeFilter - /* - -``` - -第三步、编写App.java和路由文件,下面是一个示例 +## 示例 ```java public class App extends Bootstrap{ @@ -82,7 +46,7 @@ public class App extends Bootstrap{ // 注册函数式路由 Blade.register("/hello", SayHi.class, "hello"); - // 匿名路由,java8方式更简化 + // 匿名路由 Blade.get("/get", new Router() { @Override public String handler(Request request, Response response) { @@ -92,13 +56,10 @@ public class App extends Bootstrap{ } }); - // 多个路由 - Blade.get("/", "/index").run(new Router() { - @Override - public String handler(Request request, Response response) { - System.out.println("进入index!!"); - return "index"; - } + // 多个路由,java8语法 + Blade.get("/", "/index").run(request, response) -> { + System.out.println("come index!!"); + return "index"; }); } } @@ -115,8 +76,8 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 1. 完善文档 2. 添加可配置日志 - 3. 优化数据库查询、连接池 - 4. 完成java中国论坛 + 3. 完成java中国论坛 + 4. 维护和优化代码 ## 更新日志 From 2a89067fe4b0d5b2aaeb76ff0271b3555be874f1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Sep 2015 15:02:57 +0800 Subject: [PATCH 140/545] - --- blade-sql2o/pom.xml | 2 +- .../src/main/java/blade/plugin/sql2o/Model.java | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index a6c4007a7..012bfa7a1 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - 1.2.8 + 1.2.9-alpha blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 7efde412a..200860f0b 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -1079,15 +1079,14 @@ public Page fetchPage(Integer page, Integer pageSize){ sqlEnd += " limit :page, :pageSize"; - condition.eq("page", page - 1); - condition.eq("pageSize", pageSize); - Connection conn = null; try { // 设置query conn = sql2o.open(); Query query = conn.createQuery(sqlEnd); query = parseParams(query); + query.addParameter("page", page - 1); + query.addParameter("pageSize", pageSize); LOGGER.debug("execute sql:" + query.toString()); condition.printLog(); @@ -1170,14 +1169,16 @@ public Page> fetchPageMap(Integer page, Integer pageSize){ sqlEnd += " limit :page, :pageSize"; - condition.eq("page", page - 1); - condition.eq("pageSize", pageSize); +// condition.eq("page", page - 1); +// condition.eq("pageSize", pageSize); Connection conn = null; try { // 设置query conn = sql2o.open(); Query query = conn.createQuery(sqlEnd); query = parseParams(query); + query.addParameter("page", page - 1); + query.addParameter("pageSize", pageSize); LOGGER.debug("execute sql:" + query.toString()); condition.printLog(); From 90327099b980644d972d056d25a7cdb5ad1038f8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Sep 2015 11:11:43 +0800 Subject: [PATCH 141/545] to simplify the route,fix sql2o bug --- .../java/blade/route/DefaultRouteMatcher.java | 4 -- .../main/java/blade/route/RouteMatcher.java | 16 ------ .../src/main/java/blade/servlet/Request.java | 52 +++++++++++++++++-- .../main/java/blade/plugin/sql2o/Model.java | 13 ++--- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index 75cec2514..332e4d570 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -129,7 +129,6 @@ public void addRoute(Class target, Method execMethod, String url, HttpMethod entry.execMethod = execMethod; entry.httpMethod = method; entry.path = url; - entry.requestURI = url; if(Blade.debug()){ LOGGER.debug("Add Route:" + entry); @@ -154,7 +153,6 @@ public void addInterceptor(Class target, Method execMethod, String url, HttpM entry.execMethod = execMethod; entry.httpMethod = method; entry.path = url; - entry.requestURI = url; if(Blade.debug()){ LOGGER.debug("Add Interceptor:" + entry); @@ -177,7 +175,6 @@ public void addRoute(Router router, String url, HttpMethod method, String accept entry.router = router; entry.httpMethod = method; entry.path = url; - entry.requestURI = url; if(Blade.debug()){ LOGGER.debug("Add Route:" + entry); @@ -200,7 +197,6 @@ public void addInterceptor(Router router, String url, HttpMethod method, String entry.router = router; entry.httpMethod = method; entry.path = url; - entry.requestURI = url; if(Blade.debug()){ LOGGER.debug("Add Interceptor:" + entry); diff --git a/blade-core/src/main/java/blade/route/RouteMatcher.java b/blade-core/src/main/java/blade/route/RouteMatcher.java index f68ed8246..de2f3ff2e 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/blade/route/RouteMatcher.java @@ -53,11 +53,6 @@ public class RouteMatcher { */ String path; - /** - * 请求URI - */ - String requestURI; - public RouteMatcher() { } @@ -67,7 +62,6 @@ public RouteMatcher(Router router, Class target, Method execMethod, HttpMetho this.execMethod = execMethod; this.httpMethod = httpMethod; this.path = path; - this.requestURI = requestUri; } public HttpMethod getHttpMethod() { @@ -82,10 +76,6 @@ public String getPath() { return path; } - public String getRequestURI() { - return requestURI; - } - public Class getTarget() { return target; } @@ -197,7 +187,6 @@ public int hashCode() { result = prime * result + ((execMethod == null) ? 0 : execMethod.hashCode()); result = prime * result + ((httpMethod == null) ? 0 : httpMethod.hashCode()); result = prime * result + ((path == null) ? 0 : path.hashCode()); - result = prime * result + ((requestURI == null) ? 0 : requestURI.hashCode()); result = prime * result + ((router == null) ? 0 : router.hashCode()); result = prime * result + ((target == null) ? 0 : target.hashCode()); return result; @@ -224,11 +213,6 @@ public boolean equals(Object obj) { return false; } else if (!path.equals(other.path)) return false; - if (requestURI == null) { - if (other.requestURI != null) - return false; - } else if (!requestURI.equals(other.requestURI)) - return false; if (router == null) { if (other.router != null) return false; diff --git a/blade-core/src/main/java/blade/servlet/Request.java b/blade-core/src/main/java/blade/servlet/Request.java index af10f8142..163986a76 100644 --- a/blade-core/src/main/java/blade/servlet/Request.java +++ b/blade-core/src/main/java/blade/servlet/Request.java @@ -87,10 +87,10 @@ public Request(RouteMatcher match, HttpServletRequest request) { */ public void initRequest(RouteMatcher match) { - List requestList = PathKit.convertRouteToList(match.getRequestURI()); + List requestList = PathKit.convertRouteToList(match.getPath()); List pathList = PathKit.convertRouteToList(match.getPath()); - this.pathParams = getPathParams(requestList, pathList); + this.pathParams = getPathParams(requestList); this.splat = getSplat(requestList, pathList); } @@ -523,7 +523,24 @@ public String protocol() { return servletRequest.getProtocol(); } - protected static Map getPathParams(List request, List matched) { + protected static Map getPathParams(List request) { + + Map params = CollectionKit.newHashMap(); + + for (int i = 0; (i < request.size()); i++) { + String matchedPart = request.get(i); + if (PathKit.isParam(matchedPart)) { + LOGGER.debug("matchedPart: " + + matchedPart + + " = " + + request.get(i)); + params.put(matchedPart.toLowerCase(), request.get(i)); + } + } + return Collections.unmodifiableMap(params); + } + + /*protected static Map getPathParams(List request, List matched) { Map params = CollectionKit.newHashMap(); @@ -538,7 +555,34 @@ protected static Map getPathParams(List request, List getSplat(List request, List matched) { + + int nbrOfRequestParts = request.size(); + int nbrOfMatchedParts = matched.size(); + + boolean sameLength = (nbrOfRequestParts == nbrOfMatchedParts); + + List splat = CollectionKit.newArrayList(); + + for (int i = 0; (i < nbrOfRequestParts) && (i < nbrOfMatchedParts); i++) { + String matchedPart = matched.get(i); + + if (PathKit.isSplat(matchedPart)) { + + StringBuilder splatParam = new StringBuilder(request.get(i)); + if (!sameLength && (i == (nbrOfMatchedParts - 1))) { + for (int j = i + 1; j < nbrOfRequestParts; j++) { + splatParam.append("/"); + splatParam.append(request.get(j)); + } + } + splat.add(splatParam.toString()); + } + } + return Collections.unmodifiableList(splat); + }*/ protected static List getSplat(List request, List matched) { diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 200860f0b..1ef44b84b 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -1237,8 +1237,7 @@ public V executeAndCommit(Class returnType) { if(isCache()){ LOGGER.debug("更新缓存:" + model.getName() + " -> count,list"); - sql2oCache.hdel(CACHE_KEY_COUNT); - sql2oCache.hdel(CACHE_KEY_LIST); + cleanAll(); } if(null == query){ @@ -1259,8 +1258,7 @@ public V executeAndCommit(Class returnType) { if(isCache()){ LOGGER.debug("更新缓存:" + model.getName() + " -> detail,list"); - sql2oCache.hdel(CACHE_KEY_DETAIL); - sql2oCache.hdel(CACHE_KEY_LIST); + cleanAll(); } if(null == query){ @@ -1276,9 +1274,7 @@ public V executeAndCommit(Class returnType) { if(isCache()){ LOGGER.debug("更新缓存:" + model.getName() + " -> count,list,detail"); - sql2oCache.hdel(CACHE_KEY_COUNT); - sql2oCache.hdel(CACHE_KEY_LIST); - sql2oCache.hdel(CACHE_KEY_DETAIL); + cleanAll(); } if(null == query){ LOGGER.error("query is null"); @@ -1451,9 +1447,6 @@ private Query updateCommit(Connection conn){ LOGGER.debug("execute sql:" + query.toString()); LOGGER.debug("execute parameter:" + condition.params.values() + condition.equalsParams.values()); - if(null != conn){ - conn.close(); - } return query; } return null; From eb12e8d61800eb677949de2f40db0b49ce863f2d Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 14 Sep 2015 10:25:48 +0800 Subject: [PATCH 142/545] optimize the context --- .../src/main/java/blade/BladeFilter.java | 8 +- .../src/main/java/blade/BladeWebContext.java | 138 +++++++----------- blade-core/src/main/java/blade/Bootstrap.java | 4 +- .../src/main/java/blade/RequestHandler.java | 2 +- 4 files changed, 57 insertions(+), 95 deletions(-) diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java index 88ac708c0..ccd2b7b12 100644 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ b/blade-core/src/main/java/blade/BladeFilter.java @@ -44,7 +44,7 @@ public class BladeFilter implements Filter { /** * blade全局初始化类 */ - private static final String APPLCATION_CLASS = "applicationClass"; + private static final String BOOSTRAP_CLASS = "bootstrapClass"; @Override public void init(FilterConfig filterConfig) throws ServletException { @@ -55,9 +55,7 @@ public void init(FilterConfig filterConfig) throws ServletException { Blade.webRoot(filterConfig.getServletContext().getRealPath("/")); - BladeWebContext.servletContext(filterConfig.getServletContext()); - - final Bootstrap bootstrap = getBootstrap(filterConfig.getInitParameter(APPLCATION_CLASS)); + final Bootstrap bootstrap = getBootstrap(filterConfig.getInitParameter(BOOSTRAP_CLASS)); bootstrap.init(); Blade.app(bootstrap); @@ -66,7 +64,7 @@ public void init(FilterConfig filterConfig) throws ServletException { IocApplication.init(); - bootstrap.contextInitialized(BladeWebContext.servletContext()); + bootstrap.contextInitialized(); Blade.init(); diff --git a/blade-core/src/main/java/blade/BladeWebContext.java b/blade-core/src/main/java/blade/BladeWebContext.java index 834e3f827..cb0f4086b 100644 --- a/blade-core/src/main/java/blade/BladeWebContext.java +++ b/blade-core/src/main/java/blade/BladeWebContext.java @@ -21,9 +21,6 @@ import blade.servlet.Request; import blade.servlet.Response; -import blade.servlet.Session; -import blade.wrapper.RequestWrapper; -import blade.wrapper.ResponseWrapper; /** * 全局的WeContext @@ -36,109 +33,78 @@ public final class BladeWebContext { /** * 当前线程的Request对象 */ - private static ThreadLocal currentRequest = new ThreadLocal(); - - /** - * 当前线程的Response对象 - */ - private static ThreadLocal currentResponse = new ThreadLocal(); + private static final ThreadLocal BLADE_WEB_CONTEXT = new ThreadLocal(); /** * ServletContext对象,在应用初始化时创建 */ - private static ServletContext servletContext; + private ServletContext context; + private HttpServletRequest httpServletRequest; + private HttpServletResponse httpServletResponse; + private Request request; + private Response response; private BladeWebContext(){} - /** - * @return 返回当前线程的Request对象 - */ - public static Request request() { - return requestWrapper().getDelegate(); + public static BladeWebContext me(){ + return BLADE_WEB_CONTEXT.get(); } - /** - * @return 返回当前线程的RequestWrapper对象 - */ - public static RequestWrapper requestWrapper() { - return currentRequest.get(); + static void setContext(ServletContext servletContext, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Request request, Response response) { + BladeWebContext bladeWebContext = new BladeWebContext(); + bladeWebContext.context = servletContext; + bladeWebContext.httpServletRequest = httpServletRequest; + bladeWebContext.httpServletResponse = httpServletResponse; + bladeWebContext.request = request; + bladeWebContext.response = response; + BLADE_WEB_CONTEXT.set(bladeWebContext); } /** - * @return 返回当前线程的HttpServletRequest对象 - */ - public static HttpServletRequest servletRequest() { - return request().servletRequest(); - } - - /** - * @return 返回当前线程的Response对象 + * 移除当前线程的Request、Response对象 */ - public static Response response() { - return responseWrapper().getDelegate(); + public static void remove(){ + BLADE_WEB_CONTEXT.remove(); } - /** - * @return 返回当前线程的RequestWrapper对象 - */ - public static ResponseWrapper responseWrapper() { - return currentResponse.get(); + public static Request request() { + return BladeWebContext.me().request; } - - /** - * @return 返回当前线程的HttpServletResponse对象 - */ - public static HttpServletResponse servletResponse() { - return response().servletResponse(); + public static Response response() { + return BladeWebContext.me().response; } + + public static ServletContext servletContext() { + return BladeWebContext.me().context; + } + + public static HttpServletResponse servletResponse() { + return BladeWebContext.me().httpServletResponse; + } + + public static HttpServletRequest servletRequest() { + return BladeWebContext.me().httpServletRequest; + } - /** - * @return 返回当前线程的Session对象 - */ - public static Session session() { - return request().session(); - } + public ServletContext getContext() { + return context; + } - /** - * 设置ServletContext - * - * @param servletContext ServletContext对象 - */ - public static void servletContext(ServletContext servletContext) { - BladeWebContext.servletContext = servletContext; + public HttpServletRequest getHttpServletRequest() { + return httpServletRequest; } - - /** - * @return 返回当前线程的ServletContext对象 - */ - public static ServletContext servletContext() { - return servletContext; - } - - /** - * 设置context对象到ActionContext中 - * - * @param requestWrapper RequestWrapper对象 - * @param responseWrapper ResponseWrapper对象 - */ - public static void init(RequestWrapper requestWrapper, ResponseWrapper responseWrapper) { - remove(); - currentRequest.set(requestWrapper); - currentResponse.set(responseWrapper); - } - - /** - * 移除当前线程的Request、Response对象 - */ - public static void remove(){ - currentRequest.remove(); - currentResponse.remove(); - } - public static void destroy(){ - remove(); - currentRequest = null; - currentResponse = null; - } + public HttpServletResponse getHttpServletResponse() { + return httpServletResponse; + } + + public Request getRequest() { + return request; + } + + public Response getResponse() { + return response; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/blade/Bootstrap.java b/blade-core/src/main/java/blade/Bootstrap.java index 0da16a3c4..3c9c15209 100644 --- a/blade-core/src/main/java/blade/Bootstrap.java +++ b/blade-core/src/main/java/blade/Bootstrap.java @@ -15,8 +15,6 @@ */ package blade; -import javax.servlet.ServletContext; - /** * Blade全局初始化类,可以在应用启动的时候做一些操作 * @@ -30,7 +28,7 @@ public abstract class Bootstrap { */ public abstract void init(); - public void contextInitialized(ServletContext servletContext){ + public void contextInitialized(){ // } } diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 967fb619c..407dabc51 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -197,7 +197,7 @@ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper reques } // 初始化context - BladeWebContext.init(requestWrapper, responseWrapper); + BladeWebContext.setContext(httpRequest.getServletContext(), httpRequest, responseWrapper.servletResponse(), requestWrapper, responseWrapper); if(null != router){ From e6dc409a803a15a59c856c7bd8e8b7f4f9fb6418 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 14 Sep 2015 10:47:17 +0800 Subject: [PATCH 143/545] fix request PathParam --- .../java/blade/route/DefaultRouteMatcher.java | 10 +--- .../main/java/blade/route/RouteMatcher.java | 10 ++++ .../java/blade/route/RouteMatcherBuilder.java | 6 +-- .../src/main/java/blade/servlet/Request.java | 53 ++----------------- 4 files changed, 18 insertions(+), 61 deletions(-) diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java index 332e4d570..022a2ccfe 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java @@ -56,7 +56,6 @@ public static DefaultRouteMatcher instance(){ * * @param httpMethod http请求方法,GET/POST * @param uri 请求路径 - * @param acceptType 请求的acceptType * @return 返回一个路由匹配对象 */ public RouteMatcher findRoute(HttpMethod httpMethod, String uri) { @@ -90,7 +89,6 @@ public int compare(RouteMatcher o1, RouteMatcher o2) { * * @param httpMethod http请求方法,GET/POST * @param path 请求路径 - * @param acceptType 请求的acceptType * @return 返回一个路由匹配对象集合 */ public List findInterceptor(HttpMethod httpMethod, String uri) { @@ -121,7 +119,6 @@ public void clearRoutes() { * @param execMethod 路由执行方法 * @param url 路由url * @param method 路由http方法 - * @param acceptType 路由acceptType */ public void addRoute(Class target, Method execMethod, String url, HttpMethod method) { RouteMatcher entry = new RouteMatcher(); @@ -145,7 +142,6 @@ public void addRoute(Class target, Method execMethod, String url, HttpMethod * @param execMethod 路由执行方法 * @param url 路由url * @param method 路由http方法 - * @param acceptType 路由acceptType */ public void addInterceptor(Class target, Method execMethod, String url, HttpMethod method) { RouteMatcher entry = new RouteMatcher(); @@ -168,9 +164,8 @@ public void addInterceptor(Class target, Method execMethod, String url, HttpM * @param router 执行的匿名类 * @param url 路由url * @param method 路由http方法 - * @param acceptType 路由acceptType */ - public void addRoute(Router router, String url, HttpMethod method, String acceptType) { + public void addRoute(Router router, String url, HttpMethod method) { RouteMatcher entry = new RouteMatcher(); entry.router = router; entry.httpMethod = method; @@ -190,9 +185,8 @@ public void addRoute(Router router, String url, HttpMethod method, String accept * @param router 执行的匿名类 * @param url 路由url * @param method 路由http方法 - * @param acceptType 路由acceptType */ - public void addInterceptor(Router router, String url, HttpMethod method, String acceptType) { + public void addInterceptor(Router router, String url, HttpMethod method) { RouteMatcher entry = new RouteMatcher(); entry.router = router; entry.httpMethod = method; diff --git a/blade-core/src/main/java/blade/route/RouteMatcher.java b/blade-core/src/main/java/blade/route/RouteMatcher.java index de2f3ff2e..17f06d059 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/blade/route/RouteMatcher.java @@ -48,6 +48,11 @@ public class RouteMatcher { */ HttpMethod httpMethod; + /** + * 请求URI + */ + String requestURI; + /** * 路由path */ @@ -62,6 +67,7 @@ public RouteMatcher(Router router, Class target, Method execMethod, HttpMetho this.execMethod = execMethod; this.httpMethod = httpMethod; this.path = path; + this.requestURI = requestUri; } public HttpMethod getHttpMethod() { @@ -230,5 +236,9 @@ public boolean equals(Object obj) { public String toString() { return httpMethod.name() + ":" + path; } + + public String getRequestURI() { + return requestURI; + } } diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index acd6edd62..e1a5e7241 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -147,7 +147,7 @@ public static void buildFunctional(String path, Class clazz, String methodNam */ public static void buildHandler(String path, Router router, HttpMethod httpMethod){ if(StringKit.isNotBlank(path) && null != router){ - defaultRouteMatcher.addRoute(router, path, httpMethod, "*/*"); + defaultRouteMatcher.addRoute(router, path, httpMethod); } else { throw new BladeException("an unqualified configuration"); } @@ -158,7 +158,7 @@ public static void buildHandler(String path, Router router, HttpMethod httpMetho */ public static void buildInterceptor(String path, Router router, HttpMethod httpMethod){ if(StringKit.isNotBlank(path) && null != router){ - defaultRouteMatcher.addInterceptor(router, path, httpMethod, "*/*"); + defaultRouteMatcher.addInterceptor(router, path, httpMethod); } else { throw new BladeException("an unqualified configuration"); } @@ -366,7 +366,6 @@ private static String getRoutePath(String value, String nameSpace, String suffix * @param execMethod 路由执行方法 * @param path 路由url * @param method 路由http方法 - * @param acceptType 路由acceptType */ private static void buildRoute(Class target, Method execMethod, String path, HttpMethod method){ defaultRouteMatcher.addRoute(target, execMethod, path, method); @@ -379,7 +378,6 @@ private static void buildRoute(Class target, Method execMethod, String path, * @param target 路由目标执行的class * @param execMethod 路由执行方法 * @param method 路由http方法 - * @param acceptType 路由acceptType */ private static void buildInterceptor(String path, Class target, Method execMethod, HttpMethod method){ defaultRouteMatcher.addInterceptor(target, execMethod, path, method); diff --git a/blade-core/src/main/java/blade/servlet/Request.java b/blade-core/src/main/java/blade/servlet/Request.java index 163986a76..f25434cbe 100644 --- a/blade-core/src/main/java/blade/servlet/Request.java +++ b/blade-core/src/main/java/blade/servlet/Request.java @@ -87,12 +87,11 @@ public Request(RouteMatcher match, HttpServletRequest request) { */ public void initRequest(RouteMatcher match) { - List requestList = PathKit.convertRouteToList(match.getPath()); + List requestList = PathKit.convertRouteToList(match.getRequestURI()); List pathList = PathKit.convertRouteToList(match.getPath()); - this.pathParams = getPathParams(requestList); + this.pathParams = getPathParams(requestList, pathList); this.splat = getSplat(requestList, pathList); - } /** @@ -523,24 +522,7 @@ public String protocol() { return servletRequest.getProtocol(); } - protected static Map getPathParams(List request) { - - Map params = CollectionKit.newHashMap(); - - for (int i = 0; (i < request.size()); i++) { - String matchedPart = request.get(i); - if (PathKit.isParam(matchedPart)) { - LOGGER.debug("matchedPart: " - + matchedPart - + " = " - + request.get(i)); - params.put(matchedPart.toLowerCase(), request.get(i)); - } - } - return Collections.unmodifiableMap(params); - } - - /*protected static Map getPathParams(List request, List matched) { +protected static Map getPathParams(List request, List matched) { Map params = CollectionKit.newHashMap(); @@ -555,34 +537,7 @@ protected static Map getPathParams(List request) { } } return Collections.unmodifiableMap(params); - }*/ - - /*protected static List getSplat(List request, List matched) { - - int nbrOfRequestParts = request.size(); - int nbrOfMatchedParts = matched.size(); - - boolean sameLength = (nbrOfRequestParts == nbrOfMatchedParts); - - List splat = CollectionKit.newArrayList(); - - for (int i = 0; (i < nbrOfRequestParts) && (i < nbrOfMatchedParts); i++) { - String matchedPart = matched.get(i); - - if (PathKit.isSplat(matchedPart)) { - - StringBuilder splatParam = new StringBuilder(request.get(i)); - if (!sameLength && (i == (nbrOfMatchedParts - 1))) { - for (int j = i + 1; j < nbrOfRequestParts; j++) { - splatParam.append("/"); - splatParam.append(request.get(j)); - } - } - splat.add(splatParam.toString()); - } - } - return Collections.unmodifiableList(splat); - }*/ + } protected static List getSplat(List request, List matched) { From 72692e3ea2b23282fd090fe443d8672f55b042d5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 14 Sep 2015 11:22:32 +0800 Subject: [PATCH 144/545] update version --- LAST_VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 004fc616a..9b22a79f1 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -14,7 +14,7 @@     com.bladejava     blade-core -    1.2.9-beta +    1.2.9 ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) From 507ac052e171a7463fa7ee2d62a1a58d676f6d2d Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 14 Sep 2015 13:38:07 +0800 Subject: [PATCH 145/545] update version --- LAST_VERSION.md | 18 ++++++++++++++++++ .../src/main/java/blade/BladeWebContext.java | 13 ++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 9b22a79f1..d18830357 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -1,5 +1,23 @@ # blade last version +如果在maven仓库中下载不到最新版本的依赖,请添加maven snapshots仓库 +```xml + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + +``` +和`dependencies`相同级别 + + ## [blade-kit](http://search.maven.org/#search%7Cga%7C1%7Cblade-kit) ```xml diff --git a/blade-core/src/main/java/blade/BladeWebContext.java b/blade-core/src/main/java/blade/BladeWebContext.java index cb0f4086b..f26f8b356 100644 --- a/blade-core/src/main/java/blade/BladeWebContext.java +++ b/blade-core/src/main/java/blade/BladeWebContext.java @@ -21,6 +21,9 @@ import blade.servlet.Request; import blade.servlet.Response; +import blade.servlet.Session; +import blade.wrapper.RequestWrapper; +import blade.wrapper.ResponseWrapper; /** * 全局的WeContext @@ -50,13 +53,13 @@ public static BladeWebContext me(){ return BLADE_WEB_CONTEXT.get(); } - static void setContext(ServletContext servletContext, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Request request, Response response) { + static void setContext(ServletContext servletContext, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, RequestWrapper request, ResponseWrapper response) { BladeWebContext bladeWebContext = new BladeWebContext(); bladeWebContext.context = servletContext; bladeWebContext.httpServletRequest = httpServletRequest; bladeWebContext.httpServletResponse = httpServletResponse; - bladeWebContext.request = request; - bladeWebContext.response = response; + bladeWebContext.request = request.getDelegate(); + bladeWebContext.response = response.getDelegate(); BLADE_WEB_CONTEXT.set(bladeWebContext); } @@ -75,6 +78,10 @@ public static Response response() { return BladeWebContext.me().response; } + public static Session session() { + return request().session(); + } + public static ServletContext servletContext() { return BladeWebContext.me().context; } From c765e1e7526ffbc6fc787533c7ce77e0186ba05c Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 15 Sep 2015 18:36:40 +0800 Subject: [PATCH 146/545] update blade redis version --- .../blade/plugin/redis/RedisExecutor.java | 9 ++++--- .../java/blade/plugin/redis/RedisLock.java | 4 +-- .../java/blade/plugin/redis/RedisPlugin.java | 27 +++++++++++++++---- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java b/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java index 5787ba6bd..272f148cc 100644 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java +++ b/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java @@ -31,11 +31,11 @@ public class RedisExecutor { // 数据源 private static ShardedJedisPool shardedJedisPool; - private static RedisPoolConfig redisPoolConfig = RedisPlugin.INSTANCE.redisPoolConfig(); + private static RedisPoolConfig redisPoolConfig = RedisPlugin.me().redisPoolConfig(); - static{ + static void init(){ // 根据配置文件,创建shared池实例 - shardedJedisPool = new ShardedJedisPool(redisPoolConfig, RedisPlugin.INSTANCE.shards()); + shardedJedisPool = new ShardedJedisPool(redisPoolConfig, RedisPlugin.me().shards()); } /** @@ -64,7 +64,8 @@ public Executor(ShardedJedisPool shardedJedisPool) { * * @return 执行结果 */ - public T getResult() { + @SuppressWarnings("deprecation") + public T getResult() { T result = null; try { result = execute(); diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisLock.java b/blade-redis/src/main/java/blade/plugin/redis/RedisLock.java index 0743dccc3..7abe9b188 100644 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisLock.java +++ b/blade-redis/src/main/java/blade/plugin/redis/RedisLock.java @@ -113,8 +113,8 @@ public void unlock() { this.jedis.del(this.key); } } finally { - this.shardedJedisPool.returnResourceObject(this.jedis); -// this.shardedJedisPool.returnResource(this.jedis); + this.shardedJedisPool.close(); +// this.shardedJedisPool.returnResourceObject(this.jedis); } } } diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java b/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java index 865050f21..be62d1408 100644 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java +++ b/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java @@ -24,6 +24,10 @@ private RedisPlugin() { shards = new ArrayList(); } + public static RedisPlugin me(){ + return INSTANCE; + } + /** * redis连接池配置 */ @@ -40,26 +44,39 @@ public RedisPoolConfig redisPoolConfig() { public RedisPlugin host(String host, int port) { shards.add(new JedisShardInfo(host, port)); - return INSTANCE; + return this; + } + + public RedisPlugin host(String host, int port, String auth) { + JedisShardInfo jedisShardInfo = new JedisShardInfo(host, port); + jedisShardInfo.setPassword(auth); + shards.add(jedisShardInfo); + return this; } public RedisPlugin host(JedisShardInfo jedisShardInfo) { shards.add(jedisShardInfo); - return INSTANCE; + return this; } public RedisPlugin host(String host) { shards.add(new JedisShardInfo(host)); - return INSTANCE; + return this; } public List shards() { - return INSTANCE.shards; + return this.shards; } @Override public void run() { - LOGGER.info("redis插件配置成功..."); + RedisExecutor.init(); + LOGGER.info("redis plugin config success!"); + } + + @Override + public void destroy() { + shards.clear(); } } From ea2b67e3682b769eadc8664a744f47e2b2df5cd4 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 15 Sep 2015 18:37:03 +0800 Subject: [PATCH 147/545] update version --- LAST_VERSION.md | 2 +- blade-redis/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index d18830357..908c7ada0 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -85,6 +85,6 @@     com.bladejava     blade-redis -    1.2.1 +    1.2.2 ``` \ No newline at end of file diff --git a/blade-redis/README.md b/blade-redis/README.md index d949e489d..ec29a7327 100644 --- a/blade-redis/README.md +++ b/blade-redis/README.md @@ -6,7 +6,7 @@ ```java // 配置 -RedisPlugin redisPlugin = RedisPlugin.INSTANCE; +RedisPlugin redisPlugin = RedisPlugin.me(); redisPlugin.host("127.0.0.1", 6379); redisPlugin.run(); ``` From e5f0c727e2444f1121ce79cf565c7ad7c8e2f0bb Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 22 Sep 2015 17:20:11 +0800 Subject: [PATCH 148/545] fix the jetty servletContext --- LAST_VERSION.md | 2 +- blade-core/src/main/java/blade/BladeFilter.java | 6 ++++++ blade-core/src/main/java/blade/RequestHandler.java | 2 +- blade-redis/pom.xml | 4 ++-- pom.xml | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 908c7ada0..1ac1f3a1d 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -32,7 +32,7 @@     com.bladejava     blade-core -    1.2.9 +    1.3.0-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/BladeFilter.java index ccd2b7b12..c6728f9ab 100644 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ b/blade-core/src/main/java/blade/BladeFilter.java @@ -20,6 +20,7 @@ import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; @@ -46,6 +47,9 @@ public class BladeFilter implements Filter { */ private static final String BOOSTRAP_CLASS = "bootstrapClass"; + static ServletContext servletContext; + + @Override public void init(FilterConfig filterConfig) throws ServletException { @@ -64,6 +68,8 @@ public void init(FilterConfig filterConfig) throws ServletException { IocApplication.init(); + servletContext = filterConfig.getServletContext(); + bootstrap.contextInitialized(); Blade.init(); diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 407dabc51..7432340b9 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -197,7 +197,7 @@ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper reques } // 初始化context - BladeWebContext.setContext(httpRequest.getServletContext(), httpRequest, responseWrapper.servletResponse(), requestWrapper, responseWrapper); + BladeWebContext.setContext(BladeFilter.servletContext, httpRequest, responseWrapper.servletResponse(), requestWrapper, responseWrapper); if(null != router){ diff --git a/blade-redis/pom.xml b/blade-redis/pom.xml index 25a8e92c5..424711890 100644 --- a/blade-redis/pom.xml +++ b/blade-redis/pom.xml @@ -11,7 +11,7 @@ blade-redis jar - 1.2.1 + 1.2.2 blade-redis https://github.com/biezhi/blade/blade-redis @@ -25,7 +25,7 @@ redis.clients jedis - 2.7.2 + 2.7.3 diff --git a/pom.xml b/pom.xml index c78bbdaa1..02b49543d 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ UTF-8 4.11 3.0.1 - 1.2.9 + 1.3.0-alpha From 52d11b09d1116aaabc780bed3cc29066da9f8fdc Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 22 Sep 2015 17:21:14 +0800 Subject: [PATCH 149/545] update readme --- README.md | 2 +- README_CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3e2bda72a..edcd80b11 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LI ## Contact -OSC Blog:[http://my.oschina.net/biezhi](http://my.oschina.net/biezhi) +Blog:[https://biezhi.me](https://biezhi.me) Mail: biezhi.me#gmail.com diff --git a/README_CN.md b/README_CN.md index 8ff774b61..c4735feff 100644 --- a/README_CN.md +++ b/README_CN.md @@ -89,7 +89,7 @@ Blade框架基于 [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.h ## 联系我 -OSC Blog:[http://my.oschina.net/biezhi](http://my.oschina.net/biezhi) +Blog:[https://biezhi.me](https://biezhi.me) Mail: biezhi.me#gmail.com From 886f14a799523b2a43661f4ff6f89b2a04ea3338 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 10:09:57 +0800 Subject: [PATCH 150/545] simple the class name --- blade-core/src/main/java/blade/Blade.java | 54 +++++++++---------- .../blade/{BladeConfig.java => Config.java} | 4 +- ...adeConfigurator.java => Configurator.java} | 6 +-- .../{BladeFilter.java => CoreFilter.java} | 4 +- .../src/main/java/blade/RequestHandler.java | 2 +- .../blade/exception/ExceptionHandler.java | 10 ++++ .../exception/WebApplicationException.java | 45 ++++++++++++++++ .../java/blade/route/RouteMatcherBuilder.java | 4 +- .../main/java/blade/route/RouterChain.java | 7 +++ .../test/java/org/blade/server/AppTest.java | 38 +++++++++++++ 10 files changed, 137 insertions(+), 37 deletions(-) rename blade-core/src/main/java/blade/{BladeConfig.java => Config.java} (98%) rename blade-core/src/main/java/blade/{BladeConfigurator.java => Configurator.java} (93%) rename blade-core/src/main/java/blade/{BladeFilter.java => CoreFilter.java} (93%) create mode 100644 blade-core/src/main/java/blade/exception/ExceptionHandler.java create mode 100644 blade-core/src/main/java/blade/exception/WebApplicationException.java create mode 100644 blade-core/src/main/java/blade/route/RouterChain.java create mode 100644 blade-server/src/test/java/org/blade/server/AppTest.java diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index c4e0f16b8..0e75b0416 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -55,7 +55,7 @@ public final class Blade { /** * 全局配置对象 */ - protected final static BladeConfig BLADE_CONFIG = new BladeConfig(); + protected final static Config CONFIG = new Config(); /** * IOC容器,存储路由到ioc中 @@ -134,7 +134,7 @@ public static synchronized void configJson(String json){ * @param configMap 存放配置的map */ private static void configuration(Map configMap){ - new BladeConfigurator(Blade.BLADE_CONFIG, configMap).run(); + new Configurator(CONFIG, configMap).run(); } /** @@ -145,7 +145,7 @@ private static void configuration(Map configMap){ */ public static synchronized void routes(String...packages){ if(null != packages && packages.length >0){ - BLADE_CONFIG.setRoutePackages(packages); + CONFIG.setRoutePackages(packages); } } @@ -157,7 +157,7 @@ public static synchronized void routes(String...packages){ */ public static synchronized void defaultRoute(String basePackage){ if(null != basePackage){ - BLADE_CONFIG.setBasePackage(basePackage); + CONFIG.setBasePackage(basePackage); } } @@ -168,7 +168,7 @@ public static synchronized void defaultRoute(String basePackage){ */ public static synchronized void interceptor(String packageName) { if(null != packageName && packageName.length() >0){ - BLADE_CONFIG.setInterceptorPackage(packageName); + CONFIG.setInterceptorPackage(packageName); } } @@ -179,7 +179,7 @@ public static synchronized void interceptor(String packageName) { */ public static synchronized void ioc(String...packages){ if(null != packages && packages.length >0){ - BLADE_CONFIG.setIocPackages(packages); + CONFIG.setIocPackages(packages); } } @@ -199,7 +199,7 @@ public static synchronized void viewEngin(Render render) { */ public static synchronized void viewPrefix(final String prefix) { if(null != prefix && prefix.startsWith("/")){ - BLADE_CONFIG.setViewPrefix(prefix); + CONFIG.setViewPrefix(prefix); } } @@ -210,7 +210,7 @@ public static synchronized void viewPrefix(final String prefix) { */ public static synchronized void viewSuffix(final String suffix) { if(null != suffix && suffix.startsWith(".")){ - BLADE_CONFIG.setViewSuffix(suffix); + CONFIG.setViewSuffix(suffix); } } @@ -231,7 +231,7 @@ public static synchronized void view(final String viewPath, final String viewExt * @param folders */ public static synchronized void staticFolder(final String ... folders) { - BLADE_CONFIG.setStaticFolders(folders); + CONFIG.setStaticFolders(folders); } /** @@ -249,7 +249,7 @@ public static synchronized void app(Bootstrap bootstrap){ * @param view404 404视图页面 */ public static synchronized void view404(final String view404){ - BLADE_CONFIG.setView404(view404); + CONFIG.setView404(view404); } /** @@ -258,7 +258,7 @@ public static synchronized void view404(final String view404){ * @param view500 500视图页面 */ public static synchronized void view500(final String view500){ - BLADE_CONFIG.setView500(view500); + CONFIG.setView500(view500); } /** @@ -267,7 +267,7 @@ public static synchronized void view500(final String view500){ * @param webRoot web根目录物理路径 */ public static synchronized void webRoot(final String webRoot){ - BLADE_CONFIG.setWebRoot(webRoot); + CONFIG.setWebRoot(webRoot); } /** @@ -275,7 +275,7 @@ public static synchronized void webRoot(final String webRoot){ * @param isdebug true:是,默认true;false:否 */ public static synchronized void debug(boolean isdebug){ - BLADE_CONFIG.setDebug(isdebug); + CONFIG.setDebug(isdebug); } /** @@ -549,36 +549,36 @@ public static synchronized RouterExecutor after(String... paths){ return null; } - public final static BladeConfig config(){ - return BLADE_CONFIG; + public final static Config config(){ + return CONFIG; } /** * @return 返回Blade要扫描的基础包 */ public static String basePackage(){ - return BLADE_CONFIG.getBasePackage(); + return CONFIG.getBasePackage(); } /** * @return 返回路由包数组 */ public static String[] routes(){ - return BLADE_CONFIG.getRoutePackages(); + return CONFIG.getRoutePackages(); } /** * @return 返回IOC所有包 */ public static String[] iocs(){ - return BLADE_CONFIG.getIocPackages(); + return CONFIG.getIocPackages(); } /** * @return 返回拦截器包数组,只有一个元素 这里统一用String[] */ public static String interceptor(){ - return BLADE_CONFIG.getInterceptorPackage(); + return CONFIG.getInterceptorPackage(); } @@ -586,56 +586,56 @@ public static String interceptor(){ * @return 返回视图存放路径 */ public static String viewPrefix(){ - return BLADE_CONFIG.getViewPrefix(); + return CONFIG.getViewPrefix(); } /** * @return 返回系统默认字符编码 */ public static String encoding(){ - return BLADE_CONFIG.getEncoding(); + return CONFIG.getEncoding(); } /** * @return 返回balde启动端口 */ public static String viewSuffix(){ - return BLADE_CONFIG.getViewSuffix(); + return CONFIG.getViewSuffix(); } /** * @return 返回404视图 */ public static String view404(){ - return BLADE_CONFIG.getView404(); + return CONFIG.getView404(); } /** * @return 返回500视图 */ public static String view500(){ - return BLADE_CONFIG.getView500(); + return CONFIG.getView500(); } /** * @return 返回webroot路径 */ public static String webRoot(){ - return BLADE_CONFIG.getWebRoot(); + return CONFIG.getWebRoot(); } /** * @return 返回系统是否以debug方式运行 */ public static boolean debug(){ - return BLADE_CONFIG.isDebug(); + return CONFIG.isDebug(); } /** * @return 返回静态资源目录 */ public static String[] staticFolder(){ - return BLADE_CONFIG.getStaticFolders(); + return CONFIG.getStaticFolders(); } /** diff --git a/blade-core/src/main/java/blade/BladeConfig.java b/blade-core/src/main/java/blade/Config.java similarity index 98% rename from blade-core/src/main/java/blade/BladeConfig.java rename to blade-core/src/main/java/blade/Config.java index 5520ee7c6..35edef740 100644 --- a/blade-core/src/main/java/blade/BladeConfig.java +++ b/blade-core/src/main/java/blade/Config.java @@ -28,7 +28,7 @@ * @since 1.0 * */ -public class BladeConfig { +public class Config { // 存放所有变量 private Map configMap = CollectionKit.newHashMap(); @@ -57,7 +57,7 @@ public class BladeConfig { // 是否是DEBUG模式 private boolean isDebug = true; - public BladeConfig() { + public Config() { } public Map getConfigMap() { diff --git a/blade-core/src/main/java/blade/BladeConfigurator.java b/blade-core/src/main/java/blade/Configurator.java similarity index 93% rename from blade-core/src/main/java/blade/BladeConfigurator.java rename to blade-core/src/main/java/blade/Configurator.java index d5d3135b7..678e9e3db 100644 --- a/blade-core/src/main/java/blade/BladeConfigurator.java +++ b/blade-core/src/main/java/blade/Configurator.java @@ -25,15 +25,15 @@ * @author biezhi * @since 1.0 */ -public class BladeConfigurator { +public class Configurator { // 配置文件对象 - private BladeConfig bladeConfig; + private Config bladeConfig; // 配置map private Map configMap; - public BladeConfigurator(BladeConfig bladeConfig, + public Configurator(Config bladeConfig, Map configMap) { this.bladeConfig = bladeConfig; this.configMap = configMap; diff --git a/blade-core/src/main/java/blade/BladeFilter.java b/blade-core/src/main/java/blade/CoreFilter.java similarity index 93% rename from blade-core/src/main/java/blade/BladeFilter.java rename to blade-core/src/main/java/blade/CoreFilter.java index c6728f9ab..4e37ab6be 100644 --- a/blade-core/src/main/java/blade/BladeFilter.java +++ b/blade-core/src/main/java/blade/CoreFilter.java @@ -38,9 +38,9 @@ * @author biezhi * @since 1.0 */ -public class BladeFilter implements Filter { +public class CoreFilter implements Filter { - private static final Logger LOGGER = Logger.getLogger(BladeFilter.class); + private static final Logger LOGGER = Logger.getLogger(CoreFilter.class); /** * blade全局初始化类 diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 7432340b9..849b3cd42 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -197,7 +197,7 @@ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper reques } // 初始化context - BladeWebContext.setContext(BladeFilter.servletContext, httpRequest, responseWrapper.servletResponse(), requestWrapper, responseWrapper); + BladeWebContext.setContext(CoreFilter.servletContext, httpRequest, responseWrapper.servletResponse(), requestWrapper, responseWrapper); if(null != router){ diff --git a/blade-core/src/main/java/blade/exception/ExceptionHandler.java b/blade-core/src/main/java/blade/exception/ExceptionHandler.java new file mode 100644 index 000000000..a8728db61 --- /dev/null +++ b/blade-core/src/main/java/blade/exception/ExceptionHandler.java @@ -0,0 +1,10 @@ +package blade.exception; + +import blade.servlet.Request; +import blade.servlet.Response; + +public interface ExceptionHandler { + + void handle(Exception e, Request request, Response response); + +} diff --git a/blade-core/src/main/java/blade/exception/WebApplicationException.java b/blade-core/src/main/java/blade/exception/WebApplicationException.java new file mode 100644 index 000000000..bb8300b9a --- /dev/null +++ b/blade-core/src/main/java/blade/exception/WebApplicationException.java @@ -0,0 +1,45 @@ +package blade.exception; + +public class WebApplicationException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + protected int status; + + protected String name; + + public WebApplicationException(int status, String name) { + this.status = status; + this.name = name; + } + + public WebApplicationException(int status, String name, String message) { + super(message); + this.status = status; + this.name = name; + } + + public WebApplicationException(int status, String name, Throwable cause) { + super(cause); + this.status = status; + this.name = name; + } + + public WebApplicationException(int status, String name, String message, Throwable cause) { + super(message, cause); + this.status = status; + this.name = name; + } + + public static long getSerialversionuid() { + return serialVersionUID; + } + + public int getStatus() { + return status; + } + + public String getName() { + return name; + } +} diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index e1a5e7241..87c904f9e 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -292,7 +292,7 @@ private static void parseInterceptor(final Class interceptor){ buildInterceptor(path, interceptor, method, HttpMethod.AFTER); - String[] paths = before.values(); + String[] paths = after.values(); if(null != paths && paths.length > 0){ for(String value : paths){ String pathV = getRoutePath(value, "", suffix); @@ -391,4 +391,4 @@ private static HttpMethod getHttpMethod(String name){ } return null; } -} +} \ No newline at end of file diff --git a/blade-core/src/main/java/blade/route/RouterChain.java b/blade-core/src/main/java/blade/route/RouterChain.java new file mode 100644 index 000000000..9758664d1 --- /dev/null +++ b/blade-core/src/main/java/blade/route/RouterChain.java @@ -0,0 +1,7 @@ +package blade.route; + +public interface RouterChain { + + void next() throws Exception; + +} diff --git a/blade-server/src/test/java/org/blade/server/AppTest.java b/blade-server/src/test/java/org/blade/server/AppTest.java new file mode 100644 index 000000000..fc032d009 --- /dev/null +++ b/blade-server/src/test/java/org/blade/server/AppTest.java @@ -0,0 +1,38 @@ +package org.blade.server; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} From fa659cda545adba7a677b95198ee8dea8b0ae922 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 10:20:38 +0800 Subject: [PATCH 151/545] rename --- blade-core/src/main/java/blade/Blade.java | 26 +++---- .../src/main/java/blade/RequestHandler.java | 6 +- .../route/{Router.java => RouteHandler.java} | 2 +- .../main/java/blade/route/RouteMatcher.java | 59 ++++++++++----- .../java/blade/route/RouteMatcherBuilder.java | 5 +- .../main/java/blade/route/RouterExecutor.java | 2 +- .../route/{ => impl}/DefaultRouteMatcher.java | 73 ++++++++++--------- 7 files changed, 102 insertions(+), 71 deletions(-) rename blade-core/src/main/java/blade/route/{Router.java => RouteHandler.java} (78%) rename blade-core/src/main/java/blade/route/{ => impl}/DefaultRouteMatcher.java (76%) diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/blade/Blade.java index 0e75b0416..436dd7d2d 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/blade/Blade.java @@ -30,7 +30,7 @@ import blade.route.HttpMethod; import blade.route.RouteBase; import blade.route.RouteMatcherBuilder; -import blade.route.Router; +import blade.route.RouteHandler; import blade.route.RouterExecutor; /** @@ -315,7 +315,7 @@ public static synchronized void register(String path, Class clazz, String met * @param path * @param routeHandler */ - public static synchronized void get(String path, Router router){ + public static synchronized void get(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.GET); } @@ -335,7 +335,7 @@ public static synchronized RouterExecutor get(String... paths){ * @param path * @param routeHandler */ - public static synchronized void post(String path, Router router){ + public static synchronized void post(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.POST); } @@ -355,7 +355,7 @@ public static synchronized RouterExecutor post(String... paths){ * @param path * @param routeHandler */ - public static synchronized void delete(String path, Router router){ + public static synchronized void delete(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.DELETE); } @@ -374,7 +374,7 @@ public static synchronized RouterExecutor delete(String... paths){ * put请求 * @param paths */ - public static synchronized void put(String path, Router router){ + public static synchronized void put(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PUT); } @@ -394,7 +394,7 @@ public static synchronized RouterExecutor put(String... paths){ * @param path * @param routeHandler */ - public static synchronized void patch(String path, Router router){ + public static synchronized void patch(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PATCH); } @@ -414,7 +414,7 @@ public static synchronized RouterExecutor patch(String... paths){ * @param path * @param routeHandler */ - public static synchronized void head(String path, Router router){ + public static synchronized void head(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.HEAD); } @@ -434,7 +434,7 @@ public static synchronized RouterExecutor head(String... paths){ * @param path * @param routeHandler */ - public static synchronized void trace(String path, Router router){ + public static synchronized void trace(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.TRACE); } @@ -454,7 +454,7 @@ public static synchronized RouterExecutor trace(String... paths){ * @param path * @param routeHandler */ - public static synchronized void options(String path, Router router){ + public static synchronized void options(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.OPTIONS); } @@ -474,7 +474,7 @@ public static synchronized RouterExecutor options(String... paths){ * @param path * @param routeHandler */ - public static synchronized void connect(String path, Router router){ + public static synchronized void connect(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.CONNECT); } @@ -494,7 +494,7 @@ public static synchronized RouterExecutor connect(String... paths){ * @param path * @param routeHandler */ - public static synchronized void all(String path, Router router){ + public static synchronized void all(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.ALL); } @@ -514,7 +514,7 @@ public static synchronized RouterExecutor all(String... paths){ * @param path * @param routeHandler */ - public static synchronized void before(String path, Router routeHandler){ + public static synchronized void before(String path, RouteHandler routeHandler){ RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); } @@ -534,7 +534,7 @@ public static synchronized RouterExecutor before(String... paths){ * @param path * @param routeHandler */ - public static synchronized void after(String path, Router routeHandler){ + public static synchronized void after(String path, RouteHandler routeHandler){ RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); } diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/blade/RequestHandler.java index 849b3cd42..d18acbf65 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/blade/RequestHandler.java @@ -29,10 +29,10 @@ import blade.kit.ReflectKit; import blade.kit.log.Logger; import blade.render.ModelAndView; -import blade.route.DefaultRouteMatcher; import blade.route.HttpMethod; import blade.route.RouteMatcher; -import blade.route.Router; +import blade.route.impl.DefaultRouteMatcher; +import blade.route.RouteHandler; import blade.servlet.Request; import blade.servlet.Response; import blade.wrapper.RequestResponseBuilder; @@ -187,7 +187,7 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse */ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper requestWrapper, ResponseWrapper responseWrapper, RouteMatcher match){ Object result = null; - Router router = match.getRouter(); + RouteHandler router = match.getRouterHandler(); if (requestWrapper.getDelegate() == null) { Request request = RequestResponseBuilder.build(match, httpRequest); diff --git a/blade-core/src/main/java/blade/route/Router.java b/blade-core/src/main/java/blade/route/RouteHandler.java similarity index 78% rename from blade-core/src/main/java/blade/route/Router.java rename to blade-core/src/main/java/blade/route/RouteHandler.java index 08b13a136..bf75fb66a 100644 --- a/blade-core/src/main/java/blade/route/Router.java +++ b/blade-core/src/main/java/blade/route/RouteHandler.java @@ -3,7 +3,7 @@ import blade.servlet.Request; import blade.servlet.Response; -public interface Router { +public interface RouteHandler { public Object handler(Request request, Response response); diff --git a/blade-core/src/main/java/blade/route/RouteMatcher.java b/blade-core/src/main/java/blade/route/RouteMatcher.java index 17f06d059..f8843dd7c 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/blade/route/RouteMatcher.java @@ -31,38 +31,38 @@ public class RouteMatcher { /** * 目标运行类实例 */ - Class target; + private Class target; /** * 执行的类实例 */ - Router router; + private RouteHandler routerHandler; /** * 要运行的方法对象 */ - Method execMethod; + private Method execMethod; /** * http请求方法 */ - HttpMethod httpMethod; + private HttpMethod httpMethod; /** * 请求URI */ - String requestURI; + private String requestURI; /** * 路由path */ - String path; + private String path; public RouteMatcher() { } - public RouteMatcher(Router router, Class target, Method execMethod, HttpMethod httpMethod, String path, String requestUri) { - this.router = router; + public RouteMatcher(RouteHandler routerHandler, Class target, Method execMethod, HttpMethod httpMethod, String path, String requestUri) { + this.routerHandler = routerHandler; this.target = target; this.execMethod = execMethod; this.httpMethod = httpMethod; @@ -86,18 +86,18 @@ public Class getTarget() { return target; } - public Router getRouter() { - return router; + public RouteHandler getRouterHandler() { + return routerHandler; } - - /** + + /** * 根据http方法和path进行匹配 * * @param httpMethod http方法,GET/POST * @param path 匹配的路径 * @return true:匹配成功,false:匹配失败 */ - boolean matches(HttpMethod httpMethod, String path) { + public boolean matches(HttpMethod httpMethod, String path) { // 如果是拦截器的全部匹配模式则跳过,返回true if ((httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER) @@ -193,7 +193,7 @@ public int hashCode() { result = prime * result + ((execMethod == null) ? 0 : execMethod.hashCode()); result = prime * result + ((httpMethod == null) ? 0 : httpMethod.hashCode()); result = prime * result + ((path == null) ? 0 : path.hashCode()); - result = prime * result + ((router == null) ? 0 : router.hashCode()); + result = prime * result + ((routerHandler == null) ? 0 : routerHandler.hashCode()); result = prime * result + ((target == null) ? 0 : target.hashCode()); return result; } @@ -219,10 +219,10 @@ public boolean equals(Object obj) { return false; } else if (!path.equals(other.path)) return false; - if (router == null) { - if (other.router != null) + if (routerHandler == null) { + if (other.routerHandler != null) return false; - } else if (!router.equals(other.router)) + } else if (!routerHandler.equals(other.routerHandler)) return false; if (target == null) { if (other.target != null) @@ -232,6 +232,31 @@ public boolean equals(Object obj) { return true; } + + public void setTarget(Class target) { + this.target = target; + } + + public void setRouterHandler(RouteHandler routerHandler) { + this.routerHandler = routerHandler; + } + + public void setExecMethod(Method execMethod) { + this.execMethod = execMethod; + } + + public void setHttpMethod(HttpMethod httpMethod) { + this.httpMethod = httpMethod; + } + + public void setRequestURI(String requestURI) { + this.requestURI = requestURI; + } + + public void setPath(String path) { + this.path = path; + } + @Override public String toString() { return httpMethod.name() + ":" + path; diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java index 87c904f9e..78af675d3 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java @@ -32,6 +32,7 @@ import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; +import blade.route.impl.DefaultRouteMatcher; /** * 路由构造器 @@ -145,7 +146,7 @@ public static void buildFunctional(String path, Class clazz, String methodNam /** * Handler路由构建 */ - public static void buildHandler(String path, Router router, HttpMethod httpMethod){ + public static void buildHandler(String path, RouteHandler router, HttpMethod httpMethod){ if(StringKit.isNotBlank(path) && null != router){ defaultRouteMatcher.addRoute(router, path, httpMethod); } else { @@ -156,7 +157,7 @@ public static void buildHandler(String path, Router router, HttpMethod httpMetho /** * 函数式构建拦截器 */ - public static void buildInterceptor(String path, Router router, HttpMethod httpMethod){ + public static void buildInterceptor(String path, RouteHandler router, HttpMethod httpMethod){ if(StringKit.isNotBlank(path) && null != router){ defaultRouteMatcher.addInterceptor(router, path, httpMethod); } else { diff --git a/blade-core/src/main/java/blade/route/RouterExecutor.java b/blade-core/src/main/java/blade/route/RouterExecutor.java index 5b4fc7244..ad97b618a 100644 --- a/blade-core/src/main/java/blade/route/RouterExecutor.java +++ b/blade-core/src/main/java/blade/route/RouterExecutor.java @@ -32,7 +32,7 @@ public RouterExecutor(String[] paths, HttpMethod httpMethod) { this.httpMethod = httpMethod; } - public void run(Router router) { + public void run(RouteHandler router) { // 拦截器 if(this.httpMethod == HttpMethod.BEFORE || this.httpMethod == HttpMethod.AFTER){ for(String path : paths){ diff --git a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java b/blade-core/src/main/java/blade/route/impl/DefaultRouteMatcher.java similarity index 76% rename from blade-core/src/main/java/blade/route/DefaultRouteMatcher.java rename to blade-core/src/main/java/blade/route/impl/DefaultRouteMatcher.java index 022a2ccfe..8b3d6da8b 100644 --- a/blade-core/src/main/java/blade/route/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/blade/route/impl/DefaultRouteMatcher.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.route; +package blade.route.impl; import java.lang.reflect.Method; import java.util.Collections; @@ -23,6 +23,9 @@ import blade.Blade; import blade.kit.CollectionKit; import blade.kit.log.Logger; +import blade.route.HttpMethod; +import blade.route.RouteHandler; +import blade.route.RouteMatcher; /** * 默认的路由匹配器 @@ -69,15 +72,15 @@ public RouteMatcher findRoute(HttpMethod httpMethod, String uri) { RouteMatcher entry = routeEntries.size() > 0 ? routeEntries.get(0) : null; - return entry != null ? new RouteMatcher(entry.router, entry.target, entry.execMethod, entry.httpMethod, entry.path, uri) : null; + return entry != null ? new RouteMatcher(entry.getRouterHandler(), entry.getTarget(), entry.getExecMethod(), entry.getHttpMethod(), entry.getPath(), uri) : null; } private void giveMatch(final String uri, List routeEntries) { Collections.sort(routeEntries, new Comparator() { @Override public int compare(RouteMatcher o1, RouteMatcher o2) { - if(o2.path.equals(uri)){ - return o2.path.indexOf(uri); + if(o2.getPath().equals(uri)){ + return o2.getPath().indexOf(uri); } return -1; } @@ -120,19 +123,19 @@ public void clearRoutes() { * @param url 路由url * @param method 路由http方法 */ - public void addRoute(Class target, Method execMethod, String url, HttpMethod method) { - RouteMatcher entry = new RouteMatcher(); - entry.target = target; - entry.execMethod = execMethod; - entry.httpMethod = method; - entry.path = url; + public void addRoute(Class target, Method execMethod, String url, HttpMethod httpMethod) { + RouteMatcher routeMatcher = new RouteMatcher(); + routeMatcher.setTarget(target); + routeMatcher.setExecMethod(execMethod); + routeMatcher.setHttpMethod(httpMethod); + routeMatcher.setPath(url); if(Blade.debug()){ - LOGGER.debug("Add Route:" + entry); + LOGGER.debug("Add Route:" + routeMatcher); } // 添加到路由集合 - routes.add(entry); + routes.add(routeMatcher); } /** @@ -143,19 +146,19 @@ public void addRoute(Class target, Method execMethod, String url, HttpMethod * @param url 路由url * @param method 路由http方法 */ - public void addInterceptor(Class target, Method execMethod, String url, HttpMethod method) { - RouteMatcher entry = new RouteMatcher(); - entry.target = target; - entry.execMethod = execMethod; - entry.httpMethod = method; - entry.path = url; + public void addInterceptor(Class target, Method execMethod, String url, HttpMethod httpMethod) { + RouteMatcher routeMatcher = new RouteMatcher(); + routeMatcher.setTarget(target); + routeMatcher.setExecMethod(execMethod); + routeMatcher.setHttpMethod(httpMethod); + routeMatcher.setPath(url); if(Blade.debug()){ - LOGGER.debug("Add Interceptor:" + entry); + LOGGER.debug("Add Interceptor:" + routeMatcher); } // 添加到路由集合 - interceptors.add(entry); + interceptors.add(routeMatcher); } /** @@ -165,18 +168,19 @@ public void addInterceptor(Class target, Method execMethod, String url, HttpM * @param url 路由url * @param method 路由http方法 */ - public void addRoute(Router router, String url, HttpMethod method) { - RouteMatcher entry = new RouteMatcher(); - entry.router = router; - entry.httpMethod = method; - entry.path = url; + public void addRoute(RouteHandler routerHandler, String url, HttpMethod httpMethod) { + + RouteMatcher routeMatcher = new RouteMatcher(); + routeMatcher.setRouterHandler(routerHandler); + routeMatcher.setHttpMethod(httpMethod); + routeMatcher.setPath(url); if(Blade.debug()){ - LOGGER.debug("Add Route:" + entry); + LOGGER.debug("Add Route:" + routeMatcher); } // 添加到路由集合 - routes.add(entry); + routes.add(routeMatcher); } /** @@ -186,18 +190,19 @@ public void addRoute(Router router, String url, HttpMethod method) { * @param url 路由url * @param method 路由http方法 */ - public void addInterceptor(Router router, String url, HttpMethod method) { - RouteMatcher entry = new RouteMatcher(); - entry.router = router; - entry.httpMethod = method; - entry.path = url; + public void addInterceptor(RouteHandler routerHandler, String url, HttpMethod httpMethod) { + + RouteMatcher routeMatcher = new RouteMatcher(); + routeMatcher.setRouterHandler(routerHandler); + routeMatcher.setHttpMethod(httpMethod); + routeMatcher.setPath(url); if(Blade.debug()){ - LOGGER.debug("Add Interceptor:" + entry); + LOGGER.debug("Add Interceptor:" + routeMatcher); } // 添加到路由集合 - interceptors.add(entry); + interceptors.add(routeMatcher); } /** From fc2faf13293e3a2ed5a700a7dcfefd5608515d63 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 10:28:09 +0800 Subject: [PATCH 152/545] modify the package name --- .../blade/exception/ExceptionHandler.java | 10 -- .../src/main/java/blade/package-info.java | 4 - .../main/java/blade/route/RouteHandler.java | 10 -- .../src/main/java/blade/servlet/FileItem.java | 120 ------------------ .../src/main/java/{ => com}/blade/Blade.java | 23 ++-- .../java/{ => com}/blade/BladeWebContext.java | 12 +- .../main/java/{ => com}/blade/Bootstrap.java | 2 +- .../src/main/java/{ => com}/blade/Config.java | 2 +- .../java/{ => com}/blade/Configurator.java | 2 +- .../main/java/{ => com}/blade/CoreFilter.java | 5 +- .../java/{ => com}/blade/IocApplication.java | 13 +- .../java/{ => com}/blade/RequestHandler.java | 29 +++-- .../{ => com}/blade/annotation/After.java | 2 +- .../{ => com}/blade/annotation/Before.java | 2 +- .../{ => com}/blade/annotation/Component.java | 2 +- .../{ => com}/blade/annotation/Inject.java | 2 +- .../blade/annotation/Interceptor.java | 2 +- .../java/{ => com}/blade/annotation/Path.java | 2 +- .../{ => com}/blade/annotation/Route.java | 4 +- .../blade/annotation/package-info.java | 2 +- .../com/blade/exception/ExceptionHandler.java | 10 ++ .../exception/WebApplicationException.java | 2 +- .../blade/ioc/AbstractBeanFactory.java | 2 +- .../java/{ => com}/blade/ioc/Container.java | 2 +- .../{ => com}/blade/ioc/DefaultContainer.java | 12 +- .../{ => com}/blade/ioc/PrototypeBean.java | 2 +- .../main/java/{ => com}/blade/ioc/Scope.java | 2 +- .../java/{ => com}/blade/ioc/SingleBean.java | 2 +- .../{ => com}/blade/ioc/package-info.java | 2 +- .../src/main/java/com/blade/package-info.java | 4 + .../java/{ => com}/blade/plugin/Plugin.java | 2 +- .../{ => com}/blade/plugin/package-info.java | 2 +- .../{ => com}/blade/render/JspRender.java | 7 +- .../{ => com}/blade/render/ModelAndView.java | 2 +- .../java/{ => com}/blade/render/Render.java | 9 +- .../{ => com}/blade/render/RenderFactory.java | 2 +- .../{ => com}/blade/render/package-info.java | 2 +- .../{ => com}/blade/route/HttpMethod.java | 2 +- .../java/{ => com}/blade/route/RouteBase.java | 2 +- .../java/com/blade/route/RouteHandler.java | 10 ++ .../{ => com}/blade/route/RouteMatcher.java | 2 +- .../blade/route/RouteMatcherBuilder.java | 21 +-- .../{ => com}/blade/route/RouterChain.java | 2 +- .../{ => com}/blade/route/RouterExecutor.java | 2 +- .../blade/route/impl/DefaultRouteMatcher.java | 11 +- .../{ => com}/blade/route/package-info.java | 2 +- .../blade/servlet/QueryParamsMap.java | 2 +- .../java/{ => com}/blade/servlet/Request.java | 5 +- .../{ => com}/blade/servlet/Response.java | 13 +- .../java/{ => com}/blade/servlet/Session.java | 2 +- .../servlet/multipart}/ServletFileUpload.java | 5 +- .../{ => com}/blade/servlet/package-info.java | 2 +- .../blade/wrapper/RequestResponseBuilder.java | 8 +- .../blade/wrapper/RequestWrapper.java | 10 +- .../blade/wrapper/ResponseWrapper.java | 6 +- .../{ => com}/blade/wrapper/package-info.java | 2 +- 56 files changed, 159 insertions(+), 266 deletions(-) delete mode 100644 blade-core/src/main/java/blade/exception/ExceptionHandler.java delete mode 100644 blade-core/src/main/java/blade/package-info.java delete mode 100644 blade-core/src/main/java/blade/route/RouteHandler.java delete mode 100644 blade-core/src/main/java/blade/servlet/FileItem.java rename blade-core/src/main/java/{ => com}/blade/Blade.java (97%) rename blade-core/src/main/java/{ => com}/blade/BladeWebContext.java (90%) rename blade-core/src/main/java/{ => com}/blade/Bootstrap.java (98%) rename blade-core/src/main/java/{ => com}/blade/Config.java (99%) rename blade-core/src/main/java/{ => com}/blade/Configurator.java (96%) rename blade-core/src/main/java/{ => com}/blade/CoreFilter.java (95%) rename blade-core/src/main/java/{ => com}/blade/IocApplication.java (91%) rename blade-core/src/main/java/{ => com}/blade/RequestHandler.java (91%) rename blade-core/src/main/java/{ => com}/blade/annotation/After.java (94%) rename blade-core/src/main/java/{ => com}/blade/annotation/Before.java (94%) rename blade-core/src/main/java/{ => com}/blade/annotation/Component.java (94%) rename blade-core/src/main/java/{ => com}/blade/annotation/Inject.java (97%) rename blade-core/src/main/java/{ => com}/blade/annotation/Interceptor.java (94%) rename blade-core/src/main/java/{ => com}/blade/annotation/Path.java (94%) rename blade-core/src/main/java/{ => com}/blade/annotation/Route.java (94%) rename blade-core/src/main/java/{ => com}/blade/annotation/package-info.java (52%) create mode 100644 blade-core/src/main/java/com/blade/exception/ExceptionHandler.java rename blade-core/src/main/java/{ => com}/blade/exception/WebApplicationException.java (92%) rename blade-core/src/main/java/{ => com}/blade/ioc/AbstractBeanFactory.java (95%) rename blade-core/src/main/java/{ => com}/blade/ioc/Container.java (99%) rename blade-core/src/main/java/{ => com}/blade/ioc/DefaultContainer.java (98%) rename blade-core/src/main/java/{ => com}/blade/ioc/PrototypeBean.java (94%) rename blade-core/src/main/java/{ => com}/blade/ioc/Scope.java (97%) rename blade-core/src/main/java/{ => com}/blade/ioc/SingleBean.java (94%) rename blade-core/src/main/java/{ => com}/blade/ioc/package-info.java (59%) create mode 100644 blade-core/src/main/java/com/blade/package-info.java rename blade-core/src/main/java/{ => com}/blade/plugin/Plugin.java (93%) rename blade-core/src/main/java/{ => com}/blade/plugin/package-info.java (50%) rename blade-core/src/main/java/{ => com}/blade/render/JspRender.java (97%) rename blade-core/src/main/java/{ => com}/blade/render/ModelAndView.java (98%) rename blade-core/src/main/java/{ => com}/blade/render/Render.java (98%) rename blade-core/src/main/java/{ => com}/blade/render/RenderFactory.java (97%) rename blade-core/src/main/java/{ => com}/blade/render/package-info.java (53%) rename blade-core/src/main/java/{ => com}/blade/route/HttpMethod.java (97%) rename blade-core/src/main/java/{ => com}/blade/route/RouteBase.java (63%) create mode 100644 blade-core/src/main/java/com/blade/route/RouteHandler.java rename blade-core/src/main/java/{ => com}/blade/route/RouteMatcher.java (99%) rename blade-core/src/main/java/{ => com}/blade/route/RouteMatcherBuilder.java (96%) rename blade-core/src/main/java/{ => com}/blade/route/RouterChain.java (68%) rename blade-core/src/main/java/{ => com}/blade/route/RouterExecutor.java (94%) rename blade-core/src/main/java/{ => com}/blade/route/impl/DefaultRouteMatcher.java (97%) rename blade-core/src/main/java/{ => com}/blade/route/package-info.java (54%) rename blade-core/src/main/java/{ => com}/blade/servlet/QueryParamsMap.java (99%) rename blade-core/src/main/java/{ => com}/blade/servlet/Request.java (99%) rename blade-core/src/main/java/{ => com}/blade/servlet/Response.java (97%) rename blade-core/src/main/java/{ => com}/blade/servlet/Session.java (98%) rename blade-core/src/main/java/{blade/servlet => com/blade/servlet/multipart}/ServletFileUpload.java (94%) rename blade-core/src/main/java/{ => com}/blade/servlet/package-info.java (59%) rename blade-core/src/main/java/{ => com}/blade/wrapper/RequestResponseBuilder.java (92%) rename blade-core/src/main/java/{ => com}/blade/wrapper/RequestWrapper.java (96%) rename blade-core/src/main/java/{ => com}/blade/wrapper/ResponseWrapper.java (97%) rename blade-core/src/main/java/{ => com}/blade/wrapper/package-info.java (71%) diff --git a/blade-core/src/main/java/blade/exception/ExceptionHandler.java b/blade-core/src/main/java/blade/exception/ExceptionHandler.java deleted file mode 100644 index a8728db61..000000000 --- a/blade-core/src/main/java/blade/exception/ExceptionHandler.java +++ /dev/null @@ -1,10 +0,0 @@ -package blade.exception; - -import blade.servlet.Request; -import blade.servlet.Response; - -public interface ExceptionHandler { - - void handle(Exception e, Request request, Response response); - -} diff --git a/blade-core/src/main/java/blade/package-info.java b/blade-core/src/main/java/blade/package-info.java deleted file mode 100644 index bd5612aa1..000000000 --- a/blade-core/src/main/java/blade/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * blade - */ -package blade; \ No newline at end of file diff --git a/blade-core/src/main/java/blade/route/RouteHandler.java b/blade-core/src/main/java/blade/route/RouteHandler.java deleted file mode 100644 index bf75fb66a..000000000 --- a/blade-core/src/main/java/blade/route/RouteHandler.java +++ /dev/null @@ -1,10 +0,0 @@ -package blade.route; - -import blade.servlet.Request; -import blade.servlet.Response; - -public interface RouteHandler { - - public Object handler(Request request, Response response); - -} diff --git a/blade-core/src/main/java/blade/servlet/FileItem.java b/blade-core/src/main/java/blade/servlet/FileItem.java deleted file mode 100644 index 009cacd14..000000000 --- a/blade-core/src/main/java/blade/servlet/FileItem.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.servlet; - -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.util.Arrays; - -import blade.kit.io.FastByteArrayOutputStream; - -/** - * 文件上传Item - * - * @author biezhi - * @since 1.0 - */ -public class FileItem { - - private String name; - - private boolean isFile; - private String fileName; - private String contentType; - private InputStream inputStream; - - public static final String FORM_DATA = "form-data"; - - public static final String MULTIPART_FORM_DATA = "multipart/form-data"; - - // 数据体缓存 - private FastByteArrayOutputStream outputStream; - - public void write(byte[] buf, int off, int len) { - if (outputStream == null) { - outputStream = new FastByteArrayOutputStream(); - } - outputStream.write(buf, off, len); - } - - // ----------------------------------------------------------------- - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getFileName() { - return fileName; - } - - public void setFileName(String fileName) { - this.fileName = fileName; - } - - public String getContentType() { - return contentType; - } - - public void setContentType(String contentType) { - this.contentType = contentType; - } - - public boolean isFile() { - return isFile; - } - - public void setFile(boolean isFile) { - this.isFile = isFile; - } - - public byte[] getFileContent() { - byte[] buf = outputStream.toByteArray(); - int dirtyCount = 2; - - // 最后会多出一个\r\n, - // 根据ServletInputStream, \n 就算一行结束, 因此对于\r需要特殊判断 - if ('\r' != buf[buf.length - 2]) - dirtyCount = 1; - - return Arrays.copyOfRange(buf, 0, buf.length - dirtyCount); - } - - public String getString(String encoding){ - try { - return outputStream == null ? null : new String(getFileContent(), encoding); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return null; - } - - public String getString() { - return outputStream == null ? null : new String(getFileContent()); - } - - public InputStream getInputStream() { - return inputStream; - } - - public void setInputStream(InputStream inputStream) { - this.inputStream = inputStream; - } - -} - diff --git a/blade-core/src/main/java/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java similarity index 97% rename from blade-core/src/main/java/blade/Blade.java rename to blade-core/src/main/java/com/blade/Blade.java index 436dd7d2d..5d9721113 100644 --- a/blade-core/src/main/java/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -13,25 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade; +package com.blade; import java.io.IOException; import java.io.InputStream; import java.util.Map; -import blade.ioc.Container; -import blade.ioc.DefaultContainer; +import com.blade.ioc.Container; +import com.blade.ioc.DefaultContainer; +import com.blade.plugin.Plugin; +import com.blade.render.Render; +import com.blade.render.RenderFactory; +import com.blade.route.HttpMethod; +import com.blade.route.RouteBase; +import com.blade.route.RouteHandler; +import com.blade.route.RouteMatcherBuilder; +import com.blade.route.RouterExecutor; + import blade.kit.IOKit; import blade.kit.PropertyKit; import blade.kit.json.JSONKit; -import blade.plugin.Plugin; -import blade.render.Render; -import blade.render.RenderFactory; -import blade.route.HttpMethod; -import blade.route.RouteBase; -import blade.route.RouteMatcherBuilder; -import blade.route.RouteHandler; -import blade.route.RouterExecutor; /** * Blade Core Class diff --git a/blade-core/src/main/java/blade/BladeWebContext.java b/blade-core/src/main/java/com/blade/BladeWebContext.java similarity index 90% rename from blade-core/src/main/java/blade/BladeWebContext.java rename to blade-core/src/main/java/com/blade/BladeWebContext.java index f26f8b356..2f8246480 100644 --- a/blade-core/src/main/java/blade/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/BladeWebContext.java @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade; +package com.blade; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import blade.servlet.Request; -import blade.servlet.Response; -import blade.servlet.Session; -import blade.wrapper.RequestWrapper; -import blade.wrapper.ResponseWrapper; +import com.blade.servlet.Request; +import com.blade.servlet.Response; +import com.blade.servlet.Session; +import com.blade.wrapper.RequestWrapper; +import com.blade.wrapper.ResponseWrapper; /** * 全局的WeContext diff --git a/blade-core/src/main/java/blade/Bootstrap.java b/blade-core/src/main/java/com/blade/Bootstrap.java similarity index 98% rename from blade-core/src/main/java/blade/Bootstrap.java rename to blade-core/src/main/java/com/blade/Bootstrap.java index 3c9c15209..a23dd96d9 100644 --- a/blade-core/src/main/java/blade/Bootstrap.java +++ b/blade-core/src/main/java/com/blade/Bootstrap.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade; +package com.blade; /** * Blade全局初始化类,可以在应用启动的时候做一些操作 diff --git a/blade-core/src/main/java/blade/Config.java b/blade-core/src/main/java/com/blade/Config.java similarity index 99% rename from blade-core/src/main/java/blade/Config.java rename to blade-core/src/main/java/com/blade/Config.java index 35edef740..0c25e38af 100644 --- a/blade-core/src/main/java/blade/Config.java +++ b/blade-core/src/main/java/com/blade/Config.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade; +package com.blade; import java.util.Arrays; import java.util.List; diff --git a/blade-core/src/main/java/blade/Configurator.java b/blade-core/src/main/java/com/blade/Configurator.java similarity index 96% rename from blade-core/src/main/java/blade/Configurator.java rename to blade-core/src/main/java/com/blade/Configurator.java index 678e9e3db..2f5c42ec8 100644 --- a/blade-core/src/main/java/blade/Configurator.java +++ b/blade-core/src/main/java/com/blade/Configurator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade; +package com.blade; import java.util.Map; diff --git a/blade-core/src/main/java/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java similarity index 95% rename from blade-core/src/main/java/blade/CoreFilter.java rename to blade-core/src/main/java/com/blade/CoreFilter.java index 4e37ab6be..0ae08879e 100644 --- a/blade-core/src/main/java/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade; +package com.blade; import java.io.IOException; @@ -27,9 +27,10 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import com.blade.route.RouteMatcherBuilder; + import blade.kit.TaskKit; import blade.kit.log.Logger; -import blade.route.RouteMatcherBuilder; /** * blade核心过滤器,mvc总线 diff --git a/blade-core/src/main/java/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java similarity index 91% rename from blade-core/src/main/java/blade/IocApplication.java rename to blade-core/src/main/java/com/blade/IocApplication.java index 455984c72..6f4c281f2 100644 --- a/blade-core/src/main/java/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -13,21 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade; +package com.blade; import java.util.List; import java.util.Set; -import blade.ioc.Container; -import blade.ioc.DefaultContainer; -import blade.ioc.Scope; +import com.blade.ioc.Container; +import com.blade.ioc.DefaultContainer; +import com.blade.ioc.Scope; +import com.blade.plugin.Plugin; +import com.blade.route.RouteBase; + import blade.kit.CollectionKit; import blade.kit.ReflectKit; import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; -import blade.plugin.Plugin; -import blade.route.RouteBase; /** * IOC容器初始化类 diff --git a/blade-core/src/main/java/blade/RequestHandler.java b/blade-core/src/main/java/com/blade/RequestHandler.java similarity index 91% rename from blade-core/src/main/java/blade/RequestHandler.java rename to blade-core/src/main/java/com/blade/RequestHandler.java index d18acbf65..463c7e5f8 100644 --- a/blade-core/src/main/java/blade/RequestHandler.java +++ b/blade-core/src/main/java/com/blade/RequestHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade; +package com.blade; import java.lang.reflect.Method; import java.util.List; @@ -21,23 +21,24 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import com.blade.ioc.Container; +import com.blade.ioc.DefaultContainer; +import com.blade.ioc.Scope; +import com.blade.render.ModelAndView; +import com.blade.route.HttpMethod; +import com.blade.route.RouteHandler; +import com.blade.route.RouteMatcher; +import com.blade.route.impl.DefaultRouteMatcher; +import com.blade.servlet.Request; +import com.blade.servlet.Response; +import com.blade.wrapper.RequestResponseBuilder; +import com.blade.wrapper.RequestWrapper; +import com.blade.wrapper.ResponseWrapper; + import blade.exception.BladeException; -import blade.ioc.Container; -import blade.ioc.DefaultContainer; -import blade.ioc.Scope; import blade.kit.PathKit; import blade.kit.ReflectKit; import blade.kit.log.Logger; -import blade.render.ModelAndView; -import blade.route.HttpMethod; -import blade.route.RouteMatcher; -import blade.route.impl.DefaultRouteMatcher; -import blade.route.RouteHandler; -import blade.servlet.Request; -import blade.servlet.Response; -import blade.wrapper.RequestResponseBuilder; -import blade.wrapper.RequestWrapper; -import blade.wrapper.ResponseWrapper; /** * 请求执行的Handler diff --git a/blade-core/src/main/java/blade/annotation/After.java b/blade-core/src/main/java/com/blade/annotation/After.java similarity index 94% rename from blade-core/src/main/java/blade/annotation/After.java rename to blade-core/src/main/java/com/blade/annotation/After.java index 249386c16..5da81bbd0 100644 --- a/blade-core/src/main/java/blade/annotation/After.java +++ b/blade-core/src/main/java/com/blade/annotation/After.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.annotation; +package com.blade.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/blade/annotation/Before.java b/blade-core/src/main/java/com/blade/annotation/Before.java similarity index 94% rename from blade-core/src/main/java/blade/annotation/Before.java rename to blade-core/src/main/java/com/blade/annotation/Before.java index b699c0363..e74f64f57 100644 --- a/blade-core/src/main/java/blade/annotation/Before.java +++ b/blade-core/src/main/java/com/blade/annotation/Before.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.annotation; +package com.blade.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/blade/annotation/Component.java b/blade-core/src/main/java/com/blade/annotation/Component.java similarity index 94% rename from blade-core/src/main/java/blade/annotation/Component.java rename to blade-core/src/main/java/com/blade/annotation/Component.java index bbe9a0cde..c2bdffdea 100644 --- a/blade-core/src/main/java/blade/annotation/Component.java +++ b/blade-core/src/main/java/com/blade/annotation/Component.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.annotation; +package com.blade.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/blade/annotation/Inject.java b/blade-core/src/main/java/com/blade/annotation/Inject.java similarity index 97% rename from blade-core/src/main/java/blade/annotation/Inject.java rename to blade-core/src/main/java/com/blade/annotation/Inject.java index 2edec1f74..48805477b 100644 --- a/blade-core/src/main/java/blade/annotation/Inject.java +++ b/blade-core/src/main/java/com/blade/annotation/Inject.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.annotation; +package com.blade.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/blade/annotation/Interceptor.java b/blade-core/src/main/java/com/blade/annotation/Interceptor.java similarity index 94% rename from blade-core/src/main/java/blade/annotation/Interceptor.java rename to blade-core/src/main/java/com/blade/annotation/Interceptor.java index a3c0a5cb4..f54fa1929 100644 --- a/blade-core/src/main/java/blade/annotation/Interceptor.java +++ b/blade-core/src/main/java/com/blade/annotation/Interceptor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.annotation; +package com.blade.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/blade/annotation/Path.java b/blade-core/src/main/java/com/blade/annotation/Path.java similarity index 94% rename from blade-core/src/main/java/blade/annotation/Path.java rename to blade-core/src/main/java/com/blade/annotation/Path.java index 47623643d..6ffa13dbe 100644 --- a/blade-core/src/main/java/blade/annotation/Path.java +++ b/blade-core/src/main/java/com/blade/annotation/Path.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.annotation; +package com.blade.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/blade/annotation/Route.java b/blade-core/src/main/java/com/blade/annotation/Route.java similarity index 94% rename from blade-core/src/main/java/blade/annotation/Route.java rename to blade-core/src/main/java/com/blade/annotation/Route.java index dce2c2096..430a9690e 100644 --- a/blade-core/src/main/java/blade/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/annotation/Route.java @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.annotation; +package com.blade.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import blade.route.HttpMethod; +import com.blade.route.HttpMethod; /** * 方法上定义的路由注解 diff --git a/blade-core/src/main/java/blade/annotation/package-info.java b/blade-core/src/main/java/com/blade/annotation/package-info.java similarity index 52% rename from blade-core/src/main/java/blade/annotation/package-info.java rename to blade-core/src/main/java/com/blade/annotation/package-info.java index dcbe40f5e..2c47704f1 100644 --- a/blade-core/src/main/java/blade/annotation/package-info.java +++ b/blade-core/src/main/java/com/blade/annotation/package-info.java @@ -1,4 +1,4 @@ /** * blade注解所在包 */ -package blade.annotation; \ No newline at end of file +package com.blade.annotation; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/exception/ExceptionHandler.java b/blade-core/src/main/java/com/blade/exception/ExceptionHandler.java new file mode 100644 index 000000000..26f461e77 --- /dev/null +++ b/blade-core/src/main/java/com/blade/exception/ExceptionHandler.java @@ -0,0 +1,10 @@ +package com.blade.exception; + +import com.blade.servlet.Request; +import com.blade.servlet.Response; + +public interface ExceptionHandler { + + void handle(Exception e, Request request, Response response); + +} diff --git a/blade-core/src/main/java/blade/exception/WebApplicationException.java b/blade-core/src/main/java/com/blade/exception/WebApplicationException.java similarity index 92% rename from blade-core/src/main/java/blade/exception/WebApplicationException.java rename to blade-core/src/main/java/com/blade/exception/WebApplicationException.java index bb8300b9a..3e398a422 100644 --- a/blade-core/src/main/java/blade/exception/WebApplicationException.java +++ b/blade-core/src/main/java/com/blade/exception/WebApplicationException.java @@ -1,4 +1,4 @@ -package blade.exception; +package com.blade.exception; public class WebApplicationException extends RuntimeException { diff --git a/blade-core/src/main/java/blade/ioc/AbstractBeanFactory.java b/blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java similarity index 95% rename from blade-core/src/main/java/blade/ioc/AbstractBeanFactory.java rename to blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java index cb80bb1e9..27e5ea2cf 100644 --- a/blade-core/src/main/java/blade/ioc/AbstractBeanFactory.java +++ b/blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.ioc; +package com.blade.ioc; import java.lang.annotation.Annotation; import java.util.Collection; diff --git a/blade-core/src/main/java/blade/ioc/Container.java b/blade-core/src/main/java/com/blade/ioc/Container.java similarity index 99% rename from blade-core/src/main/java/blade/ioc/Container.java rename to blade-core/src/main/java/com/blade/ioc/Container.java index 64cacc7c3..61f85176e 100644 --- a/blade-core/src/main/java/blade/ioc/Container.java +++ b/blade-core/src/main/java/com/blade/ioc/Container.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.ioc; +package com.blade.ioc; import java.lang.annotation.Annotation; import java.util.Collection; diff --git a/blade-core/src/main/java/blade/ioc/DefaultContainer.java b/blade-core/src/main/java/com/blade/ioc/DefaultContainer.java similarity index 98% rename from blade-core/src/main/java/blade/ioc/DefaultContainer.java rename to blade-core/src/main/java/com/blade/ioc/DefaultContainer.java index efbe4c13f..337ce80c0 100644 --- a/blade-core/src/main/java/blade/ioc/DefaultContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/DefaultContainer.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.ioc; +package com.blade.ioc; import java.lang.annotation.Annotation; import java.lang.reflect.Field; @@ -23,12 +23,14 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; + +import com.blade.Blade; +import com.blade.annotation.Component; +import com.blade.annotation.Inject; +import com.blade.annotation.Path; + import java.util.Set; -import blade.Blade; -import blade.annotation.Component; -import blade.annotation.Inject; -import blade.annotation.Path; import blade.exception.BladeException; import blade.kit.CloneKit; import blade.kit.CollectionKit; diff --git a/blade-core/src/main/java/blade/ioc/PrototypeBean.java b/blade-core/src/main/java/com/blade/ioc/PrototypeBean.java similarity index 94% rename from blade-core/src/main/java/blade/ioc/PrototypeBean.java rename to blade-core/src/main/java/com/blade/ioc/PrototypeBean.java index b0de1fa01..9821e4ee5 100644 --- a/blade-core/src/main/java/blade/ioc/PrototypeBean.java +++ b/blade-core/src/main/java/com/blade/ioc/PrototypeBean.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.ioc; +package com.blade.ioc; /** * 原生bean对象 diff --git a/blade-core/src/main/java/blade/ioc/Scope.java b/blade-core/src/main/java/com/blade/ioc/Scope.java similarity index 97% rename from blade-core/src/main/java/blade/ioc/Scope.java rename to blade-core/src/main/java/com/blade/ioc/Scope.java index 46f853a0a..dae4b4147 100644 --- a/blade-core/src/main/java/blade/ioc/Scope.java +++ b/blade-core/src/main/java/com/blade/ioc/Scope.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.ioc; +package com.blade.ioc; /** * Bean创建类型 diff --git a/blade-core/src/main/java/blade/ioc/SingleBean.java b/blade-core/src/main/java/com/blade/ioc/SingleBean.java similarity index 94% rename from blade-core/src/main/java/blade/ioc/SingleBean.java rename to blade-core/src/main/java/com/blade/ioc/SingleBean.java index 5e0695d7a..be60db8b1 100644 --- a/blade-core/src/main/java/blade/ioc/SingleBean.java +++ b/blade-core/src/main/java/com/blade/ioc/SingleBean.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.ioc; +package com.blade.ioc; /** * 单例bean对象,容器中只存在一个bean实例 diff --git a/blade-core/src/main/java/blade/ioc/package-info.java b/blade-core/src/main/java/com/blade/ioc/package-info.java similarity index 59% rename from blade-core/src/main/java/blade/ioc/package-info.java rename to blade-core/src/main/java/com/blade/ioc/package-info.java index 3b4f02639..7e196796a 100644 --- a/blade-core/src/main/java/blade/ioc/package-info.java +++ b/blade-core/src/main/java/com/blade/ioc/package-info.java @@ -1,4 +1,4 @@ /** * blade依赖注入包 */ -package blade.ioc; \ No newline at end of file +package com.blade.ioc; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/package-info.java b/blade-core/src/main/java/com/blade/package-info.java new file mode 100644 index 000000000..262b7b19a --- /dev/null +++ b/blade-core/src/main/java/com/blade/package-info.java @@ -0,0 +1,4 @@ +/** + * blade + */ +package com.blade; \ No newline at end of file diff --git a/blade-core/src/main/java/blade/plugin/Plugin.java b/blade-core/src/main/java/com/blade/plugin/Plugin.java similarity index 93% rename from blade-core/src/main/java/blade/plugin/Plugin.java rename to blade-core/src/main/java/com/blade/plugin/Plugin.java index c5bdf05d7..9785f5477 100644 --- a/blade-core/src/main/java/blade/plugin/Plugin.java +++ b/blade-core/src/main/java/com/blade/plugin/Plugin.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.plugin; +package com.blade.plugin; /** * 插件顶层接口 diff --git a/blade-core/src/main/java/blade/plugin/package-info.java b/blade-core/src/main/java/com/blade/plugin/package-info.java similarity index 50% rename from blade-core/src/main/java/blade/plugin/package-info.java rename to blade-core/src/main/java/com/blade/plugin/package-info.java index 60d209844..974e945e6 100644 --- a/blade-core/src/main/java/blade/plugin/package-info.java +++ b/blade-core/src/main/java/com/blade/plugin/package-info.java @@ -1,4 +1,4 @@ /** * blade插件包 */ -package blade.plugin; \ No newline at end of file +package com.blade.plugin; \ No newline at end of file diff --git a/blade-core/src/main/java/blade/render/JspRender.java b/blade-core/src/main/java/com/blade/render/JspRender.java similarity index 97% rename from blade-core/src/main/java/blade/render/JspRender.java rename to blade-core/src/main/java/com/blade/render/JspRender.java index 54beb6c83..1f2f128bb 100644 --- a/blade-core/src/main/java/blade/render/JspRender.java +++ b/blade-core/src/main/java/com/blade/render/JspRender.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.render; +package com.blade.render; import java.io.IOException; import java.util.Map; @@ -23,8 +23,9 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import blade.Blade; -import blade.BladeWebContext; +import com.blade.Blade; +import com.blade.BladeWebContext; + import blade.kit.log.Logger; /** diff --git a/blade-core/src/main/java/blade/render/ModelAndView.java b/blade-core/src/main/java/com/blade/render/ModelAndView.java similarity index 98% rename from blade-core/src/main/java/blade/render/ModelAndView.java rename to blade-core/src/main/java/com/blade/render/ModelAndView.java index 5aa25ab58..fed21bac8 100644 --- a/blade-core/src/main/java/blade/render/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/render/ModelAndView.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.render; +package com.blade.render; import java.util.Map; diff --git a/blade-core/src/main/java/blade/render/Render.java b/blade-core/src/main/java/com/blade/render/Render.java similarity index 98% rename from blade-core/src/main/java/blade/render/Render.java rename to blade-core/src/main/java/com/blade/render/Render.java index b5ecad3e0..88be2417d 100644 --- a/blade-core/src/main/java/blade/render/Render.java +++ b/blade-core/src/main/java/com/blade/render/Render.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.render; +package com.blade.render; import java.io.IOException; import java.io.PrintWriter; @@ -23,10 +23,11 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import blade.Blade; -import blade.BladeWebContext; +import com.blade.Blade; +import com.blade.BladeWebContext; +import com.blade.servlet.Response; + import blade.kit.log.Logger; -import blade.servlet.Response; /** * 渲染器抽象类 * diff --git a/blade-core/src/main/java/blade/render/RenderFactory.java b/blade-core/src/main/java/com/blade/render/RenderFactory.java similarity index 97% rename from blade-core/src/main/java/blade/render/RenderFactory.java rename to blade-core/src/main/java/com/blade/render/RenderFactory.java index ab7748b72..3a22a95d5 100644 --- a/blade-core/src/main/java/blade/render/RenderFactory.java +++ b/blade-core/src/main/java/com/blade/render/RenderFactory.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.render; +package com.blade.render; /** * 渲染引擎工厂 diff --git a/blade-core/src/main/java/blade/render/package-info.java b/blade-core/src/main/java/com/blade/render/package-info.java similarity index 53% rename from blade-core/src/main/java/blade/render/package-info.java rename to blade-core/src/main/java/com/blade/render/package-info.java index a8e93cae8..82911835d 100644 --- a/blade-core/src/main/java/blade/render/package-info.java +++ b/blade-core/src/main/java/com/blade/render/package-info.java @@ -1,4 +1,4 @@ /** * blade视图渲染 */ -package blade.render; \ No newline at end of file +package com.blade.render; \ No newline at end of file diff --git a/blade-core/src/main/java/blade/route/HttpMethod.java b/blade-core/src/main/java/com/blade/route/HttpMethod.java similarity index 97% rename from blade-core/src/main/java/blade/route/HttpMethod.java rename to blade-core/src/main/java/com/blade/route/HttpMethod.java index 3d3a5d430..351e648c4 100644 --- a/blade-core/src/main/java/blade/route/HttpMethod.java +++ b/blade-core/src/main/java/com/blade/route/HttpMethod.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.route; +package com.blade.route; /** * HTTP请求方法 diff --git a/blade-core/src/main/java/blade/route/RouteBase.java b/blade-core/src/main/java/com/blade/route/RouteBase.java similarity index 63% rename from blade-core/src/main/java/blade/route/RouteBase.java rename to blade-core/src/main/java/com/blade/route/RouteBase.java index c8eb5801c..107b8f521 100644 --- a/blade-core/src/main/java/blade/route/RouteBase.java +++ b/blade-core/src/main/java/com/blade/route/RouteBase.java @@ -1,4 +1,4 @@ -package blade.route; +package com.blade.route; public interface RouteBase { diff --git a/blade-core/src/main/java/com/blade/route/RouteHandler.java b/blade-core/src/main/java/com/blade/route/RouteHandler.java new file mode 100644 index 000000000..16e821f81 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/RouteHandler.java @@ -0,0 +1,10 @@ +package com.blade.route; + +import com.blade.servlet.Request; +import com.blade.servlet.Response; + +public interface RouteHandler { + + public Object handler(Request request, Response response); + +} diff --git a/blade-core/src/main/java/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java similarity index 99% rename from blade-core/src/main/java/blade/route/RouteMatcher.java rename to blade-core/src/main/java/com/blade/route/RouteMatcher.java index f8843dd7c..d562544ca 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcher.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.route; +package com.blade.route; import java.lang.reflect.Method; import java.util.List; diff --git a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java similarity index 96% rename from blade-core/src/main/java/blade/route/RouteMatcherBuilder.java rename to blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java index 78af675d3..87cae4b50 100644 --- a/blade-core/src/main/java/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java @@ -13,26 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.route; +package com.blade.route; import java.lang.reflect.Method; import java.util.Set; -import blade.Blade; -import blade.annotation.After; -import blade.annotation.Before; -import blade.annotation.Interceptor; -import blade.annotation.Path; -import blade.annotation.Route; +import com.blade.Blade; +import com.blade.annotation.After; +import com.blade.annotation.Before; +import com.blade.annotation.Interceptor; +import com.blade.annotation.Path; +import com.blade.annotation.Route; +import com.blade.ioc.Container; +import com.blade.ioc.DefaultContainer; +import com.blade.route.impl.DefaultRouteMatcher; + import blade.exception.BladeException; -import blade.ioc.Container; -import blade.ioc.DefaultContainer; import blade.kit.ReflectKit; import blade.kit.StringKit; import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; -import blade.route.impl.DefaultRouteMatcher; /** * 路由构造器 diff --git a/blade-core/src/main/java/blade/route/RouterChain.java b/blade-core/src/main/java/com/blade/route/RouterChain.java similarity index 68% rename from blade-core/src/main/java/blade/route/RouterChain.java rename to blade-core/src/main/java/com/blade/route/RouterChain.java index 9758664d1..ac22e4899 100644 --- a/blade-core/src/main/java/blade/route/RouterChain.java +++ b/blade-core/src/main/java/com/blade/route/RouterChain.java @@ -1,4 +1,4 @@ -package blade.route; +package com.blade.route; public interface RouterChain { diff --git a/blade-core/src/main/java/blade/route/RouterExecutor.java b/blade-core/src/main/java/com/blade/route/RouterExecutor.java similarity index 94% rename from blade-core/src/main/java/blade/route/RouterExecutor.java rename to blade-core/src/main/java/com/blade/route/RouterExecutor.java index ad97b618a..0769e1e15 100644 --- a/blade-core/src/main/java/blade/route/RouterExecutor.java +++ b/blade-core/src/main/java/com/blade/route/RouterExecutor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.route; +package com.blade.route; /** * 多个路由的执行器 diff --git a/blade-core/src/main/java/blade/route/impl/DefaultRouteMatcher.java b/blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java similarity index 97% rename from blade-core/src/main/java/blade/route/impl/DefaultRouteMatcher.java rename to blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java index 8b3d6da8b..434e95f66 100644 --- a/blade-core/src/main/java/blade/route/impl/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java @@ -13,19 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.route.impl; +package com.blade.route.impl; import java.lang.reflect.Method; import java.util.Collections; import java.util.Comparator; import java.util.List; -import blade.Blade; +import com.blade.Blade; +import com.blade.route.HttpMethod; +import com.blade.route.RouteHandler; +import com.blade.route.RouteMatcher; + import blade.kit.CollectionKit; import blade.kit.log.Logger; -import blade.route.HttpMethod; -import blade.route.RouteHandler; -import blade.route.RouteMatcher; /** * 默认的路由匹配器 diff --git a/blade-core/src/main/java/blade/route/package-info.java b/blade-core/src/main/java/com/blade/route/package-info.java similarity index 54% rename from blade-core/src/main/java/blade/route/package-info.java rename to blade-core/src/main/java/com/blade/route/package-info.java index d33ca2e58..8c19d51f1 100644 --- a/blade-core/src/main/java/blade/route/package-info.java +++ b/blade-core/src/main/java/com/blade/route/package-info.java @@ -1,4 +1,4 @@ /** * blade路由实现 */ -package blade.route; \ No newline at end of file +package com.blade.route; \ No newline at end of file diff --git a/blade-core/src/main/java/blade/servlet/QueryParamsMap.java b/blade-core/src/main/java/com/blade/servlet/QueryParamsMap.java similarity index 99% rename from blade-core/src/main/java/blade/servlet/QueryParamsMap.java rename to blade-core/src/main/java/com/blade/servlet/QueryParamsMap.java index ca8b1f561..8dd83693e 100644 --- a/blade-core/src/main/java/blade/servlet/QueryParamsMap.java +++ b/blade-core/src/main/java/com/blade/servlet/QueryParamsMap.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.servlet; +package com.blade.servlet; import java.util.Map; import java.util.Map.Entry; diff --git a/blade-core/src/main/java/blade/servlet/Request.java b/blade-core/src/main/java/com/blade/servlet/Request.java similarity index 99% rename from blade-core/src/main/java/blade/servlet/Request.java rename to blade-core/src/main/java/com/blade/servlet/Request.java index f25434cbe..4bb7e591e 100644 --- a/blade-core/src/main/java/blade/servlet/Request.java +++ b/blade-core/src/main/java/com/blade/servlet/Request.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.servlet; +package com.blade.servlet; import java.util.Collections; import java.util.Enumeration; @@ -27,12 +27,13 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import com.blade.route.RouteMatcher; + import blade.kit.CollectionKit; import blade.kit.IOKit; import blade.kit.PathKit; import blade.kit.StringKit; import blade.kit.log.Logger; -import blade.route.RouteMatcher; /** * HttpServletRequest请求包装类 diff --git a/blade-core/src/main/java/blade/servlet/Response.java b/blade-core/src/main/java/com/blade/servlet/Response.java similarity index 97% rename from blade-core/src/main/java/blade/servlet/Response.java rename to blade-core/src/main/java/com/blade/servlet/Response.java index 1df1078eb..b44289abd 100644 --- a/blade-core/src/main/java/blade/servlet/Response.java +++ b/blade-core/src/main/java/com/blade/servlet/Response.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.servlet; +package com.blade.servlet; import java.io.IOException; import java.io.PrintWriter; @@ -22,12 +22,13 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; -import blade.Blade; -import blade.BladeWebContext; +import com.blade.Blade; +import com.blade.BladeWebContext; +import com.blade.render.ModelAndView; +import com.blade.render.Render; +import com.blade.render.RenderFactory; + import blade.kit.log.Logger; -import blade.render.ModelAndView; -import blade.render.Render; -import blade.render.RenderFactory; /** * HttpServletResponse响应包装类 diff --git a/blade-core/src/main/java/blade/servlet/Session.java b/blade-core/src/main/java/com/blade/servlet/Session.java similarity index 98% rename from blade-core/src/main/java/blade/servlet/Session.java rename to blade-core/src/main/java/com/blade/servlet/Session.java index 1942acd2a..6b7985049 100644 --- a/blade-core/src/main/java/blade/servlet/Session.java +++ b/blade-core/src/main/java/com/blade/servlet/Session.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.servlet; +package com.blade.servlet; import java.util.Enumeration; import java.util.Set; diff --git a/blade-core/src/main/java/blade/servlet/ServletFileUpload.java b/blade-core/src/main/java/com/blade/servlet/multipart/ServletFileUpload.java similarity index 94% rename from blade-core/src/main/java/blade/servlet/ServletFileUpload.java rename to blade-core/src/main/java/com/blade/servlet/multipart/ServletFileUpload.java index fa34c3502..f6b63e4ed 100644 --- a/blade-core/src/main/java/blade/servlet/ServletFileUpload.java +++ b/blade-core/src/main/java/com/blade/servlet/multipart/ServletFileUpload.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.servlet; +package com.blade.servlet.multipart; import java.io.IOException; import java.util.List; @@ -25,8 +25,9 @@ import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; +import com.blade.route.HttpMethod; + import blade.kit.CollectionKit; -import blade.route.HttpMethod; /** * 文件上传对象 diff --git a/blade-core/src/main/java/blade/servlet/package-info.java b/blade-core/src/main/java/com/blade/servlet/package-info.java similarity index 59% rename from blade-core/src/main/java/blade/servlet/package-info.java rename to blade-core/src/main/java/com/blade/servlet/package-info.java index 8f93e0cfd..b92f99871 100644 --- a/blade-core/src/main/java/blade/servlet/package-info.java +++ b/blade-core/src/main/java/com/blade/servlet/package-info.java @@ -1,4 +1,4 @@ /** * blade处理请求和响应 */ -package blade.servlet; \ No newline at end of file +package com.blade.servlet; \ No newline at end of file diff --git a/blade-core/src/main/java/blade/wrapper/RequestResponseBuilder.java b/blade-core/src/main/java/com/blade/wrapper/RequestResponseBuilder.java similarity index 92% rename from blade-core/src/main/java/blade/wrapper/RequestResponseBuilder.java rename to blade-core/src/main/java/com/blade/wrapper/RequestResponseBuilder.java index 3ce54662a..6f1632fcb 100644 --- a/blade-core/src/main/java/blade/wrapper/RequestResponseBuilder.java +++ b/blade-core/src/main/java/com/blade/wrapper/RequestResponseBuilder.java @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.wrapper; +package com.blade.wrapper; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import blade.route.RouteMatcher; -import blade.servlet.Request; -import blade.servlet.Response; +import com.blade.route.RouteMatcher; +import com.blade.servlet.Request; +import com.blade.servlet.Response; /** * Request、Response构建器 diff --git a/blade-core/src/main/java/blade/wrapper/RequestWrapper.java b/blade-core/src/main/java/com/blade/wrapper/RequestWrapper.java similarity index 96% rename from blade-core/src/main/java/blade/wrapper/RequestWrapper.java rename to blade-core/src/main/java/com/blade/wrapper/RequestWrapper.java index 4e0bd8767..5ed43fd18 100644 --- a/blade-core/src/main/java/blade/wrapper/RequestWrapper.java +++ b/blade-core/src/main/java/com/blade/wrapper/RequestWrapper.java @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.wrapper; +package com.blade.wrapper; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; -import blade.route.RouteMatcher; -import blade.servlet.QueryParamsMap; -import blade.servlet.Request; -import blade.servlet.Session; +import com.blade.route.RouteMatcher; +import com.blade.servlet.QueryParamsMap; +import com.blade.servlet.Request; +import com.blade.servlet.Session; /** * Request增强 diff --git a/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java b/blade-core/src/main/java/com/blade/wrapper/ResponseWrapper.java similarity index 97% rename from blade-core/src/main/java/blade/wrapper/ResponseWrapper.java rename to blade-core/src/main/java/com/blade/wrapper/ResponseWrapper.java index 611f523f7..25af7a372 100644 --- a/blade-core/src/main/java/blade/wrapper/ResponseWrapper.java +++ b/blade-core/src/main/java/com/blade/wrapper/ResponseWrapper.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.wrapper; +package com.blade.wrapper; import javax.servlet.http.HttpServletResponse; -import blade.render.ModelAndView; -import blade.servlet.Response; +import com.blade.render.ModelAndView; +import com.blade.servlet.Response; /** * Response增强 diff --git a/blade-core/src/main/java/blade/wrapper/package-info.java b/blade-core/src/main/java/com/blade/wrapper/package-info.java similarity index 71% rename from blade-core/src/main/java/blade/wrapper/package-info.java rename to blade-core/src/main/java/com/blade/wrapper/package-info.java index 4d6f56a30..975baf60b 100644 --- a/blade-core/src/main/java/blade/wrapper/package-info.java +++ b/blade-core/src/main/java/com/blade/wrapper/package-info.java @@ -1,4 +1,4 @@ /** * 对HttpServletRequest和HttpServletResponse的包装 */ -package blade.wrapper; \ No newline at end of file +package com.blade.wrapper; \ No newline at end of file From e28d51005f1aecd4dd1b00cfe7d0cdbbcb57f69e Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 10:37:31 +0800 Subject: [PATCH 153/545] separation of the ioc package --- blade-core/src/main/java/com/blade/Blade.java | 2 +- blade-core/src/main/java/com/blade/IocApplication.java | 2 +- blade-core/src/main/java/com/blade/RequestHandler.java | 2 +- .../java/com/blade/ioc/{ => impl}/AbstractBeanFactory.java | 4 +++- .../main/java/com/blade/ioc/{ => impl}/DefaultContainer.java | 4 +++- .../src/main/java/com/blade/ioc/{ => impl}/PrototypeBean.java | 4 +++- .../src/main/java/com/blade/ioc/{ => impl}/SingleBean.java | 4 +++- .../src/main/java/com/blade/route/RouteMatcherBuilder.java | 2 +- 8 files changed, 16 insertions(+), 8 deletions(-) rename blade-core/src/main/java/com/blade/ioc/{ => impl}/AbstractBeanFactory.java (93%) rename blade-core/src/main/java/com/blade/ioc/{ => impl}/DefaultContainer.java (99%) rename blade-core/src/main/java/com/blade/ioc/{ => impl}/PrototypeBean.java (91%) rename blade-core/src/main/java/com/blade/ioc/{ => impl}/SingleBean.java (91%) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 5d9721113..1c0840149 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -20,7 +20,7 @@ import java.util.Map; import com.blade.ioc.Container; -import com.blade.ioc.DefaultContainer; +import com.blade.ioc.impl.DefaultContainer; import com.blade.plugin.Plugin; import com.blade.render.Render; import com.blade.render.RenderFactory; diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index 6f4c281f2..be1d59ad1 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -19,8 +19,8 @@ import java.util.Set; import com.blade.ioc.Container; -import com.blade.ioc.DefaultContainer; import com.blade.ioc.Scope; +import com.blade.ioc.impl.DefaultContainer; import com.blade.plugin.Plugin; import com.blade.route.RouteBase; diff --git a/blade-core/src/main/java/com/blade/RequestHandler.java b/blade-core/src/main/java/com/blade/RequestHandler.java index 463c7e5f8..6f14c8abc 100644 --- a/blade-core/src/main/java/com/blade/RequestHandler.java +++ b/blade-core/src/main/java/com/blade/RequestHandler.java @@ -22,8 +22,8 @@ import javax.servlet.http.HttpServletResponse; import com.blade.ioc.Container; -import com.blade.ioc.DefaultContainer; import com.blade.ioc.Scope; +import com.blade.ioc.impl.DefaultContainer; import com.blade.render.ModelAndView; import com.blade.route.HttpMethod; import com.blade.route.RouteHandler; diff --git a/blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java b/blade-core/src/main/java/com/blade/ioc/impl/AbstractBeanFactory.java similarity index 93% rename from blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java rename to blade-core/src/main/java/com/blade/ioc/impl/AbstractBeanFactory.java index 27e5ea2cf..404bc4bdb 100644 --- a/blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java +++ b/blade-core/src/main/java/com/blade/ioc/impl/AbstractBeanFactory.java @@ -13,13 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.ioc; +package com.blade.ioc.impl; import java.lang.annotation.Annotation; import java.util.Collection; import java.util.List; import java.util.Set; +import com.blade.ioc.Container; + import blade.kit.log.Logger; /** diff --git a/blade-core/src/main/java/com/blade/ioc/DefaultContainer.java b/blade-core/src/main/java/com/blade/ioc/impl/DefaultContainer.java similarity index 99% rename from blade-core/src/main/java/com/blade/ioc/DefaultContainer.java rename to blade-core/src/main/java/com/blade/ioc/impl/DefaultContainer.java index 337ce80c0..c276294f1 100644 --- a/blade-core/src/main/java/com/blade/ioc/DefaultContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/impl/DefaultContainer.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.ioc; +package com.blade.ioc.impl; import java.lang.annotation.Annotation; import java.lang.reflect.Field; @@ -28,6 +28,8 @@ import com.blade.annotation.Component; import com.blade.annotation.Inject; import com.blade.annotation.Path; +import com.blade.ioc.Container; +import com.blade.ioc.Scope; import java.util.Set; diff --git a/blade-core/src/main/java/com/blade/ioc/PrototypeBean.java b/blade-core/src/main/java/com/blade/ioc/impl/PrototypeBean.java similarity index 91% rename from blade-core/src/main/java/com/blade/ioc/PrototypeBean.java rename to blade-core/src/main/java/com/blade/ioc/impl/PrototypeBean.java index 9821e4ee5..4963132fb 100644 --- a/blade-core/src/main/java/com/blade/ioc/PrototypeBean.java +++ b/blade-core/src/main/java/com/blade/ioc/impl/PrototypeBean.java @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.ioc; +package com.blade.ioc.impl; + +import com.blade.ioc.Scope; /** * 原生bean对象 diff --git a/blade-core/src/main/java/com/blade/ioc/SingleBean.java b/blade-core/src/main/java/com/blade/ioc/impl/SingleBean.java similarity index 91% rename from blade-core/src/main/java/com/blade/ioc/SingleBean.java rename to blade-core/src/main/java/com/blade/ioc/impl/SingleBean.java index be60db8b1..a4d24678e 100644 --- a/blade-core/src/main/java/com/blade/ioc/SingleBean.java +++ b/blade-core/src/main/java/com/blade/ioc/impl/SingleBean.java @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.ioc; +package com.blade.ioc.impl; + +import com.blade.ioc.Scope; /** * 单例bean对象,容器中只存在一个bean实例 diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java index 87cae4b50..ca7ef79f7 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java @@ -25,7 +25,7 @@ import com.blade.annotation.Path; import com.blade.annotation.Route; import com.blade.ioc.Container; -import com.blade.ioc.DefaultContainer; +import com.blade.ioc.impl.DefaultContainer; import com.blade.route.impl.DefaultRouteMatcher; import blade.exception.BladeException; From 34614e9f9650883ca77d2b98719b3a6a15c8041b Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 11:02:29 +0800 Subject: [PATCH 154/545] refactoring --- blade-core/pom.xml | 20 +- blade-core/src/main/java/com/blade/Blade.java | 427 ++++-------------- .../src/main/java/com/blade/CoreFilter.java | 20 +- ...RequestHandler.java => FilterHandler.java} | 18 +- .../main/java/com/blade/IocApplication.java | 9 +- .../com/blade/ioc/impl/DefaultContainer.java | 14 +- .../main/java/com/blade/render/JspRender.java | 5 +- .../main/java/com/blade/render/Render.java | 12 +- .../com/blade/route/RouteMatcherBuilder.java | 8 +- .../blade/route/impl/DefaultRouteMatcher.java | 17 +- .../main/java/com/blade/servlet/Response.java | 9 +- 11 files changed, 152 insertions(+), 407 deletions(-) rename blade-core/src/main/java/com/blade/{RequestHandler.java => FilterHandler.java} (93%) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index eaa01c691..f68fbd01f 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -14,7 +14,7 @@ ${blade.version} blade-core https://github.com/biezhi/blade/blade-core - + com.bladejava @@ -25,5 +25,23 @@ javax.servlet javax.servlet-api + + org.eclipse.jetty + jetty-server + 8.1.15.v20140411 + provided + + + org.testng + testng + 6.9.6 + provided + + + org.mockito + mockito-all + 2.0.2-beta + test + diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 1c0840149..53ca5d0f8 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -24,11 +24,6 @@ import com.blade.plugin.Plugin; import com.blade.render.Render; import com.blade.render.RenderFactory; -import com.blade.route.HttpMethod; -import com.blade.route.RouteBase; -import com.blade.route.RouteHandler; -import com.blade.route.RouteMatcherBuilder; -import com.blade.route.RouterExecutor; import blade.kit.IOKit; import blade.kit.PropertyKit; @@ -40,35 +35,47 @@ * @author biezhi * @since 1.0 */ -public final class Blade { +public class Blade { + + public static final String VERSION = "1.4.0-alpha"; + + private static final Blade ME = new Blade(); - public static final String VERSION = "1.2.9"; /** * 框架是否已经初始化 */ - protected static boolean IS_INIT = false; + boolean isInit = false; /** * blade全局初始化对象,在web.xml中配置,必须 */ - protected static Bootstrap bootstrap; + Bootstrap bootstrap; /** * 全局配置对象 */ - protected final static Config CONFIG = new Config(); + protected Config config = new Config(); /** * IOC容器,存储路由到ioc中 */ - private final static Container container = DefaultContainer.single(); + private Container container = DefaultContainer.single(); + + /** + * 默认启动端口 + */ + public int DEFAULT_PORT = 9000; private Blade() { } - static synchronized void init() { - Blade.IS_INIT = true; - } + public static Blade me(){ + return ME; + } + + public void setInit(boolean isInit) { + this.isInit = isInit; + } /** *
@@ -77,7 +84,7 @@ static synchronized void init() {
 	 * 
 	 * @param object		要注册的object
 	 */
-	public static synchronized void regObject(Object object){
+	public void regObject(Object object){
 		container.registBean(object);
 	}
 	
@@ -89,7 +96,7 @@ public static synchronized void regObject(Object object){
 	 * 
 	 * @param confName		配置文件路径
 	 */
-	public static synchronized void config(String confName){
+	public void config(String confName){
 		Map configMap = PropertyKit.getPropertyMap(confName);
 		configuration(configMap);
 	}
@@ -102,7 +109,7 @@ public static synchronized void config(String confName){
 	 * 
 	 * @param jsonPath		json文件路径
 	 */
-	public static synchronized void configJsonPath(String jsonPath){
+	public void configJsonPath(String jsonPath){
 		InputStream inputStream = Blade.class.getResourceAsStream(jsonPath);
 		if(null != inputStream){
 			try {
@@ -122,7 +129,7 @@ public static synchronized void configJsonPath(String jsonPath){
 	 * 
 	 * @param json		json配置
 	 */
-	public static synchronized void configJson(String json){
+	public void configJson(String json){
 		Map configMap = JSONKit.toMap(json);
 		configuration(configMap);
 	}
@@ -134,8 +141,8 @@ public static synchronized void configJson(String json){
 	 * 
 	 * @param configMap		存放配置的map
 	 */
-	private static void configuration(Map configMap){
-		new Configurator(CONFIG, configMap).run();
+	private void configuration(Map configMap){
+		new Configurator(config, configMap).run();
 	}
 	
 	/**
@@ -144,9 +151,9 @@ private static void configuration(Map configMap){
      * 
      * @param packages 	路由包路径
      */
-    public static synchronized void routes(String...packages){
+    public void routes(String...packages){
     	if(null != packages && packages.length >0){
-    		CONFIG.setRoutePackages(packages);
+    		config.setRoutePackages(packages);
     	}
     }
     
@@ -156,9 +163,9 @@ public static synchronized void routes(String...packages){
      * 
      * @param basePackage 	默认包路径
      */
-    public static synchronized void defaultRoute(String basePackage){
+    public void defaultRoute(String basePackage){
     	if(null != basePackage){
-    		CONFIG.setBasePackage(basePackage);
+    		config.setBasePackage(basePackage);
     	}
     }
     
@@ -167,9 +174,9 @@ public static synchronized void defaultRoute(String basePackage){
      * 
      * @param packageName 拦截器所在的包
      */
-	public static synchronized void interceptor(String packageName) {
+	public void interceptor(String packageName) {
 		if(null != packageName && packageName.length() >0){
-			CONFIG.setInterceptorPackage(packageName);
+			config.setInterceptorPackage(packageName);
     	}
 	}
 	
@@ -178,9 +185,9 @@ public static synchronized void interceptor(String packageName) {
      * 
      * @param packages 	所有需要做注入的包,可传入多个
      */
-    public static synchronized void ioc(String...packages){
+    public void ioc(String...packages){
     	if(null != packages && packages.length >0){
-    		CONFIG.setIocPackages(packages);
+    		config.setIocPackages(packages);
     	}
     }
     
@@ -189,7 +196,7 @@ public static synchronized void ioc(String...packages){
 	 * 
 	 * @param render 	渲染引擎对象
 	 */
-	public static synchronized void viewEngin(Render render) {
+	public void viewEngin(Render render) {
 		RenderFactory.init(render);
 	}
 	
@@ -198,9 +205,9 @@ public static synchronized void viewEngin(Render render) {
 	 * 
 	 * @param prefix 	视图路径,如:/WEB-INF/views
 	 */
-	public static synchronized void viewPrefix(final String prefix) {
+	public void viewPrefix(final String prefix) {
 		if(null != prefix && prefix.startsWith("/")){
-			CONFIG.setViewPrefix(prefix);
+			config.setViewPrefix(prefix);
 		}
 	}
 	
@@ -209,9 +216,9 @@ public static synchronized void viewPrefix(final String prefix) {
 	 * 
 	 * @param viewExt	视图后缀,如:.html	 .vm
 	 */
-	public static synchronized void viewSuffix(final String suffix) {
+	public void viewSuffix(final String suffix) {
 		if(null != suffix && suffix.startsWith(".")){
-			CONFIG.setViewSuffix(suffix);
+			config().setViewSuffix(suffix);
 		}
 	}
 	
@@ -221,7 +228,7 @@ public static synchronized void viewSuffix(final String suffix) {
 	 * @param viewPath	视图路径,如:/WEB-INF/views
 	 * @param viewExt	视图后缀,如:.html	 .vm
 	 */
-	public static synchronized void view(final String viewPath, final String viewExt) {
+	public void view(final String viewPath, final String viewExt) {
 		viewPrefix(viewPath);
 		viewSuffix(viewExt);
 	}
@@ -231,8 +238,8 @@ public static synchronized void view(final String viewPath, final String viewExt
 	 * 
 	 * @param folders
 	 */
-	public static synchronized void staticFolder(final String ... folders) {
-		CONFIG.setStaticFolders(folders);
+	public void staticFolder(final String ... folders) {
+		config.setStaticFolders(folders);
 	}
 	
     /**
@@ -240,8 +247,8 @@ public static synchronized void staticFolder(final String ... folders) {
      * 
      * @param bladeApplication 	全局初始化bladeApplication
      */
-    public static synchronized  void app(Bootstrap bootstrap){
-    	Blade.bootstrap = bootstrap;
+    public  void app(Bootstrap bootstrap){
+    	this.bootstrap = bootstrap;
     }
     
     /**
@@ -249,8 +256,8 @@ public static synchronized  void app(Bootstrap bootstrap){
      * 
      * @param view404	404视图页面
      */
-    public static synchronized void view404(final String view404){
-    	CONFIG.setView404(view404);
+    public void view404(final String view404){
+    	config().setView404(view404);
     }
     
     /**
@@ -258,8 +265,8 @@ public static synchronized void view404(final String view404){
      * 
      * @param view500	500视图页面
      */
-    public static synchronized void view500(final String view500){
-    	CONFIG.setView500(view500);
+    public void view500(final String view500){
+    	config.setView500(view500);
     }
 
     /**
@@ -267,382 +274,120 @@ public static synchronized void view500(final String view500){
      * 
      * @param webRoot	web根目录物理路径
      */
-    public static synchronized void webRoot(final String webRoot){
-    	CONFIG.setWebRoot(webRoot);
+    public void webRoot(final String webRoot){
+    	config.setWebRoot(webRoot);
     }
     
     /**
 	 * 设置系统是否以debug方式运行
 	 * @param isdebug	true:是,默认true;false:否
 	 */
-	public static synchronized void debug(boolean isdebug){
-		CONFIG.setDebug(isdebug);
-	}
-	
-	/**
-	 * 加载一个Route
-	 * @param route
-	 */
-	public static synchronized void load(Class route){
-		IocApplication.addRouteClass(route);
-	}
-	
-	/**
-	 * 注册一个函数式的路由
- *

- * 方法上指定请求类型,如:post:signin - *

- * @param path 路由url - * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 - */ - public static synchronized void register(String path, Class clazz, String methodName){ - RouteMatcherBuilder.buildFunctional(path, clazz, methodName, null); - } - - /** - * 注册一个函数式的路由 - * @param path 路由url - * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 - * @param httpMethod 请求类型,GET/POST - */ - public static synchronized void register(String path, Class clazz, String methodName, HttpMethod httpMethod){ - RouteMatcherBuilder.buildFunctional(path, clazz, methodName, httpMethod); - } - - /** - * get请求 - * @param path - * @param routeHandler - */ - public static synchronized void get(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.GET); - } - - /** - * get请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor get(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.GET); - } - return null; + public void debug(boolean isdebug){ + config.setDebug(isdebug); } - /** - * post请求 - * @param path - * @param routeHandler - */ - public static synchronized void post(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.POST); + public Blade listen(int port){ + DEFAULT_PORT = port; + return this; } - /** - * post请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor post(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.POST); - } - return null; - } - - /** - * delete请求 - * @param path - * @param routeHandler - */ - public static synchronized void delete(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.DELETE); - } - - /** - * delete请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor delete(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.DELETE); - } - return null; - } - - /** - * put请求 - * @param paths - */ - public static synchronized void put(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PUT); - } - - /** - * put请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor put(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.PUT); - } - return null; - } - - /** - * patch请求 - * @param path - * @param routeHandler - */ - public static synchronized void patch(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PATCH); - } - - /** - * patch请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor patch(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.PATCH); - } - return null; - } - - /** - * head请求 - * @param path - * @param routeHandler - */ - public static synchronized void head(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.HEAD); - } - - /** - * head请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor head(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.HEAD); - } - return null; - } - - /** - * trace请求 - * @param path - * @param routeHandler - */ - public static synchronized void trace(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.TRACE); - } - - /** - * trace请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor trace(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.TRACE); - } - return null; - } - - /** - * options请求 - * @param path - * @param routeHandler - */ - public static synchronized void options(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.OPTIONS); - } - - /** - * options请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor options(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.OPTIONS); - } - return null; - } - - /** - * connect请求 - * @param path - * @param routeHandler - */ - public static synchronized void connect(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.CONNECT); - } - - /** - * connect请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor connect(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.CONNECT); - } - return null; - } - - /** - * 任意请求 - * @param path - * @param routeHandler - */ - public static synchronized void all(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.ALL); - } - - /** - * all请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor all(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.ALL); - } - return null; - } - - /** - * 拦截器before请求 - * @param path - * @param routeHandler - */ - public static synchronized void before(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); - } - - /** - * before请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor before(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.BEFORE); - } - return null; - } - - /** - * 拦截器after请求 - * @param path - * @param routeHandler - */ - public static synchronized void after(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); - } - - /** - * after请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor after(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.AFTER); - } - return null; + public void start() { + } - public final static Config config(){ - return CONFIG; + public Config config(){ + return config(); } /** * @return 返回Blade要扫描的基础包 */ - public static String basePackage(){ - return CONFIG.getBasePackage(); + public String basePackage(){ + return config.getBasePackage(); } /** * @return 返回路由包数组 */ - public static String[] routes(){ - return CONFIG.getRoutePackages(); + public String[] routes(){ + return config.getRoutePackages(); } /** * @return 返回IOC所有包 */ - public static String[] iocs(){ - return CONFIG.getIocPackages(); + public String[] iocs(){ + return config.getIocPackages(); } /** * @return 返回拦截器包数组,只有一个元素 这里统一用String[] */ - public static String interceptor(){ - return CONFIG.getInterceptorPackage(); + public String interceptor(){ + return config.getInterceptorPackage(); } /** * @return 返回视图存放路径 */ - public static String viewPrefix(){ - return CONFIG.getViewPrefix(); + public String viewPrefix(){ + return config.getViewPrefix(); } /** * @return 返回系统默认字符编码 */ - public static String encoding(){ - return CONFIG.getEncoding(); + public String encoding(){ + return config.getEncoding(); } /** * @return 返回balde启动端口 */ - public static String viewSuffix(){ - return CONFIG.getViewSuffix(); + public String viewSuffix(){ + return config.getViewSuffix(); } /** * @return 返回404视图 */ - public static String view404(){ - return CONFIG.getView404(); + public String view404(){ + return config.getView404(); } /** * @return 返回500视图 */ - public static String view500(){ - return CONFIG.getView500(); + public String view500(){ + return config.getView500(); } /** * @return 返回webroot路径 */ - public static String webRoot(){ - return CONFIG.getWebRoot(); + public String webRoot(){ + return config.getWebRoot(); } /** * @return 返回系统是否以debug方式运行 */ - public static boolean debug(){ - return CONFIG.isDebug(); + public boolean debug(){ + return config.isDebug(); } /** * @return 返回静态资源目录 */ - public static String[] staticFolder(){ - return CONFIG.getStaticFolders(); + public String[] staticFolder(){ + return config.getStaticFolders(); } /** * @return 返回Bootstrap对象 */ - public static Bootstrap bootstrap(){ + public Bootstrap bootstrap(){ return bootstrap; } @@ -652,7 +397,7 @@ public static Bootstrap bootstrap(){ * @return */ @SuppressWarnings("unchecked") - public static T plugin(Class pluginClazz){ + public T plugin(Class pluginClazz){ Object object = IocApplication.getPlugin(pluginClazz); if(null == object){ object = IocApplication.registerPlugin(pluginClazz); diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 0ae08879e..7f95db146 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -50,30 +50,32 @@ public class CoreFilter implements Filter { static ServletContext servletContext; + private Blade blade; @Override public void init(FilterConfig filterConfig) throws ServletException { // 防止重复初始化 try { - if(!Blade.IS_INIT){ + blade = Blade.me(); + if(!blade.isInit){ - Blade.webRoot(filterConfig.getServletContext().getRealPath("/")); + blade.webRoot(filterConfig.getServletContext().getRealPath("/")); final Bootstrap bootstrap = getBootstrap(filterConfig.getInitParameter(BOOSTRAP_CLASS)); bootstrap.init(); - Blade.app(bootstrap); + blade.app(bootstrap); // 构建路由 - RouteMatcherBuilder.building(); + RouteMatcherBuilder.building(blade); - IocApplication.init(); + IocApplication.init(blade); servletContext = filterConfig.getServletContext(); bootstrap.contextInitialized(); - Blade.init(); + blade.setInit(true); LOGGER.info("blade init complete!"); } @@ -114,13 +116,13 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; - httpRequest.setCharacterEncoding(Blade.encoding()); - httpResponse.setCharacterEncoding(Blade.encoding()); + httpRequest.setCharacterEncoding(blade.encoding()); + httpResponse.setCharacterEncoding(blade.encoding()); /** * 是否被RequestHandler执行 */ - boolean isHandler = new RequestHandler().handler(httpRequest, httpResponse); + boolean isHandler = new FilterHandler(blade).handler(httpRequest, httpResponse); if(!isHandler){ chain.doFilter(httpRequest, httpResponse); } diff --git a/blade-core/src/main/java/com/blade/RequestHandler.java b/blade-core/src/main/java/com/blade/FilterHandler.java similarity index 93% rename from blade-core/src/main/java/com/blade/RequestHandler.java rename to blade-core/src/main/java/com/blade/FilterHandler.java index 6f14c8abc..80c9b4a9f 100644 --- a/blade-core/src/main/java/com/blade/RequestHandler.java +++ b/blade-core/src/main/java/com/blade/FilterHandler.java @@ -49,9 +49,11 @@ * @author biezhi * @since 1.0 */ -public class RequestHandler { +public class FilterHandler { - private static final Logger LOGGER = Logger.getLogger(RequestHandler.class); + private static final Logger LOGGER = Logger.getLogger(FilterHandler.class); + + private Blade blade; /** * 服务器500错误时返回的HTML @@ -70,8 +72,8 @@ public class RequestHandler { */ private static final DefaultRouteMatcher DEFAULT_ROUTE_MATCHER = DefaultRouteMatcher.instance(); - public RequestHandler(){ - + public FilterHandler(Blade blade){ + this.blade = blade; } /** @@ -90,13 +92,13 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse String uri = PathKit.getRelativePath(httpRequest); // 如果是静态资源则交给filter处理 - if(null != Blade.staticFolder() && Blade.staticFolder().length > 0){ + if(null != blade.staticFolder() && blade.staticFolder().length > 0){ if(!filterStaticFolder(uri)){ return false; } } - if(Blade.debug()){ + if(blade.debug()){ LOGGER.debug("Request : " + method + "\t" + uri); } @@ -307,9 +309,9 @@ private void render(Response response, Object result){ * @return */ private boolean filterStaticFolder(String uri){ - int len = Blade.staticFolder().length; + int len = blade.staticFolder().length; for(int i=0; i> ROUTE_CLASS_LIST = CollectionKit.newArrayList(); - public static void init(){ + public static void init(Blade blade){ // 初始化全局配置类 if(null == container.getBean(Bootstrap.class, Scope.SINGLE)){ - container.registBean(Blade.bootstrap()); + container.registBean(blade.bootstrap); } // 初始化ioc容器 - initIOC(); + initIOC(blade.iocs()); // 初始化注入 try { @@ -92,8 +92,7 @@ public static void init(){ * 要配置符合ioc的注解的类才会被加载 * */ - private static void initIOC() { - String[] iocPackages = Blade.iocs(); + private static void initIOC(String[] iocPackages) { if(null != iocPackages && iocPackages.length > 0){ for(String packageName : iocPackages){ registerBean(packageName); diff --git a/blade-core/src/main/java/com/blade/ioc/impl/DefaultContainer.java b/blade-core/src/main/java/com/blade/ioc/impl/DefaultContainer.java index c276294f1..8509d0f4e 100644 --- a/blade-core/src/main/java/com/blade/ioc/impl/DefaultContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/impl/DefaultContainer.java @@ -23,16 +23,14 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; -import com.blade.Blade; import com.blade.annotation.Component; import com.blade.annotation.Inject; import com.blade.annotation.Path; import com.blade.ioc.Container; import com.blade.ioc.Scope; -import java.util.Set; - import blade.exception.BladeException; import blade.kit.CloneKit; import blade.kit.CollectionKit; @@ -174,11 +172,7 @@ public Object registBean(Class clazz) { if(null != clazz.getDeclaredAnnotations()){ putAnnotationMap(clazz, object); } - - if(Blade.debug()){ - LOGGER.info("register object:" + name + "=" + object); - } - + LOGGER.info("register object:" + name + "=" + object); } return object; } @@ -307,9 +301,7 @@ public void registBean(Set> classes) { public Object registBean(Object object) { String name = object.getClass().getName(); put(name, object); - if(Blade.debug()){ - LOGGER.info("register object:" + name + "=" + object); - } + LOGGER.info("register object:" + name + "=" + object); return object; } diff --git a/blade-core/src/main/java/com/blade/render/JspRender.java b/blade-core/src/main/java/com/blade/render/JspRender.java index 1f2f128bb..6c17b9706 100644 --- a/blade-core/src/main/java/com/blade/render/JspRender.java +++ b/blade-core/src/main/java/com/blade/render/JspRender.java @@ -23,7 +23,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.blade.Blade; import com.blade.BladeWebContext; import blade.kit.log.Logger; @@ -50,8 +49,8 @@ public Object render(final String view){ HttpServletResponse servletResponse = BladeWebContext.servletResponse(); // 设置编码 - servletRequest.setCharacterEncoding(Blade.encoding()); - servletResponse.setCharacterEncoding(Blade.encoding()); + servletRequest.setCharacterEncoding(blade.encoding()); + servletResponse.setCharacterEncoding(blade.encoding()); // 构造jsp地址 String realPath = disposeView(view); diff --git a/blade-core/src/main/java/com/blade/render/Render.java b/blade-core/src/main/java/com/blade/render/Render.java index 88be2417d..98ec51207 100644 --- a/blade-core/src/main/java/com/blade/render/Render.java +++ b/blade-core/src/main/java/com/blade/render/Render.java @@ -38,6 +38,8 @@ public abstract class Render { private static final Logger LOGGER = Logger.getLogger(Render.class); + Blade blade = Blade.me(); + static final String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + Blade.VERSION +"
"; @@ -53,7 +55,7 @@ public void render404(String viewName){ */ public void render404(Response response, String viewName){ try { - String view404 = Blade.view404(); + String view404 = blade.view404(); if(null != view404){ ModelAndView modelAndView = new ModelAndView(view404); modelAndView.add("viewName", viewName); @@ -82,7 +84,7 @@ public void render404(Response response, String viewName){ public void render500(String bodyContent){ try { - String view500 = Blade.view500(); + String view500 = blade.view500(); if(null != view500){ ModelAndView modelAndView = new ModelAndView(view500); modelAndView.add("body", bodyContent); @@ -236,10 +238,10 @@ public void javascript(String javascript){ */ String disposeView(String view){ if(null != view){ - view = Blade.viewPrefix() + view; + view = blade.viewPrefix() + view; view = view.replaceAll("[/]+", "/"); - if(!view.endsWith(Blade.viewSuffix())){ - view = view + Blade.viewSuffix(); + if(!view.endsWith(blade.viewSuffix())){ + view = view + blade.viewSuffix(); } } return view; diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java index ca7ef79f7..92f756450 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java @@ -75,9 +75,9 @@ private RouteMatcherBuilder() { * * @return 返回构建路由后的构造器 */ - public static synchronized void building() { + public static synchronized void building(Blade blade) { - String basePackage = Blade.basePackage(); + String basePackage = blade.basePackage(); if(StringKit.isNotBlank(basePackage)){ @@ -95,13 +95,13 @@ public static synchronized void building() { } else { // 路由 - String[] routePackages = Blade.routes(); + String[] routePackages = blade.routes(); if(null != routePackages && routePackages.length > 0){ buildRoute(routePackages); } // 拦截器 - String interceptorPackage = Blade.interceptor(); + String interceptorPackage = blade.interceptor(); if(StringKit.isNotBlank(interceptorPackage)){ buildInterceptor(interceptorPackage); } diff --git a/blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java b/blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java index 434e95f66..88d0f721f 100644 --- a/blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java @@ -20,7 +20,6 @@ import java.util.Comparator; import java.util.List; -import com.blade.Blade; import com.blade.route.HttpMethod; import com.blade.route.RouteHandler; import com.blade.route.RouteMatcher; @@ -131,9 +130,7 @@ public void addRoute(Class target, Method execMethod, String url, HttpMethod routeMatcher.setHttpMethod(httpMethod); routeMatcher.setPath(url); - if(Blade.debug()){ - LOGGER.debug("Add Route:" + routeMatcher); - } + LOGGER.debug("Add Route:" + routeMatcher); // 添加到路由集合 routes.add(routeMatcher); @@ -154,9 +151,7 @@ public void addInterceptor(Class target, Method execMethod, String url, HttpM routeMatcher.setHttpMethod(httpMethod); routeMatcher.setPath(url); - if(Blade.debug()){ - LOGGER.debug("Add Interceptor:" + routeMatcher); - } + LOGGER.debug("Add Interceptor:" + routeMatcher); // 添加到路由集合 interceptors.add(routeMatcher); @@ -176,9 +171,7 @@ public void addRoute(RouteHandler routerHandler, String url, HttpMethod httpMeth routeMatcher.setHttpMethod(httpMethod); routeMatcher.setPath(url); - if(Blade.debug()){ - LOGGER.debug("Add Route:" + routeMatcher); - } + LOGGER.debug("Add Route:" + routeMatcher); // 添加到路由集合 routes.add(routeMatcher); @@ -198,9 +191,7 @@ public void addInterceptor(RouteHandler routerHandler, String url, HttpMethod ht routeMatcher.setHttpMethod(httpMethod); routeMatcher.setPath(url); - if(Blade.debug()){ - LOGGER.debug("Add Interceptor:" + routeMatcher); - } + LOGGER.debug("Add Interceptor:" + routeMatcher); // 添加到路由集合 interceptors.add(routeMatcher); diff --git a/blade-core/src/main/java/com/blade/servlet/Response.java b/blade-core/src/main/java/com/blade/servlet/Response.java index b44289abd..c61976353 100644 --- a/blade-core/src/main/java/com/blade/servlet/Response.java +++ b/blade-core/src/main/java/com/blade/servlet/Response.java @@ -22,7 +22,6 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; -import com.blade.Blade; import com.blade.BladeWebContext; import com.blade.render.ModelAndView; import com.blade.render.Render; @@ -120,9 +119,7 @@ public HttpServletResponse servletResponse() { * @param location 重定向的location */ public void go(String path) { - if (Blade.debug()) { - LOGGER.debug("Redirecting (%s %s to %s", "Found", HttpServletResponse.SC_FOUND, path); - } + LOGGER.debug("Redirecting (%s %s to %s", "Found", HttpServletResponse.SC_FOUND, path); try { String ctx = BladeWebContext.servletContext().getContextPath(); String location = (ctx + path).replaceAll("//", "/"); @@ -138,9 +135,7 @@ public void go(String path) { * @param location 重定向的location */ public void redirect(String location) { - if (Blade.debug()) { - LOGGER.debug("Redirecting (%s %s to %s", "Found", HttpServletResponse.SC_FOUND, location); - } + LOGGER.debug("Redirecting (%s %s to %s", "Found", HttpServletResponse.SC_FOUND, location); try { response.sendRedirect(location); } catch (IOException ioException) { From 43289cf9e1f17f4efee89f6e30cf11dfbafd8cce Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 11:02:48 +0800 Subject: [PATCH 155/545] refactoring --- .../src/main/java/com/blade/route/Router.java | 279 ++++++++++++++++++ .../com/blade/servlet/multipart/FileItem.java | 120 ++++++++ .../test/java/org/blade/server/AppTest.java | 38 --- 3 files changed, 399 insertions(+), 38 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/route/Router.java create mode 100644 blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java delete mode 100644 blade-server/src/test/java/org/blade/server/AppTest.java diff --git a/blade-core/src/main/java/com/blade/route/Router.java b/blade-core/src/main/java/com/blade/route/Router.java new file mode 100644 index 000000000..64a837954 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/Router.java @@ -0,0 +1,279 @@ +package com.blade.route; + +import com.blade.IocApplication; + +public class Router { + + /** + * 加载一个Route + * @param route + */ + @Deprecated + public static synchronized void load(Class route){ + IocApplication.addRouteClass(route); + } + + /** + * 注册一个函数式的路由
+ *

+ * 方法上指定请求类型,如:post:signin + *

+ * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + */ + public static synchronized void register(String path, Class clazz, String methodName){ + RouteMatcherBuilder.buildFunctional(path, clazz, methodName, null); + } + + /** + * 注册一个函数式的路由 + * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + * @param httpMethod 请求类型,GET/POST + */ + public static synchronized void register(String path, Class clazz, String methodName, HttpMethod httpMethod){ + RouteMatcherBuilder.buildFunctional(path, clazz, methodName, httpMethod); + } + + /** + * get请求 + * @param path + * @param routeHandler + */ + public static synchronized void get(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.GET); + } + + /** + * get请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor get(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.GET); + } + return null; + } + + /** + * post请求 + * @param path + * @param routeHandler + */ + public static synchronized void post(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.POST); + } + + /** + * post请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor post(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.POST); + } + return null; + } + + /** + * delete请求 + * @param path + * @param routeHandler + */ + public static synchronized void delete(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.DELETE); + } + + /** + * delete请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor delete(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.DELETE); + } + return null; + } + + /** + * put请求 + * @param paths + */ + public static synchronized void put(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PUT); + } + + /** + * put请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor put(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.PUT); + } + return null; + } + + /** + * patch请求 + * @param path + * @param routeHandler + */ + public static synchronized void patch(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PATCH); + } + + /** + * patch请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor patch(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.PATCH); + } + return null; + } + + /** + * head请求 + * @param path + * @param routeHandler + */ + public static synchronized void head(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.HEAD); + } + + /** + * head请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor head(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.HEAD); + } + return null; + } + + /** + * trace请求 + * @param path + * @param routeHandler + */ + public static synchronized void trace(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.TRACE); + } + + /** + * trace请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor trace(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.TRACE); + } + return null; + } + + /** + * options请求 + * @param path + * @param routeHandler + */ + public static synchronized void options(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.OPTIONS); + } + + /** + * options请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor options(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.OPTIONS); + } + return null; + } + + /** + * connect请求 + * @param path + * @param routeHandler + */ + public static synchronized void connect(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.CONNECT); + } + + /** + * connect请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor connect(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.CONNECT); + } + return null; + } + + /** + * 任意请求 + * @param path + * @param routeHandler + */ + public static synchronized void all(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.ALL); + } + + /** + * all请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor all(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.ALL); + } + return null; + } + + /** + * 拦截器before请求 + * @param path + * @param routeHandler + */ + public static synchronized void before(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); + } + + /** + * before请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor before(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.BEFORE); + } + return null; + } + + /** + * 拦截器after请求 + * @param path + * @param routeHandler + */ + public static synchronized void after(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); + } + + /** + * after请求,多个路由 + * @param paths + */ + public static synchronized RouterExecutor after(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.AFTER); + } + return null; + } + +} diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java b/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java new file mode 100644 index 000000000..9e65c9d03 --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet.multipart; + +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; + +import blade.kit.io.FastByteArrayOutputStream; + +/** + * 文件上传Item + * + * @author biezhi + * @since 1.0 + */ +public class FileItem { + + private String name; + + private boolean isFile; + private String fileName; + private String contentType; + private InputStream inputStream; + + public static final String FORM_DATA = "form-data"; + + public static final String MULTIPART_FORM_DATA = "multipart/form-data"; + + // 数据体缓存 + private FastByteArrayOutputStream outputStream; + + public void write(byte[] buf, int off, int len) { + if (outputStream == null) { + outputStream = new FastByteArrayOutputStream(); + } + outputStream.write(buf, off, len); + } + + // ----------------------------------------------------------------- + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getContentType() { + return contentType; + } + + public void setContentType(String contentType) { + this.contentType = contentType; + } + + public boolean isFile() { + return isFile; + } + + public void setFile(boolean isFile) { + this.isFile = isFile; + } + + public byte[] getFileContent() { + byte[] buf = outputStream.toByteArray(); + int dirtyCount = 2; + + // 最后会多出一个\r\n, + // 根据ServletInputStream, \n 就算一行结束, 因此对于\r需要特殊判断 + if ('\r' != buf[buf.length - 2]) + dirtyCount = 1; + + return Arrays.copyOfRange(buf, 0, buf.length - dirtyCount); + } + + public String getString(String encoding){ + try { + return outputStream == null ? null : new String(getFileContent(), encoding); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } + + public String getString() { + return outputStream == null ? null : new String(getFileContent()); + } + + public InputStream getInputStream() { + return inputStream; + } + + public void setInputStream(InputStream inputStream) { + this.inputStream = inputStream; + } + +} + diff --git a/blade-server/src/test/java/org/blade/server/AppTest.java b/blade-server/src/test/java/org/blade/server/AppTest.java deleted file mode 100644 index fc032d009..000000000 --- a/blade-server/src/test/java/org/blade/server/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.blade.server; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -/** - * Unit test for simple App. - */ -public class AppTest - extends TestCase -{ - /** - * Create the test case - * - * @param testName name of the test case - */ - public AppTest( String testName ) - { - super( testName ); - } - - /** - * @return the suite of tests being tested - */ - public static Test suite() - { - return new TestSuite( AppTest.class ); - } - - /** - * Rigourous Test :-) - */ - public void testApp() - { - assertTrue( true ); - } -} From 1633d22b57f7d37d1320ccfe740d681b9ec9388f Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 14:29:16 +0800 Subject: [PATCH 156/545] add server --- blade-core/src/main/java/com/blade/Blade.java | 310 +++++++++++++++++- .../src/main/java/com/blade/CoreFilter.java | 6 +- .../main/java/com/blade/IocApplication.java | 2 +- .../src/main/java/com/blade/route/Router.java | 13 +- blade-core/src/test/java/com/blade/App.java | 34 ++ 5 files changed, 351 insertions(+), 14 deletions(-) create mode 100644 blade-core/src/test/java/com/blade/App.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 53ca5d0f8..e7475f1ce 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -17,16 +17,28 @@ import java.io.IOException; import java.io.InputStream; +import java.util.EnumSet; import java.util.Map; +import javax.servlet.DispatcherType; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; + import com.blade.ioc.Container; import com.blade.ioc.impl.DefaultContainer; import com.blade.plugin.Plugin; import com.blade.render.Render; import com.blade.render.RenderFactory; +import com.blade.route.HttpMethod; +import com.blade.route.RouteBase; +import com.blade.route.RouteHandler; +import com.blade.route.RouteMatcherBuilder; +import com.blade.route.RouterExecutor; import blade.kit.IOKit; import blade.kit.PropertyKit; +import blade.kit.ReflectKit; import blade.kit.json.JSONKit; /** @@ -49,7 +61,7 @@ public class Blade { /** * blade全局初始化对象,在web.xml中配置,必须 */ - Bootstrap bootstrap; + private Bootstrap bootstrap; /** * 全局配置对象 @@ -191,6 +203,277 @@ public void ioc(String...packages){ } } + /** + * 加载一个Route + * @param route + */ + public void load(Class route){ + IocApplication.addRouteClass(route); + } + + /** + * 注册一个函数式的路由
+ *

+ * 方法上指定请求类型,如:post:signin + *

+ * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + */ + public void register(String path, Class clazz, String methodName){ + RouteMatcherBuilder.buildFunctional(path, clazz, methodName, null); + } + + /** + * 注册一个函数式的路由 + * @param path 路由url + * @param clazz 路由处理类 + * @param methodName 路由处理方法名称 + * @param httpMethod 请求类型,GET/POST + */ + public void register(String path, Class clazz, String methodName, HttpMethod httpMethod){ + RouteMatcherBuilder.buildFunctional(path, clazz, methodName, httpMethod); + } + + /** + * get请求 + * @param path + * @param routeHandler + */ + public void get(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.GET); + } + + /** + * get请求,多个路由 + * @param paths + */ + public RouterExecutor get(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.GET); + } + return null; + } + + /** + * post请求 + * @param path + * @param routeHandler + */ + public void post(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.POST); + } + + /** + * post请求,多个路由 + * @param paths + */ + public RouterExecutor post(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.POST); + } + return null; + } + + /** + * delete请求 + * @param path + * @param routeHandler + */ + public void delete(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.DELETE); + } + + /** + * delete请求,多个路由 + * @param paths + */ + public RouterExecutor delete(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.DELETE); + } + return null; + } + + /** + * put请求 + * @param paths + */ + public void put(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PUT); + } + + /** + * put请求,多个路由 + * @param paths + */ + public RouterExecutor put(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.PUT); + } + return null; + } + + /** + * patch请求 + * @param path + * @param routeHandler + */ + public void patch(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PATCH); + } + + /** + * patch请求,多个路由 + * @param paths + */ + public RouterExecutor patch(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.PATCH); + } + return null; + } + + /** + * head请求 + * @param path + * @param routeHandler + */ + public void head(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.HEAD); + } + + /** + * head请求,多个路由 + * @param paths + */ + public RouterExecutor head(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.HEAD); + } + return null; + } + + /** + * trace请求 + * @param path + * @param routeHandler + */ + public void trace(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.TRACE); + } + + /** + * trace请求,多个路由 + * @param paths + */ + public RouterExecutor trace(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.TRACE); + } + return null; + } + + /** + * options请求 + * @param path + * @param routeHandler + */ + public void options(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.OPTIONS); + } + + /** + * options请求,多个路由 + * @param paths + */ + public RouterExecutor options(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.OPTIONS); + } + return null; + } + + /** + * connect请求 + * @param path + * @param routeHandler + */ + public void connect(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.CONNECT); + } + + /** + * connect请求,多个路由 + * @param paths + */ + public RouterExecutor connect(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.CONNECT); + } + return null; + } + + /** + * 任意请求 + * @param path + * @param routeHandler + */ + public void all(String path, RouteHandler router){ + RouteMatcherBuilder.buildHandler(path, router, HttpMethod.ALL); + } + + /** + * all请求,多个路由 + * @param paths + */ + public RouterExecutor all(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.ALL); + } + return null; + } + + /** + * 拦截器before请求 + * @param path + * @param routeHandler + */ + public void before(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); + } + + /** + * before请求,多个路由 + * @param paths + */ + public RouterExecutor before(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.BEFORE); + } + return null; + } + + /** + * 拦截器after请求 + * @param path + * @param routeHandler + */ + public void after(String path, RouteHandler routeHandler){ + RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); + } + + /** + * after请求,多个路由 + * @param paths + */ + public RouterExecutor after(String... paths){ + if(null != paths && paths.length > 0){ + return new RouterExecutor(paths, HttpMethod.AFTER); + } + return null; + } + /** * 设置渲染引擎,默认是JSP引擎 * @@ -242,15 +525,25 @@ public void staticFolder(final String ... folders) { config.setStaticFolders(folders); } + /** * 动态设置全局初始化类 * - * @param bladeApplication 全局初始化bladeApplication + * @param bootstrap 全局初始化bladeApplication */ public void app(Bootstrap bootstrap){ this.bootstrap = bootstrap; } + /** + * 动态设置全局初始化类 + * + * @param bootstrap 全局初始化bladeApplication + */ + public void app(Class bootstrap){ + this.bootstrap = (Bootstrap) ReflectKit.newInstance(bootstrap); + } + /** * 设置404视图页面 * @@ -291,8 +584,19 @@ public Blade listen(int port){ return this; } - public void start() { + public void start() throws Exception { + + Server server = new Server(DEFAULT_PORT); + ServletContextHandler context = new ServletContextHandler(/*ServletContextHandler.SESSIONS*/); + context.setContextPath("/"); + context.setResourceBase(System.getProperty("java.io.tmpdir")); + context.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + server.setHandler(context); + + server.start(); + server.join(); + } public Config config(){ diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 7f95db146..0ce5a0c03 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -62,7 +62,11 @@ public void init(FilterConfig filterConfig) throws ServletException { blade.webRoot(filterConfig.getServletContext().getRealPath("/")); - final Bootstrap bootstrap = getBootstrap(filterConfig.getInitParameter(BOOSTRAP_CLASS)); + Bootstrap bootstrap = blade.bootstrap(); + if(null == bootstrap){ + bootstrap = getBootstrap(filterConfig.getInitParameter(BOOSTRAP_CLASS)); + } + bootstrap.init(); blade.app(bootstrap); diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index 3b01fc840..fcfe0b73a 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -64,7 +64,7 @@ public static void init(Blade blade){ // 初始化全局配置类 if(null == container.getBean(Bootstrap.class, Scope.SINGLE)){ - container.registBean(blade.bootstrap); + container.registBean(blade.bootstrap()); } // 初始化ioc容器 diff --git a/blade-core/src/main/java/com/blade/route/Router.java b/blade-core/src/main/java/com/blade/route/Router.java index 64a837954..31ef2619d 100644 --- a/blade-core/src/main/java/com/blade/route/Router.java +++ b/blade-core/src/main/java/com/blade/route/Router.java @@ -3,13 +3,8 @@ import com.blade.IocApplication; public class Router { - - /** - * 加载一个Route - * @param route - */ - @Deprecated - public static synchronized void load(Class route){ + + public void load(Class route){ IocApplication.addRouteClass(route); } @@ -22,7 +17,7 @@ public static synchronized void load(Class route){ * @param clazz 路由处理类 * @param methodName 路由处理方法名称 */ - public static synchronized void register(String path, Class clazz, String methodName){ + public void register(String path, Class clazz, String methodName){ RouteMatcherBuilder.buildFunctional(path, clazz, methodName, null); } @@ -42,7 +37,7 @@ public static synchronized void register(String path, Class clazz, String met * @param path * @param routeHandler */ - public static synchronized void get(String path, RouteHandler router){ + public void get(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.GET); } diff --git a/blade-core/src/test/java/com/blade/App.java b/blade-core/src/test/java/com/blade/App.java new file mode 100644 index 000000000..28ecf51b8 --- /dev/null +++ b/blade-core/src/test/java/com/blade/App.java @@ -0,0 +1,34 @@ +package com.blade; + +import com.blade.route.RouteHandler; +import com.blade.servlet.Request; +import com.blade.servlet.Response; + +public class App extends Bootstrap { + + @Override + public void init() { + + } + + public static void main(String[] args) { + Blade blade = Blade.me(); + blade.get("/").run(new RouteHandler() { + + @Override + public Object handler(Request request, Response response) { + response.html("

hello blade!

"); + return null; + } + }); + + try { + blade.app(new App()); + blade.start(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + +} From c32250c914ab51190fcafb9532c0b51b1e5b8e99 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 16:01:59 +0800 Subject: [PATCH 157/545] add asset and update readme --- README.md | 79 +++++++----------- README_CN.md | 83 +++++++++++++++++++ blade-core/pom.xml | 24 ++++-- blade-core/src/main/java/com/blade/Blade.java | 16 ++-- .../src/main/java/com/blade/asset/Asset.java | 69 +++++++++++++++ .../java/com/blade/asset/AssetLoader.java | 19 +++++ .../java/com/blade/asset/FileAssetLoader.java | 64 ++++++++++++++ blade-core/src/test/java/com/blade/App.java | 16 +--- 8 files changed, 297 insertions(+), 73 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/asset/Asset.java create mode 100644 blade-core/src/main/java/com/blade/asset/AssetLoader.java create mode 100644 blade-core/src/main/java/com/blade/asset/FileAssetLoader.java diff --git a/README.md b/README.md index edcd80b11..f3d05cc5b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![a concise and powerful web development framework](http://i1.tietuku.com/0c4b9726253b6268.png "a concise and powerful web development framework")](http://bladejava.com) + +[![](https://i.imgur.com/8I289mA.png)](http://bladejava.com) [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) @@ -7,65 +8,47 @@ [中文](https://github.com/biezhi/blade/blob/master/README_CN.md) -## What Is Blade? - -**blade** Is a concise and powerful web development framework. If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! - -- __Simple MVC__ -Use Java language to complete the MVC more concise. - -- __Restful__ -Provide a Restful style routing interface. +# What Is Blade? +`blade` is a lightweight MVC framework. It is based on the principles of simplicity, relevance and elegance. +If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! -- __Multiple routing configuration__ -Routing configuration in the form of more functional routing, annotations routing, routing reflection way. +# Features +* [x] Lightweight. The code is simple and structure is clear +* [x] Modular (you can choose which components to use) +* [x] Support plug-in extension mechanism +* [x] Restful style routing interface +* [x] Multiple configuration files support (currently properties, json and coding) +* [x] Eembed jetty server and template engine support +* [x] Support jdk1.6 or higher version -- __Coding/JSON/configuration file__ -Blade offers a variety of configurations, including JSON, the Properties file, hard coding. +# Overview -- __Plug-in extension mechanism__ -Blade extensions support you use third party components, modular development of more convenient. +* Simplicity. The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. It is a goal of the project that users should be able to understand the whole framework in a single day. -- __Template engine Plugin__ -Support access to mainstream template engine, there are beetl, jetbrick, velocity engine. +* Relevance. `blade` doesn't assume anything. We focus on things that matter, this way we are able to ensure easy maintenance and keep the system well-organized, well-planned and sweet. -- __Support JDK1.6 +__ -Support jdk1.6 or higher version. - -- __The source code of less than 100kb__ -The source code of the blade framework is less than 100 KB, learn easy, get started quickly, the code is simple. - -## Example +* Elegance. `blade` uses golang best practises. We are not afraid of heights, it's just that we need a parachute in our backpack. The source code is heavily documented, any functionality should be well explained and well tested. +# Getting started +To get started, first [include the Blade library](http://bladejava.com) and then create a class with a main method like this: ```java -public class App extends Bootstrap{ - - Logger logger = Logger.getLogger(App.class); +public class App extends Bootstrap { + @Override - public void init() { - // register router - Blade.regsiter("/hello", SayHi.class, "hello"); - - // anonymous router,java8 so simple - Blade.get("/get", new Router() { - @Override - public String handler(Request request, Response response) { - System.out.println("come get!!"); - System.out.println(request.query("name")); - return "get"; - } - }); - - // multiple routing, java8 syntax - Blade.get("/", "/index").run(request, response) -> { - System.out.println("come index!!"); - return "index"; + public void init() {} + + public static void main(String[] args) throws Exception { + Blade blade = Blade.me(); + blade.get("/").run(request, response) -> { + response.html("

Hello blade!

"); + return null; }); + blade.app(App.class).listen(9001).start(); } - } ``` - +Run it and point your browser to http://localhost:9001. There you go, you've just created your first Blade app! + OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: + [hello project](https://github.com/bladejava/hello) diff --git a/README_CN.md b/README_CN.md index c4735feff..2766e511d 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,3 +1,86 @@ + +[![](https://i.imgur.com/8I289mA.png)](http://bladejava.com) + +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) +[![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) +[![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) +[![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) + +[English](https://github.com/biezhi/blade/blob/master/README.md) + +# Blade是什么? +`blade` 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计。 +如果你喜欢,欢迎 [Star and Fork](https://github.com/biezhi/blade), 谢谢! + +# 特性 +* [x] 轻量级。代码简洁,结构清晰,更容易开发 +* [x] 模块化(你可以选择使用哪些组件) +* [x] 插件扩展机制 +* [x] Restful风格的路由接口 +* [x] 多种配置文件支持(当前支持properties、json和硬编码) +* [x] 内置Jetty服务,模板引擎支持 +* [x] 支持JDK1.6或者更高版本 + +# 概述 + +* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 + +* Relevance. `blade` doesn't assume anything. We focus on things that matter, this way we are able to ensure easy maintenance and keep the system well-organized, well-planned and sweet. + +* Elegance. `blade` uses golang best practises. We are not afraid of heights, it's just that we need a parachute in our backpack. The source code is heavily documented, any functionality should be well explained and well tested. + +# Getting started +To get started, first [include the Blade library](http://bladejava.com) and then create a class with a main method like this: +```java +public class App extends Bootstrap { + + @Override + public void init() {} + + public static void main(String[] args) throws Exception { + Blade blade = Blade.me(); + blade.get("/").run(request, response) -> { + response.html("

Hello blade!

"); + return null; + }); + blade.app(App.class).listen(9001).start(); + } +} +``` +Run it and point your browser to http://localhost:9001. There you go, you've just created your first Blade app! + +OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: + ++ [hello project](https://github.com/bladejava/hello) ++ [api docs](http://bladejava.com/apidocs/) ++ [user guide](https://github.com/biezhi/blade/wiki) ++ [some examples](https://github.com/bladejava) + +## Plan + + 1. Improve the document + 2. Add configurable log + 3. Complete the Java China BBS + 4. Maintain and optimize the code + +## Update + +[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## licenses + +Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) + +## Contact + +Blog:[https://biezhi.me](https://biezhi.me) + +Mail: biezhi.me#gmail.com + +QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) + + + [![简洁强大的JavaWeb框架](http://i1.tietuku.com/0c4b9726253b6268.png "简洁强大的JavaWeb框架")](http://bladejava.com) [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index f68fbd01f..1b59f0aa3 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -15,6 +15,10 @@ blade-core https://github.com/biezhi/blade/blade-core + + 9.3.4.v20151007 + + com.bladejava @@ -24,13 +28,21 @@ javax.servlet javax.servlet-api + runtime - - org.eclipse.jetty - jetty-server - 8.1.15.v20140411 - provided - + + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + provided + org.testng testng diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index e7475f1ce..20b777df6 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -66,7 +66,7 @@ public class Blade { /** * 全局配置对象 */ - protected Config config = new Config(); + private Config config = new Config(); /** * IOC容器,存储路由到ioc中 @@ -501,7 +501,7 @@ public void viewPrefix(final String prefix) { */ public void viewSuffix(final String suffix) { if(null != suffix && suffix.startsWith(".")){ - config().setViewSuffix(suffix); + config.setViewSuffix(suffix); } } @@ -531,8 +531,9 @@ public void staticFolder(final String ... folders) { * * @param bootstrap 全局初始化bladeApplication */ - public void app(Bootstrap bootstrap){ + public Blade app(Bootstrap bootstrap){ this.bootstrap = bootstrap; + return this; } /** @@ -540,8 +541,9 @@ public void app(Bootstrap bootstrap){ * * @param bootstrap 全局初始化bladeApplication */ - public void app(Class bootstrap){ + public Blade app(Class bootstrap){ this.bootstrap = (Bootstrap) ReflectKit.newInstance(bootstrap); + return this; } /** @@ -550,7 +552,7 @@ public void app(Class bootstrap){ * @param view404 404视图页面 */ public void view404(final String view404){ - config().setView404(view404); + config.setView404(view404); } /** @@ -588,12 +590,12 @@ public void start() throws Exception { Server server = new Server(DEFAULT_PORT); - ServletContextHandler context = new ServletContextHandler(/*ServletContextHandler.SESSIONS*/); + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); context.setResourceBase(System.getProperty("java.io.tmpdir")); context.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); server.setHandler(context); - + server.start(); server.join(); diff --git a/blade-core/src/main/java/com/blade/asset/Asset.java b/blade-core/src/main/java/com/blade/asset/Asset.java new file mode 100644 index 000000000..a9c25fe8c --- /dev/null +++ b/blade-core/src/main/java/com/blade/asset/Asset.java @@ -0,0 +1,69 @@ +package com.blade.asset; + +import java.io.InputStream; + +/** + * Represents a static asset resource. + * + * @author German Escobar + */ +public class Asset { + + /** + * The input stream of the asset. + */ + private final InputStream inputStream; + + /** + * The name of the asset. + */ + private final String name; + + /** + * The content length of the asset. + */ + private final long length; + + /** + * The epoch timestamp when this asset was last modified + */ + private final long lastModified; + + /** + * The content type of the asset. + */ + private final String contentType; + + + public Asset(InputStream inputStream, String name, String contentType, long length) { + this(inputStream, name, contentType, length, 0); + } + + public Asset(InputStream inputStream, String name, String contentType, long length, long lastModified) { + this.inputStream = inputStream; + this.name = name; + this.contentType = contentType; + this.length = length; + this.lastModified = lastModified; + } + + public String getName() { + return name; + } + + public String getContentType() { + return contentType; + } + + public InputStream getInputStream() { + return inputStream; + } + + public long getLength() { + return length; + } + + public long getLastModified() { + return lastModified; + } +} diff --git a/blade-core/src/main/java/com/blade/asset/AssetLoader.java b/blade-core/src/main/java/com/blade/asset/AssetLoader.java new file mode 100644 index 000000000..3efa5626b --- /dev/null +++ b/blade-core/src/main/java/com/blade/asset/AssetLoader.java @@ -0,0 +1,19 @@ +package com.blade.asset; + +/** + * Implementations of this interface provide mechanisms to load assets. + * + * @author German Escobar + */ +public interface AssetLoader { + + /** + * Retrieves the asset identified with the uri. + * + * @param uri represents the location of the asset. + * + * @return an {@link Asset} object or null if not found. + */ + Asset load(String uri); + +} diff --git a/blade-core/src/main/java/com/blade/asset/FileAssetLoader.java b/blade-core/src/main/java/com/blade/asset/FileAssetLoader.java new file mode 100644 index 000000000..354586c0c --- /dev/null +++ b/blade-core/src/main/java/com/blade/asset/FileAssetLoader.java @@ -0,0 +1,64 @@ +package com.blade.asset; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; + +import org.eclipse.jetty.http.MimeTypes; + +/** + * An {@link AssetLoader} implementation that uses the file system to retrieve assets. + * + * @author German Escobar + */ +public class FileAssetLoader implements AssetLoader { + + private static final String DEFAULT_BASE_DIRECTORY = "assets"; + + private File parent; + + /** + * Constructor. Initializes the object with the default base directory. + */ + public FileAssetLoader() { + this(DEFAULT_BASE_DIRECTORY); + } + + /** + * Constructor. Initializes the object with the specified base directory. + * + * @param directory + */ + public FileAssetLoader(String directory) { + this.parent = new File(directory); + } + + public FileAssetLoader(File parent) { + this.parent = parent; + } + + @Override + public Asset load(String fileName) { + try { + File file = new File(parent, fileName); + + if (!file.exists() || !file.isFile()) { + return null; + } + + long lastModified = file.lastModified(); + MimeTypes mimeTypes = new MimeTypes(); + + String contentType = "text/plain"; + String buffer = mimeTypes.getMimeByExtension(file.getName()); + if (buffer != null) { + contentType = buffer.toString(); + } + + return new Asset(new FileInputStream(file), file.getName(), contentType, file.length(), lastModified); + } catch (FileNotFoundException e) { + return null; + } + } + +} diff --git a/blade-core/src/test/java/com/blade/App.java b/blade-core/src/test/java/com/blade/App.java index 28ecf51b8..d1167ddf9 100644 --- a/blade-core/src/test/java/com/blade/App.java +++ b/blade-core/src/test/java/com/blade/App.java @@ -7,27 +7,19 @@ public class App extends Bootstrap { @Override - public void init() { - - } + public void init() {} - public static void main(String[] args) { + public static void main(String[] args) throws Exception { Blade blade = Blade.me(); blade.get("/").run(new RouteHandler() { - @Override public Object handler(Request request, Response response) { - response.html("

hello blade!

"); + response.html("

Hello blade!

"); return null; } }); - try { - blade.app(new App()); - blade.start(); - } catch (Exception e) { - e.printStackTrace(); - } + blade.app(App.class).listen(9001).start(); } From c1ff781aa088d3650fcf6f7292354c74156d2dd8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 16:42:39 +0800 Subject: [PATCH 158/545] update readme --- README.md | 25 +++++------ README_CN.md | 124 +++++---------------------------------------------- pom.xml | 9 ++-- 3 files changed, 26 insertions(+), 132 deletions(-) diff --git a/README.md b/README.md index f3d05cc5b..247591ae9 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,17 @@ [![](https://i.imgur.com/8I289mA.png)](http://bladejava.com) -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) -[![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [中文](https://github.com/biezhi/blade/blob/master/README_CN.md) -# What Is Blade? -`blade` is a lightweight MVC framework. It is based on the principles of simplicity, relevance and elegance. +## What Is Blade? +`blade` is a lightweight MVC framework. It is based on the principles of simplicity and elegance. If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! -# Features +## Features * [x] Lightweight. The code is simple and structure is clear * [x] Modular (you can choose which components to use) * [x] Support plug-in extension mechanism @@ -21,15 +20,13 @@ If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! * [x] Eembed jetty server and template engine support * [x] Support jdk1.6 or higher version -# Overview +## Overview * Simplicity. The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. It is a goal of the project that users should be able to understand the whole framework in a single day. -* Relevance. `blade` doesn't assume anything. We focus on things that matter, this way we are able to ensure easy maintenance and keep the system well-organized, well-planned and sweet. - -* Elegance. `blade` uses golang best practises. We are not afraid of heights, it's just that we need a parachute in our backpack. The source code is heavily documented, any functionality should be well explained and well tested. +* Elegance. `blade` Support the REST style routing interface, provide DSL grammar to write, no invasive interceptors. -# Getting started +## Getting started To get started, first [include the Blade library](http://bladejava.com) and then create a class with a main method like this: ```java public class App extends Bootstrap { @@ -51,10 +48,10 @@ Run it and point your browser to http://localhost:9001. There you go, you've jus OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: -+ [hello project](https://github.com/bladejava/hello) -+ [api docs](http://bladejava.com/apidocs/) -+ [user guide](https://github.com/biezhi/blade/wiki) -+ [some examples](https://github.com/bladejava) ++ [HELLO](https://github.com/bladejava/hello) ++ [API DOCS](http://bladejava.com/apidocs/) ++ [USE GUIDE](https://github.com/biezhi/blade/wiki) ++ [EXAMPLES](https://github.com/bladejava) ## Plan diff --git a/README_CN.md b/README_CN.md index 2766e511d..62581a850 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,18 +1,17 @@ [![](https://i.imgur.com/8I289mA.png)](http://bladejava.com) -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) -[![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [English](https://github.com/biezhi/blade/blob/master/README.md) -# Blade是什么? +## Blade是什么? `blade` 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计。 如果你喜欢,欢迎 [Star and Fork](https://github.com/biezhi/blade), 谢谢! -# 特性 +## 特性 * [x] 轻量级。代码简洁,结构清晰,更容易开发 * [x] 模块化(你可以选择使用哪些组件) * [x] 插件扩展机制 @@ -21,16 +20,14 @@ * [x] 内置Jetty服务,模板引擎支持 * [x] 支持JDK1.6或者更高版本 -# 概述 +## 概述 * 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 -* Relevance. `blade` doesn't assume anything. We focus on things that matter, this way we are able to ensure easy maintenance and keep the system well-organized, well-planned and sweet. +* 优雅的:`blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 -* Elegance. `blade` uses golang best practises. We are not afraid of heights, it's just that we need a parachute in our backpack. The source code is heavily documented, any functionality should be well explained and well tested. - -# Getting started -To get started, first [include the Blade library](http://bladejava.com) and then create a class with a main method like this: +## 快速入门 +开始之前,首先 [引入Blade的库文件](http://bladejava.com) ,然后创建一个类继承自 `Bootstrap` ,编写 `Main` 函数: ```java public class App extends Bootstrap { @@ -47,113 +44,14 @@ public class App extends Bootstrap { } } ``` -Run it and point your browser to http://localhost:9001. There you go, you've just created your first Blade app! - -OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: - -+ [hello project](https://github.com/bladejava/hello) -+ [api docs](http://bladejava.com/apidocs/) -+ [user guide](https://github.com/biezhi/blade/wiki) -+ [some examples](https://github.com/bladejava) - -## Plan - - 1. Improve the document - 2. Add configurable log - 3. Complete the Java China BBS - 4. Maintain and optimize the code - -## Update - -[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## licenses - -Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) - -## Contact - -Blog:[https://biezhi.me](https://biezhi.me) - -Mail: biezhi.me#gmail.com - -QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) - - - -[![简洁强大的JavaWeb框架](http://i1.tietuku.com/0c4b9726253b6268.png "简洁强大的JavaWeb框架")](http://bladejava.com) - -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) -[![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) -[![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) -[![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) - -[English](https://github.com/biezhi/blade/blob/master/README.md) - -## Blade是什么? - -**blade** 是一个简洁强大的web框架,简洁的源码值得你阅读和学习。如果你喜欢,欢迎[Star and Fork](https://github.com/biezhi/blade) ! - -- __简洁的MVC__ -使用java语言完成mvc更加简洁 - -- __RESTful__ -提供Restful风格的路由接口 - -- __多种路由配置方式__ -更多方式进行路由的配置,函数式路由,注解路由,反射方式路由 - -- __编码/JSON/配置文件__ -blade提供多种配置方式,包括JSON、Properties文件,硬编码 - -- __插件扩展机制__ -blade支持你使用第三方的组件进行扩展,更方便的积木式开发 - -- __模板引擎支持__ -支持主流模板引擎接入,目前已经有beetl、jetbrick、velocity引擎 +用浏览器打开 http://localhost:9001 这样就可以看到第一个Blade应用了! -- __支持JDK1.6+__ -支持jdk1.6或者更高版本 - -- __不到100K的源码__ -目前blade框架的源代码不到100kb,学习简单,上手快速,代码简洁 - -## 示例 - -```java -public class App extends Bootstrap{ - - Logger logger = Logger.getLogger(App.class); - @Override - public void init() { - // 注册函数式路由 - Blade.register("/hello", SayHi.class, "hello"); - - // 匿名路由 - Blade.get("/get", new Router() { - @Override - public String handler(Request request, Response response) { - System.out.println("进入get!!"); - System.out.println(request.query("name")); - return "get"; - } - }); - - // 多个路由,java8语法 - Blade.get("/", "/index").run(request, response) -> { - System.out.println("come index!!"); - return "index"; - }); - } -} -``` - OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: -+ [hello](https://github.com/bladejava/hello) -+ [api docs](http://bladejava.com/apidocs/) ++ [hello工程](https://github.com/bladejava/hello) ++ [API文档](http://bladejava.com/apidocs/) + [使用指南](https://github.com/biezhi/blade/wiki) -+ [更多例子](https://github.com/bladejava) ++ [相关案例](https://github.com/bladejava) ### 计划 diff --git a/pom.xml b/pom.xml index 02b49543d..6c90da95a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,5 @@ - + 4.0.0 com.bladejava @@ -16,8 +15,8 @@ 1.6 UTF-8 4.11 - 3.0.1 - 1.3.0-alpha + 3.1.0 + 1.4.0-alpha @@ -29,7 +28,7 @@ blade-velocity blade-beetl blade-redis - + From def01d87e134e3d7f02fb8019f4bc2aa04ab17f8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 16:53:12 +0800 Subject: [PATCH 159/545] upgrade blade version to 1.4.0-alpha --- blade-core/src/main/java/com/blade/Blade.java | 2 +- blade-core/src/main/java/com/blade/render/Render.java | 4 ++-- blade-redis/pom.xml | 2 +- .../src/main/java/blade/plugin/redis/RedisPlugin.java | 5 +++-- blade-sql2o/pom.xml | 2 +- blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java | 5 +++-- .../src/main/java/blade/plugin/sql2o/Sql2oPlugin.java | 7 ++++--- .../main/java/blade/plugin/sql2o/ds/DataSourceManager.java | 6 ++++-- 8 files changed, 19 insertions(+), 14 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 20b777df6..4b16ce774 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -703,7 +703,7 @@ public Bootstrap bootstrap(){ * @return */ @SuppressWarnings("unchecked") - public T plugin(Class pluginClazz){ + public T plugin(Class pluginClazz){ Object object = IocApplication.getPlugin(pluginClazz); if(null == object){ object = IocApplication.registerPlugin(pluginClazz); diff --git a/blade-core/src/main/java/com/blade/render/Render.java b/blade-core/src/main/java/com/blade/render/Render.java index 98ec51207..d7d830a0f 100644 --- a/blade-core/src/main/java/com/blade/render/Render.java +++ b/blade-core/src/main/java/com/blade/render/Render.java @@ -38,7 +38,7 @@ public abstract class Render { private static final Logger LOGGER = Logger.getLogger(Render.class); - Blade blade = Blade.me(); + protected Blade blade = Blade.me(); static final String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + Blade.VERSION +"
"; @@ -236,7 +236,7 @@ public void javascript(String javascript){ * @param view 视图名称 * @return 返回取出多余"/"的全路径 */ - String disposeView(String view){ + protected String disposeView(String view){ if(null != view){ view = blade.viewPrefix() + view; view = view.replaceAll("[/]+", "/"); diff --git a/blade-redis/pom.xml b/blade-redis/pom.xml index 424711890..fbbbfc706 100644 --- a/blade-redis/pom.xml +++ b/blade-redis/pom.xml @@ -11,7 +11,7 @@ blade-redis jar - 1.2.2 + 1.4.0-alpha blade-redis https://github.com/biezhi/blade/blade-redis diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java b/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java index be62d1408..e8e691791 100644 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java +++ b/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java @@ -3,9 +3,10 @@ import java.util.ArrayList; import java.util.List; -import redis.clients.jedis.JedisShardInfo; +import com.blade.plugin.Plugin; + import blade.kit.log.Logger; -import blade.plugin.Plugin; +import redis.clients.jedis.JedisShardInfo; /** * redis插件 diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 012bfa7a1..b88daf208 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - 1.2.9-alpha + 1.4.0-alpha blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 1ef44b84b..f43f23ac6 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -11,7 +11,8 @@ import org.sql2o.Query; import org.sql2o.Sql2o; -import blade.Blade; +import com.blade.Blade; + import blade.kit.EncrypKit; import blade.kit.StringKit; import blade.kit.log.Logger; @@ -41,7 +42,7 @@ public class Model { */ private Sql2o sql2o = DataSourceManager.me().getSql2o(); - private static final Sql2oPlugin SQL2O_PLUGIN = Blade.plugin(Sql2oPlugin.class); + private static final Sql2oPlugin SQL2O_PLUGIN = Blade.me().plugin(Sql2oPlugin.class); /** * 当前class实例 diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index 7eeb3a714..95c7a1979 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -7,12 +7,13 @@ import javax.sql.DataSource; -import blade.Blade; +import com.blade.Blade; +import com.blade.plugin.Plugin; + import blade.cache.CacheException; import blade.kit.PropertyKit; import blade.kit.StringKit; import blade.kit.log.Logger; -import blade.plugin.Plugin; import blade.plugin.sql2o.cache.Sql2oCache; import blade.plugin.sql2o.cache.Sql2oCacheFactory; import blade.plugin.sql2o.ds.DataSourceManager; @@ -89,7 +90,7 @@ public Sql2oPlugin config(DBConfig dbConfig){ * @param dataSource 数据源对象 */ public Sql2oPlugin config(DataSource dataSource){ - String opencache = Blade.config().get("blade.db.opencache"); + String opencache = Blade.me().config().get("blade.db.opencache"); if(StringKit.isNotBlank(opencache)){ isOpenCache = Boolean.valueOf(opencache); } diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java index 6df231dbc..e27d0fac2 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java @@ -4,7 +4,8 @@ import org.sql2o.Sql2o; -import blade.Blade; +import com.blade.Blade; + import blade.plugin.sql2o.DBConfig; import blade.plugin.sql2o.Sql2oPlugin; import blade.plugin.sql2o.exception.DataSourceException; @@ -33,7 +34,8 @@ public void run(){ if(null != this.dataSource){ sql2o = new Sql2o(this.dataSource); } else { - DBConfig dbConfig = Blade.plugin(Sql2oPlugin.class).dbConfig(); + Sql2oPlugin sql2oPlugin = Blade.me().plugin(Sql2oPlugin.class); + DBConfig dbConfig = sql2oPlugin.dbConfig(); if(null == dbConfig){ throw new DataSourceException("数据库配置失败"); } From 0023143ee147383d156f450d7a1f978a0cf4f1a4 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 17:31:38 +0800 Subject: [PATCH 160/545] - --- blade-core/src/main/java/com/blade/Blade.java | 66 +++-- .../src/main/java/com/blade/route/Router.java | 274 ------------------ .../java/com/blade/route/RouterChain.java | 7 - blade-core/src/test/java/com/blade/App.java | 2 + 4 files changed, 47 insertions(+), 302 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/route/Router.java delete mode 100644 blade-core/src/main/java/com/blade/route/RouterChain.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 4b16ce774..f634650ca 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -40,6 +40,7 @@ import blade.kit.PropertyKit; import blade.kit.ReflectKit; import blade.kit.json.JSONKit; +import blade.kit.log.Logger; /** * Blade Core Class @@ -53,6 +54,8 @@ public class Blade { private static final Blade ME = new Blade(); + private static final Logger LOGGER = Logger.getLogger(Blade.class); + /** * 框架是否已经初始化 */ @@ -207,8 +210,9 @@ public void ioc(String...packages){ * 加载一个Route * @param route */ - public void load(Class route){ + public Blade load(Class route){ IocApplication.addRouteClass(route); + return this; } /** @@ -220,8 +224,9 @@ public void load(Class route){ * @param clazz 路由处理类 * @param methodName 路由处理方法名称 */ - public void register(String path, Class clazz, String methodName){ - RouteMatcherBuilder.buildFunctional(path, clazz, methodName, null); + public Blade addRoute(String path, Class clazz, String method){ + RouteMatcherBuilder.buildFunctional(path, clazz, method, null); + return this; } /** @@ -231,8 +236,9 @@ public void register(String path, Class clazz, String methodName){ * @param methodName 路由处理方法名称 * @param httpMethod 请求类型,GET/POST */ - public void register(String path, Class clazz, String methodName, HttpMethod httpMethod){ - RouteMatcherBuilder.buildFunctional(path, clazz, methodName, httpMethod); + public Blade addRoute(String path, Class clazz, String method, HttpMethod httpMethod){ + RouteMatcherBuilder.buildFunctional(path, clazz, method, httpMethod); + return this; } /** @@ -240,8 +246,9 @@ public void register(String path, Class clazz, String methodName, HttpMethod * @param path * @param routeHandler */ - public void get(String path, RouteHandler router){ + public Blade get(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.GET); + return this; } /** @@ -260,8 +267,9 @@ public RouterExecutor get(String... paths){ * @param path * @param routeHandler */ - public void post(String path, RouteHandler router){ + public Blade post(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.POST); + return this; } /** @@ -280,8 +288,9 @@ public RouterExecutor post(String... paths){ * @param path * @param routeHandler */ - public void delete(String path, RouteHandler router){ + public Blade delete(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.DELETE); + return this; } /** @@ -299,8 +308,9 @@ public RouterExecutor delete(String... paths){ * put请求 * @param paths */ - public void put(String path, RouteHandler router){ + public Blade put(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PUT); + return this; } /** @@ -319,8 +329,9 @@ public RouterExecutor put(String... paths){ * @param path * @param routeHandler */ - public void patch(String path, RouteHandler router){ + public Blade patch(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PATCH); + return this; } /** @@ -339,8 +350,9 @@ public RouterExecutor patch(String... paths){ * @param path * @param routeHandler */ - public void head(String path, RouteHandler router){ + public Blade head(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.HEAD); + return this; } /** @@ -359,8 +371,9 @@ public RouterExecutor head(String... paths){ * @param path * @param routeHandler */ - public void trace(String path, RouteHandler router){ + public Blade trace(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.TRACE); + return this; } /** @@ -379,8 +392,9 @@ public RouterExecutor trace(String... paths){ * @param path * @param routeHandler */ - public void options(String path, RouteHandler router){ + public Blade options(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.OPTIONS); + return this; } /** @@ -399,8 +413,9 @@ public RouterExecutor options(String... paths){ * @param path * @param routeHandler */ - public void connect(String path, RouteHandler router){ + public Blade connect(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.CONNECT); + return this; } /** @@ -419,8 +434,9 @@ public RouterExecutor connect(String... paths){ * @param path * @param routeHandler */ - public void all(String path, RouteHandler router){ + public Blade all(String path, RouteHandler router){ RouteMatcherBuilder.buildHandler(path, router, HttpMethod.ALL); + return this; } /** @@ -439,8 +455,9 @@ public RouterExecutor all(String... paths){ * @param path * @param routeHandler */ - public void before(String path, RouteHandler routeHandler){ + public Blade before(String path, RouteHandler routeHandler){ RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); + return this; } /** @@ -459,8 +476,9 @@ public RouterExecutor before(String... paths){ * @param path * @param routeHandler */ - public void after(String path, RouteHandler routeHandler){ + public Blade after(String path, RouteHandler routeHandler){ RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); + return this; } /** @@ -586,21 +604,28 @@ public Blade listen(int port){ return this; } - public void start() throws Exception { - + public void start(String contextPath) throws Exception { + Server server = new Server(DEFAULT_PORT); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); + context.setContextPath(contextPath); context.setResourceBase(System.getProperty("java.io.tmpdir")); context.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); server.setHandler(context); server.start(); + + LOGGER.info("Blade Server Listen on http://127.0.0.1:" + DEFAULT_PORT); + server.join(); } + public void start() throws Exception { + this.start("/"); + } + public Config config(){ return config(); } @@ -710,5 +735,4 @@ public T plugin(Class pluginClazz){ } return (T) object; } - } diff --git a/blade-core/src/main/java/com/blade/route/Router.java b/blade-core/src/main/java/com/blade/route/Router.java deleted file mode 100644 index 31ef2619d..000000000 --- a/blade-core/src/main/java/com/blade/route/Router.java +++ /dev/null @@ -1,274 +0,0 @@ -package com.blade.route; - -import com.blade.IocApplication; - -public class Router { - - public void load(Class route){ - IocApplication.addRouteClass(route); - } - - /** - * 注册一个函数式的路由
- *

- * 方法上指定请求类型,如:post:signin - *

- * @param path 路由url - * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 - */ - public void register(String path, Class clazz, String methodName){ - RouteMatcherBuilder.buildFunctional(path, clazz, methodName, null); - } - - /** - * 注册一个函数式的路由 - * @param path 路由url - * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 - * @param httpMethod 请求类型,GET/POST - */ - public static synchronized void register(String path, Class clazz, String methodName, HttpMethod httpMethod){ - RouteMatcherBuilder.buildFunctional(path, clazz, methodName, httpMethod); - } - - /** - * get请求 - * @param path - * @param routeHandler - */ - public void get(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.GET); - } - - /** - * get请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor get(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.GET); - } - return null; - } - - /** - * post请求 - * @param path - * @param routeHandler - */ - public static synchronized void post(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.POST); - } - - /** - * post请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor post(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.POST); - } - return null; - } - - /** - * delete请求 - * @param path - * @param routeHandler - */ - public static synchronized void delete(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.DELETE); - } - - /** - * delete请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor delete(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.DELETE); - } - return null; - } - - /** - * put请求 - * @param paths - */ - public static synchronized void put(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PUT); - } - - /** - * put请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor put(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.PUT); - } - return null; - } - - /** - * patch请求 - * @param path - * @param routeHandler - */ - public static synchronized void patch(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PATCH); - } - - /** - * patch请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor patch(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.PATCH); - } - return null; - } - - /** - * head请求 - * @param path - * @param routeHandler - */ - public static synchronized void head(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.HEAD); - } - - /** - * head请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor head(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.HEAD); - } - return null; - } - - /** - * trace请求 - * @param path - * @param routeHandler - */ - public static synchronized void trace(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.TRACE); - } - - /** - * trace请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor trace(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.TRACE); - } - return null; - } - - /** - * options请求 - * @param path - * @param routeHandler - */ - public static synchronized void options(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.OPTIONS); - } - - /** - * options请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor options(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.OPTIONS); - } - return null; - } - - /** - * connect请求 - * @param path - * @param routeHandler - */ - public static synchronized void connect(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.CONNECT); - } - - /** - * connect请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor connect(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.CONNECT); - } - return null; - } - - /** - * 任意请求 - * @param path - * @param routeHandler - */ - public static synchronized void all(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.ALL); - } - - /** - * all请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor all(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.ALL); - } - return null; - } - - /** - * 拦截器before请求 - * @param path - * @param routeHandler - */ - public static synchronized void before(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); - } - - /** - * before请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor before(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.BEFORE); - } - return null; - } - - /** - * 拦截器after请求 - * @param path - * @param routeHandler - */ - public static synchronized void after(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); - } - - /** - * after请求,多个路由 - * @param paths - */ - public static synchronized RouterExecutor after(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.AFTER); - } - return null; - } - -} diff --git a/blade-core/src/main/java/com/blade/route/RouterChain.java b/blade-core/src/main/java/com/blade/route/RouterChain.java deleted file mode 100644 index ac22e4899..000000000 --- a/blade-core/src/main/java/com/blade/route/RouterChain.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.blade.route; - -public interface RouterChain { - - void next() throws Exception; - -} diff --git a/blade-core/src/test/java/com/blade/App.java b/blade-core/src/test/java/com/blade/App.java index d1167ddf9..41cb21eba 100644 --- a/blade-core/src/test/java/com/blade/App.java +++ b/blade-core/src/test/java/com/blade/App.java @@ -19,6 +19,8 @@ public Object handler(Request request, Response response) { } }); + blade.addRoute("/hello", Index.class, "hello"); + blade.app(App.class).listen(9001).start(); } From fb9b7630e2bd4a3d08a009479b734ce4a19d61d6 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 18:23:00 +0800 Subject: [PATCH 161/545] rname --- blade-core/pom.xml | 6 +++--- blade-core/src/main/java/com/blade/Blade.java | 14 +++++++++++--- .../blade/{CoreFilter.java => BladeFilter.java} | 4 ++-- .../src/main/java/com/blade/FilterHandler.java | 2 +- blade-core/src/test/java/com/blade/App.java | 1 + 5 files changed, 18 insertions(+), 9 deletions(-) rename blade-core/src/main/java/com/blade/{CoreFilter.java => BladeFilter.java} (93%) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 1b59f0aa3..5e840053d 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -31,12 +31,12 @@ runtime
- +
org.eclipse.jetty jetty-webapp diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index f634650ca..9279754a1 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -23,7 +23,7 @@ import javax.servlet.DispatcherType; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.webapp.WebAppContext; import com.blade.ioc.Container; import com.blade.ioc.impl.DefaultContainer; @@ -608,11 +608,19 @@ public void start(String contextPath) throws Exception { Server server = new Server(DEFAULT_PORT); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + /*ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath(contextPath); context.setResourceBase(System.getProperty("java.io.tmpdir")); context.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); - server.setHandler(context); + server.setHandler(context);*/ + + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setContextPath(contextPath); + webAppContext.setDescriptor("src/main/webapp/WEB-INF/web.xml"); + webAppContext.setResourceBase("src/main/webapp/"); + webAppContext.setParentLoaderPriority(true); + webAppContext.addFilter(BladeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + server.setHandler(webAppContext); server.start(); diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/BladeFilter.java similarity index 93% rename from blade-core/src/main/java/com/blade/CoreFilter.java rename to blade-core/src/main/java/com/blade/BladeFilter.java index 0ce5a0c03..eaaafb2ed 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/BladeFilter.java @@ -39,9 +39,9 @@ * @author biezhi * @since 1.0 */ -public class CoreFilter implements Filter { +public class BladeFilter implements Filter { - private static final Logger LOGGER = Logger.getLogger(CoreFilter.class); + private static final Logger LOGGER = Logger.getLogger(BladeFilter.class); /** * blade全局初始化类 diff --git a/blade-core/src/main/java/com/blade/FilterHandler.java b/blade-core/src/main/java/com/blade/FilterHandler.java index 80c9b4a9f..d19fa080f 100644 --- a/blade-core/src/main/java/com/blade/FilterHandler.java +++ b/blade-core/src/main/java/com/blade/FilterHandler.java @@ -200,7 +200,7 @@ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper reques } // 初始化context - BladeWebContext.setContext(CoreFilter.servletContext, httpRequest, responseWrapper.servletResponse(), requestWrapper, responseWrapper); + BladeWebContext.setContext(BladeFilter.servletContext, httpRequest, responseWrapper.servletResponse(), requestWrapper, responseWrapper); if(null != router){ diff --git a/blade-core/src/test/java/com/blade/App.java b/blade-core/src/test/java/com/blade/App.java index 41cb21eba..4ef16e5da 100644 --- a/blade-core/src/test/java/com/blade/App.java +++ b/blade-core/src/test/java/com/blade/App.java @@ -10,6 +10,7 @@ public class App extends Bootstrap { public void init() {} public static void main(String[] args) throws Exception { + Blade blade = Blade.me(); blade.get("/").run(new RouteHandler() { @Override From 0a3195e0ac7d68865526bef3b9507cee24982a14 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 10 Oct 2015 18:33:15 +0800 Subject: [PATCH 162/545] rname --- blade-core/src/main/java/com/blade/Blade.java | 2 +- .../main/java/com/blade/{BladeFilter.java => CoreFilter.java} | 4 ++-- blade-core/src/main/java/com/blade/FilterHandler.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename blade-core/src/main/java/com/blade/{BladeFilter.java => CoreFilter.java} (93%) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 9279754a1..6273aee50 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -619,7 +619,7 @@ public void start(String contextPath) throws Exception { webAppContext.setDescriptor("src/main/webapp/WEB-INF/web.xml"); webAppContext.setResourceBase("src/main/webapp/"); webAppContext.setParentLoaderPriority(true); - webAppContext.addFilter(BladeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + webAppContext.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); server.setHandler(webAppContext); server.start(); diff --git a/blade-core/src/main/java/com/blade/BladeFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java similarity index 93% rename from blade-core/src/main/java/com/blade/BladeFilter.java rename to blade-core/src/main/java/com/blade/CoreFilter.java index eaaafb2ed..0ce5a0c03 100644 --- a/blade-core/src/main/java/com/blade/BladeFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -39,9 +39,9 @@ * @author biezhi * @since 1.0 */ -public class BladeFilter implements Filter { +public class CoreFilter implements Filter { - private static final Logger LOGGER = Logger.getLogger(BladeFilter.class); + private static final Logger LOGGER = Logger.getLogger(CoreFilter.class); /** * blade全局初始化类 diff --git a/blade-core/src/main/java/com/blade/FilterHandler.java b/blade-core/src/main/java/com/blade/FilterHandler.java index d19fa080f..80c9b4a9f 100644 --- a/blade-core/src/main/java/com/blade/FilterHandler.java +++ b/blade-core/src/main/java/com/blade/FilterHandler.java @@ -200,7 +200,7 @@ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper reques } // 初始化context - BladeWebContext.setContext(BladeFilter.servletContext, httpRequest, responseWrapper.servletResponse(), requestWrapper, responseWrapper); + BladeWebContext.setContext(CoreFilter.servletContext, httpRequest, responseWrapper.servletResponse(), requestWrapper, responseWrapper); if(null != router){ From 2883e92bd333e4c64d7474fdc55af111e88b9d7b Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 12 Oct 2015 10:26:51 +0800 Subject: [PATCH 163/545] update pom --- blade-beetl/pom.xml | 2 +- .../main/java/blade/render/BeetlRender.java | 23 ++++++++------- blade-core/pom.xml | 1 - blade-jetbrick/pom.xml | 4 +-- .../java/blade/render/JetbrickRender.java | 28 ++++++++++--------- blade-velocity/pom.xml | 2 +- .../java/blade/render/VelocityRender.java | 22 ++++++++------- 7 files changed, 44 insertions(+), 38 deletions(-) diff --git a/blade-beetl/pom.xml b/blade-beetl/pom.xml index 757ec55b5..ae9c521cd 100644 --- a/blade-beetl/pom.xml +++ b/blade-beetl/pom.xml @@ -11,7 +11,7 @@ blade-beetl jar - 1.2.3 + 1.2.4 blade-beetl https://github.com/biezhi/blade/tree/master/blade-beetl diff --git a/blade-beetl/src/main/java/blade/render/BeetlRender.java b/blade-beetl/src/main/java/blade/render/BeetlRender.java index 23def105e..3a30f91fb 100644 --- a/blade-beetl/src/main/java/blade/render/BeetlRender.java +++ b/blade-beetl/src/main/java/blade/render/BeetlRender.java @@ -10,13 +10,15 @@ import org.beetl.core.exception.BeetlException; import org.beetl.core.resource.WebAppResourceLoader; -import blade.Blade; -import blade.BladeWebContext; +import com.blade.BladeWebContext; +import com.blade.render.ModelAndView; +import com.blade.render.Render; +import com.blade.servlet.Request; +import com.blade.servlet.Response; +import com.blade.servlet.Session; + import blade.exception.BladeException; import blade.kit.log.Logger; -import blade.servlet.Request; -import blade.servlet.Response; -import blade.servlet.Session; /** * Beetl渲染引擎 @@ -34,7 +36,7 @@ public class BeetlRender extends Render { */ public BeetlRender() { try { - String root = Blade.webRoot() + Blade.viewPrefix(); + String root = blade.webRoot() + blade.viewPrefix(); WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); resourceLoader.setAutoCheck(true); resourceLoader.setRoot(root); @@ -47,7 +49,7 @@ public BeetlRender() { public BeetlRender(Configuration configuration) { try { - String root = Blade.webRoot() + Blade.viewPrefix(); + String root = blade.webRoot() + blade.viewPrefix(); WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); resourceLoader.setAutoCheck(true); resourceLoader.setRoot(root); @@ -155,11 +157,12 @@ public Object render(ModelAndView modelAndView) { * @param view 视图名称 * @return 返回取出多余"/"的全路径 */ - String disposeView(String view){ + @Override + protected String disposeView(String view){ if(null != view){ view = view.replaceAll("[/]+", "/"); - if(!view.endsWith(Blade.viewSuffix())){ - view = view + Blade.viewSuffix(); + if(!view.endsWith(blade.viewSuffix())){ + view = view + blade.viewSuffix(); } } return view; diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 5e840053d..be36cb88b 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -28,7 +28,6 @@ javax.servlet javax.servlet-api - runtime diff --git a/blade-jetbrick/pom.xml b/blade-jetbrick/pom.xml index f8b01ae18..13baa2111 100644 --- a/blade-jetbrick/pom.xml +++ b/blade-jetbrick/pom.xml @@ -11,7 +11,7 @@ blade-jetbrick jar - 1.2.3 + 1.2.5 blade-jetbrick https://github.com/biezhi/blade/tree/master/blade-jetbrick @@ -29,7 +29,7 @@ com.github.subchen jetbrick-template - 2.0.11 + 2.0.12
diff --git a/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java b/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java index fea8ce88e..020b5bce6 100644 --- a/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java +++ b/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java @@ -6,16 +6,18 @@ import java.util.Properties; import java.util.Set; +import com.blade.BladeWebContext; +import com.blade.render.ModelAndView; +import com.blade.render.Render; +import com.blade.servlet.Request; +import com.blade.servlet.Response; +import com.blade.servlet.Session; + +import blade.exception.BladeException; +import blade.kit.log.Logger; import jetbrick.io.resource.ResourceNotFoundException; import jetbrick.template.JetEngine; import jetbrick.template.JetTemplate; -import blade.Blade; -import blade.BladeWebContext; -import blade.exception.BladeException; -import blade.kit.log.Logger; -import blade.servlet.Request; -import blade.servlet.Response; -import blade.servlet.Session; /** * Velocity渲染引擎 @@ -35,8 +37,8 @@ public class JetbrickRender extends Render { */ public JetbrickRender() { config = new Properties(); - config.put("jetx.input.encoding", Blade.encoding()); - config.put("jetx.output.encoding", Blade.encoding()); + config.put("jetx.input.encoding", blade.encoding()); + config.put("jetx.output.encoding", blade.encoding()); config.put("jetx.template.suffix", ".html"); config.put("jetx.template.loaders", "jetbrick.template.loader.FileSystemResourceLoader"); @@ -108,9 +110,9 @@ public Object render(String view) { Request request = BladeWebContext.request(); Session session = BladeWebContext.session(); - view = Blade.webRoot() + disposeView(view); + String realView = blade.webRoot() + disposeView(view); - JetTemplate template = jetEngine.getTemplate(view); + JetTemplate template = jetEngine.getTemplate(realView); Map context = new HashMap(); @@ -130,7 +132,7 @@ public Object render(String view) { template.render(context, response.outputStream()); } catch (ResourceNotFoundException e) { - render404(response, view); + render404(response, disposeView(view)); } catch (IOException e) { LOGGER.error(e); } @@ -154,7 +156,7 @@ public Object render(ModelAndView modelAndView) { throw new BladeException("modelAndView is null"); } - String view = Blade.webRoot() + disposeView(modelAndView.getView()); + String view = blade.webRoot() + disposeView(modelAndView.getView()); JetTemplate template = jetEngine.getTemplate(view); diff --git a/blade-velocity/pom.xml b/blade-velocity/pom.xml index 5049587fc..7408e2d4d 100644 --- a/blade-velocity/pom.xml +++ b/blade-velocity/pom.xml @@ -11,7 +11,7 @@ blade-velocity jar - 1.2.2 + 1.2.3 blade-velocity https://github.com/biezhi/blade/tree/master/blade-velocity diff --git a/blade-velocity/src/main/java/blade/render/VelocityRender.java b/blade-velocity/src/main/java/blade/render/VelocityRender.java index 9230522cc..27ed48e07 100644 --- a/blade-velocity/src/main/java/blade/render/VelocityRender.java +++ b/blade-velocity/src/main/java/blade/render/VelocityRender.java @@ -16,13 +16,15 @@ import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.exception.ResourceNotFoundException; -import blade.Blade; -import blade.BladeWebContext; +import com.blade.BladeWebContext; +import com.blade.render.ModelAndView; +import com.blade.render.Render; +import com.blade.servlet.Request; +import com.blade.servlet.Response; +import com.blade.servlet.Session; + import blade.exception.BladeException; import blade.kit.log.Logger; -import blade.servlet.Request; -import blade.servlet.Response; -import blade.servlet.Session; /** * Velocity渲染引擎 @@ -41,10 +43,10 @@ public class VelocityRender extends Render { public VelocityRender() { Properties properties = new Properties(); - properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, Blade.webRoot()); - properties.setProperty(Velocity.ENCODING_DEFAULT, Blade.encoding()); - properties.setProperty(Velocity.INPUT_ENCODING, Blade.encoding()); - properties.setProperty(Velocity.OUTPUT_ENCODING, Blade.encoding()); + properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, blade.webRoot()); + properties.setProperty(Velocity.ENCODING_DEFAULT, blade.encoding()); + properties.setProperty(Velocity.INPUT_ENCODING, blade.encoding()); + properties.setProperty(Velocity.OUTPUT_ENCODING, blade.encoding()); velocityEngine = new VelocityEngine(properties); } @@ -63,7 +65,7 @@ public VelocityRender(String propertiesFile) throws IOException { // 默认查询路径 if(!properties.contains(Velocity.FILE_RESOURCE_LOADER_PATH)){ - properties.put(Velocity.FILE_RESOURCE_LOADER_PATH, Blade.webRoot()); + properties.put(Velocity.FILE_RESOURCE_LOADER_PATH, blade.webRoot()); } velocityEngine = new VelocityEngine(properties); } From 1a2b7d3430f5dfc437497b373c2654ca802500e9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 12 Oct 2015 10:27:54 +0800 Subject: [PATCH 164/545] update pom --- blade-sql2o/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index b88daf208..823eaa6ef 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - 1.4.0-alpha + 1.2.9-beta blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o From f3dfaed8e23615435dfb5c532effbfa61afe4cda Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 12 Oct 2015 10:35:37 +0800 Subject: [PATCH 165/545] update last version --- LAST_VERSION.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 1ac1f3a1d..caa7d8ee8 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -32,7 +32,7 @@     com.bladejava     blade-core -    1.3.0-alpha +    1.4.0-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -40,7 +40,7 @@     com.bladejava     blade-sql2o -    1.2.8 +    1.2.9-beta ``` @@ -49,7 +49,7 @@     com.bladejava     blade-jetbrick -    1.2.4 +    1.2.5 ``` @@ -58,7 +58,7 @@     com.bladejava     blade-beetl -    1.2.3 +    1.2.4 ``` @@ -67,7 +67,7 @@     com.bladejava     blade-velocity -    1.2.2 +    1.2.3 ``` @@ -85,6 +85,6 @@     com.bladejava     blade-redis -    1.2.2 +    1.2.3 ``` \ No newline at end of file From a8b68e9594936d587ee5c2a41c98fdb86fb9d0ba Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 12 Oct 2015 11:27:54 +0800 Subject: [PATCH 166/545] add blade server --- blade-core/src/main/java/com/blade/Blade.java | 74 ++++++++----------- .../java/com/blade/server/BladeServer.java | 38 ++++++++++ blade-core/src/test/java/com/blade/Index.java | 13 ++++ 3 files changed, 80 insertions(+), 45 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/server/BladeServer.java create mode 100644 blade-core/src/test/java/com/blade/Index.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 6273aee50..3bdef2c14 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -17,14 +17,8 @@ import java.io.IOException; import java.io.InputStream; -import java.util.EnumSet; import java.util.Map; -import javax.servlet.DispatcherType; - -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.webapp.WebAppContext; - import com.blade.ioc.Container; import com.blade.ioc.impl.DefaultContainer; import com.blade.plugin.Plugin; @@ -35,12 +29,12 @@ import com.blade.route.RouteHandler; import com.blade.route.RouteMatcherBuilder; import com.blade.route.RouterExecutor; +import com.blade.server.BladeServer; import blade.kit.IOKit; import blade.kit.PropertyKit; import blade.kit.ReflectKit; import blade.kit.json.JSONKit; -import blade.kit.log.Logger; /** * Blade Core Class @@ -54,8 +48,6 @@ public class Blade { private static final Blade ME = new Blade(); - private static final Logger LOGGER = Logger.getLogger(Blade.class); - /** * 框架是否已经初始化 */ @@ -166,10 +158,11 @@ private void configuration(Map configMap){ * * @param packages 路由包路径 */ - public void routes(String...packages){ + public Blade routes(String...packages){ if(null != packages && packages.length >0){ config.setRoutePackages(packages); } + return this; } /** @@ -178,10 +171,11 @@ public void routes(String...packages){ * * @param basePackage 默认包路径 */ - public void defaultRoute(String basePackage){ + public Blade defaultRoute(String basePackage){ if(null != basePackage){ config.setBasePackage(basePackage); } + return this; } /** @@ -189,10 +183,11 @@ public void defaultRoute(String basePackage){ * * @param packageName 拦截器所在的包 */ - public void interceptor(String packageName) { + public Blade interceptor(String packageName) { if(null != packageName && packageName.length() >0){ config.setInterceptorPackage(packageName); } + return this; } /** @@ -200,10 +195,11 @@ public void interceptor(String packageName) { * * @param packages 所有需要做注入的包,可传入多个 */ - public void ioc(String...packages){ + public Blade ioc(String...packages){ if(null != packages && packages.length >0){ config.setIocPackages(packages); } + return this; } /** @@ -497,8 +493,9 @@ public RouterExecutor after(String... paths){ * * @param render 渲染引擎对象 */ - public void viewEngin(Render render) { + public Blade viewEngin(Render render) { RenderFactory.init(render); + return this; } /** @@ -506,10 +503,11 @@ public void viewEngin(Render render) { * * @param prefix 视图路径,如:/WEB-INF/views */ - public void viewPrefix(final String prefix) { + public Blade viewPrefix(final String prefix) { if(null != prefix && prefix.startsWith("/")){ config.setViewPrefix(prefix); } + return this; } /** @@ -517,10 +515,11 @@ public void viewPrefix(final String prefix) { * * @param viewExt 视图后缀,如:.html .vm */ - public void viewSuffix(final String suffix) { + public Blade viewSuffix(final String suffix) { if(null != suffix && suffix.startsWith(".")){ config.setViewSuffix(suffix); } + return this; } /** @@ -529,9 +528,10 @@ public void viewSuffix(final String suffix) { * @param viewPath 视图路径,如:/WEB-INF/views * @param viewExt 视图后缀,如:.html .vm */ - public void view(final String viewPath, final String viewExt) { + public Blade view(final String viewPath, final String viewExt) { viewPrefix(viewPath); viewSuffix(viewExt); + return this; } /** @@ -539,8 +539,9 @@ public void view(final String viewPath, final String viewExt) { * * @param folders */ - public void staticFolder(final String ... folders) { + public Blade staticFolder(final String ... folders) { config.setStaticFolders(folders); + return this; } @@ -569,8 +570,9 @@ public Blade app(Class bootstrap){ * * @param view404 404视图页面 */ - public void view404(final String view404){ + public Blade view404(final String view404){ config.setView404(view404); + return this; } /** @@ -578,8 +580,9 @@ public void view404(final String view404){ * * @param view500 500视图页面 */ - public void view500(final String view500){ + public Blade view500(final String view500){ config.setView500(view500); + return this; } /** @@ -587,16 +590,18 @@ public void view500(final String view500){ * * @param webRoot web根目录物理路径 */ - public void webRoot(final String webRoot){ + public Blade webRoot(final String webRoot){ config.setWebRoot(webRoot); + return this; } /** * 设置系统是否以debug方式运行 * @param isdebug true:是,默认true;false:否 */ - public void debug(boolean isdebug){ + public Blade debug(boolean isdebug){ config.setDebug(isdebug); + return this; } public Blade listen(int port){ @@ -605,29 +610,8 @@ public Blade listen(int port){ } public void start(String contextPath) throws Exception { - - Server server = new Server(DEFAULT_PORT); - - /*ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath(contextPath); - context.setResourceBase(System.getProperty("java.io.tmpdir")); - context.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); - server.setHandler(context);*/ - - WebAppContext webAppContext = new WebAppContext(); - webAppContext.setContextPath(contextPath); - webAppContext.setDescriptor("src/main/webapp/WEB-INF/web.xml"); - webAppContext.setResourceBase("src/main/webapp/"); - webAppContext.setParentLoaderPriority(true); - webAppContext.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); - server.setHandler(webAppContext); - - server.start(); - - LOGGER.info("Blade Server Listen on http://127.0.0.1:" + DEFAULT_PORT); - - server.join(); - + BladeServer bladeServer = new BladeServer(DEFAULT_PORT); + bladeServer.run(contextPath); } public void start() throws Exception { diff --git a/blade-core/src/main/java/com/blade/server/BladeServer.java b/blade-core/src/main/java/com/blade/server/BladeServer.java new file mode 100644 index 000000000..62ea925cd --- /dev/null +++ b/blade-core/src/main/java/com/blade/server/BladeServer.java @@ -0,0 +1,38 @@ +package com.blade.server; + +import java.util.EnumSet; + +import javax.servlet.DispatcherType; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; + +import com.blade.CoreFilter; + +import blade.kit.log.Logger; + +public class BladeServer { + + private static final Logger LOGGER = Logger.getLogger(BladeServer.class); + + private int port = 9000; + + public BladeServer(int port) { + this.port = port; + } + + public void run(String contextPath) throws Exception{ + + Server server = new Server(port); + + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath(contextPath); + context.setResourceBase(System.getProperty("java.io.tmpdir")); + context.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + server.setHandler(context); + + server.start(); + LOGGER.info("Blade Server Listen on 0.0.0.0:" + port); + server.join(); + } +} diff --git a/blade-core/src/test/java/com/blade/Index.java b/blade-core/src/test/java/com/blade/Index.java new file mode 100644 index 000000000..e19b31423 --- /dev/null +++ b/blade-core/src/test/java/com/blade/Index.java @@ -0,0 +1,13 @@ +package com.blade; + +import com.blade.servlet.Request; +import com.blade.servlet.Response; + +public class Index { + + public void hello(Request request, Response response){ + System.out.println("请求hello"); + response.html("hi~"); + } + +} From 72cd4e8a8c1e3687bc1958400ceb5e4beaee35f7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 20 Oct 2015 13:25:19 +0800 Subject: [PATCH 167/545] update readme --- README.md | 4 ++-- README_CN.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 247591ae9..bf562a472 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![](https://i.imgur.com/8I289mA.png)](http://bladejava.com) +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) @@ -27,7 +27,7 @@ If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! * Elegance. `blade` Support the REST style routing interface, provide DSL grammar to write, no invasive interceptors. ## Getting started -To get started, first [include the Blade library](http://bladejava.com) and then create a class with a main method like this: +To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) and then create a class with a main method like this: ```java public class App extends Bootstrap { diff --git a/README_CN.md b/README_CN.md index 62581a850..aa037a363 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,5 +1,5 @@ -[![](https://i.imgur.com/8I289mA.png)](http://bladejava.com) +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) [![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) @@ -27,7 +27,7 @@ * 优雅的:`blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 ## 快速入门 -开始之前,首先 [引入Blade的库文件](http://bladejava.com) ,然后创建一个类继承自 `Bootstrap` ,编写 `Main` 函数: +开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) ,然后创建一个类继承自 `Bootstrap` ,编写 `Main` 函数: ```java public class App extends Bootstrap { From 716731ae709dab18b5c61040cdb20e3a99506c07 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 20 Oct 2015 15:25:31 +0800 Subject: [PATCH 168/545] rname method --- .../src/main/java/com/blade/Config.java | 41 +++++++++++++++++++ .../main/java/com/blade/servlet/Request.java | 14 +++---- .../com/blade/wrapper/RequestWrapper.java | 18 ++++++-- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Config.java b/blade-core/src/main/java/com/blade/Config.java index 0c25e38af..c07920907 100644 --- a/blade-core/src/main/java/com/blade/Config.java +++ b/blade-core/src/main/java/com/blade/Config.java @@ -20,6 +20,7 @@ import java.util.Map; import blade.kit.CollectionKit; +import blade.kit.PatternKit; /** * Blade配置类 @@ -71,6 +72,46 @@ public void setConfigMap(Map configMap) { public String get(String key){ return configMap.get(key); } + + public Integer getToInt(String key){ + String val = get(key); + if(null != val && PatternKit.isNumber(val)){ + return Integer.valueOf(val); + } + return null; + } + + public Long getToLong(String key){ + String val = get(key); + if(null != val && PatternKit.isNumber(val)){ + return Long.valueOf(val); + } + return null; + } + + public Boolean getToBoolean(String key){ + String val = get(key); + if(null != val){ + return Boolean.valueOf(val); + } + return null; + } + + public Double getToDouble(String key){ + String val = get(key); + if(null != val){ + return Double.valueOf(val); + } + return null; + } + + public Float getToFloat(String key){ + String val = get(key); + if(null != val){ + return Float.valueOf(val); + } + return null; + } public String[] getRoutePackages() { String[] routeArr = new String[routePackages.size()]; diff --git a/blade-core/src/main/java/com/blade/servlet/Request.java b/blade-core/src/main/java/com/blade/servlet/Request.java index 4bb7e591e..f86b0bfa8 100644 --- a/blade-core/src/main/java/com/blade/servlet/Request.java +++ b/blade-core/src/main/java/com/blade/servlet/Request.java @@ -98,7 +98,7 @@ public void initRequest(RouteMatcher match) { /** * @return 返回URL路径上的所有参数 */ - public Map pathParams() { + public Map params() { return Collections.unmodifiableMap(this.pathParams); } @@ -107,7 +107,7 @@ public Map pathParams() { * @param param 参数名称 * @return 返回URL上对应的String参数值 */ - public String pathParam(String param) { + public String param(String param) { if (param == null) { return null; } @@ -124,8 +124,8 @@ public String pathParam(String param) { * @param param 参数名称 * @return 返回URL上对应的Integer参数值 */ - public Integer pathParamToInt(String param) { - String value = pathParam(param); + public Integer paramToInt(String param) { + String value = param(param); if(null != value){ return Integer.valueOf(value); } @@ -133,12 +133,12 @@ public Integer pathParamToInt(String param) { } /** - * 返回long类型的path param + * 返回long类型的参数值 * @param param 参数名称 * @return 返回URL上对应的Long参数值 */ - public Long pathParamToLong(String param) { - String value = pathParam(param); + public Long paramToLong(String param) { + String value = param(param); if(null != value){ return Long.valueOf(value); } diff --git a/blade-core/src/main/java/com/blade/wrapper/RequestWrapper.java b/blade-core/src/main/java/com/blade/wrapper/RequestWrapper.java index 5ed43fd18..326d6fa26 100644 --- a/blade-core/src/main/java/com/blade/wrapper/RequestWrapper.java +++ b/blade-core/src/main/java/com/blade/wrapper/RequestWrapper.java @@ -107,13 +107,23 @@ public int hashCode() { } @Override - public Map pathParams() { - return delegate.pathParams(); + public Map params() { + return delegate.params(); } @Override - public String pathParam(String param) { - return delegate.pathParam(param); + public String param(String param) { + return delegate.param(param); + } + + @Override + public Integer paramToInt(String param) { + return delegate.paramToInt(param); + } + + @Override + public Long paramToLong(String param) { + return delegate.paramToLong(param); } @Override From 773e8f6767edc90338a9055a9598c1e3b7d90287 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 20 Oct 2015 17:24:49 +0800 Subject: [PATCH 169/545] optimize json --- .../main/java/com/blade/FilterHandler.java | 12 +- blade-kit/pom.xml | 2 +- blade-kit/src/main/java/blade/kit/Assert.java | 7 + blade-kit/src/main/java/blade/kit/IOKit.java | 12 + .../src/main/java/blade/kit/ReflectKit.java | 19 + .../main/java/blade/kit/json/JSONArray.java | 1640 +++++-------- .../java/blade/kit/json/JSONException.java | 85 +- .../src/main/java/blade/kit/json/JSONKit.java | 98 +- .../main/java/blade/kit/json/JSONObject.java | 2128 +++-------------- .../java/blade/kit/log/SysLoggerAdaptor.java | 2 +- 10 files changed, 1055 insertions(+), 2950 deletions(-) diff --git a/blade-core/src/main/java/com/blade/FilterHandler.java b/blade-core/src/main/java/com/blade/FilterHandler.java index 80c9b4a9f..04de05c7c 100644 --- a/blade-core/src/main/java/com/blade/FilterHandler.java +++ b/blade-core/src/main/java/com/blade/FilterHandler.java @@ -38,6 +38,7 @@ import blade.exception.BladeException; import blade.kit.PathKit; import blade.kit.ReflectKit; +import blade.kit.base.ThrowableKit; import blade.kit.log.Logger; /** @@ -159,7 +160,11 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse response.render404(uri); return true; } catch (BladeException bex) { - bex.printStackTrace(); + + String error = ThrowableKit.getStackTraceAsString(bex); + LOGGER.error(error); + ThrowableKit.propagate(bex); + httpResponse.setStatus(500); // 写入内容到浏览器 if (!httpResponse.isCommitted()) { @@ -167,7 +172,10 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse return true; } } catch (Exception e) { - e.printStackTrace(); + String error = ThrowableKit.getStackTraceAsString(e); + LOGGER.error(error); + ThrowableKit.propagate(e); + httpResponse.setStatus(500); // 写入内容到浏览器 if (!httpResponse.isCommitted()) { diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index 2dee888a6..7c2e6bfe7 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - 1.2.6 + 1.2.7-alpha blade-kit https://github.com/biezhi/blade/tree/master/blade-kit diff --git a/blade-kit/src/main/java/blade/kit/Assert.java b/blade-kit/src/main/java/blade/kit/Assert.java index 271422882..e87b71cf4 100644 --- a/blade-kit/src/main/java/blade/kit/Assert.java +++ b/blade-kit/src/main/java/blade/kit/Assert.java @@ -54,6 +54,13 @@ public static void notNull(Object object, String message) { public static void notNull(Object object) { notNull(object, "[Assertion failed] - this argument is required; it must not be null"); } + + public static T checkNotNull(T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } public static void hasLength(String text, String message) { if (StringKit.isEmpty(text)) { diff --git a/blade-kit/src/main/java/blade/kit/IOKit.java b/blade-kit/src/main/java/blade/kit/IOKit.java index d4725ad78..e2476f245 100644 --- a/blade-kit/src/main/java/blade/kit/IOKit.java +++ b/blade-kit/src/main/java/blade/kit/IOKit.java @@ -48,6 +48,8 @@ public final class IOKit { public static final String LINE_SEPARATOR; + private static final int EOF = -1; + static { // avoid security issues StringWriter buf = new StringWriter(4); // NOSONAR @@ -264,4 +266,14 @@ public static void closeQuietly(Closeable closeable) { } } } + + public static String toString(Reader input) throws IOException { + StringBuilder output = new StringBuilder(); + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + int n; + while (EOF != (n = input.read(buffer))) { + output.append(buffer, 0, n); + } + return output.toString(); + } } diff --git a/blade-kit/src/main/java/blade/kit/ReflectKit.java b/blade-kit/src/main/java/blade/kit/ReflectKit.java index be9c117c0..bab56a071 100644 --- a/blade-kit/src/main/java/blade/kit/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/ReflectKit.java @@ -408,6 +408,25 @@ static boolean isSynthetic(Member m) { } return false; } + + /** + * Check whether the {@link Class} identified by the supplied name is present. + * + * @param className the name of the class to check + * @return true if class is present, false otherwise + */ + public static boolean isPresent(String className) { + try { + // what's wrong with old plain Class.forName + // this code supposed to work everywhere including containers + Class.forName(className); + // getClassLoader().loadClass(className); + return true; + } + catch (Throwable ex) { + return false; + } + } public static boolean isPublic(Member m) { return m != null && Modifier.isPublic(m.getModifiers()); diff --git a/blade-kit/src/main/java/blade/kit/json/JSONArray.java b/blade-kit/src/main/java/blade/kit/json/JSONArray.java index c2fa9e2ac..fcb612584 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONArray.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONArray.java @@ -1,1061 +1,579 @@ -package blade.kit.json; - -/* - Copyright (c) 2002 JSON.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - The Software shall be used for Good, not Evil. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Array; -import java.math.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; - -/** - * A JSONArray is an ordered sequence of values. Its external text form is a - * string wrapped in square brackets with commas separating the values. The - * internal form is an object having get and opt - * methods for accessing the values by index, and put methods for - * adding or replacing values. The values can be any of these types: - * Boolean, JSONArray, JSONObject, - * Number, String, or the - * JSONObject.NULL object. - *

- * The constructor can convert a JSON text into a Java object. The - * toString method converts to JSON text. - *

- * A get method returns a value if one can be found, and throws an - * exception if one cannot be found. An opt method returns a - * default value instead of throwing an exception, and so is useful for - * obtaining optional values. - *

- * The generic get() and opt() methods return an - * object which you can cast or query for type. There are also typed - * get and opt methods that do type checking and type - * coercion for you. - *

- * The texts produced by the toString methods strictly conform to - * JSON syntax rules. The constructors are more forgiving in the texts they will - * accept: - *

    - *
  • An extra , (comma) may appear just - * before the closing bracket.
  • - *
  • The null value will be inserted when there is , - *  (comma) elision.
  • - *
  • Strings may be quoted with ' (single - * quote).
  • - *
  • Strings do not need to be quoted at all if they do not begin with a quote - * or single quote, and if they do not contain leading or trailing spaces, and - * if they do not contain any of these characters: - * { } [ ] / \ : , # and if they do not look like numbers and - * if they are not the reserved words true, false, or - * null.
  • - *
- * - * @author JSON.org - * @version 2015-07-06 - */ -public class JSONArray implements Iterable { - - /** - * The arrayList where the JSONArray's properties are kept. - */ - private final ArrayList myArrayList; - - /** - * Construct an empty JSONArray. - */ - public JSONArray() { - this.myArrayList = new ArrayList(); - } - - /** - * Construct a JSONArray from a JSONTokener. - * - * @param x - * A JSONTokener - * @throws JSONException - * If there is a syntax error. - */ - public JSONArray(JSONTokener x) throws JSONException { - this(); - if (x.nextClean() != '[') { - throw x.syntaxError("A JSONArray text must start with '['"); - } - if (x.nextClean() != ']') { - x.back(); - for (;;) { - if (x.nextClean() == ',') { - x.back(); - this.myArrayList.add(JSONObject.NULL); - } else { - x.back(); - this.myArrayList.add(x.nextValue()); - } - switch (x.nextClean()) { - case ',': - if (x.nextClean() == ']') { - return; - } - x.back(); - break; - case ']': - return; - default: - throw x.syntaxError("Expected a ',' or ']'"); - } - } - } - } - - /** - * Construct a JSONArray from a source JSON text. - * - * @param source - * A string that begins with [ (left - * bracket) and ends with ] - *  (right bracket). - * @throws JSONException - * If there is a syntax error. - */ - public JSONArray(String source) throws JSONException { - this(new JSONTokener(source)); - } - - /** - * Construct a JSONArray from a Collection. - * - * @param collection - * A Collection. - */ - public JSONArray(Collection collection) { - this.myArrayList = new ArrayList(); - if (collection != null) { - Iterator iter = collection.iterator(); - while (iter.hasNext()) { - this.myArrayList.add(JSONObject.wrap(iter.next())); - } - } - } - - /** - * Construct a JSONArray from an array - * - * @throws JSONException - * If not an array. - */ - public JSONArray(Object array) throws JSONException { - this(); - if (array.getClass().isArray()) { - int length = Array.getLength(array); - for (int i = 0; i < length; i += 1) { - this.put(JSONObject.wrap(Array.get(array, i))); - } - } else { - throw new JSONException( - "JSONArray initial value should be a string or collection or array."); - } - } - - @Override - public Iterator iterator() { - return myArrayList.iterator(); - } - - /** - * Get the object value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return An object value. - * @throws JSONException - * If there is no value for the index. - */ - public Object get(int index) throws JSONException { - Object object = this.opt(index); - if (object == null) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - return object; - } - - /** - * Get the boolean value associated with an index. The string values "true" - * and "false" are converted to boolean. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The truth. - * @throws JSONException - * If there is no value for the index or if the value is not - * convertible to boolean. - */ - public boolean getBoolean(int index) throws JSONException { - Object object = this.get(index); - if (object.equals(Boolean.FALSE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONArray[" + index + "] is not a boolean."); - } - - /** - * Get the double value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a number. - */ - public double getDouble(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).doubleValue() - : Double.parseDouble((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); - } - } - - /** - * Get the BigDecimal value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a BigDecimal. - */ - public BigDecimal getBigDecimal (int index) throws JSONException { - Object object = this.get(index); - try { - return new BigDecimal(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] could not convert to BigDecimal."); - } - } - - /** - * Get the BigInteger value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a BigInteger. - */ - public BigInteger getBigInteger (int index) throws JSONException { - Object object = this.get(index); - try { - return new BigInteger(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] could not convert to BigInteger."); - } - } - - /** - * Get the int value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value is not a number. - */ - public int getInt(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).intValue() - : Integer.parseInt((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); - } - } - - /** - * Get the JSONArray associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return A JSONArray value. - * @throws JSONException - * If there is no value for the index. or if the value is not a - * JSONArray - */ - public JSONArray getJSONArray(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONArray) { - return (JSONArray) object; - } - throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); - } - - /** - * Get the JSONObject associated with an index. - * - * @param index - * subscript - * @return A JSONObject value. - * @throws JSONException - * If there is no value for the index or if the value is not a - * JSONObject - */ - public JSONObject getJSONObject(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONObject) { - return (JSONObject) object; - } - throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); - } - - /** - * Get the long value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a number. - */ - public long getLong(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).longValue() - : Long.parseLong((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); - } - } - - /** - * Get the string associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return A string value. - * @throws JSONException - * If there is no string value for the index. - */ - public String getString(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof String) { - return (String) object; - } - throw new JSONException("JSONArray[" + index + "] not a string."); - } - - /** - * Determine if the value is null. - * - * @param index - * The index must be between 0 and length() - 1. - * @return true if the value at the index is null, or if there is no value. - */ - public boolean isNull(int index) { - return JSONObject.NULL.equals(this.opt(index)); - } - - /** - * Make a string from the contents of this JSONArray. The - * separator string is inserted between each element. Warning: - * This method assumes that the data structure is acyclical. - * - * @param separator - * A string that will be inserted between the elements. - * @return a string. - * @throws JSONException - * If the array contains an invalid number. - */ - public String join(String separator) throws JSONException { - int len = this.length(); - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < len; i += 1) { - if (i > 0) { - sb.append(separator); - } - sb.append(JSONObject.valueToString(this.myArrayList.get(i))); - } - return sb.toString(); - } - - /** - * Get the number of elements in the JSONArray, included nulls. - * - * @return The length (or size). - */ - public int length() { - return this.myArrayList.size(); - } - - /** - * Get the optional object value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return An object value, or null if there is no object at that index. - */ - public Object opt(int index) { - return (index < 0 || index >= this.length()) ? null : this.myArrayList - .get(index); - } - - /** - * Get the optional boolean value associated with an index. It returns false - * if there is no value at that index, or if the value is not Boolean.TRUE - * or the String "true". - * - * @param index - * The index must be between 0 and length() - 1. - * @return The truth. - */ - public boolean optBoolean(int index) { - return this.optBoolean(index, false); - } - - /** - * Get the optional boolean value associated with an index. It returns the - * defaultValue if there is no value at that index or if it is not a Boolean - * or the String "true" or "false" (case insensitive). - * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * A boolean default. - * @return The truth. - */ - public boolean optBoolean(int index, boolean defaultValue) { - try { - return this.getBoolean(index); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get the optional double value associated with an index. NaN is returned - * if there is no value for the index, or if the value is not a number and - * cannot be converted to a number. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - */ - public double optDouble(int index) { - return this.optDouble(index, Double.NaN); - } - - /** - * Get the optional double value associated with an index. The defaultValue - * is returned if there is no value for the index, or if the value is not a - * number and cannot be converted to a number. - * - * @param index - * subscript - * @param defaultValue - * The default value. - * @return The value. - */ - public double optDouble(int index, double defaultValue) { - try { - return this.getDouble(index); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get the optional int value associated with an index. Zero is returned if - * there is no value for the index, or if the value is not a number and - * cannot be converted to a number. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - */ - public int optInt(int index) { - return this.optInt(index, 0); - } - - /** - * Get the optional int value associated with an index. The defaultValue is - * returned if there is no value for the index, or if the value is not a - * number and cannot be converted to a number. - * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. - * @return The value. - */ - public int optInt(int index, int defaultValue) { - try { - return this.getInt(index); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get the optional BigInteger value associated with an index. The - * defaultValue is returned if there is no value for the index, or if the - * value is not a number and cannot be converted to a number. - * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. - * @return The value. - */ - public BigInteger optBigInteger(int index, BigInteger defaultValue) { - try { - return this.getBigInteger(index); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get the optional BigDecimal value associated with an index. The - * defaultValue is returned if there is no value for the index, or if the - * value is not a number and cannot be converted to a number. - * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. - * @return The value. - */ - public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) { - try { - return this.getBigDecimal(index); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get the optional JSONArray associated with an index. - * - * @param index - * subscript - * @return A JSONArray value, or null if the index has no value, or if the - * value is not a JSONArray. - */ - public JSONArray optJSONArray(int index) { - Object o = this.opt(index); - return o instanceof JSONArray ? (JSONArray) o : null; - } - - /** - * Get the optional JSONObject associated with an index. Null is returned if - * the key is not found, or null if the index has no value, or if the value - * is not a JSONObject. - * - * @param index - * The index must be between 0 and length() - 1. - * @return A JSONObject value. - */ - public JSONObject optJSONObject(int index) { - Object o = this.opt(index); - return o instanceof JSONObject ? (JSONObject) o : null; - } - - /** - * Get the optional long value associated with an index. Zero is returned if - * there is no value for the index, or if the value is not a number and - * cannot be converted to a number. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - */ - public long optLong(int index) { - return this.optLong(index, 0); - } - - /** - * Get the optional long value associated with an index. The defaultValue is - * returned if there is no value for the index, or if the value is not a - * number and cannot be converted to a number. - * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. - * @return The value. - */ - public long optLong(int index, long defaultValue) { - try { - return this.getLong(index); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get the optional string value associated with an index. It returns an - * empty string if there is no value at that index. If the value is not a - * string and is not null, then it is coverted to a string. - * - * @param index - * The index must be between 0 and length() - 1. - * @return A String value. - */ - public String optString(int index) { - return this.optString(index, ""); - } - - /** - * Get the optional string associated with an index. The defaultValue is - * returned if the key is not found. - * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. - * @return A String value. - */ - public String optString(int index, String defaultValue) { - Object object = this.opt(index); - return JSONObject.NULL.equals(object) ? defaultValue : object - .toString(); - } - - /** - * Append a boolean value. This increases the array's length by one. - * - * @param value - * A boolean value. - * @return this. - */ - public JSONArray put(boolean value) { - this.put(value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - /** - * Put a value in the JSONArray, where the value will be a JSONArray which - * is produced from a Collection. - * - * @param value - * A Collection value. - * @return this. - */ - public JSONArray put(Collection value) { - this.put(new JSONArray(value)); - return this; - } - - /** - * Append a double value. This increases the array's length by one. - * - * @param value - * A double value. - * @throws JSONException - * if the value is not finite. - * @return this. - */ - public JSONArray put(double value) throws JSONException { - Double d = new Double(value); - JSONObject.testValidity(d); - this.put(d); - return this; - } - - /** - * Append an int value. This increases the array's length by one. - * - * @param value - * An int value. - * @return this. - */ - public JSONArray put(int value) { - this.put(new Integer(value)); - return this; - } - - /** - * Append an long value. This increases the array's length by one. - * - * @param value - * A long value. - * @return this. - */ - public JSONArray put(long value) { - this.put(new Long(value)); - return this; - } - - /** - * Put a value in the JSONArray, where the value will be a JSONObject which - * is produced from a Map. - * - * @param value - * A Map value. - * @return this. - */ - public JSONArray put(Map value) { - this.put(new JSONObject(value)); - return this; - } - - /** - * Append an object value. This increases the array's length by one. - * - * @param value - * An object value. The value should be a Boolean, Double, - * Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. - * @return this. - */ - public JSONArray put(Object value) { - this.myArrayList.add(value); - return this; - } - - /** - * Put or replace a boolean value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * - * @param index - * The subscript. - * @param value - * A boolean value. - * @return this. - * @throws JSONException - * If the index is negative. - */ - public JSONArray put(int index, boolean value) throws JSONException { - this.put(index, value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - /** - * Put a value in the JSONArray, where the value will be a JSONArray which - * is produced from a Collection. - * - * @param index - * The subscript. - * @param value - * A Collection value. - * @return this. - * @throws JSONException - * If the index is negative or if the value is not finite. - */ - public JSONArray put(int index, Collection value) throws JSONException { - this.put(index, new JSONArray(value)); - return this; - } - - /** - * Put or replace a double value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad it - * out. - * - * @param index - * The subscript. - * @param value - * A double value. - * @return this. - * @throws JSONException - * If the index is negative or if the value is not finite. - */ - public JSONArray put(int index, double value) throws JSONException { - this.put(index, new Double(value)); - return this; - } - - /** - * Put or replace an int value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad it - * out. - * - * @param index - * The subscript. - * @param value - * An int value. - * @return this. - * @throws JSONException - * If the index is negative. - */ - public JSONArray put(int index, int value) throws JSONException { - this.put(index, new Integer(value)); - return this; - } - - /** - * Put or replace a long value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad it - * out. - * - * @param index - * The subscript. - * @param value - * A long value. - * @return this. - * @throws JSONException - * If the index is negative. - */ - public JSONArray put(int index, long value) throws JSONException { - this.put(index, new Long(value)); - return this; - } - - /** - * Put a value in the JSONArray, where the value will be a JSONObject that - * is produced from a Map. - * - * @param index - * The subscript. - * @param value - * The Map value. - * @return this. - * @throws JSONException - * If the index is negative or if the the value is an invalid - * number. - */ - public JSONArray put(int index, Map value) throws JSONException { - this.put(index, new JSONObject(value)); - return this; - } - - /** - * Put or replace an object value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * - * @param index - * The subscript. - * @param value - * The value to put into the array. The value should be a - * Boolean, Double, Integer, JSONArray, JSONObject, Long, or - * String, or the JSONObject.NULL object. - * @return this. - * @throws JSONException - * If the index is negative or if the the value is an invalid - * number. - */ - public JSONArray put(int index, Object value) throws JSONException { - JSONObject.testValidity(value); - if (index < 0) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - if (index < this.length()) { - this.myArrayList.set(index, value); - } else { - while (index != this.length()) { - this.put(JSONObject.NULL); - } - this.put(value); - } - return this; - } - - /** - * Remove an index and close the hole. - * - * @param index - * The index of the element to be removed. - * @return The value that was associated with the index, or null if there - * was no value. - */ - public Object remove(int index) { - return index >= 0 && index < this.length() - ? this.myArrayList.remove(index) - : null; - } - - /** - * Determine if two JSONArrays are similar. - * They must contain similar sequences. - * - * @param other The other JSONArray - * @return true if they are equal - */ - public boolean similar(Object other) { - if (!(other instanceof JSONArray)) { - return false; - } - int len = this.length(); - if (len != ((JSONArray)other).length()) { - return false; - } - for (int i = 0; i < len; i += 1) { - Object valueThis = this.get(i); - Object valueOther = ((JSONArray)other).get(i); - if (valueThis instanceof JSONObject) { - if (!((JSONObject)valueThis).similar(valueOther)) { - return false; - } - } else if (valueThis instanceof JSONArray) { - if (!((JSONArray)valueThis).similar(valueOther)) { - return false; - } - } else if (!valueThis.equals(valueOther)) { - return false; - } - } - return true; - } - - /** - * Produce a JSONObject by combining a JSONArray of names with the values of - * this JSONArray. - * - * @param names - * A JSONArray containing a list of key strings. These will be - * paired with the values. - * @return A JSONObject, or null if there are no names or if this JSONArray - * has no values. - * @throws JSONException - * If any of the names are null. - */ - public JSONObject toJSONObject(JSONArray names) throws JSONException { - if (names == null || names.length() == 0 || this.length() == 0) { - return null; - } - JSONObject jo = new JSONObject(); - for (int i = 0; i < names.length(); i += 1) { - jo.put(names.getString(i), this.opt(i)); - } - return jo; - } - - /** - * Make a JSON text of this JSONArray. For compactness, no unnecessary - * whitespace is added. If it is not possible to produce a syntactically - * correct JSON text then null will be returned instead. This could occur if - * the array contains an invalid number. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return a printable, displayable, transmittable representation of the - * array. - */ - public String toString() { - try { - return this.toString(0); - } catch (Exception e) { - return null; - } - } - - /** - * Make a prettyprinted JSON text of this JSONArray. Warning: This method - * assumes that the data structure is acyclical. - * - * @param indentFactor - * The number of spaces to add to each level of indentation. - * @return a printable, displayable, transmittable representation of the - * object, beginning with [ (left - * bracket) and ending with ] - *  (right bracket). - * @throws JSONException - */ - public String toString(int indentFactor) throws JSONException { - StringWriter sw = new StringWriter(); - synchronized (sw.getBuffer()) { - return this.write(sw, indentFactor, 0).toString(); - } - } - - /** - * Write the contents of the JSONArray as JSON text to a writer. For - * compactness, no whitespace is added. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer) throws JSONException { - return this.write(writer, 0, 0); - } - - /** - * Write the contents of the JSONArray as JSON text to a writer. For - * compactness, no whitespace is added. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @param indentFactor - * The number of spaces to add to each level of indentation. - * @param indent - * The indention of the top level. - * @return The writer. - * @throws JSONException - */ - Writer write(Writer writer, int indentFactor, int indent) - throws JSONException { - try { - boolean commanate = false; - int length = this.length(); - writer.write('['); - - if (length == 1) { - JSONObject.writeValue(writer, this.myArrayList.get(0), - indentFactor, indent); - } else if (length != 0) { - final int newindent = indent + indentFactor; - - for (int i = 0; i < length; i += 1) { - if (commanate) { - writer.write(','); - } - if (indentFactor > 0) { - writer.write('\n'); - } - JSONObject.indent(writer, newindent); - JSONObject.writeValue(writer, this.myArrayList.get(i), - indentFactor, newindent); - commanate = true; - } - if (indentFactor > 0) { - writer.write('\n'); - } - JSONObject.indent(writer, indent); - } - writer.write(']'); - return writer; - } catch (IOException e) { - throw new JSONException(e); - } - } -} +/* + * $Id: JSONArray.java,v 1.1 2006/04/15 14:10:48 platform Exp $ + * Created on 2006-4-10 + */ +package blade.kit.json; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +/** + * A JSON array. JSONObject supports java.util.List interface. + * + * @author FangYidong + */ +@SuppressWarnings({"rawtypes","unchecked"}) +public class JSONArray extends ArrayList implements JSONAware, JSONStreamAware { + + private static final long serialVersionUID = 3957988303675231981L; + + /** + * Constructs an empty JSONArray. + */ + public JSONArray(){ + super(); + } + + /** + * Constructs a JSONArray containing the elements of the specified + * collection, in the order they are returned by the collection's iterator. + * + * @param c the collection whose elements are to be placed into this JSONArray + */ + public JSONArray(Collection c){ + super(c); + } + + /** + * Encode a list into JSON text and write it to out. + * If this list is also a JSONStreamAware or a JSONAware, JSONStreamAware and JSONAware specific behaviours will be ignored at this top level. + * + * @see blade.kit.json2.JSONValue#writeJSONString(Object, Writer) + * + * @param collection + * @param out + */ + public static void writeJSONString(Collection collection, Writer out) throws IOException{ + if(collection == null){ + out.write("null"); + return; + } + + boolean first = true; + Iterator iter=collection.iterator(); + + out.write('['); + while(iter.hasNext()){ + if(first) + first = false; + else + out.write(','); + + Object value=iter.next(); + if(value == null){ + out.write("null"); + continue; + } + + JSONValue.writeJSONString(value, out); + } + out.write(']'); + } + + public void writeJSONString(Writer out) throws IOException{ + writeJSONString(this, out); + } + + /** + * Convert a list to JSON text. The result is a JSON array. + * If this list is also a JSONAware, JSONAware specific behaviours will be omitted at this top level. + * + * @see blade.kit.json2.JSONValue#toJSONString(Object) + * + * @param collection + * @return JSON text, or "null" if list is null. + */ + public static String toJSONString(Collection collection){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(collection, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + public static void writeJSONString(byte[] array, Writer out) throws IOException{ + if(array == null){ + out.write("null"); + } else if(array.length == 0) { + out.write("[]"); + } else { + out.write("["); + out.write(String.valueOf(array[0])); + + for(int i = 1; i < array.length; i++){ + out.write(","); + out.write(String.valueOf(array[i])); + } + + out.write("]"); + } + } + + public static String toJSONString(byte[] array){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(array, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + public static void writeJSONString(short[] array, Writer out) throws IOException{ + if(array == null){ + out.write("null"); + } else if(array.length == 0) { + out.write("[]"); + } else { + out.write("["); + out.write(String.valueOf(array[0])); + + for(int i = 1; i < array.length; i++){ + out.write(","); + out.write(String.valueOf(array[i])); + } + + out.write("]"); + } + } + + public static String toJSONString(short[] array){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(array, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + public static void writeJSONString(int[] array, Writer out) throws IOException{ + if(array == null){ + out.write("null"); + } else if(array.length == 0) { + out.write("[]"); + } else { + out.write("["); + out.write(String.valueOf(array[0])); + + for(int i = 1; i < array.length; i++){ + out.write(","); + out.write(String.valueOf(array[i])); + } + + out.write("]"); + } + } + + public static String toJSONString(int[] array){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(array, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + public static void writeJSONString(long[] array, Writer out) throws IOException{ + if(array == null){ + out.write("null"); + } else if(array.length == 0) { + out.write("[]"); + } else { + out.write("["); + out.write(String.valueOf(array[0])); + + for(int i = 1; i < array.length; i++){ + out.write(","); + out.write(String.valueOf(array[i])); + } + + out.write("]"); + } + } + + public static String toJSONString(long[] array){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(array, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + public static void writeJSONString(float[] array, Writer out) throws IOException{ + if(array == null){ + out.write("null"); + } else if(array.length == 0) { + out.write("[]"); + } else { + out.write("["); + out.write(String.valueOf(array[0])); + + for(int i = 1; i < array.length; i++){ + out.write(","); + out.write(String.valueOf(array[i])); + } + + out.write("]"); + } + } + + public static String toJSONString(float[] array){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(array, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + public static void writeJSONString(double[] array, Writer out) throws IOException{ + if(array == null){ + out.write("null"); + } else if(array.length == 0) { + out.write("[]"); + } else { + out.write("["); + out.write(String.valueOf(array[0])); + + for(int i = 1; i < array.length; i++){ + out.write(","); + out.write(String.valueOf(array[i])); + } + + out.write("]"); + } + } + + public static String toJSONString(double[] array){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(array, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + public static void writeJSONString(boolean[] array, Writer out) throws IOException{ + if(array == null){ + out.write("null"); + } else if(array.length == 0) { + out.write("[]"); + } else { + out.write("["); + out.write(String.valueOf(array[0])); + + for(int i = 1; i < array.length; i++){ + out.write(","); + out.write(String.valueOf(array[i])); + } + + out.write("]"); + } + } + + public static String toJSONString(boolean[] array){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(array, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + public static void writeJSONString(char[] array, Writer out) throws IOException{ + if(array == null){ + out.write("null"); + } else if(array.length == 0) { + out.write("[]"); + } else { + out.write("[\""); + out.write(String.valueOf(array[0])); + + for(int i = 1; i < array.length; i++){ + out.write("\",\""); + out.write(String.valueOf(array[i])); + } + + out.write("\"]"); + } + } + + public static String toJSONString(char[] array){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(array, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + public static void writeJSONString(Object[] array, Writer out) throws IOException{ + if(array == null){ + out.write("null"); + } else if(array.length == 0) { + out.write("[]"); + } else { + out.write("["); + JSONValue.writeJSONString(array[0], out); + + for(int i = 1; i < array.length; i++){ + out.write(","); + JSONValue.writeJSONString(array[i], out); + } + + out.write("]"); + } + } + + public static String toJSONString(Object[] array){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(array, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + public String toJSONString(){ + return toJSONString(this); + } + + /** + * Returns a string representation of this array. This is equivalent to + * calling {@link JSONArray#toJSONString()}. + */ + public String toString() { + return toJSONString(); + } + + /** + * Get the object value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return An object value. + * @throws JSONException + * If there is no value for the index. + */ + public Object get(int index) throws JSONException { + Object object = this.get(index); + if (object == null) { + throw new JSONException("JSONArray[" + index + "] not found."); + } + return object; + } + + /** + * Get the boolean value associated with an index. The string values "true" + * and "false" are converted to boolean. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The truth. + * @throws JSONException + * If there is no value for the index or if the value is not + * convertible to boolean. + */ + public boolean getBoolean(int index) throws JSONException { + Object object = this.get(index); + if (object.equals(Boolean.FALSE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("false"))) { + return false; + } else if (object.equals(Boolean.TRUE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("true"))) { + return true; + } + throw new JSONException("JSONArray[" + index + "] is not a boolean."); + } + + /** + * Get the double value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a number. + */ + public double getDouble(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number ? ((Number) object).doubleValue() + : Double.parseDouble((String) object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + "] is not a number."); + } + } + + /** + * Get the BigDecimal value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a BigDecimal. + */ + public BigDecimal getBigDecimal (int index) throws JSONException { + Object object = this.get(index); + try { + return new BigDecimal(object.toString()); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + + "] could not convert to BigDecimal."); + } + } + + /** + * Get the BigInteger value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a BigInteger. + */ + public BigInteger getBigInteger (int index) throws JSONException { + Object object = this.get(index); + try { + return new BigInteger(object.toString()); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + + "] could not convert to BigInteger."); + } + } + + /** + * Get the int value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value is not a number. + */ + public int getInt(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number ? ((Number) object).intValue() + : Integer.parseInt((String) object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + "] is not a number."); + } + } + + /** + * Get the JSONArray associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A JSONArray value. + * @throws JSONException + * If there is no value for the index. or if the value is not a + * JSONArray + */ + public JSONArray getJSONArray(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof JSONArray) { + return (JSONArray) object; + } + throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); + } + + /** + * Get the JSONObject associated with an index. + * + * @param index + * subscript + * @return A JSONObject value. + * @throws JSONException + * If there is no value for the index or if the value is not a + * JSONObject + */ + public JSONObject getJSONObject(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof JSONObject) { + return (JSONObject) object; + } + throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); + } + + /** + * Get the long value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted + * to a number. + */ + public long getLong(int index) throws JSONException { + Object object = this.get(index); + try { + return object instanceof Number ? ((Number) object).longValue() + : Long.parseLong((String) object); + } catch (Exception e) { + throw new JSONException("JSONArray[" + index + "] is not a number."); + } + } + + /** + * Get the string associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A string value. + * @throws JSONException + * If there is no string value for the index. + */ + public String getString(int index) throws JSONException { + Object object = this.get(index); + if (object instanceof String) { + return (String) object; + } + throw new JSONException("JSONArray[" + index + "] not a string."); + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONException.java b/blade-kit/src/main/java/blade/kit/json/JSONException.java index 1f0564e74..e0dac7222 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONException.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONException.java @@ -1,43 +1,42 @@ -package blade.kit.json; - -/** - * The JSONException is thrown by the JSON.org classes when things are amiss. - * - * @author JSON.org - * @version 2014-05-03 - */ -public class JSONException extends RuntimeException { - private static final long serialVersionUID = 0; - private Throwable cause; - - /** - * Constructs a JSONException with an explanatory message. - * - * @param message - * Detail about the reason for the exception. - */ - public JSONException(String message) { - super(message); - } - - /** - * Constructs a new JSONException with the specified cause. - * @param cause The cause. - */ - public JSONException(Throwable cause) { - super(cause.getMessage()); - this.cause = cause; - } - - /** - * Returns the cause of this exception or null if the cause is nonexistent - * or unknown. - * - * @return the cause of this exception or null if the cause is nonexistent - * or unknown. - */ - @Override - public Throwable getCause() { - return this.cause; - } -} +package blade.kit.json; +/** + * The JSONException is thrown by the JSON.org classes when things are amiss. + * + * @author JSON.org + * @version 2014-05-03 + */ +public class JSONException extends RuntimeException { + private static final long serialVersionUID = 0; + private Throwable cause; + + /** + * Constructs a JSONException with an explanatory message. + * + * @param message + * Detail about the reason for the exception. + */ + public JSONException(String message) { + super(message); + } + + /** + * Constructs a new JSONException with the specified cause. + * @param cause The cause. + */ + public JSONException(Throwable cause) { + super(cause.getMessage()); + this.cause = cause; + } + + /** + * Returns the cause of this exception or null if the cause is nonexistent + * or unknown. + * + * @return the cause of this exception or null if the cause is nonexistent + * or unknown. + */ + @Override + public Throwable getCause() { + return this.cause; + } +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/JSONKit.java b/blade-kit/src/main/java/blade/kit/json/JSONKit.java index 6a9ad97cd..3b771712e 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONKit.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONKit.java @@ -3,94 +3,66 @@ import java.util.List; import java.util.Map; -import blade.kit.CollectionKit; +import blade.kit.base.ThrowableKit; +import blade.kit.json.parse.ParseException; +import blade.kit.log.Logger; +/** + * JSON工具类 + * @author biezhi + * + */ @SuppressWarnings("unchecked") public class JSONKit { - public static Map toMap(String json){ - try { - JSONObject jsonObject = new JSONObject(json); - return JSONMap.toMap(jsonObject); - } catch (JSONException e) { - e.printStackTrace(); - } - return null; - } + private static final Logger LOGGER = Logger.getLogger(JSONKit.class); - public static Map toMap(JSONObject jsonObject){ + public static Map toMap(String json){ try { - return JSONMap.toMap(jsonObject); - } catch (JSONException e) { - e.printStackTrace(); + return (Map) JSONValue.parse(json); + } catch (ParseException e) { + String error = ThrowableKit.getStackTraceAsString(e); + LOGGER.error(error); + ThrowableKit.propagate(e); } return null; } public static List toList(String json){ - JSONArray jsonArray = new JSONArray(json); - int len = jsonArray.length(); - List list = CollectionKit.newArrayList(len); - for(int i=0; i String toJSONString(Map map){ try { - return toJSON(map).toString(); - } catch (Exception e) { - e.printStackTrace(); + return (List) JSONValue.parse(json); + } catch (ParseException e) { + String error = ThrowableKit.getStackTraceAsString(e); + LOGGER.error(error); + ThrowableKit.propagate(e); } return null; } - public static JSONObject toJSON(Map map){ + public static T parse(final String json) { try { - JSONObject jsonObj = new JSONObject(); - for (Map.Entry entry : map.entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - try { - jsonObj.put(key, value); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return jsonObj; - } catch (Exception e) { - e.printStackTrace(); + return (T) JSONValue.parse(json); + } catch (ParseException e) { + String error = ThrowableKit.getStackTraceAsString(e); + LOGGER.error(error); + ThrowableKit.propagate(e); } return null; } - public static String toJSONString(List> list){ - if(null != list && list.size() > 0){ - JSONArray jsonArr = new JSONArray(); - for (Map map : list) { - jsonArr.put(toJSON(map)); - } - return jsonArr.toString(); + public static T parse(final String json, Class type) { + try { + return (T) JSONValue.parse(json); + } catch (ParseException e) { + String error = ThrowableKit.getStackTraceAsString(e); + LOGGER.error(error); + ThrowableKit.propagate(e); } return null; } - public static String toJSONString(Object bean){ - try { - JSONObject jsonObject = new JSONObject(bean); - return jsonObject.toString(); - } catch (Exception e) { - e.printStackTrace(); - } - return null; + public static String toJSONString(Object object){ + return JSONValue.toJSONString(object); } } diff --git a/blade-kit/src/main/java/blade/kit/json/JSONObject.java b/blade-kit/src/main/java/blade/kit/json/JSONObject.java index 303595e01..0f91ac2e4 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONObject.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONObject.java @@ -1,1779 +1,349 @@ -package blade.kit.json; - -/* - Copyright (c) 2002 JSON.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - The Software shall be used for Good, not Evil. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.math.*; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.ResourceBundle; -import java.util.Set; - -/** - * A JSONObject is an unordered collection of name/value pairs. Its external - * form is a string wrapped in curly braces with colons between the names and - * values, and commas between the values and names. The internal form is an - * object having get and opt methods for accessing - * the values by name, and put methods for adding or replacing - * values by name. The values can be any of these types: Boolean, - * JSONArray, JSONObject, Number, - * String, or the JSONObject.NULL object. A - * JSONObject constructor can be used to convert an external form JSON text - * into an internal form whose values can be retrieved with the - * get and opt methods, or to convert values into a - * JSON text using the put and toString methods. A - * get method returns a value if one can be found, and throws an - * exception if one cannot be found. An opt method returns a - * default value instead of throwing an exception, and so is useful for - * obtaining optional values. - *

- * The generic get() and opt() methods return an - * object, which you can cast or query for type. There are also typed - * get and opt methods that do type checking and type - * coercion for you. The opt methods differ from the get methods in that they - * do not throw. Instead, they return a specified value, such as null. - *

- * The put methods add or replace values in an object. For - * example, - * - *

- * myString = new JSONObject()
- *         .put("JSON", "Hello, World!").toString();
- * 
- * - * produces the string {"JSON": "Hello, World"}. - *

- * The texts produced by the toString methods strictly conform to - * the JSON syntax rules. The constructors are more forgiving in the texts they - * will accept: - *

    - *
  • An extra , (comma) may appear just - * before the closing brace.
  • - *
  • Strings may be quoted with ' (single - * quote).
  • - *
  • Strings do not need to be quoted at all if they do not begin with a - * quote or single quote, and if they do not contain leading or trailing - * spaces, and if they do not contain any of these characters: - * { } [ ] / \ : , # and if they do not look like numbers and - * if they are not the reserved words true, false, - * or null.
  • - *
- * - * @author JSON.org - * @version 2015-07-06 - */ -public class JSONObject { - /** - * JSONObject.NULL is equivalent to the value that JavaScript calls null, - * whilst Java's null is equivalent to the value that JavaScript calls - * undefined. - */ - private static final class Null { - - /** - * There is only intended to be a single instance of the NULL object, - * so the clone method returns itself. - * - * @return NULL. - */ - @Override - protected final Object clone() { - return this; - } - - /** - * A Null object is equal to the null value and to itself. - * - * @param object - * An object to test for nullness. - * @return true if the object parameter is the JSONObject.NULL object or - * null. - */ - @Override - public boolean equals(Object object) { - return object == null || object == this; - } - - /** - * Get the "null" string value. - * - * @return The string "null". - */ - public String toString() { - return "null"; - } - } - - /** - * The map where the JSONObject's properties are kept. - */ - private final Map map; - - /** - * It is sometimes more convenient and less ambiguous to have a - * NULL object than to use Java's null value. - * JSONObject.NULL.equals(null) returns true. - * JSONObject.NULL.toString() returns "null". - */ - public static final Object NULL = new Null(); - - /** - * Construct an empty JSONObject. - */ - public JSONObject() { - this.map = new HashMap(); - } - - /** - * Construct a JSONObject from a subset of another JSONObject. An array of - * strings is used to identify the keys that should be copied. Missing keys - * are ignored. - * - * @param jo - * A JSONObject. - * @param names - * An array of strings. - * @throws JSONException - * @exception JSONException - * If a value is a non-finite number or if a name is - * duplicated. - */ - public JSONObject(JSONObject jo, String[] names) { - this(); - for (int i = 0; i < names.length; i += 1) { - try { - this.putOnce(names[i], jo.opt(names[i])); - } catch (Exception ignore) { - } - } - } - - /** - * Construct a JSONObject from a JSONTokener. - * - * @param x - * A JSONTokener object containing the source string. - * @throws JSONException - * If there is a syntax error in the source string or a - * duplicated key. - */ - public JSONObject(JSONTokener x) throws JSONException { - this(); - char c; - String key; - - if (x.nextClean() != '{') { - throw x.syntaxError("A JSONObject text must begin with '{'"); - } - for (;;) { - c = x.nextClean(); - switch (c) { - case 0: - throw x.syntaxError("A JSONObject text must end with '}'"); - case '}': - return; - default: - x.back(); - key = x.nextValue().toString(); - } - -// The key is followed by ':'. - - c = x.nextClean(); - if (c != ':') { - throw x.syntaxError("Expected a ':' after a key"); - } - this.putOnce(key, x.nextValue()); - -// Pairs are separated by ','. - - switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == '}') { - return; - } - x.back(); - break; - case '}': - return; - default: - throw x.syntaxError("Expected a ',' or '}'"); - } - } - } - - /** - * Construct a JSONObject from a Map. - * - * @param map - * A map object that can be used to initialize the contents of - * the JSONObject. - * @throws JSONException - */ - public JSONObject(Map map) { - this.map = new HashMap(); - if (map != null) { - Iterator> i = map.entrySet().iterator(); - while (i.hasNext()) { - Entry entry = i.next(); - Object value = entry.getValue(); - if (value != null) { - this.map.put(entry.getKey(), wrap(value)); - } - } - } - } - - /** - * Construct a JSONObject from an Object using bean getters. It reflects on - * all of the public methods of the object. For each of the methods with no - * parameters and a name starting with "get" or - * "is" followed by an uppercase letter, the method is invoked, - * and a key and the value returned from the getter method are put into the - * new JSONObject. - * - * The key is formed by removing the "get" or "is" - * prefix. If the second remaining character is not upper case, then the - * first character is converted to lower case. - * - * For example, if an object has a method named "getName", and - * if the result of calling object.getName() is - * "Larry Fine", then the JSONObject will contain - * "name": "Larry Fine". - * - * @param bean - * An object that has getter methods that should be used to make - * a JSONObject. - */ - public JSONObject(Object bean) { - this(); - this.populateMap(bean); - } - - /** - * Construct a JSONObject from an Object, using reflection to find the - * public members. The resulting JSONObject's keys will be the strings from - * the names array, and the values will be the field values associated with - * those keys in the object. If a key is not found or not visible, then it - * will not be copied into the new JSONObject. - * - * @param object - * An object that has fields that should be used to make a - * JSONObject. - * @param names - * An array of strings, the names of the fields to be obtained - * from the object. - */ - public JSONObject(Object object, String names[]) { - this(); - Class c = object.getClass(); - for (int i = 0; i < names.length; i += 1) { - String name = names[i]; - try { - this.putOpt(name, c.getField(name).get(object)); - } catch (Exception ignore) { - } - } - } - - /** - * Construct a JSONObject from a source JSON text string. This is the most - * commonly used JSONObject constructor. - * - * @param source - * A string beginning with { (left - * brace) and ending with } - *  (right brace). - * @exception JSONException - * If there is a syntax error in the source string or a - * duplicated key. - */ - public JSONObject(String source) throws JSONException { - this(new JSONTokener(source)); - } - - /** - * Construct a JSONObject from a ResourceBundle. - * - * @param baseName - * The ResourceBundle base name. - * @param locale - * The Locale to load the ResourceBundle for. - * @throws JSONException - * If any JSONExceptions are detected. - */ - public JSONObject(String baseName, Locale locale) throws JSONException { - this(); - ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, - Thread.currentThread().getContextClassLoader()); - -// Iterate through the keys in the bundle. - - Enumeration keys = bundle.getKeys(); - while (keys.hasMoreElements()) { - Object key = keys.nextElement(); - if (key != null) { - -// Go through the path, ensuring that there is a nested JSONObject for each -// segment except the last. Add the value using the last segment's name into -// the deepest nested JSONObject. - - String[] path = ((String) key).split("\\."); - int last = path.length - 1; - JSONObject target = this; - for (int i = 0; i < last; i += 1) { - String segment = path[i]; - JSONObject nextTarget = target.optJSONObject(segment); - if (nextTarget == null) { - nextTarget = new JSONObject(); - target.put(segment, nextTarget); - } - target = nextTarget; - } - target.put(path[last], bundle.getString((String) key)); - } - } - } - - /** - * Accumulate values under a key. It is similar to the put method except - * that if there is already an object stored under the key then a JSONArray - * is stored under the key to hold all of the accumulated values. If there - * is already a JSONArray, then the new value is appended to it. In - * contrast, the put method replaces the previous value. - * - * If only one value is accumulated that is not a JSONArray, then the result - * will be the same as using put. But if multiple values are accumulated, - * then the result will be like append. - * - * @param key - * A key string. - * @param value - * An object to be accumulated under the key. - * @return this. - * @throws JSONException - * If the value is an invalid number or if the key is null. - */ - public JSONObject accumulate(String key, Object value) throws JSONException { - testValidity(value); - Object object = this.opt(key); - if (object == null) { - this.put(key, - value instanceof JSONArray ? new JSONArray().put(value) - : value); - } else if (object instanceof JSONArray) { - ((JSONArray) object).put(value); - } else { - this.put(key, new JSONArray().put(object).put(value)); - } - return this; - } - - /** - * Append values to the array under a key. If the key does not exist in the - * JSONObject, then the key is put in the JSONObject with its value being a - * JSONArray containing the value parameter. If the key was already - * associated with a JSONArray, then the value parameter is appended to it. - * - * @param key - * A key string. - * @param value - * An object to be accumulated under the key. - * @return this. - * @throws JSONException - * If the key is null or if the current value associated with - * the key is not a JSONArray. - */ - public JSONObject append(String key, Object value) throws JSONException { - testValidity(value); - Object object = this.opt(key); - if (object == null) { - this.put(key, new JSONArray().put(value)); - } else if (object instanceof JSONArray) { - this.put(key, ((JSONArray) object).put(value)); - } else { - throw new JSONException("JSONObject[" + key - + "] is not a JSONArray."); - } - return this; - } - - /** - * Produce a string from a double. The string "null" will be returned if the - * number is not finite. - * - * @param d - * A double. - * @return A String. - */ - public static String doubleToString(double d) { - if (Double.isInfinite(d) || Double.isNaN(d)) { - return "null"; - } - -// Shave off trailing zeros and decimal point, if possible. - - String string = Double.toString(d); - if (string.indexOf('.') > 0 && string.indexOf('e') < 0 - && string.indexOf('E') < 0) { - while (string.endsWith("0")) { - string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - } - return string; - } - - /** - * Get the value object associated with a key. - * - * @param key - * A key string. - * @return The object associated with the key. - * @throws JSONException - * if the key is not found. - */ - public Object get(String key) throws JSONException { - if (key == null) { - throw new JSONException("Null key."); - } - Object object = this.opt(key); - if (object == null) { - throw new JSONException("JSONObject[" + quote(key) + "] not found."); - } - return object; - } - - /** - * Get the boolean value associated with a key. - * - * @param key - * A key string. - * @return The truth. - * @throws JSONException - * if the value is not a Boolean or the String "true" or - * "false". - */ - public boolean getBoolean(String key) throws JSONException { - Object object = this.get(key); - if (object.equals(Boolean.FALSE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a Boolean."); - } - - /** - * Get the BigInteger value associated with a key. - * - * @param key - * A key string. - * @return The numeric value. - * @throws JSONException - * if the key is not found or if the value cannot - * be converted to BigInteger. - */ - public BigInteger getBigInteger(String key) throws JSONException { - Object object = this.get(key); - try { - return new BigInteger(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] could not be converted to BigInteger."); - } - } - - /** - * Get the BigDecimal value associated with a key. - * - * @param key - * A key string. - * @return The numeric value. - * @throws JSONException - * if the key is not found or if the value - * cannot be converted to BigDecimal. - */ - public BigDecimal getBigDecimal(String key) throws JSONException { - Object object = this.get(key); - try { - return new BigDecimal(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] could not be converted to BigDecimal."); - } - } - - /** - * Get the double value associated with a key. - * - * @param key - * A key string. - * @return The numeric value. - * @throws JSONException - * if the key is not found or if the value is not a Number - * object and cannot be converted to a number. - */ - public double getDouble(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number ? ((Number) object).doubleValue() - : Double.parseDouble((String) object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] is not a number."); - } - } - - /** - * Get the int value associated with a key. - * - * @param key - * A key string. - * @return The integer value. - * @throws JSONException - * if the key is not found or if the value cannot be converted - * to an integer. - */ - public int getInt(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number ? ((Number) object).intValue() - : Integer.parseInt((String) object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] is not an int."); - } - } - - /** - * Get the JSONArray value associated with a key. - * - * @param key - * A key string. - * @return A JSONArray which is the value. - * @throws JSONException - * if the key is not found or if the value is not a JSONArray. - */ - public JSONArray getJSONArray(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONArray) { - return (JSONArray) object; - } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a JSONArray."); - } - - /** - * Get the JSONObject value associated with a key. - * - * @param key - * A key string. - * @return A JSONObject which is the value. - * @throws JSONException - * if the key is not found or if the value is not a JSONObject. - */ - public JSONObject getJSONObject(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONObject) { - return (JSONObject) object; - } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a JSONObject."); - } - - /** - * Get the long value associated with a key. - * - * @param key - * A key string. - * @return The long value. - * @throws JSONException - * if the key is not found or if the value cannot be converted - * to a long. - */ - public long getLong(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number ? ((Number) object).longValue() - : Long.parseLong((String) object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] is not a long."); - } - } - - /** - * Get an array of field names from a JSONObject. - * - * @return An array of field names, or null if there are no names. - */ - public static String[] getNames(JSONObject jo) { - int length = jo.length(); - if (length == 0) { - return null; - } - Iterator iterator = jo.keys(); - String[] names = new String[length]; - int i = 0; - while (iterator.hasNext()) { - names[i] = iterator.next(); - i += 1; - } - return names; - } - - /** - * Get an array of field names from an Object. - * - * @return An array of field names, or null if there are no names. - */ - public static String[] getNames(Object object) { - if (object == null) { - return null; - } - Class klass = object.getClass(); - Field[] fields = klass.getFields(); - int length = fields.length; - if (length == 0) { - return null; - } - String[] names = new String[length]; - for (int i = 0; i < length; i += 1) { - names[i] = fields[i].getName(); - } - return names; - } - - /** - * Get the string associated with a key. - * - * @param key - * A key string. - * @return A string which is the value. - * @throws JSONException - * if there is no string value for the key. - */ - public String getString(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof String) { - return (String) object; - } - throw new JSONException("JSONObject[" + quote(key) + "] not a string."); - } - - /** - * Determine if the JSONObject contains a specific key. - * - * @param key - * A key string. - * @return true if the key exists in the JSONObject. - */ - public boolean has(String key) { - return this.map.containsKey(key); - } - - /** - * Increment a property of a JSONObject. If there is no such property, - * create one with a value of 1. If there is such a property, and if it is - * an Integer, Long, Double, or Float, then add one to it. - * - * @param key - * A key string. - * @return this. - * @throws JSONException - * If there is already a property with this name that is not an - * Integer, Long, Double, or Float. - */ - public JSONObject increment(String key) throws JSONException { - Object value = this.opt(key); - if (value == null) { - this.put(key, 1); - } else if (value instanceof BigInteger) { - this.put(key, ((BigInteger)value).add(BigInteger.ONE)); - } else if (value instanceof BigDecimal) { - this.put(key, ((BigDecimal)value).add(BigDecimal.ONE)); - } else if (value instanceof Integer) { - this.put(key, (Integer) value + 1); - } else if (value instanceof Long) { - this.put(key, (Long) value + 1); - } else if (value instanceof Double) { - this.put(key, (Double) value + 1); - } else if (value instanceof Float) { - this.put(key, (Float) value + 1); - } else { - throw new JSONException("Unable to increment [" + quote(key) + "]."); - } - return this; - } - - /** - * Determine if the value associated with the key is null or if there is no - * value. - * - * @param key - * A key string. - * @return true if there is no value associated with the key or if the value - * is the JSONObject.NULL object. - */ - public boolean isNull(String key) { - return JSONObject.NULL.equals(this.opt(key)); - } - - /** - * Get an enumeration of the keys of the JSONObject. - * - * @return An iterator of the keys. - */ - public Iterator keys() { - return this.keySet().iterator(); - } - - /** - * Get a set of keys of the JSONObject. - * - * @return A keySet. - */ - public Set keySet() { - return this.map.keySet(); - } - - /** - * Get the number of keys stored in the JSONObject. - * - * @return The number of keys in the JSONObject. - */ - public int length() { - return this.map.size(); - } - - /** - * Produce a JSONArray containing the names of the elements of this - * JSONObject. - * - * @return A JSONArray containing the key strings, or null if the JSONObject - * is empty. - */ - public JSONArray names() { - JSONArray ja = new JSONArray(); - Iterator keys = this.keys(); - while (keys.hasNext()) { - ja.put(keys.next()); - } - return ja.length() == 0 ? null : ja; - } - - /** - * Produce a string from a Number. - * - * @param number - * A Number - * @return A String. - * @throws JSONException - * If n is a non-finite number. - */ - public static String numberToString(Number number) throws JSONException { - if (number == null) { - throw new JSONException("Null pointer"); - } - testValidity(number); - -// Shave off trailing zeros and decimal point, if possible. - - String string = number.toString(); - if (string.indexOf('.') > 0 && string.indexOf('e') < 0 - && string.indexOf('E') < 0) { - while (string.endsWith("0")) { - string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { - string = string.substring(0, string.length() - 1); - } - } - return string; - } - - /** - * Get an optional value associated with a key. - * - * @param key - * A key string. - * @return An object which is the value, or null if there is no value. - */ - public Object opt(String key) { - return key == null ? null : this.map.get(key); - } - - /** - * Get an optional boolean associated with a key. It returns false if there - * is no such key, or if the value is not Boolean.TRUE or the String "true". - * - * @param key - * A key string. - * @return The truth. - */ - public boolean optBoolean(String key) { - return this.optBoolean(key, false); - } - - /** - * Get an optional boolean associated with a key. It returns the - * defaultValue if there is no such key, or if it is not a Boolean or the - * String "true" or "false" (case insensitive). - * - * @param key - * A key string. - * @param defaultValue - * The default. - * @return The truth. - */ - public boolean optBoolean(String key, boolean defaultValue) { - try { - return this.getBoolean(key); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get an optional double associated with a key, or NaN if there is no such - * key or if its value is not a number. If the value is a string, an attempt - * will be made to evaluate it as a number. - * - * @param key - * A string which is the key. - * @return An object which is the value. - */ - public double optDouble(String key) { - return this.optDouble(key, Double.NaN); - } - - /** - * Get an optional BigInteger associated with a key, or the defaultValue if - * there is no such key or if its value is not a number. If the value is a - * string, an attempt will be made to evaluate it as a number. - * - * @param key - * A key string. - * @param defaultValue - * The default. - * @return An object which is the value. - */ - public BigInteger optBigInteger(String key, BigInteger defaultValue) { - try { - return this.getBigInteger(key); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get an optional BigDecimal associated with a key, or the defaultValue if - * there is no such key or if its value is not a number. If the value is a - * string, an attempt will be made to evaluate it as a number. - * - * @param key - * A key string. - * @param defaultValue - * The default. - * @return An object which is the value. - */ - public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) { - try { - return this.getBigDecimal(key); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get an optional double associated with a key, or the defaultValue if - * there is no such key or if its value is not a number. If the value is a - * string, an attempt will be made to evaluate it as a number. - * - * @param key - * A key string. - * @param defaultValue - * The default. - * @return An object which is the value. - */ - public double optDouble(String key, double defaultValue) { - try { - return this.getDouble(key); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get an optional int value associated with a key, or zero if there is no - * such key or if the value is not a number. If the value is a string, an - * attempt will be made to evaluate it as a number. - * - * @param key - * A key string. - * @return An object which is the value. - */ - public int optInt(String key) { - return this.optInt(key, 0); - } - - /** - * Get an optional int value associated with a key, or the default if there - * is no such key or if the value is not a number. If the value is a string, - * an attempt will be made to evaluate it as a number. - * - * @param key - * A key string. - * @param defaultValue - * The default. - * @return An object which is the value. - */ - public int optInt(String key, int defaultValue) { - try { - return this.getInt(key); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get an optional JSONArray associated with a key. It returns null if there - * is no such key, or if its value is not a JSONArray. - * - * @param key - * A key string. - * @return A JSONArray which is the value. - */ - public JSONArray optJSONArray(String key) { - Object o = this.opt(key); - return o instanceof JSONArray ? (JSONArray) o : null; - } - - /** - * Get an optional JSONObject associated with a key. It returns null if - * there is no such key, or if its value is not a JSONObject. - * - * @param key - * A key string. - * @return A JSONObject which is the value. - */ - public JSONObject optJSONObject(String key) { - Object object = this.opt(key); - return object instanceof JSONObject ? (JSONObject) object : null; - } - - /** - * Get an optional long value associated with a key, or zero if there is no - * such key or if the value is not a number. If the value is a string, an - * attempt will be made to evaluate it as a number. - * - * @param key - * A key string. - * @return An object which is the value. - */ - public long optLong(String key) { - return this.optLong(key, 0); - } - - /** - * Get an optional long value associated with a key, or the default if there - * is no such key or if the value is not a number. If the value is a string, - * an attempt will be made to evaluate it as a number. - * - * @param key - * A key string. - * @param defaultValue - * The default. - * @return An object which is the value. - */ - public long optLong(String key, long defaultValue) { - try { - return this.getLong(key); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get an optional string associated with a key. It returns an empty string - * if there is no such key. If the value is not a string and is not null, - * then it is converted to a string. - * - * @param key - * A key string. - * @return A string which is the value. - */ - public String optString(String key) { - return this.optString(key, ""); - } - - /** - * Get an optional string associated with a key. It returns the defaultValue - * if there is no such key. - * - * @param key - * A key string. - * @param defaultValue - * The default. - * @return A string which is the value. - */ - public String optString(String key, String defaultValue) { - Object object = this.opt(key); - return NULL.equals(object) ? defaultValue : object.toString(); - } - - private void populateMap(Object bean) { - Class klass = bean.getClass(); - -// If klass is a System class then set includeSuperClass to false. - - boolean includeSuperClass = klass.getClassLoader() != null; - - Method[] methods = includeSuperClass ? klass.getMethods() : klass - .getDeclaredMethods(); - for (int i = 0; i < methods.length; i += 1) { - try { - Method method = methods[i]; - if (Modifier.isPublic(method.getModifiers())) { - String name = method.getName(); - String key = ""; - if (name.startsWith("get")) { - if ("getClass".equals(name) - || "getDeclaringClass".equals(name)) { - key = ""; - } else { - key = name.substring(3); - } - } else if (name.startsWith("is")) { - key = name.substring(2); - } - if (key.length() > 0 - && Character.isUpperCase(key.charAt(0)) - && method.getParameterTypes().length == 0) { - if (key.length() == 1) { - key = key.toLowerCase(); - } else if (!Character.isUpperCase(key.charAt(1))) { - key = key.substring(0, 1).toLowerCase() - + key.substring(1); - } - - Object result = method.invoke(bean, (Object[]) null); - if (result != null) { - this.map.put(key, wrap(result)); - } - } - } - } catch (Exception ignore) { - } - } - } - - /** - * Put a key/boolean pair in the JSONObject. - * - * @param key - * A key string. - * @param value - * A boolean which is the value. - * @return this. - * @throws JSONException - * If the key is null. - */ - public JSONObject put(String key, boolean value) throws JSONException { - this.put(key, value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - /** - * Put a key/value pair in the JSONObject, where the value will be a - * JSONArray which is produced from a Collection. - * - * @param key - * A key string. - * @param value - * A Collection value. - * @return this. - * @throws JSONException - */ - public JSONObject put(String key, Collection value) throws JSONException { - this.put(key, new JSONArray(value)); - return this; - } - - /** - * Put a key/double pair in the JSONObject. - * - * @param key - * A key string. - * @param value - * A double which is the value. - * @return this. - * @throws JSONException - * If the key is null or if the number is invalid. - */ - public JSONObject put(String key, double value) throws JSONException { - this.put(key, new Double(value)); - return this; - } - - /** - * Put a key/int pair in the JSONObject. - * - * @param key - * A key string. - * @param value - * An int which is the value. - * @return this. - * @throws JSONException - * If the key is null. - */ - public JSONObject put(String key, int value) throws JSONException { - this.put(key, new Integer(value)); - return this; - } - - /** - * Put a key/long pair in the JSONObject. - * - * @param key - * A key string. - * @param value - * A long which is the value. - * @return this. - * @throws JSONException - * If the key is null. - */ - public JSONObject put(String key, long value) throws JSONException { - this.put(key, new Long(value)); - return this; - } - - /** - * Put a key/value pair in the JSONObject, where the value will be a - * JSONObject which is produced from a Map. - * - * @param key - * A key string. - * @param value - * A Map value. - * @return this. - * @throws JSONException - */ - public JSONObject put(String key, Map value) throws JSONException { - this.put(key, new JSONObject(value)); - return this; - } - - /** - * Put a key/value pair in the JSONObject. If the value is null, then the - * key will be removed from the JSONObject if it is present. - * - * @param key - * A key string. - * @param value - * An object which is the value. It should be of one of these - * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, - * String, or the JSONObject.NULL object. - * @return this. - * @throws JSONException - * If the value is non-finite number or if the key is null. - */ - public JSONObject put(String key, Object value) throws JSONException { - if (key == null) { - throw new NullPointerException("Null key."); - } - if (value != null) { - testValidity(value); - this.map.put(key, value); - } else { - this.remove(key); - } - return this; - } - - /** - * Put a key/value pair in the JSONObject, but only if the key and the value - * are both non-null, and only if there is not already a member with that - * name. - * - * @param key string - * @param value object - * @return this. - * @throws JSONException - * if the key is a duplicate - */ - public JSONObject putOnce(String key, Object value) throws JSONException { - if (key != null && value != null) { - if (this.opt(key) != null) { - throw new JSONException("Duplicate key \"" + key + "\""); - } - this.put(key, value); - } - return this; - } - - /** - * Put a key/value pair in the JSONObject, but only if the key and the value - * are both non-null. - * - * @param key - * A key string. - * @param value - * An object which is the value. It should be of one of these - * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, - * String, or the JSONObject.NULL object. - * @return this. - * @throws JSONException - * If the value is a non-finite number. - */ - public JSONObject putOpt(String key, Object value) throws JSONException { - if (key != null && value != null) { - this.put(key, value); - } - return this; - } - - /** - * Produce a string in double quotes with backslash sequences in all the - * right places. A backslash will be inserted within = '\u0080' && c < '\u00a0') - || (c >= '\u2000' && c < '\u2100')) { - w.write("\\u"); - hhhh = Integer.toHexString(c); - w.write("0000", 0, 4 - hhhh.length()); - w.write(hhhh); - } else { - w.write(c); - } - } - } - w.write('"'); - return w; - } - - /** - * Remove a name and its value, if present. - * - * @param key - * The name to be removed. - * @return The value that was associated with the name, or null if there was - * no value. - */ - public Object remove(String key) { - return this.map.remove(key); - } - - /** - * Determine if two JSONObjects are similar. - * They must contain the same set of names which must be associated with - * similar values. - * - * @param other The other JSONObject - * @return true if they are equal - */ - public boolean similar(Object other) { - try { - if (!(other instanceof JSONObject)) { - return false; - } - Set set = this.keySet(); - if (!set.equals(((JSONObject)other).keySet())) { - return false; - } - Iterator iterator = set.iterator(); - while (iterator.hasNext()) { - String name = iterator.next(); - Object valueThis = this.get(name); - Object valueOther = ((JSONObject)other).get(name); - if (valueThis instanceof JSONObject) { - if (!((JSONObject)valueThis).similar(valueOther)) { - return false; - } - } else if (valueThis instanceof JSONArray) { - if (!((JSONArray)valueThis).similar(valueOther)) { - return false; - } - } else if (!valueThis.equals(valueOther)) { - return false; - } - } - return true; - } catch (Throwable exception) { - return false; - } - } - - /** - * Try to convert a string into a number, boolean, or null. If the string - * can't be converted, return the string. - * - * @param string - * A String. - * @return A simple JSON value. - */ - public static Object stringToValue(String string) { - Double d; - if (string.equals("")) { - return string; - } - if (string.equalsIgnoreCase("true")) { - return Boolean.TRUE; - } - if (string.equalsIgnoreCase("false")) { - return Boolean.FALSE; - } - if (string.equalsIgnoreCase("null")) { - return JSONObject.NULL; - } - - /* - * If it might be a number, try converting it. If a number cannot be - * produced, then the value will just be a string. - */ - - char b = string.charAt(0); - if ((b >= '0' && b <= '9') || b == '-') { - try { - if (string.indexOf('.') > -1 || string.indexOf('e') > -1 - || string.indexOf('E') > -1) { - d = Double.valueOf(string); - if (!d.isInfinite() && !d.isNaN()) { - return d; - } - } else { - Long myLong = new Long(string); - if (string.equals(myLong.toString())) { - if (myLong == myLong.intValue()) { - return myLong.intValue(); - } else { - return myLong; - } - } - } - } catch (Exception ignore) { - } - } - return string; - } - - /** - * Throw an exception if the object is a NaN or infinite number. - * - * @param o - * The object to test. - * @throws JSONException - * If o is a non-finite number. - */ - public static void testValidity(Object o) throws JSONException { - if (o != null) { - if (o instanceof Double) { - if (((Double) o).isInfinite() || ((Double) o).isNaN()) { - throw new JSONException( - "JSON does not allow non-finite numbers."); - } - } else if (o instanceof Float) { - if (((Float) o).isInfinite() || ((Float) o).isNaN()) { - throw new JSONException( - "JSON does not allow non-finite numbers."); - } - } - } - } - - /** - * Produce a JSONArray containing the values of the members of this - * JSONObject. - * - * @param names - * A JSONArray containing a list of key strings. This determines - * the sequence of the values in the result. - * @return A JSONArray of values. - * @throws JSONException - * If any of the values are non-finite numbers. - */ - public JSONArray toJSONArray(JSONArray names) throws JSONException { - if (names == null || names.length() == 0) { - return null; - } - JSONArray ja = new JSONArray(); - for (int i = 0; i < names.length(); i += 1) { - ja.put(this.opt(names.getString(i))); - } - return ja; - } - - /** - * Make a JSON text of this JSONObject. For compactness, no whitespace is - * added. If this would not result in a syntactically correct JSON text, - * then null will be returned instead. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return a printable, displayable, portable, transmittable representation - * of the object, beginning with { (left - * brace) and ending with } (right - * brace). - */ - public String toString() { - try { - return this.toString(0); - } catch (Exception e) { - return null; - } - } - - /** - * Make a prettyprinted JSON text of this JSONObject. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @param indentFactor - * The number of spaces to add to each level of indentation. - * @return a printable, displayable, portable, transmittable representation - * of the object, beginning with { (left - * brace) and ending with } (right - * brace). - * @throws JSONException - * If the object contains an invalid number. - */ - public String toString(int indentFactor) throws JSONException { - StringWriter w = new StringWriter(); - synchronized (w.getBuffer()) { - return this.write(w, indentFactor, 0).toString(); - } - } - - /** - * Make a JSON text of an Object value. If the object has an - * value.toJSONString() method, then that method will be used to produce the - * JSON text. The method is required to produce a strictly conforming text. - * If the object does not contain a toJSONString method (which is the most - * common case), then a text will be produced by other means. If the value - * is an array or Collection, then a JSONArray will be made from it and its - * toJSONString method will be called. If the value is a MAP, then a - * JSONObject will be made from it and its toJSONString method will be - * called. Otherwise, the value's toString method will be called, and the - * result will be quoted. - * - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @param value - * The value to be serialized. - * @return a printable, displayable, transmittable representation of the - * object, beginning with { (left - * brace) and ending with } (right - * brace). - * @throws JSONException - * If the value is or contains an invalid number. - */ - public static String valueToString(Object value) throws JSONException { - if (value == null || value.equals(null)) { - return "null"; - } - if (value instanceof JSONString) { - Object object; - try { - object = ((JSONString) value).toJSONString(); - } catch (Exception e) { - throw new JSONException(e); - } - if (object instanceof String) { - return (String) object; - } - throw new JSONException("Bad value from toJSONString: " + object); - } - if (value instanceof Number) { - return numberToString((Number) value); - } - if (value instanceof Boolean || value instanceof JSONObject - || value instanceof JSONArray) { - return value.toString(); - } - if (value instanceof Map) { - @SuppressWarnings("unchecked") - Map map = (Map) value; - return new JSONObject(map).toString(); - } - if (value instanceof Collection) { - @SuppressWarnings("unchecked") - Collection coll = (Collection) value; - return new JSONArray(coll).toString(); - } - if (value.getClass().isArray()) { - return new JSONArray(value).toString(); - } - return quote(value.toString()); - } - - /** - * Wrap an object, if necessary. If the object is null, return the NULL - * object. If it is an array or collection, wrap it in a JSONArray. If it is - * a map, wrap it in a JSONObject. If it is a standard property (Double, - * String, et al) then it is already wrapped. Otherwise, if it comes from - * one of the java packages, turn it into a string. And if it doesn't, try - * to wrap it in a JSONObject. If the wrapping fails, then null is returned. - * - * @param object - * The object to wrap - * @return The wrapped value - */ - public static Object wrap(Object object) { - try { - if (object == null) { - return NULL; - } - if (object instanceof JSONObject || object instanceof JSONArray - || NULL.equals(object) || object instanceof JSONString - || object instanceof Byte || object instanceof Character - || object instanceof Short || object instanceof Integer - || object instanceof Long || object instanceof Boolean - || object instanceof Float || object instanceof Double - || object instanceof String || object instanceof BigInteger - || object instanceof BigDecimal) { - return object; - } - - if (object instanceof Collection) { - @SuppressWarnings("unchecked") - Collection coll = (Collection) object; - return new JSONArray(coll); - } - if (object.getClass().isArray()) { - return new JSONArray(object); - } - if (object instanceof Map) { - @SuppressWarnings("unchecked") - Map map = (Map) object; - return new JSONObject(map); - } - Package objectPackage = object.getClass().getPackage(); - String objectPackageName = objectPackage != null ? objectPackage - .getName() : ""; - if (objectPackageName.startsWith("java.") - || objectPackageName.startsWith("javax.") - || object.getClass().getClassLoader() == null) { - return object.toString(); - } - return new JSONObject(object); - } catch (Exception exception) { - return null; - } - } - - /** - * Write the contents of the JSONObject as JSON text to a writer. For - * compactness, no whitespace is added. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer) throws JSONException { - return this.write(writer, 0, 0); - } - - static final Writer writeValue(Writer writer, Object value, - int indentFactor, int indent) throws JSONException, IOException { - if (value == null || value.equals(null)) { - writer.write("null"); - } else if (value instanceof JSONObject) { - ((JSONObject) value).write(writer, indentFactor, indent); - } else if (value instanceof JSONArray) { - ((JSONArray) value).write(writer, indentFactor, indent); - } else if (value instanceof Map) { - @SuppressWarnings("unchecked") - Map map = (Map) value; - new JSONObject(map).write(writer, indentFactor, indent); - } else if (value instanceof Collection) { - @SuppressWarnings("unchecked") - Collection coll = (Collection) value; - new JSONArray(coll).write(writer, indentFactor, - indent); - } else if (value.getClass().isArray()) { - new JSONArray(value).write(writer, indentFactor, indent); - } else if (value instanceof Number) { - writer.write(numberToString((Number) value)); - } else if (value instanceof Boolean) { - writer.write(value.toString()); - } else if (value instanceof JSONString) { - Object o; - try { - o = ((JSONString) value).toJSONString(); - } catch (Exception e) { - throw new JSONException(e); - } - writer.write(o != null ? o.toString() : quote(value.toString())); - } else { - quote(value.toString(), writer); - } - return writer; - } - - static final void indent(Writer writer, int indent) throws IOException { - for (int i = 0; i < indent; i += 1) { - writer.write(' '); - } - } - - /** - * Write the contents of the JSONObject as JSON text to a writer. For - * compactness, no whitespace is added. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - Writer write(Writer writer, int indentFactor, int indent) - throws JSONException { - try { - boolean commanate = false; - final int length = this.length(); - Iterator keys = this.keys(); - writer.write('{'); - - if (length == 1) { - Object key = keys.next(); - writer.write(quote(key.toString())); - writer.write(':'); - if (indentFactor > 0) { - writer.write(' '); - } - writeValue(writer, this.map.get(key), indentFactor, indent); - } else if (length != 0) { - final int newindent = indent + indentFactor; - while (keys.hasNext()) { - Object key = keys.next(); - if (commanate) { - writer.write(','); - } - if (indentFactor > 0) { - writer.write('\n'); - } - indent(writer, newindent); - writer.write(quote(key.toString())); - writer.write(':'); - if (indentFactor > 0) { - writer.write(' '); - } - writeValue(writer, this.map.get(key), indentFactor, newindent); - commanate = true; - } - if (indentFactor > 0) { - writer.write('\n'); - } - indent(writer, indent); - } - writer.write('}'); - return writer; - } catch (IOException exception) { - throw new JSONException(exception); - } - } -} +/* + * $Id: JSONObject.java,v 1.1 2006/04/15 14:10:48 platform Exp $ + * Created on 2006-4-10 + */ +package blade.kit.json; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * A JSON object. Key value pairs are unordered. JSONObject supports java.util.Map interface. + * + * @author FangYidong + */ +@SuppressWarnings("rawtypes") +public class JSONObject extends HashMap implements Map, JSONAware, JSONStreamAware{ + + private static final long serialVersionUID = -503443796854799292L; + + + public JSONObject() { + super(); + } + + /** + * Allows creation of a JSONObject from a Map. After that, both the + * generated JSONObject and the Map can be modified independently. + * + * @param map + */ + @SuppressWarnings("unchecked") + public JSONObject(Map map) { + super(map); + } + + public Object get(String key) throws JSONException { + if (key == null) { + throw new JSONException("Null key."); + } + Object object = this.get(key); + if (object == null) { + throw new JSONException("JSONObject[" + quote(key) + "] not found."); + } + return object; + } + + public String getString(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof String) { + return (String) object; + } + throw new JSONException("JSONObject[" + quote(key) + "] not a string."); + } + + public int getInt(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number ? ((Number) object).intValue() : Integer.parseInt((String) object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + "] is not an int."); + } + } + + /** + * Get the boolean value associated with a key. + * + * @param key + * A key string. + * @return The truth. + * @throws JSONException + * if the value is not a Boolean or the String "true" or + * "false". + */ + public boolean getBoolean(String key) throws JSONException { + Object object = this.get(key); + if (object.equals(Boolean.FALSE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("false"))) { + return false; + } else if (object.equals(Boolean.TRUE) + || (object instanceof String && ((String) object) + .equalsIgnoreCase("true"))) { + return true; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a Boolean."); + } + + /** + * Get the BigInteger value associated with a key. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value cannot + * be converted to BigInteger. + */ + public BigInteger getBigInteger(String key) throws JSONException { + Object object = this.get(key); + try { + return new BigInteger(object.toString()); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] could not be converted to BigInteger."); + } + } + + /** + * Get the BigDecimal value associated with a key. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value + * cannot be converted to BigDecimal. + */ + public BigDecimal getBigDecimal(String key) throws JSONException { + Object object = this.get(key); + try { + return new BigDecimal(object.toString()); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] could not be converted to BigDecimal."); + } + } + + /** + * Get the double value associated with a key. + * + * @param key + * A key string. + * @return The numeric value. + * @throws JSONException + * if the key is not found or if the value is not a Number + * object and cannot be converted to a number. + */ + public double getDouble(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number ? ((Number) object).doubleValue() + : Double.parseDouble((String) object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not a number."); + } + } + + public JSONArray getJSONArray(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof JSONArray) { + return (JSONArray) object; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a JSONArray."); + } + + public JSONObject getJSONObject(String key) throws JSONException { + Object object = this.get(key); + if (object instanceof JSONObject) { + return (JSONObject) object; + } + throw new JSONException("JSONObject[" + quote(key) + + "] is not a JSONObject."); + } + + public long getLong(String key) throws JSONException { + Object object = this.get(key); + try { + return object instanceof Number ? ((Number) object).longValue() + : Long.parseLong((String) object); + } catch (Exception e) { + throw new JSONException("JSONObject[" + quote(key) + + "] is not a long."); + } + } + + public static String quote(String string) { + StringWriter sw = new StringWriter(); + synchronized (sw.getBuffer()) { + try { + return quote(string, sw).toString(); + } catch (IOException ignored) { + // will never happen - we are writing to a string writer + return ""; + } + } + } + + public static Writer quote(String string, Writer w) throws IOException { + if (string == null || string.length() == 0) { + w.write("\"\""); + return w; + } + + char b; + char c = 0; + String hhhh; + int i; + int len = string.length(); + + w.write('"'); + for (i = 0; i < len; i += 1) { + b = c; + c = string.charAt(i); + switch (c) { + case '\\': + case '"': + w.write('\\'); + w.write(c); + break; + case '/': + if (b == '<') { + w.write('\\'); + } + w.write(c); + break; + case '\b': + w.write("\\b"); + break; + case '\t': + w.write("\\t"); + break; + case '\n': + w.write("\\n"); + break; + case '\f': + w.write("\\f"); + break; + case '\r': + w.write("\\r"); + break; + default: + if (c < ' ' || (c >= '\u0080' && c < '\u00a0') + || (c >= '\u2000' && c < '\u2100')) { + w.write("\\u"); + hhhh = Integer.toHexString(c); + w.write("0000", 0, 4 - hhhh.length()); + w.write(hhhh); + } else { + w.write(c); + } + } + } + w.write('"'); + return w; + } + + /** + * Encode a map into JSON text and write it to out. + * If this map is also a JSONAware or JSONStreamAware, JSONAware or JSONStreamAware specific behaviours will be ignored at this top level. + * + * @see blade.kit.json2.JSONValue#writeJSONString(Object, Writer) + * + * @param map + * @param out + */ + public static void writeJSONString(Map map, Writer out) throws IOException { + if(map == null){ + out.write("null"); + return; + } + + boolean first = true; + Iterator iter=map.entrySet().iterator(); + + out.write('{'); + while(iter.hasNext()){ + if(first) + first = false; + else + out.write(','); + Map.Entry entry=(Map.Entry)iter.next(); + out.write('\"'); + out.write(escape(String.valueOf(entry.getKey()))); + out.write('\"'); + out.write(':'); + JSONValue.writeJSONString(entry.getValue(), out); + } + out.write('}'); + } + + public void writeJSONString(Writer out) throws IOException{ + writeJSONString(this, out); + } + + /** + * Convert a map to JSON text. The result is a JSON object. + * If this map is also a JSONAware, JSONAware specific behaviours will be omitted at this top level. + * + * @see blade.kit.json2.JSONValue#toJSONString(Object) + * + * @param map + * @return JSON text, or "null" if map is null. + */ + public static String toJSONString(Map map){ + final StringWriter writer = new StringWriter(); + + try { + writeJSONString(map, writer); + return writer.toString(); + } catch (IOException e) { + // This should never happen with a StringWriter + throw new RuntimeException(e); + } + } + + public String toJSONString(){ + return toJSONString(this); + } + + public String toString(){ + return toJSONString(); + } + + public static String toString(String key,Object value){ + StringBuffer sb = new StringBuffer(); + sb.append('\"'); + if(key == null) + sb.append("null"); + else + JSONValue.escape(key, sb); + sb.append('\"').append(':'); + + sb.append(JSONValue.toJSONString(value)); + + return sb.toString(); + } + + /** + * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F). + * It's the same as JSONValue.escape() only for compatibility here. + * + * @see blade.kit.json2.JSONValue#escape(String) + * + * @param s + * @return + */ + public static String escape(String s){ + return JSONValue.escape(s); + } +} diff --git a/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java b/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java index 76c37b375..53aa349da 100644 --- a/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java +++ b/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java @@ -68,8 +68,8 @@ public void log(int level, Object message, Throwable t, Object... args) { outprint.println(sb.toString()); if (t != null) { t.printStackTrace(System.err); + System.err.flush(); } - } } From da5d3b08d2b28290dc62ada1c00b3fdbd6ffb1f7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 09:49:40 +0800 Subject: [PATCH 170/545] optimize log and exception --- .../java/blade/kit/base/ThrowableKit.java | 185 +++++ .../main/java/blade/kit/json/ItemList.java | 149 ++++ .../main/java/blade/kit/json/JSONAware.java | 12 + .../java/blade/kit/json/JSONStreamAware.java | 15 + .../main/java/blade/kit/json/JSONValue.java | 262 +++++++ .../kit/json/parse/ContainerFactory.java | 24 + .../blade/kit/json/parse/ContentHandler.java | 110 +++ .../java/blade/kit/json/parse/JSONParser.java | 534 ++++++++++++++ .../blade/kit/json/parse/ParseException.java | 90 +++ .../main/java/blade/kit/json/parse/Yylex.java | 689 ++++++++++++++++++ .../java/blade/kit/json/parse/Yytoken.java | 58 ++ .../main/java/blade/kit/log/JdkLogger.java | 76 ++ .../java/blade/kit/log/JdkLoggerFactory.java | 12 + .../src/main/java/blade/kit/log/Level.java | 22 + .../main/java/blade/kit/log/Log4jLogger.java | 186 +++++ .../blade/kit/log/Log4jLoggerFactory.java | 12 + .../src/main/java/blade/kit/log/Logger.java | 141 ++-- .../java/blade/kit/log/LoggerFactory.java | 8 + .../main/java/blade/kit/log/SimpleLogger.java | 75 ++ .../blade/kit/log/SimpleLoggerFactory.java | 12 + .../src/test/java/blade/test/LogTest.java | 14 +- 21 files changed, 2607 insertions(+), 79 deletions(-) create mode 100644 blade-kit/src/main/java/blade/kit/base/ThrowableKit.java create mode 100644 blade-kit/src/main/java/blade/kit/json/ItemList.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONAware.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONStreamAware.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONValue.java create mode 100644 blade-kit/src/main/java/blade/kit/json/parse/ContainerFactory.java create mode 100644 blade-kit/src/main/java/blade/kit/json/parse/ContentHandler.java create mode 100644 blade-kit/src/main/java/blade/kit/json/parse/JSONParser.java create mode 100644 blade-kit/src/main/java/blade/kit/json/parse/ParseException.java create mode 100644 blade-kit/src/main/java/blade/kit/json/parse/Yylex.java create mode 100644 blade-kit/src/main/java/blade/kit/json/parse/Yytoken.java create mode 100644 blade-kit/src/main/java/blade/kit/log/JdkLogger.java create mode 100644 blade-kit/src/main/java/blade/kit/log/JdkLoggerFactory.java create mode 100644 blade-kit/src/main/java/blade/kit/log/Level.java create mode 100644 blade-kit/src/main/java/blade/kit/log/Log4jLogger.java create mode 100644 blade-kit/src/main/java/blade/kit/log/Log4jLoggerFactory.java create mode 100644 blade-kit/src/main/java/blade/kit/log/LoggerFactory.java create mode 100644 blade-kit/src/main/java/blade/kit/log/SimpleLogger.java create mode 100644 blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java diff --git a/blade-kit/src/main/java/blade/kit/base/ThrowableKit.java b/blade-kit/src/main/java/blade/kit/base/ThrowableKit.java new file mode 100644 index 000000000..2557fb968 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/base/ThrowableKit.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * 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 blade.kit.base; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import blade.kit.Assert; + + +/** + * Static utility methods pertaining to instances of {@link Throwable}. + * + *

See the Guava User Guide entry on + * Throwables. + * + * @author Kevin Bourrillion + * @author Ben Yu + * @since 1.0 + */ +public final class ThrowableKit { + private ThrowableKit() {} + + /** + * Propagates {@code throwable} exactly as-is, if and only if it is an + * instance of {@code declaredType}. Example usage: + *

+   *   try {
+   *     someMethodThatCouldThrowAnything();
+   *   } catch (IKnowWhatToDoWithThisException e) {
+   *     handle(e);
+   *   } catch (Throwable t) {
+   *     Throwables.propagateIfInstanceOf(t, IOException.class);
+   *     Throwables.propagateIfInstanceOf(t, SQLException.class);
+   *     throw Throwables.propagate(t);
+   *   }
+   * 
+ */ + public static void propagateIfInstanceOf(Throwable throwable, Class declaredType) throws X { + // Check for null is needed to avoid frequent JNI calls to isInstance(). + if (throwable != null && declaredType.isInstance(throwable)) { + throw declaredType.cast(throwable); + } + } + + /** + * Propagates {@code throwable} exactly as-is, if and only if it is an + * instance of {@link RuntimeException} or {@link Error}. Example usage: + *
+   *   try {
+   *     someMethodThatCouldThrowAnything();
+   *   } catch (IKnowWhatToDoWithThisException e) {
+   *     handle(e);
+   *   } catch (Throwable t) {
+   *     Throwables.propagateIfPossible(t);
+   *     throw new RuntimeException("unexpected", t);
+   *   }
+   * 
+ */ + public static void propagateIfPossible(Throwable throwable) { + propagateIfInstanceOf(throwable, Error.class); + propagateIfInstanceOf(throwable, RuntimeException.class); + } + + /** + * Propagates {@code throwable} exactly as-is, if and only if it is an + * instance of {@link RuntimeException}, {@link Error}, or + * {@code declaredType}. Example usage: + *
+   *   try {
+   *     someMethodThatCouldThrowAnything();
+   *   } catch (IKnowWhatToDoWithThisException e) {
+   *     handle(e);
+   *   } catch (Throwable t) {
+   *     Throwables.propagateIfPossible(t, OtherException.class);
+   *     throw new RuntimeException("unexpected", t);
+   *   }
+   * 
+ * + * @param throwable the Throwable to possibly propagate + * @param declaredType the single checked exception type declared by the + * calling method + */ + public static void propagateIfPossible( + Throwable throwable, Class declaredType) throws X { + propagateIfInstanceOf(throwable, declaredType); + propagateIfPossible(throwable); + } + + /** + * Propagates {@code throwable} exactly as-is, if and only if it is an + * instance of {@link RuntimeException}, {@link Error}, {@code declaredType1}, + * or {@code declaredType2}. In the unlikely case that you have three or more + * declared checked exception types, you can handle them all by invoking these + * methods repeatedly. See usage example in {@link + * #propagateIfPossible(Throwable, Class)}. + * + * @param throwable the Throwable to possibly propagate + * @param declaredType1 any checked exception type declared by the calling + * method + * @param declaredType2 any other checked exception type declared by the + * calling method + */ + public static + void propagateIfPossible(Throwable throwable, + Class declaredType1, Class declaredType2) throws X1, X2 { + Assert.notNull(declaredType2); + propagateIfInstanceOf(throwable, declaredType1); + propagateIfPossible(throwable, declaredType2); + } + + /** + * Propagates {@code throwable} as-is if it is an instance of + * {@link RuntimeException} or {@link Error}, or else as a last resort, wraps + * it in a {@code RuntimeException} then propagates. + *

+ * This method always throws an exception. The {@code RuntimeException} return + * type is only for client code to make Java type system happy in case a + * return value is required by the enclosing method. Example usage: + *

+   *   T doSomething() {
+   *     try {
+   *       return someMethodThatCouldThrowAnything();
+   *     } catch (IKnowWhatToDoWithThisException e) {
+   *       return handle(e);
+   *     } catch (Throwable t) {
+   *       throw Throwables.propagate(t);
+   *     }
+   *   }
+   * 
+ * + * @param throwable the Throwable to propagate + * @return nothing will ever be returned; this return type is only for your + * convenience, as illustrated in the example above + */ + public static RuntimeException propagate(Throwable throwable) { + propagateIfPossible(Assert.checkNotNull(throwable)); + throw new RuntimeException(throwable); + } + + /** + * Returns the innermost cause of {@code throwable}. The first throwable in a + * chain provides context from when the error or exception was initially + * detected. Example usage: + *
+   *   assertEquals("Unable to assign a customer id",
+   *       Throwables.getRootCause(e).getMessage());
+   * 
+ */ + public static Throwable getRootCause(Throwable throwable) { + Throwable cause; + while ((cause = throwable.getCause()) != null) { + throwable = cause; + } + return throwable; + } + + /** + * Returns a string containing the result of + * {@link Throwable#toString() toString()}, followed by the full, recursive + * stack trace of {@code throwable}. Note that you probably should not be + * parsing the resulting string; if you need programmatic access to the stack + * frames, you can call {@link Throwable#getStackTrace()}. + */ + public static String getStackTraceAsString(Throwable throwable) { + StringWriter stringWriter = new StringWriter(); + throwable.printStackTrace(new PrintWriter(stringWriter)); + return stringWriter.toString(); + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/ItemList.java b/blade-kit/src/main/java/blade/kit/json/ItemList.java new file mode 100644 index 000000000..2dc7e7374 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/ItemList.java @@ -0,0 +1,149 @@ +/* + * $Id: ItemList.java,v 1.1 2006/04/15 14:10:48 platform Exp $ + * Created on 2006-3-24 + */ +package blade.kit.json; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +/** + * |a:b:c| => |a|,|b|,|c| + * |:| => ||,|| + * |a:| => |a|,|| + * @author FangYidong + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public class ItemList { + private String sp=","; + + List items = new ArrayList(); + + + public ItemList(){} + + + public ItemList(String s){ + this.split(s,sp,items); + } + + public ItemList(String s,String sp){ + this.sp=s; + this.split(s,sp,items); + } + + public ItemList(String s,String sp,boolean isMultiToken){ + split(s,sp,items,isMultiToken); + } + + public List getItems(){ + return this.items; + } + + public String[] getArray(){ + return (String[])this.items.toArray(); + } + + public void split(String s,String sp,List append,boolean isMultiToken){ + if(s==null || sp==null) + return; + if(isMultiToken){ + StringTokenizer tokens=new StringTokenizer(s,sp); + while(tokens.hasMoreTokens()){ + append.add(tokens.nextToken().trim()); + } + } + else{ + this.split(s,sp,append); + } + } + + public void split(String s,String sp, List append){ + if(s==null || sp==null) + return; + int pos=0; + int prevPos=0; + do{ + prevPos=pos; + pos=s.indexOf(sp,pos); + if(pos==-1) + break; + append.add(s.substring(prevPos,pos).trim()); + pos+=sp.length(); + }while(pos!=-1); + append.add(s.substring(prevPos).trim()); + } + + public void setSP(String sp){ + this.sp=sp; + } + + public void add(int i,String item){ + if(item==null) + return; + items.add(i,item.trim()); + } + + public void add(String item){ + if(item==null) + return; + items.add(item.trim()); + } + + public void addAll(ItemList list){ + items.addAll(list.items); + } + + public void addAll(String s){ + this.split(s,sp,items); + } + + public void addAll(String s,String sp){ + this.split(s,sp,items); + } + + public void addAll(String s,String sp,boolean isMultiToken){ + this.split(s,sp,items,isMultiToken); + } + + /** + * @param i 0-based + * @return + */ + public String get(int i){ + return (String)items.get(i); + } + + public int size(){ + return items.size(); + } + + public String toString(){ + return toString(sp); + } + + public String toString(String sp){ + StringBuffer sb=new StringBuffer(); + + for(int i=0;i + */ +public interface JSONAware { + /** + * @return JSON text + */ + String toJSONString(); +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONStreamAware.java b/blade-kit/src/main/java/blade/kit/json/JSONStreamAware.java new file mode 100644 index 000000000..75c7c07a0 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONStreamAware.java @@ -0,0 +1,15 @@ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; + +/** + * Beans that support customized output of JSON text to a writer shall implement this interface. + * @author FangYidong + */ +public interface JSONStreamAware { + /** + * write JSON string to out. + */ + void writeJSONString(Writer out) throws IOException; +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONValue.java b/blade-kit/src/main/java/blade/kit/json/JSONValue.java new file mode 100644 index 000000000..7193140c3 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONValue.java @@ -0,0 +1,262 @@ +/* + * $Id: JSONValue.java,v 1.1 2006/04/15 14:37:04 platform Exp $ + * Created on 2006-4-15 + */ +package blade.kit.json; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.Collection; +import java.util.List; +// import java.util.List; +import java.util.Map; + +import blade.kit.json.parse.JSONParser; +import blade.kit.json.parse.ParseException; + +/** + * @author FangYidong + */ +@SuppressWarnings({"rawtypes"}) +public class JSONValue { + + /** + * Parse JSON text into java object from the input source. + * + * @see org.json.simple.parser.JSONParser + * + * @param in + * @return Instance of the following: + * org.json.simple.JSONObject, + * org.json.simple.JSONArray, + * java.lang.String, + * java.lang.Number, + * java.lang.Boolean, + * null + * + * @throws IOException + * @throws ParseException + */ + public static Object parse(Reader in) throws IOException, ParseException{ + JSONParser parser=new JSONParser(); + return parser.parse(in); + } + + public static Object parse(String s) throws ParseException{ + JSONParser parser=new JSONParser(); + return parser.parse(s); + } + + /** + * Encode an object into JSON text and write it to out. + *

+ * If this object is a Map or a List, and it's also a JSONStreamAware or a JSONAware, JSONStreamAware or JSONAware will be considered firstly. + *

+ * DO NOT call this method from writeJSONString(Writer) of a class that implements both JSONStreamAware and (Map or List) with + * "this" as the first parameter, use JSONObject.writeJSONString(Map, Writer) or JSONArray.writeJSONString(List, Writer) instead. + * + * @see blade.kit.json2.JSONObject#writeJSONString(Map, Writer) + * @see blade.kit.json2.JSONArray#writeJSONString(List, Writer) + * + * @param value + * @param writer + */ + public static void writeJSONString(Object value, Writer out) throws IOException { + if(value == null){ + out.write("null"); + return; + } + + if(value instanceof String){ + out.write('\"'); + out.write(escape((String)value)); + out.write('\"'); + return; + } + + if(value instanceof Double){ + if(((Double)value).isInfinite() || ((Double)value).isNaN()) + out.write("null"); + else + out.write(value.toString()); + return; + } + + if(value instanceof Float){ + if(((Float)value).isInfinite() || ((Float)value).isNaN()) + out.write("null"); + else + out.write(value.toString()); + return; + } + + if(value instanceof Number){ + out.write(value.toString()); + return; + } + + if(value instanceof Boolean){ + out.write(value.toString()); + return; + } + + if((value instanceof JSONStreamAware)){ + ((JSONStreamAware)value).writeJSONString(out); + return; + } + + if((value instanceof JSONAware)){ + out.write(((JSONAware)value).toJSONString()); + return; + } + + if(value instanceof Map){ + JSONObject.writeJSONString((Map)value, out); + return; + } + + if(value instanceof Collection){ + JSONArray.writeJSONString((Collection)value, out); + return; + } + + if(value instanceof byte[]){ + JSONArray.writeJSONString((byte[])value, out); + return; + } + + if(value instanceof short[]){ + JSONArray.writeJSONString((short[])value, out); + return; + } + + if(value instanceof int[]){ + JSONArray.writeJSONString((int[])value, out); + return; + } + + if(value instanceof long[]){ + JSONArray.writeJSONString((long[])value, out); + return; + } + + if(value instanceof float[]){ + JSONArray.writeJSONString((float[])value, out); + return; + } + + if(value instanceof double[]){ + JSONArray.writeJSONString((double[])value, out); + return; + } + + if(value instanceof boolean[]){ + JSONArray.writeJSONString((boolean[])value, out); + return; + } + + if(value instanceof char[]){ + JSONArray.writeJSONString((char[])value, out); + return; + } + + if(value instanceof Object[]){ + JSONArray.writeJSONString((Object[])value, out); + return; + } + + out.write(value.toString()); + } + + /** + * Convert an object to JSON text. + *

+ * If this object is a Map or a List, and it's also a JSONAware, JSONAware will be considered firstly. + *

+ * DO NOT call this method from toJSONString() of a class that implements both JSONAware and Map or List with + * "this" as the parameter, use JSONObject.toJSONString(Map) or JSONArray.toJSONString(List) instead. + * + * @see blade.kit.json2.JSONObject#toJSONString(Map) + * @see blade.kit.json2.JSONArray#toJSONString(List) + * + * @param value + * @return JSON text, or "null" if value is null or it's an NaN or an INF number. + */ + public static String toJSONString(Object value){ + final StringWriter writer = new StringWriter(); + + try{ + writeJSONString(value, writer); + return writer.toString(); + } catch(IOException e){ + // This should never happen for a StringWriter + throw new RuntimeException(e); + } + } + + /** + * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F). + * @param s + * @return + */ + public static String escape(String s){ + if(s==null) + return null; + StringBuffer sb = new StringBuffer(); + escape(s, sb); + return sb.toString(); + } + + /** + * @param s - Must not be null. + * @param sb + */ + static void escape(String s, StringBuffer sb) { + final int len = s.length(); + for(int i=0;i='\u0000' && ch<='\u001F') || (ch>='\u007F' && ch<='\u009F') || (ch>='\u2000' && ch<='\u20FF')){ + String ss=Integer.toHexString(ch); + sb.append("\\u"); + for(int k=0;k<4-ss.length();k++){ + sb.append('0'); + } + sb.append(ss.toUpperCase()); + } + else{ + sb.append(ch); + } + } + }//for + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/ContainerFactory.java b/blade-kit/src/main/java/blade/kit/json/parse/ContainerFactory.java new file mode 100644 index 000000000..c25f98a96 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/parse/ContainerFactory.java @@ -0,0 +1,24 @@ +package blade.kit.json.parse; + +import java.util.List; +import java.util.Map; + +/** + * Container factory for creating containers for JSON object and JSON array. + * + * @see org.json.simple.parser.JSONParser#parse(java.io.Reader, ContainerFactory) + * + * @author FangYidong + */ +@SuppressWarnings({"rawtypes"}) +public interface ContainerFactory { + /** + * @return A Map instance to store JSON object, or null if you want to use org.json.simple.JSONObject. + */ + Map createObjectContainer(); + + /** + * @return A List instance to store JSON array, or null if you want to use org.json.simple.JSONArray. + */ + List creatArrayContainer(); +} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/ContentHandler.java b/blade-kit/src/main/java/blade/kit/json/parse/ContentHandler.java new file mode 100644 index 000000000..6ad41302a --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/parse/ContentHandler.java @@ -0,0 +1,110 @@ +package blade.kit.json.parse; + +import java.io.IOException; + +/** + * A simplified and stoppable SAX-like content handler for stream processing of JSON text. + * + * @see org.xml.sax.ContentHandler + * @see org.json.simple.parser.JSONParser#parse(java.io.Reader, ContentHandler, boolean) + * + * @author FangYidong + */ +public interface ContentHandler { + /** + * Receive notification of the beginning of JSON processing. + * The parser will invoke this method only once. + * + * @throws ParseException + * - JSONParser will stop and throw the same exception to the caller when receiving this exception. + */ + void startJSON() throws ParseException, IOException; + + /** + * Receive notification of the end of JSON processing. + * + * @throws ParseException + */ + void endJSON() throws ParseException, IOException; + + /** + * Receive notification of the beginning of a JSON object. + * + * @return false if the handler wants to stop parsing after return. + * @throws ParseException + * - JSONParser will stop and throw the same exception to the caller when receiving this exception. + * @see #endJSON + */ + boolean startObject() throws ParseException, IOException; + + /** + * Receive notification of the end of a JSON object. + * + * @return false if the handler wants to stop parsing after return. + * @throws ParseException + * + * @see #startObject + */ + boolean endObject() throws ParseException, IOException; + + /** + * Receive notification of the beginning of a JSON object entry. + * + * @param key - Key of a JSON object entry. + * + * @return false if the handler wants to stop parsing after return. + * @throws ParseException + * + * @see #endObjectEntry + */ + boolean startObjectEntry(String key) throws ParseException, IOException; + + /** + * Receive notification of the end of the value of previous object entry. + * + * @return false if the handler wants to stop parsing after return. + * @throws ParseException + * + * @see #startObjectEntry + */ + boolean endObjectEntry() throws ParseException, IOException; + + /** + * Receive notification of the beginning of a JSON array. + * + * @return false if the handler wants to stop parsing after return. + * @throws ParseException + * + * @see #endArray + */ + boolean startArray() throws ParseException, IOException; + + /** + * Receive notification of the end of a JSON array. + * + * @return false if the handler wants to stop parsing after return. + * @throws ParseException + * + * @see #startArray + */ + boolean endArray() throws ParseException, IOException; + + /** + * Receive notification of the JSON primitive values: + * java.lang.String, + * java.lang.Number, + * java.lang.Boolean + * null + * + * @param value - Instance of the following: + * java.lang.String, + * java.lang.Number, + * java.lang.Boolean + * null + * + * @return false if the handler wants to stop parsing after return. + * @throws ParseException + */ + boolean primitive(Object value) throws ParseException, IOException; + +} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/JSONParser.java b/blade-kit/src/main/java/blade/kit/json/parse/JSONParser.java new file mode 100644 index 000000000..b16445e6b --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/parse/JSONParser.java @@ -0,0 +1,534 @@ +/* + * $Id: JSONParser.java,v 1.1 2006/04/15 14:10:48 platform Exp $ + * Created on 2006-4-15 + */ +package blade.kit.json.parse; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import blade.kit.json.JSONArray; +import blade.kit.json.JSONObject; + + +/** + * Parser for JSON text. Please note that JSONParser is NOT thread-safe. + * + * @author FangYidong + */ +@SuppressWarnings({"rawtypes","unchecked"}) +public class JSONParser { + public static final int S_INIT=0; + public static final int S_IN_FINISHED_VALUE=1;//string,number,boolean,null,object,array + public static final int S_IN_OBJECT=2; + public static final int S_IN_ARRAY=3; + public static final int S_PASSED_PAIR_KEY=4; + public static final int S_IN_PAIR_VALUE=5; + public static final int S_END=6; + public static final int S_IN_ERROR=-1; + + private LinkedList handlerStatusStack; + private Yylex lexer = new Yylex((Reader)null); + private Yytoken token = null; + private int status = S_INIT; + + private int peekStatus(LinkedList statusStack){ + if(statusStack.size()==0) + return -1; + Integer status=(Integer)statusStack.getFirst(); + return status.intValue(); + } + + /** + * Reset the parser to the initial state without resetting the underlying reader. + * + */ + public void reset(){ + token = null; + status = S_INIT; + handlerStatusStack = null; + } + + /** + * Reset the parser to the initial state with a new character reader. + * + * @param in - The new character reader. + * @throws IOException + * @throws ParseException + */ + public void reset(Reader in){ + lexer.yyreset(in); + reset(); + } + + /** + * @return The position of the beginning of the current token. + */ + public int getPosition(){ + return lexer.getPosition(); + } + + public Object parse(String s) throws ParseException{ + return parse(s, (ContainerFactory)null); + } + + public Object parse(String s, ContainerFactory containerFactory) throws ParseException{ + StringReader in=new StringReader(s); + try{ + return parse(in, containerFactory); + } + catch(IOException ie){ + /* + * Actually it will never happen. + */ + throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie); + } + } + + public Object parse(Reader in) throws IOException, ParseException{ + return parse(in, (ContainerFactory)null); + } + + /** + * Parse JSON text into java object from the input source. + * + * @param in + * @param containerFactory - Use this factory to createyour own JSON object and JSON array containers. + * @return Instance of the following: + * org.json.simple.JSONObject, + * org.json.simple.JSONArray, + * java.lang.String, + * java.lang.Number, + * java.lang.Boolean, + * null + * + * @throws IOException + * @throws ParseException + */ + public Object parse(Reader in, ContainerFactory containerFactory) throws IOException, ParseException{ + reset(in); + LinkedList statusStack = new LinkedList(); + LinkedList valueStack = new LinkedList(); + + try{ + do{ + nextToken(); + switch(status){ + case S_INIT: + switch(token.type){ + case Yytoken.TYPE_VALUE: + status=S_IN_FINISHED_VALUE; + statusStack.addFirst(new Integer(status)); + valueStack.addFirst(token.value); + break; + case Yytoken.TYPE_LEFT_BRACE: + status=S_IN_OBJECT; + statusStack.addFirst(new Integer(status)); + valueStack.addFirst(createObjectContainer(containerFactory)); + break; + case Yytoken.TYPE_LEFT_SQUARE: + status=S_IN_ARRAY; + statusStack.addFirst(new Integer(status)); + valueStack.addFirst(createArrayContainer(containerFactory)); + break; + default: + status=S_IN_ERROR; + }//inner switch + break; + + case S_IN_FINISHED_VALUE: + if(token.type==Yytoken.TYPE_EOF) + return valueStack.removeFirst(); + else + throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); + + case S_IN_OBJECT: + switch(token.type){ + case Yytoken.TYPE_COMMA: + break; + case Yytoken.TYPE_VALUE: + if(token.value instanceof String){ + String key=(String)token.value; + valueStack.addFirst(key); + status=S_PASSED_PAIR_KEY; + statusStack.addFirst(new Integer(status)); + } + else{ + status=S_IN_ERROR; + } + break; + case Yytoken.TYPE_RIGHT_BRACE: + if(valueStack.size()>1){ + statusStack.removeFirst(); + valueStack.removeFirst(); + status=peekStatus(statusStack); + } + else{ + status=S_IN_FINISHED_VALUE; + } + break; + default: + status=S_IN_ERROR; + break; + }//inner switch + break; + + case S_PASSED_PAIR_KEY: + switch(token.type){ + case Yytoken.TYPE_COLON: + break; + case Yytoken.TYPE_VALUE: + statusStack.removeFirst(); + String key=(String)valueStack.removeFirst(); + Map parent=(Map)valueStack.getFirst(); + parent.put(key,token.value); + status=peekStatus(statusStack); + break; + case Yytoken.TYPE_LEFT_SQUARE: + statusStack.removeFirst(); + key=(String)valueStack.removeFirst(); + parent=(Map)valueStack.getFirst(); + List newArray=createArrayContainer(containerFactory); + parent.put(key,newArray); + status=S_IN_ARRAY; + statusStack.addFirst(new Integer(status)); + valueStack.addFirst(newArray); + break; + case Yytoken.TYPE_LEFT_BRACE: + statusStack.removeFirst(); + key=(String)valueStack.removeFirst(); + parent=(Map)valueStack.getFirst(); + Map newObject=createObjectContainer(containerFactory); + parent.put(key,newObject); + status=S_IN_OBJECT; + statusStack.addFirst(new Integer(status)); + valueStack.addFirst(newObject); + break; + default: + status=S_IN_ERROR; + } + break; + + case S_IN_ARRAY: + switch(token.type){ + case Yytoken.TYPE_COMMA: + break; + case Yytoken.TYPE_VALUE: + List val=(List)valueStack.getFirst(); + val.add(token.value); + break; + case Yytoken.TYPE_RIGHT_SQUARE: + if(valueStack.size()>1){ + statusStack.removeFirst(); + valueStack.removeFirst(); + status=peekStatus(statusStack); + } + else{ + status=S_IN_FINISHED_VALUE; + } + break; + case Yytoken.TYPE_LEFT_BRACE: + val=(List)valueStack.getFirst(); + Map newObject=createObjectContainer(containerFactory); + val.add(newObject); + status=S_IN_OBJECT; + statusStack.addFirst(new Integer(status)); + valueStack.addFirst(newObject); + break; + case Yytoken.TYPE_LEFT_SQUARE: + val=(List)valueStack.getFirst(); + List newArray=createArrayContainer(containerFactory); + val.add(newArray); + status=S_IN_ARRAY; + statusStack.addFirst(new Integer(status)); + valueStack.addFirst(newArray); + break; + default: + status=S_IN_ERROR; + }//inner switch + break; + case S_IN_ERROR: + throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); + }//switch + if(status==S_IN_ERROR){ + throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); + } + }while(token.type!=Yytoken.TYPE_EOF); + } + catch(IOException ie){ + throw ie; + } + + throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); + } + + private void nextToken() throws ParseException, IOException{ + token = lexer.yylex(); + if(token == null) + token = new Yytoken(Yytoken.TYPE_EOF, null); + } + + private Map createObjectContainer(ContainerFactory containerFactory){ + if(containerFactory == null) + return new JSONObject(); + Map m = containerFactory.createObjectContainer(); + + if(m == null) + return new JSONObject(); + return m; + } + + private List createArrayContainer(ContainerFactory containerFactory){ + if(containerFactory == null) + return new JSONArray(); + List l = containerFactory.creatArrayContainer(); + + if(l == null) + return new JSONArray(); + return l; + } + + public void parse(String s, ContentHandler contentHandler) throws ParseException{ + parse(s, contentHandler, false); + } + + public void parse(String s, ContentHandler contentHandler, boolean isResume) throws ParseException{ + StringReader in=new StringReader(s); + try{ + parse(in, contentHandler, isResume); + } + catch(IOException ie){ + /* + * Actually it will never happen. + */ + throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie); + } + } + + public void parse(Reader in, ContentHandler contentHandler) throws IOException, ParseException{ + parse(in, contentHandler, false); + } + + /** + * Stream processing of JSON text. + * + * @see ContentHandler + * + * @param in + * @param contentHandler + * @param isResume - Indicates if it continues previous parsing operation. + * If set to true, resume parsing the old stream, and parameter 'in' will be ignored. + * If this method is called for the first time in this instance, isResume will be ignored. + * + * @throws IOException + * @throws ParseException + */ + public void parse(Reader in, ContentHandler contentHandler, boolean isResume) throws IOException, ParseException{ + if(!isResume){ + reset(in); + handlerStatusStack = new LinkedList(); + } + else{ + if(handlerStatusStack == null){ + isResume = false; + reset(in); + handlerStatusStack = new LinkedList(); + } + } + + LinkedList statusStack = handlerStatusStack; + + try{ + do{ + switch(status){ + case S_INIT: + contentHandler.startJSON(); + nextToken(); + switch(token.type){ + case Yytoken.TYPE_VALUE: + status=S_IN_FINISHED_VALUE; + statusStack.addFirst(new Integer(status)); + if(!contentHandler.primitive(token.value)) + return; + break; + case Yytoken.TYPE_LEFT_BRACE: + status=S_IN_OBJECT; + statusStack.addFirst(new Integer(status)); + if(!contentHandler.startObject()) + return; + break; + case Yytoken.TYPE_LEFT_SQUARE: + status=S_IN_ARRAY; + statusStack.addFirst(new Integer(status)); + if(!contentHandler.startArray()) + return; + break; + default: + status=S_IN_ERROR; + }//inner switch + break; + + case S_IN_FINISHED_VALUE: + nextToken(); + if(token.type==Yytoken.TYPE_EOF){ + contentHandler.endJSON(); + status = S_END; + return; + } + else{ + status = S_IN_ERROR; + throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); + } + + case S_IN_OBJECT: + nextToken(); + switch(token.type){ + case Yytoken.TYPE_COMMA: + break; + case Yytoken.TYPE_VALUE: + if(token.value instanceof String){ + String key=(String)token.value; + status=S_PASSED_PAIR_KEY; + statusStack.addFirst(new Integer(status)); + if(!contentHandler.startObjectEntry(key)) + return; + } + else{ + status=S_IN_ERROR; + } + break; + case Yytoken.TYPE_RIGHT_BRACE: + if(statusStack.size()>1){ + statusStack.removeFirst(); + status=peekStatus(statusStack); + } + else{ + status=S_IN_FINISHED_VALUE; + } + if(!contentHandler.endObject()) + return; + break; + default: + status=S_IN_ERROR; + break; + }//inner switch + break; + + case S_PASSED_PAIR_KEY: + nextToken(); + switch(token.type){ + case Yytoken.TYPE_COLON: + break; + case Yytoken.TYPE_VALUE: + statusStack.removeFirst(); + status=peekStatus(statusStack); + if(!contentHandler.primitive(token.value)) + return; + if(!contentHandler.endObjectEntry()) + return; + break; + case Yytoken.TYPE_LEFT_SQUARE: + statusStack.removeFirst(); + statusStack.addFirst(new Integer(S_IN_PAIR_VALUE)); + status=S_IN_ARRAY; + statusStack.addFirst(new Integer(status)); + if(!contentHandler.startArray()) + return; + break; + case Yytoken.TYPE_LEFT_BRACE: + statusStack.removeFirst(); + statusStack.addFirst(new Integer(S_IN_PAIR_VALUE)); + status=S_IN_OBJECT; + statusStack.addFirst(new Integer(status)); + if(!contentHandler.startObject()) + return; + break; + default: + status=S_IN_ERROR; + } + break; + + case S_IN_PAIR_VALUE: + /* + * S_IN_PAIR_VALUE is just a marker to indicate the end of an object entry, it doesn't proccess any token, + * therefore delay consuming token until next round. + */ + statusStack.removeFirst(); + status = peekStatus(statusStack); + if(!contentHandler.endObjectEntry()) + return; + break; + + case S_IN_ARRAY: + nextToken(); + switch(token.type){ + case Yytoken.TYPE_COMMA: + break; + case Yytoken.TYPE_VALUE: + if(!contentHandler.primitive(token.value)) + return; + break; + case Yytoken.TYPE_RIGHT_SQUARE: + if(statusStack.size()>1){ + statusStack.removeFirst(); + status=peekStatus(statusStack); + } + else{ + status=S_IN_FINISHED_VALUE; + } + if(!contentHandler.endArray()) + return; + break; + case Yytoken.TYPE_LEFT_BRACE: + status=S_IN_OBJECT; + statusStack.addFirst(new Integer(status)); + if(!contentHandler.startObject()) + return; + break; + case Yytoken.TYPE_LEFT_SQUARE: + status=S_IN_ARRAY; + statusStack.addFirst(new Integer(status)); + if(!contentHandler.startArray()) + return; + break; + default: + status=S_IN_ERROR; + }//inner switch + break; + + case S_END: + return; + + case S_IN_ERROR: + throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); + }//switch + if(status==S_IN_ERROR){ + throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); + } + }while(token.type!=Yytoken.TYPE_EOF); + } + catch(IOException ie){ + status = S_IN_ERROR; + throw ie; + } + catch(ParseException pe){ + status = S_IN_ERROR; + throw pe; + } + catch(RuntimeException re){ + status = S_IN_ERROR; + throw re; + } + catch(Error e){ + status = S_IN_ERROR; + throw e; + } + + status = S_IN_ERROR; + throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/ParseException.java b/blade-kit/src/main/java/blade/kit/json/parse/ParseException.java new file mode 100644 index 000000000..24b383c26 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/parse/ParseException.java @@ -0,0 +1,90 @@ +package blade.kit.json.parse; + +/** + * ParseException explains why and where the error occurs in source JSON text. + * + * @author FangYidong + * + */ +public class ParseException extends Exception { + private static final long serialVersionUID = -7880698968187728547L; + + public static final int ERROR_UNEXPECTED_CHAR = 0; + public static final int ERROR_UNEXPECTED_TOKEN = 1; + public static final int ERROR_UNEXPECTED_EXCEPTION = 2; + + private int errorType; + private Object unexpectedObject; + private int position; + + public ParseException(int errorType){ + this(-1, errorType, null); + } + + public ParseException(int errorType, Object unexpectedObject){ + this(-1, errorType, unexpectedObject); + } + + public ParseException(int position, int errorType, Object unexpectedObject){ + this.position = position; + this.errorType = errorType; + this.unexpectedObject = unexpectedObject; + } + + public int getErrorType() { + return errorType; + } + + public void setErrorType(int errorType) { + this.errorType = errorType; + } + + /** + * @see org.json.simple.parser.JSONParser#getPosition() + * + * @return The character position (starting with 0) of the input where the error occurs. + */ + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + /** + * @see org.json.simple.parser.Yytoken + * + * @return One of the following base on the value of errorType: + * ERROR_UNEXPECTED_CHAR java.lang.Character + * ERROR_UNEXPECTED_TOKEN org.json.simple.parser.Yytoken + * ERROR_UNEXPECTED_EXCEPTION java.lang.Exception + */ + public Object getUnexpectedObject() { + return unexpectedObject; + } + + public void setUnexpectedObject(Object unexpectedObject) { + this.unexpectedObject = unexpectedObject; + } + + public String getMessage() { + StringBuffer sb = new StringBuffer(); + + switch(errorType){ + case ERROR_UNEXPECTED_CHAR: + sb.append("Unexpected character (").append(unexpectedObject).append(") at position ").append(position).append("."); + break; + case ERROR_UNEXPECTED_TOKEN: + sb.append("Unexpected token ").append(unexpectedObject).append(" at position ").append(position).append("."); + break; + case ERROR_UNEXPECTED_EXCEPTION: + sb.append("Unexpected exception at position ").append(position).append(": ").append(unexpectedObject); + break; + default: + sb.append("Unkown error at position ").append(position).append("."); + break; + } + return sb.toString(); + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/Yylex.java b/blade-kit/src/main/java/blade/kit/json/parse/Yylex.java new file mode 100644 index 000000000..d8c4f3bf9 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/parse/Yylex.java @@ -0,0 +1,689 @@ +/* The following code was generated by JFlex 1.4.2 */ + +package blade.kit.json.parse; + +@SuppressWarnings("unused") +class Yylex { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int YYINITIAL = 0; + public static final int STRING_BEGIN = 2; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\7\1\7\2\0\1\7\22\0\1\7\1\0\1\11\10\0"+ + "\1\6\1\31\1\2\1\4\1\12\12\3\1\32\6\0\4\1\1\5"+ + "\1\1\24\0\1\27\1\10\1\30\3\0\1\22\1\13\2\1\1\21"+ + "\1\14\5\0\1\23\1\0\1\15\3\0\1\16\1\24\1\17\1\20"+ + "\5\0\1\25\1\0\1\26\uff82\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\2\0\2\1\1\2\1\3\1\4\3\1\1\5\1\6"+ + "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\5\0"+ + "\1\14\1\16\1\17\1\20\1\21\1\22\1\23\1\24"+ + "\1\0\1\25\1\0\1\25\4\0\1\26\1\27\2\0"+ + "\1\30"; + + private static int [] zzUnpackAction() { + int [] result = new int[45]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\33\0\66\0\121\0\154\0\207\0\66\0\242"+ + "\0\275\0\330\0\66\0\66\0\66\0\66\0\66\0\66"+ + "\0\363\0\u010e\0\66\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195"+ + "\0\66\0\66\0\66\0\66\0\66\0\66\0\66\0\66"+ + "\0\u01b0\0\u01cb\0\u01e6\0\u01e6\0\u0201\0\u021c\0\u0237\0\u0252"+ + "\0\66\0\66\0\u026d\0\u0288\0\66"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[45]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int ZZ_TRANS [] = { + 2, 2, 3, 4, 2, 2, 2, 5, 2, 6, + 2, 2, 7, 8, 2, 9, 2, 2, 2, 2, + 2, 10, 11, 12, 13, 14, 15, 16, 16, 16, + 16, 16, 16, 16, 16, 17, 18, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 4, 19, 20, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 16, 16, 16, 16, 16, 16, 16, + 16, -1, -1, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + -1, -1, -1, -1, -1, -1, -1, -1, 24, 25, + 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 34, 35, -1, -1, + 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 39, -1, 39, -1, 39, -1, -1, + -1, -1, -1, 39, 39, -1, -1, -1, -1, 39, + 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 33, -1, 20, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 42, -1, 42, -1, 42, + -1, -1, -1, -1, -1, 42, 42, -1, -1, -1, + -1, 42, 42, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 43, -1, 43, -1, 43, -1, -1, -1, + -1, -1, 43, 43, -1, -1, -1, -1, 43, 43, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, + -1, 44, -1, 44, -1, -1, -1, -1, -1, 44, + 44, -1, -1, -1, -1, 44, 44, -1, -1, -1, + -1, -1, -1, -1, -1, + }; + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\2\0\1\11\3\1\1\11\3\1\6\11\2\1\1\11"+ + "\5\0\10\11\1\0\1\1\1\0\1\1\4\0\2\11"+ + "\2\0\1\11"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[45]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /* user code: */ +private StringBuffer sb=new StringBuffer(); + +int getPosition(){ + return yychar; +} + + + + /** + * Creates a new scanner + * There is also a java.io.InputStream version of this constructor. + * + * @param in the java.io.Reader to read input from. + */ + Yylex(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + Yylex(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 90) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead-zzStartRead); + + /* translate stored positions */ + zzEndRead-= zzStartRead; + zzCurrentPos-= zzStartRead; + zzMarkedPos-= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length) { + /* if not: blow it up */ + char newBuffer[] = new char[zzCurrentPos*2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + } + + /* finally: fill the buffer with new input */ + int numRead = zzReader.read(zzBuffer, zzEndRead, + zzBuffer.length-zzEndRead); + + if (numRead > 0) { + zzEndRead+= numRead; + return false; + } + // unlikely but not impossible: read 0 characters, but not at end of stream + if (numRead == 0) { + int c = zzReader.read(); + if (c == -1) { + return true; + } else { + zzBuffer[zzEndRead++] = (char) c; + return false; + } + } + + // numRead < 0 + return true; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) + zzReader.close(); + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * cannot be reused (internal buffer is discarded and lost). + * Lexical state is set to ZZ_INITIAL. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position pos from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public Yytoken yylex() throws java.io.IOException, ParseException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + yychar+= zzMarkedPosL-zzStartRead; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) + zzInput = zzBufferL[zzCurrentPosL++]; + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = zzBufferL[zzCurrentPosL++]; + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 11: + { sb.append(yytext()); + } + case 25: break; + case 4: + { sb = null; sb = new StringBuffer(); yybegin(STRING_BEGIN); + } + case 26: break; + case 16: + { sb.append('\b'); + } + case 27: break; + case 6: + { return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null); + } + case 28: break; + case 23: + { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); + } + case 29: break; + case 22: + { return new Yytoken(Yytoken.TYPE_VALUE, null); + } + case 30: break; + case 13: + { yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE, sb.toString()); + } + case 31: break; + case 12: + { sb.append('\\'); + } + case 32: break; + case 21: + { Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); + } + case 33: break; + case 1: + { throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_CHAR, new Character(yycharat(0))); + } + case 34: break; + case 8: + { return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null); + } + case 35: break; + case 19: + { sb.append('\r'); + } + case 36: break; + case 15: + { sb.append('/'); + } + case 37: break; + case 10: + { return new Yytoken(Yytoken.TYPE_COLON,null); + } + case 38: break; + case 14: + { sb.append('"'); + } + case 39: break; + case 5: + { return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null); + } + case 40: break; + case 17: + { sb.append('\f'); + } + case 41: break; + case 24: + { try{ + int ch=Integer.parseInt(yytext().substring(2),16); + sb.append((char)ch); + } + catch(Exception e){ + throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_EXCEPTION, e); + } + } + case 42: break; + case 20: + { sb.append('\t'); + } + case 43: break; + case 7: + { return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null); + } + case 44: break; + case 2: + { Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); + } + case 45: break; + case 18: + { sb.append('\n'); + } + case 46: break; + case 9: + { return new Yytoken(Yytoken.TYPE_COMMA,null); + } + case 47: break; + case 3: + { + } + case 48: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + return null; + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/Yytoken.java b/blade-kit/src/main/java/blade/kit/json/parse/Yytoken.java new file mode 100644 index 000000000..90a111141 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/parse/Yytoken.java @@ -0,0 +1,58 @@ +/* + * $Id: Yytoken.java,v 1.1 2006/04/15 14:10:48 platform Exp $ + * Created on 2006-4-15 + */ +package blade.kit.json.parse; + +/** + * @author FangYidong + */ +public class Yytoken { + public static final int TYPE_VALUE=0;//JSON primitive value: string,number,boolean,null + public static final int TYPE_LEFT_BRACE=1; + public static final int TYPE_RIGHT_BRACE=2; + public static final int TYPE_LEFT_SQUARE=3; + public static final int TYPE_RIGHT_SQUARE=4; + public static final int TYPE_COMMA=5; + public static final int TYPE_COLON=6; + public static final int TYPE_EOF=-1;//end of file + + public int type=0; + public Object value=null; + + public Yytoken(int type,Object value){ + this.type=type; + this.value=value; + } + + public String toString(){ + StringBuffer sb = new StringBuffer(); + switch(type){ + case TYPE_VALUE: + sb.append("VALUE(").append(value).append(")"); + break; + case TYPE_LEFT_BRACE: + sb.append("LEFT BRACE({)"); + break; + case TYPE_RIGHT_BRACE: + sb.append("RIGHT BRACE(})"); + break; + case TYPE_LEFT_SQUARE: + sb.append("LEFT SQUARE([)"); + break; + case TYPE_RIGHT_SQUARE: + sb.append("RIGHT SQUARE(])"); + break; + case TYPE_COMMA: + sb.append("COMMA(,)"); + break; + case TYPE_COLON: + sb.append("COLON(:)"); + break; + case TYPE_EOF: + sb.append("END OF FILE"); + break; + } + return sb.toString(); + } +} diff --git a/blade-kit/src/main/java/blade/kit/log/JdkLogger.java b/blade-kit/src/main/java/blade/kit/log/JdkLogger.java new file mode 100644 index 000000000..5b96cdcc0 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/log/JdkLogger.java @@ -0,0 +1,76 @@ +package blade.kit.log; + +import java.util.logging.Level; + +/** + * JDK的日志适配 + * + * @author biezhi + * @since 1.0 + */ +public class JdkLogger extends Logger { + + private java.util.logging.Logger logger; + + public JdkLogger(Class clazz) { + this(clazz.getName()); + } + + public JdkLogger(String name) { + this.name = name; + logger = java.util.logging.Logger.getLogger(name); + } + + private Level getLevel(int level) { + switch (level) { + case blade.kit.log.Level.TRACE: + return Level.FINEST; + case blade.kit.log.Level.DEBUG: + return Level.FINE; + case blade.kit.log.Level.INFO: + return Level.INFO; + case blade.kit.log.Level.WARN: + return Level.WARNING; + case blade.kit.log.Level.ERROR: + case blade.kit.log.Level.FATAL: + return Level.SEVERE; + } + return Level.INFO; + } + + @Override + public void log(int level, Object message, Object... args) { + log(level, message, null, args); + } + + @Override + public void log(int level, Object message, Throwable t, Object... args) { + + log(getLevel(level), format(message, args), t); + + } + + private void log(Level level, String msg, Throwable ex) { + if (logger.isLoggable(level)) { + // Hack (?) to get the stack trace. + Throwable dummyException = new Throwable(); + StackTraceElement locations[] = dummyException.getStackTrace(); + // Caller will be the third element + String cname = "unknown"; + String method = "unknown"; + if (locations != null && locations.length > 3) { + StackTraceElement caller = locations[3]; + cname = caller.getClassName(); + method = caller.getMethodName(); + } + + if (ex == null) { + logger.logp(level, cname, method, msg); + } else { + logger.logp(level, cname, method, msg, ex); + } + } + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/log/JdkLoggerFactory.java b/blade-kit/src/main/java/blade/kit/log/JdkLoggerFactory.java new file mode 100644 index 000000000..b9dee5345 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/log/JdkLoggerFactory.java @@ -0,0 +1,12 @@ +package blade.kit.log; + +public class JdkLoggerFactory implements LoggerFactory { + + public Logger getLogger(Class clazz) { + return new JdkLogger(clazz); + } + + public Logger getLogger(String name) { + return new JdkLogger(name); + } +} diff --git a/blade-kit/src/main/java/blade/kit/log/Level.java b/blade-kit/src/main/java/blade/kit/log/Level.java new file mode 100644 index 000000000..efe75650a --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/log/Level.java @@ -0,0 +1,22 @@ +package blade.kit.log; + +/** + * 日志级别 + * @author biezhi + * + */ +public final class Level { + + public static final int TRACE = 100; + + public static final int DEBUG = 200; + + public static final int INFO = 300; + + public static final int WARN = 400; + + public static final int ERROR = 500; + + public static final int FATAL = 600; + +} diff --git a/blade-kit/src/main/java/blade/kit/log/Log4jLogger.java b/blade-kit/src/main/java/blade/kit/log/Log4jLogger.java new file mode 100644 index 000000000..fd18d8747 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/log/Log4jLogger.java @@ -0,0 +1,186 @@ +package blade.kit.log; + +import org.apache.log4j.Level; +import org.apache.log4j.Priority; + +/** + * Log4j日志适配 + * + * @author biezhi + * @since 1.0 + */ +@SuppressWarnings("deprecation") +public class Log4jLogger extends Logger{ + + private static final String FQCN = Log4jLogger.class.getName(); + private static Priority traceLevel; + private org.apache.log4j.Logger logger; + + static { + try { + traceLevel = (Priority) Level.class.getDeclaredField("TRACE").get(null); + } catch (Exception ex) { + traceLevel = Priority.DEBUG; + } + } + + public Log4jLogger(String name) { + this.name = name; + logger = org.apache.log4j.Logger.getLogger(name); + } + + @Override + public String getName() { + return this.name; + } + + private Priority getLevel(int level) { + switch (level) { + case blade.kit.log.Level.TRACE: + return traceLevel; + case blade.kit.log.Level.DEBUG: + return Priority.DEBUG; + case blade.kit.log.Level.INFO: + return Priority.INFO; + case blade.kit.log.Level.WARN: + return Priority.WARN; + case blade.kit.log.Level.ERROR: + return Priority.ERROR; + case blade.kit.log.Level.FATAL: + return Priority.FATAL; + } + return Priority.DEBUG; + } + + @Override + public void log(int level, Object message, Object... args) { + message = format(message, args); + logger.log(FQCN, getLevel(level), message, null); + } + + @Override + public void log(int level, Object message, Throwable t, Object... args) { + message = format(message, args); + logger.log(FQCN, getLevel(level), message, t); + } + + @Override + public void trace(Object message) { + + } + + @Override + public void trace(Object message, Object... args) { + // TODO Auto-generated method stub + + } + + @Override + public void trace(Object message, Throwable t) { + // TODO Auto-generated method stub + + } + + @Override + public void trace(Object message, Throwable t, Object... args) { + // TODO Auto-generated method stub + + } + + @Override + public void debug(Object message) { + // TODO Auto-generated method stub + + } + + @Override + public void debug(Object message, Object... args) { + // TODO Auto-generated method stub + + } + + @Override + public void debug(Object message, Throwable t) { + // TODO Auto-generated method stub + + } + + @Override + public void debug(Object message, Throwable t, Object... args) { + // TODO Auto-generated method stub + + } + + @Override + public void info(Object message) { + // TODO Auto-generated method stub + + } + + @Override + public void info(Object message, Object... args) { + // TODO Auto-generated method stub + + } + + @Override + public void info(Object message, Throwable t) { + // TODO Auto-generated method stub + + } + + @Override + public void info(Object message, Throwable t, Object... args) { + // TODO Auto-generated method stub + + } + + @Override + public void warn(Object message) { + // TODO Auto-generated method stub + + } + + @Override + public void warn(Object message, Object... args) { + // TODO Auto-generated method stub + + } + + @Override + public void warn(Object message, Throwable t) { + // TODO Auto-generated method stub + + } + + @Override + public void warn(Object message, Throwable t, Object... args) { + // TODO Auto-generated method stub + + } + + @Override + public void error(Object message) { + // TODO Auto-generated method stub + + } + + @Override + public void error(Object message, Object... args) { + // TODO Auto-generated method stub + + } + + @Override + public void error(Object message, Throwable t) { + // TODO Auto-generated method stub + + } + + @Override + public void error(Object message, Throwable t, Object... args) { + // TODO Auto-generated method stub + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/log/Log4jLoggerFactory.java b/blade-kit/src/main/java/blade/kit/log/Log4jLoggerFactory.java new file mode 100644 index 000000000..0d0f3fb90 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/log/Log4jLoggerFactory.java @@ -0,0 +1,12 @@ +package blade.kit.log; + +public class Log4jLoggerFactory implements LoggerFactory { + + public Logger getLogger(Class clazz) { + return new JdkLogger(clazz); + } + + public Logger getLogger(String name) { + return new JdkLogger(name); + } +} diff --git a/blade-kit/src/main/java/blade/kit/log/Logger.java b/blade-kit/src/main/java/blade/kit/log/Logger.java index eed9b2594..3f32a9538 100644 --- a/blade-kit/src/main/java/blade/kit/log/Logger.java +++ b/blade-kit/src/main/java/blade/kit/log/Logger.java @@ -1,7 +1,5 @@ package blade.kit.log; -import java.lang.reflect.Constructor; - /** * 日志输出 * @@ -10,17 +8,9 @@ */ public abstract class Logger { - private static Class logClass = SysLoggerAdaptor.class; - private static Constructor logConstructor; - - public static final int TRACE = 10; - public static final int DEBUG = 20; - public static final int INFO = 30; - public static final int WARN = 40; - public static final int ERROR = 50; - public static final int FATAL = 60; + private static LoggerFactory factory; - private int level = Logger.DEBUG; + private int level = Level.DEBUG; /** * 日志名称 @@ -34,34 +24,22 @@ public abstract class Logger { static{ try { Class.forName("org.apache.log4j.Logger"); - logClass = Log4jLogAdaptor.class; + factory = new Log4jLoggerFactory(); } catch (Exception e) { - logClass = SysLoggerAdaptor.class; + factory = new SimpleLoggerFactory(); } } - public static void setLoggerImpl(Class loggerClass){ - logClass = loggerClass; + public static void setLoggerFactory(LoggerFactory loggerFactory){ + factory = loggerFactory; } public static Logger getLogger(String name) { - try { - - if (logConstructor == null) { - synchronized (Logger.class) { - if (logConstructor == null) - logConstructor = logClass.getConstructor(String.class); - } - } - Logger log = (Logger) logConstructor.newInstance(name); - return log; - } catch (Exception e) { - throw new RuntimeException(e); - } + return factory.getLogger(name); } public static Logger getLogger(Class clazz) { - return getLogger(clazz.getName()); + return factory.getLogger(clazz); } public static Logger getLogger() { @@ -78,132 +56,132 @@ public void setLevel(int level) { } public void trace(Object message) { - if (level <= TRACE) - log(TRACE, message); + if (level <= Level.TRACE) + log(Level.TRACE, message); } public void trace(Object message, Object... args) { - if (level <= TRACE) - log(TRACE, message, args); + if (level <= Level.TRACE) + log(Level.TRACE, message, args); } public void trace(Object message, Throwable t) { - if (level <= TRACE) - log(TRACE, message, t); + if (level <= Level.TRACE) + log(Level.TRACE, message, t); } public void trace(Object message, Throwable t, Object... args) { - if (level <= TRACE) - log(TRACE, message, t, args); + if (level <= Level.TRACE) + log(Level.TRACE, message, t, args); } public void debug(Object message) { - if (level <= DEBUG) - log(DEBUG, message); + if (level <= Level.DEBUG) + log(Level.DEBUG, message); } public void debug(Object message, Object... args) { - if (level <= DEBUG) - log(DEBUG, message, args); + if (level <= Level.DEBUG) + log(Level.DEBUG, message, args); } public void debug(Object message, Throwable t) { - if (level <= DEBUG) - log(DEBUG, message, t); + if (level <= Level.DEBUG) + log(Level.DEBUG, message, t); } public void debug(Object message, Throwable t, Object... args) { - if (level <= DEBUG) - log(DEBUG, message, t, args); + if (level <= Level.DEBUG) + log(Level.DEBUG, message, t, args); } public void info(Object message) { - if (level <= INFO) - log(INFO, message); + if (level <= Level.INFO) + log(Level.INFO, message); } public void info(Object message, Object... args) { - if (level <= INFO) - log(INFO, message, args); + if (level <= Level.INFO) + log(Level.INFO, message, args); } public void info(Object message, Throwable t) { - if (level <= INFO) - log(INFO, message, t); + if (level <= Level.INFO) + log(Level.INFO, message, t); } public void info(Object message, Throwable t, Object... args) { - if (level <= INFO) - log(INFO, message, t, args); + if (level <= Level.INFO) + log(Level.INFO, message, t, args); } public void warn(Object message) { - if (level <= WARN) - log(WARN, message); + if (level <= Level.WARN) + log(Level.WARN, message); } public void warn(Object message, Object... args) { - if (level <= WARN) - log(WARN, message, args); + if (level <= Level.WARN) + log(Level.WARN, message, args); } public void warn(Object message, Throwable t) { - if (level <= WARN) - log(WARN, message, t); + if (level <= Level.WARN) + log(Level.WARN, message, t); } public void warn(Object message, Throwable t, Object... args) { - if (level <= WARN) - log(WARN, message, t, args); + if (level <= Level.WARN) + log(Level.WARN, message, t, args); } public void error(Object message) { - if (level <= ERROR) - log(ERROR, message); + if (level <= Level.ERROR) + log(Level.ERROR, message); } public void error(Object message, Object... args) { - if (level <= ERROR) - log(ERROR, message, args); + if (level <= Level.ERROR) + log(Level.ERROR, message, args); } public void error(Object message, Throwable t) { - if (level <= ERROR) - log(ERROR, message, t); + if (level <= Level.ERROR) + log(Level.ERROR, message, t); } public void error(Object message, Throwable t, Object... args) { - if (level <= ERROR) - log(ERROR, message, t, args); + if (level <= Level.ERROR) + log(Level.ERROR, message, t, args); } public void fatal(Object message, Object... args) { - if (level <= FATAL) - log(FATAL, message, args); + if (level <= Level.FATAL) + log(Level.FATAL, message, args); } public void fatal(Object message, Throwable t, Object... args) { - if (level <= FATAL) - log(FATAL, message, t, args); + if (level <= Level.FATAL) + log(Level.FATAL, message, t, args); } protected String format(Object message, Object... args) { @@ -218,6 +196,19 @@ protected String format(Object message, Object... args) { } public boolean isDebugEnabled() { - return level <= DEBUG; + return level <= Level.DEBUG; } + + public boolean isErrorEnabled() { + return level <= Level.ERROR; + } + + public boolean isInfoEnabled() { + return level <= Level.INFO; + } + + public boolean isWarnEnabled() { + return level <= Level.WARN; + } + } diff --git a/blade-kit/src/main/java/blade/kit/log/LoggerFactory.java b/blade-kit/src/main/java/blade/kit/log/LoggerFactory.java new file mode 100644 index 000000000..89fb57d6f --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/log/LoggerFactory.java @@ -0,0 +1,8 @@ +package blade.kit.log; + +public interface LoggerFactory { + + Logger getLogger(Class clazz); + + Logger getLogger(String name); +} diff --git a/blade-kit/src/main/java/blade/kit/log/SimpleLogger.java b/blade-kit/src/main/java/blade/kit/log/SimpleLogger.java new file mode 100644 index 000000000..00982814f --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/log/SimpleLogger.java @@ -0,0 +1,75 @@ +package blade.kit.log; + +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Blade自带的日志实现 + * + * @author biezhi + * @since 1.0 + */ +public class SimpleLogger extends Logger { + + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"); + + private static PrintStream outprint = System.out; + + public SimpleLogger() { + } + + public SimpleLogger(String name) { + this.name = name; + } + + private String getLevel(int level){ + if(level <= blade.kit.log.Level.TRACE){ + return "TRACE"; + } + if(level <= blade.kit.log.Level.DEBUG){ + return "DEBUG"; + } + if(level <= blade.kit.log.Level.INFO){ + return "INFO"; + } + if(level <= blade.kit.log.Level.WARN){ + return "WARN"; + } + if(level <= blade.kit.log.Level.ERROR){ + outprint = System.err; + return "ERROR"; + } + if(level <= blade.kit.log.Level.FATAL){ + return "FATAL"; + } + return "DEBUG"; + } + + private String now() { + return sdf.format(new Date()); + } + + @Override + public void log(int level, Object message, Object... args) { + log(level, message, null, args); + + } + + @Override + public void log(int level, Object message, Throwable t, Object... args) { + + StringBuilder sb = new StringBuilder(now()); + sb.append(" ").append(getLevel(level)).append(" "); + sb.append("[").append(Thread.currentThread().getName()).append("]").append(" "); + sb.append(getName()).append(" | "); + sb.append(format(message, args)); + + outprint.println(sb.toString()); + if (t != null) { + t.printStackTrace(System.err); + System.err.flush(); + } + } + +} diff --git a/blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java b/blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java new file mode 100644 index 000000000..8e0021044 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java @@ -0,0 +1,12 @@ +package blade.kit.log; + +public class SimpleLoggerFactory implements LoggerFactory { + + public Logger getLogger(Class clazz) { + return new JdkLogger(clazz); + } + + public Logger getLogger(String name) { + return new JdkLogger(name); + } +} diff --git a/blade-kit/src/test/java/blade/test/LogTest.java b/blade-kit/src/test/java/blade/test/LogTest.java index 42e463fa3..cbfeaf514 100644 --- a/blade-kit/src/test/java/blade/test/LogTest.java +++ b/blade-kit/src/test/java/blade/test/LogTest.java @@ -1,13 +1,19 @@ package blade.test; import blade.kit.log.Logger; -import blade.kit.log.SysLoggerAdaptor; public class LogTest { + private static final Logger LOGGER = Logger.getLogger(LogTest.class); + public static void main(String[] args) { - Logger.setLoggerImpl(SysLoggerAdaptor.class); - Logger logger = Logger.getLogger(LogTest.class); - logger.info("hello %s", "aaa"); +// LOGGER.setLevel(Level.INFO); + LOGGER.debug("debug hello"); + LOGGER.info("info hello %s", "aaa"); + LOGGER.warn("warn hello"); + + System.out.println(LOGGER.isDebugEnabled()); + System.out.println(LOGGER.isInfoEnabled()); + System.out.println(LOGGER.isErrorEnabled()); } } From 470aa6bee120d13af2fb4015d5351b88b189fac3 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 11:26:52 +0800 Subject: [PATCH 171/545] optimize blade-kit --- LAST_VERSION.md | 4 +- blade-core/pom.xml | 2 +- blade-kit/pom.xml | 2 +- blade-kit/src/main/java/blade/kit/Assert.java | 72 +++++++++++++++++++ .../src/main/java/blade/kit/CharKit.java | 14 +--- .../main/java/blade/kit/CollectionKit.java | 7 +- blade-kit/src/main/java/blade/kit/IOKit.java | 2 +- .../main/java/blade/kit/log/JdkLogger.java | 2 +- .../main/java/blade/kit/log/Log4jLogger.java | 2 +- .../main/java/blade/kit/log/SimpleLogger.java | 2 +- .../blade/kit/log/SimpleLoggerFactory.java | 4 +- pom.xml | 2 +- 12 files changed, 89 insertions(+), 26 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index caa7d8ee8..63ab1b2dd 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -23,7 +23,7 @@     com.bladejava     blade-kit -    1.2.7-alpha +    1.2.7-beta ``` @@ -32,7 +32,7 @@     com.bladejava     blade-core -    1.4.0-alpha +    1.4.0-beta ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index be36cb88b..f89e44c6e 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -23,7 +23,7 @@ com.bladejava blade-kit - 1.2.7-alpha + 1.2.7-beta javax.servlet diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index 7c2e6bfe7..98b72a4dd 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - 1.2.7-alpha + 1.2.7-beta blade-kit https://github.com/biezhi/blade/tree/master/blade-kit diff --git a/blade-kit/src/main/java/blade/kit/Assert.java b/blade-kit/src/main/java/blade/kit/Assert.java index e87b71cf4..152926146 100644 --- a/blade-kit/src/main/java/blade/kit/Assert.java +++ b/blade-kit/src/main/java/blade/kit/Assert.java @@ -61,6 +61,78 @@ public static T checkNotNull(T reference) { } return reference; } + + public static void checkPositionIndexes(int start, int end, int size) { + // Carefully optimized for execution by hotspot (explanatory comment + // above) + if (start < 0 || end < start || end > size) { + throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); + } + } + + private static String badPositionIndexes(int start, int end, int size) { + if (start < 0 || start > size) { + return badPositionIndex(start, size, "start index"); + } + if (end < 0 || end > size) { + return badPositionIndex(end, size, "end index"); + } + // end < start + return format("end index (%s) must not be less than start index (%s)", end, start); + } + + private static String badPositionIndex(int index, int size, String desc) { + if (index < 0) { + return format("%s (%s) must not be negative", desc, index); + } else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } else { // index > size + return format("%s (%s) must not be greater than size (%s)", desc, index, size); + } + } + + /** + * Substitutes each {@code %s} in {@code template} with an argument. These are matched by + * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than + * placeholders, the unmatched arguments will be appended to the end of the formatted message in + * square braces. + * + * @param template a non-null string containing 0 or more {@code %s} placeholders. + * @param args the arguments to be substituted into the message template. Arguments are converted + * to strings using {@link String#valueOf(Object)}. Arguments can be null. + */ + // Note that this is somewhat-improperly used from Verify.java as well. + static String format(String template, Object... args) { + template = String.valueOf(template); // null -> "null" + + // start substituting the arguments into the '%s' placeholders + StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); + int templateStart = 0; + int i = 0; + while (i < args.length) { + int placeholderStart = template.indexOf("%s", templateStart); + if (placeholderStart == -1) { + break; + } + builder.append(template.substring(templateStart, placeholderStart)); + builder.append(args[i++]); + templateStart = placeholderStart + 2; + } + builder.append(template.substring(templateStart)); + + // if we run out of placeholders, append the extra args in square braces + if (i < args.length) { + builder.append(" ["); + builder.append(args[i++]); + while (i < args.length) { + builder.append(", "); + builder.append(args[i++]); + } + builder.append(']'); + } + + return builder.toString(); + } public static void hasLength(String text, String message) { if (StringKit.isEmpty(text)) { diff --git a/blade-kit/src/main/java/blade/kit/CharKit.java b/blade-kit/src/main/java/blade/kit/CharKit.java index 48b8a267d..85f1898b9 100644 --- a/blade-kit/src/main/java/blade/kit/CharKit.java +++ b/blade-kit/src/main/java/blade/kit/CharKit.java @@ -236,9 +236,6 @@ public static byte[] toAsciiByteArray(CharSequence charSequence) { return barr; } - // ---------------------------------------------------------------- raw - // arrays - public static byte[] toRawByteArray(char[] carr) { if (carr == null) { return null; @@ -275,8 +272,6 @@ public static char[] toRawCharArray(byte[] barr) { return carr; } - // ---------------------------------------------------------------- encoding - public static byte[] toByteArray(char[] carr) throws UnsupportedEncodingException { if (carr == null) { return null; @@ -305,8 +300,6 @@ public static char[] toCharArray(byte[] barr, String charset) throws Unsupported return new String(barr, charset).toCharArray(); } - // ---------------------------------------------------------------- find - public static boolean equalsOne(char c, char[] match) { if (match == null) { return false; @@ -367,9 +360,7 @@ public static int findFirstDiff(char[] source, int index, char match) { } return -1; } - - // ---------------------------------------------------------------- is - + public static boolean isLowercaseLetter(char c) { return (c >= 'a') && (c <= 'z'); } @@ -414,9 +405,6 @@ public static boolean isChinese(char c) { return (c >= 0x4e00 && c <= 0x9fa5); } - // ---------------------------------------------------------------- - // conversions - public static char toUpperAscii(char c) { if (isLowercaseLetter(c)) { c -= (char) 0x20; diff --git a/blade-kit/src/main/java/blade/kit/CollectionKit.java b/blade-kit/src/main/java/blade/kit/CollectionKit.java index cf455f29c..cf539946d 100644 --- a/blade-kit/src/main/java/blade/kit/CollectionKit.java +++ b/blade-kit/src/main/java/blade/kit/CollectionKit.java @@ -64,6 +64,9 @@ */ public abstract class CollectionKit { + private static final int DEFAULT_INITIAL_CAPACITY = 16; + private static final int DEFAULT_CONCURRENCY_LEVEL = 4; + /** * new HashMap */ @@ -96,7 +99,7 @@ public static LinkedHashMap newLinkedHashMap(int size) { * new concurrentHashMap */ public static ConcurrentHashMap newConcurrentHashMap() { - return new ConcurrentHashMap(); + return new ConcurrentHashMap(DEFAULT_INITIAL_CAPACITY, 0.75f, DEFAULT_CONCURRENCY_LEVEL); } /** @@ -105,7 +108,7 @@ public static ConcurrentHashMap newConcurrentHashMap() { public static ConcurrentHashMap newConcurrentHashMap(int size) { return new ConcurrentHashMap(size); } - + /** * new ArrayList */ diff --git a/blade-kit/src/main/java/blade/kit/IOKit.java b/blade-kit/src/main/java/blade/kit/IOKit.java index e2476f245..2fc14061b 100644 --- a/blade-kit/src/main/java/blade/kit/IOKit.java +++ b/blade-kit/src/main/java/blade/kit/IOKit.java @@ -61,7 +61,7 @@ public final class IOKit { /** * The default buffer size to use. */ - public static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + public static final int DEFAULT_BUFFER_SIZE = 0x1000; private IOKit() { } diff --git a/blade-kit/src/main/java/blade/kit/log/JdkLogger.java b/blade-kit/src/main/java/blade/kit/log/JdkLogger.java index 5b96cdcc0..7c14839d0 100644 --- a/blade-kit/src/main/java/blade/kit/log/JdkLogger.java +++ b/blade-kit/src/main/java/blade/kit/log/JdkLogger.java @@ -3,7 +3,7 @@ import java.util.logging.Level; /** - * JDK的日志适配 + * JDK的日志实现 * * @author biezhi * @since 1.0 diff --git a/blade-kit/src/main/java/blade/kit/log/Log4jLogger.java b/blade-kit/src/main/java/blade/kit/log/Log4jLogger.java index fd18d8747..2dd73380f 100644 --- a/blade-kit/src/main/java/blade/kit/log/Log4jLogger.java +++ b/blade-kit/src/main/java/blade/kit/log/Log4jLogger.java @@ -4,7 +4,7 @@ import org.apache.log4j.Priority; /** - * Log4j日志适配 + * Log4j的日志实现 * * @author biezhi * @since 1.0 diff --git a/blade-kit/src/main/java/blade/kit/log/SimpleLogger.java b/blade-kit/src/main/java/blade/kit/log/SimpleLogger.java index 00982814f..07ea0921d 100644 --- a/blade-kit/src/main/java/blade/kit/log/SimpleLogger.java +++ b/blade-kit/src/main/java/blade/kit/log/SimpleLogger.java @@ -5,7 +5,7 @@ import java.util.Date; /** - * Blade自带的日志实现 + * 默认日志实现 * * @author biezhi * @since 1.0 diff --git a/blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java b/blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java index 8e0021044..46bc4ae5d 100644 --- a/blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java +++ b/blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java @@ -3,10 +3,10 @@ public class SimpleLoggerFactory implements LoggerFactory { public Logger getLogger(Class clazz) { - return new JdkLogger(clazz); + return new SimpleLogger(clazz.getName()); } public Logger getLogger(String name) { - return new JdkLogger(name); + return new SimpleLogger(name); } } diff --git a/pom.xml b/pom.xml index 6c90da95a..f8a8096a1 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ UTF-8 4.11 3.1.0 - 1.4.0-alpha + 1.4.0-beta From e3393e39343c8df66c7cdea00d4f6309839d285a Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 11:41:42 +0800 Subject: [PATCH 172/545] add blade-startup --- LAST_VERSION.md | 9 + blade-core/pom.xml | 10 +- blade-kit/pom.xml | 8 +- .../src/main/java/blade/kit/TimeKit.java | 68 +++++ .../java/blade/kit/io/AppendableWriter.java | 102 +++++++ .../main/java/blade/kit/io/CharStreams.java | 273 ++++++++++++++++++ .../main/java/blade/kit/io/LineBuffer.java | 104 +++++++ .../main/java/blade/kit/io/LineProcessor.java | 26 ++ .../main/java/blade/kit/io/LineReader.java | 66 +++++ .../main/java/blade/kit/json/JSONObject.java | 10 +- pom.xml | 8 +- 11 files changed, 672 insertions(+), 12 deletions(-) create mode 100644 blade-kit/src/main/java/blade/kit/TimeKit.java create mode 100644 blade-kit/src/main/java/blade/kit/io/AppendableWriter.java create mode 100644 blade-kit/src/main/java/blade/kit/io/CharStreams.java create mode 100644 blade-kit/src/main/java/blade/kit/io/LineBuffer.java create mode 100644 blade-kit/src/main/java/blade/kit/io/LineProcessor.java create mode 100644 blade-kit/src/main/java/blade/kit/io/LineReader.java diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 63ab1b2dd..e903c0412 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -87,4 +87,13 @@     blade-redis     1.2.3 +``` + +## [blade-startup](http://search.maven.org/#search%7Cga%7C1%7Cblade-startup) +```xml + +    com.bladejava +    blade-startup +    1.0.0 + ``` \ No newline at end of file diff --git a/blade-core/pom.xml b/blade-core/pom.xml index f89e44c6e..9c7e902dc 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -16,6 +16,7 @@ https://github.com/biezhi/blade/blade-core + 3.0.1 9.3.4.v20151007 @@ -25,10 +26,13 @@ blade-kit 1.2.7-beta + - javax.servlet - javax.servlet-api - + javax.servlet + javax.servlet-api + ${servlet.version} + provided + org.eclipse.jetty diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index 98b72a4dd..247e3647e 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -14,7 +14,11 @@ 1.2.7-beta blade-kit https://github.com/biezhi/blade/tree/master/blade-kit - + + + 3.0.1 + + junit @@ -35,6 +39,8 @@ javax.servlet javax.servlet-api + ${servlet.version} + provided diff --git a/blade-kit/src/main/java/blade/kit/TimeKit.java b/blade-kit/src/main/java/blade/kit/TimeKit.java new file mode 100644 index 000000000..f67dcb33b --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/TimeKit.java @@ -0,0 +1,68 @@ +package blade.kit; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * 时间处理类 + * + * @author biezhi + * @since 1.0 + */ +public class TimeKit { + + public static final SimpleDateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + public static final SimpleDateFormat DATE_FORMAT_DATE = new SimpleDateFormat("yyyy-MM-dd"); + + private TimeKit() { + throw new AssertionError(); + } + + /** + * long time to string + * + * @param timeInMillis + * @param dateFormat + * @return + */ + public static String getTime(long timeInMillis, SimpleDateFormat dateFormat) { + return dateFormat.format(new Date(timeInMillis)); + } + + /** + * long time to string, format is {@link #DEFAULT_DATE_FORMAT} + * + * @param timeInMillis + * @return + */ + public static String getTime(long timeInMillis) { + return getTime(timeInMillis, DEFAULT_DATE_FORMAT); + } + + /** + * get current time in milliseconds + * + * @return + */ + public static long getCurrentTimeInLong() { + return System.currentTimeMillis(); + } + + /** + * get current time in milliseconds, format is {@link #DEFAULT_DATE_FORMAT} + * + * @return + */ + public static String getCurrentTimeInString() { + return getTime(getCurrentTimeInLong()); + } + + /** + * get current time in milliseconds + * + * @return + */ + public static String getCurrentTimeInString(SimpleDateFormat dateFormat) { + return getTime(getCurrentTimeInLong(), dateFormat); + } +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/io/AppendableWriter.java b/blade-kit/src/main/java/blade/kit/io/AppendableWriter.java new file mode 100644 index 000000000..11a721def --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/io/AppendableWriter.java @@ -0,0 +1,102 @@ +package blade.kit.io; + +import java.io.Closeable; +import java.io.Flushable; +import java.io.IOException; +import java.io.Writer; +import static blade.kit.Assert.checkNotNull; + +/** + * Writer that places all output on an {@link Appendable} target. If the target + * is {@link Flushable} or {@link Closeable}, flush()es and close()s will also + * be delegated to the target. + * + * @author Alan Green + * @author Sebastian Kanthak + * @since 1.0 + */ +class AppendableWriter extends Writer { + private final Appendable target; + private boolean closed; + + /** + * Creates a new writer that appends everything it writes to {@code target}. + * + * @param target target to which to append output + */ + AppendableWriter(Appendable target) { + this.target = checkNotNull(target); + } + + /* + * Abstract methods from Writer + */ + + @Override public void write(char cbuf[], int off, int len) + throws IOException { + checkNotClosed(); + // It turns out that creating a new String is usually as fast, or faster + // than wrapping cbuf in a light-weight CharSequence. + target.append(new String(cbuf, off, len)); + } + + @Override public void flush() throws IOException { + checkNotClosed(); + if (target instanceof Flushable) { + ((Flushable) target).flush(); + } + } + + @Override public void close() throws IOException { + this.closed = true; + if (target instanceof Closeable) { + ((Closeable) target).close(); + } + } + + /* + * Override a few functions for performance reasons to avoid creating + * unnecessary strings. + */ + + @Override public void write(int c) throws IOException { + checkNotClosed(); + target.append((char) c); + } + + @Override public void write(String str) throws IOException { + checkNotClosed(); + target.append(str); + } + + @Override public void write(String str, int off, int len) throws IOException { + checkNotClosed(); + // tricky: append takes start, end pair... + target.append(str, off, off + len); + } + + @Override public Writer append(char c) throws IOException { + checkNotClosed(); + target.append(c); + return this; + } + + @Override public Writer append(CharSequence charSeq) throws IOException { + checkNotClosed(); + target.append(charSeq); + return this; + } + + @Override public Writer append(CharSequence charSeq, int start, int end) + throws IOException { + checkNotClosed(); + target.append(charSeq, start, end); + return this; + } + + private void checkNotClosed() throws IOException { + if (closed) { + throw new IOException("Cannot write to a closed writer."); + } + } +} diff --git a/blade-kit/src/main/java/blade/kit/io/CharStreams.java b/blade-kit/src/main/java/blade/kit/io/CharStreams.java new file mode 100644 index 000000000..0d98ffb39 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/io/CharStreams.java @@ -0,0 +1,273 @@ +package blade.kit.io; + + +import java.io.Closeable; +import java.io.EOFException; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.nio.CharBuffer; +import java.util.ArrayList; +import java.util.List; + +import static blade.kit.Assert.checkNotNull; +import static blade.kit.Assert.checkPositionIndexes; + +import blade.kit.Assert; + +/** + * Provides utility methods for working with character streams. + * + *

All method parameters must be non-null unless documented otherwise. + * + *

Some of the methods in this class take arguments with a generic type of + * {@code Readable & Closeable}. A {@link java.io.Reader} implements both of + * those interfaces. Similarly for {@code Appendable & Closeable} and + * {@link java.io.Writer}. + * + * @author Chris Nokleberg + * @author Bin Zhu + * @author Colin Decker + * @since 1.0 + */ +public final class CharStreams { + private static final int BUF_SIZE = 0x800; // 2K chars (4K bytes) + + private CharStreams() {} + + /** + * Copies all characters between the {@link Readable} and {@link Appendable} + * objects. Does not close or flush either object. + * + * @param from the object to read from + * @param to the object to write to + * @return the number of characters copied + * @throws IOException if an I/O error occurs + */ + public static long copy(Readable from, Appendable to) throws IOException { + Assert.checkNotNull(from); + checkNotNull(to); + CharBuffer buf = CharBuffer.allocate(BUF_SIZE); + long total = 0; + while (from.read(buf) != -1) { + buf.flip(); + to.append(buf); + total += buf.remaining(); + buf.clear(); + } + return total; + } + + /** + * Reads all characters from a {@link Readable} object into a {@link String}. + * Does not close the {@code Readable}. + * + * @param r the object to read from + * @return a string containing all the characters + * @throws IOException if an I/O error occurs + */ + public static String toString(Readable r) throws IOException { + return toStringBuilder(r).toString(); + } + + /** + * Reads all characters from a {@link Readable} object into a new + * {@link StringBuilder} instance. Does not close the {@code Readable}. + * + * @param r the object to read from + * @return a {@link StringBuilder} containing all the characters + * @throws IOException if an I/O error occurs + */ + private static StringBuilder toStringBuilder(Readable r) throws IOException { + StringBuilder sb = new StringBuilder(); + copy(r, sb); + return sb; + } + + /** + * Reads all of the lines from a {@link Readable} object. The lines do + * not include line-termination characters, but do include other + * leading and trailing whitespace. + * + *

Does not close the {@code Readable}. If reading files or resources you + * should use the {@link Files#readLines} and {@link Resources#readLines} + * methods. + * + * @param r the object to read from + * @return a mutable {@link List} containing all the lines + * @throws IOException if an I/O error occurs + */ + public static List readLines(Readable r) throws IOException { + List result = new ArrayList(); + LineReader lineReader = new LineReader(r); + String line; + while ((line = lineReader.readLine()) != null) { + result.add(line); + } + return result; + } + + /** + * Streams lines from a {@link Readable} object, stopping when the processor + * returns {@code false} or all lines have been read and returning the result + * produced by the processor. Does not close {@code readable}. Note that this + * method may not fully consume the contents of {@code readable} if the + * processor stops processing early. + * + * @throws IOException if an I/O error occurs + * @since 14.0 + */ + public static T readLines( + Readable readable, LineProcessor processor) throws IOException { + checkNotNull(readable); + checkNotNull(processor); + + LineReader lineReader = new LineReader(readable); + String line; + while ((line = lineReader.readLine()) != null) { + if (!processor.processLine(line)) { + break; + } + } + return processor.getResult(); + } + + /** + * Discards {@code n} characters of data from the reader. This method + * will block until the full amount has been skipped. Does not close the + * reader. + * + * @param reader the reader to read from + * @param n the number of characters to skip + * @throws EOFException if this stream reaches the end before skipping all + * the characters + * @throws IOException if an I/O error occurs + */ + public static void skipFully(Reader reader, long n) throws IOException { + checkNotNull(reader); + while (n > 0) { + long amt = reader.skip(n); + if (amt == 0) { + // force a blocking read + if (reader.read() == -1) { + throw new EOFException(); + } + n--; + } else { + n -= amt; + } + } + } + + /** + * Returns a {@link Writer} that simply discards written chars. + * + * @since 15.0 + */ + public static Writer nullWriter() { + return NullWriter.INSTANCE; + } + + private static final class NullWriter extends Writer { + + private static final NullWriter INSTANCE = new NullWriter(); + + @Override + public void write(int c) { + } + + @Override + public void write(char[] cbuf) { + checkNotNull(cbuf); + } + + @Override + public void write(char[] cbuf, int off, int len) { + checkPositionIndexes(off, off + len, cbuf.length); + } + + @Override + public void write(String str) { + checkNotNull(str); + } + + @Override + public void write(String str, int off, int len) { + checkPositionIndexes(off, off + len, str.length()); + } + + @Override + public Writer append(CharSequence csq) { + checkNotNull(csq); + return this; + } + + @Override + public Writer append(CharSequence csq, int start, int end) { + checkPositionIndexes(start, end, csq.length()); + return this; + } + + @Override + public Writer append(char c) { + return this; + } + + @Override + public void flush() { + } + + @Override + public void close() { + } + + @Override + public String toString() { + return "CharStreams.nullWriter()"; + } + } + + /** + * Returns a Writer that sends all output to the given {@link Appendable} + * target. Closing the writer will close the target if it is {@link + * Closeable}, and flushing the writer will flush the target if it is {@link + * java.io.Flushable}. + * + * @param target the object to which output will be sent + * @return a new Writer object, unless target is a Writer, in which case the + * target is returned + */ + public static Writer asWriter(Appendable target) { + if (target instanceof Writer) { + return (Writer) target; + } + return new AppendableWriter(target); + } + + // TODO(user): Remove these once Input/OutputSupplier methods are removed + + static Reader asReader(final Readable readable) { + checkNotNull(readable); + if (readable instanceof Reader) { + return (Reader) readable; + } + return new Reader() { + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + return read(CharBuffer.wrap(cbuf, off, len)); + } + + @Override + public int read(CharBuffer target) throws IOException { + return readable.read(target); + } + + @Override + public void close() throws IOException { + if (readable instanceof Closeable) { + ((Closeable) readable).close(); + } + } + }; + } +} diff --git a/blade-kit/src/main/java/blade/kit/io/LineBuffer.java b/blade-kit/src/main/java/blade/kit/io/LineBuffer.java new file mode 100644 index 000000000..ac0830c63 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/io/LineBuffer.java @@ -0,0 +1,104 @@ +package blade.kit.io; + +import java.io.IOException; + +/** + * Package-protected abstract class that implements the line reading + * algorithm used by {@link LineReader}. Line separators are per {@link + * java.io.BufferedReader}: line feed, carriage return, or carriage + * return followed immediately by a linefeed. + * + *

Subclasses must implement {@link #handleLine}, call {@link #add} + * to pass character data, and call {@link #finish} at the end of stream. + * + * @author Chris Nokleberg + * @since 1.0 + */ +abstract class LineBuffer { + /** Holds partial line contents. */ + private StringBuilder line = new StringBuilder(); + /** Whether a line ending with a CR is pending processing. */ + private boolean sawReturn; + + /** + * Process additional characters from the stream. When a line separator + * is found the contents of the line and the line separator itself + * are passed to the abstract {@link #handleLine} method. + * + * @param cbuf the character buffer to process + * @param off the offset into the buffer + * @param len the number of characters to process + * @throws IOException if an I/O error occurs + * @see #finish + */ + protected void add(char[] cbuf, int off, int len) throws IOException { + int pos = off; + if (sawReturn && len > 0) { + // Last call to add ended with a CR; we can handle the line now. + if (finishLine(cbuf[pos] == '\n')) { + pos++; + } + } + + int start = pos; + for (int end = off + len; pos < end; pos++) { + switch (cbuf[pos]) { + case '\r': + line.append(cbuf, start, pos - start); + sawReturn = true; + if (pos + 1 < end) { + if (finishLine(cbuf[pos + 1] == '\n')) { + pos++; + } + } + start = pos + 1; + break; + + case '\n': + line.append(cbuf, start, pos - start); + finishLine(true); + start = pos + 1; + break; + + default: + // do nothing + } + } + line.append(cbuf, start, off + len - start); + } + + /** Called when a line is complete. */ + private boolean finishLine(boolean sawNewline) throws IOException { + handleLine(line.toString(), sawReturn + ? (sawNewline ? "\r\n" : "\r") + : (sawNewline ? "\n" : "")); + line = new StringBuilder(); + sawReturn = false; + return sawNewline; + } + + /** + * Subclasses must call this method after finishing character processing, + * in order to ensure that any unterminated line in the buffer is + * passed to {@link #handleLine}. + * + * @throws IOException if an I/O error occurs + */ + protected void finish() throws IOException { + if (sawReturn || line.length() > 0) { + finishLine(false); + } + } + + /** + * Called for each line found in the character data passed to + * {@link #add}. + * + * @param line a line of text (possibly empty), without any line separators + * @param end the line separator; one of {@code "\r"}, {@code "\n"}, + * {@code "\r\n"}, or {@code ""} + * @throws IOException if an I/O error occurs + */ + protected abstract void handleLine(String line, String end) + throws IOException; +} diff --git a/blade-kit/src/main/java/blade/kit/io/LineProcessor.java b/blade-kit/src/main/java/blade/kit/io/LineProcessor.java new file mode 100644 index 000000000..a1c33af44 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/io/LineProcessor.java @@ -0,0 +1,26 @@ +package blade.kit.io; + +import java.io.IOException; + +/** + * A callback to be used with the streaming {@code readLines} methods. + * + *

{@link #processLine} will be called for each line that is read, and + * should return {@code false} when you want to stop processing. + * + * @author Miles Barr + * @since 1.0 + */ +public interface LineProcessor { + + /** + * This method will be called once for each line. + * + * @param line the line read from the input, without delimiter + * @return true to continue processing, false to stop + */ + boolean processLine(String line) throws IOException; + + /** Return the result of processing all the lines. */ + T getResult(); +} diff --git a/blade-kit/src/main/java/blade/kit/io/LineReader.java b/blade-kit/src/main/java/blade/kit/io/LineReader.java new file mode 100644 index 000000000..cb458c88a --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/io/LineReader.java @@ -0,0 +1,66 @@ +package blade.kit.io; + +import java.io.IOException; +import java.io.Reader; +import java.nio.CharBuffer; +import java.util.LinkedList; +import java.util.Queue; +import static blade.kit.Assert.checkNotNull; +/** + * A class for reading lines of text. Provides the same functionality + * as {@link java.io.BufferedReader#readLine()} but for all {@link Readable} + * objects, not just instances of {@link Reader}. + * + * @author Chris Nokleberg + * @since 1.0 + */ +public final class LineReader { + private final Readable readable; + private final Reader reader; + private final char[] buf = new char[0x1000]; // 4K + private final CharBuffer cbuf = CharBuffer.wrap(buf); + + private final Queue lines = new LinkedList(); + private final LineBuffer lineBuf = new LineBuffer() { + @Override protected void handleLine(String line, String end) { + lines.add(line); + } + }; + + /** + * Creates a new instance that will read lines from the given + * {@code Readable} object. + */ + public LineReader(Readable readable) { + this.readable = checkNotNull(readable); + this.reader = (readable instanceof Reader) ? (Reader) readable : null; + } + + /** + * Reads a line of text. A line is considered to be terminated by any + * one of a line feed ({@code '\n'}), a carriage return + * ({@code '\r'}), or a carriage return followed immediately by a linefeed + * ({@code "\r\n"}). + * + * @return a {@code String} containing the contents of the line, not + * including any line-termination characters, or {@code null} if the + * end of the stream has been reached. + * @throws IOException if an I/O error occurs + */ + public String readLine() throws IOException { + while (lines.peek() == null) { + cbuf.clear(); + // The default implementation of Reader#read(CharBuffer) allocates a + // temporary char[], so we call Reader#read(char[], int, int) instead. + int read = (reader != null) + ? reader.read(buf, 0, buf.length) + : readable.read(cbuf); + if (read == -1) { + lineBuf.finish(); + break; + } + lineBuf.add(buf, 0, read); + } + return lines.poll(); + } +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONObject.java b/blade-kit/src/main/java/blade/kit/json/JSONObject.java index 0f91ac2e4..8f4e56d0e 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONObject.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONObject.java @@ -38,7 +38,15 @@ public JSONObject() { public JSONObject(Map map) { super(map); } - + + public boolean put(String key, Object value){ + return this.put(key, value); + } + + public Object put(Object key, Object value){ + return this.put(key, value); + } + public Object get(String key) throws JSONException { if (key == null) { throw new JSONException("Null key."); diff --git a/pom.xml b/pom.xml index f8a8096a1..4f0344558 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,6 @@ 1.6 UTF-8 4.11 - 3.1.0 1.4.0-beta @@ -28,6 +27,7 @@ blade-velocity blade-beetl blade-redis + blade-startup @@ -38,12 +38,6 @@ ${junit.version} test - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - From 7e46fb8bc36eb7c417a1ddd8fc66b161812c1952 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 11:42:03 +0800 Subject: [PATCH 173/545] add blade-startup --- blade-startup/pom.xml | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 blade-startup/pom.xml diff --git a/blade-startup/pom.xml b/blade-startup/pom.xml new file mode 100644 index 000000000..63a824e71 --- /dev/null +++ b/blade-startup/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + + blade-startup + 1.0.0 + blade-startup + + https://github.com/biezhi/blade/blade-startup + + + UTF-8 + 9.3.4.v20151007 + 3.1.0 + + + + + com.bladejava + blade-core + ${blade.version} + + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + + + + org.eclipse.jetty + jetty-servlet + 9.3.4.v20151007 + + + + + From e47fd26fb85edd110a5fed6999480e314252daf6 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 13:19:21 +0800 Subject: [PATCH 174/545] jsonarray add method addAll --- blade-core/pom.xml | 13 +------------ .../src/main/java/blade/kit/json/JSONArray.java | 16 ++++++++++++++++ blade-kit/src/test/java/blade/test/JSONTest.java | 9 +++++++++ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 9c7e902dc..e2d914956 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -46,17 +46,6 @@ ${jetty.version} provided - - org.testng - testng - 6.9.6 - provided - - - org.mockito - mockito-all - 2.0.2-beta - test - + diff --git a/blade-kit/src/main/java/blade/kit/json/JSONArray.java b/blade-kit/src/main/java/blade/kit/json/JSONArray.java index fcb612584..9d2f071e0 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONArray.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONArray.java @@ -40,6 +40,22 @@ public JSONArray(Collection c){ super(c); } + public boolean add(Object object){ + return this.add(object); + } + + public void add(int index, Object object){ + this.add(index, object); + } + + public boolean addAll(Collection collection){ + return this.addAll(collection); + } + + public boolean addAll(int index, Collection collection){ + return this.addAll(index, collection); + } + /** * Encode a list into JSON text and write it to out. * If this list is also a JSONStreamAware or a JSONAware, JSONStreamAware and JSONAware specific behaviours will be ignored at this top level. diff --git a/blade-kit/src/test/java/blade/test/JSONTest.java b/blade-kit/src/test/java/blade/test/JSONTest.java index 565c32112..56d8d8d42 100644 --- a/blade-kit/src/test/java/blade/test/JSONTest.java +++ b/blade-kit/src/test/java/blade/test/JSONTest.java @@ -5,7 +5,9 @@ import java.util.List; import java.util.Map; +import blade.kit.json.JSONArray; import blade.kit.json.JSONKit; +import blade.kit.json.JSONObject; public class JSONTest { @@ -31,6 +33,13 @@ public static void main(String[] args) { System.out.println(string); System.out.println(JSONKit.toList(json)); + + + JSONObject obj1 = new JSONObject(); + obj1.put("", ""); + + JSONArray obj2 = new JSONArray(); + obj2.add(""); } } From c883344c793b939f6c8351f5de25ca31bd3b2eab Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 13:21:46 +0800 Subject: [PATCH 175/545] reset --- .../src/main/java/blade/kit/json/JSONMap.java | 38 -- .../main/java/blade/kit/json/JSONString.java | 18 - .../java/blade/kit/json/JSONStringer.java | 78 --- .../main/java/blade/kit/json/JSONTokener.java | 446 ------------------ .../main/java/blade/kit/json/JSONWriter.java | 327 ------------- .../java/blade/kit/log/JDKLoggerAdaptor.java | 75 --- .../java/blade/kit/log/Log4jLogAdaptor.java | 186 -------- .../java/blade/kit/log/SysLoggerAdaptor.java | 75 --- 8 files changed, 1243 deletions(-) delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONMap.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONString.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONStringer.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONTokener.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONWriter.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/JDKLoggerAdaptor.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/Log4jLogAdaptor.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java diff --git a/blade-kit/src/main/java/blade/kit/json/JSONMap.java b/blade-kit/src/main/java/blade/kit/json/JSONMap.java deleted file mode 100644 index 834840211..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JSONMap.java +++ /dev/null @@ -1,38 +0,0 @@ -package blade.kit.json; - -import java.util.Iterator; -import java.util.Map; - -import blade.kit.CollectionKit; - -@SuppressWarnings("unchecked") -public class JSONMap { - - public static JSONObject toJSONObject(Map map) throws JSONException { - JSONObject jo = new JSONObject(); - if (map != null && !map.isEmpty()) { - Iterator iterator = map.entrySet().iterator(); - while(iterator.hasNext()) { - Map.Entry entry = (Map.Entry) iterator.next(); - String key = entry.getKey(); - Object val = entry.getValue(); - jo.put(key, val); - } - } - return jo; - } - - public static Map toMap(JSONObject jo) throws JSONException { - Map properties = CollectionKit.newHashMap(); - if (jo != null) { - Iterator keys = jo.keys(); - while (keys.hasNext()) { - String name = keys.next(); - K k = (K) name; - V v = (V) jo.get(name); - properties.put(k, v); - } - } - return properties; - } -} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONString.java b/blade-kit/src/main/java/blade/kit/json/JSONString.java deleted file mode 100644 index 70d3f5508..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JSONString.java +++ /dev/null @@ -1,18 +0,0 @@ -package blade.kit.json; -/** - * The JSONString interface allows a toJSONString() - * method so that a class can change the behavior of - * JSONObject.toString(), JSONArray.toString(), - * and JSONWriter.value(Object). The - * toJSONString method will be used instead of the default behavior - * of using the Object's toString() method and quoting the result. - */ -public interface JSONString { - /** - * The toJSONString method allows a class to produce its own JSON - * serialization. - * - * @return A strictly syntactically correct JSON text. - */ - public String toJSONString(); -} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONStringer.java b/blade-kit/src/main/java/blade/kit/json/JSONStringer.java deleted file mode 100644 index 9e128f4d4..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JSONStringer.java +++ /dev/null @@ -1,78 +0,0 @@ -package blade.kit.json; - -/* -Copyright (c) 2006 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -import java.io.StringWriter; - -/** - * JSONStringer provides a quick and convenient way of producing JSON text. - * The texts produced strictly conform to JSON syntax rules. No whitespace is - * added, so the results are ready for transmission or storage. Each instance of - * JSONStringer can produce one JSON text. - *

- * A JSONStringer instance provides a value method for appending - * values to the - * text, and a key - * method for adding keys before values in objects. There are array - * and endArray methods that make and bound array values, and - * object and endObject methods which make and bound - * object values. All of these methods return the JSONWriter instance, - * permitting cascade style. For example,

- * myString = new JSONStringer()
- *     .object()
- *         .key("JSON")
- *         .value("Hello, World!")
- *     .endObject()
- *     .toString();
which produces the string
- * {"JSON":"Hello, World!"}
- *

- * The first method called must be array or object. - * There are no methods for adding commas or colons. JSONStringer adds them for - * you. Objects and arrays can be nested up to 20 levels deep. - *

- * This can sometimes be easier than using a JSONObject to build a string. - * @author JSON.org - * @version 2008-09-18 - */ -public class JSONStringer extends JSONWriter { - /** - * Make a fresh JSONStringer. It can be used to build one JSON text. - */ - public JSONStringer() { - super(new StringWriter()); - } - - /** - * Return the JSON text. This method is used to obtain the product of the - * JSONStringer instance. It will return null if there was a - * problem in the construction of the JSON text (such as the calls to - * array were not properly balanced with calls to - * endArray). - * @return The JSON text. - */ - public String toString() { - return this.mode == 'd' ? this.writer.toString() : null; - } -} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONTokener.java b/blade-kit/src/main/java/blade/kit/json/JSONTokener.java deleted file mode 100644 index fb271e1cd..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JSONTokener.java +++ /dev/null @@ -1,446 +0,0 @@ -package blade.kit.json; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; - -/* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * A JSONTokener takes a source string and extracts characters and tokens from - * it. It is used by the JSONObject and JSONArray constructors to parse - * JSON source strings. - * @author JSON.org - * @version 2014-05-03 - */ -public class JSONTokener { - - private long character; - private boolean eof; - private long index; - private long line; - private char previous; - private Reader reader; - private boolean usePrevious; - - - /** - * Construct a JSONTokener from a Reader. - * - * @param reader A reader. - */ - public JSONTokener(Reader reader) { - this.reader = reader.markSupported() - ? reader - : new BufferedReader(reader); - this.eof = false; - this.usePrevious = false; - this.previous = 0; - this.index = 0; - this.character = 1; - this.line = 1; - } - - - /** - * Construct a JSONTokener from an InputStream. - * @param inputStream The source. - */ - public JSONTokener(InputStream inputStream) throws JSONException { - this(new InputStreamReader(inputStream)); - } - - - /** - * Construct a JSONTokener from a string. - * - * @param s A source string. - */ - public JSONTokener(String s) { - this(new StringReader(s)); - } - - - /** - * Back up one character. This provides a sort of lookahead capability, - * so that you can test for a digit or letter before attempting to parse - * the next number or identifier. - */ - public void back() throws JSONException { - if (this.usePrevious || this.index <= 0) { - throw new JSONException("Stepping back two steps is not supported"); - } - this.index -= 1; - this.character -= 1; - this.usePrevious = true; - this.eof = false; - } - - - /** - * Get the hex value of a character (base16). - * @param c A character between '0' and '9' or between 'A' and 'F' or - * between 'a' and 'f'. - * @return An int between 0 and 15, or -1 if c was not a hex digit. - */ - public static int dehexchar(char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - if (c >= 'A' && c <= 'F') { - return c - ('A' - 10); - } - if (c >= 'a' && c <= 'f') { - return c - ('a' - 10); - } - return -1; - } - - public boolean end() { - return this.eof && !this.usePrevious; - } - - - /** - * Determine if the source string still contains characters that next() - * can consume. - * @return true if not yet at the end of the source. - */ - public boolean more() throws JSONException { - this.next(); - if (this.end()) { - return false; - } - this.back(); - return true; - } - - - /** - * Get the next character in the source string. - * - * @return The next character, or 0 if past the end of the source string. - */ - public char next() throws JSONException { - int c; - if (this.usePrevious) { - this.usePrevious = false; - c = this.previous; - } else { - try { - c = this.reader.read(); - } catch (IOException exception) { - throw new JSONException(exception); - } - - if (c <= 0) { // End of stream - this.eof = true; - c = 0; - } - } - this.index += 1; - if (this.previous == '\r') { - this.line += 1; - this.character = c == '\n' ? 0 : 1; - } else if (c == '\n') { - this.line += 1; - this.character = 0; - } else { - this.character += 1; - } - this.previous = (char) c; - return this.previous; - } - - - /** - * Consume the next character, and check that it matches a specified - * character. - * @param c The character to match. - * @return The character. - * @throws JSONException if the character does not match. - */ - public char next(char c) throws JSONException { - char n = this.next(); - if (n != c) { - throw this.syntaxError("Expected '" + c + "' and instead saw '" + - n + "'"); - } - return n; - } - - - /** - * Get the next n characters. - * - * @param n The number of characters to take. - * @return A string of n characters. - * @throws JSONException - * Substring bounds error if there are not - * n characters remaining in the source string. - */ - public String next(int n) throws JSONException { - if (n == 0) { - return ""; - } - - char[] chars = new char[n]; - int pos = 0; - - while (pos < n) { - chars[pos] = this.next(); - if (this.end()) { - throw this.syntaxError("Substring bounds error"); - } - pos += 1; - } - return new String(chars); - } - - - /** - * Get the next char in the string, skipping whitespace. - * @throws JSONException - * @return A character, or 0 if there are no more characters. - */ - public char nextClean() throws JSONException { - for (;;) { - char c = this.next(); - if (c == 0 || c > ' ') { - return c; - } - } - } - - - /** - * Return the characters up to the next close quote character. - * Backslash processing is done. The formal JSON format does not - * allow strings in single quotes, but an implementation is allowed to - * accept them. - * @param quote The quoting character, either - * " (double quote) or - * ' (single quote). - * @return A String. - * @throws JSONException Unterminated string. - */ - public String nextString(char quote) throws JSONException { - char c; - StringBuilder sb = new StringBuilder(); - for (;;) { - c = this.next(); - switch (c) { - case 0: - case '\n': - case '\r': - throw this.syntaxError("Unterminated string"); - case '\\': - c = this.next(); - switch (c) { - case 'b': - sb.append('\b'); - break; - case 't': - sb.append('\t'); - break; - case 'n': - sb.append('\n'); - break; - case 'f': - sb.append('\f'); - break; - case 'r': - sb.append('\r'); - break; - case 'u': - sb.append((char)Integer.parseInt(this.next(4), 16)); - break; - case '"': - case '\'': - case '\\': - case '/': - sb.append(c); - break; - default: - throw this.syntaxError("Illegal escape."); - } - break; - default: - if (c == quote) { - return sb.toString(); - } - sb.append(c); - } - } - } - - - /** - * Get the text up but not including the specified character or the - * end of line, whichever comes first. - * @param delimiter A delimiter character. - * @return A string. - */ - public String nextTo(char delimiter) throws JSONException { - StringBuilder sb = new StringBuilder(); - for (;;) { - char c = this.next(); - if (c == delimiter || c == 0 || c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } - return sb.toString().trim(); - } - sb.append(c); - } - } - - - /** - * Get the text up but not including one of the specified delimiter - * characters or the end of line, whichever comes first. - * @param delimiters A set of delimiter characters. - * @return A string, trimmed. - */ - public String nextTo(String delimiters) throws JSONException { - char c; - StringBuilder sb = new StringBuilder(); - for (;;) { - c = this.next(); - if (delimiters.indexOf(c) >= 0 || c == 0 || - c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } - return sb.toString().trim(); - } - sb.append(c); - } - } - - - /** - * Get the next value. The value can be a Boolean, Double, Integer, - * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. - * @throws JSONException If syntax error. - * - * @return An object. - */ - public Object nextValue() throws JSONException { - char c = this.nextClean(); - String string; - - switch (c) { - case '"': - case '\'': - return this.nextString(c); - case '{': - this.back(); - return new JSONObject(this); - case '[': - this.back(); - return new JSONArray(this); - } - - /* - * Handle unquoted text. This could be the values true, false, or - * null, or it can be a number. An implementation (such as this one) - * is allowed to also accept non-standard forms. - * - * Accumulate characters until we reach the end of the text or a - * formatting character. - */ - - StringBuilder sb = new StringBuilder(); - while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { - sb.append(c); - c = this.next(); - } - this.back(); - - string = sb.toString().trim(); - if ("".equals(string)) { - throw this.syntaxError("Missing value"); - } - return JSONObject.stringToValue(string); - } - - - /** - * Skip characters until the next character is the requested character. - * If the requested character is not found, no characters are skipped. - * @param to A character to skip to. - * @return The requested character, or zero if the requested character - * is not found. - */ - public char skipTo(char to) throws JSONException { - char c; - try { - long startIndex = this.index; - long startCharacter = this.character; - long startLine = this.line; - this.reader.mark(1000000); - do { - c = this.next(); - if (c == 0) { - this.reader.reset(); - this.index = startIndex; - this.character = startCharacter; - this.line = startLine; - return c; - } - } while (c != to); - } catch (IOException exception) { - throw new JSONException(exception); - } - this.back(); - return c; - } - - - /** - * Make a JSONException to signal a syntax error. - * - * @param message The error message. - * @return A JSONException object, suitable for throwing - */ - public JSONException syntaxError(String message) { - return new JSONException(message + this.toString()); - } - - - /** - * Make a printable string of this JSONTokener. - * - * @return " at {index} [character {character} line {line}]" - */ - public String toString() { - return " at " + this.index + " [character " + this.character + " line " + - this.line + "]"; - } -} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONWriter.java b/blade-kit/src/main/java/blade/kit/json/JSONWriter.java deleted file mode 100644 index 6d001b981..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JSONWriter.java +++ /dev/null @@ -1,327 +0,0 @@ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; - -/* -Copyright (c) 2006 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * JSONWriter provides a quick and convenient way of producing JSON text. - * The texts produced strictly conform to JSON syntax rules. No whitespace is - * added, so the results are ready for transmission or storage. Each instance of - * JSONWriter can produce one JSON text. - *

- * A JSONWriter instance provides a value method for appending - * values to the - * text, and a key - * method for adding keys before values in objects. There are array - * and endArray methods that make and bound array values, and - * object and endObject methods which make and bound - * object values. All of these methods return the JSONWriter instance, - * permitting a cascade style. For example,

- * new JSONWriter(myWriter)
- *     .object()
- *         .key("JSON")
- *         .value("Hello, World!")
- *     .endObject();
which writes
- * {"JSON":"Hello, World!"}
- *

- * The first method called must be array or object. - * There are no methods for adding commas or colons. JSONWriter adds them for - * you. Objects and arrays can be nested up to 20 levels deep. - *

- * This can sometimes be easier than using a JSONObject to build a string. - * @author JSON.org - * @version 2011-11-24 - */ -public class JSONWriter { - private static final int maxdepth = 200; - - /** - * The comma flag determines if a comma should be output before the next - * value. - */ - private boolean comma; - - /** - * The current mode. Values: - * 'a' (array), - * 'd' (done), - * 'i' (initial), - * 'k' (key), - * 'o' (object). - */ - protected char mode; - - /** - * The object/array stack. - */ - private final JSONObject stack[]; - - /** - * The stack top index. A value of 0 indicates that the stack is empty. - */ - private int top; - - /** - * The writer that will receive the output. - */ - protected Writer writer; - - /** - * Make a fresh JSONWriter. It can be used to build one JSON text. - */ - public JSONWriter(Writer w) { - this.comma = false; - this.mode = 'i'; - this.stack = new JSONObject[maxdepth]; - this.top = 0; - this.writer = w; - } - - /** - * Append a value. - * @param string A string value. - * @return this - * @throws JSONException If the value is out of sequence. - */ - private JSONWriter append(String string) throws JSONException { - if (string == null) { - throw new JSONException("Null pointer"); - } - if (this.mode == 'o' || this.mode == 'a') { - try { - if (this.comma && this.mode == 'a') { - this.writer.write(','); - } - this.writer.write(string); - } catch (IOException e) { - throw new JSONException(e); - } - if (this.mode == 'o') { - this.mode = 'k'; - } - this.comma = true; - return this; - } - throw new JSONException("Value out of sequence."); - } - - /** - * Begin appending a new array. All values until the balancing - * endArray will be appended to this array. The - * endArray method must be called to mark the array's end. - * @return this - * @throws JSONException If the nesting is too deep, or if the object is - * started in the wrong place (for example as a key or after the end of the - * outermost array or object). - */ - public JSONWriter array() throws JSONException { - if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { - this.push(null); - this.append("["); - this.comma = false; - return this; - } - throw new JSONException("Misplaced array."); - } - - /** - * End something. - * @param mode Mode - * @param c Closing character - * @return this - * @throws JSONException If unbalanced. - */ - private JSONWriter end(char mode, char c) throws JSONException { - if (this.mode != mode) { - throw new JSONException(mode == 'a' - ? "Misplaced endArray." - : "Misplaced endObject."); - } - this.pop(mode); - try { - this.writer.write(c); - } catch (IOException e) { - throw new JSONException(e); - } - this.comma = true; - return this; - } - - /** - * End an array. This method most be called to balance calls to - * array. - * @return this - * @throws JSONException If incorrectly nested. - */ - public JSONWriter endArray() throws JSONException { - return this.end('a', ']'); - } - - /** - * End an object. This method most be called to balance calls to - * object. - * @return this - * @throws JSONException If incorrectly nested. - */ - public JSONWriter endObject() throws JSONException { - return this.end('k', '}'); - } - - /** - * Append a key. The key will be associated with the next value. In an - * object, every value must be preceded by a key. - * @param string A key string. - * @return this - * @throws JSONException If the key is out of place. For example, keys - * do not belong in arrays or if the key is null. - */ - public JSONWriter key(String string) throws JSONException { - if (string == null) { - throw new JSONException("Null key."); - } - if (this.mode == 'k') { - try { - this.stack[this.top - 1].putOnce(string, Boolean.TRUE); - if (this.comma) { - this.writer.write(','); - } - this.writer.write(JSONObject.quote(string)); - this.writer.write(':'); - this.comma = false; - this.mode = 'o'; - return this; - } catch (IOException e) { - throw new JSONException(e); - } - } - throw new JSONException("Misplaced key."); - } - - - /** - * Begin appending a new object. All keys and values until the balancing - * endObject will be appended to this object. The - * endObject method must be called to mark the object's end. - * @return this - * @throws JSONException If the nesting is too deep, or if the object is - * started in the wrong place (for example as a key or after the end of the - * outermost array or object). - */ - public JSONWriter object() throws JSONException { - if (this.mode == 'i') { - this.mode = 'o'; - } - if (this.mode == 'o' || this.mode == 'a') { - this.append("{"); - this.push(new JSONObject()); - this.comma = false; - return this; - } - throw new JSONException("Misplaced object."); - - } - - - /** - * Pop an array or object scope. - * @param c The scope to close. - * @throws JSONException If nesting is wrong. - */ - private void pop(char c) throws JSONException { - if (this.top <= 0) { - throw new JSONException("Nesting error."); - } - char m = this.stack[this.top - 1] == null ? 'a' : 'k'; - if (m != c) { - throw new JSONException("Nesting error."); - } - this.top -= 1; - this.mode = this.top == 0 - ? 'd' - : this.stack[this.top - 1] == null - ? 'a' - : 'k'; - } - - /** - * Push an array or object scope. - * @param jo The scope to open. - * @throws JSONException If nesting is too deep. - */ - private void push(JSONObject jo) throws JSONException { - if (this.top >= maxdepth) { - throw new JSONException("Nesting too deep."); - } - this.stack[this.top] = jo; - this.mode = jo == null ? 'a' : 'k'; - this.top += 1; - } - - - /** - * Append either the value true or the value - * false. - * @param b A boolean. - * @return this - * @throws JSONException - */ - public JSONWriter value(boolean b) throws JSONException { - return this.append(b ? "true" : "false"); - } - - /** - * Append a double value. - * @param d A double. - * @return this - * @throws JSONException If the number is not finite. - */ - public JSONWriter value(double d) throws JSONException { - return this.value(new Double(d)); - } - - /** - * Append a long value. - * @param l A long. - * @return this - * @throws JSONException - */ - public JSONWriter value(long l) throws JSONException { - return this.append(Long.toString(l)); - } - - - /** - * Append an object value. - * @param object The object to append. It can be null, or a Boolean, Number, - * String, JSONObject, or JSONArray, or an object that implements JSONString. - * @return this - * @throws JSONException If the value is out of sequence. - */ - public JSONWriter value(Object object) throws JSONException { - return this.append(JSONObject.valueToString(object)); - } -} diff --git a/blade-kit/src/main/java/blade/kit/log/JDKLoggerAdaptor.java b/blade-kit/src/main/java/blade/kit/log/JDKLoggerAdaptor.java deleted file mode 100644 index e7de7adb2..000000000 --- a/blade-kit/src/main/java/blade/kit/log/JDKLoggerAdaptor.java +++ /dev/null @@ -1,75 +0,0 @@ -package blade.kit.log; - -import java.util.logging.Level; - -/** - * JDK的日志适配 - * - * @author biezhi - * @since 1.0 - */ -public class JDKLoggerAdaptor extends Logger { - - private java.util.logging.Logger logger; - - public JDKLoggerAdaptor() { - } - - public JDKLoggerAdaptor(String name) { - this.name = name; - logger = java.util.logging.Logger.getLogger(name); - } - - private Level getLevel(int level) { - switch (level) { - case TRACE: - return Level.FINEST; - case DEBUG: - return Level.FINE; - case INFO: - return Level.INFO; - case WARN: - return Level.WARNING; - case ERROR: - case FATAL: - return Level.SEVERE; - } - return Level.INFO; - } - - @Override - public void log(int level, Object message, Object... args) { - log(level, message, null, args); - } - - @Override - public void log(int level, Object message, Throwable t, Object... args) { - - log(getLevel(level), format(message, args), t); - - } - - private void log(Level level, String msg, Throwable ex) { - if (logger.isLoggable(level)) { - // Hack (?) to get the stack trace. - Throwable dummyException = new Throwable(); - StackTraceElement locations[] = dummyException.getStackTrace(); - // Caller will be the third element - String cname = "unknown"; - String method = "unknown"; - if (locations != null && locations.length > 3) { - StackTraceElement caller = locations[3]; - cname = caller.getClassName(); - method = caller.getMethodName(); - } - - if (ex == null) { - logger.logp(level, cname, method, msg); - } else { - logger.logp(level, cname, method, msg, ex); - } - } - - } - -} diff --git a/blade-kit/src/main/java/blade/kit/log/Log4jLogAdaptor.java b/blade-kit/src/main/java/blade/kit/log/Log4jLogAdaptor.java deleted file mode 100644 index ed113114e..000000000 --- a/blade-kit/src/main/java/blade/kit/log/Log4jLogAdaptor.java +++ /dev/null @@ -1,186 +0,0 @@ -package blade.kit.log; - -import org.apache.log4j.Level; -import org.apache.log4j.Priority; - -/** - * Log4j日志适配 - * - * @author biezhi - * @since 1.0 - */ -@SuppressWarnings("deprecation") -public class Log4jLogAdaptor extends Logger{ - - private static final String FQCN = Log4jLogAdaptor.class.getName(); - private static Priority traceLevel; - private org.apache.log4j.Logger logger; - - static { - try { - traceLevel = (Priority) Level.class.getDeclaredField("TRACE").get(null); - } catch (Exception ex) { - traceLevel = Priority.DEBUG; - } - } - - public Log4jLogAdaptor(String name) { - this.name = name; - logger = org.apache.log4j.Logger.getLogger(name); - } - - @Override - public String getName() { - return this.name; - } - - private Priority getLevel(int level) { - switch (level) { - case TRACE: - return traceLevel; - case DEBUG: - return Priority.DEBUG; - case INFO: - return Priority.INFO; - case WARN: - return Priority.WARN; - case ERROR: - return Priority.ERROR; - case FATAL: - return Priority.FATAL; - } - return Priority.DEBUG; - } - - @Override - public void log(int level, Object message, Object... args) { - message = format(message, args); - logger.log(FQCN, getLevel(level), message, null); - } - - @Override - public void log(int level, Object message, Throwable t, Object... args) { - message = format(message, args); - logger.log(FQCN, getLevel(level), message, t); - } - - @Override - public void trace(Object message) { - - } - - @Override - public void trace(Object message, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void trace(Object message, Throwable t) { - // TODO Auto-generated method stub - - } - - @Override - public void trace(Object message, Throwable t, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void debug(Object message) { - // TODO Auto-generated method stub - - } - - @Override - public void debug(Object message, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void debug(Object message, Throwable t) { - // TODO Auto-generated method stub - - } - - @Override - public void debug(Object message, Throwable t, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void info(Object message) { - // TODO Auto-generated method stub - - } - - @Override - public void info(Object message, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void info(Object message, Throwable t) { - // TODO Auto-generated method stub - - } - - @Override - public void info(Object message, Throwable t, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void warn(Object message) { - // TODO Auto-generated method stub - - } - - @Override - public void warn(Object message, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void warn(Object message, Throwable t) { - // TODO Auto-generated method stub - - } - - @Override - public void warn(Object message, Throwable t, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void error(Object message) { - // TODO Auto-generated method stub - - } - - @Override - public void error(Object message, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void error(Object message, Throwable t) { - // TODO Auto-generated method stub - - } - - @Override - public void error(Object message, Throwable t, Object... args) { - // TODO Auto-generated method stub - - } - -} diff --git a/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java b/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java deleted file mode 100644 index 53aa349da..000000000 --- a/blade-kit/src/main/java/blade/kit/log/SysLoggerAdaptor.java +++ /dev/null @@ -1,75 +0,0 @@ -package blade.kit.log; - -import java.io.PrintStream; -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * Blade自带的日志实现 - * - * @author biezhi - * @since 1.0 - */ -public class SysLoggerAdaptor extends Logger { - - private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"); - - private static PrintStream outprint = System.out; - - public SysLoggerAdaptor() { - } - - public SysLoggerAdaptor(String name) { - this.name = name; - } - - private String getLevel(int level){ - if(level <= TRACE){ - return "TRACE"; - } - if(level <= DEBUG){ - return "DEBUG"; - } - if(level <= INFO){ - return "INFO"; - } - if(level <= WARN){ - return "WARN"; - } - if(level <= ERROR){ - outprint = System.err; - return "ERROR"; - } - if(level <= FATAL){ - return "FATAL"; - } - return "DEBUG"; - } - - private String now() { - return sdf.format(new Date()); - } - - @Override - public void log(int level, Object message, Object... args) { - log(level, message, null, args); - - } - - @Override - public void log(int level, Object message, Throwable t, Object... args) { - - StringBuilder sb = new StringBuilder(now()); - sb.append(" ").append(getLevel(level)).append(" "); - sb.append("[").append(Thread.currentThread().getName()).append("]").append(" "); - sb.append(getName()).append(" | "); - sb.append(format(message, args)); - - outprint.println(sb.toString()); - if (t != null) { - t.printStackTrace(System.err); - System.err.flush(); - } - } - -} From cc8b2b10218ae16b6d43464f8e125c446d004aba Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 13:28:46 +0800 Subject: [PATCH 176/545] modify add return param --- blade-kit/src/main/java/blade/kit/json/JSONObject.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/json/JSONObject.java b/blade-kit/src/main/java/blade/kit/json/JSONObject.java index 8f4e56d0e..63336859c 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONObject.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONObject.java @@ -39,12 +39,14 @@ public JSONObject(Map map) { super(map); } - public boolean put(String key, Object value){ - return this.put(key, value); + public JSONObject put(String key, Object value){ + this.put(key, value); + return this; } - public Object put(Object key, Object value){ - return this.put(key, value); + public JSONObject put(Object key, Object value){ + this.put(key, value); + return this; } public Object get(String key) throws JSONException { From 0b364fb8e039182e34f3eb4fc119dd9f70868b0a Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 13:34:42 +0800 Subject: [PATCH 177/545] update blade VERSION --- blade-core/src/main/java/com/blade/Blade.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 3bdef2c14..e56beef67 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -44,7 +44,7 @@ */ public class Blade { - public static final String VERSION = "1.4.0-alpha"; + public static final String VERSION = "1.4.0-beta"; private static final Blade ME = new Blade(); From 5c4584a713eabcce9d9a1bcb8e03d2703d22df19 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 16:46:12 +0800 Subject: [PATCH 178/545] update jetbrick version --- LAST_VERSION.md | 2 +- blade-core/pom.xml | 1 - blade-jetbrick/pom.xml | 12 +++++++----- pom.xml | 18 ++++++++++++++++-- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index e903c0412..e100bf2e3 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -49,7 +49,7 @@     com.bladejava     blade-jetbrick -    1.2.5 +    1.2.6 ``` diff --git a/blade-core/pom.xml b/blade-core/pom.xml index e2d914956..694e0bd6d 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -16,7 +16,6 @@ https://github.com/biezhi/blade/blade-core - 3.0.1 9.3.4.v20151007 diff --git a/blade-jetbrick/pom.xml b/blade-jetbrick/pom.xml index 13baa2111..3be6989fb 100644 --- a/blade-jetbrick/pom.xml +++ b/blade-jetbrick/pom.xml @@ -11,21 +11,23 @@ blade-jetbrick jar - 1.2.5 + 1.2.6 blade-jetbrick https://github.com/biezhi/blade/tree/master/blade-jetbrick - - javax.servlet - javax.servlet-api - com.bladejava blade-core ${blade.version} provided + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + com.github.subchen jetbrick-template diff --git a/pom.xml b/pom.xml index 4f0344558..67103f9f5 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ 1.6 UTF-8 4.11 + 3.0.1 1.4.0-beta @@ -29,7 +30,7 @@ blade-redis blade-startup - + @@ -40,7 +41,20 @@ - + + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + From 89ed7ac0f3214e7e35b58b6ff5524e735b5f0cb1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 16:48:08 +0800 Subject: [PATCH 179/545] update beetl version --- blade-beetl/pom.xml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/blade-beetl/pom.xml b/blade-beetl/pom.xml index ae9c521cd..1f0ac6c2a 100644 --- a/blade-beetl/pom.xml +++ b/blade-beetl/pom.xml @@ -16,14 +16,17 @@ https://github.com/biezhi/blade/tree/master/blade-beetl - - javax.servlet - javax.servlet-api - com.bladejava blade-core ${blade.version} + provided + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided org.beetl From 372f3e470ea384ec606dbc20bc4f2040cdb101dc Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Oct 2015 17:04:03 +0800 Subject: [PATCH 180/545] update velocity version --- blade-velocity/pom.xml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/blade-velocity/pom.xml b/blade-velocity/pom.xml index 7408e2d4d..734c28e10 100644 --- a/blade-velocity/pom.xml +++ b/blade-velocity/pom.xml @@ -16,14 +16,17 @@ https://github.com/biezhi/blade/tree/master/blade-velocity - - javax.servlet - javax.servlet-api - com.bladejava blade-core ${blade.version} + provided + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided org.apache.velocity From b6fa324b3f087a74d2e3858fcb3a3c3b141cb0e1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 22 Oct 2015 13:27:32 +0800 Subject: [PATCH 181/545] update readme --- README.md | 22 ++++++++++++---------- README_CN.md | 22 ++++++++++++---------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index bf562a472..ecd468f28 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,12 @@ [中文](https://github.com/biezhi/blade/blob/master/README_CN.md) ## What Is Blade? + `blade` is a lightweight MVC framework. It is based on the principles of simplicity and elegance. If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! ## Features + * [x] Lightweight. The code is simple and structure is clear * [x] Modular (you can choose which components to use) * [x] Support plug-in extension mechanism @@ -23,11 +25,12 @@ If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! ## Overview * Simplicity. The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. It is a goal of the project that users should be able to understand the whole framework in a single day. - * Elegance. `blade` Support the REST style routing interface, provide DSL grammar to write, no invasive interceptors. ## Getting started + To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) and then create a class with a main method like this: + ```java public class App extends Bootstrap { @@ -44,6 +47,7 @@ public class App extends Bootstrap { } } ``` + Run it and point your browser to http://localhost:9001. There you go, you've just created your first Blade app! OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: @@ -55,10 +59,10 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ## Plan - 1. Improve the document - 2. Add configurable log - 3. Complete the Java China BBS - 4. Maintain and optimize the code +1. Improve the document +2. Add the routing configuration way +3. To develop personalized social applications +4. Maintain and optimize the code ## Update @@ -70,8 +74,6 @@ Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LI ## Contact -Blog:[https://biezhi.me](https://biezhi.me) - -Mail: biezhi.me#gmail.com - -QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me#gmail.com +- QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) diff --git a/README_CN.md b/README_CN.md index aa037a363..18c0be38e 100644 --- a/README_CN.md +++ b/README_CN.md @@ -8,10 +8,12 @@ [English](https://github.com/biezhi/blade/blob/master/README.md) ## Blade是什么? + `blade` 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计。 如果你喜欢,欢迎 [Star and Fork](https://github.com/biezhi/blade), 谢谢! ## 特性 + * [x] 轻量级。代码简洁,结构清晰,更容易开发 * [x] 模块化(你可以选择使用哪些组件) * [x] 插件扩展机制 @@ -23,11 +25,12 @@ ## 概述 * 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 - * 优雅的:`blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 ## 快速入门 + 开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) ,然后创建一个类继承自 `Bootstrap` ,编写 `Main` 函数: + ```java public class App extends Bootstrap { @@ -44,6 +47,7 @@ public class App extends Bootstrap { } } ``` + 用浏览器打开 http://localhost:9001 这样就可以看到第一个Blade应用了! OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: @@ -55,10 +59,10 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ### 计划 - 1. 完善文档 - 2. 添加可配置日志 - 3. 完成java中国论坛 - 4. 维护和优化代码 +- 1. 完善文档 +- 2. 添加配置方式路由 +- 3. 开发个性化社交应用 +- 4. 维护和优化代码 ## 更新日志 @@ -70,8 +74,6 @@ Blade框架基于 [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.h ## 联系我 -Blog:[https://biezhi.me](https://biezhi.me) - -Mail: biezhi.me#gmail.com - -Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me#gmail.com +- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) From 9b4fe57a22660181575ca3fd87840053c7e441fd Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 22 Oct 2015 15:29:49 +0800 Subject: [PATCH 182/545] fix sql2o datasource is null --- .../java/blade/plugin/sql2o/Sql2oPlugin.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index 95c7a1979..24b49ff1e 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -104,18 +104,13 @@ public Sql2oPlugin openCache(){ } /** - * 设置数据库配置 - * - * @param url + * 数据库配置 * @param driver + * @param url * @param user * @param pass + * @return */ - public Sql2oPlugin config(String url, String user, String pass){ - - return config(null, url, user, pass); - } - public Sql2oPlugin config(String driver, String url, String user, String pass){ if(null == dbConfig){ dbConfig = new DBConfig(); @@ -137,9 +132,10 @@ public DBConfig dbConfig(){ @Override public void run() { - DataSourceManager.me().run(); - DataSource dataSource = DataSourceManager.me().getDataSource(); - if(null == dataSource){ + DataSourceManager dm = DataSourceManager.me(); + dm.run(); + DataSource dataSource = dm.getDataSource(); + if(null == dataSource && null == dm.getSql2o()){ LOGGER.error("blade sql2o config fail!"); } else { LOGGER.debug("blade sql2o config success!"); From 0a5154a5645e6aff6c7f08d47818fb592dc7bdec Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 22 Oct 2015 15:36:47 +0800 Subject: [PATCH 183/545] update blade-sql2o version --- LAST_VERSION.md | 2 +- blade-sql2o/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index e100bf2e3..dc6834eef 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -40,7 +40,7 @@     com.bladejava     blade-sql2o -    1.2.9-beta +    1.2.9 ``` diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index 823eaa6ef..c7773aaac 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -11,7 +11,7 @@ blade-sql2o jar - 1.2.9-beta + 1.2.9 blade-sql2o https://github.com/biezhi/blade/tree/master/blade-sql2o From acfd6b9a1f93aa7ae980f788f0c56af0a716352d Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 22 Oct 2015 16:14:59 +0800 Subject: [PATCH 184/545] fix sql2o depend error --- blade-sql2o/pom.xml | 2 +- .../src/main/java/blade/plugin/sql2o/Model.java | 10 +++++----- .../src/main/java/blade/plugin/sql2o/Sql2oPlugin.java | 7 +++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index c7773aaac..a4c77732e 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -26,7 +26,7 @@ com.bladejava blade-cache 1.2.3 - true + provided org.sql2o diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index f43f23ac6..45a590eaa 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -32,11 +32,6 @@ public class Model { private static final Logger LOGGER = Logger.getLogger(Model.class); - /** - * 缓存对象 - */ - public Sql2oCache sql2oCache = Sql2oCacheFactory.getSql2oCache(); - /** * sql2o对象,操作数据库 */ @@ -44,6 +39,11 @@ public class Model { private static final Sql2oPlugin SQL2O_PLUGIN = Blade.me().plugin(Sql2oPlugin.class); + /** + * 缓存对象 + */ + public Sql2oCache sql2oCache = SQL2O_PLUGIN.isOpenCache() ? Sql2oCacheFactory.getSql2oCache() : null; + /** * 当前class实例 */ diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java index 24b49ff1e..eba61b9ec 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java @@ -10,9 +10,9 @@ import com.blade.Blade; import com.blade.plugin.Plugin; -import blade.cache.CacheException; import blade.kit.PropertyKit; import blade.kit.StringKit; +import blade.kit.base.ThrowableKit; import blade.kit.log.Logger; import blade.plugin.sql2o.cache.Sql2oCache; import blade.plugin.sql2o.cache.Sql2oCacheFactory; @@ -137,6 +137,7 @@ public void run() { DataSource dataSource = dm.getDataSource(); if(null == dataSource && null == dm.getSql2o()){ LOGGER.error("blade sql2o config fail!"); + System.exit(0); } else { LOGGER.debug("blade sql2o config success!"); } @@ -158,10 +159,8 @@ public void destroy() { Sql2oCache sql2oCache = Sql2oCacheFactory.getSql2oCache(); sql2oCache.destroy(); } - } catch (CacheException e) { - e.printStackTrace(); } catch (Exception e) { - e.printStackTrace(); + LOGGER.error(ThrowableKit.getStackTraceAsString(e)); } } From c29a5e61bce0c18cd424b41ccb035c3a958847bf Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 23 Oct 2015 15:19:35 +0800 Subject: [PATCH 185/545] add csrf keep --- blade-core/src/main/java/com/blade/Blade.java | 2 +- .../main/java/com/blade/BladeWebContext.java | 4 +- .../src/main/java/com/blade/Config.java | 27 +- .../src/main/java/com/blade/Configurator.java | 8 + .../main/java/com/blade/FilterHandler.java | 11 +- .../src/main/java/com/blade/asset/Asset.java | 69 ---- .../java/com/blade/asset/AssetLoader.java | 19 - .../java/com/blade/asset/FileAssetLoader.java | 64 --- .../main/java/com/blade/servlet/Request.java | 9 + .../main/java/com/blade/servlet/Response.java | 2 +- .../wrapper/RequestResponseBuilder.java | 2 +- .../{ => servlet}/wrapper/RequestWrapper.java | 11 +- .../wrapper/ResponseWrapper.java | 2 +- .../{ => servlet}/wrapper/package-info.java | 2 +- .../java/com/blade/verify/CSRFConfig.java | 25 ++ .../com/blade/verify/CSRFTokenManager.java | 121 ++++++ .../src/main/java/blade/kit/HashidKit.java | 370 ++++++++++++++++++ 17 files changed, 581 insertions(+), 167 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/asset/Asset.java delete mode 100644 blade-core/src/main/java/com/blade/asset/AssetLoader.java delete mode 100644 blade-core/src/main/java/com/blade/asset/FileAssetLoader.java rename blade-core/src/main/java/com/blade/{ => servlet}/wrapper/RequestResponseBuilder.java (98%) rename blade-core/src/main/java/com/blade/{ => servlet}/wrapper/RequestWrapper.java (97%) rename blade-core/src/main/java/com/blade/{ => servlet}/wrapper/ResponseWrapper.java (99%) rename blade-core/src/main/java/com/blade/{ => servlet}/wrapper/package-info.java (65%) create mode 100644 blade-core/src/main/java/com/blade/verify/CSRFConfig.java create mode 100644 blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java create mode 100644 blade-kit/src/main/java/blade/kit/HashidKit.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index e56beef67..9c253c95d 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -619,7 +619,7 @@ public void start() throws Exception { } public Config config(){ - return config(); + return config; } /** diff --git a/blade-core/src/main/java/com/blade/BladeWebContext.java b/blade-core/src/main/java/com/blade/BladeWebContext.java index 2f8246480..e7317d287 100644 --- a/blade-core/src/main/java/com/blade/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/BladeWebContext.java @@ -22,8 +22,8 @@ import com.blade.servlet.Request; import com.blade.servlet.Response; import com.blade.servlet.Session; -import com.blade.wrapper.RequestWrapper; -import com.blade.wrapper.ResponseWrapper; +import com.blade.servlet.wrapper.RequestWrapper; +import com.blade.servlet.wrapper.ResponseWrapper; /** * 全局的WeContext diff --git a/blade-core/src/main/java/com/blade/Config.java b/blade-core/src/main/java/com/blade/Config.java index c07920907..03be192a4 100644 --- a/blade-core/src/main/java/com/blade/Config.java +++ b/blade-core/src/main/java/com/blade/Config.java @@ -33,31 +33,46 @@ public class Config { // 存放所有变量 private Map configMap = CollectionKit.newHashMap(); + // 存放所有路由的包 private List routePackages = CollectionKit.newArrayList(); + // 存放所有IOC的包 private List iocPackages = CollectionKit.newArrayList(); + // 存放所有过滤目录 private List staticFolders = CollectionKit.newArrayList(); + // 基础包 private String basePackage; + // 拦截器包 private String interceptorPackage; + // 编码 private String encoding = "utf-8"; + // 视图前缀 private String viewPrefix = "/WEB-INF/"; + // 视图后缀 private String viewSuffix = ".jsp"; + // webroot根目录,物理路径 private String webRoot; + // 404视图位置 private String view404; + // 500视图位置 private String view500; + // 是否是DEBUG模式 private boolean isDebug = true; - + + // 是否开启XSS防御 + private boolean enableXSS = false; + public Config() { } @@ -212,5 +227,13 @@ public String getEncoding() { public void setEncoding(String encoding) { this.encoding = encoding; } - + + public boolean isEnableXSS() { + return enableXSS; + } + + public void setEnableXSS(boolean enableXSS) { + this.enableXSS = enableXSS; + } + } diff --git a/blade-core/src/main/java/com/blade/Configurator.java b/blade-core/src/main/java/com/blade/Configurator.java index 2f5c42ec8..ff20d1331 100644 --- a/blade-core/src/main/java/com/blade/Configurator.java +++ b/blade-core/src/main/java/com/blade/Configurator.java @@ -49,8 +49,10 @@ public Configurator(Config bladeConfig, private static final String BLADE_VIEW_404 = "blade.view404"; private static final String BLADE_VIEW_500 = "blade.view500"; private static final String BLADE_DEBUG = "blade.debug"; + private static final String BLADE_ENABLEXSS = "blade.enableXSS"; public void run() { + if (null != configMap && configMap.size() > 0) { bladeConfig.setConfigMap(configMap); @@ -65,6 +67,7 @@ public void run() { String view404 = configMap.get(BLADE_VIEW_404); String view500 = configMap.get(BLADE_VIEW_500); String debug = configMap.get(BLADE_DEBUG); + String xss = configMap.get(BLADE_ENABLEXSS); if (StringKit.isNotBlank(route)) { String[] blade_routes = StringKit.split(route, ","); @@ -109,6 +112,11 @@ public void run() { Boolean debugBool = Boolean.valueOf(debug); bladeConfig.setDebug(debugBool); } + + if (StringKit.isNotBlank(xss)) { + Boolean enableXssBool = Boolean.valueOf(xss); + bladeConfig.setEnableXSS(enableXssBool); + } } } } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/FilterHandler.java b/blade-core/src/main/java/com/blade/FilterHandler.java index 04de05c7c..bef318a19 100644 --- a/blade-core/src/main/java/com/blade/FilterHandler.java +++ b/blade-core/src/main/java/com/blade/FilterHandler.java @@ -31,9 +31,9 @@ import com.blade.route.impl.DefaultRouteMatcher; import com.blade.servlet.Request; import com.blade.servlet.Response; -import com.blade.wrapper.RequestResponseBuilder; -import com.blade.wrapper.RequestWrapper; -import com.blade.wrapper.ResponseWrapper; +import com.blade.servlet.wrapper.RequestResponseBuilder; +import com.blade.servlet.wrapper.RequestWrapper; +import com.blade.servlet.wrapper.ResponseWrapper; import blade.exception.BladeException; import blade.kit.PathKit; @@ -110,7 +110,11 @@ boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse // 构建一个包装后的response Response response = RequestResponseBuilder.build(httpResponse); + // 初始化context + BladeWebContext.setContext(CoreFilter.servletContext, httpRequest, httpResponse, requestWrapper, responseWrapper); + HttpMethod httpMethod = HttpMethod.valueOf(method); + Object result = null; try { responseWrapper.setDelegate(response); @@ -325,4 +329,5 @@ private boolean filterStaticFolder(String uri){ } return true; } + } diff --git a/blade-core/src/main/java/com/blade/asset/Asset.java b/blade-core/src/main/java/com/blade/asset/Asset.java deleted file mode 100644 index a9c25fe8c..000000000 --- a/blade-core/src/main/java/com/blade/asset/Asset.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.blade.asset; - -import java.io.InputStream; - -/** - * Represents a static asset resource. - * - * @author German Escobar - */ -public class Asset { - - /** - * The input stream of the asset. - */ - private final InputStream inputStream; - - /** - * The name of the asset. - */ - private final String name; - - /** - * The content length of the asset. - */ - private final long length; - - /** - * The epoch timestamp when this asset was last modified - */ - private final long lastModified; - - /** - * The content type of the asset. - */ - private final String contentType; - - - public Asset(InputStream inputStream, String name, String contentType, long length) { - this(inputStream, name, contentType, length, 0); - } - - public Asset(InputStream inputStream, String name, String contentType, long length, long lastModified) { - this.inputStream = inputStream; - this.name = name; - this.contentType = contentType; - this.length = length; - this.lastModified = lastModified; - } - - public String getName() { - return name; - } - - public String getContentType() { - return contentType; - } - - public InputStream getInputStream() { - return inputStream; - } - - public long getLength() { - return length; - } - - public long getLastModified() { - return lastModified; - } -} diff --git a/blade-core/src/main/java/com/blade/asset/AssetLoader.java b/blade-core/src/main/java/com/blade/asset/AssetLoader.java deleted file mode 100644 index 3efa5626b..000000000 --- a/blade-core/src/main/java/com/blade/asset/AssetLoader.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.blade.asset; - -/** - * Implementations of this interface provide mechanisms to load assets. - * - * @author German Escobar - */ -public interface AssetLoader { - - /** - * Retrieves the asset identified with the uri. - * - * @param uri represents the location of the asset. - * - * @return an {@link Asset} object or null if not found. - */ - Asset load(String uri); - -} diff --git a/blade-core/src/main/java/com/blade/asset/FileAssetLoader.java b/blade-core/src/main/java/com/blade/asset/FileAssetLoader.java deleted file mode 100644 index 354586c0c..000000000 --- a/blade-core/src/main/java/com/blade/asset/FileAssetLoader.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.blade.asset; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; - -import org.eclipse.jetty.http.MimeTypes; - -/** - * An {@link AssetLoader} implementation that uses the file system to retrieve assets. - * - * @author German Escobar - */ -public class FileAssetLoader implements AssetLoader { - - private static final String DEFAULT_BASE_DIRECTORY = "assets"; - - private File parent; - - /** - * Constructor. Initializes the object with the default base directory. - */ - public FileAssetLoader() { - this(DEFAULT_BASE_DIRECTORY); - } - - /** - * Constructor. Initializes the object with the specified base directory. - * - * @param directory - */ - public FileAssetLoader(String directory) { - this.parent = new File(directory); - } - - public FileAssetLoader(File parent) { - this.parent = parent; - } - - @Override - public Asset load(String fileName) { - try { - File file = new File(parent, fileName); - - if (!file.exists() || !file.isFile()) { - return null; - } - - long lastModified = file.lastModified(); - MimeTypes mimeTypes = new MimeTypes(); - - String contentType = "text/plain"; - String buffer = mimeTypes.getMimeByExtension(file.getName()); - if (buffer != null) { - contentType = buffer.toString(); - } - - return new Asset(new FileInputStream(file), file.getName(), contentType, file.length(), lastModified); - } catch (FileNotFoundException e) { - return null; - } - } - -} diff --git a/blade-core/src/main/java/com/blade/servlet/Request.java b/blade-core/src/main/java/com/blade/servlet/Request.java index f86b0bfa8..9c859a4de 100644 --- a/blade-core/src/main/java/com/blade/servlet/Request.java +++ b/blade-core/src/main/java/com/blade/servlet/Request.java @@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import com.blade.route.HttpMethod; import com.blade.route.RouteMatcher; import blade.kit.CollectionKit; @@ -583,4 +584,12 @@ public Object invoke(){ public Object invoke(String locaiton) { return "redirect." + locaiton; } + + /** + * 获取http method + * @return + */ + public HttpMethod method() { + return HttpMethod.valueOf(servletRequest.getMethod()); + } } diff --git a/blade-core/src/main/java/com/blade/servlet/Response.java b/blade-core/src/main/java/com/blade/servlet/Response.java index c61976353..9db6bc5ed 100644 --- a/blade-core/src/main/java/com/blade/servlet/Response.java +++ b/blade-core/src/main/java/com/blade/servlet/Response.java @@ -210,7 +210,7 @@ public void cookie(String name, String value, int maxAge, boolean secured) { * 设置cookie * @param path cookie所在域 * @param name cookie name - * @param value cookie name + * @param value cookie 值 * @param maxAge cookie有效期 * @param secured 是否SSL */ diff --git a/blade-core/src/main/java/com/blade/wrapper/RequestResponseBuilder.java b/blade-core/src/main/java/com/blade/servlet/wrapper/RequestResponseBuilder.java similarity index 98% rename from blade-core/src/main/java/com/blade/wrapper/RequestResponseBuilder.java rename to blade-core/src/main/java/com/blade/servlet/wrapper/RequestResponseBuilder.java index 6f1632fcb..a02c39005 100644 --- a/blade-core/src/main/java/com/blade/wrapper/RequestResponseBuilder.java +++ b/blade-core/src/main/java/com/blade/servlet/wrapper/RequestResponseBuilder.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.wrapper; +package com.blade.servlet.wrapper; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/blade-core/src/main/java/com/blade/wrapper/RequestWrapper.java b/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java similarity index 97% rename from blade-core/src/main/java/com/blade/wrapper/RequestWrapper.java rename to blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java index 326d6fa26..a73791abb 100644 --- a/blade-core/src/main/java/com/blade/wrapper/RequestWrapper.java +++ b/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java @@ -13,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.wrapper; +package com.blade.servlet.wrapper; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; +import com.blade.route.HttpMethod; import com.blade.route.RouteMatcher; import com.blade.servlet.QueryParamsMap; import com.blade.servlet.Request; @@ -32,7 +33,7 @@ * @since 1.0 */ public final class RequestWrapper extends Request { - + private Request delegate; public RequestWrapper() { @@ -240,7 +241,11 @@ public Map cookies() { public String cookie(String name) { return delegate.cookie(name); } - + + public HttpMethod method() { + return delegate.method(); + } + public Object invoke(){ return delegate.invoke(); } diff --git a/blade-core/src/main/java/com/blade/wrapper/ResponseWrapper.java b/blade-core/src/main/java/com/blade/servlet/wrapper/ResponseWrapper.java similarity index 99% rename from blade-core/src/main/java/com/blade/wrapper/ResponseWrapper.java rename to blade-core/src/main/java/com/blade/servlet/wrapper/ResponseWrapper.java index 25af7a372..b01e288cd 100644 --- a/blade-core/src/main/java/com/blade/wrapper/ResponseWrapper.java +++ b/blade-core/src/main/java/com/blade/servlet/wrapper/ResponseWrapper.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.wrapper; +package com.blade.servlet.wrapper; import javax.servlet.http.HttpServletResponse; diff --git a/blade-core/src/main/java/com/blade/wrapper/package-info.java b/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java similarity index 65% rename from blade-core/src/main/java/com/blade/wrapper/package-info.java rename to blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java index 975baf60b..c530ba12f 100644 --- a/blade-core/src/main/java/com/blade/wrapper/package-info.java +++ b/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java @@ -1,4 +1,4 @@ /** * 对HttpServletRequest和HttpServletResponse的包装 */ -package com.blade.wrapper; \ No newline at end of file +package com.blade.servlet.wrapper; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/verify/CSRFConfig.java b/blade-core/src/main/java/com/blade/verify/CSRFConfig.java new file mode 100644 index 000000000..70050b1f3 --- /dev/null +++ b/blade-core/src/main/java/com/blade/verify/CSRFConfig.java @@ -0,0 +1,25 @@ +package com.blade.verify; + +/** + * CSRF配置 + * @author biezhi + * + */ +public class CSRFConfig { + + String salt = CSRFTokenManager.CSRF_PARAM_NAME; + + int length = 32; + + public CSRFConfig() { + } + + public void setSalt(String salt) { + this.salt = salt; + } + + public void setLength(int length) { + this.length = length; + } + +} diff --git a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java new file mode 100644 index 000000000..a398f2b9c --- /dev/null +++ b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java @@ -0,0 +1,121 @@ +package com.blade.verify; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import com.blade.servlet.Request; +import com.blade.servlet.Session; + +import blade.kit.HashidKit; +import blade.kit.StringKit; + +/** + * CSRF token管理器 + * @author biezhi + * + */ +public class CSRFTokenManager { + + public static final String CSRF_PARAM_NAME = "_CSRFToken"; + + private static CSRFConfig config = new CSRFConfig(); + + private static HashidKit HASHID = new HashidKit(CSRF_PARAM_NAME, config.length); + + private CSRFTokenManager() { + } + + /*public static void config(String salt, int length){ + CSRFTokenManager.length = length; + HASHID = new HashidKit(salt, length); + }*/ + + public static void config(CSRFConfig config){ + CSRFTokenManager.config = config; + HASHID = new HashidKit(config.salt, config.length); + } + + /** + * 创建一个token + * @param session + * @return + */ + public static String createToken(HttpSession session) { + String token = null; + synchronized (session) { + Object objToken = session.getAttribute(CSRF_PARAM_NAME); + if (null == objToken) { + token = HASHID.encode( System.currentTimeMillis() ); + session.setAttribute(CSRF_PARAM_NAME, token); + } else { + token = objToken.toString(); + } + } + return token; + } + + /** + * 创建一个token + * @param session + * @return + */ + public static String createToken(Session session) { + String token = null; + synchronized (session) { + Object objToken = session.attribute(CSRF_PARAM_NAME); + if (null == objToken) { + token = HASHID.encode( System.currentTimeMillis() ); + session.attribute(CSRF_PARAM_NAME, token); + } else { + token = objToken.toString(); + } + } + return token; + } + + /** + * csrf验证 + * @param request + * @return + */ + public static boolean verifyCsrfForm(HttpServletRequest request) { + // 从 session 中得到 csrftoken 属性 + HttpSession session = request.getSession(); + Object oToken = session.getAttribute(CSRFTokenManager.CSRF_PARAM_NAME); + String sToken = ( null != oToken ) ? oToken.toString() : null; + if (sToken == null) { + // 产生新的 token 放入 session 中 + sToken = CSRFTokenManager.createToken(session); + System.out.println("生成token:" + sToken); + return true; + } else { + String pToken = request.getParameter(CSRFTokenManager.CSRF_PARAM_NAME); + if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { + return true; + } + } + + return false; + } + + public static boolean verifyCsrfForm(Request request) { + // 从 session 中得到 csrftoken 属性 + Session session = request.session(); + Object oToken = session.attribute(CSRFTokenManager.CSRF_PARAM_NAME); + String sToken = ( null != oToken ) ? oToken.toString() : null; + if (sToken == null) { + // 产生新的 token 放入 session 中 + sToken = CSRFTokenManager.createToken(session); + System.out.println("生成token:" + sToken); + return true; + } else { + String pToken = request.query(CSRFTokenManager.CSRF_PARAM_NAME); + if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { + return true; + } + } + + return false; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/HashidKit.java b/blade-kit/src/main/java/blade/kit/HashidKit.java new file mode 100644 index 000000000..cd8c4f761 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/HashidKit.java @@ -0,0 +1,370 @@ +package blade.kit; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Hashids designed for Generating short hashes from numbers (like YouTube and + * Bitly), obfuscate database IDs, use them as forgotten password hashes, + * invitation codes, store shard numbers This is implementation of + * http://hashids.org v0.3.3 version. + * + * @author fanweixiao + * @since 0.3.3 + */ +public class HashidKit { + + private static final String DEFAULT_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + + private String salt = ""; + private String alphabet = ""; + private String seps = "cfhistuCFHISTU"; + private int minHashLength = 0; + private String guards; + + public HashidKit() { + this(""); + } + + public HashidKit(String salt) { + this(salt, 0); + } + + public HashidKit(String salt, int minHashLength) { + this(salt, minHashLength, DEFAULT_ALPHABET); + } + + public HashidKit(String salt, int minHashLength, String alphabet) { + this.salt = salt; + if (minHashLength < 0) + this.minHashLength = 0; + else + this.minHashLength = minHashLength; + this.alphabet = alphabet; + + String uniqueAlphabet = ""; + for (int i = 0; i < this.alphabet.length(); i++) { + if (!uniqueAlphabet.contains("" + this.alphabet.charAt(i))) { + uniqueAlphabet += "" + this.alphabet.charAt(i); + } + } + + this.alphabet = uniqueAlphabet; + + int minAlphabetLength = 16; + if (this.alphabet.length() < minAlphabetLength) { + throw new IllegalArgumentException( + "alphabet must contain at least " + minAlphabetLength + + " unique characters"); + } + + if (this.alphabet.contains(" ")) { + throw new IllegalArgumentException( + "alphabet cannot contains spaces"); + } + + // seps should contain only characters present in alphabet; + // alphabet should not contains seps + for (int i = 0; i < this.seps.length(); i++) { + int j = this.alphabet.indexOf(this.seps.charAt(i)); + if (j == -1) { + this.seps = this.seps.substring(0, i) + " " + + this.seps.substring(i + 1); + } else { + this.alphabet = this.alphabet.substring(0, j) + " " + + this.alphabet.substring(j + 1); + } + } + + this.alphabet = this.alphabet.replaceAll("\\s+", ""); + this.seps = this.seps.replaceAll("\\s+", ""); + this.seps = this.consistentShuffle(this.seps, this.salt); + + double sepDiv = 3.5; + if ((this.seps.equals("")) + || ((this.alphabet.length() / this.seps.length()) > sepDiv)) { + int seps_len = (int) Math.ceil(this.alphabet.length() / sepDiv); + + if (seps_len == 1) { + seps_len++; + } + + if (seps_len > this.seps.length()) { + int diff = seps_len - this.seps.length(); + this.seps += this.alphabet.substring(0, diff); + this.alphabet = this.alphabet.substring(diff); + } else { + this.seps = this.seps.substring(0, seps_len); + } + } + + this.alphabet = this.consistentShuffle(this.alphabet, this.salt); + // use double to round up + int guardDiv = 12; + int guardCount = (int) Math.ceil((double) this.alphabet.length() + / guardDiv); + + if (this.alphabet.length() < 3) { + this.guards = this.seps.substring(0, guardCount); + this.seps = this.seps.substring(guardCount); + } else { + this.guards = this.alphabet.substring(0, guardCount); + this.alphabet = this.alphabet.substring(guardCount); + } + } + + /** + * Encrypt numbers to string + * + * @param numbers + * the numbers to encrypt + * @return the encrypt string + */ + public String encode(long... numbers) { + for (long number : numbers) { + if (number > 9007199254740992L) { + throw new IllegalArgumentException( + "number can not be greater than 9007199254740992L"); + } + } + + String retval = ""; + if (numbers.length == 0) { + return retval; + } + + return this._encode(numbers); + } + + /** + * Decrypt string to numbers + * + * @param hash + * the encrypt string + * @return decryped numbers + */ + public long[] decode(String hash) { + long[] ret = {}; + + if (hash.equals("")) + return ret; + + return this._decode(hash, this.alphabet); + } + + /** + * Encrypt hexa to string + * + * @param hexa + * the hexa to encrypt + * @return the encrypt string + */ + public String encodeHex(String hexa) { + if (!hexa.matches("^[0-9a-fA-F]+$")) + return ""; + + List matched = new ArrayList(); + Matcher matcher = Pattern.compile("[\\w\\W]{1,12}").matcher(hexa); + + while (matcher.find()) + matched.add(Long.parseLong("1" + matcher.group(), 16)); + + // conversion + long[] result = new long[matched.size()]; + for (int i = 0; i < matched.size(); i++) + result[i] = matched.get(i); + + return this._encode(result); + } + + /** + * Decrypt string to numbers + * + * @param hash + * the encrypt string + * @return decryped numbers + */ + public String decodeHex(String hash) { + String result = ""; + long[] numbers = this.decode(hash); + + for (long number : numbers) { + result += Long.toHexString(number).substring(1); + } + + return result; + } + + private String _encode(long... numbers) { + int numberHashInt = 0; + for (int i = 0; i < numbers.length; i++) { + numberHashInt += (numbers[i] % (i + 100)); + } + String alphabet = this.alphabet; + char ret = alphabet.toCharArray()[numberHashInt % alphabet.length()]; + // char lottery = ret; + long num; + int sepsIndex, guardIndex; + String buffer, ret_str = ret + ""; + char guard; + + for (int i = 0; i < numbers.length; i++) { + num = numbers[i]; + buffer = ret + this.salt + alphabet; + + alphabet = this.consistentShuffle(alphabet, + buffer.substring(0, alphabet.length())); + String last = this.hash(num, alphabet); + + ret_str += last; + + if (i + 1 < numbers.length) { + num %= ((int) last.toCharArray()[0] + i); + sepsIndex = (int) (num % this.seps.length()); + ret_str += this.seps.toCharArray()[sepsIndex]; + } + } + + if (ret_str.length() < this.minHashLength) { + guardIndex = (numberHashInt + (int) (ret_str.toCharArray()[0])) + % this.guards.length(); + guard = this.guards.toCharArray()[guardIndex]; + + ret_str = guard + ret_str; + + if (ret_str.length() < this.minHashLength) { + guardIndex = (numberHashInt + (int) (ret_str.toCharArray()[2])) + % this.guards.length(); + guard = this.guards.toCharArray()[guardIndex]; + + ret_str += guard; + } + } + + int halfLen = alphabet.length() / 2; + while (ret_str.length() < this.minHashLength) { + alphabet = this.consistentShuffle(alphabet, alphabet); + ret_str = alphabet.substring(halfLen) + ret_str + + alphabet.substring(0, halfLen); + int excess = ret_str.length() - this.minHashLength; + if (excess > 0) { + int start_pos = excess / 2; + ret_str = ret_str.substring(start_pos, start_pos + + this.minHashLength); + } + } + + return ret_str; + } + + private long[] _decode(String hash, String alphabet) { + ArrayList ret = new ArrayList(); + + int i = 0; + String regexp = "[" + this.guards + "]"; + String hashBreakdown = hash.replaceAll(regexp, " "); + String[] hashArray = hashBreakdown.split(" "); + + if (hashArray.length == 3 || hashArray.length == 2) { + i = 1; + } + + hashBreakdown = hashArray[i]; + + char lottery = hashBreakdown.toCharArray()[0]; + + hashBreakdown = hashBreakdown.substring(1); + hashBreakdown = hashBreakdown.replaceAll("[" + this.seps + "]", " "); + hashArray = hashBreakdown.split(" "); + + String subHash, buffer; + for (String aHashArray : hashArray) { + subHash = aHashArray; + buffer = lottery + this.salt + alphabet; + alphabet = this.consistentShuffle(alphabet, + buffer.substring(0, alphabet.length())); + ret.add(this.unhash(subHash, alphabet)); + } + + // transform from List to long[] + long[] arr = new long[ret.size()]; + for (int k = 0; k < arr.length; k++) { + arr[k] = ret.get(k); + } + + if (!this._encode(arr).equals(hash)) { + arr = new long[0]; + } + + return arr; + } + + /* Private methods */ + private String consistentShuffle(String alphabet, String salt) { + if (salt.length() <= 0) + return alphabet; + + char[] arr = salt.toCharArray(); + int asc_val, j; + char tmp; + for (int i = alphabet.length() - 1, v = 0, p = 0; i > 0; i--, v++) { + v %= salt.length(); + asc_val = (int) arr[v]; + p += asc_val; + j = (asc_val + v + p) % i; + + tmp = alphabet.charAt(j); + alphabet = alphabet.substring(0, j) + alphabet.charAt(i) + + alphabet.substring(j + 1); + alphabet = alphabet.substring(0, i) + tmp + + alphabet.substring(i + 1); + } + + return alphabet; + } + + private String hash(long input, String alphabet) { + String hash = ""; + int alphabetLen = alphabet.length(); + char[] arr = alphabet.toCharArray(); + + do { + hash = arr[(int) (input % alphabetLen)] + hash; + input /= alphabetLen; + } while (input > 0); + + return hash; + } + + private Long unhash(String input, String alphabet) { + long number = 0, pos; + char[] input_arr = input.toCharArray(); + + for (int i = 0; i < input.length(); i++) { + pos = alphabet.indexOf(input_arr[i]); + number += pos * Math.pow(alphabet.length(), input.length() - i - 1); + } + + return number; + } + + public static int checkedCast(long value) { + int result = (int) value; + if (result != value) { + // don't use checkArgument here, to avoid boxing + throw new IllegalArgumentException("Out of range: " + value); + } + return result; + } + + /** + * Get version + * + * @return version + */ + public String getVersion() { + return "1.0.0"; + } + +} \ No newline at end of file From 42b47868bf2788523366e7b3593b1381de6e4cdc Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 23 Oct 2015 16:51:25 +0800 Subject: [PATCH 186/545] update csrf config --- blade-core/pom.xml | 2 +- .../java/com/blade/verify/CSRFConfig.java | 71 ++++++++++- .../com/blade/verify/CSRFTokenManager.java | 114 ++++++++++-------- blade-kit/pom.xml | 2 +- pom.xml | 2 +- 5 files changed, 132 insertions(+), 59 deletions(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 694e0bd6d..9fe6ce832 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -23,7 +23,7 @@ com.bladejava blade-kit - 1.2.7-beta + 1.2.7 diff --git a/blade-core/src/main/java/com/blade/verify/CSRFConfig.java b/blade-core/src/main/java/com/blade/verify/CSRFConfig.java index 70050b1f3..ea2953f14 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFConfig.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFConfig.java @@ -7,19 +7,84 @@ */ public class CSRFConfig { - String salt = CSRFTokenManager.CSRF_PARAM_NAME; + // 用于生成令牌的全局秘钥,默认为随机字符串 + String secret = "blade"; + + // 用于保存用户 ID 的 session 名称,默认为 "csrf_token" + String session = "csrf_token"; + // 用于传递令牌的 HTTP 请求头信息字段,默认为 "X-CSRFToken" + String header = "X-CSRFToken"; + + // 用于传递令牌的表单字段名,默认为 "_csrf" + String form = "_csrf"; + + // 用于传递令牌的 Cookie 名称,默认为 "_csrf" + String cookie = "_csrf"; + + // Cookie 设置路径,默认为 "/" + String cookiePath = "/"; + + // 生成token的长度,默认32位 int length = 32; + // cookie过期时长,默认60秒 + int expire = 3600; + + // 用于指定是否要求只有使用 HTTPS 时才设置 Cookie,默认为 false + boolean secured = false; + + // 用于指定是否将令牌设置到响应的头信息中,默认为 false + boolean setHeader = false; + + // 用于指定是否将令牌设置到响应的 Cookie 中,默认为 false + boolean setCookie = false; + public CSRFConfig() { } - public void setSalt(String salt) { - this.salt = salt; + public void setSecret(String secret) { + this.secret = secret; + } + + public void setSession(String session) { + this.session = session; + } + + public void setHeader(String header) { + this.header = header; + } + + public void setForm(String form) { + this.form = form; + } + + public void setCookie(String cookie) { + this.cookie = cookie; } public void setLength(int length) { this.length = length; } + + public void setExpire(int expire) { + this.expire = expire; + } + + public void setSetHeader(boolean setHeader) { + this.setHeader = setHeader; + } + + public void setSetCookie(boolean setCookie) { + this.setCookie = setCookie; + } + + public void setCookiePath(String cookiePath) { + this.cookiePath = cookiePath; + } + + public void setSecured(boolean secured) { + this.secured = secured; + } } diff --git a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java index a398f2b9c..9b95482a1 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java @@ -1,13 +1,12 @@ package com.blade.verify; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - import com.blade.servlet.Request; +import com.blade.servlet.Response; import com.blade.servlet.Session; import blade.kit.HashidKit; import blade.kit.StringKit; +import blade.kit.log.Logger; /** * CSRF token管理器 @@ -16,80 +15,86 @@ */ public class CSRFTokenManager { - public static final String CSRF_PARAM_NAME = "_CSRFToken"; - + private static Logger LOGGER = Logger.getLogger(CSRFTokenManager.class); + private static CSRFConfig config = new CSRFConfig(); - private static HashidKit HASHID = new HashidKit(CSRF_PARAM_NAME, config.length); + private static HashidKit HASHID = new HashidKit(config.secret, config.length); private CSRFTokenManager() { } - /*public static void config(String salt, int length){ - CSRFTokenManager.length = length; - HASHID = new HashidKit(salt, length); - }*/ - public static void config(CSRFConfig config){ CSRFTokenManager.config = config; - HASHID = new HashidKit(config.salt, config.length); + HASHID = new HashidKit(config.secret, config.length); } /** * 创建一个token - * @param session + * @param request + * @param response * @return */ - public static String createToken(HttpSession session) { + public static String createToken(Request request, Response response) { String token = null; - synchronized (session) { - Object objToken = session.getAttribute(CSRF_PARAM_NAME); + synchronized (request) { + Session session = request.session(); + String objToken = session.attribute(config.session); if (null == objToken) { token = HASHID.encode( System.currentTimeMillis() ); - session.setAttribute(CSRF_PARAM_NAME, token); } else { token = objToken.toString(); } + session.attribute(config.session, token); + if(config.setHeader){ + response.header(config.header, token); + } + if(config.setCookie){ + response.cookie(config.cookiePath, config.cookie, token, config.expire, config.secured); + } + LOGGER.info("create csrf_token:" + token); } return token; } /** - * 创建一个token - * @param session - * @return - */ - public static String createToken(Session session) { - String token = null; - synchronized (session) { - Object objToken = session.attribute(CSRF_PARAM_NAME); - if (null == objToken) { - token = HASHID.encode( System.currentTimeMillis() ); - session.attribute(CSRF_PARAM_NAME, token); - } else { - token = objToken.toString(); + * 根据表单参数验证 + * @param request + * @param response + * @return + */ + public static boolean verifyAsForm(Request request, Response response) { + // 从 session 中得到 csrftoken 属性 + String sToken = request.session().attribute(config.session); + if (sToken == null) { + // 产生新的 token 放入 session 中 + sToken = CSRFTokenManager.createToken(request, response); + return true; + } else { + String pToken = request.query(config.form); + if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { + return true; } - } - return token; - } + } + + return false; + } /** - * csrf验证 - * @param request - * @return - */ - public static boolean verifyCsrfForm(HttpServletRequest request) { + * 根据头信息验证 + * @param request + * @param response + * @return + */ + public static boolean verifyAsHeader(Request request, Response response) { // 从 session 中得到 csrftoken 属性 - HttpSession session = request.getSession(); - Object oToken = session.getAttribute(CSRFTokenManager.CSRF_PARAM_NAME); - String sToken = ( null != oToken ) ? oToken.toString() : null; + String sToken = request.session().attribute(config.session); if (sToken == null) { // 产生新的 token 放入 session 中 - sToken = CSRFTokenManager.createToken(session); - System.out.println("生成token:" + sToken); + sToken = CSRFTokenManager.createToken(request, response); return true; } else { - String pToken = request.getParameter(CSRFTokenManager.CSRF_PARAM_NAME); + String pToken = request.header(config.header); if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { return true; } @@ -97,19 +102,22 @@ public static boolean verifyCsrfForm(HttpServletRequest request) { return false; } - - public static boolean verifyCsrfForm(Request request) { + + /** + * 根据cookie验证 + * @param request + * @param response + * @return + */ + public static boolean verifyAsCookie(Request request, Response response) { // 从 session 中得到 csrftoken 属性 - Session session = request.session(); - Object oToken = session.attribute(CSRFTokenManager.CSRF_PARAM_NAME); - String sToken = ( null != oToken ) ? oToken.toString() : null; + String sToken = request.session().attribute(config.session); if (sToken == null) { // 产生新的 token 放入 session 中 - sToken = CSRFTokenManager.createToken(session); - System.out.println("生成token:" + sToken); + sToken = CSRFTokenManager.createToken(request, response); return true; } else { - String pToken = request.query(CSRFTokenManager.CSRF_PARAM_NAME); + String pToken = request.cookie(config.cookie); if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { return true; } @@ -117,5 +125,5 @@ public static boolean verifyCsrfForm(Request request) { return false; } - + } diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index 247e3647e..dbd1cfbf9 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - 1.2.7-beta + 1.2.7 blade-kit https://github.com/biezhi/blade/tree/master/blade-kit diff --git a/pom.xml b/pom.xml index 67103f9f5..e7fea3786 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ UTF-8 4.11 3.0.1 - 1.4.0-beta + 1.4.0 From 6097c2dd9903f395fa046b21c3f62b4cd8d90ff9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 23 Oct 2015 17:43:31 +0800 Subject: [PATCH 187/545] add xss defense --- blade-core/src/main/java/com/blade/Blade.java | 16 + .../blade/servlet/wrapper/RequestWrapper.java | 16 +- .../java/com/blade/verify/HTMLFilter.java | 537 ++++++++++++++++++ .../src/test/java/com/blade/XSSTest.java | 26 + 4 files changed, 593 insertions(+), 2 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/verify/HTMLFilter.java create mode 100644 blade-core/src/test/java/com/blade/XSSTest.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 9c253c95d..405fab354 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -544,6 +544,15 @@ public Blade staticFolder(final String ... folders) { return this; } + /** + * 设置是否启用XSS防御 + * @param enableXSS + * @return + */ + public Blade enableXSS(boolean enableXSS){ + config.setEnableXSS(enableXSS); + return this; + } /** * 动态设置全局初始化类 @@ -714,6 +723,13 @@ public Bootstrap bootstrap(){ return bootstrap; } + /** + * @return 返回是否启用XSS防御 + */ + public boolean enableXSS(){ + return config.isEnableXSS(); + } + /** * 返回插件对象 * @param pluginClazz 插件class diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java b/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java index a73791abb..aa68f8e0d 100644 --- a/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java +++ b/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java @@ -20,11 +20,13 @@ import javax.servlet.http.HttpServletRequest; +import com.blade.Blade; import com.blade.route.HttpMethod; import com.blade.route.RouteMatcher; import com.blade.servlet.QueryParamsMap; import com.blade.servlet.Request; import com.blade.servlet.Session; +import com.blade.verify.HTMLFilter; /** * Request增强 @@ -114,7 +116,12 @@ public Map params() { @Override public String param(String param) { - return delegate.param(param); + String val = delegate.param(param); + // 是否启用xss防范 + if(Blade.me().enableXSS()){ + return HTMLFilter.htmlSpecialChars(val); + } + return val; } @Override @@ -144,7 +151,12 @@ public String ip() { @Override public String query(String queryParam) { - return delegate.query(queryParam); + String val = delegate.query(queryParam); + // 是否启用xss防范 + if(Blade.me().enableXSS()){ + return HTMLFilter.htmlSpecialChars(val); + } + return val; } @Override diff --git a/blade-core/src/main/java/com/blade/verify/HTMLFilter.java b/blade-core/src/main/java/com/blade/verify/HTMLFilter.java new file mode 100644 index 000000000..292617655 --- /dev/null +++ b/blade-core/src/main/java/com/blade/verify/HTMLFilter.java @@ -0,0 +1,537 @@ +package com.blade.verify; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * HTML filtering utility for protecting against XSS (Cross Site Scripting). + * + * This code is licensed LGPLv3 + * + * This code is a Java port of the original work in PHP by Cal Hendersen. + * http://code.iamcal.com/php/lib_filter/ + * + * The trickiest part of the translation was handling the differences in regex handling + * between PHP and Java. These resources were helpful in the process: + * + * http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html + * http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php + * http://www.regular-expressions.info/modifiers.html + * + * A note on naming conventions: instance variables are prefixed with a "v"; global + * constants are in all caps. + * + * Sample use: + * String input = ... + * String clean = new HTMLFilter().filter( input ); + * + * The class is not thread safe. Create a new instance if in doubt. + * + * If you find bugs or have suggestions on improvement (especially regarding + * performance), please contact us. The latest version of this + * source, and our contact details, can be found at http://xss-html-filter.sf.net + * + * @author Joseph O'Connell + * @author Cal Hendersen + * @author Michael Semb Wever + */ +public final class HTMLFilter { + + /** regex flag union representing /si modifiers in php **/ + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; + private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); + private static final Pattern P_END_ARROW = Pattern.compile("^>"); + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_AMP = Pattern.compile("&"); + private static final Pattern P_QUOTE = Pattern.compile("\""); + private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); + + // @xxx could grow large... maybe use sesat's ReferenceMap + private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap(); + private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap(); + + /** set of allowed html elements, along with allowed attributes for each element **/ + private final Map> vAllowed; + /** counts of open tags for each (allowable) html element **/ + private final Map vTagCounts = new HashMap(); + + /** html elements which must always be self-closing (e.g. "") **/ + private final String[] vSelfClosingTags; + /** html elements which must always have separate opening and closing tags (e.g. "") **/ + private final String[] vNeedClosingTags; + /** set of disallowed html elements **/ + private final String[] vDisallowed; + /** attributes which should be checked for valid protocols **/ + private final String[] vProtocolAtts; + /** allowed protocols **/ + private final String[] vAllowedProtocols; + /** tags which should be removed if they contain no content (e.g. "" or "") **/ + private final String[] vRemoveBlanks; + /** entities allowed within html markup **/ + private final String[] vAllowedEntities; + /** flag determining whether comments are allowed in input String. */ + private final boolean stripComment; + private final boolean encodeQuotes; + private boolean vDebug = false; + /** + * flag determining whether to try to make tags when presented with "unbalanced" + * angle brackets (e.g. "" becomes " text "). If set to false, + * unbalanced angle brackets will be html escaped. + */ + private final boolean alwaysMakeTags; + + /** Default constructor. + * + */ + public HTMLFilter() { + vAllowed = new HashMap>(); + + final ArrayList a_atts = new ArrayList(); + a_atts.add("href"); + a_atts.add("target"); + vAllowed.put("a", a_atts); + + final ArrayList img_atts = new ArrayList(); + img_atts.add("src"); + img_atts.add("width"); + img_atts.add("height"); + img_atts.add("alt"); + vAllowed.put("img", img_atts); + + final ArrayList no_atts = new ArrayList(); + vAllowed.put("b", no_atts); + vAllowed.put("strong", no_atts); + vAllowed.put("i", no_atts); + vAllowed.put("em", no_atts); + + vSelfClosingTags = new String[]{"img"}; + vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"}; + vDisallowed = new String[]{}; + vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp. + vProtocolAtts = new String[]{"src", "href"}; + vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"}; + vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"}; + stripComment = true; + encodeQuotes = true; + alwaysMakeTags = true; + } + + /** Set debug flag to true. Otherwise use default settings. See the default constructor. + * + * @param debug turn debug on with a true argument + */ + public HTMLFilter(final boolean debug) { + this(); + vDebug = debug; + + } + + /** Map-parameter configurable constructor. + * + * @param conf map containing configuration. keys match field names. + */ + public HTMLFilter(final Map conf) { + + assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; + + vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); + vDisallowed = (String[]) conf.get("vDisallowed"); + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); + vProtocolAtts = (String[]) conf.get("vProtocolAtts"); + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); + vAllowedEntities = (String[]) conf.get("vAllowedEntities"); + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; + } + + private void reset() { + vTagCounts.clear(); + } + + private void debug(final String msg) { + if (vDebug) { + Logger.getAnonymousLogger().info(msg); + } + } + + //--------------------------------------------------------------- + // my versions of some PHP library functions + public static String chr(final int decimal) { + return String.valueOf((char) decimal); + } + + public static String htmlSpecialChars(final String s) { + if(null == s){ + return s; + } + String result = s; + result = regexReplace(P_AMP, "&", result); + result = regexReplace(P_QUOTE, """, result); + result = regexReplace(P_LEFT_ARROW, "<", result); + result = regexReplace(P_RIGHT_ARROW, ">", result); + return result; + } + + //--------------------------------------------------------------- + /** + * given a user submitted input String, filter out any invalid or restricted + * html. + * + * @param input text (i.e. submitted by a user) than may contain html + * @return "clean" version of input, with only valid, whitelisted html elements allowed + */ + public String filter(final String input) { + reset(); + String s = input; + + debug("************************************************"); + debug(" INPUT: " + input); + + s = escapeComments(s); + debug(" escapeComments: " + s); + + s = balanceHTML(s); + debug(" balanceHTML: " + s); + + s = checkTags(s); + debug(" checkTags: " + s); + + s = processRemoveBlanks(s); + debug("processRemoveBlanks: " + s); + + s = validateEntities(s); + debug(" validateEntites: " + s); + + debug("************************************************\n\n"); + return s; + } + + public boolean isAlwaysMakeTags(){ + return alwaysMakeTags; + } + + public boolean isStripComments(){ + return stripComment; + } + + private String escapeComments(final String s) { + final Matcher m = P_COMMENTS.matcher(s); + final StringBuffer buf = new StringBuffer(); + if (m.find()) { + final String match = m.group(1); //(.*?) + m.appendReplacement(buf, Matcher.quoteReplacement("")); + } + m.appendTail(buf); + + return buf.toString(); + } + + private String balanceHTML(String s) { + if (alwaysMakeTags) { + // + // try and form html + // + s = regexReplace(P_END_ARROW, "", s); + s = regexReplace(P_BODY_TO_END, "<$1>", s); + s = regexReplace(P_XML_CONTENT, "$1<$2", s); + + } else { + // + // escape stray brackets + // + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); + + // + // the last regexp causes '<>' entities to appear + // (we need to do a lookahead assertion so that the last bracket can + // be used in the next pass of the regexp) + // + s = regexReplace(P_BOTH_ARROWS, "", s); + } + + return s; + } + + private String checkTags(String s) { + Matcher m = P_TAGS.matcher(s); + + final StringBuffer buf = new StringBuffer(); + while (m.find()) { + String replaceStr = m.group(1); + replaceStr = processTag(replaceStr); + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); + } + m.appendTail(buf); + + s = buf.toString(); + + // these get tallied in processTag + // (remember to reset before subsequent calls to filter method) + for (String key : vTagCounts.keySet()) { + for (int ii = 0; ii < vTagCounts.get(key); ii++) { + s += ""; + } + } + + return s; + } + + private String processRemoveBlanks(final String s) { + String result = s; + for (String tag : vRemoveBlanks) { + if(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){ + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); + } + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); + if(!P_REMOVE_SELF_BLANKS.containsKey(tag)){ + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); + } + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); + } + + return result; + } + + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) { + Matcher m = regex_pattern.matcher(s); + return m.replaceAll(replacement); + } + + private String processTag(final String s) { + // ending tags + Matcher m = P_END_TAG.matcher(s); + if (m.find()) { + final String name = m.group(1).toLowerCase(); + if (allowed(name)) { + if (!inArray(name, vSelfClosingTags)) { + if (vTagCounts.containsKey(name)) { + vTagCounts.put(name, vTagCounts.get(name) - 1); + return ""; + } + } + } + } + + // starting tags + m = P_START_TAG.matcher(s); + if (m.find()) { + final String name = m.group(1).toLowerCase(); + final String body = m.group(2); + String ending = m.group(3); + + //debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); + if (allowed(name)) { + String params = ""; + + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); + final List paramNames = new ArrayList(); + final List paramValues = new ArrayList(); + while (m2.find()) { + paramNames.add(m2.group(1)); //([a-z0-9]+) + paramValues.add(m2.group(3)); //(.*?) + } + while (m3.find()) { + paramNames.add(m3.group(1)); //([a-z0-9]+) + paramValues.add(m3.group(3)); //([^\"\\s']+) + } + + String paramName, paramValue; + for (int ii = 0; ii < paramNames.size(); ii++) { + paramName = paramNames.get(ii).toLowerCase(); + paramValue = paramValues.get(ii); + +// debug( "paramName='" + paramName + "'" ); +// debug( "paramValue='" + paramValue + "'" ); +// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); + + if (allowedAttribute(name, paramName)) { + if (inArray(paramName, vProtocolAtts)) { + paramValue = processParamProtocol(paramValue); + } + params += " " + paramName + "=\"" + paramValue + "\""; + } + } + + if (inArray(name, vSelfClosingTags)) { + ending = " /"; + } + + if (inArray(name, vNeedClosingTags)) { + ending = ""; + } + + if (ending == null || ending.length() < 1) { + if (vTagCounts.containsKey(name)) { + vTagCounts.put(name, vTagCounts.get(name) + 1); + } else { + vTagCounts.put(name, 1); + } + } else { + ending = " /"; + } + return "<" + name + params + ending + ">"; + } else { + return ""; + } + } + + // comments + m = P_COMMENT.matcher(s); + if (!stripComment && m.find()) { + return "<" + m.group() + ">"; + } + + return ""; + } + + private String processParamProtocol(String s) { + s = decodeEntities(s); + final Matcher m = P_PROTOCOL.matcher(s); + if (m.find()) { + final String protocol = m.group(1); + if (!inArray(protocol, vAllowedProtocols)) { + // bad protocol, turn into local anchor link instead + s = "#" + s.substring(protocol.length() + 1, s.length()); + if (s.startsWith("#//")) { + s = "#" + s.substring(3, s.length()); + } + } + } + + return s; + } + + private String decodeEntities(String s) { + StringBuffer buf = new StringBuffer(); + + Matcher m = P_ENTITY.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.decode(match).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENTITY_UNICODE.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENCODE.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + s = validateEntities(s); + return s; + } + + private String validateEntities(final String s) { + StringBuffer buf = new StringBuffer(); + + // validate entities throughout the string + Matcher m = P_VALID_ENTITIES.matcher(s); + while (m.find()) { + final String one = m.group(1); //([^&;]*) + final String two = m.group(2); //(?=(;|&|$)) + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); + } + m.appendTail(buf); + + return encodeQuotes(buf.toString()); + } + + private String encodeQuotes(final String s){ + if(encodeQuotes){ + StringBuffer buf = new StringBuffer(); + Matcher m = P_VALID_QUOTES.matcher(s); + while (m.find()) { + final String one = m.group(1); //(>|^) + final String two = m.group(2); //([^<]+?) + final String three = m.group(3); //(<|$) + m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, """, two) + three)); + } + m.appendTail(buf); + return buf.toString(); + }else{ + return s; + } + } + + private String checkEntity(final String preamble, final String term) { + + return ";".equals(term) && isValidEntity(preamble) + ? '&' + preamble + : "&" + preamble; + } + + private boolean isValidEntity(final String entity) { + return inArray(entity, vAllowedEntities); + } + + private static boolean inArray(final String s, final String[] array) { + for (String item : array) { + if (item != null && item.equals(s)) { + return true; + } + } + return false; + } + + private boolean allowed(final String name) { + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); + } + + private boolean allowedAttribute(final String name, final String paramName) { + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); + } +} \ No newline at end of file diff --git a/blade-core/src/test/java/com/blade/XSSTest.java b/blade-core/src/test/java/com/blade/XSSTest.java new file mode 100644 index 000000000..b41a88e07 --- /dev/null +++ b/blade-core/src/test/java/com/blade/XSSTest.java @@ -0,0 +1,26 @@ +package com.blade; + +import com.blade.verify.HTMLFilter; + +public class XSSTest { + + public static void main(String[] args) { + + String string1 = ""; + String string2 = ""; + String string3 = "%0a%0a.jsp"; + String string4 = "%22%3cscript%3ealert(%22xss%22)%3c/script%3e"; + String string5 = "%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd"; + String string6 = "%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/windows/win.ini"; + String string7 = "%3c/a%3e%3cscript%3ealert(%22xss%22)%3c/script%3e"; + + System.out.println(HTMLFilter.htmlSpecialChars(string1)); + System.out.println(HTMLFilter.htmlSpecialChars(string2)); + System.out.println(HTMLFilter.htmlSpecialChars(string3)); + System.out.println(HTMLFilter.htmlSpecialChars(string4)); + System.out.println(HTMLFilter.htmlSpecialChars(string5)); + System.out.println(HTMLFilter.htmlSpecialChars(string6)); + System.out.println(HTMLFilter.htmlSpecialChars(string7)); + + } +} From 33da584f5e42122493883cf106c6321f435ce05a Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 23 Oct 2015 17:46:44 +0800 Subject: [PATCH 188/545] update log --- UPDATE_LOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 213d4cde0..6f5b0513b 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,5 +1,9 @@ #Blade 更新日志 +### v1.4.0 + 1. 添加CSRF防御 + 2. 添加XSS防御 + ### v1.2.9 1. 优化路由配置 2. 优化数据库缓存操作 From 0210ede943dc87b68d2296a6112e21eb3d23c0f5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 26 Oct 2015 09:57:20 +0800 Subject: [PATCH 189/545] fix json error --- blade-kit/src/main/java/blade/kit/json/JSONArray.java | 8 ++++---- blade-kit/src/main/java/blade/kit/json/JSONObject.java | 7 +++---- blade-kit/src/test/java/blade/test/JSONTest.java | 10 +++++++--- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/json/JSONArray.java b/blade-kit/src/main/java/blade/kit/json/JSONArray.java index 9d2f071e0..88715748e 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONArray.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONArray.java @@ -41,19 +41,19 @@ public JSONArray(Collection c){ } public boolean add(Object object){ - return this.add(object); + return super.add(object); } public void add(int index, Object object){ - this.add(index, object); + super.add(index, object); } public boolean addAll(Collection collection){ - return this.addAll(collection); + return super.addAll(collection); } public boolean addAll(int index, Collection collection){ - return this.addAll(index, collection); + return super.addAll(index, collection); } /** diff --git a/blade-kit/src/main/java/blade/kit/json/JSONObject.java b/blade-kit/src/main/java/blade/kit/json/JSONObject.java index 63336859c..554bcc277 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONObject.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONObject.java @@ -18,7 +18,7 @@ * * @author FangYidong */ -@SuppressWarnings("rawtypes") +@SuppressWarnings({"rawtypes","unchecked"}) public class JSONObject extends HashMap implements Map, JSONAware, JSONStreamAware{ private static final long serialVersionUID = -503443796854799292L; @@ -34,18 +34,17 @@ public JSONObject() { * * @param map */ - @SuppressWarnings("unchecked") public JSONObject(Map map) { super(map); } public JSONObject put(String key, Object value){ - this.put(key, value); + super.put(key, value); return this; } public JSONObject put(Object key, Object value){ - this.put(key, value); + super.put(key, value); return this; } diff --git a/blade-kit/src/test/java/blade/test/JSONTest.java b/blade-kit/src/test/java/blade/test/JSONTest.java index 56d8d8d42..356b150e3 100644 --- a/blade-kit/src/test/java/blade/test/JSONTest.java +++ b/blade-kit/src/test/java/blade/test/JSONTest.java @@ -27,7 +27,7 @@ public static void main(String[] args) { map.put("abc", "123456"); map.put("def", "hmm"); - list.add(map); + list.add(map); String string = JSONKit.toJSONString(list); System.out.println(string); @@ -36,10 +36,14 @@ public static void main(String[] args) { JSONObject obj1 = new JSONObject(); - obj1.put("", ""); + obj1.put("name", "jack"); + + System.out.println(obj1); JSONArray obj2 = new JSONArray(); - obj2.add(""); + obj2.add("123"); + + System.out.println(obj2); } } From 92f5961f5769d053e4ba025a0d5eb3a7625a2882 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 26 Oct 2015 10:45:17 +0800 Subject: [PATCH 190/545] fix json convert error --- .../src/main/java/blade/kit/BeanKit.java | 27 ++++++++++++++++++- .../main/java/blade/kit/json/JSONArray.java | 2 +- .../src/main/java/blade/kit/json/JSONKit.java | 4 ++- .../main/java/blade/kit/json/JSONObject.java | 2 +- .../src/test/java/blade/test/JSONTest.java | 5 ++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/BeanKit.java b/blade-kit/src/main/java/blade/kit/BeanKit.java index eaaf3b1d6..4b2733874 100644 --- a/blade-kit/src/main/java/blade/kit/BeanKit.java +++ b/blade-kit/src/main/java/blade/kit/BeanKit.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.Map; +import blade.kit.json.JSONObject; + /** * java对象和map转换 * @author:rex @@ -106,5 +108,28 @@ public static List> toListMap(List list) { return result; } - + public static T jsonToBean(JSONObject map, Class clazz){ + T object = null; + try { + object = clazz.newInstance(); + BeanInfo beanInfo = Introspector.getBeanInfo(clazz); + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + + for (PropertyDescriptor property : propertyDescriptors) { + String key = property.getName(); + + if (map.containsKey(key)) { + Object value = map.get(key); + + // 得到property对应的setter方法 + Method setter = property.getWriteMethod(); + setter.invoke(object, value); + } + } + } catch (Exception e) { + System.out.println("json covert to bean error:" + e); + } + return object; + + } } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/JSONArray.java b/blade-kit/src/main/java/blade/kit/json/JSONArray.java index 88715748e..17d2d97a8 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONArray.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONArray.java @@ -409,7 +409,7 @@ public String toString() { * If there is no value for the index. */ public Object get(int index) throws JSONException { - Object object = this.get(index); + Object object = super.get(index); if (object == null) { throw new JSONException("JSONArray[" + index + "] not found."); } diff --git a/blade-kit/src/main/java/blade/kit/json/JSONKit.java b/blade-kit/src/main/java/blade/kit/json/JSONKit.java index 3b771712e..0930c7a2e 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONKit.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONKit.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Map; +import blade.kit.BeanKit; import blade.kit.base.ThrowableKit; import blade.kit.json.parse.ParseException; import blade.kit.log.Logger; @@ -52,7 +53,8 @@ public static T parse(final String json) { public static T parse(final String json, Class type) { try { - return (T) JSONValue.parse(json); + JSONObject obj = (JSONObject) JSONValue.parse(json); + return (T) BeanKit.jsonToBean(obj, type); } catch (ParseException e) { String error = ThrowableKit.getStackTraceAsString(e); LOGGER.error(error); diff --git a/blade-kit/src/main/java/blade/kit/json/JSONObject.java b/blade-kit/src/main/java/blade/kit/json/JSONObject.java index 554bcc277..a2b53a1e3 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONObject.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONObject.java @@ -52,7 +52,7 @@ public Object get(String key) throws JSONException { if (key == null) { throw new JSONException("Null key."); } - Object object = this.get(key); + Object object = super.get(key); if (object == null) { throw new JSONException("JSONObject[" + quote(key) + "] not found."); } diff --git a/blade-kit/src/test/java/blade/test/JSONTest.java b/blade-kit/src/test/java/blade/test/JSONTest.java index 356b150e3..1eee781dd 100644 --- a/blade-kit/src/test/java/blade/test/JSONTest.java +++ b/blade-kit/src/test/java/blade/test/JSONTest.java @@ -12,6 +12,7 @@ public class JSONTest { + public static void main(String[] args) { //[{"text": "首页","href": "/"},{"text": "博客","href": "blog"},{"text": "关于","href": "about"},{"text": "联系","href": "contact"}] String json = "[{\"text\": \"博客\",\"href\": \"blog\"}]"; @@ -44,6 +45,10 @@ public static void main(String[] args) { obj2.add("123"); System.out.println(obj2); + + User u = JSONKit.parse("{\"name\":\"jack\",\"age\":20}", User.class); +// User u = BeanKit.mapToBean(user, User.class); + System.out.println(u); } } From e99b0ba7f0ae06d4dfb39f8b1cd1bd03777e459c Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 26 Oct 2015 14:04:19 +0800 Subject: [PATCH 191/545] fix json convert --- .../src/main/java/blade/kit/BeanKit.java | 26 - .../main/java/blade/kit/json/ItemList.java | 149 --- .../main/java/blade/kit/json/JSONArray.java | 595 ----------- .../main/java/blade/kit/json/JSONAware.java | 12 - .../java/blade/kit/json/JSONException.java | 42 - .../src/main/java/blade/kit/json/JSONKit.java | 67 +- .../main/java/blade/kit/json/JSONObject.java | 358 ------- .../java/blade/kit/json/JSONStreamAware.java | 15 - .../main/java/blade/kit/json/JSONValue.java | 262 ----- .../src/main/java/blade/kit/json/Json.java | 427 ++++++++ .../main/java/blade/kit/json/JsonArray.java | 457 +++++++++ .../main/java/blade/kit/json/JsonLiteral.java | 97 ++ .../main/java/blade/kit/json/JsonNumber.java | 94 ++ .../main/java/blade/kit/json/JsonObject.java | 966 ++++++++++++++++++ .../main/java/blade/kit/json/JsonParser.java | 400 ++++++++ .../main/java/blade/kit/json/JsonString.java | 74 ++ .../main/java/blade/kit/json/JsonValue.java | 500 +++++++++ .../main/java/blade/kit/json/JsonWriter.java | 145 +++ .../java/blade/kit/json/ParseException.java | 70 ++ .../main/java/blade/kit/json/PrettyPrint.java | 157 +++ .../java/blade/kit/json/WriterConfig.java | 50 + .../java/blade/kit/json/WritingBuffer.java | 99 ++ .../kit/json/parse/ContainerFactory.java | 24 - .../blade/kit/json/parse/ContentHandler.java | 110 -- .../java/blade/kit/json/parse/JSONParser.java | 534 ---------- .../blade/kit/json/parse/ParseException.java | 90 -- .../main/java/blade/kit/json/parse/Yylex.java | 689 ------------- .../java/blade/kit/json/parse/Yytoken.java | 58 -- .../src/test/java/blade/test/JSONTest.java | 29 +- blade-kit/src/test/java/blade/test/User.java | 32 + 30 files changed, 3601 insertions(+), 3027 deletions(-) delete mode 100644 blade-kit/src/main/java/blade/kit/json/ItemList.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONArray.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONAware.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONException.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONObject.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONStreamAware.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JSONValue.java create mode 100644 blade-kit/src/main/java/blade/kit/json/Json.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JsonArray.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JsonLiteral.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JsonNumber.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JsonObject.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JsonParser.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JsonString.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JsonValue.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JsonWriter.java create mode 100644 blade-kit/src/main/java/blade/kit/json/ParseException.java create mode 100644 blade-kit/src/main/java/blade/kit/json/PrettyPrint.java create mode 100644 blade-kit/src/main/java/blade/kit/json/WriterConfig.java create mode 100644 blade-kit/src/main/java/blade/kit/json/WritingBuffer.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/parse/ContainerFactory.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/parse/ContentHandler.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/parse/JSONParser.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/parse/ParseException.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/parse/Yylex.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/parse/Yytoken.java create mode 100644 blade-kit/src/test/java/blade/test/User.java diff --git a/blade-kit/src/main/java/blade/kit/BeanKit.java b/blade-kit/src/main/java/blade/kit/BeanKit.java index 4b2733874..40a57ea8c 100644 --- a/blade-kit/src/main/java/blade/kit/BeanKit.java +++ b/blade-kit/src/main/java/blade/kit/BeanKit.java @@ -23,8 +23,6 @@ import java.util.List; import java.util.Map; -import blade.kit.json.JSONObject; - /** * java对象和map转换 * @author:rex @@ -108,28 +106,4 @@ public static List> toListMap(List list) { return result; } - public static T jsonToBean(JSONObject map, Class clazz){ - T object = null; - try { - object = clazz.newInstance(); - BeanInfo beanInfo = Introspector.getBeanInfo(clazz); - PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); - - for (PropertyDescriptor property : propertyDescriptors) { - String key = property.getName(); - - if (map.containsKey(key)) { - Object value = map.get(key); - - // 得到property对应的setter方法 - Method setter = property.getWriteMethod(); - setter.invoke(object, value); - } - } - } catch (Exception e) { - System.out.println("json covert to bean error:" + e); - } - return object; - - } } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/ItemList.java b/blade-kit/src/main/java/blade/kit/json/ItemList.java deleted file mode 100644 index 2dc7e7374..000000000 --- a/blade-kit/src/main/java/blade/kit/json/ItemList.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * $Id: ItemList.java,v 1.1 2006/04/15 14:10:48 platform Exp $ - * Created on 2006-3-24 - */ -package blade.kit.json; - -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -/** - * |a:b:c| => |a|,|b|,|c| - * |:| => ||,|| - * |a:| => |a|,|| - * @author FangYidong - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class ItemList { - private String sp=","; - - List items = new ArrayList(); - - - public ItemList(){} - - - public ItemList(String s){ - this.split(s,sp,items); - } - - public ItemList(String s,String sp){ - this.sp=s; - this.split(s,sp,items); - } - - public ItemList(String s,String sp,boolean isMultiToken){ - split(s,sp,items,isMultiToken); - } - - public List getItems(){ - return this.items; - } - - public String[] getArray(){ - return (String[])this.items.toArray(); - } - - public void split(String s,String sp,List append,boolean isMultiToken){ - if(s==null || sp==null) - return; - if(isMultiToken){ - StringTokenizer tokens=new StringTokenizer(s,sp); - while(tokens.hasMoreTokens()){ - append.add(tokens.nextToken().trim()); - } - } - else{ - this.split(s,sp,append); - } - } - - public void split(String s,String sp, List append){ - if(s==null || sp==null) - return; - int pos=0; - int prevPos=0; - do{ - prevPos=pos; - pos=s.indexOf(sp,pos); - if(pos==-1) - break; - append.add(s.substring(prevPos,pos).trim()); - pos+=sp.length(); - }while(pos!=-1); - append.add(s.substring(prevPos).trim()); - } - - public void setSP(String sp){ - this.sp=sp; - } - - public void add(int i,String item){ - if(item==null) - return; - items.add(i,item.trim()); - } - - public void add(String item){ - if(item==null) - return; - items.add(item.trim()); - } - - public void addAll(ItemList list){ - items.addAll(list.items); - } - - public void addAll(String s){ - this.split(s,sp,items); - } - - public void addAll(String s,String sp){ - this.split(s,sp,items); - } - - public void addAll(String s,String sp,boolean isMultiToken){ - this.split(s,sp,items,isMultiToken); - } - - /** - * @param i 0-based - * @return - */ - public String get(int i){ - return (String)items.get(i); - } - - public int size(){ - return items.size(); - } - - public String toString(){ - return toString(sp); - } - - public String toString(String sp){ - StringBuffer sb=new StringBuffer(); - - for(int i=0;i - */ -@SuppressWarnings({"rawtypes","unchecked"}) -public class JSONArray extends ArrayList implements JSONAware, JSONStreamAware { - - private static final long serialVersionUID = 3957988303675231981L; - - /** - * Constructs an empty JSONArray. - */ - public JSONArray(){ - super(); - } - - /** - * Constructs a JSONArray containing the elements of the specified - * collection, in the order they are returned by the collection's iterator. - * - * @param c the collection whose elements are to be placed into this JSONArray - */ - public JSONArray(Collection c){ - super(c); - } - - public boolean add(Object object){ - return super.add(object); - } - - public void add(int index, Object object){ - super.add(index, object); - } - - public boolean addAll(Collection collection){ - return super.addAll(collection); - } - - public boolean addAll(int index, Collection collection){ - return super.addAll(index, collection); - } - - /** - * Encode a list into JSON text and write it to out. - * If this list is also a JSONStreamAware or a JSONAware, JSONStreamAware and JSONAware specific behaviours will be ignored at this top level. - * - * @see blade.kit.json2.JSONValue#writeJSONString(Object, Writer) - * - * @param collection - * @param out - */ - public static void writeJSONString(Collection collection, Writer out) throws IOException{ - if(collection == null){ - out.write("null"); - return; - } - - boolean first = true; - Iterator iter=collection.iterator(); - - out.write('['); - while(iter.hasNext()){ - if(first) - first = false; - else - out.write(','); - - Object value=iter.next(); - if(value == null){ - out.write("null"); - continue; - } - - JSONValue.writeJSONString(value, out); - } - out.write(']'); - } - - public void writeJSONString(Writer out) throws IOException{ - writeJSONString(this, out); - } - - /** - * Convert a list to JSON text. The result is a JSON array. - * If this list is also a JSONAware, JSONAware specific behaviours will be omitted at this top level. - * - * @see blade.kit.json2.JSONValue#toJSONString(Object) - * - * @param collection - * @return JSON text, or "null" if list is null. - */ - public static String toJSONString(Collection collection){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(collection, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - public static void writeJSONString(byte[] array, Writer out) throws IOException{ - if(array == null){ - out.write("null"); - } else if(array.length == 0) { - out.write("[]"); - } else { - out.write("["); - out.write(String.valueOf(array[0])); - - for(int i = 1; i < array.length; i++){ - out.write(","); - out.write(String.valueOf(array[i])); - } - - out.write("]"); - } - } - - public static String toJSONString(byte[] array){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(array, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - public static void writeJSONString(short[] array, Writer out) throws IOException{ - if(array == null){ - out.write("null"); - } else if(array.length == 0) { - out.write("[]"); - } else { - out.write("["); - out.write(String.valueOf(array[0])); - - for(int i = 1; i < array.length; i++){ - out.write(","); - out.write(String.valueOf(array[i])); - } - - out.write("]"); - } - } - - public static String toJSONString(short[] array){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(array, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - public static void writeJSONString(int[] array, Writer out) throws IOException{ - if(array == null){ - out.write("null"); - } else if(array.length == 0) { - out.write("[]"); - } else { - out.write("["); - out.write(String.valueOf(array[0])); - - for(int i = 1; i < array.length; i++){ - out.write(","); - out.write(String.valueOf(array[i])); - } - - out.write("]"); - } - } - - public static String toJSONString(int[] array){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(array, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - public static void writeJSONString(long[] array, Writer out) throws IOException{ - if(array == null){ - out.write("null"); - } else if(array.length == 0) { - out.write("[]"); - } else { - out.write("["); - out.write(String.valueOf(array[0])); - - for(int i = 1; i < array.length; i++){ - out.write(","); - out.write(String.valueOf(array[i])); - } - - out.write("]"); - } - } - - public static String toJSONString(long[] array){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(array, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - public static void writeJSONString(float[] array, Writer out) throws IOException{ - if(array == null){ - out.write("null"); - } else if(array.length == 0) { - out.write("[]"); - } else { - out.write("["); - out.write(String.valueOf(array[0])); - - for(int i = 1; i < array.length; i++){ - out.write(","); - out.write(String.valueOf(array[i])); - } - - out.write("]"); - } - } - - public static String toJSONString(float[] array){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(array, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - public static void writeJSONString(double[] array, Writer out) throws IOException{ - if(array == null){ - out.write("null"); - } else if(array.length == 0) { - out.write("[]"); - } else { - out.write("["); - out.write(String.valueOf(array[0])); - - for(int i = 1; i < array.length; i++){ - out.write(","); - out.write(String.valueOf(array[i])); - } - - out.write("]"); - } - } - - public static String toJSONString(double[] array){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(array, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - public static void writeJSONString(boolean[] array, Writer out) throws IOException{ - if(array == null){ - out.write("null"); - } else if(array.length == 0) { - out.write("[]"); - } else { - out.write("["); - out.write(String.valueOf(array[0])); - - for(int i = 1; i < array.length; i++){ - out.write(","); - out.write(String.valueOf(array[i])); - } - - out.write("]"); - } - } - - public static String toJSONString(boolean[] array){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(array, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - public static void writeJSONString(char[] array, Writer out) throws IOException{ - if(array == null){ - out.write("null"); - } else if(array.length == 0) { - out.write("[]"); - } else { - out.write("[\""); - out.write(String.valueOf(array[0])); - - for(int i = 1; i < array.length; i++){ - out.write("\",\""); - out.write(String.valueOf(array[i])); - } - - out.write("\"]"); - } - } - - public static String toJSONString(char[] array){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(array, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - public static void writeJSONString(Object[] array, Writer out) throws IOException{ - if(array == null){ - out.write("null"); - } else if(array.length == 0) { - out.write("[]"); - } else { - out.write("["); - JSONValue.writeJSONString(array[0], out); - - for(int i = 1; i < array.length; i++){ - out.write(","); - JSONValue.writeJSONString(array[i], out); - } - - out.write("]"); - } - } - - public static String toJSONString(Object[] array){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(array, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - public String toJSONString(){ - return toJSONString(this); - } - - /** - * Returns a string representation of this array. This is equivalent to - * calling {@link JSONArray#toJSONString()}. - */ - public String toString() { - return toJSONString(); - } - - /** - * Get the object value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return An object value. - * @throws JSONException - * If there is no value for the index. - */ - public Object get(int index) throws JSONException { - Object object = super.get(index); - if (object == null) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - return object; - } - - /** - * Get the boolean value associated with an index. The string values "true" - * and "false" are converted to boolean. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The truth. - * @throws JSONException - * If there is no value for the index or if the value is not - * convertible to boolean. - */ - public boolean getBoolean(int index) throws JSONException { - Object object = this.get(index); - if (object.equals(Boolean.FALSE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONArray[" + index + "] is not a boolean."); - } - - /** - * Get the double value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a number. - */ - public double getDouble(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).doubleValue() - : Double.parseDouble((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); - } - } - - /** - * Get the BigDecimal value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a BigDecimal. - */ - public BigDecimal getBigDecimal (int index) throws JSONException { - Object object = this.get(index); - try { - return new BigDecimal(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] could not convert to BigDecimal."); - } - } - - /** - * Get the BigInteger value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a BigInteger. - */ - public BigInteger getBigInteger (int index) throws JSONException { - Object object = this.get(index); - try { - return new BigInteger(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] could not convert to BigInteger."); - } - } - - /** - * Get the int value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value is not a number. - */ - public int getInt(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).intValue() - : Integer.parseInt((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); - } - } - - /** - * Get the JSONArray associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return A JSONArray value. - * @throws JSONException - * If there is no value for the index. or if the value is not a - * JSONArray - */ - public JSONArray getJSONArray(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONArray) { - return (JSONArray) object; - } - throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); - } - - /** - * Get the JSONObject associated with an index. - * - * @param index - * subscript - * @return A JSONObject value. - * @throws JSONException - * If there is no value for the index or if the value is not a - * JSONObject - */ - public JSONObject getJSONObject(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONObject) { - return (JSONObject) object; - } - throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); - } - - /** - * Get the long value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a number. - */ - public long getLong(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).longValue() - : Long.parseLong((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); - } - } - - /** - * Get the string associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return A string value. - * @throws JSONException - * If there is no string value for the index. - */ - public String getString(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof String) { - return (String) object; - } - throw new JSONException("JSONArray[" + index + "] not a string."); - } -} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONAware.java b/blade-kit/src/main/java/blade/kit/json/JSONAware.java deleted file mode 100644 index 0c1dbafaa..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JSONAware.java +++ /dev/null @@ -1,12 +0,0 @@ -package blade.kit.json; - -/** - * Beans that support customized output of JSON text shall implement this interface. - * @author FangYidong - */ -public interface JSONAware { - /** - * @return JSON text - */ - String toJSONString(); -} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONException.java b/blade-kit/src/main/java/blade/kit/json/JSONException.java deleted file mode 100644 index e0dac7222..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JSONException.java +++ /dev/null @@ -1,42 +0,0 @@ -package blade.kit.json; -/** - * The JSONException is thrown by the JSON.org classes when things are amiss. - * - * @author JSON.org - * @version 2014-05-03 - */ -public class JSONException extends RuntimeException { - private static final long serialVersionUID = 0; - private Throwable cause; - - /** - * Constructs a JSONException with an explanatory message. - * - * @param message - * Detail about the reason for the exception. - */ - public JSONException(String message) { - super(message); - } - - /** - * Constructs a new JSONException with the specified cause. - * @param cause The cause. - */ - public JSONException(Throwable cause) { - super(cause.getMessage()); - this.cause = cause; - } - - /** - * Returns the cause of this exception or null if the cause is nonexistent - * or unknown. - * - * @return the cause of this exception or null if the cause is nonexistent - * or unknown. - */ - @Override - public Throwable getCause() { - return this.cause; - } -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/JSONKit.java b/blade-kit/src/main/java/blade/kit/json/JSONKit.java index 0930c7a2e..41d2a4f4b 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONKit.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONKit.java @@ -3,68 +3,33 @@ import java.util.List; import java.util.Map; -import blade.kit.BeanKit; -import blade.kit.base.ThrowableKit; -import blade.kit.json.parse.ParseException; -import blade.kit.log.Logger; - -/** - * JSON工具类 - * @author biezhi - * - */ -@SuppressWarnings("unchecked") public class JSONKit { - private static final Logger LOGGER = Logger.getLogger(JSONKit.class); + public static Map toMap(String json){ + return Json.parseToMap(json); + } - public static Map toMap(String json){ - try { - return (Map) JSONValue.parse(json); - } catch (ParseException e) { - String error = ThrowableKit.getStackTraceAsString(e); - LOGGER.error(error); - ThrowableKit.propagate(e); - } - return null; + public static Map toMap(JsonObject jsonObject){ + return Json.parseToMap(jsonObject); } - public static List toList(String json){ - try { - return (List) JSONValue.parse(json); - } catch (ParseException e) { - String error = ThrowableKit.getStackTraceAsString(e); - LOGGER.error(error); - ThrowableKit.propagate(e); - } - return null; + public static String toJSONString(Object bean){ + return Json.parse(bean).toString(); } - public static T parse(final String json) { - try { - return (T) JSONValue.parse(json); - } catch (ParseException e) { - String error = ThrowableKit.getStackTraceAsString(e); - LOGGER.error(error); - ThrowableKit.propagate(e); - } - return null; + public static String toJSONString(Map map){ + return Json.parse(map).toString(); } - public static T parse(final String json, Class type) { - try { - JSONObject obj = (JSONObject) JSONValue.parse(json); - return (T) BeanKit.jsonToBean(obj, type); - } catch (ParseException e) { - String error = ThrowableKit.getStackTraceAsString(e); - LOGGER.error(error); - ThrowableKit.propagate(e); + public static String toJSONString(List list){ + if(null != list && list.size() > 0){ + JsonArray jsonArray = new JsonArray(); + for(T oT : list){ + jsonArray.add(Json.parse(oT)); + } + return jsonArray.toString(); } return null; } - public static String toJSONString(Object object){ - return JSONValue.toJSONString(object); - } - } diff --git a/blade-kit/src/main/java/blade/kit/json/JSONObject.java b/blade-kit/src/main/java/blade/kit/json/JSONObject.java deleted file mode 100644 index a2b53a1e3..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JSONObject.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * $Id: JSONObject.java,v 1.1 2006/04/15 14:10:48 platform Exp $ - * Created on 2006-4-10 - */ -package blade.kit.json; - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -/** - * A JSON object. Key value pairs are unordered. JSONObject supports java.util.Map interface. - * - * @author FangYidong - */ -@SuppressWarnings({"rawtypes","unchecked"}) -public class JSONObject extends HashMap implements Map, JSONAware, JSONStreamAware{ - - private static final long serialVersionUID = -503443796854799292L; - - - public JSONObject() { - super(); - } - - /** - * Allows creation of a JSONObject from a Map. After that, both the - * generated JSONObject and the Map can be modified independently. - * - * @param map - */ - public JSONObject(Map map) { - super(map); - } - - public JSONObject put(String key, Object value){ - super.put(key, value); - return this; - } - - public JSONObject put(Object key, Object value){ - super.put(key, value); - return this; - } - - public Object get(String key) throws JSONException { - if (key == null) { - throw new JSONException("Null key."); - } - Object object = super.get(key); - if (object == null) { - throw new JSONException("JSONObject[" + quote(key) + "] not found."); - } - return object; - } - - public String getString(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof String) { - return (String) object; - } - throw new JSONException("JSONObject[" + quote(key) + "] not a string."); - } - - public int getInt(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number ? ((Number) object).intValue() : Integer.parseInt((String) object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) + "] is not an int."); - } - } - - /** - * Get the boolean value associated with a key. - * - * @param key - * A key string. - * @return The truth. - * @throws JSONException - * if the value is not a Boolean or the String "true" or - * "false". - */ - public boolean getBoolean(String key) throws JSONException { - Object object = this.get(key); - if (object.equals(Boolean.FALSE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a Boolean."); - } - - /** - * Get the BigInteger value associated with a key. - * - * @param key - * A key string. - * @return The numeric value. - * @throws JSONException - * if the key is not found or if the value cannot - * be converted to BigInteger. - */ - public BigInteger getBigInteger(String key) throws JSONException { - Object object = this.get(key); - try { - return new BigInteger(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] could not be converted to BigInteger."); - } - } - - /** - * Get the BigDecimal value associated with a key. - * - * @param key - * A key string. - * @return The numeric value. - * @throws JSONException - * if the key is not found or if the value - * cannot be converted to BigDecimal. - */ - public BigDecimal getBigDecimal(String key) throws JSONException { - Object object = this.get(key); - try { - return new BigDecimal(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] could not be converted to BigDecimal."); - } - } - - /** - * Get the double value associated with a key. - * - * @param key - * A key string. - * @return The numeric value. - * @throws JSONException - * if the key is not found or if the value is not a Number - * object and cannot be converted to a number. - */ - public double getDouble(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number ? ((Number) object).doubleValue() - : Double.parseDouble((String) object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] is not a number."); - } - } - - public JSONArray getJSONArray(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONArray) { - return (JSONArray) object; - } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a JSONArray."); - } - - public JSONObject getJSONObject(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONObject) { - return (JSONObject) object; - } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a JSONObject."); - } - - public long getLong(String key) throws JSONException { - Object object = this.get(key); - try { - return object instanceof Number ? ((Number) object).longValue() - : Long.parseLong((String) object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] is not a long."); - } - } - - public static String quote(String string) { - StringWriter sw = new StringWriter(); - synchronized (sw.getBuffer()) { - try { - return quote(string, sw).toString(); - } catch (IOException ignored) { - // will never happen - we are writing to a string writer - return ""; - } - } - } - - public static Writer quote(String string, Writer w) throws IOException { - if (string == null || string.length() == 0) { - w.write("\"\""); - return w; - } - - char b; - char c = 0; - String hhhh; - int i; - int len = string.length(); - - w.write('"'); - for (i = 0; i < len; i += 1) { - b = c; - c = string.charAt(i); - switch (c) { - case '\\': - case '"': - w.write('\\'); - w.write(c); - break; - case '/': - if (b == '<') { - w.write('\\'); - } - w.write(c); - break; - case '\b': - w.write("\\b"); - break; - case '\t': - w.write("\\t"); - break; - case '\n': - w.write("\\n"); - break; - case '\f': - w.write("\\f"); - break; - case '\r': - w.write("\\r"); - break; - default: - if (c < ' ' || (c >= '\u0080' && c < '\u00a0') - || (c >= '\u2000' && c < '\u2100')) { - w.write("\\u"); - hhhh = Integer.toHexString(c); - w.write("0000", 0, 4 - hhhh.length()); - w.write(hhhh); - } else { - w.write(c); - } - } - } - w.write('"'); - return w; - } - - /** - * Encode a map into JSON text and write it to out. - * If this map is also a JSONAware or JSONStreamAware, JSONAware or JSONStreamAware specific behaviours will be ignored at this top level. - * - * @see blade.kit.json2.JSONValue#writeJSONString(Object, Writer) - * - * @param map - * @param out - */ - public static void writeJSONString(Map map, Writer out) throws IOException { - if(map == null){ - out.write("null"); - return; - } - - boolean first = true; - Iterator iter=map.entrySet().iterator(); - - out.write('{'); - while(iter.hasNext()){ - if(first) - first = false; - else - out.write(','); - Map.Entry entry=(Map.Entry)iter.next(); - out.write('\"'); - out.write(escape(String.valueOf(entry.getKey()))); - out.write('\"'); - out.write(':'); - JSONValue.writeJSONString(entry.getValue(), out); - } - out.write('}'); - } - - public void writeJSONString(Writer out) throws IOException{ - writeJSONString(this, out); - } - - /** - * Convert a map to JSON text. The result is a JSON object. - * If this map is also a JSONAware, JSONAware specific behaviours will be omitted at this top level. - * - * @see blade.kit.json2.JSONValue#toJSONString(Object) - * - * @param map - * @return JSON text, or "null" if map is null. - */ - public static String toJSONString(Map map){ - final StringWriter writer = new StringWriter(); - - try { - writeJSONString(map, writer); - return writer.toString(); - } catch (IOException e) { - // This should never happen with a StringWriter - throw new RuntimeException(e); - } - } - - public String toJSONString(){ - return toJSONString(this); - } - - public String toString(){ - return toJSONString(); - } - - public static String toString(String key,Object value){ - StringBuffer sb = new StringBuffer(); - sb.append('\"'); - if(key == null) - sb.append("null"); - else - JSONValue.escape(key, sb); - sb.append('\"').append(':'); - - sb.append(JSONValue.toJSONString(value)); - - return sb.toString(); - } - - /** - * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F). - * It's the same as JSONValue.escape() only for compatibility here. - * - * @see blade.kit.json2.JSONValue#escape(String) - * - * @param s - * @return - */ - public static String escape(String s){ - return JSONValue.escape(s); - } -} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONStreamAware.java b/blade-kit/src/main/java/blade/kit/json/JSONStreamAware.java deleted file mode 100644 index 75c7c07a0..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JSONStreamAware.java +++ /dev/null @@ -1,15 +0,0 @@ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; - -/** - * Beans that support customized output of JSON text to a writer shall implement this interface. - * @author FangYidong - */ -public interface JSONStreamAware { - /** - * write JSON string to out. - */ - void writeJSONString(Writer out) throws IOException; -} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONValue.java b/blade-kit/src/main/java/blade/kit/json/JSONValue.java deleted file mode 100644 index 7193140c3..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JSONValue.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * $Id: JSONValue.java,v 1.1 2006/04/15 14:37:04 platform Exp $ - * Created on 2006-4-15 - */ -package blade.kit.json; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; -import java.util.Collection; -import java.util.List; -// import java.util.List; -import java.util.Map; - -import blade.kit.json.parse.JSONParser; -import blade.kit.json.parse.ParseException; - -/** - * @author FangYidong - */ -@SuppressWarnings({"rawtypes"}) -public class JSONValue { - - /** - * Parse JSON text into java object from the input source. - * - * @see org.json.simple.parser.JSONParser - * - * @param in - * @return Instance of the following: - * org.json.simple.JSONObject, - * org.json.simple.JSONArray, - * java.lang.String, - * java.lang.Number, - * java.lang.Boolean, - * null - * - * @throws IOException - * @throws ParseException - */ - public static Object parse(Reader in) throws IOException, ParseException{ - JSONParser parser=new JSONParser(); - return parser.parse(in); - } - - public static Object parse(String s) throws ParseException{ - JSONParser parser=new JSONParser(); - return parser.parse(s); - } - - /** - * Encode an object into JSON text and write it to out. - *

- * If this object is a Map or a List, and it's also a JSONStreamAware or a JSONAware, JSONStreamAware or JSONAware will be considered firstly. - *

- * DO NOT call this method from writeJSONString(Writer) of a class that implements both JSONStreamAware and (Map or List) with - * "this" as the first parameter, use JSONObject.writeJSONString(Map, Writer) or JSONArray.writeJSONString(List, Writer) instead. - * - * @see blade.kit.json2.JSONObject#writeJSONString(Map, Writer) - * @see blade.kit.json2.JSONArray#writeJSONString(List, Writer) - * - * @param value - * @param writer - */ - public static void writeJSONString(Object value, Writer out) throws IOException { - if(value == null){ - out.write("null"); - return; - } - - if(value instanceof String){ - out.write('\"'); - out.write(escape((String)value)); - out.write('\"'); - return; - } - - if(value instanceof Double){ - if(((Double)value).isInfinite() || ((Double)value).isNaN()) - out.write("null"); - else - out.write(value.toString()); - return; - } - - if(value instanceof Float){ - if(((Float)value).isInfinite() || ((Float)value).isNaN()) - out.write("null"); - else - out.write(value.toString()); - return; - } - - if(value instanceof Number){ - out.write(value.toString()); - return; - } - - if(value instanceof Boolean){ - out.write(value.toString()); - return; - } - - if((value instanceof JSONStreamAware)){ - ((JSONStreamAware)value).writeJSONString(out); - return; - } - - if((value instanceof JSONAware)){ - out.write(((JSONAware)value).toJSONString()); - return; - } - - if(value instanceof Map){ - JSONObject.writeJSONString((Map)value, out); - return; - } - - if(value instanceof Collection){ - JSONArray.writeJSONString((Collection)value, out); - return; - } - - if(value instanceof byte[]){ - JSONArray.writeJSONString((byte[])value, out); - return; - } - - if(value instanceof short[]){ - JSONArray.writeJSONString((short[])value, out); - return; - } - - if(value instanceof int[]){ - JSONArray.writeJSONString((int[])value, out); - return; - } - - if(value instanceof long[]){ - JSONArray.writeJSONString((long[])value, out); - return; - } - - if(value instanceof float[]){ - JSONArray.writeJSONString((float[])value, out); - return; - } - - if(value instanceof double[]){ - JSONArray.writeJSONString((double[])value, out); - return; - } - - if(value instanceof boolean[]){ - JSONArray.writeJSONString((boolean[])value, out); - return; - } - - if(value instanceof char[]){ - JSONArray.writeJSONString((char[])value, out); - return; - } - - if(value instanceof Object[]){ - JSONArray.writeJSONString((Object[])value, out); - return; - } - - out.write(value.toString()); - } - - /** - * Convert an object to JSON text. - *

- * If this object is a Map or a List, and it's also a JSONAware, JSONAware will be considered firstly. - *

- * DO NOT call this method from toJSONString() of a class that implements both JSONAware and Map or List with - * "this" as the parameter, use JSONObject.toJSONString(Map) or JSONArray.toJSONString(List) instead. - * - * @see blade.kit.json2.JSONObject#toJSONString(Map) - * @see blade.kit.json2.JSONArray#toJSONString(List) - * - * @param value - * @return JSON text, or "null" if value is null or it's an NaN or an INF number. - */ - public static String toJSONString(Object value){ - final StringWriter writer = new StringWriter(); - - try{ - writeJSONString(value, writer); - return writer.toString(); - } catch(IOException e){ - // This should never happen for a StringWriter - throw new RuntimeException(e); - } - } - - /** - * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F). - * @param s - * @return - */ - public static String escape(String s){ - if(s==null) - return null; - StringBuffer sb = new StringBuffer(); - escape(s, sb); - return sb.toString(); - } - - /** - * @param s - Must not be null. - * @param sb - */ - static void escape(String s, StringBuffer sb) { - final int len = s.length(); - for(int i=0;i='\u0000' && ch<='\u001F') || (ch>='\u007F' && ch<='\u009F') || (ch>='\u2000' && ch<='\u20FF')){ - String ss=Integer.toHexString(ch); - sb.append("\\u"); - for(int k=0;k<4-ss.length();k++){ - sb.append('0'); - } - sb.append(ss.toUpperCase()); - } - else{ - sb.append(ch); - } - } - }//for - } - -} diff --git a/blade-kit/src/main/java/blade/kit/json/Json.java b/blade-kit/src/main/java/blade/kit/json/Json.java new file mode 100644 index 000000000..447de974d --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/Json.java @@ -0,0 +1,427 @@ +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Reader; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import blade.kit.CollectionKit; + +/** + * This class serves as the entry point to the minimal-json API. + *

+ * To parse a given JSON input, use the parse() + * methods like in this example: + *

+ * + *
+ * JsonObject object = Json.parse(string).asObject();
+ * 
+ *

+ * To create a JSON data structure to be serialized, use the + * methods value(), array(), and object() + * . For example, the following snippet will produce the JSON string + * {"foo": 23, "bar": true}: + *

+ * + *
+ * String string = Json.object().add("foo", 23).add("bar", true).toString();
+ * 
+ *

+ * To create a JSON array from a given Java array, you can use one of the + * array() methods with varargs parameters: + *

+ * + *
+ * String[] names = ...
+ * JsonArray array = Json.array(names);
+ * 
+ */ +@SuppressWarnings("unchecked") +public final class Json { + + private Json() { + // not meant to be instantiated + } + + /** + * Represents the JSON literal null. + */ + public static final JsonValue NULL = new JsonLiteral("null"); + + /** + * Represents the JSON literal true. + */ + public static final JsonValue TRUE = new JsonLiteral("true"); + + /** + * Represents the JSON literal false. + */ + public static final JsonValue FALSE = new JsonLiteral("false"); + + /** + * Returns a JsonValue instance that represents the given int + * value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JsonValue value(int value) { + return new JsonNumber(Integer.toString(value, 10)); + } + + /** + * Returns a JsonValue instance that represents the given long + * value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JsonValue value(long value) { + return new JsonNumber(Long.toString(value, 10)); + } + + /** + * Returns a JsonValue instance that represents the given float + * value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JsonValue value(float value) { + if (Float.isInfinite(value) || Float.isNaN(value)) { + throw new IllegalArgumentException("Infinite and NaN values not permitted in JSON"); + } + return new JsonNumber(cutOffPointZero(Float.toString(value))); + } + + /** + * Returns a JsonValue instance that represents the given + * double value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JsonValue value(double value) { + if (Double.isInfinite(value) || Double.isNaN(value)) { + throw new IllegalArgumentException("Infinite and NaN values not permitted in JSON"); + } + return new JsonNumber(cutOffPointZero(Double.toString(value))); + } + + /** + * Returns a JsonValue instance that represents the given string. + * + * @param string + * the string to get a JSON representation for + * @return a JSON value that represents the given string + */ + public static JsonValue value(String string) { + return string == null ? NULL : new JsonString(string); + } + + /** + * Returns a JsonValue instance that represents the given + * boolean value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JsonValue value(boolean value) { + return value ? TRUE : FALSE; + } + + /** + * Creates a new empty JsonArray. This is equivalent to creating a new + * JsonArray using the constructor. + * + * @return a new empty JSON array + */ + public static JsonValue array() { + return new JsonArray(); + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given int values. + * + * @param values the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JsonArray array(int... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JsonArray array = new JsonArray(); + for (int value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given long values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JsonArray array(long... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JsonArray array = new JsonArray(); + for (long value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given float values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JsonArray array(float... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JsonArray array = new JsonArray(); + for (float value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given double values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JsonArray array(double... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JsonArray array = new JsonArray(); + for (double value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given boolean values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JsonArray array(boolean... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JsonArray array = new JsonArray(); + for (boolean value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given strings. + * + * @param strings + * the strings to be included in the new JSON array + * @return a new JSON array that contains the given strings + */ + public static JsonArray array(String... strings) { + if (strings == null) { + throw new NullPointerException("values is null"); + } + JsonArray array = new JsonArray(); + for (String value : strings) { + array.add(value); + } + return array; + } + + /** + * Creates a new empty JsonObject. This is equivalent to creating a new + * JsonObject using the constructor. + * + * @return a new empty JSON object + */ + public static JsonObject object() { + return new JsonObject(); + } + + /** + * Parses the given input string as JSON. The input must contain a valid + * JSON value, optionally padded with whitespace. + * + * @param string + * the input string, must be valid JSON + * @return a value that represents the parsed JSON + * @throws ParseException + * if the input is not valid JSON + */ + public static JsonValue parse(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + try { + return new JsonParser(string).parse(); + } catch (IOException exception) { + // JsonParser does not throw IOException for String + throw new RuntimeException(exception); + } + } + + /** + * Reads the entire input stream from the given reader and parses it as + * JSON. The input must contain a valid JSON value, optionally padded with + * whitespace. + *

+ * Characters are read in chunks and buffered internally, therefore wrapping + * an existing reader in an additional BufferedReader does + * not improve reading performance. + *

+ * + * @param reader + * the reader to read the JSON value from + * @return a value that represents the parsed JSON + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + */ + public static JsonValue parse(Reader reader) throws IOException { + if (reader == null) { + throw new NullPointerException("reader is null"); + } + return new JsonParser(reader).parse(); + } + + /** + * 对象转换为JsonValue对象 + * + * @param bean + * @return + */ + public static JsonObject parse(Object bean) { + JsonObject json = new JsonObject(); + Class klass = bean.getClass(); + boolean includeSuperClass = klass.getClassLoader() != null; + + Method[] methods = includeSuperClass ? klass.getMethods() : klass.getDeclaredMethods(); + for (int i = 0; i < methods.length; i += 1) { + try { + Method method = methods[i]; + if (Modifier.isPublic(method.getModifiers())) { + String name = method.getName(); + String key = ""; + if (name.startsWith("get")) { + if ("getClass".equals(name) || "getDeclaringClass".equals(name)) { + key = ""; + } else { + key = name.substring(3); + } + } else if (name.startsWith("is")) { + key = name.substring(2); + } + if (key.length() > 0 && Character.isUpperCase(key.charAt(0)) + && method.getParameterTypes().length == 0) { + if (key.length() == 1) { + key = key.toLowerCase(); + } else if (!Character.isUpperCase(key.charAt(1))) { + key = key.substring(0, 1).toLowerCase() + key.substring(1); + } + + Object result = method.invoke(bean, (Object[]) null); + if (result != null) { + json.add(name, result); + } + } + } + } catch (Exception ignore) { + } + } + return json; + } + + public static JsonObject parse(Map map) { + if (map != null && !map.isEmpty()) { + JsonObject jsonObject = new JsonObject(); + Iterator iterator = map.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry) iterator.next(); + String key = entry.getKey(); + Object val = entry.getValue(); + jsonObject.add(key, val); + } + return jsonObject; + } + return null; + } + + public static Map parseToMap(JsonObject jo) { + Map map = CollectionKit.newHashMap(); + if (jo != null) { + List names = jo.names(); + for (String name : names) { + map.put(name, (V) jo.get(name)); + } + } + return map; + } + + public static Map parseToMap(String json) { + return parseToMap(parse(json).asObject()); + } + + private static String cutOffPointZero(String string) { + if (string.endsWith(".0")) { + return string.substring(0, string.length() - 2); + } + return string; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonArray.java b/blade-kit/src/main/java/blade/kit/json/JsonArray.java new file mode 100644 index 000000000..ac8e562c1 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JsonArray.java @@ -0,0 +1,457 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + + +/** + * Represents a JSON array, an ordered collection of JSON values. + *

+ * Elements can be added using the add(...) methods which accept instances of + * {@link JsonValue}, strings, primitive numbers, and boolean values. To replace an element of an + * array, use the set(int, ...) methods. + *

+ *

+ * Elements can be accessed by their index using {@link #get(int)}. This class also supports + * iterating over the elements in document order using an {@link #iterator()} or an enhanced for + * loop: + *

+ *
+ * for (JsonValue value : jsonArray) {
+ *   ...
+ * }
+ * 
+ *

+ * An equivalent {@link List} can be obtained from the method {@link #values()}. + *

+ *

+ * Note that this class is not thread-safe. If multiple threads access a + * JsonArray instance concurrently, while at least one of these threads modifies the + * contents of this array, access to the instance must be synchronized externally. Failure to do so + * may lead to an inconsistent state. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public class JsonArray extends JsonValue implements Iterable { + + private final List values; + + /** + * Creates a new empty JsonArray. + */ + public JsonArray() { + values = new ArrayList(); + } + + /** + * Creates a new JsonArray with the contents of the specified JSON array. + * + * @param array + * the JsonArray to get the initial contents from, must not be null + */ + public JsonArray(JsonArray array) { + this(array, false); + } + + private JsonArray(JsonArray array, boolean unmodifiable) { + if (array == null) { + throw new NullPointerException("array is null"); + } + if (unmodifiable) { + values = Collections.unmodifiableList(array.values); + } else { + values = new ArrayList(array.values); + } + } + + /** + * Returns an unmodifiable wrapper for the specified JsonArray. This method allows to provide + * read-only access to a JsonArray. + *

+ * The returned JsonArray is backed by the given array and reflects subsequent changes. Attempts + * to modify the returned JsonArray result in an UnsupportedOperationException. + *

+ * + * @param array + * the JsonArray for which an unmodifiable JsonArray is to be returned + * @return an unmodifiable view of the specified JsonArray + */ + public static JsonArray unmodifiableArray(JsonArray array) { + return new JsonArray(array, true); + } + + /** + * Appends the JSON representation of the specified int value to the end of this + * array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JsonArray add(int value) { + values.add(Json.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified long value to the end of this + * array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JsonArray add(long value) { + values.add(Json.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified float value to the end of this + * array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JsonArray add(float value) { + values.add(Json.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified double value to the end of this + * array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JsonArray add(double value) { + values.add(Json.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified boolean value to the end of this + * array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JsonArray add(boolean value) { + values.add(Json.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified string to the end of this array. + * + * @param value + * the string to add to the array + * @return the array itself, to enable method chaining + */ + public JsonArray add(String value) { + values.add(Json.value(value)); + return this; + } + + /** + * Appends the specified JSON value to the end of this array. + * + * @param value + * the JsonValue to add to the array, must not be null + * @return the array itself, to enable method chaining + */ + public JsonArray add(JsonValue value) { + if (value == null) { + throw new NullPointerException("value is null"); + } + values.add(value); + return this; + } + + /** + * Replaces the element at the specified position in this array with the JSON representation of + * the specified int value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 or + * index >= size + */ + public JsonArray set(int index, int value) { + values.set(index, Json.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the JSON representation of + * the specified long value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 or + * index >= size + */ + public JsonArray set(int index, long value) { + values.set(index, Json.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the JSON representation of + * the specified float value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 or + * index >= size + */ + public JsonArray set(int index, float value) { + values.set(index, Json.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the JSON representation of + * the specified double value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 or + * index >= size + */ + public JsonArray set(int index, double value) { + values.set(index, Json.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the JSON representation of + * the specified boolean value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 or + * index >= size + */ + public JsonArray set(int index, boolean value) { + values.set(index, Json.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the JSON representation of + * the specified string. + * + * @param index + * the index of the array element to replace + * @param value + * the string to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 or + * index >= size + */ + public JsonArray set(int index, String value) { + values.set(index, Json.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the specified JSON value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position, must not be null + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 or + * index >= size + */ + public JsonArray set(int index, JsonValue value) { + if (value == null) { + throw new NullPointerException("value is null"); + } + values.set(index, value); + return this; + } + + /** + * Removes the element at the specified index from this array. + * + * @param index + * the index of the element to remove + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 or + * index >= size + */ + public JsonArray remove(int index) { + values.remove(index); + return this; + } + + /** + * Returns the number of elements in this array. + * + * @return the number of elements in this array + */ + public int size() { + return values.size(); + } + + /** + * Returns true if this array contains no elements. + * + * @return true if this array contains no elements + */ + public boolean isEmpty() { + return values.isEmpty(); + } + + /** + * Returns the value of the element at the specified position in this array. + * + * @param index + * the index of the array element to return + * @return the value of the element at the specified position + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 or + * index >= size + */ + public JsonValue get(int index) { + return values.get(index); + } + + /** + * Returns a list of the values in this array in document order. The returned list is backed by + * this array and will reflect subsequent changes. It cannot be used to modify this array. + * Attempts to modify the returned list will result in an exception. + * + * @return a list of the values in this array + */ + public List values() { + return Collections.unmodifiableList(values); + } + + /** + * Returns an iterator over the values of this array in document order. The returned iterator + * cannot be used to modify this array. + * + * @return an iterator over the values of this array + */ + public Iterator iterator() { + final Iterator iterator = values.iterator(); + return new Iterator() { + + public boolean hasNext() { + return iterator.hasNext(); + } + + public JsonValue next() { + return iterator.next(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + void write(JsonWriter writer) throws IOException { + writer.writeArrayOpen(); + Iterator iterator = iterator(); + boolean first = true; + while (iterator.hasNext()) { + if (!first) { + writer.writeArraySeparator(); + } + iterator.next().write(writer); + first = false; + } + writer.writeArrayClose(); + } + + @Override + public boolean isArray() { + return true; + } + + @Override + public JsonArray asArray() { + return this; + } + + @Override + public int hashCode() { + return values.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JsonArray other = (JsonArray)object; + return values.equals(other.values); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonLiteral.java b/blade-kit/src/main/java/blade/kit/json/JsonLiteral.java new file mode 100644 index 000000000..ea32b91bc --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JsonLiteral.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; + + +@SuppressWarnings("serial") // use default serial UID +class JsonLiteral extends JsonValue { + + private final String value; + private final boolean isNull; + private final boolean isTrue; + private final boolean isFalse; + + JsonLiteral(String value) { + this.value = value; + isNull = "null".equals(value); + isTrue = "true".equals(value); + isFalse = "false".equals(value); + } + + @Override + void write(JsonWriter writer) throws IOException { + writer.writeLiteral(value); + } + + @Override + public String toString() { + return value; + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public boolean isNull() { + return isNull; + } + + @Override + public boolean isTrue() { + return isTrue; + } + + @Override + public boolean isFalse() { + return isFalse; + } + + @Override + public boolean isBoolean() { + return isTrue || isFalse; + } + + @Override + public boolean asBoolean() { + return isNull ? super.asBoolean() : isTrue; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JsonLiteral other = (JsonLiteral)object; + return value.equals(other.value); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonNumber.java b/blade-kit/src/main/java/blade/kit/json/JsonNumber.java new file mode 100644 index 000000000..4ff0c4b8a --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JsonNumber.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; + + +@SuppressWarnings("serial") // use default serial UID +class JsonNumber extends JsonValue { + + private final String string; + + JsonNumber(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + this.string = string; + } + + @Override + public String toString() { + return string; + } + + @Override + void write(JsonWriter writer) throws IOException { + writer.writeNumber(string); + } + + @Override + public boolean isNumber() { + return true; + } + + @Override + public int asInt() { + return Integer.parseInt(string, 10); + } + + @Override + public long asLong() { + return Long.parseLong(string, 10); + } + + @Override + public float asFloat() { + return Float.parseFloat(string); + } + + @Override + public double asDouble() { + return Double.parseDouble(string); + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JsonNumber other = (JsonNumber)object; + return string.equals(other.string); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonObject.java b/blade-kit/src/main/java/blade/kit/json/JsonObject.java new file mode 100644 index 000000000..2b863e692 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JsonObject.java @@ -0,0 +1,966 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import blade.kit.json.JsonObject.Member; + + +/** + * Represents a JSON object, a set of name/value pairs, where the names are strings and the values + * are JSON values. + *

+ * Members can be added using the add(String, ...) methods which accept instances of + * {@link JsonValue}, strings, primitive numbers, and boolean values. To modify certain values of an + * object, use the set(String, ...) methods. Please note that the add + * methods are faster than set as they do not search for existing members. On the other + * hand, the add methods do not prevent adding multiple members with the same name. + * Duplicate names are discouraged but not prohibited by JSON. + *

+ *

+ * Members can be accessed by their name using {@link #get(String)}. A list of all names can be + * obtained from the method {@link #names()}. This class also supports iterating over the members in + * document order using an {@link #iterator()} or an enhanced for loop: + *

+ *
+ * for (Member member : jsonObject) {
+ *   String name = member.getName();
+ *   JsonValue value = member.getValue();
+ *   ...
+ * }
+ * 
+ *

+ * Even though JSON objects are unordered by definition, instances of this class preserve the order + * of members to allow processing in document order and to guarantee a predictable output. + *

+ *

+ * Note that this class is not thread-safe. If multiple threads access a + * JsonObject instance concurrently, while at least one of these threads modifies the + * contents of this object, access to the instance must be synchronized externally. Failure to do so + * may lead to an inconsistent state. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public class JsonObject extends JsonValue implements Iterable { + + private final List names; + private final List values; + private transient HashIndexTable table; + + /** + * Creates a new empty JsonObject. + */ + public JsonObject() { + names = new ArrayList(); + values = new ArrayList(); + table = new HashIndexTable(); + } + + /** + * Creates a new JsonObject, initialized with the contents of the specified JSON object. + * + * @param object + * the JSON object to get the initial contents from, must not be null + */ + public JsonObject(JsonObject object) { + this(object, false); + } + + private JsonObject(JsonObject object, boolean unmodifiable) { + if (object == null) { + throw new NullPointerException("object is null"); + } + if (unmodifiable) { + names = Collections.unmodifiableList(object.names); + values = Collections.unmodifiableList(object.values); + } else { + names = new ArrayList(object.names); + values = new ArrayList(object.values); + } + table = new HashIndexTable(); + updateHashIndex(); + } + + /** + * Returns an unmodifiable JsonObject for the specified one. This method allows to provide + * read-only access to a JsonObject. + *

+ * The returned JsonObject is backed by the given object and reflect changes that happen to it. + * Attempts to modify the returned JsonObject result in an + * UnsupportedOperationException. + *

+ * + * @param object + * the JsonObject for which an unmodifiable JsonObject is to be returned + * @return an unmodifiable view of the specified JsonObject + */ + public static JsonObject unmodifiableObject(JsonObject object) { + return new JsonObject(object, true); + } + + /** + * Appends a new member to the end of this object, with the specified name and the JSON + * representation of the specified int value. + *

+ * This method does not prevent duplicate names. Calling this method with a name + * that already exists in the object will append another member with the same name. In order to + * replace existing members, use the method set(name, value) instead. However, + * add is much faster than set (because it does not need to + * search for existing members). Therefore add should be preferred when constructing new + * objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JsonObject add(String name, int value) { + add(name, Json.value(value)); + return this; + } + + public JsonObject add(String name, Object value) { + + if(value instanceof String){ + add(name, Json.value((String) value)); + } + + if(value instanceof Integer){ + add(name, Json.value((Integer) value)); + } + + if(value instanceof Long){ + add(name, Json.value((Long) value)); + } + + if(value instanceof JsonValue){ + add(name, (JsonValue) value); + } + + if(value instanceof JsonObject){ + add(name, (JsonObject) value); + } + + if(value instanceof JsonArray){ + add(name, (JsonArray) value); + } + + if(value instanceof Boolean){ + add(name, Json.value((Boolean) value)); + } + + if(value instanceof Byte){ + add(name, Json.value((Byte) value)); + } + + if(value instanceof Character){ + add(name, Json.value((Character) value)); + } + + if(value instanceof Short){ + add(name, Json.value((Short) value)); + } + + if(value instanceof Float){ + add(name, Json.value((Float) value)); + } + + if(value instanceof Double){ + add(name, Json.value((Double) value)); + } + + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name and the JSON + * representation of the specified long value. + *

+ * This method does not prevent duplicate names. Calling this method with a name + * that already exists in the object will append another member with the same name. In order to + * replace existing members, use the method set(name, value) instead. However, + * add is much faster than set (because it does not need to + * search for existing members). Therefore add should be preferred when constructing new + * objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JsonObject add(String name, long value) { + add(name, Json.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name and the JSON + * representation of the specified float value. + *

+ * This method does not prevent duplicate names. Calling this method with a name + * that already exists in the object will append another member with the same name. In order to + * replace existing members, use the method set(name, value) instead. However, + * add is much faster than set (because it does not need to + * search for existing members). Therefore add should be preferred when constructing new + * objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JsonObject add(String name, float value) { + add(name, Json.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name and the JSON + * representation of the specified double value. + *

+ * This method does not prevent duplicate names. Calling this method with a name + * that already exists in the object will append another member with the same name. In order to + * replace existing members, use the method set(name, value) instead. However, + * add is much faster than set (because it does not need to + * search for existing members). Therefore add should be preferred when constructing new + * objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JsonObject add(String name, double value) { + add(name, Json.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name and the JSON + * representation of the specified boolean value. + *

+ * This method does not prevent duplicate names. Calling this method with a name + * that already exists in the object will append another member with the same name. In order to + * replace existing members, use the method set(name, value) instead. However, + * add is much faster than set (because it does not need to + * search for existing members). Therefore add should be preferred when constructing new + * objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JsonObject add(String name, boolean value) { + add(name, Json.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name and the JSON + * representation of the specified string. + *

+ * This method does not prevent duplicate names. Calling this method with a name + * that already exists in the object will append another member with the same name. In order to + * replace existing members, use the method set(name, value) instead. However, + * add is much faster than set (because it does not need to + * search for existing members). Therefore add should be preferred when constructing new + * objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JsonObject add(String name, String value) { + add(name, Json.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name and the specified JSON + * value. + *

+ * This method does not prevent duplicate names. Calling this method with a name + * that already exists in the object will append another member with the same name. In order to + * replace existing members, use the method set(name, value) instead. However, + * add is much faster than set (because it does not need to + * search for existing members). Therefore add should be preferred when constructing new + * objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add, must not be null + * @return the object itself, to enable method chaining + */ + public JsonObject add(String name, JsonValue value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + table.add(name, names.size()); + names.add(name); + values.add(value); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON representation of the + * specified int value. If this object does not contain a member with this name, a + * new member is added at the end of the object. If this object contains multiple members with + * this name, only the last one is changed. + *

+ * This method should only be used to modify existing objects. To fill a new + * object with members, the method add(name, value) should be preferred which is much + * faster (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to replace + * @param value + * the value to set to the member + * @return the object itself, to enable method chaining + */ + public JsonObject set(String name, int value) { + set(name, Json.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON representation of the + * specified long value. If this object does not contain a member with this name, a + * new member is added at the end of the object. If this object contains multiple members with + * this name, only the last one is changed. + *

+ * This method should only be used to modify existing objects. To fill a new + * object with members, the method add(name, value) should be preferred which is much + * faster (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to replace + * @param value + * the value to set to the member + * @return the object itself, to enable method chaining + */ + public JsonObject set(String name, long value) { + set(name, Json.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON representation of the + * specified float value. If this object does not contain a member with this name, a + * new member is added at the end of the object. If this object contains multiple members with + * this name, only the last one is changed. + *

+ * This method should only be used to modify existing objects. To fill a new + * object with members, the method add(name, value) should be preferred which is much + * faster (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JsonObject set(String name, float value) { + set(name, Json.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON representation of the + * specified double value. If this object does not contain a member with this name, a + * new member is added at the end of the object. If this object contains multiple members with + * this name, only the last one is changed. + *

+ * This method should only be used to modify existing objects. To fill a new + * object with members, the method add(name, value) should be preferred which is much + * faster (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JsonObject set(String name, double value) { + set(name, Json.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON representation of the + * specified boolean value. If this object does not contain a member with this name, + * a new member is added at the end of the object. If this object contains multiple members with + * this name, only the last one is changed. + *

+ * This method should only be used to modify existing objects. To fill a new + * object with members, the method add(name, value) should be preferred which is much + * faster (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JsonObject set(String name, boolean value) { + set(name, Json.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON representation of the + * specified string. If this object does not contain a member with this name, a new member is + * added at the end of the object. If this object contains multiple members with this name, only + * the last one is changed. + *

+ * This method should only be used to modify existing objects. To fill a new + * object with members, the method add(name, value) should be preferred which is much + * faster (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JsonObject set(String name, String value) { + set(name, Json.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the specified JSON value. If this + * object does not contain a member with this name, a new member is added at the end of the + * object. If this object contains multiple members with this name, only the last one is changed. + *

+ * This method should only be used to modify existing objects. To fill a new + * object with members, the method add(name, value) should be preferred which is much + * faster (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add, must not be null + * @return the object itself, to enable method chaining + */ + public JsonObject set(String name, JsonValue value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + int index = indexOf(name); + if (index != -1) { + values.set(index, value); + } else { + table.add(name, names.size()); + names.add(name); + values.add(value); + } + return this; + } + + /** + * Removes a member with the specified name from this object. If this object contains multiple + * members with the given name, only the last one is removed. If this object does not contain a + * member with the specified name, the object is not modified. + * + * @param name + * the name of the member to remove + * @return the object itself, to enable method chaining + */ + public JsonObject remove(String name) { + if (name == null) { + throw new NullPointerException("name is null"); + } + int index = indexOf(name); + if (index != -1) { + table.remove(index); + names.remove(index); + values.remove(index); + } + return this; + } + + /** + * Copies all members of the specified object into this object. When the specified object contains + * members with names that also exist in this object, the existing values in this object will be + * replaced by the corresponding values in the specified object. + * + * @param object + * the object to merge + * @return the object itself, to enable method chaining + */ + public JsonObject merge(JsonObject object) { + if (object == null) { + throw new NullPointerException("object is null"); + } + for (Member member : object) { + this.set(member.name, member.value); + } + return this; + } + + /** + * Returns the value of the member with the specified name in this object. If this object contains + * multiple members with the given name, this method will return the last one. + * + * @param name + * the name of the member whose value is to be returned + * @return the value of the last member with the specified name, or null if this + * object does not contain a member with that name + */ + public JsonValue get(String name) { + if (name == null) { + throw new NullPointerException("name is null"); + } + int index = indexOf(name); + return index != -1 ? values.get(index) : null; + } + + /** + * Returns the int value of the member with the specified name in this object. If + * this object does not contain a member with this name, the given default value is returned. If + * this object contains multiple members with the given name, the last one will be picked. If this + * member's value does not represent a JSON number or if it cannot be interpreted as Java + * int, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the given default value if + * this object does not contain a member with that name + */ + public int getInt(String name, int defaultValue) { + JsonValue value = get(name); + return value != null ? value.asInt() : defaultValue; + } + + public Integer getInt(String name) { + JsonValue value = get(name); + if(null != value){ + return value.asInt(); + } + return null; + } + + /** + * Returns the long value of the member with the specified name in this object. If + * this object does not contain a member with this name, the given default value is returned. If + * this object contains multiple members with the given name, the last one will be picked. If this + * member's value does not represent a JSON number or if it cannot be interpreted as Java + * long, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the given default value if + * this object does not contain a member with that name + */ + public long getLong(String name, long defaultValue) { + JsonValue value = get(name); + return value != null ? value.asLong() : defaultValue; + } + + public Long getLong(String name) { + JsonValue value = get(name); + if(null != value){ + return value.asLong(); + } + return null; + } + + /** + * Returns the float value of the member with the specified name in this object. If + * this object does not contain a member with this name, the given default value is returned. If + * this object contains multiple members with the given name, the last one will be picked. If this + * member's value does not represent a JSON number or if it cannot be interpreted as Java + * float, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the given default value if + * this object does not contain a member with that name + */ + public float getFloat(String name, float defaultValue) { + JsonValue value = get(name); + return value != null ? value.asFloat() : defaultValue; + } + + public Float getFloat(String name) { + JsonValue value = get(name); + if(null != value){ + return value.asFloat(); + } + return null; + } + + /** + * Returns the double value of the member with the specified name in this object. If + * this object does not contain a member with this name, the given default value is returned. If + * this object contains multiple members with the given name, the last one will be picked. If this + * member's value does not represent a JSON number or if it cannot be interpreted as Java + * double, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the given default value if + * this object does not contain a member with that name + */ + public double getDouble(String name, double defaultValue) { + JsonValue value = get(name); + return value != null ? value.asDouble() : defaultValue; + } + + public Double getDouble(String name) { + JsonValue value = get(name); + if(null != value){ + return value.asDouble(); + } + return null; + } + + /** + * Returns the boolean value of the member with the specified name in this object. If + * this object does not contain a member with this name, the given default value is returned. If + * this object contains multiple members with the given name, the last one will be picked. If this + * member's value does not represent a JSON true or false value, an + * exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the given default value if + * this object does not contain a member with that name + */ + public boolean getBoolean(String name, boolean defaultValue) { + JsonValue value = get(name); + return value != null ? value.asBoolean() : defaultValue; + } + + public Boolean getBoolean(String name) { + JsonValue value = get(name); + if(null != value){ + return value.asBoolean(); + } + return null; + } + + /** + * Returns the String value of the member with the specified name in this object. If + * this object does not contain a member with this name, the given default value is returned. If + * this object contains multiple members with the given name, the last one is picked. If this + * member's value does not represent a JSON string, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the given default value if + * this object does not contain a member with that name + */ + public String getString(String name, String defaultValue) { + JsonValue value = get(name); + return value != null ? value.asString() : defaultValue; + } + + public String getString(String name) { + JsonValue value = get(name); + if(null != value){ + return value.asString(); + } + return null; + } + + /** + * Returns the number of members (name/value pairs) in this object. + * + * @return the number of members in this object + */ + public int size() { + return names.size(); + } + + /** + * Returns true if this object contains no members. + * + * @return true if this object contains no members + */ + public boolean isEmpty() { + return names.isEmpty(); + } + + /** + * Returns a list of the names in this object in document order. The returned list is backed by + * this object and will reflect subsequent changes. It cannot be used to modify this object. + * Attempts to modify the returned list will result in an exception. + * + * @return a list of the names in this object + */ + public List names() { + return Collections.unmodifiableList(names); + } + + /** + * Returns an iterator over the members of this object in document order. The returned iterator + * cannot be used to modify this object. + * + * @return an iterator over the members of this object + */ + public Iterator iterator() { + final Iterator namesIterator = names.iterator(); + final Iterator valuesIterator = values.iterator(); + return new Iterator() { + + public boolean hasNext() { + return namesIterator.hasNext(); + } + + public Member next() { + String name = namesIterator.next(); + JsonValue value = valuesIterator.next(); + return new Member(name, value); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + }; + } + + @Override + void write(JsonWriter writer) throws IOException { + writer.writeObjectOpen(); + Iterator namesIterator = names.iterator(); + Iterator valuesIterator = values.iterator(); + boolean first = true; + while (namesIterator.hasNext()) { + if (!first) { + writer.writeObjectSeparator(); + } + writer.writeMemberName(namesIterator.next()); + writer.writeMemberSeparator(); + valuesIterator.next().write(writer); + first = false; + } + writer.writeObjectClose(); + } + + @Override + public boolean isObject() { + return true; + } + + @Override + public JsonObject asObject() { + return this; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + names.hashCode(); + result = 31 * result + values.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + JsonObject other = (JsonObject)obj; + return names.equals(other.names) && values.equals(other.values); + } + + int indexOf(String name) { + int index = table.get(name); + if (index != -1 && name.equals(names.get(index))) { + return index; + } + return names.lastIndexOf(name); + } + + private synchronized void readObject(ObjectInputStream inputStream) + throws IOException, ClassNotFoundException + { + inputStream.defaultReadObject(); + table = new HashIndexTable(); + updateHashIndex(); + } + + private void updateHashIndex() { + int size = names.size(); + for (int i = 0; i < size; i++) { + table.add(names.get(i), i); + } + } + + /** + * Represents a member of a JSON object, a pair of a name and a value. + */ + public static class Member { + + private final String name; + private final JsonValue value; + + Member(String name, JsonValue value) { + this.name = name; + this.value = value; + } + + /** + * Returns the name of this member. + * + * @return the name of this member, never null + */ + public String getName() { + return name; + } + + /** + * Returns the value of this member. + * + * @return the value of this member, never null + */ + public JsonValue getValue() { + return value; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + name.hashCode(); + result = 31 * result + value.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Member other = (Member)obj; + return name.equals(other.name) && value.equals(other.value); + } + + } + + static class HashIndexTable { + + private final byte[] hashTable = new byte[32]; // must be a power of two + + public HashIndexTable() { + } + + public HashIndexTable(HashIndexTable original) { + System.arraycopy(original.hashTable, 0, hashTable, 0, hashTable.length); + } + + void add(String name, int index) { + int slot = hashSlotFor(name); + if (index < 0xff) { + // increment by 1, 0 stands for empty + hashTable[slot] = (byte)(index + 1); + } else { + hashTable[slot] = 0; + } + } + + void remove(int index) { + for (int i = 0; i < hashTable.length; i++) { + if (hashTable[i] == index + 1) { + hashTable[i] = 0; + } else if (hashTable[i] > index + 1) { + hashTable[i]--; + } + } + } + + int get(Object name) { + int slot = hashSlotFor(name); + // subtract 1, 0 stands for empty + return (hashTable[slot] & 0xff) - 1; + } + + private int hashSlotFor(Object element) { + return element.hashCode() & hashTable.length - 1; + } + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonParser.java b/blade-kit/src/main/java/blade/kit/json/JsonParser.java new file mode 100644 index 000000000..c1cc3274c --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JsonParser.java @@ -0,0 +1,400 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + + +class JsonParser { + + private static final int MIN_BUFFER_SIZE = 10; + private static final int DEFAULT_BUFFER_SIZE = 1024; + + private final Reader reader; + private final char[] buffer; + private int bufferOffset; + private int index; + private int fill; + private int line; + private int lineOffset; + private int current; + private StringBuilder captureBuffer; + private int captureStart; + + /* + * | bufferOffset + * v + * [a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t] < input + * [l|m|n|o|p|q|r|s|t|?|?] < buffer + * ^ ^ + * | index fill + */ + + JsonParser(String string) { + this(new StringReader(string), + Math.max(MIN_BUFFER_SIZE, Math.min(DEFAULT_BUFFER_SIZE, string.length()))); + } + + JsonParser(Reader reader) { + this(reader, DEFAULT_BUFFER_SIZE); + } + + JsonParser(Reader reader, int buffersize) { + this.reader = reader; + buffer = new char[buffersize]; + line = 1; + captureStart = -1; + } + + JsonValue parse() throws IOException { + read(); + skipWhiteSpace(); + JsonValue result = readValue(); + skipWhiteSpace(); + if (!isEndOfText()) { + throw error("Unexpected character"); + } + return result; + } + + private JsonValue readValue() throws IOException { + switch (current) { + case 'n': + return readNull(); + case 't': + return readTrue(); + case 'f': + return readFalse(); + case '"': + return readString(); + case '[': + return readArray(); + case '{': + return readObject(); + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return readNumber(); + default: + throw expected("value"); + } + } + + private JsonArray readArray() throws IOException { + read(); + JsonArray array = new JsonArray(); + skipWhiteSpace(); + if (readChar(']')) { + return array; + } + do { + skipWhiteSpace(); + array.add(readValue()); + skipWhiteSpace(); + } while (readChar(',')); + if (!readChar(']')) { + throw expected("',' or ']'"); + } + return array; + } + + private JsonObject readObject() throws IOException { + read(); + JsonObject object = new JsonObject(); + skipWhiteSpace(); + if (readChar('}')) { + return object; + } + do { + skipWhiteSpace(); + String name = readName(); + skipWhiteSpace(); + if (!readChar(':')) { + throw expected("':'"); + } + skipWhiteSpace(); + object.add(name, readValue()); + skipWhiteSpace(); + } while (readChar(',')); + if (!readChar('}')) { + throw expected("',' or '}'"); + } + return object; + } + + private String readName() throws IOException { + if (current != '"') { + throw expected("name"); + } + return readStringInternal(); + } + + private JsonValue readNull() throws IOException { + read(); + readRequiredChar('u'); + readRequiredChar('l'); + readRequiredChar('l'); + return Json.NULL; + } + + private JsonValue readTrue() throws IOException { + read(); + readRequiredChar('r'); + readRequiredChar('u'); + readRequiredChar('e'); + return Json.TRUE; + } + + private JsonValue readFalse() throws IOException { + read(); + readRequiredChar('a'); + readRequiredChar('l'); + readRequiredChar('s'); + readRequiredChar('e'); + return Json.FALSE; + } + + private void readRequiredChar(char ch) throws IOException { + if (!readChar(ch)) { + throw expected("'" + ch + "'"); + } + } + + private JsonValue readString() throws IOException { + return new JsonString(readStringInternal()); + } + + private String readStringInternal() throws IOException { + read(); + startCapture(); + while (current != '"') { + if (current == '\\') { + pauseCapture(); + readEscape(); + startCapture(); + } else if (current < 0x20) { + throw expected("valid string character"); + } else { + read(); + } + } + String string = endCapture(); + read(); + return string; + } + + private void readEscape() throws IOException { + read(); + switch (current) { + case '"': + case '/': + case '\\': + captureBuffer.append((char)current); + break; + case 'b': + captureBuffer.append('\b'); + break; + case 'f': + captureBuffer.append('\f'); + break; + case 'n': + captureBuffer.append('\n'); + break; + case 'r': + captureBuffer.append('\r'); + break; + case 't': + captureBuffer.append('\t'); + break; + case 'u': + char[] hexChars = new char[4]; + for (int i = 0; i < 4; i++) { + read(); + if (!isHexDigit()) { + throw expected("hexadecimal digit"); + } + hexChars[i] = (char)current; + } + captureBuffer.append((char)Integer.parseInt(new String(hexChars), 16)); + break; + default: + throw expected("valid escape sequence"); + } + read(); + } + + private JsonValue readNumber() throws IOException { + startCapture(); + readChar('-'); + int firstDigit = current; + if (!readDigit()) { + throw expected("digit"); + } + if (firstDigit != '0') { + while (readDigit()) { + } + } + readFraction(); + readExponent(); + return new JsonNumber(endCapture()); + } + + private boolean readFraction() throws IOException { + if (!readChar('.')) { + return false; + } + if (!readDigit()) { + throw expected("digit"); + } + while (readDigit()) { + } + return true; + } + + private boolean readExponent() throws IOException { + if (!readChar('e') && !readChar('E')) { + return false; + } + if (!readChar('+')) { + readChar('-'); + } + if (!readDigit()) { + throw expected("digit"); + } + while (readDigit()) { + } + return true; + } + + private boolean readChar(char ch) throws IOException { + if (current != ch) { + return false; + } + read(); + return true; + } + + private boolean readDigit() throws IOException { + if (!isDigit()) { + return false; + } + read(); + return true; + } + + private void skipWhiteSpace() throws IOException { + while (isWhiteSpace()) { + read(); + } + } + + private void read() throws IOException { + if (index == fill) { + if (captureStart != -1) { + captureBuffer.append(buffer, captureStart, fill - captureStart); + captureStart = 0; + } + bufferOffset += fill; + fill = reader.read(buffer, 0, buffer.length); + index = 0; + if (fill == -1) { + current = -1; + return; + } + } + if (current == '\n') { + line++; + lineOffset = bufferOffset + index; + } + current = buffer[index++]; + } + + private void startCapture() { + if (captureBuffer == null) { + captureBuffer = new StringBuilder(); + } + captureStart = index - 1; + } + + private void pauseCapture() { + int end = current == -1 ? index : index - 1; + captureBuffer.append(buffer, captureStart, end - captureStart); + captureStart = -1; + } + + private String endCapture() { + int end = current == -1 ? index : index - 1; + String captured; + if (captureBuffer.length() > 0) { + captureBuffer.append(buffer, captureStart, end - captureStart); + captured = captureBuffer.toString(); + captureBuffer.setLength(0); + } else { + captured = new String(buffer, captureStart, end - captureStart); + } + captureStart = -1; + return captured; + } + + private ParseException expected(String expected) { + if (isEndOfText()) { + return error("Unexpected end of input"); + } + return error("Expected " + expected); + } + + private ParseException error(String message) { + int absIndex = bufferOffset + index; + int column = absIndex - lineOffset; + int offset = isEndOfText() ? absIndex : absIndex - 1; + return new ParseException(message, offset, line, column - 1); + } + + private boolean isWhiteSpace() { + return current == ' ' || current == '\t' || current == '\n' || current == '\r'; + } + + private boolean isDigit() { + return current >= '0' && current <= '9'; + } + + private boolean isHexDigit() { + return current >= '0' && current <= '9' + || current >= 'a' && current <= 'f' + || current >= 'A' && current <= 'F'; + } + + private boolean isEndOfText() { + return current == -1; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonString.java b/blade-kit/src/main/java/blade/kit/json/JsonString.java new file mode 100644 index 000000000..4d7a188bf --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JsonString.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; + + +@SuppressWarnings("serial") // use default serial UID +class JsonString extends JsonValue { + + private final String string; + + JsonString(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + this.string = string; + } + + @Override + void write(JsonWriter writer) throws IOException { + writer.writeString(string); + } + + @Override + public boolean isString() { + return true; + } + + @Override + public String asString() { + return string; + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JsonString other = (JsonString)object; + return string.equals(other.string); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonValue.java b/blade-kit/src/main/java/blade/kit/json/JsonValue.java new file mode 100644 index 000000000..61b3f1792 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JsonValue.java @@ -0,0 +1,500 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Reader; +import java.io.Serializable; +import java.io.StringWriter; +import java.io.Writer; + + +/** + * Represents a JSON value. This can be a JSON object, an array, + * a number, a string, or one of the literals + * true, false, and null. + *

+ * The literals true, false, and null are + * represented by the constants {@link #TRUE}, {@link #FALSE}, and {@link #NULL}. + *

+ *

+ * JSON objects and arrays are represented by the subtypes + * {@link JsonObject} and {@link JsonArray}. Instances of these types can be created using the + * public constructors of these classes. + *

+ *

+ * Instances that represent JSON numbers, strings and + * boolean values can be created using the static factory methods + * {@link #valueOf(String)}, {@link #valueOf(long)}, {@link #valueOf(double)}, etc. + *

+ *

+ * In order to find out whether an instance of this class is of a certain type, the methods + * {@link #isObject()}, {@link #isArray()}, {@link #isString()}, {@link #isNumber()} etc. can be + * used. + *

+ *

+ * If the type of a JSON value is known, the methods {@link #asObject()}, {@link #asArray()}, + * {@link #asString()}, {@link #asInt()}, etc. can be used to get this value directly in the + * appropriate target type. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public abstract class JsonValue implements Serializable { + + /** + * Represents the JSON literal true. + * @deprecated Use Json.TRUE instead + */ + @Deprecated + public static final JsonValue TRUE = new JsonLiteral("true"); + + /** + * Represents the JSON literal false. + * @deprecated Use Json.FALSE instead + */ + @Deprecated + public static final JsonValue FALSE = new JsonLiteral("false"); + + /** + * Represents the JSON literal null. + * @deprecated Use Json.NULL instead + */ + @Deprecated + public static final JsonValue NULL = new JsonLiteral("null"); + + JsonValue() { + // prevent subclasses outside of this package + } + + /** + * Reads a JSON value from the given reader. + *

+ * Characters are read in chunks and buffered internally, therefore wrapping an existing reader in + * an additional BufferedReader does not improve reading + * performance. + *

+ * + * @param reader + * the reader to read the JSON value from + * @return the JSON value that has been read + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + * @deprecated Use {@link Json#parse(Reader)} instead + */ + @Deprecated + public static JsonValue readFrom(Reader reader) throws IOException { + return new JsonParser(reader).parse(); + } + + /** + * Reads a JSON value from the given string. + * + * @param text + * the string that contains the JSON value + * @return the JSON value that has been read + * @throws ParseException + * if the input is not valid JSON + * @deprecated Use {@link Json#parse(String)} instead + */ + @Deprecated + public static JsonValue readFrom(String text) { + try { + return new JsonParser(text).parse(); + } catch (IOException exception) { + // JsonParser does not throw IOException for String + throw new RuntimeException(exception); + } + } + + /** + * Returns a JsonValue instance that represents the given int value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JsonValue valueOf(int value) { + return Json.value(value); + } + + /** + * Returns a JsonValue instance that represents the given long value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JsonValue valueOf(long value) { + return Json.value(value); + } + + /** + * Returns a JsonValue instance that represents the given float value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JsonValue valueOf(float value) { + return Json.value(value); + } + + /** + * Returns a JsonValue instance that represents the given double value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JsonValue valueOf(double value) { + return Json.value(value); + } + + /** + * Returns a JsonValue instance that represents the given string. + * + * @param string + * the string to get a JSON representation for + * @return a JSON value that represents the given string + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JsonValue valueOf(String string) { + return Json.value(string); + } + + /** + * Returns a JsonValue instance that represents the given boolean value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JsonValue valueOf(boolean value) { + return Json.value(value); + } + + /** + * Detects whether this value represents a JSON object. If this is the case, this value is an + * instance of {@link JsonObject}. + * + * @return true if this value is an instance of JsonObject + */ + public boolean isObject() { + return false; + } + + /** + * Detects whether this value represents a JSON array. If this is the case, this value is an + * instance of {@link JsonArray}. + * + * @return true if this value is an instance of JsonArray + */ + public boolean isArray() { + return false; + } + + /** + * Detects whether this value represents a JSON number. + * + * @return true if this value represents a JSON number + */ + public boolean isNumber() { + return false; + } + + /** + * Detects whether this value represents a JSON string. + * + * @return true if this value represents a JSON string + */ + public boolean isString() { + return false; + } + + /** + * Detects whether this value represents a boolean value. + * + * @return true if this value represents either the JSON literal true or + * false + */ + public boolean isBoolean() { + return false; + } + + /** + * Detects whether this value represents the JSON literal true. + * + * @return true if this value represents the JSON literal true + */ + public boolean isTrue() { + return false; + } + + /** + * Detects whether this value represents the JSON literal false. + * + * @return true if this value represents the JSON literal false + */ + public boolean isFalse() { + return false; + } + + /** + * Detects whether this value represents the JSON literal null. + * + * @return true if this value represents the JSON literal null + */ + public boolean isNull() { + return false; + } + + /** + * Returns this JSON value as {@link JsonObject}, assuming that this value represents a JSON + * object. If this is not the case, an exception is thrown. + * + * @return a JSONObject for this value + * @throws UnsupportedOperationException + * if this value is not a JSON object + */ + public JsonObject asObject() { + throw new UnsupportedOperationException("Not an object: " + toString()); + } + + /** + * Returns this JSON value as {@link JsonArray}, assuming that this value represents a JSON array. + * If this is not the case, an exception is thrown. + * + * @return a JSONArray for this value + * @throws UnsupportedOperationException + * if this value is not a JSON array + */ + public JsonArray asArray() { + throw new UnsupportedOperationException("Not an array: " + toString()); + } + + /** + * Returns this JSON value as an int value, assuming that this value represents a + * JSON number that can be interpreted as Java int. If this is not the case, an + * exception is thrown. + *

+ * To be interpreted as Java int, the JSON number must neither contain an exponent + * nor a fraction part. Moreover, the number must be in the Integer range. + *

+ * + * @return this value as int + * @throws UnsupportedOperationException + * if this value is not a JSON number + * @throws NumberFormatException + * if this JSON number can not be interpreted as int value + */ + public int asInt() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a long value, assuming that this value represents a + * JSON number that can be interpreted as Java long. If this is not the case, an + * exception is thrown. + *

+ * To be interpreted as Java long, the JSON number must neither contain an exponent + * nor a fraction part. Moreover, the number must be in the Long range. + *

+ * + * @return this value as long + * @throws UnsupportedOperationException + * if this value is not a JSON number + * @throws NumberFormatException + * if this JSON number can not be interpreted as long value + */ + public long asLong() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a float value, assuming that this value represents a + * JSON number. If this is not the case, an exception is thrown. + *

+ * If the JSON number is out of the Float range, {@link Float#POSITIVE_INFINITY} or + * {@link Float#NEGATIVE_INFINITY} is returned. + *

+ * + * @return this value as float + * @throws UnsupportedOperationException + * if this value is not a JSON number + */ + public float asFloat() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a double value, assuming that this value represents a + * JSON number. If this is not the case, an exception is thrown. + *

+ * If the JSON number is out of the Double range, {@link Double#POSITIVE_INFINITY} or + * {@link Double#NEGATIVE_INFINITY} is returned. + *

+ * + * @return this value as double + * @throws UnsupportedOperationException + * if this value is not a JSON number + */ + public double asDouble() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as String, assuming that this value represents a JSON string. If this + * is not the case, an exception is thrown. + * + * @return the string represented by this value + * @throws UnsupportedOperationException + * if this value is not a JSON string + */ + public String asString() { + throw new UnsupportedOperationException("Not a string: " + toString()); + } + + /** + * Returns this JSON value as a boolean value, assuming that this value is either + * true or false. If this is not the case, an exception is thrown. + * + * @return this value as boolean + * @throws UnsupportedOperationException + * if this value is neither true or false + */ + public boolean asBoolean() { + throw new UnsupportedOperationException("Not a boolean: " + toString()); + } + + /** + * Writes the JSON representation of this value to the given writer in its minimal form, without + * any additional whitespace. + *

+ * Writing performance can be improved by using a {@link java.io.BufferedWriter BufferedWriter}. + *

+ * + * @param writer + * the writer to write this value to + * @throws IOException + * if an I/O error occurs in the writer + */ + public void writeTo(Writer writer) throws IOException { + writeTo(writer, WriterConfig.MINIMAL); + } + + /** + * Writes the JSON representation of this value to the given writer using the given formatting. + *

+ * Writing performance can be improved by using a {@link java.io.BufferedWriter BufferedWriter}. + *

+ * + * @param writer + * the writer to write this value to + * @param config + * a configuration that controls the formatting or null for the minimal form + * @throws IOException + * if an I/O error occurs in the writer + */ + public void writeTo(Writer writer, WriterConfig config) throws IOException { + if (writer == null) { + throw new NullPointerException("writer is null"); + } + if (config == null) { + throw new NullPointerException("config is null"); + } + WritingBuffer buffer = new WritingBuffer(writer, 128); + write(config.createWriter(buffer)); + buffer.flush(); + } + + /** + * Returns the JSON string for this value in its minimal form, without any additional whitespace. + * The result is guaranteed to be a valid input for the method {@link #readFrom(String)} and to + * create a value that is equal to this object. + * + * @return a JSON string that represents this value + */ + @Override + public String toString() { + return toString(WriterConfig.MINIMAL); + } + + /** + * Returns the JSON string for this value using the given formatting. + * + * @param config + * a configuration that controls the formatting or null for the minimal form + * @return a JSON string that represents this value + */ + public String toString(WriterConfig config) { + StringWriter writer = new StringWriter(); + try { + writeTo(writer, config); + } catch (IOException exception) { + // StringWriter does not throw IOExceptions + throw new RuntimeException(exception); + } + return writer.toString(); + } + + /** + * Indicates whether some other object is "equal to" this one according to the contract specified + * in {@link Object#equals(Object)}. + *

+ * Two JsonValues are considered equal if and only if they represent the same JSON text. As a + * consequence, two given JsonObjects may be different even though they contain the same set of + * names with the same values, but in a different order. + *

+ * + * @param object + * the reference object with which to compare + * @return true if this object is the same as the object argument; false otherwise + */ + @Override + public boolean equals(Object object) { + return super.equals(object); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + abstract void write(JsonWriter writer) throws IOException; + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonWriter.java b/blade-kit/src/main/java/blade/kit/json/JsonWriter.java new file mode 100644 index 000000000..52acf7659 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JsonWriter.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; + + +class JsonWriter { + + private static final int CONTROL_CHARACTERS_END = 0x001f; + + private static final char[] QUOT_CHARS = {'\\', '"'}; + private static final char[] BS_CHARS = {'\\', '\\'}; + private static final char[] LF_CHARS = {'\\', 'n'}; + private static final char[] CR_CHARS = {'\\', 'r'}; + private static final char[] TAB_CHARS = {'\\', 't'}; + // In JavaScript, U+2028 and U+2029 characters count as line endings and must be encoded. + // http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character + private static final char[] UNICODE_2028_CHARS = {'\\', 'u', '2', '0', '2', '8'}; + private static final char[] UNICODE_2029_CHARS = {'\\', 'u', '2', '0', '2', '9'}; + private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; + + protected final Writer writer; + + JsonWriter(Writer writer) { + this.writer = writer; + } + + protected void writeLiteral(String value) throws IOException { + writer.write(value); + } + + protected void writeNumber(String string) throws IOException { + writer.write(string); + } + + protected void writeString(String string) throws IOException { + writer.write('"'); + writeJsonString(string); + writer.write('"'); + } + + protected void writeArrayOpen() throws IOException { + writer.write('['); + } + + protected void writeArrayClose() throws IOException { + writer.write(']'); + } + + protected void writeArraySeparator() throws IOException { + writer.write(','); + } + + protected void writeObjectOpen() throws IOException { + writer.write('{'); + } + + protected void writeObjectClose() throws IOException { + writer.write('}'); + } + + protected void writeMemberName(String name) throws IOException { + writer.write('"'); + writeJsonString(name); + writer.write('"'); + } + + protected void writeMemberSeparator() throws IOException { + writer.write(':'); + } + + protected void writeObjectSeparator() throws IOException { + writer.write(','); + } + + protected void writeJsonString(String string) throws IOException { + int length = string.length(); + int start = 0; + for (int index = 0; index < length; index++) { + char[] replacement = getReplacementChars(string.charAt(index)); + if (replacement != null) { + writer.write(string, start, index - start); + writer.write(replacement); + start = index + 1; + } + } + writer.write(string, start, length - start); + } + + private static char[] getReplacementChars(char ch) { + if (ch > '\\') { + if (ch < '\u2028' || ch > '\u2029') { + // The lower range contains 'a' .. 'z'. Only 2 checks required. + return null; + } + return ch == '\u2028' ? UNICODE_2028_CHARS : UNICODE_2029_CHARS; + } + if (ch == '\\') { + return BS_CHARS; + } + if (ch > '"') { + // This range contains '0' .. '9' and 'A' .. 'Z'. Need 3 checks to get here. + return null; + } + if (ch == '"') { + return QUOT_CHARS; + } + if (ch > CONTROL_CHARACTERS_END) { + return null; + } + if (ch == '\n') { + return LF_CHARS; + } + if (ch == '\r') { + return CR_CHARS; + } + if (ch == '\t') { + return TAB_CHARS; + } + return new char[] {'\\', 'u', '0', '0', HEX_DIGITS[ch >> 4 & 0x000f], HEX_DIGITS[ch & 0x000f]}; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/ParseException.java b/blade-kit/src/main/java/blade/kit/json/ParseException.java new file mode 100644 index 000000000..bf60c6ba6 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/ParseException.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +/** + * An unchecked exception to indicate that an input does not qualify as valid JSON. + */ +@SuppressWarnings("serial") // use default serial UID +public class ParseException extends RuntimeException { + + private final int offset; + private final int line; + private final int column; + + ParseException(String message, int offset, int line, int column) { + super(message + " at " + line + ":" + column); + this.offset = offset; + this.line = line; + this.column = column; + } + + /** + * Returns the absolute index of the character at which the error occurred. The index of the first + * character of a document is 0. + * + * @return the character offset at which the error occurred, will be >= 0 + */ + public int getOffset() { + return offset; + } + + /** + * Returns the number of the line in which the error occurred. The first line counts as 1. + * + * @return the line in which the error occurred, will be >= 1 + */ + public int getLine() { + return line; + } + + /** + * Returns the index of the character at which the error occurred, relative to the line. The index + * of the first character of a line is 0. + * + * @return the column in which the error occurred, will be >= 0 + */ + public int getColumn() { + return column; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java b/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java new file mode 100644 index 000000000..c7de761b8 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; +import java.util.Arrays; + + +/** + * Enables human readable JSON output by inserting whitespace between values.after commas and + * colons. Example: + * + *
+ * jsonValue.writeTo(writer, PrettyPrint.singleLine());
+ * 
+ */ +public class PrettyPrint extends WriterConfig { + + private final char[] indentChars; + + protected PrettyPrint(char[] indentChars) { + this.indentChars = indentChars; + } + + /** + * Print every value on a separate line. Use tabs (\t) for indentation. + * + * @return A PrettyPrint instance for wrapped mode with tab indentation + */ + public static PrettyPrint singleLine() { + return new PrettyPrint(null); + } + + /** + * Print every value on a separate line. Use the given number of spaces for indentation. + * + * @param number + * the number of spaces to use + * @return A PrettyPrint instance for wrapped mode with spaces indentation + */ + public static PrettyPrint indentWithSpaces(int number) { + if (number < 0) { + throw new IllegalArgumentException("number is negative"); + } + char[] chars = new char[number]; + Arrays.fill(chars, ' '); + return new PrettyPrint(chars); + } + + /** + * Do not break lines, but still insert whitespace between values. + * + * @return A PrettyPrint instance for single-line mode + */ + public static PrettyPrint indentWithTabs() { + return new PrettyPrint(new char[] {'\t'}); + } + + @Override + protected JsonWriter createWriter(Writer writer) { + return new PrettyPrintWriter(writer, indentChars); + } + + private static class PrettyPrintWriter extends JsonWriter { + + private final char[] indentChars; + private int indent; + + private PrettyPrintWriter(Writer writer, char[] indentChars) { + super(writer); + this.indentChars = indentChars; + } + + @Override + protected void writeArrayOpen() throws IOException { + indent++; + writer.write('['); + writeNewLine(); + } + + @Override + protected void writeArrayClose() throws IOException { + indent--; + writeNewLine(); + writer.write(']'); + } + + @Override + protected void writeArraySeparator() throws IOException { + writer.write(','); + if (!writeNewLine()) { + writer.write(' '); + } + } + + @Override + protected void writeObjectOpen() throws IOException { + indent++; + writer.write('{'); + writeNewLine(); + } + + @Override + protected void writeObjectClose() throws IOException { + indent--; + writeNewLine(); + writer.write('}'); + } + + @Override + protected void writeMemberSeparator() throws IOException { + writer.write(':'); + writer.write(' '); + } + + @Override + protected void writeObjectSeparator() throws IOException { + writer.write(','); + if (!writeNewLine()) { + writer.write(' '); + } + } + + private boolean writeNewLine() throws IOException { + if (indentChars == null) { + return false; + } + writer.write('\n'); + for (int i = 0; i < indent; i++) { + writer.write(indentChars); + } + return true; + } + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/WriterConfig.java b/blade-kit/src/main/java/blade/kit/json/WriterConfig.java new file mode 100644 index 000000000..3cc828241 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/WriterConfig.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.Writer; + + +/** + * Controls the formatting of the JSON output. Use one of the available constants. + */ +public abstract class WriterConfig { + + /** + * Write JSON in its minimal form, without any additional whitespace. This is the default. + */ + public static WriterConfig MINIMAL = new WriterConfig() { + @Override + JsonWriter createWriter(Writer writer) { + return new JsonWriter(writer); + } + }; + + /** + * Write JSON in pretty-print, with each value on a separate line and an indentation of two + * spaces. + */ + public static WriterConfig PRETTY_PRINT = PrettyPrint.indentWithSpaces(2); + + abstract JsonWriter createWriter(Writer writer); + +} diff --git a/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java b/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java new file mode 100644 index 000000000..58a779b0c --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; + + +/** + * A lightweight writing buffer to reduce the amount of write operations to be performed on the + * underlying writer. This implementation is not thread-safe. It deliberately deviates from the + * contract of Writer. In particular, it does not flush or close the wrapped writer nor does it + * ensure that the wrapped writer is open. + */ +class WritingBuffer extends Writer { + + private final Writer writer; + private final char[] buffer; + private int fill = 0; + + WritingBuffer(Writer writer) { + this(writer, 16); + } + + WritingBuffer(Writer writer, int bufferSize) { + this.writer = writer; + buffer = new char[bufferSize]; + } + + @Override + public void write(int c) throws IOException { + if (fill > buffer.length - 1) { + flush(); + } + buffer[fill++] = (char)c; + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + if (fill > buffer.length - len) { + flush(); + if (len > buffer.length) { + writer.write(cbuf, off, len); + return; + } + } + System.arraycopy(cbuf, off, buffer, fill, len); + fill += len; + } + + @Override + public void write(String str, int off, int len) throws IOException { + if (fill > buffer.length - len) { + flush(); + if (len > buffer.length) { + writer.write(str, off, len); + return; + } + } + str.getChars(off, off + len, buffer, fill); + fill += len; + } + + /** + * Flushes the internal buffer but does not flush the wrapped writer. + */ + @Override + public void flush() throws IOException { + writer.write(buffer, 0, fill); + fill = 0; + } + + /** + * Does not close or flush the wrapped writer. + */ + @Override + public void close() throws IOException { + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/ContainerFactory.java b/blade-kit/src/main/java/blade/kit/json/parse/ContainerFactory.java deleted file mode 100644 index c25f98a96..000000000 --- a/blade-kit/src/main/java/blade/kit/json/parse/ContainerFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -package blade.kit.json.parse; - -import java.util.List; -import java.util.Map; - -/** - * Container factory for creating containers for JSON object and JSON array. - * - * @see org.json.simple.parser.JSONParser#parse(java.io.Reader, ContainerFactory) - * - * @author FangYidong - */ -@SuppressWarnings({"rawtypes"}) -public interface ContainerFactory { - /** - * @return A Map instance to store JSON object, or null if you want to use org.json.simple.JSONObject. - */ - Map createObjectContainer(); - - /** - * @return A List instance to store JSON array, or null if you want to use org.json.simple.JSONArray. - */ - List creatArrayContainer(); -} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/ContentHandler.java b/blade-kit/src/main/java/blade/kit/json/parse/ContentHandler.java deleted file mode 100644 index 6ad41302a..000000000 --- a/blade-kit/src/main/java/blade/kit/json/parse/ContentHandler.java +++ /dev/null @@ -1,110 +0,0 @@ -package blade.kit.json.parse; - -import java.io.IOException; - -/** - * A simplified and stoppable SAX-like content handler for stream processing of JSON text. - * - * @see org.xml.sax.ContentHandler - * @see org.json.simple.parser.JSONParser#parse(java.io.Reader, ContentHandler, boolean) - * - * @author FangYidong - */ -public interface ContentHandler { - /** - * Receive notification of the beginning of JSON processing. - * The parser will invoke this method only once. - * - * @throws ParseException - * - JSONParser will stop and throw the same exception to the caller when receiving this exception. - */ - void startJSON() throws ParseException, IOException; - - /** - * Receive notification of the end of JSON processing. - * - * @throws ParseException - */ - void endJSON() throws ParseException, IOException; - - /** - * Receive notification of the beginning of a JSON object. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - JSONParser will stop and throw the same exception to the caller when receiving this exception. - * @see #endJSON - */ - boolean startObject() throws ParseException, IOException; - - /** - * Receive notification of the end of a JSON object. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - * @see #startObject - */ - boolean endObject() throws ParseException, IOException; - - /** - * Receive notification of the beginning of a JSON object entry. - * - * @param key - Key of a JSON object entry. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - * @see #endObjectEntry - */ - boolean startObjectEntry(String key) throws ParseException, IOException; - - /** - * Receive notification of the end of the value of previous object entry. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - * @see #startObjectEntry - */ - boolean endObjectEntry() throws ParseException, IOException; - - /** - * Receive notification of the beginning of a JSON array. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - * @see #endArray - */ - boolean startArray() throws ParseException, IOException; - - /** - * Receive notification of the end of a JSON array. - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - * - * @see #startArray - */ - boolean endArray() throws ParseException, IOException; - - /** - * Receive notification of the JSON primitive values: - * java.lang.String, - * java.lang.Number, - * java.lang.Boolean - * null - * - * @param value - Instance of the following: - * java.lang.String, - * java.lang.Number, - * java.lang.Boolean - * null - * - * @return false if the handler wants to stop parsing after return. - * @throws ParseException - */ - boolean primitive(Object value) throws ParseException, IOException; - -} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/JSONParser.java b/blade-kit/src/main/java/blade/kit/json/parse/JSONParser.java deleted file mode 100644 index b16445e6b..000000000 --- a/blade-kit/src/main/java/blade/kit/json/parse/JSONParser.java +++ /dev/null @@ -1,534 +0,0 @@ -/* - * $Id: JSONParser.java,v 1.1 2006/04/15 14:10:48 platform Exp $ - * Created on 2006-4-15 - */ -package blade.kit.json.parse; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import blade.kit.json.JSONArray; -import blade.kit.json.JSONObject; - - -/** - * Parser for JSON text. Please note that JSONParser is NOT thread-safe. - * - * @author FangYidong - */ -@SuppressWarnings({"rawtypes","unchecked"}) -public class JSONParser { - public static final int S_INIT=0; - public static final int S_IN_FINISHED_VALUE=1;//string,number,boolean,null,object,array - public static final int S_IN_OBJECT=2; - public static final int S_IN_ARRAY=3; - public static final int S_PASSED_PAIR_KEY=4; - public static final int S_IN_PAIR_VALUE=5; - public static final int S_END=6; - public static final int S_IN_ERROR=-1; - - private LinkedList handlerStatusStack; - private Yylex lexer = new Yylex((Reader)null); - private Yytoken token = null; - private int status = S_INIT; - - private int peekStatus(LinkedList statusStack){ - if(statusStack.size()==0) - return -1; - Integer status=(Integer)statusStack.getFirst(); - return status.intValue(); - } - - /** - * Reset the parser to the initial state without resetting the underlying reader. - * - */ - public void reset(){ - token = null; - status = S_INIT; - handlerStatusStack = null; - } - - /** - * Reset the parser to the initial state with a new character reader. - * - * @param in - The new character reader. - * @throws IOException - * @throws ParseException - */ - public void reset(Reader in){ - lexer.yyreset(in); - reset(); - } - - /** - * @return The position of the beginning of the current token. - */ - public int getPosition(){ - return lexer.getPosition(); - } - - public Object parse(String s) throws ParseException{ - return parse(s, (ContainerFactory)null); - } - - public Object parse(String s, ContainerFactory containerFactory) throws ParseException{ - StringReader in=new StringReader(s); - try{ - return parse(in, containerFactory); - } - catch(IOException ie){ - /* - * Actually it will never happen. - */ - throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie); - } - } - - public Object parse(Reader in) throws IOException, ParseException{ - return parse(in, (ContainerFactory)null); - } - - /** - * Parse JSON text into java object from the input source. - * - * @param in - * @param containerFactory - Use this factory to createyour own JSON object and JSON array containers. - * @return Instance of the following: - * org.json.simple.JSONObject, - * org.json.simple.JSONArray, - * java.lang.String, - * java.lang.Number, - * java.lang.Boolean, - * null - * - * @throws IOException - * @throws ParseException - */ - public Object parse(Reader in, ContainerFactory containerFactory) throws IOException, ParseException{ - reset(in); - LinkedList statusStack = new LinkedList(); - LinkedList valueStack = new LinkedList(); - - try{ - do{ - nextToken(); - switch(status){ - case S_INIT: - switch(token.type){ - case Yytoken.TYPE_VALUE: - status=S_IN_FINISHED_VALUE; - statusStack.addFirst(new Integer(status)); - valueStack.addFirst(token.value); - break; - case Yytoken.TYPE_LEFT_BRACE: - status=S_IN_OBJECT; - statusStack.addFirst(new Integer(status)); - valueStack.addFirst(createObjectContainer(containerFactory)); - break; - case Yytoken.TYPE_LEFT_SQUARE: - status=S_IN_ARRAY; - statusStack.addFirst(new Integer(status)); - valueStack.addFirst(createArrayContainer(containerFactory)); - break; - default: - status=S_IN_ERROR; - }//inner switch - break; - - case S_IN_FINISHED_VALUE: - if(token.type==Yytoken.TYPE_EOF) - return valueStack.removeFirst(); - else - throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); - - case S_IN_OBJECT: - switch(token.type){ - case Yytoken.TYPE_COMMA: - break; - case Yytoken.TYPE_VALUE: - if(token.value instanceof String){ - String key=(String)token.value; - valueStack.addFirst(key); - status=S_PASSED_PAIR_KEY; - statusStack.addFirst(new Integer(status)); - } - else{ - status=S_IN_ERROR; - } - break; - case Yytoken.TYPE_RIGHT_BRACE: - if(valueStack.size()>1){ - statusStack.removeFirst(); - valueStack.removeFirst(); - status=peekStatus(statusStack); - } - else{ - status=S_IN_FINISHED_VALUE; - } - break; - default: - status=S_IN_ERROR; - break; - }//inner switch - break; - - case S_PASSED_PAIR_KEY: - switch(token.type){ - case Yytoken.TYPE_COLON: - break; - case Yytoken.TYPE_VALUE: - statusStack.removeFirst(); - String key=(String)valueStack.removeFirst(); - Map parent=(Map)valueStack.getFirst(); - parent.put(key,token.value); - status=peekStatus(statusStack); - break; - case Yytoken.TYPE_LEFT_SQUARE: - statusStack.removeFirst(); - key=(String)valueStack.removeFirst(); - parent=(Map)valueStack.getFirst(); - List newArray=createArrayContainer(containerFactory); - parent.put(key,newArray); - status=S_IN_ARRAY; - statusStack.addFirst(new Integer(status)); - valueStack.addFirst(newArray); - break; - case Yytoken.TYPE_LEFT_BRACE: - statusStack.removeFirst(); - key=(String)valueStack.removeFirst(); - parent=(Map)valueStack.getFirst(); - Map newObject=createObjectContainer(containerFactory); - parent.put(key,newObject); - status=S_IN_OBJECT; - statusStack.addFirst(new Integer(status)); - valueStack.addFirst(newObject); - break; - default: - status=S_IN_ERROR; - } - break; - - case S_IN_ARRAY: - switch(token.type){ - case Yytoken.TYPE_COMMA: - break; - case Yytoken.TYPE_VALUE: - List val=(List)valueStack.getFirst(); - val.add(token.value); - break; - case Yytoken.TYPE_RIGHT_SQUARE: - if(valueStack.size()>1){ - statusStack.removeFirst(); - valueStack.removeFirst(); - status=peekStatus(statusStack); - } - else{ - status=S_IN_FINISHED_VALUE; - } - break; - case Yytoken.TYPE_LEFT_BRACE: - val=(List)valueStack.getFirst(); - Map newObject=createObjectContainer(containerFactory); - val.add(newObject); - status=S_IN_OBJECT; - statusStack.addFirst(new Integer(status)); - valueStack.addFirst(newObject); - break; - case Yytoken.TYPE_LEFT_SQUARE: - val=(List)valueStack.getFirst(); - List newArray=createArrayContainer(containerFactory); - val.add(newArray); - status=S_IN_ARRAY; - statusStack.addFirst(new Integer(status)); - valueStack.addFirst(newArray); - break; - default: - status=S_IN_ERROR; - }//inner switch - break; - case S_IN_ERROR: - throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); - }//switch - if(status==S_IN_ERROR){ - throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); - } - }while(token.type!=Yytoken.TYPE_EOF); - } - catch(IOException ie){ - throw ie; - } - - throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); - } - - private void nextToken() throws ParseException, IOException{ - token = lexer.yylex(); - if(token == null) - token = new Yytoken(Yytoken.TYPE_EOF, null); - } - - private Map createObjectContainer(ContainerFactory containerFactory){ - if(containerFactory == null) - return new JSONObject(); - Map m = containerFactory.createObjectContainer(); - - if(m == null) - return new JSONObject(); - return m; - } - - private List createArrayContainer(ContainerFactory containerFactory){ - if(containerFactory == null) - return new JSONArray(); - List l = containerFactory.creatArrayContainer(); - - if(l == null) - return new JSONArray(); - return l; - } - - public void parse(String s, ContentHandler contentHandler) throws ParseException{ - parse(s, contentHandler, false); - } - - public void parse(String s, ContentHandler contentHandler, boolean isResume) throws ParseException{ - StringReader in=new StringReader(s); - try{ - parse(in, contentHandler, isResume); - } - catch(IOException ie){ - /* - * Actually it will never happen. - */ - throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie); - } - } - - public void parse(Reader in, ContentHandler contentHandler) throws IOException, ParseException{ - parse(in, contentHandler, false); - } - - /** - * Stream processing of JSON text. - * - * @see ContentHandler - * - * @param in - * @param contentHandler - * @param isResume - Indicates if it continues previous parsing operation. - * If set to true, resume parsing the old stream, and parameter 'in' will be ignored. - * If this method is called for the first time in this instance, isResume will be ignored. - * - * @throws IOException - * @throws ParseException - */ - public void parse(Reader in, ContentHandler contentHandler, boolean isResume) throws IOException, ParseException{ - if(!isResume){ - reset(in); - handlerStatusStack = new LinkedList(); - } - else{ - if(handlerStatusStack == null){ - isResume = false; - reset(in); - handlerStatusStack = new LinkedList(); - } - } - - LinkedList statusStack = handlerStatusStack; - - try{ - do{ - switch(status){ - case S_INIT: - contentHandler.startJSON(); - nextToken(); - switch(token.type){ - case Yytoken.TYPE_VALUE: - status=S_IN_FINISHED_VALUE; - statusStack.addFirst(new Integer(status)); - if(!contentHandler.primitive(token.value)) - return; - break; - case Yytoken.TYPE_LEFT_BRACE: - status=S_IN_OBJECT; - statusStack.addFirst(new Integer(status)); - if(!contentHandler.startObject()) - return; - break; - case Yytoken.TYPE_LEFT_SQUARE: - status=S_IN_ARRAY; - statusStack.addFirst(new Integer(status)); - if(!contentHandler.startArray()) - return; - break; - default: - status=S_IN_ERROR; - }//inner switch - break; - - case S_IN_FINISHED_VALUE: - nextToken(); - if(token.type==Yytoken.TYPE_EOF){ - contentHandler.endJSON(); - status = S_END; - return; - } - else{ - status = S_IN_ERROR; - throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); - } - - case S_IN_OBJECT: - nextToken(); - switch(token.type){ - case Yytoken.TYPE_COMMA: - break; - case Yytoken.TYPE_VALUE: - if(token.value instanceof String){ - String key=(String)token.value; - status=S_PASSED_PAIR_KEY; - statusStack.addFirst(new Integer(status)); - if(!contentHandler.startObjectEntry(key)) - return; - } - else{ - status=S_IN_ERROR; - } - break; - case Yytoken.TYPE_RIGHT_BRACE: - if(statusStack.size()>1){ - statusStack.removeFirst(); - status=peekStatus(statusStack); - } - else{ - status=S_IN_FINISHED_VALUE; - } - if(!contentHandler.endObject()) - return; - break; - default: - status=S_IN_ERROR; - break; - }//inner switch - break; - - case S_PASSED_PAIR_KEY: - nextToken(); - switch(token.type){ - case Yytoken.TYPE_COLON: - break; - case Yytoken.TYPE_VALUE: - statusStack.removeFirst(); - status=peekStatus(statusStack); - if(!contentHandler.primitive(token.value)) - return; - if(!contentHandler.endObjectEntry()) - return; - break; - case Yytoken.TYPE_LEFT_SQUARE: - statusStack.removeFirst(); - statusStack.addFirst(new Integer(S_IN_PAIR_VALUE)); - status=S_IN_ARRAY; - statusStack.addFirst(new Integer(status)); - if(!contentHandler.startArray()) - return; - break; - case Yytoken.TYPE_LEFT_BRACE: - statusStack.removeFirst(); - statusStack.addFirst(new Integer(S_IN_PAIR_VALUE)); - status=S_IN_OBJECT; - statusStack.addFirst(new Integer(status)); - if(!contentHandler.startObject()) - return; - break; - default: - status=S_IN_ERROR; - } - break; - - case S_IN_PAIR_VALUE: - /* - * S_IN_PAIR_VALUE is just a marker to indicate the end of an object entry, it doesn't proccess any token, - * therefore delay consuming token until next round. - */ - statusStack.removeFirst(); - status = peekStatus(statusStack); - if(!contentHandler.endObjectEntry()) - return; - break; - - case S_IN_ARRAY: - nextToken(); - switch(token.type){ - case Yytoken.TYPE_COMMA: - break; - case Yytoken.TYPE_VALUE: - if(!contentHandler.primitive(token.value)) - return; - break; - case Yytoken.TYPE_RIGHT_SQUARE: - if(statusStack.size()>1){ - statusStack.removeFirst(); - status=peekStatus(statusStack); - } - else{ - status=S_IN_FINISHED_VALUE; - } - if(!contentHandler.endArray()) - return; - break; - case Yytoken.TYPE_LEFT_BRACE: - status=S_IN_OBJECT; - statusStack.addFirst(new Integer(status)); - if(!contentHandler.startObject()) - return; - break; - case Yytoken.TYPE_LEFT_SQUARE: - status=S_IN_ARRAY; - statusStack.addFirst(new Integer(status)); - if(!contentHandler.startArray()) - return; - break; - default: - status=S_IN_ERROR; - }//inner switch - break; - - case S_END: - return; - - case S_IN_ERROR: - throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); - }//switch - if(status==S_IN_ERROR){ - throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); - } - }while(token.type!=Yytoken.TYPE_EOF); - } - catch(IOException ie){ - status = S_IN_ERROR; - throw ie; - } - catch(ParseException pe){ - status = S_IN_ERROR; - throw pe; - } - catch(RuntimeException re){ - status = S_IN_ERROR; - throw re; - } - catch(Error e){ - status = S_IN_ERROR; - throw e; - } - - status = S_IN_ERROR; - throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); - } -} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/ParseException.java b/blade-kit/src/main/java/blade/kit/json/parse/ParseException.java deleted file mode 100644 index 24b383c26..000000000 --- a/blade-kit/src/main/java/blade/kit/json/parse/ParseException.java +++ /dev/null @@ -1,90 +0,0 @@ -package blade.kit.json.parse; - -/** - * ParseException explains why and where the error occurs in source JSON text. - * - * @author FangYidong - * - */ -public class ParseException extends Exception { - private static final long serialVersionUID = -7880698968187728547L; - - public static final int ERROR_UNEXPECTED_CHAR = 0; - public static final int ERROR_UNEXPECTED_TOKEN = 1; - public static final int ERROR_UNEXPECTED_EXCEPTION = 2; - - private int errorType; - private Object unexpectedObject; - private int position; - - public ParseException(int errorType){ - this(-1, errorType, null); - } - - public ParseException(int errorType, Object unexpectedObject){ - this(-1, errorType, unexpectedObject); - } - - public ParseException(int position, int errorType, Object unexpectedObject){ - this.position = position; - this.errorType = errorType; - this.unexpectedObject = unexpectedObject; - } - - public int getErrorType() { - return errorType; - } - - public void setErrorType(int errorType) { - this.errorType = errorType; - } - - /** - * @see org.json.simple.parser.JSONParser#getPosition() - * - * @return The character position (starting with 0) of the input where the error occurs. - */ - public int getPosition() { - return position; - } - - public void setPosition(int position) { - this.position = position; - } - - /** - * @see org.json.simple.parser.Yytoken - * - * @return One of the following base on the value of errorType: - * ERROR_UNEXPECTED_CHAR java.lang.Character - * ERROR_UNEXPECTED_TOKEN org.json.simple.parser.Yytoken - * ERROR_UNEXPECTED_EXCEPTION java.lang.Exception - */ - public Object getUnexpectedObject() { - return unexpectedObject; - } - - public void setUnexpectedObject(Object unexpectedObject) { - this.unexpectedObject = unexpectedObject; - } - - public String getMessage() { - StringBuffer sb = new StringBuffer(); - - switch(errorType){ - case ERROR_UNEXPECTED_CHAR: - sb.append("Unexpected character (").append(unexpectedObject).append(") at position ").append(position).append("."); - break; - case ERROR_UNEXPECTED_TOKEN: - sb.append("Unexpected token ").append(unexpectedObject).append(" at position ").append(position).append("."); - break; - case ERROR_UNEXPECTED_EXCEPTION: - sb.append("Unexpected exception at position ").append(position).append(": ").append(unexpectedObject); - break; - default: - sb.append("Unkown error at position ").append(position).append("."); - break; - } - return sb.toString(); - } -} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/Yylex.java b/blade-kit/src/main/java/blade/kit/json/parse/Yylex.java deleted file mode 100644 index d8c4f3bf9..000000000 --- a/blade-kit/src/main/java/blade/kit/json/parse/Yylex.java +++ /dev/null @@ -1,689 +0,0 @@ -/* The following code was generated by JFlex 1.4.2 */ - -package blade.kit.json.parse; - -@SuppressWarnings("unused") -class Yylex { - - /** This character denotes the end of file */ - public static final int YYEOF = -1; - - /** initial size of the lookahead buffer */ - private static final int ZZ_BUFFERSIZE = 16384; - - /** lexical states */ - public static final int YYINITIAL = 0; - public static final int STRING_BEGIN = 2; - - /** - * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l - * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l - * at the beginning of a line - * l is of the form l = 2*k, k a non negative integer - */ - private static final int ZZ_LEXSTATE[] = { - 0, 0, 1, 1 - }; - - /** - * Translates characters to character classes - */ - private static final String ZZ_CMAP_PACKED = - "\11\0\1\7\1\7\2\0\1\7\22\0\1\7\1\0\1\11\10\0"+ - "\1\6\1\31\1\2\1\4\1\12\12\3\1\32\6\0\4\1\1\5"+ - "\1\1\24\0\1\27\1\10\1\30\3\0\1\22\1\13\2\1\1\21"+ - "\1\14\5\0\1\23\1\0\1\15\3\0\1\16\1\24\1\17\1\20"+ - "\5\0\1\25\1\0\1\26\uff82\0"; - - /** - * Translates characters to character classes - */ - private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - - /** - * Translates DFA states to action switch labels. - */ - private static final int [] ZZ_ACTION = zzUnpackAction(); - - private static final String ZZ_ACTION_PACKED_0 = - "\2\0\2\1\1\2\1\3\1\4\3\1\1\5\1\6"+ - "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\5\0"+ - "\1\14\1\16\1\17\1\20\1\21\1\22\1\23\1\24"+ - "\1\0\1\25\1\0\1\25\4\0\1\26\1\27\2\0"+ - "\1\30"; - - private static int [] zzUnpackAction() { - int [] result = new int[45]; - int offset = 0; - offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAction(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do result[j++] = value; while (--count > 0); - } - return j; - } - - - /** - * Translates a state to a row index in the transition table - */ - private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); - - private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\33\0\66\0\121\0\154\0\207\0\66\0\242"+ - "\0\275\0\330\0\66\0\66\0\66\0\66\0\66\0\66"+ - "\0\363\0\u010e\0\66\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195"+ - "\0\66\0\66\0\66\0\66\0\66\0\66\0\66\0\66"+ - "\0\u01b0\0\u01cb\0\u01e6\0\u01e6\0\u0201\0\u021c\0\u0237\0\u0252"+ - "\0\66\0\66\0\u026d\0\u0288\0\66"; - - private static int [] zzUnpackRowMap() { - int [] result = new int[45]; - int offset = 0; - offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackRowMap(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int high = packed.charAt(i++) << 16; - result[j++] = high | packed.charAt(i++); - } - return j; - } - - /** - * The transition table of the DFA - */ - private static final int ZZ_TRANS [] = { - 2, 2, 3, 4, 2, 2, 2, 5, 2, 6, - 2, 2, 7, 8, 2, 9, 2, 2, 2, 2, - 2, 10, 11, 12, 13, 14, 15, 16, 16, 16, - 16, 16, 16, 16, 16, 17, 18, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 4, 19, 20, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 16, 16, 16, 16, 16, 16, 16, - 16, -1, -1, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - -1, -1, -1, -1, -1, -1, -1, -1, 24, 25, - 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 34, 35, -1, -1, - 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 39, -1, 39, -1, 39, -1, -1, - -1, -1, -1, 39, 39, -1, -1, -1, -1, 39, - 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 33, -1, 20, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 42, -1, 42, -1, 42, - -1, -1, -1, -1, -1, 42, 42, -1, -1, -1, - -1, 42, 42, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 43, -1, 43, -1, 43, -1, -1, -1, - -1, -1, 43, 43, -1, -1, -1, -1, 43, 43, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, - -1, 44, -1, 44, -1, -1, -1, -1, -1, 44, - 44, -1, -1, -1, -1, 44, 44, -1, -1, -1, - -1, -1, -1, -1, -1, - }; - - /* error codes */ - private static final int ZZ_UNKNOWN_ERROR = 0; - private static final int ZZ_NO_MATCH = 1; - private static final int ZZ_PUSHBACK_2BIG = 2; - - /* error messages for the codes above */ - private static final String ZZ_ERROR_MSG[] = { - "Unkown internal scanner error", - "Error: could not match input", - "Error: pushback value was too large" - }; - - /** - * ZZ_ATTRIBUTE[aState] contains the attributes of state aState - */ - private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); - - private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\2\0\1\11\3\1\1\11\3\1\6\11\2\1\1\11"+ - "\5\0\10\11\1\0\1\1\1\0\1\1\4\0\2\11"+ - "\2\0\1\11"; - - private static int [] zzUnpackAttribute() { - int [] result = new int[45]; - int offset = 0; - offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAttribute(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do result[j++] = value; while (--count > 0); - } - return j; - } - - /** the input device */ - private java.io.Reader zzReader; - - /** the current state of the DFA */ - private int zzState; - - /** the current lexical state */ - private int zzLexicalState = YYINITIAL; - - /** this buffer contains the current text to be matched and is - the source of the yytext() string */ - private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; - - /** the textposition at the last accepting state */ - private int zzMarkedPos; - - /** the current text position in the buffer */ - private int zzCurrentPos; - - /** startRead marks the beginning of the yytext() string in the buffer */ - private int zzStartRead; - - /** endRead marks the last character in the buffer, that has been read - from input */ - private int zzEndRead; - - /** number of newlines encountered up to the start of the matched text */ - private int yyline; - - /** the number of characters up to the start of the matched text */ - private int yychar; - - /** - * the number of characters from the last newline up to the start of the - * matched text - */ - private int yycolumn; - - /** - * zzAtBOL == true <=> the scanner is currently at the beginning of a line - */ - private boolean zzAtBOL = true; - - /** zzAtEOF == true <=> the scanner is at the EOF */ - private boolean zzAtEOF; - - /* user code: */ -private StringBuffer sb=new StringBuffer(); - -int getPosition(){ - return yychar; -} - - - - /** - * Creates a new scanner - * There is also a java.io.InputStream version of this constructor. - * - * @param in the java.io.Reader to read input from. - */ - Yylex(java.io.Reader in) { - this.zzReader = in; - } - - /** - * Creates a new scanner. - * There is also java.io.Reader version of this constructor. - * - * @param in the java.io.Inputstream to read input from. - */ - Yylex(java.io.InputStream in) { - this(new java.io.InputStreamReader(in)); - } - - /** - * Unpacks the compressed character translation table. - * - * @param packed the packed character translation table - * @return the unpacked character translation table - */ - private static char [] zzUnpackCMap(String packed) { - char [] map = new char[0x10000]; - int i = 0; /* index in packed string */ - int j = 0; /* index in unpacked array */ - while (i < 90) { - int count = packed.charAt(i++); - char value = packed.charAt(i++); - do map[j++] = value; while (--count > 0); - } - return map; - } - - - /** - * Refills the input buffer. - * - * @return false, iff there was new input. - * - * @exception java.io.IOException if any I/O-Error occurs - */ - private boolean zzRefill() throws java.io.IOException { - - /* first: make room (if you can) */ - if (zzStartRead > 0) { - System.arraycopy(zzBuffer, zzStartRead, - zzBuffer, 0, - zzEndRead-zzStartRead); - - /* translate stored positions */ - zzEndRead-= zzStartRead; - zzCurrentPos-= zzStartRead; - zzMarkedPos-= zzStartRead; - zzStartRead = 0; - } - - /* is the buffer big enough? */ - if (zzCurrentPos >= zzBuffer.length) { - /* if not: blow it up */ - char newBuffer[] = new char[zzCurrentPos*2]; - System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); - zzBuffer = newBuffer; - } - - /* finally: fill the buffer with new input */ - int numRead = zzReader.read(zzBuffer, zzEndRead, - zzBuffer.length-zzEndRead); - - if (numRead > 0) { - zzEndRead+= numRead; - return false; - } - // unlikely but not impossible: read 0 characters, but not at end of stream - if (numRead == 0) { - int c = zzReader.read(); - if (c == -1) { - return true; - } else { - zzBuffer[zzEndRead++] = (char) c; - return false; - } - } - - // numRead < 0 - return true; - } - - - /** - * Closes the input stream. - */ - public final void yyclose() throws java.io.IOException { - zzAtEOF = true; /* indicate end of file */ - zzEndRead = zzStartRead; /* invalidate buffer */ - - if (zzReader != null) - zzReader.close(); - } - - - /** - * Resets the scanner to read from a new input stream. - * Does not close the old reader. - * - * All internal variables are reset, the old input stream - * cannot be reused (internal buffer is discarded and lost). - * Lexical state is set to ZZ_INITIAL. - * - * @param reader the new input stream - */ - public final void yyreset(java.io.Reader reader) { - zzReader = reader; - zzAtBOL = true; - zzAtEOF = false; - zzEndRead = zzStartRead = 0; - zzCurrentPos = zzMarkedPos = 0; - yyline = yychar = yycolumn = 0; - zzLexicalState = YYINITIAL; - } - - - /** - * Returns the current lexical state. - */ - public final int yystate() { - return zzLexicalState; - } - - - /** - * Enters a new lexical state - * - * @param newState the new lexical state - */ - public final void yybegin(int newState) { - zzLexicalState = newState; - } - - - /** - * Returns the text matched by the current regular expression. - */ - public final String yytext() { - return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); - } - - - /** - * Returns the character at position pos from the - * matched text. - * - * It is equivalent to yytext().charAt(pos), but faster - * - * @param pos the position of the character to fetch. - * A value from 0 to yylength()-1. - * - * @return the character at position pos - */ - public final char yycharat(int pos) { - return zzBuffer[zzStartRead+pos]; - } - - - /** - * Returns the length of the matched text region. - */ - public final int yylength() { - return zzMarkedPos-zzStartRead; - } - - - /** - * Reports an error that occured while scanning. - * - * In a wellformed scanner (no or only correct usage of - * yypushback(int) and a match-all fallback rule) this method - * will only be called with things that "Can't Possibly Happen". - * If this method is called, something is seriously wrong - * (e.g. a JFlex bug producing a faulty scanner etc.). - * - * Usual syntax/scanner level error handling should be done - * in error fallback rules. - * - * @param errorCode the code of the errormessage to display - */ - private void zzScanError(int errorCode) { - String message; - try { - message = ZZ_ERROR_MSG[errorCode]; - } - catch (ArrayIndexOutOfBoundsException e) { - message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; - } - - throw new Error(message); - } - - - /** - * Pushes the specified amount of characters back into the input stream. - * - * They will be read again by then next call of the scanning method - * - * @param number the number of characters to be read again. - * This number must not be greater than yylength()! - */ - public void yypushback(int number) { - if ( number > yylength() ) - zzScanError(ZZ_PUSHBACK_2BIG); - - zzMarkedPos -= number; - } - - - /** - * Resumes scanning until the next regular expression is matched, - * the end of input is encountered or an I/O-Error occurs. - * - * @return the next token - * @exception java.io.IOException if any I/O-Error occurs - */ - public Yytoken yylex() throws java.io.IOException, ParseException { - int zzInput; - int zzAction; - - // cached fields: - int zzCurrentPosL; - int zzMarkedPosL; - int zzEndReadL = zzEndRead; - char [] zzBufferL = zzBuffer; - char [] zzCMapL = ZZ_CMAP; - - int [] zzTransL = ZZ_TRANS; - int [] zzRowMapL = ZZ_ROWMAP; - int [] zzAttrL = ZZ_ATTRIBUTE; - - while (true) { - zzMarkedPosL = zzMarkedPos; - - yychar+= zzMarkedPosL-zzStartRead; - - zzAction = -1; - - zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; - - zzState = ZZ_LEXSTATE[zzLexicalState]; - - - zzForAction: { - while (true) { - - if (zzCurrentPosL < zzEndReadL) - zzInput = zzBufferL[zzCurrentPosL++]; - else if (zzAtEOF) { - zzInput = YYEOF; - break zzForAction; - } - else { - // store back cached positions - zzCurrentPos = zzCurrentPosL; - zzMarkedPos = zzMarkedPosL; - boolean eof = zzRefill(); - // get translated positions and possibly new buffer - zzCurrentPosL = zzCurrentPos; - zzMarkedPosL = zzMarkedPos; - zzBufferL = zzBuffer; - zzEndReadL = zzEndRead; - if (eof) { - zzInput = YYEOF; - break zzForAction; - } - else { - zzInput = zzBufferL[zzCurrentPosL++]; - } - } - int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; - if (zzNext == -1) break zzForAction; - zzState = zzNext; - - int zzAttributes = zzAttrL[zzState]; - if ( (zzAttributes & 1) == 1 ) { - zzAction = zzState; - zzMarkedPosL = zzCurrentPosL; - if ( (zzAttributes & 8) == 8 ) break zzForAction; - } - - } - } - - // store back cached position - zzMarkedPos = zzMarkedPosL; - - switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 11: - { sb.append(yytext()); - } - case 25: break; - case 4: - { sb = null; sb = new StringBuffer(); yybegin(STRING_BEGIN); - } - case 26: break; - case 16: - { sb.append('\b'); - } - case 27: break; - case 6: - { return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null); - } - case 28: break; - case 23: - { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); - } - case 29: break; - case 22: - { return new Yytoken(Yytoken.TYPE_VALUE, null); - } - case 30: break; - case 13: - { yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE, sb.toString()); - } - case 31: break; - case 12: - { sb.append('\\'); - } - case 32: break; - case 21: - { Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); - } - case 33: break; - case 1: - { throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_CHAR, new Character(yycharat(0))); - } - case 34: break; - case 8: - { return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null); - } - case 35: break; - case 19: - { sb.append('\r'); - } - case 36: break; - case 15: - { sb.append('/'); - } - case 37: break; - case 10: - { return new Yytoken(Yytoken.TYPE_COLON,null); - } - case 38: break; - case 14: - { sb.append('"'); - } - case 39: break; - case 5: - { return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null); - } - case 40: break; - case 17: - { sb.append('\f'); - } - case 41: break; - case 24: - { try{ - int ch=Integer.parseInt(yytext().substring(2),16); - sb.append((char)ch); - } - catch(Exception e){ - throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_EXCEPTION, e); - } - } - case 42: break; - case 20: - { sb.append('\t'); - } - case 43: break; - case 7: - { return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null); - } - case 44: break; - case 2: - { Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); - } - case 45: break; - case 18: - { sb.append('\n'); - } - case 46: break; - case 9: - { return new Yytoken(Yytoken.TYPE_COMMA,null); - } - case 47: break; - case 3: - { - } - case 48: break; - default: - if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { - zzAtEOF = true; - return null; - } - else { - zzScanError(ZZ_NO_MATCH); - } - } - } - } - - -} diff --git a/blade-kit/src/main/java/blade/kit/json/parse/Yytoken.java b/blade-kit/src/main/java/blade/kit/json/parse/Yytoken.java deleted file mode 100644 index 90a111141..000000000 --- a/blade-kit/src/main/java/blade/kit/json/parse/Yytoken.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * $Id: Yytoken.java,v 1.1 2006/04/15 14:10:48 platform Exp $ - * Created on 2006-4-15 - */ -package blade.kit.json.parse; - -/** - * @author FangYidong - */ -public class Yytoken { - public static final int TYPE_VALUE=0;//JSON primitive value: string,number,boolean,null - public static final int TYPE_LEFT_BRACE=1; - public static final int TYPE_RIGHT_BRACE=2; - public static final int TYPE_LEFT_SQUARE=3; - public static final int TYPE_RIGHT_SQUARE=4; - public static final int TYPE_COMMA=5; - public static final int TYPE_COLON=6; - public static final int TYPE_EOF=-1;//end of file - - public int type=0; - public Object value=null; - - public Yytoken(int type,Object value){ - this.type=type; - this.value=value; - } - - public String toString(){ - StringBuffer sb = new StringBuffer(); - switch(type){ - case TYPE_VALUE: - sb.append("VALUE(").append(value).append(")"); - break; - case TYPE_LEFT_BRACE: - sb.append("LEFT BRACE({)"); - break; - case TYPE_RIGHT_BRACE: - sb.append("RIGHT BRACE(})"); - break; - case TYPE_LEFT_SQUARE: - sb.append("LEFT SQUARE([)"); - break; - case TYPE_RIGHT_SQUARE: - sb.append("RIGHT SQUARE(])"); - break; - case TYPE_COMMA: - sb.append("COMMA(,)"); - break; - case TYPE_COLON: - sb.append("COLON(:)"); - break; - case TYPE_EOF: - sb.append("END OF FILE"); - break; - } - return sb.toString(); - } -} diff --git a/blade-kit/src/test/java/blade/test/JSONTest.java b/blade-kit/src/test/java/blade/test/JSONTest.java index 1eee781dd..25074fc93 100644 --- a/blade-kit/src/test/java/blade/test/JSONTest.java +++ b/blade-kit/src/test/java/blade/test/JSONTest.java @@ -5,14 +5,14 @@ import java.util.List; import java.util.Map; -import blade.kit.json.JSONArray; import blade.kit.json.JSONKit; -import blade.kit.json.JSONObject; +import blade.kit.json.Json; +import blade.kit.json.JsonArray; +import blade.kit.json.JsonObject; +import blade.kit.json.JsonValue; public class JSONTest { - - public static void main(String[] args) { //[{"text": "首页","href": "/"},{"text": "博客","href": "blog"},{"text": "关于","href": "about"},{"text": "联系","href": "contact"}] String json = "[{\"text\": \"博客\",\"href\": \"blog\"}]"; @@ -33,22 +33,27 @@ public static void main(String[] args) { String string = JSONKit.toJSONString(list); System.out.println(string); - System.out.println(JSONKit.toList(json)); - + List list2 = Json.parse(json).asArray().values(); + System.out.println(list2); - JSONObject obj1 = new JSONObject(); - obj1.put("name", "jack"); + JsonObject obj1 = new JsonObject(); + obj1.add("name", "jack"); System.out.println(obj1); - JSONArray obj2 = new JSONArray(); + JsonArray obj2 = new JsonArray(); obj2.add("123"); System.out.println(obj2); - User u = JSONKit.parse("{\"name\":\"jack\",\"age\":20}", User.class); -// User u = BeanKit.mapToBean(user, User.class); - System.out.println(u); + User u1 = new User(); + u1.setAge(22); + u1.setName("rose"); + + System.out.println(JSONKit.toJSONString(u1)); + +// User u = JSONKit.parse("{\"name\":\"jack\",\"age\":20}", User.class); +// System.out.println(u); } } diff --git a/blade-kit/src/test/java/blade/test/User.java b/blade-kit/src/test/java/blade/test/User.java new file mode 100644 index 000000000..03bdee871 --- /dev/null +++ b/blade-kit/src/test/java/blade/test/User.java @@ -0,0 +1,32 @@ +package blade.test; + +public class User { + + private String name; + private long age; + + public User() { + // TODO Auto-generated constructor stub + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getAge() { + return age; + } + + public void setAge(long age) { + this.age = age; + } + + @Override + public String toString() { + return "User [name=" + name + ", age=" + age + "]"; + } +} \ No newline at end of file From 2fd6341ac5c2e8607af55baa0f0fbbbbeef8465b Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 26 Oct 2015 14:19:11 +0800 Subject: [PATCH 192/545] add xss html filter --- .../blade/servlet/wrapper/RequestWrapper.java | 3 +- .../java/com/blade/verify/HTMLFilter.java | 537 ------------------ .../src/test/java/com/blade/XSSTest.java | 2 +- 3 files changed, 3 insertions(+), 539 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/verify/HTMLFilter.java diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java b/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java index aa68f8e0d..e9c48d752 100644 --- a/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java +++ b/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java @@ -26,7 +26,8 @@ import com.blade.servlet.QueryParamsMap; import com.blade.servlet.Request; import com.blade.servlet.Session; -import com.blade.verify.HTMLFilter; + +import blade.kit.text.HTMLFilter; /** * Request增强 diff --git a/blade-core/src/main/java/com/blade/verify/HTMLFilter.java b/blade-core/src/main/java/com/blade/verify/HTMLFilter.java deleted file mode 100644 index 292617655..000000000 --- a/blade-core/src/main/java/com/blade/verify/HTMLFilter.java +++ /dev/null @@ -1,537 +0,0 @@ -package com.blade.verify; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * - * HTML filtering utility for protecting against XSS (Cross Site Scripting). - * - * This code is licensed LGPLv3 - * - * This code is a Java port of the original work in PHP by Cal Hendersen. - * http://code.iamcal.com/php/lib_filter/ - * - * The trickiest part of the translation was handling the differences in regex handling - * between PHP and Java. These resources were helpful in the process: - * - * http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html - * http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php - * http://www.regular-expressions.info/modifiers.html - * - * A note on naming conventions: instance variables are prefixed with a "v"; global - * constants are in all caps. - * - * Sample use: - * String input = ... - * String clean = new HTMLFilter().filter( input ); - * - * The class is not thread safe. Create a new instance if in doubt. - * - * If you find bugs or have suggestions on improvement (especially regarding - * performance), please contact us. The latest version of this - * source, and our contact details, can be found at http://xss-html-filter.sf.net - * - * @author Joseph O'Connell - * @author Cal Hendersen - * @author Michael Semb Wever - */ -public final class HTMLFilter { - - /** regex flag union representing /si modifiers in php **/ - private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; - private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); - private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); - private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); - private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); - private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); - private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); - private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); - private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); - private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); - private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); - private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); - private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); - private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); - private static final Pattern P_END_ARROW = Pattern.compile("^>"); - private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); - private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); - private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); - private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); - private static final Pattern P_AMP = Pattern.compile("&"); - private static final Pattern P_QUOTE = Pattern.compile("\""); - private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); - private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); - private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); - - // @xxx could grow large... maybe use sesat's ReferenceMap - private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap(); - private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap(); - - /** set of allowed html elements, along with allowed attributes for each element **/ - private final Map> vAllowed; - /** counts of open tags for each (allowable) html element **/ - private final Map vTagCounts = new HashMap(); - - /** html elements which must always be self-closing (e.g. "") **/ - private final String[] vSelfClosingTags; - /** html elements which must always have separate opening and closing tags (e.g. "") **/ - private final String[] vNeedClosingTags; - /** set of disallowed html elements **/ - private final String[] vDisallowed; - /** attributes which should be checked for valid protocols **/ - private final String[] vProtocolAtts; - /** allowed protocols **/ - private final String[] vAllowedProtocols; - /** tags which should be removed if they contain no content (e.g. "" or "") **/ - private final String[] vRemoveBlanks; - /** entities allowed within html markup **/ - private final String[] vAllowedEntities; - /** flag determining whether comments are allowed in input String. */ - private final boolean stripComment; - private final boolean encodeQuotes; - private boolean vDebug = false; - /** - * flag determining whether to try to make tags when presented with "unbalanced" - * angle brackets (e.g. "" becomes " text "). If set to false, - * unbalanced angle brackets will be html escaped. - */ - private final boolean alwaysMakeTags; - - /** Default constructor. - * - */ - public HTMLFilter() { - vAllowed = new HashMap>(); - - final ArrayList a_atts = new ArrayList(); - a_atts.add("href"); - a_atts.add("target"); - vAllowed.put("a", a_atts); - - final ArrayList img_atts = new ArrayList(); - img_atts.add("src"); - img_atts.add("width"); - img_atts.add("height"); - img_atts.add("alt"); - vAllowed.put("img", img_atts); - - final ArrayList no_atts = new ArrayList(); - vAllowed.put("b", no_atts); - vAllowed.put("strong", no_atts); - vAllowed.put("i", no_atts); - vAllowed.put("em", no_atts); - - vSelfClosingTags = new String[]{"img"}; - vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"}; - vDisallowed = new String[]{}; - vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp. - vProtocolAtts = new String[]{"src", "href"}; - vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"}; - vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"}; - stripComment = true; - encodeQuotes = true; - alwaysMakeTags = true; - } - - /** Set debug flag to true. Otherwise use default settings. See the default constructor. - * - * @param debug turn debug on with a true argument - */ - public HTMLFilter(final boolean debug) { - this(); - vDebug = debug; - - } - - /** Map-parameter configurable constructor. - * - * @param conf map containing configuration. keys match field names. - */ - public HTMLFilter(final Map conf) { - - assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; - assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; - assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; - assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; - assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; - assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; - assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; - assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; - - vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); - vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); - vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); - vDisallowed = (String[]) conf.get("vDisallowed"); - vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); - vProtocolAtts = (String[]) conf.get("vProtocolAtts"); - vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); - vAllowedEntities = (String[]) conf.get("vAllowedEntities"); - stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; - encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; - alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; - } - - private void reset() { - vTagCounts.clear(); - } - - private void debug(final String msg) { - if (vDebug) { - Logger.getAnonymousLogger().info(msg); - } - } - - //--------------------------------------------------------------- - // my versions of some PHP library functions - public static String chr(final int decimal) { - return String.valueOf((char) decimal); - } - - public static String htmlSpecialChars(final String s) { - if(null == s){ - return s; - } - String result = s; - result = regexReplace(P_AMP, "&", result); - result = regexReplace(P_QUOTE, """, result); - result = regexReplace(P_LEFT_ARROW, "<", result); - result = regexReplace(P_RIGHT_ARROW, ">", result); - return result; - } - - //--------------------------------------------------------------- - /** - * given a user submitted input String, filter out any invalid or restricted - * html. - * - * @param input text (i.e. submitted by a user) than may contain html - * @return "clean" version of input, with only valid, whitelisted html elements allowed - */ - public String filter(final String input) { - reset(); - String s = input; - - debug("************************************************"); - debug(" INPUT: " + input); - - s = escapeComments(s); - debug(" escapeComments: " + s); - - s = balanceHTML(s); - debug(" balanceHTML: " + s); - - s = checkTags(s); - debug(" checkTags: " + s); - - s = processRemoveBlanks(s); - debug("processRemoveBlanks: " + s); - - s = validateEntities(s); - debug(" validateEntites: " + s); - - debug("************************************************\n\n"); - return s; - } - - public boolean isAlwaysMakeTags(){ - return alwaysMakeTags; - } - - public boolean isStripComments(){ - return stripComment; - } - - private String escapeComments(final String s) { - final Matcher m = P_COMMENTS.matcher(s); - final StringBuffer buf = new StringBuffer(); - if (m.find()) { - final String match = m.group(1); //(.*?) - m.appendReplacement(buf, Matcher.quoteReplacement("")); - } - m.appendTail(buf); - - return buf.toString(); - } - - private String balanceHTML(String s) { - if (alwaysMakeTags) { - // - // try and form html - // - s = regexReplace(P_END_ARROW, "", s); - s = regexReplace(P_BODY_TO_END, "<$1>", s); - s = regexReplace(P_XML_CONTENT, "$1<$2", s); - - } else { - // - // escape stray brackets - // - s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); - s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); - - // - // the last regexp causes '<>' entities to appear - // (we need to do a lookahead assertion so that the last bracket can - // be used in the next pass of the regexp) - // - s = regexReplace(P_BOTH_ARROWS, "", s); - } - - return s; - } - - private String checkTags(String s) { - Matcher m = P_TAGS.matcher(s); - - final StringBuffer buf = new StringBuffer(); - while (m.find()) { - String replaceStr = m.group(1); - replaceStr = processTag(replaceStr); - m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); - } - m.appendTail(buf); - - s = buf.toString(); - - // these get tallied in processTag - // (remember to reset before subsequent calls to filter method) - for (String key : vTagCounts.keySet()) { - for (int ii = 0; ii < vTagCounts.get(key); ii++) { - s += ""; - } - } - - return s; - } - - private String processRemoveBlanks(final String s) { - String result = s; - for (String tag : vRemoveBlanks) { - if(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){ - P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); - } - result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); - if(!P_REMOVE_SELF_BLANKS.containsKey(tag)){ - P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); - } - result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); - } - - return result; - } - - private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) { - Matcher m = regex_pattern.matcher(s); - return m.replaceAll(replacement); - } - - private String processTag(final String s) { - // ending tags - Matcher m = P_END_TAG.matcher(s); - if (m.find()) { - final String name = m.group(1).toLowerCase(); - if (allowed(name)) { - if (!inArray(name, vSelfClosingTags)) { - if (vTagCounts.containsKey(name)) { - vTagCounts.put(name, vTagCounts.get(name) - 1); - return ""; - } - } - } - } - - // starting tags - m = P_START_TAG.matcher(s); - if (m.find()) { - final String name = m.group(1).toLowerCase(); - final String body = m.group(2); - String ending = m.group(3); - - //debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); - if (allowed(name)) { - String params = ""; - - final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); - final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); - final List paramNames = new ArrayList(); - final List paramValues = new ArrayList(); - while (m2.find()) { - paramNames.add(m2.group(1)); //([a-z0-9]+) - paramValues.add(m2.group(3)); //(.*?) - } - while (m3.find()) { - paramNames.add(m3.group(1)); //([a-z0-9]+) - paramValues.add(m3.group(3)); //([^\"\\s']+) - } - - String paramName, paramValue; - for (int ii = 0; ii < paramNames.size(); ii++) { - paramName = paramNames.get(ii).toLowerCase(); - paramValue = paramValues.get(ii); - -// debug( "paramName='" + paramName + "'" ); -// debug( "paramValue='" + paramValue + "'" ); -// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); - - if (allowedAttribute(name, paramName)) { - if (inArray(paramName, vProtocolAtts)) { - paramValue = processParamProtocol(paramValue); - } - params += " " + paramName + "=\"" + paramValue + "\""; - } - } - - if (inArray(name, vSelfClosingTags)) { - ending = " /"; - } - - if (inArray(name, vNeedClosingTags)) { - ending = ""; - } - - if (ending == null || ending.length() < 1) { - if (vTagCounts.containsKey(name)) { - vTagCounts.put(name, vTagCounts.get(name) + 1); - } else { - vTagCounts.put(name, 1); - } - } else { - ending = " /"; - } - return "<" + name + params + ending + ">"; - } else { - return ""; - } - } - - // comments - m = P_COMMENT.matcher(s); - if (!stripComment && m.find()) { - return "<" + m.group() + ">"; - } - - return ""; - } - - private String processParamProtocol(String s) { - s = decodeEntities(s); - final Matcher m = P_PROTOCOL.matcher(s); - if (m.find()) { - final String protocol = m.group(1); - if (!inArray(protocol, vAllowedProtocols)) { - // bad protocol, turn into local anchor link instead - s = "#" + s.substring(protocol.length() + 1, s.length()); - if (s.startsWith("#//")) { - s = "#" + s.substring(3, s.length()); - } - } - } - - return s; - } - - private String decodeEntities(String s) { - StringBuffer buf = new StringBuffer(); - - Matcher m = P_ENTITY.matcher(s); - while (m.find()) { - final String match = m.group(1); - final int decimal = Integer.decode(match).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - buf = new StringBuffer(); - m = P_ENTITY_UNICODE.matcher(s); - while (m.find()) { - final String match = m.group(1); - final int decimal = Integer.valueOf(match, 16).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - buf = new StringBuffer(); - m = P_ENCODE.matcher(s); - while (m.find()) { - final String match = m.group(1); - final int decimal = Integer.valueOf(match, 16).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - s = validateEntities(s); - return s; - } - - private String validateEntities(final String s) { - StringBuffer buf = new StringBuffer(); - - // validate entities throughout the string - Matcher m = P_VALID_ENTITIES.matcher(s); - while (m.find()) { - final String one = m.group(1); //([^&;]*) - final String two = m.group(2); //(?=(;|&|$)) - m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); - } - m.appendTail(buf); - - return encodeQuotes(buf.toString()); - } - - private String encodeQuotes(final String s){ - if(encodeQuotes){ - StringBuffer buf = new StringBuffer(); - Matcher m = P_VALID_QUOTES.matcher(s); - while (m.find()) { - final String one = m.group(1); //(>|^) - final String two = m.group(2); //([^<]+?) - final String three = m.group(3); //(<|$) - m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, """, two) + three)); - } - m.appendTail(buf); - return buf.toString(); - }else{ - return s; - } - } - - private String checkEntity(final String preamble, final String term) { - - return ";".equals(term) && isValidEntity(preamble) - ? '&' + preamble - : "&" + preamble; - } - - private boolean isValidEntity(final String entity) { - return inArray(entity, vAllowedEntities); - } - - private static boolean inArray(final String s, final String[] array) { - for (String item : array) { - if (item != null && item.equals(s)) { - return true; - } - } - return false; - } - - private boolean allowed(final String name) { - return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); - } - - private boolean allowedAttribute(final String name, final String paramName) { - return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); - } -} \ No newline at end of file diff --git a/blade-core/src/test/java/com/blade/XSSTest.java b/blade-core/src/test/java/com/blade/XSSTest.java index b41a88e07..72b53d2ed 100644 --- a/blade-core/src/test/java/com/blade/XSSTest.java +++ b/blade-core/src/test/java/com/blade/XSSTest.java @@ -1,6 +1,6 @@ package com.blade; -import com.blade.verify.HTMLFilter; +import blade.kit.text.HTMLFilter; public class XSSTest { From d96b1094df937f1c3e98c9d9efa691f72f3763b1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 26 Oct 2015 14:19:55 +0800 Subject: [PATCH 193/545] add html filter --- .../main/java/blade/kit/text/HTMLFilter.java | 538 ++++++++++++++++++ 1 file changed, 538 insertions(+) create mode 100644 blade-kit/src/main/java/blade/kit/text/HTMLFilter.java diff --git a/blade-kit/src/main/java/blade/kit/text/HTMLFilter.java b/blade-kit/src/main/java/blade/kit/text/HTMLFilter.java new file mode 100644 index 000000000..2b437a289 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/text/HTMLFilter.java @@ -0,0 +1,538 @@ +package blade.kit.text; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** +* +* HTML filtering utility for protecting against XSS (Cross Site Scripting). +* +* This code is licensed LGPLv3 +* +* This code is a Java port of the original work in PHP by Cal Hendersen. +* http://code.iamcal.com/php/lib_filter/ +* +* The trickiest part of the translation was handling the differences in regex handling +* between PHP and Java. These resources were helpful in the process: +* +* http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html +* http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php +* http://www.regular-expressions.info/modifiers.html +* +* A note on naming conventions: instance variables are prefixed with a "v"; global +* constants are in all caps. +* +* Sample use: +* String input = ... +* String clean = new HTMLFilter().filter( input ); +* +* The class is not thread safe. Create a new instance if in doubt. +* +* If you find bugs or have suggestions on improvement (especially regarding +* performance), please contact us. The latest version of this +* source, and our contact details, can be found at http://xss-html-filter.sf.net +* +* @author Joseph O'Connell +* @author Cal Hendersen +* @author Michael Semb Wever +*/ +public final class HTMLFilter { + + /** regex flag union representing /si modifiers in php **/ + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; + private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); + private static final Pattern P_END_ARROW = Pattern.compile("^>"); + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_AMP = Pattern.compile("&"); + private static final Pattern P_QUOTE = Pattern.compile("\""); + private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); + + // @xxx could grow large... maybe use sesat's ReferenceMap + private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap(); + private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap(); + + /** set of allowed html elements, along with allowed attributes for each element **/ + private final Map> vAllowed; + /** counts of open tags for each (allowable) html element **/ + private final Map vTagCounts = new HashMap(); + + /** html elements which must always be self-closing (e.g. "") **/ + private final String[] vSelfClosingTags; + /** html elements which must always have separate opening and closing tags (e.g. "") **/ + private final String[] vNeedClosingTags; + /** set of disallowed html elements **/ + private final String[] vDisallowed; + /** attributes which should be checked for valid protocols **/ + private final String[] vProtocolAtts; + /** allowed protocols **/ + private final String[] vAllowedProtocols; + /** tags which should be removed if they contain no content (e.g. "" or "") **/ + private final String[] vRemoveBlanks; + /** entities allowed within html markup **/ + private final String[] vAllowedEntities; + /** flag determining whether comments are allowed in input String. */ + private final boolean stripComment; + private final boolean encodeQuotes; + private boolean vDebug = false; + /** + * flag determining whether to try to make tags when presented with "unbalanced" + * angle brackets (e.g. "" becomes " text "). If set to false, + * unbalanced angle brackets will be html escaped. + */ + private final boolean alwaysMakeTags; + + /** Default constructor. + * + */ + public HTMLFilter() { + vAllowed = new HashMap>(); + + final ArrayList a_atts = new ArrayList(); + a_atts.add("href"); + a_atts.add("target"); + vAllowed.put("a", a_atts); + + final ArrayList img_atts = new ArrayList(); + img_atts.add("src"); + img_atts.add("width"); + img_atts.add("height"); + img_atts.add("alt"); + vAllowed.put("img", img_atts); + + final ArrayList no_atts = new ArrayList(); + vAllowed.put("b", no_atts); + vAllowed.put("strong", no_atts); + vAllowed.put("i", no_atts); + vAllowed.put("em", no_atts); + + vSelfClosingTags = new String[]{"img"}; + vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"}; + vDisallowed = new String[]{}; + vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp. + vProtocolAtts = new String[]{"src", "href"}; + vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"}; + vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"}; + stripComment = true; + encodeQuotes = true; + alwaysMakeTags = true; + } + + /** Set debug flag to true. Otherwise use default settings. See the default constructor. + * + * @param debug turn debug on with a true argument + */ + public HTMLFilter(final boolean debug) { + this(); + vDebug = debug; + + } + + /** Map-parameter configurable constructor. + * + * @param conf map containing configuration. keys match field names. + */ + @SuppressWarnings("unchecked") + public HTMLFilter(final Map conf) { + + assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; + + vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); + vDisallowed = (String[]) conf.get("vDisallowed"); + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); + vProtocolAtts = (String[]) conf.get("vProtocolAtts"); + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); + vAllowedEntities = (String[]) conf.get("vAllowedEntities"); + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; + } + + private void reset() { + vTagCounts.clear(); + } + + private void debug(final String msg) { + if (vDebug) { + Logger.getAnonymousLogger().info(msg); + } + } + + //--------------------------------------------------------------- + // my versions of some PHP library functions + public static String chr(final int decimal) { + return String.valueOf((char) decimal); + } + + public static String htmlSpecialChars(final String s) { + if(null == s){ + return s; + } + String result = s; + result = regexReplace(P_AMP, "&", result); + result = regexReplace(P_QUOTE, """, result); + result = regexReplace(P_LEFT_ARROW, "<", result); + result = regexReplace(P_RIGHT_ARROW, ">", result); + return result; + } + + //--------------------------------------------------------------- + /** + * given a user submitted input String, filter out any invalid or restricted + * html. + * + * @param input text (i.e. submitted by a user) than may contain html + * @return "clean" version of input, with only valid, whitelisted html elements allowed + */ + public String filter(final String input) { + reset(); + String s = input; + + debug("************************************************"); + debug(" INPUT: " + input); + + s = escapeComments(s); + debug(" escapeComments: " + s); + + s = balanceHTML(s); + debug(" balanceHTML: " + s); + + s = checkTags(s); + debug(" checkTags: " + s); + + s = processRemoveBlanks(s); + debug("processRemoveBlanks: " + s); + + s = validateEntities(s); + debug(" validateEntites: " + s); + + debug("************************************************\n\n"); + return s; + } + + public boolean isAlwaysMakeTags(){ + return alwaysMakeTags; + } + + public boolean isStripComments(){ + return stripComment; + } + + private String escapeComments(final String s) { + final Matcher m = P_COMMENTS.matcher(s); + final StringBuffer buf = new StringBuffer(); + if (m.find()) { + final String match = m.group(1); //(.*?) + m.appendReplacement(buf, Matcher.quoteReplacement("")); + } + m.appendTail(buf); + + return buf.toString(); + } + + private String balanceHTML(String s) { + if (alwaysMakeTags) { + // + // try and form html + // + s = regexReplace(P_END_ARROW, "", s); + s = regexReplace(P_BODY_TO_END, "<$1>", s); + s = regexReplace(P_XML_CONTENT, "$1<$2", s); + + } else { + // + // escape stray brackets + // + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); + + // + // the last regexp causes '<>' entities to appear + // (we need to do a lookahead assertion so that the last bracket can + // be used in the next pass of the regexp) + // + s = regexReplace(P_BOTH_ARROWS, "", s); + } + + return s; + } + + private String checkTags(String s) { + Matcher m = P_TAGS.matcher(s); + + final StringBuffer buf = new StringBuffer(); + while (m.find()) { + String replaceStr = m.group(1); + replaceStr = processTag(replaceStr); + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); + } + m.appendTail(buf); + + s = buf.toString(); + + // these get tallied in processTag + // (remember to reset before subsequent calls to filter method) + for (String key : vTagCounts.keySet()) { + for (int ii = 0; ii < vTagCounts.get(key); ii++) { + s += ""; + } + } + + return s; + } + + private String processRemoveBlanks(final String s) { + String result = s; + for (String tag : vRemoveBlanks) { + if(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){ + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); + } + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); + if(!P_REMOVE_SELF_BLANKS.containsKey(tag)){ + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); + } + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); + } + + return result; + } + + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) { + Matcher m = regex_pattern.matcher(s); + return m.replaceAll(replacement); + } + + private String processTag(final String s) { + // ending tags + Matcher m = P_END_TAG.matcher(s); + if (m.find()) { + final String name = m.group(1).toLowerCase(); + if (allowed(name)) { + if (!inArray(name, vSelfClosingTags)) { + if (vTagCounts.containsKey(name)) { + vTagCounts.put(name, vTagCounts.get(name) - 1); + return ""; + } + } + } + } + + // starting tags + m = P_START_TAG.matcher(s); + if (m.find()) { + final String name = m.group(1).toLowerCase(); + final String body = m.group(2); + String ending = m.group(3); + + //debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); + if (allowed(name)) { + String params = ""; + + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); + final List paramNames = new ArrayList(); + final List paramValues = new ArrayList(); + while (m2.find()) { + paramNames.add(m2.group(1)); //([a-z0-9]+) + paramValues.add(m2.group(3)); //(.*?) + } + while (m3.find()) { + paramNames.add(m3.group(1)); //([a-z0-9]+) + paramValues.add(m3.group(3)); //([^\"\\s']+) + } + + String paramName, paramValue; + for (int ii = 0; ii < paramNames.size(); ii++) { + paramName = paramNames.get(ii).toLowerCase(); + paramValue = paramValues.get(ii); + +// debug( "paramName='" + paramName + "'" ); +// debug( "paramValue='" + paramValue + "'" ); +// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); + + if (allowedAttribute(name, paramName)) { + if (inArray(paramName, vProtocolAtts)) { + paramValue = processParamProtocol(paramValue); + } + params += " " + paramName + "=\"" + paramValue + "\""; + } + } + + if (inArray(name, vSelfClosingTags)) { + ending = " /"; + } + + if (inArray(name, vNeedClosingTags)) { + ending = ""; + } + + if (ending == null || ending.length() < 1) { + if (vTagCounts.containsKey(name)) { + vTagCounts.put(name, vTagCounts.get(name) + 1); + } else { + vTagCounts.put(name, 1); + } + } else { + ending = " /"; + } + return "<" + name + params + ending + ">"; + } else { + return ""; + } + } + + // comments + m = P_COMMENT.matcher(s); + if (!stripComment && m.find()) { + return "<" + m.group() + ">"; + } + + return ""; + } + + private String processParamProtocol(String s) { + s = decodeEntities(s); + final Matcher m = P_PROTOCOL.matcher(s); + if (m.find()) { + final String protocol = m.group(1); + if (!inArray(protocol, vAllowedProtocols)) { + // bad protocol, turn into local anchor link instead + s = "#" + s.substring(protocol.length() + 1, s.length()); + if (s.startsWith("#//")) { + s = "#" + s.substring(3, s.length()); + } + } + } + + return s; + } + + private String decodeEntities(String s) { + StringBuffer buf = new StringBuffer(); + + Matcher m = P_ENTITY.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.decode(match).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENTITY_UNICODE.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENCODE.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + s = validateEntities(s); + return s; + } + + private String validateEntities(final String s) { + StringBuffer buf = new StringBuffer(); + + // validate entities throughout the string + Matcher m = P_VALID_ENTITIES.matcher(s); + while (m.find()) { + final String one = m.group(1); //([^&;]*) + final String two = m.group(2); //(?=(;|&|$)) + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); + } + m.appendTail(buf); + + return encodeQuotes(buf.toString()); + } + + private String encodeQuotes(final String s){ + if(encodeQuotes){ + StringBuffer buf = new StringBuffer(); + Matcher m = P_VALID_QUOTES.matcher(s); + while (m.find()) { + final String one = m.group(1); //(>|^) + final String two = m.group(2); //([^<]+?) + final String three = m.group(3); //(<|$) + m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, """, two) + three)); + } + m.appendTail(buf); + return buf.toString(); + }else{ + return s; + } + } + + private String checkEntity(final String preamble, final String term) { + + return ";".equals(term) && isValidEntity(preamble) + ? '&' + preamble + : "&" + preamble; + } + + private boolean isValidEntity(final String entity) { + return inArray(entity, vAllowedEntities); + } + + private static boolean inArray(final String s, final String[] array) { + for (String item : array) { + if (item != null && item.equals(s)) { + return true; + } + } + return false; + } + + private boolean allowed(final String name) { + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); + } + + private boolean allowedAttribute(final String name, final String paramName) { + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); + } +} \ No newline at end of file From 29c1c9ed102392ace9350dbe1b25f27e09fc603c Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 26 Oct 2015 18:26:10 +0800 Subject: [PATCH 194/545] rename handler to handle --- .../src/main/java/com/blade/CoreFilter.java | 2 +- .../main/java/com/blade/FilterHandler.java | 4 +-- .../java/com/blade/route/RouteHandler.java | 7 ++++- blade-core/src/test/java/com/blade/App.java | 29 ------------------- blade-core/src/test/java/com/blade/Index.java | 13 --------- .../src/test/java/com/blade/XSSTest.java | 26 ----------------- 6 files changed, 9 insertions(+), 72 deletions(-) delete mode 100644 blade-core/src/test/java/com/blade/App.java delete mode 100644 blade-core/src/test/java/com/blade/Index.java delete mode 100644 blade-core/src/test/java/com/blade/XSSTest.java diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 0ce5a0c03..8775a90aa 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -126,7 +126,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha /** * 是否被RequestHandler执行 */ - boolean isHandler = new FilterHandler(blade).handler(httpRequest, httpResponse); + boolean isHandler = new FilterHandler(blade).handle(httpRequest, httpResponse); if(!isHandler){ chain.doFilter(httpRequest, httpResponse); } diff --git a/blade-core/src/main/java/com/blade/FilterHandler.java b/blade-core/src/main/java/com/blade/FilterHandler.java index bef318a19..f18db9016 100644 --- a/blade-core/src/main/java/com/blade/FilterHandler.java +++ b/blade-core/src/main/java/com/blade/FilterHandler.java @@ -84,7 +84,7 @@ public FilterHandler(Blade blade){ * @param httpResponse HttpServletResponse响应对象 * @return 是否拦截到请求 */ - boolean handler(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ + boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ // http方法, GET/POST ... String method = httpRequest.getMethod(); @@ -216,7 +216,7 @@ private Object realHandler(HttpServletRequest httpRequest, RequestWrapper reques if(null != router){ - result = router.handler(requestWrapper, responseWrapper); + result = router.handle(requestWrapper, responseWrapper); } else { Class target = match.getTarget(); diff --git a/blade-core/src/main/java/com/blade/route/RouteHandler.java b/blade-core/src/main/java/com/blade/route/RouteHandler.java index 16e821f81..e91dec2ac 100644 --- a/blade-core/src/main/java/com/blade/route/RouteHandler.java +++ b/blade-core/src/main/java/com/blade/route/RouteHandler.java @@ -3,8 +3,13 @@ import com.blade.servlet.Request; import com.blade.servlet.Response; +/** + * 路由执行器 + * @author biezhi + * + */ public interface RouteHandler { - public Object handler(Request request, Response response); + public Object handle(Request request, Response response); } diff --git a/blade-core/src/test/java/com/blade/App.java b/blade-core/src/test/java/com/blade/App.java deleted file mode 100644 index 4ef16e5da..000000000 --- a/blade-core/src/test/java/com/blade/App.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.blade; - -import com.blade.route.RouteHandler; -import com.blade.servlet.Request; -import com.blade.servlet.Response; - -public class App extends Bootstrap { - - @Override - public void init() {} - - public static void main(String[] args) throws Exception { - - Blade blade = Blade.me(); - blade.get("/").run(new RouteHandler() { - @Override - public Object handler(Request request, Response response) { - response.html("

Hello blade!

"); - return null; - } - }); - - blade.addRoute("/hello", Index.class, "hello"); - - blade.app(App.class).listen(9001).start(); - - } - -} diff --git a/blade-core/src/test/java/com/blade/Index.java b/blade-core/src/test/java/com/blade/Index.java deleted file mode 100644 index e19b31423..000000000 --- a/blade-core/src/test/java/com/blade/Index.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.blade; - -import com.blade.servlet.Request; -import com.blade.servlet.Response; - -public class Index { - - public void hello(Request request, Response response){ - System.out.println("请求hello"); - response.html("hi~"); - } - -} diff --git a/blade-core/src/test/java/com/blade/XSSTest.java b/blade-core/src/test/java/com/blade/XSSTest.java deleted file mode 100644 index 72b53d2ed..000000000 --- a/blade-core/src/test/java/com/blade/XSSTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.blade; - -import blade.kit.text.HTMLFilter; - -public class XSSTest { - - public static void main(String[] args) { - - String string1 = ""; - String string2 = ""; - String string3 = "%0a%0a.jsp"; - String string4 = "%22%3cscript%3ealert(%22xss%22)%3c/script%3e"; - String string5 = "%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd"; - String string6 = "%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/windows/win.ini"; - String string7 = "%3c/a%3e%3cscript%3ealert(%22xss%22)%3c/script%3e"; - - System.out.println(HTMLFilter.htmlSpecialChars(string1)); - System.out.println(HTMLFilter.htmlSpecialChars(string2)); - System.out.println(HTMLFilter.htmlSpecialChars(string3)); - System.out.println(HTMLFilter.htmlSpecialChars(string4)); - System.out.println(HTMLFilter.htmlSpecialChars(string5)); - System.out.println(HTMLFilter.htmlSpecialChars(string6)); - System.out.println(HTMLFilter.htmlSpecialChars(string7)); - - } -} From 2bb301f52ad931898d2bd545074589a67914fcb0 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 26 Oct 2015 18:31:51 +0800 Subject: [PATCH 195/545] update UPDATE_LOG --- UPDATE_LOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 6f5b0513b..bfff127e4 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -3,6 +3,7 @@ ### v1.4.0 1. 添加CSRF防御 2. 添加XSS防御 + 3. 优化JSON解析 ### v1.2.9 1. 优化路由配置 From d6ffc8843cfa8f699eafa85f1e3f54425c06a202 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 10:13:14 +0800 Subject: [PATCH 196/545] reconsitution --- blade-core/pom.xml | 9 +- .../main/java/com/blade/ActionHandler.java | 283 +++++++ blade-core/src/main/java/com/blade/Blade.java | 288 +++---- .../src/main/java/com/blade/CoreFilter.java | 14 +- .../main/java/com/blade/FilterHandler.java | 333 -------- .../main/java/com/blade/IocApplication.java | 27 +- .../main/java/com/blade/annotation/Route.java | 2 +- .../blade/{ => context}/BladeWebContext.java | 38 +- .../com/blade/exception/ExceptionHandler.java | 10 - .../exception/WebApplicationException.java | 45 - .../java/com/blade/http/HttpException.java | 23 + .../com/blade/{route => http}/HttpMethod.java | 2 +- .../main/java/com/blade/http/HttpStatus.java | 46 ++ .../RenderFactory.java => http/Path.java} | 89 +- .../src/main/java/com/blade/http/Request.java | 113 +++ .../main/java/com/blade/http/Response.java | 74 ++ .../ioc/{impl => }/AbstractBeanFactory.java | 6 +- .../blade/ioc/{impl => }/PrototypeBean.java | 4 +- ...ultContainer.java => SampleContainer.java} | 14 +- .../com/blade/ioc/{impl => }/SingleBean.java | 4 +- .../loader/AbstractFileRoutesLoader.java | 195 +++++ .../loader/ClassPathControllerLoader.java | 54 ++ .../java/com/blade/{ => loader}/Config.java | 2 +- .../com/blade/{ => loader}/Configurator.java | 2 +- .../com/blade/loader/ControllerLoader.java | 9 + .../blade/loader/FileSystemRoutesLoader.java | 34 + .../java/com/blade/loader/RoutesLoader.java | 13 + .../blade/loader/SpringControllerLoader.java | 27 + .../main/java/com/blade/render/JspRender.java | 78 +- .../main/java/com/blade/render/Render.java | 278 +------ .../src/main/java/com/blade/route/Route.java | 106 +++ .../main/java/com/blade/route/RouteBase.java | 7 - .../java/com/blade/route/RouteHandler.java | 6 +- .../java/com/blade/route/RouteMatcher.java | 269 ------ .../com/blade/route/RouteMatcherBuilder.java | 396 --------- .../src/main/java/com/blade/route/Router.java | 159 ++++ .../java/com/blade/route/RouterExecutor.java | 49 -- .../java/com/blade/route/RoutesException.java | 24 + .../com/blade/route/SampleRouteMatcher.java | 360 ++++++++ .../blade/route/impl/DefaultRouteMatcher.java | 237 ------ .../server/{BladeServer.java => Server.java} | 15 +- .../com/blade/servlet/QueryParamsMap.java | 269 ------ .../main/java/com/blade/servlet/Request.java | 595 -------------- .../main/java/com/blade/servlet/Response.java | 309 ------- .../com/blade/servlet/ServletRequest.java | 504 ++++++++++++ .../com/blade/servlet/ServletResponse.java | 312 +++++++ .../com/blade/servlet/multipart/FileItem.java | 114 +-- .../blade/servlet/multipart/Multipart.java | 306 +++++++ .../servlet/multipart/MultipartException.java | 22 + .../servlet/multipart/MultipartHandler.java | 9 + .../servlet/multipart/MultipartReader.java | 768 ++++++++++++++++++ .../servlet/multipart/ParameterParser.java | 298 +++++++ .../servlet/multipart/ServletFileUpload.java | 270 ------ .../com/blade/servlet/multipart/Streams.java | 149 ++++ .../wrapper/RequestResponseBuilder.java | 60 -- .../blade/servlet/wrapper/RequestWrapper.java | 274 ------- .../servlet/wrapper/ResponseWrapper.java | 217 ----- .../blade/servlet/wrapper/package-info.java | 4 - .../com/blade/verify/CSRFTokenManager.java | 4 +- .../java/blade/exception/BladeException.class | Bin 0 -> 1474 bytes .../exception/ClassReaderException.class | Bin 0 -> 1407 bytes .../exception/ExceptionHandlerImpl.class | Bin 0 -> 2070 bytes .../java/blade/exception/ExceptionStack.class | Bin 0 -> 4358 bytes .../exception/IllegalPathException.class | Bin 0 -> 1406 bytes .../java/blade/exception/package-info.class | Bin 0 -> 135 bytes .../bin/src/main/java/blade/kit/Assert.class | Bin 0 -> 13122 bytes .../bin/src/main/java/blade/kit/Base64.class | Bin 0 -> 4282 bytes .../bin/src/main/java/blade/kit/BeanKit.class | Bin 0 -> 5105 bytes .../bin/src/main/java/blade/kit/CharKit.class | Bin 0 -> 8477 bytes .../src/main/java/blade/kit/CloneKit.class | Bin 0 -> 7690 bytes .../main/java/blade/kit/CollectionKit.class | Bin 0 -> 23258 bytes .../bin/src/main/java/blade/kit/DateKit.class | Bin 0 -> 11063 bytes .../blade/kit/Emptys$NullPlaceholder.class | Bin 0 -> 3177 bytes .../bin/src/main/java/blade/kit/Emptys.class | Bin 0 -> 3905 bytes .../src/main/java/blade/kit/EncrypKit.class | Bin 0 -> 2878 bytes .../main/java/blade/kit/ExceptionKit.class | Bin 0 -> 9351 bytes .../kit/FileKit$FileNameAndExtension.class | Bin 0 -> 5046 bytes .../bin/src/main/java/blade/kit/FileKit.class | Bin 0 -> 12692 bytes .../src/main/java/blade/kit/HashidKit.class | Bin 0 -> 7416 bytes .../bin/src/main/java/blade/kit/IOKit.class | Bin 0 -> 10601 bytes .../bin/src/main/java/blade/kit/IpKit.class | Bin 0 -> 2351 bytes .../bin/src/main/java/blade/kit/MailKit.class | Bin 0 -> 10335 bytes .../kit/MimeParse$FitnessAndQuality.class | Bin 0 -> 4591 bytes .../blade/kit/MimeParse$ParseResults.class | Bin 0 -> 4922 bytes .../src/main/java/blade/kit/MimeParse.class | Bin 0 -> 5487 bytes .../bin/src/main/java/blade/kit/PathKit.class | Bin 0 -> 3110 bytes .../src/main/java/blade/kit/PatternKit.class | Bin 0 -> 3571 bytes .../src/main/java/blade/kit/PropertyKit.class | Bin 0 -> 6376 bytes .../src/main/java/blade/kit/ReflectKit.class | Bin 0 -> 10638 bytes .../main/java/blade/kit/SerializeKit.class | Bin 0 -> 2985 bytes .../blade/kit/ShellKit$CommandResult.class | Bin 0 -> 3156 bytes .../src/main/java/blade/kit/ShellKit.class | Bin 0 -> 5396 bytes .../StreamKit$SynchronizedOutputStream.class | Bin 0 -> 5550 bytes .../src/main/java/blade/kit/StreamKit.class | Bin 0 -> 9807 bytes .../src/main/java/blade/kit/StringKit.class | Bin 0 -> 15112 bytes .../java/blade/kit/SystemKit$HostInfo.class | Bin 0 -> 8690 bytes .../java/blade/kit/SystemKit$JavaInfo.class | Bin 0 -> 10207 bytes .../blade/kit/SystemKit$JavaRuntimeInfo.class | Bin 0 -> 9896 bytes .../blade/kit/SystemKit$JavaSpecInfo.class | Bin 0 -> 8844 bytes .../java/blade/kit/SystemKit$JvmInfo.class | Bin 0 -> 8895 bytes .../blade/kit/SystemKit$JvmSpecInfo.class | Bin 0 -> 8850 bytes .../java/blade/kit/SystemKit$OsInfo.class | Bin 0 -> 10950 bytes .../java/blade/kit/SystemKit$UserInfo.class | Bin 0 -> 9098 bytes .../src/main/java/blade/kit/SystemKit.class | Bin 0 -> 10816 bytes .../bin/src/main/java/blade/kit/TaskKit.class | Bin 0 -> 7331 bytes .../bin/src/main/java/blade/kit/TimeKit.class | Bin 0 -> 2453 bytes .../bin/src/main/java/blade/kit/TimwKit.class | Bin 0 -> 5122 bytes .../java/blade/kit/base/ThrowableKit.class | Bin 0 -> 4137 bytes .../blade/kit/http/ConnectionFactory.class | Bin 0 -> 1847 bytes .../src/main/java/blade/kit/http/Header.class | Bin 0 -> 2769 bytes .../kit/http/HttpRequest$CloseOperation.class | Bin 0 -> 5783 bytes .../kit/http/HttpRequest$FlushOperation.class | Bin 0 -> 5746 bytes .../kit/http/HttpRequest$Operation.class | Bin 0 -> 5637 bytes .../java/blade/kit/http/HttpRequest.class | Bin 0 -> 23165 bytes .../blade/kit/http/HttpRequestException.class | Bin 0 -> 1370 bytes .../main/java/blade/kit/http/MethodType.class | Bin 0 -> 1215 bytes .../blade/kit/http/RequestOutputStream.class | Bin 0 -> 1900 bytes .../java/blade/kit/http/UploadProgress.class | Bin 0 -> 599 bytes .../java/blade/kit/http/package-info.class | Bin 0 -> 134 bytes .../java/blade/kit/io/AppendableWriter.class | Bin 0 -> 7147 bytes .../main/java/blade/kit/io/ByteArray.class | Bin 0 -> 2655 bytes .../blade/kit/io/ByteArrayOutputStream.class | Bin 0 -> 3590 bytes .../blade/kit/io/CharStreams$NullWriter.class | Bin 0 -> 6301 bytes .../main/java/blade/kit/io/CharStreams.class | Bin 0 -> 8117 bytes .../kit/io/FastByteArrayOutputStream.class | Bin 0 -> 2975 bytes .../java/blade/kit/io/FastByteBuffer.class | Bin 0 -> 3179 bytes .../main/java/blade/kit/io/LineBuffer.class | Bin 0 -> 3114 bytes .../java/blade/kit/io/LineProcessor.class | Bin 0 -> 834 bytes .../main/java/blade/kit/io/LineReader.class | Bin 0 -> 3257 bytes .../blade/kit/io/StringBuilderWriter.class | Bin 0 -> 4150 bytes .../main/java/blade/kit/io/package-info.class | Bin 0 -> 132 bytes .../main/java/blade/kit/json/JSONKit.class | Bin 0 -> 3048 bytes .../src/main/java/blade/kit/json/Json.class | Bin 0 -> 9220 bytes .../main/java/blade/kit/json/JsonArray.class | Bin 0 -> 8627 bytes .../java/blade/kit/json/JsonLiteral.class | Bin 0 -> 3399 bytes .../main/java/blade/kit/json/JsonNumber.class | Bin 0 -> 4256 bytes .../kit/json/JsonObject$HashIndexTable.class | Bin 0 -> 5404 bytes .../blade/kit/json/JsonObject$Member.class | Bin 0 -> 5497 bytes .../main/java/blade/kit/json/JsonObject.class | Bin 0 -> 11454 bytes .../main/java/blade/kit/json/JsonParser.class | Bin 0 -> 17043 bytes .../main/java/blade/kit/json/JsonString.class | Bin 0 -> 2908 bytes .../main/java/blade/kit/json/JsonValue.class | Bin 0 -> 9800 bytes .../main/java/blade/kit/json/JsonWriter.class | Bin 0 -> 4410 bytes .../java/blade/kit/json/ParseException.class | Bin 0 -> 1104 bytes .../json/PrettyPrint$PrettyPrintWriter.class | Bin 0 -> 5017 bytes .../java/blade/kit/json/PrettyPrint.class | Bin 0 -> 3625 bytes .../java/blade/kit/json/WriterConfig.class | Bin 0 -> 1043 bytes .../java/blade/kit/json/WritingBuffer.class | Bin 0 -> 3500 bytes .../main/java/blade/kit/log/JdkLogger.class | Bin 0 -> 4142 bytes .../java/blade/kit/log/JdkLoggerFactory.class | Bin 0 -> 1319 bytes .../src/main/java/blade/kit/log/Level.class | Bin 0 -> 793 bytes .../main/java/blade/kit/log/Log4jLogger.class | Bin 0 -> 9128 bytes .../blade/kit/log/Log4jLoggerFactory.class | Bin 0 -> 1325 bytes .../src/main/java/blade/kit/log/Logger.class | Bin 0 -> 7210 bytes .../java/blade/kit/log/LoggerFactory.class | Bin 0 -> 831 bytes .../java/blade/kit/log/SimpleLogger.class | Bin 0 -> 4274 bytes .../blade/kit/log/SimpleLoggerFactory.class | Bin 0 -> 1328 bytes .../java/blade/kit/log/package-info.class | Bin 0 -> 133 bytes .../java/blade/kit/mail/EmailHandle.class | Bin 0 -> 9075 bytes .../java/blade/kit/mail/MailTemplate.class | Bin 0 -> 7324 bytes .../java/blade/kit/mail/package-info.class | Bin 0 -> 134 bytes .../main/java/blade/kit/package-info.class | Bin 0 -> 129 bytes .../kit/resource/AbstractClassReader.class | Bin 0 -> 8377 bytes .../kit/resource/ClassPathClassReader.class | Bin 0 -> 1275 bytes .../java/blade/kit/resource/ClassReader.class | Bin 0 -> 1864 bytes .../blade/kit/resource/JarReaderImpl.class | Bin 0 -> 9596 bytes .../blade/kit/resource/package-info.class | Bin 0 -> 138 bytes .../main/java/blade/kit/text/HTMLFilter.class | Bin 0 -> 7953 bytes .../java/blade/kit/timw/TimwCounter.class | Bin 0 -> 1013 bytes .../java/blade/kit/timw/TimwManager.class | Bin 0 -> 766 bytes .../java/blade/kit/timw/TimwMonitor.class | Bin 0 -> 2867 bytes .../java/blade/kit/timw/package-info.class | Bin 0 -> 134 bytes .../src/test/java/blade/test/HttpTest.class | Bin 0 -> 1693 bytes .../src/test/java/blade/test/JSONTest.class | Bin 0 -> 3874 bytes .../src/test/java/blade/test/LogTest.class | Bin 0 -> 1593 bytes .../src/test/java/blade/test/MailTest.class | Bin 0 -> 1636 bytes .../src/test/java/blade/test/StringTest.class | Bin 0 -> 2161 bytes .../src/test/java/blade/test/TaskTest.class | Bin 0 -> 2006 bytes .../bin/src/test/java/blade/test/User.class | Bin 0 -> 1744 bytes 179 files changed, 4140 insertions(+), 4088 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/ActionHandler.java delete mode 100644 blade-core/src/main/java/com/blade/FilterHandler.java rename blade-core/src/main/java/com/blade/{ => context}/BladeWebContext.java (60%) delete mode 100644 blade-core/src/main/java/com/blade/exception/ExceptionHandler.java delete mode 100644 blade-core/src/main/java/com/blade/exception/WebApplicationException.java create mode 100644 blade-core/src/main/java/com/blade/http/HttpException.java rename blade-core/src/main/java/com/blade/{route => http}/HttpMethod.java (97%) create mode 100644 blade-core/src/main/java/com/blade/http/HttpStatus.java rename blade-core/src/main/java/com/blade/{render/RenderFactory.java => http/Path.java} (60%) create mode 100644 blade-core/src/main/java/com/blade/http/Request.java create mode 100644 blade-core/src/main/java/com/blade/http/Response.java rename blade-core/src/main/java/com/blade/ioc/{impl => }/AbstractBeanFactory.java (90%) rename blade-core/src/main/java/com/blade/ioc/{impl => }/PrototypeBean.java (91%) rename blade-core/src/main/java/com/blade/ioc/{impl/DefaultContainer.java => SampleContainer.java} (96%) rename blade-core/src/main/java/com/blade/ioc/{impl => }/SingleBean.java (91%) create mode 100644 blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java create mode 100644 blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java rename blade-core/src/main/java/com/blade/{ => loader}/Config.java (99%) rename blade-core/src/main/java/com/blade/{ => loader}/Configurator.java (96%) create mode 100644 blade-core/src/main/java/com/blade/loader/ControllerLoader.java create mode 100644 blade-core/src/main/java/com/blade/loader/FileSystemRoutesLoader.java create mode 100644 blade-core/src/main/java/com/blade/loader/RoutesLoader.java create mode 100644 blade-core/src/main/java/com/blade/loader/SpringControllerLoader.java create mode 100644 blade-core/src/main/java/com/blade/route/Route.java delete mode 100644 blade-core/src/main/java/com/blade/route/RouteBase.java delete mode 100644 blade-core/src/main/java/com/blade/route/RouteMatcher.java delete mode 100644 blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java create mode 100644 blade-core/src/main/java/com/blade/route/Router.java delete mode 100644 blade-core/src/main/java/com/blade/route/RouterExecutor.java create mode 100644 blade-core/src/main/java/com/blade/route/RoutesException.java create mode 100644 blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java delete mode 100644 blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java rename blade-core/src/main/java/com/blade/server/{BladeServer.java => Server.java} (67%) delete mode 100644 blade-core/src/main/java/com/blade/servlet/QueryParamsMap.java delete mode 100644 blade-core/src/main/java/com/blade/servlet/Request.java delete mode 100644 blade-core/src/main/java/com/blade/servlet/Response.java create mode 100644 blade-core/src/main/java/com/blade/servlet/ServletRequest.java create mode 100644 blade-core/src/main/java/com/blade/servlet/ServletResponse.java create mode 100644 blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java create mode 100644 blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java create mode 100644 blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java create mode 100644 blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java create mode 100644 blade-core/src/main/java/com/blade/servlet/multipart/ParameterParser.java delete mode 100644 blade-core/src/main/java/com/blade/servlet/multipart/ServletFileUpload.java create mode 100644 blade-core/src/main/java/com/blade/servlet/multipart/Streams.java delete mode 100644 blade-core/src/main/java/com/blade/servlet/wrapper/RequestResponseBuilder.java delete mode 100644 blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java delete mode 100644 blade-core/src/main/java/com/blade/servlet/wrapper/ResponseWrapper.java delete mode 100644 blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java create mode 100644 blade-kit/bin/src/main/java/blade/exception/BladeException.class create mode 100644 blade-kit/bin/src/main/java/blade/exception/ClassReaderException.class create mode 100644 blade-kit/bin/src/main/java/blade/exception/ExceptionHandlerImpl.class create mode 100644 blade-kit/bin/src/main/java/blade/exception/ExceptionStack.class create mode 100644 blade-kit/bin/src/main/java/blade/exception/IllegalPathException.class create mode 100644 blade-kit/bin/src/main/java/blade/exception/package-info.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/Assert.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/Base64.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/BeanKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/CharKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/CloneKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/CollectionKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/DateKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/Emptys$NullPlaceholder.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/Emptys.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/EncrypKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/ExceptionKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/FileKit$FileNameAndExtension.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/FileKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/HashidKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/IOKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/IpKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/MailKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/MimeParse$FitnessAndQuality.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/MimeParse$ParseResults.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/MimeParse.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/PathKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/PatternKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/PropertyKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/ReflectKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/SerializeKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/ShellKit$CommandResult.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/ShellKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/StreamKit$SynchronizedOutputStream.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/StreamKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/StringKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$HostInfo.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaInfo.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaRuntimeInfo.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaSpecInfo.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmInfo.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmSpecInfo.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$OsInfo.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$UserInfo.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/TaskKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/TimeKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/TimwKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/base/ThrowableKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/ConnectionFactory.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/Header.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$CloseOperation.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$FlushOperation.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$Operation.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/HttpRequest.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/HttpRequestException.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/MethodType.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/RequestOutputStream.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/UploadProgress.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/http/package-info.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/AppendableWriter.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/ByteArray.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/ByteArrayOutputStream.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/CharStreams$NullWriter.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/CharStreams.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/FastByteArrayOutputStream.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/FastByteBuffer.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/LineBuffer.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/LineProcessor.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/LineReader.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/StringBuilderWriter.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/io/package-info.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JSONKit.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/Json.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonArray.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonLiteral.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonNumber.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonObject$HashIndexTable.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonObject$Member.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonObject.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonParser.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonString.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonValue.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonWriter.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/ParseException.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint$PrettyPrintWriter.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/WriterConfig.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/json/WritingBuffer.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/log/JdkLogger.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/log/JdkLoggerFactory.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/log/Level.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/log/Log4jLogger.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/log/Log4jLoggerFactory.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/log/Logger.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/log/LoggerFactory.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/log/SimpleLogger.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/log/SimpleLoggerFactory.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/log/package-info.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/mail/EmailHandle.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/mail/MailTemplate.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/mail/package-info.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/package-info.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/resource/AbstractClassReader.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/resource/ClassPathClassReader.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/resource/ClassReader.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/resource/JarReaderImpl.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/resource/package-info.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/text/HTMLFilter.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/timw/TimwCounter.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/timw/TimwManager.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/timw/TimwMonitor.class create mode 100644 blade-kit/bin/src/main/java/blade/kit/timw/package-info.class create mode 100644 blade-kit/bin/src/test/java/blade/test/HttpTest.class create mode 100644 blade-kit/bin/src/test/java/blade/test/JSONTest.class create mode 100644 blade-kit/bin/src/test/java/blade/test/LogTest.class create mode 100644 blade-kit/bin/src/test/java/blade/test/MailTest.class create mode 100644 blade-kit/bin/src/test/java/blade/test/StringTest.class create mode 100644 blade-kit/bin/src/test/java/blade/test/TaskTest.class create mode 100644 blade-kit/bin/src/test/java/blade/test/User.class diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 9fe6ce832..0d4e70c28 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -25,11 +25,16 @@ blade-kit 1.2.7 - + + org.springframework + spring-context + 3.2.10.RELEASE + provided + javax.servlet javax.servlet-api - ${servlet.version} + 3.0.1 provided diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java new file mode 100644 index 000000000..c9e3f01ad --- /dev/null +++ b/blade-core/src/main/java/com/blade/ActionHandler.java @@ -0,0 +1,283 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.blade.context.BladeWebContext; +import com.blade.http.HttpStatus; +import com.blade.http.Request; +import com.blade.http.Response; +import com.blade.render.ModelAndView; +import com.blade.route.Route; +import com.blade.route.RouteHandler; +import com.blade.route.Router; +import com.blade.route.SampleRouteMatcher; +import com.blade.servlet.ServletRequest; +import com.blade.servlet.ServletResponse; + +import blade.exception.BladeException; +import blade.kit.PathKit; +import blade.kit.ReflectKit; +import blade.kit.StringKit; +import blade.kit.base.ThrowableKit; +import blade.kit.log.Logger; + +/** + * 请求执行的Handler + *

+ * 拦截器所有blade的请求,处理route and interceptor + *

+ * + * @author biezhi + * @since 1.0 + */ +public class ActionHandler { + + private static final Logger LOGGER = Logger.getLogger(ActionHandler.class); + + private Blade blade; + + private Router router; + + private SampleRouteMatcher sampleRouteMatcher; + + /** + * 服务器500错误时返回的HTML + */ + + private static final String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + + Blade.VERSION +"
"; + + private static final String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + + Blade.VERSION +"
"; + + public ActionHandler(Blade blade){ + this.blade = blade; + this.router = blade.router(); + this.sampleRouteMatcher = new SampleRouteMatcher(router); + } + + /** + * handler执行方法 + * + * @param httpRequest HttpServletRequest请求对象 + * @param httpResponse HttpServletResponse响应对象 + * @return 是否拦截到请求 + */ + public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ + + Response response = null; + try { + + // http方法, GET/POST ... + String method = httpRequest.getMethod(); + + // 请求的uri + String uri = PathKit.getRelativePath(httpRequest); + + // 如果是静态资源则交给filter处理 + if(null != blade.staticFolder() && blade.staticFolder().length > 0){ + if(!filterStaticFolder(uri)){ + return false; + } + } + + if(blade.debug()){ + LOGGER.debug("Request : " + method + "\t" + uri); + } + + // 创建RequestWrapper And RequestWrapper + Request request = new ServletRequest(httpRequest); + + // 构建一个包装后的response + response = new ServletResponse(httpResponse, blade.render()); + + // 初始化context + BladeWebContext.setContext(request, response); + + Route route = sampleRouteMatcher.getRoute(method, uri); + + // 如果找到 + if (route != null) { + // 执行before拦截 + List befores = sampleRouteMatcher.getBefore(uri); + invokeInterceptor(request, response, befores); + + // 实际执行方法 + handle(request, response, route); + + // 执行after拦截 + List afters = sampleRouteMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + return true; + } + + // 没有找到 + render404(response, uri); + return true; + } catch (BladeException bex) { + + String error = ThrowableKit.getStackTraceAsString(bex); + LOGGER.error(error); + ThrowableKit.propagate(bex); + + httpResponse.setStatus(500); + // 写入内容到浏览器 + if (!httpResponse.isCommitted()) { + response.html(INTERNAL_ERROR); + return true; + } + } catch (Exception e) { + String error = ThrowableKit.getStackTraceAsString(e); + LOGGER.error(error); + ThrowableKit.propagate(e); + + httpResponse.setStatus(500); + // 写入内容到浏览器 + if (!httpResponse.isCommitted()) { + response.html(INTERNAL_ERROR); + return true; + } + } + return false; + + } + + private void render404(Response response, String uri) throws IOException{ + String view404 = blade.view404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(VIEW_NOTFOUND, uri)); + } + } + + private void invokeInterceptor(Request request, Response response, List interceptors) { + for(Route route : interceptors){ + handle(request, response, route); + } + } + + /** + * + * 实际的路由方法执行 + * @param httpRequest http请求对象 + * @param requestWrapper request包装对象 + * @param responseWrapper response包装对象 + * @param match 路由匹配对象 + * @return object + */ + private void handle(Request request, Response response, Route route){ + RouteHandler router = (RouteHandler) route.getTarget(); + request.initPathParams(request.path()); + // 初始化context + BladeWebContext.setContext(request, response); + if(null != router){ + router.handle(request, response); + } else { + Object target = route.getTarget(); + // 要执行的路由方法 + Method actionMethod = route.getAction(); + // 执行route方法 + executeMethod(target, actionMethod, request, response); + } + } + + /** + * 获取方法内的参数 + * + * @param request Request对象,用于注入到method参数列表中 + * @param response Response对象,用于注入到method参数列表中 + * @param params params参数列表 + * @return 返回生成后的参数数组 + */ + private Object[] getArgs(Request request, Response response, Class[] params){ + + int len = params.length; + Object[] args = new Object[len]; + + for(int i=0; i paramTypeClazz = params[i]; + if(paramTypeClazz.getName().equals(Request.class.getName())){ + args[i] = request; + } + if(paramTypeClazz.getName().equals(Response.class.getName())){ + args[i] = response; + } + } + + return args; + } + + /** + * 执行路由方法 + * @param object 方法的实例,即该方法所在类的对象 + * @param method 要执行的method + * @param request Request对象,作为参数注入 + * @param response Response对象,作为参数注入 + * @return 返回方法执行后的返回值 + */ + private Object executeMethod(Object object, Method method, Request request, Response response){ + int len = method.getParameterTypes().length; + method.setAccessible(true); + if(len > 0){ + Object[] args = getArgs(request, response, method.getParameterTypes()); + return ReflectKit.invokeMehod(object, method, args); + } else { + return ReflectKit.invokeMehod(object, method); + } + } + + /** + * 渲染视图 + * + * @param response + * @param result + * @return + */ + /*private void render(Response response, Object result){ + if(result instanceof String){ + response.render(result.toString()); + } else if(result instanceof ModelAndView){ + response.render( (ModelAndView) result ); + } + }*/ + + /** + * 要过滤掉的目录 + * @param uri + * @return + */ + private boolean filterStaticFolder(String uri){ + int len = blade.staticFolder().length; + for(int i=0; i * 手动注册一个对象到ioc容器中 @@ -103,7 +121,7 @@ public void regObject(Object object){ * * @param confName 配置文件路径 */ - public void config(String confName){ + public void appConf(String confName){ Map configMap = PropertyKit.getPropertyMap(confName); configuration(configMap); } @@ -116,7 +134,7 @@ public void config(String confName){ * * @param jsonPath json文件路径 */ - public void configJsonPath(String jsonPath){ + public void appJsonPath(String jsonPath){ InputStream inputStream = Blade.class.getResourceAsStream(jsonPath); if(null != inputStream){ try { @@ -136,7 +154,7 @@ public void configJsonPath(String jsonPath){ * * @param json json配置 */ - public void configJson(String json){ + public void appJson(String json){ Map configMap = JSONKit.toMap(json); configuration(configMap); } @@ -202,15 +220,11 @@ public Blade ioc(String...packages){ return this; } - /** - * 加载一个Route - * @param route - */ - public Blade load(Class route){ - IocApplication.addRouteClass(route); + public Blade route(String path, Object target, String method){ + router.route(path, target, method); return this; } - + /** * 注册一个函数式的路由
*

@@ -220,8 +234,8 @@ public Blade load(Class route){ * @param clazz 路由处理类 * @param methodName 路由处理方法名称 */ - public Blade addRoute(String path, Class clazz, String method){ - RouteMatcherBuilder.buildFunctional(path, clazz, method, null); + public Blade route(String path, Class clazz, String method){ + router.route(path, clazz, method); return this; } @@ -232,269 +246,140 @@ public Blade addRoute(String path, Class clazz, String method){ * @param methodName 路由处理方法名称 * @param httpMethod 请求类型,GET/POST */ - public Blade addRoute(String path, Class clazz, String method, HttpMethod httpMethod){ - RouteMatcherBuilder.buildFunctional(path, clazz, method, httpMethod); + public Blade route(String path, Class clazz, String method, HttpMethod httpMethod){ + router.route(path, clazz, method, httpMethod); return this; } /** * get请求 * @param path - * @param routeHandler + * @param handler */ - public Blade get(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.GET); + public Blade get(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.GET); return this; } - /** - * get请求,多个路由 - * @param paths - */ - public RouterExecutor get(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.GET); - } - return null; - } /** * post请求 * @param path - * @param routeHandler + * @param handler */ - public Blade post(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.POST); + public Blade post(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.POST); return this; } - /** - * post请求,多个路由 - * @param paths - */ - public RouterExecutor post(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.POST); - } - return null; - } /** * delete请求 * @param path - * @param routeHandler + * @param handler */ - public Blade delete(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.DELETE); + public Blade delete(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.DELETE); return this; } - /** - * delete请求,多个路由 - * @param paths - */ - public RouterExecutor delete(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.DELETE); - } - return null; - } /** * put请求 * @param paths */ - public Blade put(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PUT); + public Blade put(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.PUT); return this; } - /** - * put请求,多个路由 - * @param paths - */ - public RouterExecutor put(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.PUT); - } - return null; - } - /** * patch请求 * @param path - * @param routeHandler + * @param handler */ - public Blade patch(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.PATCH); + public Blade patch(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.PATCH); return this; } - /** - * patch请求,多个路由 - * @param paths - */ - public RouterExecutor patch(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.PATCH); - } - return null; - } - /** * head请求 * @param path - * @param routeHandler + * @param handler */ - public Blade head(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.HEAD); + public Blade head(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.HEAD); return this; } - /** - * head请求,多个路由 - * @param paths - */ - public RouterExecutor head(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.HEAD); - } - return null; - } - /** * trace请求 * @param path - * @param routeHandler + * @param handler */ - public Blade trace(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.TRACE); + public Blade trace(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.TRACE); return this; } - /** - * trace请求,多个路由 - * @param paths - */ - public RouterExecutor trace(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.TRACE); - } - return null; - } - /** * options请求 * @param path - * @param routeHandler + * @param handler */ - public Blade options(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.OPTIONS); + public Blade options(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.OPTIONS); return this; } - /** - * options请求,多个路由 - * @param paths - */ - public RouterExecutor options(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.OPTIONS); - } - return null; - } - /** * connect请求 * @param path - * @param routeHandler + * @param handler */ - public Blade connect(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.CONNECT); + public Blade connect(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.CONNECT); return this; } - /** - * connect请求,多个路由 - * @param paths - */ - public RouterExecutor connect(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.CONNECT); - } - return null; - } - /** * 任意请求 * @param path - * @param routeHandler + * @param handler */ - public Blade all(String path, RouteHandler router){ - RouteMatcherBuilder.buildHandler(path, router, HttpMethod.ALL); + public Blade all(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.ALL); return this; } - /** - * all请求,多个路由 - * @param paths - */ - public RouterExecutor all(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.ALL); - } - return null; - } - /** * 拦截器before请求 * @param path * @param routeHandler */ - public Blade before(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.BEFORE); + public Blade before(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.BEFORE); return this; } - /** - * before请求,多个路由 - * @param paths - */ - public RouterExecutor before(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.BEFORE); - } - return null; - } - /** * 拦截器after请求 * @param path * @param routeHandler */ - public Blade after(String path, RouteHandler routeHandler){ - RouteMatcherBuilder.buildInterceptor(path, routeHandler, HttpMethod.AFTER); + public Blade after(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.AFTER); return this; } - /** - * after请求,多个路由 - * @param paths - */ - public RouterExecutor after(String... paths){ - if(null != paths && paths.length > 0){ - return new RouterExecutor(paths, HttpMethod.AFTER); - } - return null; - } - /** * 设置渲染引擎,默认是JSP引擎 * * @param render 渲染引擎对象 */ public Blade viewEngin(Render render) { - RenderFactory.init(render); + this.render = render; return this; } @@ -614,19 +499,27 @@ public Blade debug(boolean isdebug){ } public Blade listen(int port){ - DEFAULT_PORT = port; + this.port = port; return this; } - public void start(String contextPath) throws Exception { - BladeServer bladeServer = new BladeServer(DEFAULT_PORT); - bladeServer.run(contextPath); + public void start(String contextPath) { + try { + Server bladeServer = new Server(this.port); + bladeServer.run(contextPath); + } catch (Exception e) { + throw new RuntimeException(e); + } } - public void start() throws Exception { + public void start() { this.start("/"); } + public void handle(){ + + } + public Config config(){ return config; } @@ -723,6 +616,10 @@ public Bootstrap bootstrap(){ return bootstrap; } + public Render render() { + return render; + } + /** * @return 返回是否启用XSS防御 */ @@ -743,4 +640,9 @@ public T plugin(Class pluginClazz){ } return (T) object; } + + public Blade routeConf(String conf) { + + return this; + } } diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 8775a90aa..eb31fe8e4 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -20,14 +20,13 @@ import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.blade.route.RouteMatcherBuilder; +import com.blade.context.BladeWebContext; import blade.kit.TaskKit; import blade.kit.log.Logger; @@ -48,10 +47,10 @@ public class CoreFilter implements Filter { */ private static final String BOOSTRAP_CLASS = "bootstrapClass"; - static ServletContext servletContext; - private Blade blade; + private ActionHandler filterHandler; + @Override public void init(FilterConfig filterConfig) throws ServletException { @@ -71,16 +70,15 @@ public void init(FilterConfig filterConfig) throws ServletException { blade.app(bootstrap); // 构建路由 - RouteMatcherBuilder.building(blade); +// RouteMatcherBuilder.building(blade); IocApplication.init(blade); - servletContext = filterConfig.getServletContext(); - bootstrap.contextInitialized(); blade.setInit(true); + filterHandler = new ActionHandler(blade); LOGGER.info("blade init complete!"); } } catch (Exception e) { @@ -126,7 +124,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha /** * 是否被RequestHandler执行 */ - boolean isHandler = new FilterHandler(blade).handle(httpRequest, httpResponse); + boolean isHandler = filterHandler.handle(httpRequest, httpResponse); if(!isHandler){ chain.doFilter(httpRequest, httpResponse); } diff --git a/blade-core/src/main/java/com/blade/FilterHandler.java b/blade-core/src/main/java/com/blade/FilterHandler.java deleted file mode 100644 index f18db9016..000000000 --- a/blade-core/src/main/java/com/blade/FilterHandler.java +++ /dev/null @@ -1,333 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.lang.reflect.Method; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.blade.ioc.Container; -import com.blade.ioc.Scope; -import com.blade.ioc.impl.DefaultContainer; -import com.blade.render.ModelAndView; -import com.blade.route.HttpMethod; -import com.blade.route.RouteHandler; -import com.blade.route.RouteMatcher; -import com.blade.route.impl.DefaultRouteMatcher; -import com.blade.servlet.Request; -import com.blade.servlet.Response; -import com.blade.servlet.wrapper.RequestResponseBuilder; -import com.blade.servlet.wrapper.RequestWrapper; -import com.blade.servlet.wrapper.ResponseWrapper; - -import blade.exception.BladeException; -import blade.kit.PathKit; -import blade.kit.ReflectKit; -import blade.kit.base.ThrowableKit; -import blade.kit.log.Logger; - -/** - * 请求执行的Handler - *

- * 拦截器所有blade的请求,处理route and interceptor - *

- * - * @author biezhi - * @since 1.0 - */ -public class FilterHandler { - - private static final Logger LOGGER = Logger.getLogger(FilterHandler.class); - - private Blade blade; - - /** - * 服务器500错误时返回的HTML - */ - - private static final String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " - + Blade.VERSION +"
"; - - /** - * IOC容器 - */ - private final static Container container = DefaultContainer.single(); - - /** - * 路由处理器,查找请求过来的URL - */ - private static final DefaultRouteMatcher DEFAULT_ROUTE_MATCHER = DefaultRouteMatcher.instance(); - - public FilterHandler(Blade blade){ - this.blade = blade; - } - - /** - * handler执行方法 - * - * @param httpRequest HttpServletRequest请求对象 - * @param httpResponse HttpServletResponse响应对象 - * @return 是否拦截到请求 - */ - boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ - - // http方法, GET/POST ... - String method = httpRequest.getMethod(); - - // 请求的uri - String uri = PathKit.getRelativePath(httpRequest); - - // 如果是静态资源则交给filter处理 - if(null != blade.staticFolder() && blade.staticFolder().length > 0){ - if(!filterStaticFolder(uri)){ - return false; - } - } - - if(blade.debug()){ - LOGGER.debug("Request : " + method + "\t" + uri); - } - - // 创建RequestWrapper And RequestWrapper - RequestWrapper requestWrapper = new RequestWrapper(); - ResponseWrapper responseWrapper = new ResponseWrapper(); - - // 构建一个包装后的response - Response response = RequestResponseBuilder.build(httpResponse); - - // 初始化context - BladeWebContext.setContext(CoreFilter.servletContext, httpRequest, httpResponse, requestWrapper, responseWrapper); - - HttpMethod httpMethod = HttpMethod.valueOf(method); - - Object result = null; - try { - responseWrapper.setDelegate(response); - - // 查找用户请求的uri - RouteMatcher match = DEFAULT_ROUTE_MATCHER.findRoute(httpMethod, uri); - // 如果找到 - if (match != null) { - // 执行before拦截 - result = intercept(httpRequest, requestWrapper, responseWrapper, uri, HttpMethod.BEFORE); - if(result instanceof Boolean){ - boolean isHandler = (Boolean) result; - if(!isHandler){ - return false; - } - } - - if(result instanceof String){ - String res = result.toString(); - if(res.startsWith("redirect.")){ - response.go(res.substring(9)); - } else { - render(responseWrapper, res); - } - return true; - } - - if(result instanceof ModelAndView){ - render(responseWrapper, result); - return true; - } - - // 实际执行方法 - responseWrapper.setDelegate(response); - result = realHandler(httpRequest, requestWrapper, responseWrapper, match); - - // 执行after拦截 - responseWrapper.setDelegate(response); - intercept(httpRequest, requestWrapper, responseWrapper, uri, HttpMethod.AFTER); - - if (null != result) - render(responseWrapper, result); - return true; - } - - // 没有找到 - response.render404(uri); - return true; - } catch (BladeException bex) { - - String error = ThrowableKit.getStackTraceAsString(bex); - LOGGER.error(error); - ThrowableKit.propagate(bex); - - httpResponse.setStatus(500); - // 写入内容到浏览器 - if (!httpResponse.isCommitted()) { - response.render500(INTERNAL_ERROR); - return true; - } - } catch (Exception e) { - String error = ThrowableKit.getStackTraceAsString(e); - LOGGER.error(error); - ThrowableKit.propagate(e); - - httpResponse.setStatus(500); - // 写入内容到浏览器 - if (!httpResponse.isCommitted()) { - response.render500(INTERNAL_ERROR); - return true; - } - } - return false; - - } - - /** - * - * 实际的路由方法执行 - * @param httpRequest http请求对象 - * @param requestWrapper request包装对象 - * @param responseWrapper response包装对象 - * @param match 路由匹配对象 - * @return object - */ - private Object realHandler(HttpServletRequest httpRequest, RequestWrapper requestWrapper, ResponseWrapper responseWrapper, RouteMatcher match){ - Object result = null; - RouteHandler router = match.getRouterHandler(); - - if (requestWrapper.getDelegate() == null) { - Request request = RequestResponseBuilder.build(match, httpRequest); - requestWrapper.setDelegate(request); - } else { - requestWrapper.initRequest(match); - } - - // 初始化context - BladeWebContext.setContext(CoreFilter.servletContext, httpRequest, responseWrapper.servletResponse(), requestWrapper, responseWrapper); - - if(null != router){ - - result = router.handle(requestWrapper, responseWrapper); - - } else { - Class target = match.getTarget(); - - Object targetObject = container.getBean(target, Scope.SINGLE); - - // 要执行的路由方法 - Method execMethod = match.getExecMethod(); - - // 执行route方法 - result = executeMethod(targetObject, execMethod, requestWrapper, responseWrapper); - } - - return result; - } - - /** - * 拦截器事件 - * - * @param httpRequest HttpServletRequest请求对象,用于构建Request - * @param requestWrapper RequestWrapper对象,包装了Request对象 - * @param responseWrapper ResponseWrapper对象,包装了Response对象 - * @param uri 请求的URI - */ - private Object intercept(HttpServletRequest httpRequest, RequestWrapper requestWrapper, - ResponseWrapper responseWrapper, String uri, HttpMethod httpMethod){ - List matchSet = DEFAULT_ROUTE_MATCHER.findInterceptor(httpMethod, uri); - - for (RouteMatcher filterMatch : matchSet) { - Object object = realHandler(httpRequest, requestWrapper, responseWrapper, filterMatch); - if(null != object){ - return object; - } - } - - return true; - } - - /** - * 获取方法内的参数 - * - * @param request Request对象,用于注入到method参数列表中 - * @param response Response对象,用于注入到method参数列表中 - * @param params params参数列表 - * @return 返回生成后的参数数组 - */ - private Object[] getArgs(Request request, Response response, Class[] params){ - - int len = params.length; - Object[] args = new Object[len]; - - for(int i=0; i paramTypeClazz = params[i]; - if(paramTypeClazz.getName().equals(Request.class.getName())){ - args[i] = request; - } - if(paramTypeClazz.getName().equals(Response.class.getName())){ - args[i] = response; - } - } - - return args; - } - - /** - * 执行路由方法 - * @param object 方法的实例,即该方法所在类的对象 - * @param method 要执行的method - * @param request Request对象,作为参数注入 - * @param response Response对象,作为参数注入 - * @return 返回方法执行后的返回值 - */ - private Object executeMethod(Object object, Method method, RequestWrapper requestWrapper, ResponseWrapper responseWrapper){ - int len = method.getParameterTypes().length; - method.setAccessible(true); - if(len > 0){ - Object[] args = getArgs(requestWrapper, responseWrapper, method.getParameterTypes()); - return ReflectKit.invokeMehod(object, method, args); - } else { - return ReflectKit.invokeMehod(object, method); - } - } - - /** - * 渲染视图 - * - * @param response - * @param result - * @return - */ - private void render(Response response, Object result){ - if(result instanceof String){ - response.render(result.toString()); - } else if(result instanceof ModelAndView){ - response.render( (ModelAndView) result ); - } - } - - /** - * 要过滤掉的目录 - * @param uri - * @return - */ - private boolean filterStaticFolder(String uri){ - int len = blade.staticFolder().length; - for(int i=0; i PLUGINS = CollectionKit.newArrayList(); - /** - * 存放路由类 - */ - static final List> ROUTE_CLASS_LIST = CollectionKit.newArrayList(); public static void init(Blade blade){ @@ -71,19 +65,7 @@ public static void init(Blade blade){ initIOC(blade.iocs()); // 初始化注入 - try { - container.initWired(); - - for(Class clazz : ROUTE_CLASS_LIST){ - Object object = ReflectKit.newInstance(clazz); - if(null != object){ - container.injection(object); - ReflectKit.invokeMehodByName(object, "run"); - } - } - } catch (Exception e) { - LOGGER.error(e); - } + container.initWired(); } @@ -112,9 +94,6 @@ public static T getPlugin(Class pluginClazz){ return container.getBean(pluginClazz, Scope.SINGLE); } - public static void addRouteClass(Class clazz){ - ROUTE_CLASS_LIST.add(clazz); - } /** * 注册一个包下的所有对象 * diff --git a/blade-core/src/main/java/com/blade/annotation/Route.java b/blade-core/src/main/java/com/blade/annotation/Route.java index 430a9690e..b73c48183 100644 --- a/blade-core/src/main/java/com/blade/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/annotation/Route.java @@ -20,7 +20,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import com.blade.route.HttpMethod; +import com.blade.http.HttpMethod; /** * 方法上定义的路由注解 diff --git a/blade-core/src/main/java/com/blade/BladeWebContext.java b/blade-core/src/main/java/com/blade/context/BladeWebContext.java similarity index 60% rename from blade-core/src/main/java/com/blade/BladeWebContext.java rename to blade-core/src/main/java/com/blade/context/BladeWebContext.java index e7317d287..595ecc217 100644 --- a/blade-core/src/main/java/com/blade/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/context/BladeWebContext.java @@ -13,17 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade; +package com.blade.context; import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import com.blade.servlet.Request; -import com.blade.servlet.Response; +import com.blade.http.Request; +import com.blade.http.Response; import com.blade.servlet.Session; -import com.blade.servlet.wrapper.RequestWrapper; -import com.blade.servlet.wrapper.ResponseWrapper; /** * 全局的WeContext @@ -42,8 +38,6 @@ public final class BladeWebContext { * ServletContext对象,在应用初始化时创建 */ private ServletContext context; - private HttpServletRequest httpServletRequest; - private HttpServletResponse httpServletResponse; private Request request; private Response response; @@ -53,13 +47,11 @@ public static BladeWebContext me(){ return BLADE_WEB_CONTEXT.get(); } - static void setContext(ServletContext servletContext, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, RequestWrapper request, ResponseWrapper response) { + public static void setContext(Request request, Response response) { BladeWebContext bladeWebContext = new BladeWebContext(); - bladeWebContext.context = servletContext; - bladeWebContext.httpServletRequest = httpServletRequest; - bladeWebContext.httpServletResponse = httpServletResponse; - bladeWebContext.request = request.getDelegate(); - bladeWebContext.response = response.getDelegate(); + bladeWebContext.request = request; + bladeWebContext.context = request.context(); + bladeWebContext.response = response; BLADE_WEB_CONTEXT.set(bladeWebContext); } @@ -86,26 +78,10 @@ public static ServletContext servletContext() { return BladeWebContext.me().context; } - public static HttpServletResponse servletResponse() { - return BladeWebContext.me().httpServletResponse; - } - - public static HttpServletRequest servletRequest() { - return BladeWebContext.me().httpServletRequest; - } - public ServletContext getContext() { return context; } - public HttpServletRequest getHttpServletRequest() { - return httpServletRequest; - } - - public HttpServletResponse getHttpServletResponse() { - return httpServletResponse; - } - public Request getRequest() { return request; } diff --git a/blade-core/src/main/java/com/blade/exception/ExceptionHandler.java b/blade-core/src/main/java/com/blade/exception/ExceptionHandler.java deleted file mode 100644 index 26f461e77..000000000 --- a/blade-core/src/main/java/com/blade/exception/ExceptionHandler.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.blade.exception; - -import com.blade.servlet.Request; -import com.blade.servlet.Response; - -public interface ExceptionHandler { - - void handle(Exception e, Request request, Response response); - -} diff --git a/blade-core/src/main/java/com/blade/exception/WebApplicationException.java b/blade-core/src/main/java/com/blade/exception/WebApplicationException.java deleted file mode 100644 index 3e398a422..000000000 --- a/blade-core/src/main/java/com/blade/exception/WebApplicationException.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.blade.exception; - -public class WebApplicationException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - protected int status; - - protected String name; - - public WebApplicationException(int status, String name) { - this.status = status; - this.name = name; - } - - public WebApplicationException(int status, String name, String message) { - super(message); - this.status = status; - this.name = name; - } - - public WebApplicationException(int status, String name, Throwable cause) { - super(cause); - this.status = status; - this.name = name; - } - - public WebApplicationException(int status, String name, String message, Throwable cause) { - super(message, cause); - this.status = status; - this.name = name; - } - - public static long getSerialversionuid() { - return serialVersionUID; - } - - public int getStatus() { - return status; - } - - public String getName() { - return name; - } -} diff --git a/blade-core/src/main/java/com/blade/http/HttpException.java b/blade-core/src/main/java/com/blade/http/HttpException.java new file mode 100644 index 000000000..74f0c04aa --- /dev/null +++ b/blade-core/src/main/java/com/blade/http/HttpException.java @@ -0,0 +1,23 @@ +package com.blade.http; + +public class HttpException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public HttpException() { + super(); + } + + public HttpException(String message, Throwable throwable) { + super(message, throwable); + } + + public HttpException(String message) { + super(message); + } + + public HttpException(Throwable throwable) { + super(throwable); + } + +} diff --git a/blade-core/src/main/java/com/blade/route/HttpMethod.java b/blade-core/src/main/java/com/blade/http/HttpMethod.java similarity index 97% rename from blade-core/src/main/java/com/blade/route/HttpMethod.java rename to blade-core/src/main/java/com/blade/http/HttpMethod.java index 351e648c4..7d2d6596a 100644 --- a/blade-core/src/main/java/com/blade/route/HttpMethod.java +++ b/blade-core/src/main/java/com/blade/http/HttpMethod.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route; +package com.blade.http; /** * HTTP请求方法 diff --git a/blade-core/src/main/java/com/blade/http/HttpStatus.java b/blade-core/src/main/java/com/blade/http/HttpStatus.java new file mode 100644 index 000000000..8f3b0b8d3 --- /dev/null +++ b/blade-core/src/main/java/com/blade/http/HttpStatus.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.http; + +/** + * HTTP状态码 + * + * @author biezhi + * @since 1.0 + */ +public final class HttpStatus { + + public static final int OK = 200; + public static final int CREATED = 201; + public static final int ACCEPTED = 202; + public static final int PARTIAL_INFO = 203; + public static final int NO_RESPONSE = 204; + public static final int MOVED = 301; + public static final int FOUND = 302; + public static final int METHOD = 303; + public static final int NOT_MODIFIED = 304; + public static final int BAD_REQUEST = 400; + public static final int UNAUTHORIZED = 401; + public static final int PAYMENT_REQUIRED = 402; + public static final int FORBIDDEN = 403; + public static final int NOT_FOUND = 404; + public static final int CONFLICT = 409; + public static final int INTERNAL_ERROR = 500; + public static final int NOT_IMPLEMENTED = 501; + public static final int OVERLOADED = 502; + public static final int GATEWAY_TIMEOUT = 503; + +} diff --git a/blade-core/src/main/java/com/blade/render/RenderFactory.java b/blade-core/src/main/java/com/blade/http/Path.java similarity index 60% rename from blade-core/src/main/java/com/blade/render/RenderFactory.java rename to blade-core/src/main/java/com/blade/http/Path.java index 3a22a95d5..7ca5352aa 100644 --- a/blade-core/src/main/java/com/blade/render/RenderFactory.java +++ b/blade-core/src/main/java/com/blade/http/Path.java @@ -1,47 +1,42 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.render; - -/** - * 渲染引擎工厂 - * - * @author biezhi - * @since 1.0 - */ -public final class RenderFactory { - - // 默认JSP引擎 - private static Render render = JspRender.single(); - - private RenderFactory() { - } - - /** - * 设置一个渲染对象 - * @param render 渲染器引擎 - */ - public static void init(Render render){ - RenderFactory.render = render; - } - - /** - * @return 返回渲染器引擎 - */ - public static Render getRender(){ - return RenderFactory.render; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.http; + +/** + * PATH处理 + * + * @author biezhi + * @since 1.0 + */ +public class Path { + + public static final String VAR_REGEXP = ":(\\w+)"; + public static final String VAR_REPLACE = "([^#/?]+)"; + + public static String fixPath(String path) { + if (path == null) { + return "/"; + } + if (!path.startsWith("/")) { + path = "/" + path; + } + if (path.length() > 1 && path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + return path; + } + +} diff --git a/blade-core/src/main/java/com/blade/http/Request.java b/blade-core/src/main/java/com/blade/http/Request.java new file mode 100644 index 000000000..2e00c01c7 --- /dev/null +++ b/blade-core/src/main/java/com/blade/http/Request.java @@ -0,0 +1,113 @@ +package com.blade.http; + +import java.io.InputStream; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletContext; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; + +import com.blade.route.Route; +import com.blade.servlet.Session; +import com.blade.servlet.multipart.FileItem; + +public interface Request { + + HttpServletRequest raw(); + + void initPathParams(String routePath); + + String host(); + + String url(); + + String path(); + + String userAgent(); + + String pathInfo(); + + String protocol(); + + String servletPath(); + + String contextPath(); + + ServletContext context(); + + Map pathParams(); + + String param(String name); + + Integer paramAsInt(String name); + + Long paramAsLong(String name); + + Boolean paramAsBoolean(String name); + + String queryString(); + + Map querys(); + + String query(String name); + + Integer queryAsInt(String name); + + Long queryAsLong(String name); + + Boolean queryAsBoolean(String name); + + Float queryAsFloat(String name); + + Double queryAsDouble(String name); + + String method(); + + HttpMethod httpMethod(); + + String address(); + + Session session(); + + Session session(boolean create); + + String contentType(); + + int port(); + + boolean isSecure(); + + boolean isAjax(); + + Map cookies(); + + String cookie(String name); + + Cookie cookieRaw(String name); + + Map headers(); + + String header(String name); + + void encoding(String encoding); + + void attribute(String name, Object value); + + Object attribute(String name); + + Set attributes(); + + FileItem[] files(); + + BodyParser body(); + + void setRoute(Route route); + + interface BodyParser { + String asString(); + InputStream asInputStream(); + byte[] asByte(); + } + +} diff --git a/blade-core/src/main/java/com/blade/http/Response.java b/blade-core/src/main/java/com/blade/http/Response.java new file mode 100644 index 000000000..fd07675dd --- /dev/null +++ b/blade-core/src/main/java/com/blade/http/Response.java @@ -0,0 +1,74 @@ +package com.blade.http; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import com.blade.render.ModelAndView; + +public interface Response { + + HttpServletResponse raw(); + + int status(); + + Response status(int status); + + Response badRequest(); + + Response unauthorized(); + + Response notFound(); + + Response conflict(); + + String contentType(); + + Response contentType(String contentType); + + String header(String name); + + Response header(String name, String value); + + Response cookie(Cookie cookie); + + Response cookie(String name, String value); + + Response cookie(String name, String value, int maxAge); + + Response cookie(String name, String value, int maxAge, boolean secured); + + Response cookie(String path, String name, String value, int maxAge, boolean secured); + + Response removeCookie(Cookie cookie); + + Response removeCookie(String name); + + Map attributes(); + + Response attribute(String name, Object object); + + Response text(String output); + + Response html(String output); + + Response json(String output); + + Response xml(String output); + + ServletOutputStream outputStream() throws IOException; + + Response render(String view) ; + + Response render(ModelAndView modelAndView) ; + + void redirect(String path); + + void go(String path); + + boolean isWritten(); + +} diff --git a/blade-core/src/main/java/com/blade/ioc/impl/AbstractBeanFactory.java b/blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java similarity index 90% rename from blade-core/src/main/java/com/blade/ioc/impl/AbstractBeanFactory.java rename to blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java index 404bc4bdb..483d75568 100644 --- a/blade-core/src/main/java/com/blade/ioc/impl/AbstractBeanFactory.java +++ b/blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java @@ -13,15 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.ioc.impl; +package com.blade.ioc; import java.lang.annotation.Annotation; import java.util.Collection; import java.util.List; import java.util.Set; -import com.blade.ioc.Container; - import blade.kit.log.Logger; /** @@ -34,7 +32,7 @@ public abstract class AbstractBeanFactory { private static final Logger LOGGER = Logger.getLogger(AbstractBeanFactory.class); - protected Container container = DefaultContainer.single(); + protected Container container = SampleContainer.single(); public abstract Object getBean(String className); diff --git a/blade-core/src/main/java/com/blade/ioc/impl/PrototypeBean.java b/blade-core/src/main/java/com/blade/ioc/PrototypeBean.java similarity index 91% rename from blade-core/src/main/java/com/blade/ioc/impl/PrototypeBean.java rename to blade-core/src/main/java/com/blade/ioc/PrototypeBean.java index 4963132fb..9821e4ee5 100644 --- a/blade-core/src/main/java/com/blade/ioc/impl/PrototypeBean.java +++ b/blade-core/src/main/java/com/blade/ioc/PrototypeBean.java @@ -13,9 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.ioc.impl; - -import com.blade.ioc.Scope; +package com.blade.ioc; /** * 原生bean对象 diff --git a/blade-core/src/main/java/com/blade/ioc/impl/DefaultContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java similarity index 96% rename from blade-core/src/main/java/com/blade/ioc/impl/DefaultContainer.java rename to blade-core/src/main/java/com/blade/ioc/SampleContainer.java index 8509d0f4e..534ecf7bf 100644 --- a/blade-core/src/main/java/com/blade/ioc/impl/DefaultContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.ioc.impl; +package com.blade.ioc; import java.lang.annotation.Annotation; import java.lang.reflect.Field; @@ -28,8 +28,6 @@ import com.blade.annotation.Component; import com.blade.annotation.Inject; import com.blade.annotation.Path; -import com.blade.ioc.Container; -import com.blade.ioc.Scope; import blade.exception.BladeException; import blade.kit.CloneKit; @@ -44,9 +42,9 @@ * @since 1.0 */ @SuppressWarnings("unchecked") -public class DefaultContainer implements Container { +public class SampleContainer implements Container { - private static final Logger LOGGER = Logger.getLogger(DefaultContainer.class); + private static final Logger LOGGER = Logger.getLogger(SampleContainer.class); /** * 保存所有bean对象 @@ -58,15 +56,15 @@ public class DefaultContainer implements Container { */ private static final Map, List> ANNOTATION_CONTAINER = CollectionKit.newConcurrentHashMap(); - private DefaultContainer() { + private SampleContainer() { } - public static DefaultContainer single() { + public static SampleContainer single() { return DefaultContainerHoder.single; } private static class DefaultContainerHoder { - private static final DefaultContainer single = new DefaultContainer(); + private static final SampleContainer single = new SampleContainer(); } public Map getBeanMap() { diff --git a/blade-core/src/main/java/com/blade/ioc/impl/SingleBean.java b/blade-core/src/main/java/com/blade/ioc/SingleBean.java similarity index 91% rename from blade-core/src/main/java/com/blade/ioc/impl/SingleBean.java rename to blade-core/src/main/java/com/blade/ioc/SingleBean.java index a4d24678e..be60db8b1 100644 --- a/blade-core/src/main/java/com/blade/ioc/impl/SingleBean.java +++ b/blade-core/src/main/java/com/blade/ioc/SingleBean.java @@ -13,9 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.ioc.impl; - -import com.blade.ioc.Scope; +package com.blade.ioc; /** * 单例bean对象,容器中只存在一个bean实例 diff --git a/blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java b/blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java new file mode 100644 index 000000000..8cb60ecc9 --- /dev/null +++ b/blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java @@ -0,0 +1,195 @@ +package com.blade.loader; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.Method; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import com.blade.http.HttpMethod; +import com.blade.http.Request; +import com.blade.http.Response; +import com.blade.route.Route; +import com.blade.route.RoutesException; + +public abstract class AbstractFileRoutesLoader implements RoutesLoader { + + private ControllerLoader controllerLoader = new ClassPathControllerLoader(); + + @Override + public List load() throws ParseException, RoutesException { + InputStream inputStream = null; + try { + inputStream = getInputStream(); + } catch (Exception e) { + throw new RoutesException("Problem loading the routes.config file: " + e.getMessage(), e); + } + + try { + return load(inputStream); + } catch (IOException e) { + throw new RoutesException("Problem loading the routes.config file: " + e.getMessage(), e); + } + } + + private List load(InputStream inputStream) throws ParseException, IOException { + int line = 0; // reset line positioning + List routes = new ArrayList(); // this is what we will fill and return + + BufferedReader in = null; + try { + in = new BufferedReader(new InputStreamReader(inputStream)); + + String input; + while ( (input = in.readLine()) != null ) { + line++; + + input = input.trim(); + + // only parse line if it is not empty and not a comment + if (!input.equals("") && !input.startsWith("#")) { + Route route = parse(input, line); + routes.add(route); + } + } + + } finally { + closeResource(in); + } + + return routes; + } + + private Route parse(String input, int line) throws ParseException { + StringTokenizer st = new StringTokenizer(input, " \t"); + if (st.countTokens() != 3) { + throw new ParseException("Unrecognized format", line); + } + + // retrieve and validate the three arguments + String httpMethod = validateHttpMethod( st.nextToken().trim(), line ); + String path = validatePath( st.nextToken().trim(), line ); + String controllerAndMethod = validateControllerAndMethod( st.nextToken().trim(), line ); + + // retrieve controller name + int hashPos = controllerAndMethod.indexOf('#'); + String controllerName = controllerAndMethod.substring(0, hashPos); + + // retrieve controller method + String controllerMethod = controllerAndMethod.substring(hashPos + 1); + + return buildRoute(httpMethod, path, controllerName, controllerMethod); + } + + private String validateHttpMethod(String httpMethod, int line) throws ParseException { + if (!httpMethod.equalsIgnoreCase("GET") && + !httpMethod.equalsIgnoreCase("POST") && + !httpMethod.equalsIgnoreCase("PUT") && + !httpMethod.equalsIgnoreCase("DELETE")) { + + throw new ParseException("Unrecognized HTTP method: " + httpMethod, line); + } + + return httpMethod; + } + + private String validatePath(String path, int line) throws ParseException { + if (!path.startsWith("/")) { + throw new ParseException("Path must start with '/'", line); + } + + boolean openedKey = false; + for (int i=0; i < path.length(); i++) { + + boolean validChar = isValidCharForPath(path.charAt(i), openedKey); + if (!validChar) { + throw new ParseException(path, i); + } + + if (path.charAt(i) == '{') { + openedKey = true; + } + + if (path.charAt(i) == '}') { + openedKey = false; + } + + } + + return path; + } + + private boolean isValidCharForPath(char c, boolean openedKey) { + char[] invalidChars = { '?', '#', ' ' }; + for (char invalidChar : invalidChars) { + if (c == invalidChar) { + return false; + } + } + + if (openedKey) { + char[] moreInvalidChars = { '/', '{' }; + for (char invalidChar : moreInvalidChars) { + if (c == invalidChar) { + return false; + } + } + } + + return true; + } + + private String validateControllerAndMethod(String beanAndMethod, int line) throws ParseException { + int hashPos = beanAndMethod.indexOf('#'); + if (hashPos == -1) { + throw new ParseException("Unrecognized format for '" + beanAndMethod + "'", line); + } + + return beanAndMethod; + } + + private Route buildRoute(String httpMethod, String path, String controllerName, String methodName) throws RoutesException { + Object controller = controllerLoader.load(controllerName); + Method method = getMethod(controller, methodName); + + return new Route(HttpMethod.valueOf(httpMethod.toUpperCase()), path, controller, method); + } + + private Method getMethod(Object controller, String methodName) throws RoutesException { + try { + // try to retrieve the method and check if an exception is thrown + return controller.getClass().getMethod(methodName, Request.class, Response.class); + } catch (Exception e) { + throw new RoutesException(e); + } + } + + private void closeResource(Reader reader) { + if (reader != null) { + try { + reader.close(); + } catch (Exception e) { + } + } + } + + protected abstract InputStream getInputStream() throws Exception; + + public void setBasePackage(String basePackage) { + this.controllerLoader = new ClassPathControllerLoader(basePackage); + } + + public ControllerLoader getControllerLoader() { + return controllerLoader; + } + + public void setControllerLoader(ControllerLoader controllerLoader) { + this.controllerLoader = controllerLoader; + } + +} diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java new file mode 100644 index 000000000..725dc4ca9 --- /dev/null +++ b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java @@ -0,0 +1,54 @@ +package com.blade.loader; + +import com.blade.route.RoutesException; + +public class ClassPathControllerLoader implements ControllerLoader { + + private String basePackage; + + private ClassLoader classLoader = ClassPathControllerLoader.class.getClassLoader(); + + public ClassPathControllerLoader() { + this(""); + } + + public ClassPathControllerLoader(String basePackage) { + this.basePackage = basePackage; + + if (this.basePackage != null && !"".equals(this.basePackage)) { + if (!this.basePackage.endsWith(".")) { + this.basePackage += "."; + } + } + } + + @Override + public Object load(String controllerName) throws RoutesException { + String className = basePackage + controllerName; + + try { + // load the controller class and instantiate it + Class controllerClass = classLoader.loadClass(className); + return controllerClass.newInstance(); + } catch (Exception e) { + throw new RoutesException(e); + } + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + +} diff --git a/blade-core/src/main/java/com/blade/Config.java b/blade-core/src/main/java/com/blade/loader/Config.java similarity index 99% rename from blade-core/src/main/java/com/blade/Config.java rename to blade-core/src/main/java/com/blade/loader/Config.java index 03be192a4..b1faee8a1 100644 --- a/blade-core/src/main/java/com/blade/Config.java +++ b/blade-core/src/main/java/com/blade/loader/Config.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade; +package com.blade.loader; import java.util.Arrays; import java.util.List; diff --git a/blade-core/src/main/java/com/blade/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java similarity index 96% rename from blade-core/src/main/java/com/blade/Configurator.java rename to blade-core/src/main/java/com/blade/loader/Configurator.java index ff20d1331..ecccffaea 100644 --- a/blade-core/src/main/java/com/blade/Configurator.java +++ b/blade-core/src/main/java/com/blade/loader/Configurator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade; +package com.blade.loader; import java.util.Map; diff --git a/blade-core/src/main/java/com/blade/loader/ControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ControllerLoader.java new file mode 100644 index 000000000..31e9bc106 --- /dev/null +++ b/blade-core/src/main/java/com/blade/loader/ControllerLoader.java @@ -0,0 +1,9 @@ +package com.blade.loader; + +import com.blade.route.RoutesException; + +public interface ControllerLoader { + + Object load(String controllerName) throws RoutesException; + +} diff --git a/blade-core/src/main/java/com/blade/loader/FileSystemRoutesLoader.java b/blade-core/src/main/java/com/blade/loader/FileSystemRoutesLoader.java new file mode 100644 index 000000000..f1a459787 --- /dev/null +++ b/blade-core/src/main/java/com/blade/loader/FileSystemRoutesLoader.java @@ -0,0 +1,34 @@ +package com.blade.loader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +public class FileSystemRoutesLoader extends AbstractFileRoutesLoader { + + private File file; + + public FileSystemRoutesLoader() { + } + + public FileSystemRoutesLoader(String filePath) { + this(new File(filePath)); + } + + public FileSystemRoutesLoader(File file) { + this.file = file; + } + + @Override + protected InputStream getInputStream() throws Exception { + return new FileInputStream(file); + } + + public void setFile(File file) { + this.file = file; + } + + public void setFilePath(String filePath) { + this.file = new File(filePath); + } +} diff --git a/blade-core/src/main/java/com/blade/loader/RoutesLoader.java b/blade-core/src/main/java/com/blade/loader/RoutesLoader.java new file mode 100644 index 000000000..a9269ee70 --- /dev/null +++ b/blade-core/src/main/java/com/blade/loader/RoutesLoader.java @@ -0,0 +1,13 @@ +package com.blade.loader; + +import java.text.ParseException; +import java.util.List; + +import com.blade.route.Route; +import com.blade.route.RoutesException; + +public interface RoutesLoader { + + List load() throws ParseException, RoutesException; + +} diff --git a/blade-core/src/main/java/com/blade/loader/SpringControllerLoader.java b/blade-core/src/main/java/com/blade/loader/SpringControllerLoader.java new file mode 100644 index 000000000..11d82dc6d --- /dev/null +++ b/blade-core/src/main/java/com/blade/loader/SpringControllerLoader.java @@ -0,0 +1,27 @@ +package com.blade.loader; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +import com.blade.route.RoutesException; + +public class SpringControllerLoader implements ControllerLoader, ApplicationContextAware { + + private ApplicationContext applicationContext; + + @Override + public Object load(String controllerName) throws RoutesException { + Object bean = applicationContext.getBean(controllerName); + if (bean == null) { + throw new RoutesException("Bean '" + controllerName + "' was not found."); + } + return bean; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + +} diff --git a/blade-core/src/main/java/com/blade/render/JspRender.java b/blade-core/src/main/java/com/blade/render/JspRender.java index 6c17b9706..9ec74af25 100644 --- a/blade-core/src/main/java/com/blade/render/JspRender.java +++ b/blade-core/src/main/java/com/blade/render/JspRender.java @@ -16,6 +16,7 @@ package com.blade.render; import java.io.IOException; +import java.io.Writer; import java.util.Map; import java.util.Set; @@ -23,7 +24,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.blade.BladeWebContext; +import com.blade.context.BladeWebContext; import blade.kit.log.Logger; @@ -33,72 +34,35 @@ * @author biezhi * @since 1.0 */ -public final class JspRender extends Render { +public final class JspRender implements Render { private static final Logger LOGGER = Logger.getLogger(JspRender.class); - private JspRender() { - } - - /** - * 视图渲染 - */ - public Object render(final String view){ - try { - HttpServletRequest servletRequest = BladeWebContext.servletRequest(); - HttpServletResponse servletResponse = BladeWebContext.servletResponse(); - - // 设置编码 - servletRequest.setCharacterEncoding(blade.encoding()); - servletResponse.setCharacterEncoding(blade.encoding()); - - // 构造jsp地址 - String realPath = disposeView(view); - - // 跳转到页面 - servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); - - } catch (ServletException e) { - LOGGER.error(e); - } catch (IOException e) { - LOGGER.error(e); - } - return null; - } - - /** - * ModelAndView渲染 - */ - public Object render(ModelAndView modelAndView){ - try { - HttpServletRequest servletRequest = BladeWebContext.servletRequest(); - HttpServletResponse servletResponse = BladeWebContext.servletResponse(); - - String realPath = disposeView(modelAndView.getView()); - - Map model = modelAndView.getModel(); + @Override + public void render(ModelAndView modelAndView, Writer writer) { + HttpServletRequest servletRequest = BladeWebContext.request().raw(); + HttpServletResponse servletResponse = BladeWebContext.response().raw(); + + Map model = modelAndView.getModel(); - if (null != model && !model.isEmpty()) { - Set keys = model.keySet(); - for (String key : keys) { - servletRequest.setAttribute(key, model.get(key)); - } + String viewPath = modelAndView.getView(); + + if (null != model && !model.isEmpty()) { + Set keys = model.keySet(); + for (String key : keys) { + servletRequest.setAttribute(key, model.get(key)); } - servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); + } + try { + servletRequest.getRequestDispatcher(viewPath).forward(servletRequest, servletResponse); } catch (ServletException e) { + e.printStackTrace(); LOGGER.error(e); } catch (IOException e) { + e.printStackTrace(); LOGGER.error(e); } - return null; + } - - public static JspRender single() { - return JspRenderHolder.single; - } - - private static class JspRenderHolder { - private static final JspRender single = new JspRender(); - } } diff --git a/blade-core/src/main/java/com/blade/render/Render.java b/blade-core/src/main/java/com/blade/render/Render.java index d7d830a0f..6b880e206 100644 --- a/blade-core/src/main/java/com/blade/render/Render.java +++ b/blade-core/src/main/java/com/blade/render/Render.java @@ -1,264 +1,14 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.render; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.blade.Blade; -import com.blade.BladeWebContext; -import com.blade.servlet.Response; - -import blade.kit.log.Logger; -/** - * 渲染器抽象类 - * - * @author biezhi - * @since 1.0 - */ -public abstract class Render { - - private static final Logger LOGGER = Logger.getLogger(Render.class); - - protected Blade blade = Blade.me(); - - static final String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " - + Blade.VERSION +"
"; - - public void render404(String viewName){ - render404(null, viewName); - } - - /** - * 404视图 - * - * @param response Responsee对象 - * @param viewName 视图名称 - */ - public void render404(Response response, String viewName){ - try { - String view404 = blade.view404(); - if(null != view404){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", viewName); - render(modelAndView); - } else { - if(null == response){ - response = BladeWebContext.response(); - } - response.contentType("text/html; charset=utf-8"); - response.status(404); - ServletOutputStream outputStream = response.outputStream(); - outputStream.print(String.format(VIEW_NOTFOUND, viewName)); - outputStream.flush(); - outputStream.close(); - } - } catch (IOException e) { - LOGGER.error(e); - } - } - - /** - * 渲染500视图 - * - * @param bodyContent 错误消息 - */ - public void render500(String bodyContent){ - try { - - String view500 = blade.view500(); - if(null != view500){ - ModelAndView modelAndView = new ModelAndView(view500); - modelAndView.add("body", bodyContent); - render(modelAndView); - } else { - HttpServletResponse httpResponse = BladeWebContext.servletResponse(); - - httpResponse.setContentType("text/html; charset=utf-8"); - ServletOutputStream outputStream = httpResponse.getOutputStream(); - - outputStream.print(bodyContent.toString()); - outputStream.flush(); - outputStream.close(); - } - } catch (IOException e) { - LOGGER.error(e); - } - } - - /** - * 输出json - * - * @param json json内容 - */ - public void json(String json){ - if(null != json){ - HttpServletResponse response = BladeWebContext.servletResponse(); - HttpServletRequest request = BladeWebContext.servletRequest(); - - response.setHeader("Cache-Control", "no-cache"); - String userAgent = request.getHeader("User-Agent"); - if (userAgent.contains("MSIE")) { - response.setContentType("text/html;charset=utf-8"); - } else { - response.setContentType("application/json;charset=utf-8"); - } - try { - request.setCharacterEncoding("utf-8"); - PrintWriter out = response.getWriter(); - out.print(json.toString()); - out.flush(); - out.close(); - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - /** - * 输出text - * @param text text内容 - */ - public void text(String text){ - if(null != text){ - HttpServletResponse response = BladeWebContext.servletResponse(); - HttpServletRequest request = BladeWebContext.servletRequest(); - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/plain;charset=utf-8"); - try { - request.setCharacterEncoding("utf-8"); - PrintWriter out = response.getWriter(); - out.print(text); - out.flush(); - out.close(); - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - /** - * 输出xml - * @param xml xml内容 - */ - public void xml(String xml){ - if(null != xml){ - HttpServletResponse response = BladeWebContext.servletResponse(); - HttpServletRequest request = BladeWebContext.servletRequest(); - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/xml;charset=utf-8"); - try { - request.setCharacterEncoding("utf-8"); - PrintWriter out = response.getWriter(); - out.print(xml); - out.flush(); - out.close(); - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - /** - * 输出HTML - * @param html html内容 - */ - public void html(String html){ - if(null != html){ - HttpServletResponse response = BladeWebContext.servletResponse(); - HttpServletRequest request = BladeWebContext.servletRequest(); - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/html;charset=utf-8"); - try { - request.setCharacterEncoding("utf-8"); - PrintWriter out = response.getWriter(); - out.print(html); - out.flush(); - out.close(); - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - /** - * 输出javascript - * @param javascript js内容 - */ - public void javascript(String javascript){ - if(null != javascript){ - HttpServletResponse response = BladeWebContext.servletResponse(); - HttpServletRequest request = BladeWebContext.servletRequest(); - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/javascript;charset=utf-8"); - try { - request.setCharacterEncoding("utf-8"); - PrintWriter out = response.getWriter(); - out.print(javascript); - out.flush(); - out.close(); - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - /** - * 处理视图 - * @param view 视图名称 - * @return 返回取出多余"/"的全路径 - */ - protected String disposeView(String view){ - if(null != view){ - view = blade.viewPrefix() + view; - view = view.replaceAll("[/]+", "/"); - if(!view.endsWith(blade.viewSuffix())){ - view = view + blade.viewSuffix(); - } - } - return view; - } - - /** - * 渲染方法 - * @param view 视图名称 - * @return null - */ - public abstract Object render(final String view); - - /** - * 渲染方法 - * @param modelAndView modelAndView对象 - * @return null - */ - public abstract Object render(ModelAndView modelAndView); - -} +package com.blade.render; + +import java.io.Writer; + +/** + * 渲染器接口 + * @author biezhi + * + */ +public interface Render { + + public void render(ModelAndView modelAndView, Writer writer); + +} diff --git a/blade-core/src/main/java/com/blade/route/Route.java b/blade-core/src/main/java/com/blade/route/Route.java new file mode 100644 index 000000000..608f94125 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/Route.java @@ -0,0 +1,106 @@ +package com.blade.route; + +import java.lang.reflect.Method; + +import com.blade.http.HttpMethod; +import com.blade.http.Path; + +public class Route { + + private HttpMethod httpMethod; + + private String path; + + private Object target; + + private Method action; + + public Route() { + } + + public Route(HttpMethod httpMethod, String path, Object target, Method action) { + super(); + this.httpMethod = httpMethod; + this.path = Path.fixPath(path); + this.target = target; + this.action = action; + } + + public HttpMethod getHttpMethod() { + return httpMethod; + } + + public void setHttpMethod(HttpMethod httpMethod) { + this.httpMethod = httpMethod; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Object getTarget() { + return target; + } + + public void setTarget(Object target) { + this.target = target; + } + + public Method getAction() { + return action; + } + + public void setAction(Method action) { + this.action = action; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((action == null) ? 0 : action.hashCode()); + result = prime * result + ((httpMethod == null) ? 0 : httpMethod.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + ((target == null) ? 0 : target.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Route other = (Route) obj; + if (action == null) { + if (other.action != null) + return false; + } else if (!action.equals(other.action)) + return false; + if (httpMethod != other.httpMethod) + return false; + if (path == null) { + if (other.path != null) + return false; + } else if (!path.equals(other.path)) + return false; + if (target == null) { + if (other.target != null) + return false; + } else if (!target.equals(other.target)) + return false; + return true; + } + + @Override + public String toString() { + return "Route [httpMethod=" + httpMethod + ", path=" + path + ", target=" + target + ", action=" + action + "]"; + } + +} diff --git a/blade-core/src/main/java/com/blade/route/RouteBase.java b/blade-core/src/main/java/com/blade/route/RouteBase.java deleted file mode 100644 index 107b8f521..000000000 --- a/blade-core/src/main/java/com/blade/route/RouteBase.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.blade.route; - -public interface RouteBase { - - public void run(); - -} diff --git a/blade-core/src/main/java/com/blade/route/RouteHandler.java b/blade-core/src/main/java/com/blade/route/RouteHandler.java index e91dec2ac..069bff8e5 100644 --- a/blade-core/src/main/java/com/blade/route/RouteHandler.java +++ b/blade-core/src/main/java/com/blade/route/RouteHandler.java @@ -1,7 +1,7 @@ package com.blade.route; -import com.blade.servlet.Request; -import com.blade.servlet.Response; +import com.blade.http.Request; +import com.blade.http.Response; /** * 路由执行器 @@ -10,6 +10,6 @@ */ public interface RouteHandler { - public Object handle(Request request, Response response); + public void handle(Request request, Response response); } diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java deleted file mode 100644 index d562544ca..000000000 --- a/blade-core/src/main/java/com/blade/route/RouteMatcher.java +++ /dev/null @@ -1,269 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import java.lang.reflect.Method; -import java.util.List; - -import blade.kit.PathKit; - -/** - * 路由匹配对象 - * - * @author biezhi - * @since 1.0 - */ -public class RouteMatcher { - - /** - * 目标运行类实例 - */ - private Class target; - - /** - * 执行的类实例 - */ - private RouteHandler routerHandler; - - /** - * 要运行的方法对象 - */ - private Method execMethod; - - /** - * http请求方法 - */ - private HttpMethod httpMethod; - - /** - * 请求URI - */ - private String requestURI; - - /** - * 路由path - */ - private String path; - - public RouteMatcher() { - } - - public RouteMatcher(RouteHandler routerHandler, Class target, Method execMethod, HttpMethod httpMethod, String path, String requestUri) { - this.routerHandler = routerHandler; - this.target = target; - this.execMethod = execMethod; - this.httpMethod = httpMethod; - this.path = path; - this.requestURI = requestUri; - } - - public HttpMethod getHttpMethod() { - return httpMethod; - } - - public Method getExecMethod() { - return execMethod; - } - - public String getPath() { - return path; - } - - public Class getTarget() { - return target; - } - - public RouteHandler getRouterHandler() { - return routerHandler; - } - - /** - * 根据http方法和path进行匹配 - * - * @param httpMethod http方法,GET/POST - * @param path 匹配的路径 - * @return true:匹配成功,false:匹配失败 - */ - public boolean matches(HttpMethod httpMethod, String path) { - - // 如果是拦截器的全部匹配模式则跳过,返回true - if ((httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER) - && (this.httpMethod == httpMethod) - && this.path.equals(PathKit.ALL_PATHS)) { - return true; - } - - boolean match = false; - - if (this.httpMethod == HttpMethod.ALL || this.httpMethod == httpMethod) { - match = matchPath(path); - } - - return match; - } - - /** - * 继续匹配 - * - * @param uri - * @return - */ - private boolean matchPath(String uri) { - - // /hello - if (!this.path.endsWith("*") && ((uri.endsWith("/") && !this.path.endsWith("/")) - || (this.path.endsWith("/") && !uri.endsWith("/")))) { - return false; - } - - if (this.path.equals(uri)) { - return true; - } - - // 检查参数 - List thisPathList = PathKit.convertRouteToList(this.path); - List uriList = PathKit.convertRouteToList(uri); - - int thisPathSize = thisPathList.size(); - int uriSize = uriList.size(); - - if (thisPathSize == uriSize) { - for (int i = 0; i < thisPathSize; i++) { - String thisPathPart = thisPathList.get(i); - String pathPart = uriList.get(i); - - if ((i == thisPathSize - 1) && (thisPathPart.equals("*") && this.path.endsWith("*"))) { - // 通配符匹配 - return true; - } - - if ((!thisPathPart.startsWith(":")) - && !thisPathPart.equals(pathPart) - && !thisPathPart.equals("*")) { - return false; - } - } - // 全部匹配 - return true; - } else { - if (this.path.endsWith("*")) { - if (uriSize == (thisPathSize - 1) && (path.endsWith("/"))) { - uriList.add(""); - uriList.add(""); - uriSize += 2; - } - - if (thisPathSize < uriSize) { - for (int i = 0; i < thisPathSize; i++) { - String thisPathPart = thisPathList.get(i); - String pathPart = uriList.get(i); - if (thisPathPart.equals("*") && (i == thisPathSize - 1) && this.path.endsWith("*")) { - return true; - } - if (!thisPathPart.startsWith(":") - && !thisPathPart.equals(pathPart) - && !thisPathPart.equals("*")) { - return false; - } - } - return true; - } - } - return false; - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((execMethod == null) ? 0 : execMethod.hashCode()); - result = prime * result + ((httpMethod == null) ? 0 : httpMethod.hashCode()); - result = prime * result + ((path == null) ? 0 : path.hashCode()); - result = prime * result + ((routerHandler == null) ? 0 : routerHandler.hashCode()); - result = prime * result + ((target == null) ? 0 : target.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - RouteMatcher other = (RouteMatcher) obj; - if (execMethod == null) { - if (other.execMethod != null) - return false; - } else if (!execMethod.equals(other.execMethod)) - return false; - if (httpMethod != other.httpMethod) - return false; - if (path == null) { - if (other.path != null) - return false; - } else if (!path.equals(other.path)) - return false; - if (routerHandler == null) { - if (other.routerHandler != null) - return false; - } else if (!routerHandler.equals(other.routerHandler)) - return false; - if (target == null) { - if (other.target != null) - return false; - } else if (!target.equals(other.target)) - return false; - return true; - } - - - public void setTarget(Class target) { - this.target = target; - } - - public void setRouterHandler(RouteHandler routerHandler) { - this.routerHandler = routerHandler; - } - - public void setExecMethod(Method execMethod) { - this.execMethod = execMethod; - } - - public void setHttpMethod(HttpMethod httpMethod) { - this.httpMethod = httpMethod; - } - - public void setRequestURI(String requestURI) { - this.requestURI = requestURI; - } - - public void setPath(String path) { - this.path = path; - } - - @Override - public String toString() { - return httpMethod.name() + ":" + path; - } - - public String getRequestURI() { - return requestURI; - } - -} diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java deleted file mode 100644 index 92f756450..000000000 --- a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java +++ /dev/null @@ -1,396 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import java.lang.reflect.Method; -import java.util.Set; - -import com.blade.Blade; -import com.blade.annotation.After; -import com.blade.annotation.Before; -import com.blade.annotation.Interceptor; -import com.blade.annotation.Path; -import com.blade.annotation.Route; -import com.blade.ioc.Container; -import com.blade.ioc.impl.DefaultContainer; -import com.blade.route.impl.DefaultRouteMatcher; - -import blade.exception.BladeException; -import blade.kit.ReflectKit; -import blade.kit.StringKit; -import blade.kit.log.Logger; -import blade.kit.resource.ClassPathClassReader; -import blade.kit.resource.ClassReader; - -/** - * 路由构造器 - * - * @author biezhi - * @since 1.0 - */ -public final class RouteMatcherBuilder { - - private static final Logger LOGGER = Logger.getLogger(RouteMatcherBuilder.class); - - private static DefaultRouteMatcher defaultRouteMatcher = DefaultRouteMatcher.instance(); - - /** - * 默认路由后缀包,用户扫描路由所在位置,默认为route,用户可自定义 - */ - private final static String PACKAGE_ROUTE = "route"; - - /** - * 默认拦截器后缀包,用户扫描拦截器所在位置,默认为interceptor,用户可自定义 - */ - private final static String PACKAGE_INTERCEPTOR = "interceptor"; - - /** - * 类读取器,用于在指定规则中扫描类 - */ - private final static ClassReader classReader = new ClassPathClassReader(); - - /** - * IOC容器,存储路由到ioc中 - */ - private final static Container container = DefaultContainer.single(); - - private RouteMatcherBuilder() { - } - - /** - * 开始构建路由 - * - * @return 返回构建路由后的构造器 - */ - public static synchronized void building(Blade blade) { - - String basePackage = blade.basePackage(); - - if(StringKit.isNotBlank(basePackage)){ - - // 处理如:com.xxx.* 表示递归扫描包 - String suffix = basePackage.endsWith(".*") ? ".*" : ""; - basePackage = basePackage.endsWith(".*") ? basePackage.substring(0, basePackage.length() - 2) : basePackage; - - String routePackage = basePackage + "." + PACKAGE_ROUTE + suffix; - String interceptorPackage = basePackage + "." + PACKAGE_INTERCEPTOR + suffix; - - buildRoute(routePackage); - - buildInterceptor(interceptorPackage); - - } else { - - // 路由 - String[] routePackages = blade.routes(); - if(null != routePackages && routePackages.length > 0){ - buildRoute(routePackages); - } - - // 拦截器 - String interceptorPackage = blade.interceptor(); - if(StringKit.isNotBlank(interceptorPackage)){ - buildInterceptor(interceptorPackage); - } - } - } - - /** - * 函数式路由构建 - */ - public static void buildFunctional(String path, Class clazz, String methodName, HttpMethod httpMethod){ - if(StringKit.isNotBlank(path) && null != clazz && StringKit.isNotBlank(methodName)){ - - // 字符串上写请求 get:hello - if(methodName.indexOf(":") != -1){ - String[] methodArr = StringKit.split(methodName, ":"); - httpMethod = getHttpMethod(methodArr[0]); - methodName = methodArr[1]; - } - - if(null == httpMethod){ - httpMethod = HttpMethod.ALL; - } - - // 查找 - Object target = container.getBean(clazz, null); - if(null == target){ - container.registBean(clazz); - } - - Method execMethod = ReflectKit.getMethodByName(clazz, methodName); - - // 拦截器 - if(httpMethod == HttpMethod.AFTER || httpMethod == HttpMethod.BEFORE){ - defaultRouteMatcher.addInterceptor(clazz, execMethod, path, httpMethod); - } else { - defaultRouteMatcher.addRoute(clazz, execMethod, path, httpMethod); - } - } else { - throw new BladeException("an unqualified configuration"); - } - } - - /** - * Handler路由构建 - */ - public static void buildHandler(String path, RouteHandler router, HttpMethod httpMethod){ - if(StringKit.isNotBlank(path) && null != router){ - defaultRouteMatcher.addRoute(router, path, httpMethod); - } else { - throw new BladeException("an unqualified configuration"); - } - } - - /** - * 函数式构建拦截器 - */ - public static void buildInterceptor(String path, RouteHandler router, HttpMethod httpMethod){ - if(StringKit.isNotBlank(path) && null != router){ - defaultRouteMatcher.addInterceptor(router, path, httpMethod); - } else { - throw new BladeException("an unqualified configuration"); - } - } - - /** - * 函数式拦截器构建 - */ - public static void buildInterceptor(String path, Class clazz, String methodName){ - if(StringKit.isNotBlank(path) && null != clazz && StringKit.isNotBlank(methodName)){ - - // 字符串上写请求 hello - if(methodName.indexOf(":") != -1){ - String[] methodArr = StringKit.split(methodName, ":"); - methodName = methodArr[1]; - } - - // 查找 - Object target = container.getBean(clazz, null); - if(null == target){ - container.registBean(clazz); - } - - Method execMethod = ReflectKit.getMethodByName(clazz, methodName); - - defaultRouteMatcher.addInterceptor(clazz, execMethod, path, HttpMethod.BEFORE); - } else { - throw new BladeException("an unqualified configuration"); - } - } - - /** - * 构建拦截器 - * - * @param interceptorPackages 要添加的拦截器包 - */ - private static void buildInterceptor(String... interceptorPackages){ - // 扫描所有的Interceptor - Set> classes = null; - // 拦截器 - for(String packageName : interceptorPackages){ - - boolean recursive = false; - - if (packageName.endsWith(".*")) { - packageName = packageName.substring(0, packageName.length() - 2); - recursive = true; - } - - // 扫描所有的Interceptor - classes = classReader.getClassByAnnotation(packageName, Interceptor.class, recursive); - - if(null != classes && classes.size() > 0){ - for(Class interceptorClazz : classes){ - parseInterceptor(interceptorClazz); - } - } - } - } - - /** - * 构建路由 - * - * @param routePackages 要添加的路由包 - */ - private static void buildRoute(String... routePackages){ - Set> classes = null; - // 路由 - for(String packageName : routePackages){ - - boolean recursive = false; - - if (packageName.endsWith(".*")) { - packageName = packageName.substring(0, packageName.length() - 2); - recursive = true; - } - - // 扫描所有的Controoler - classes = classReader.getClassByAnnotation(packageName, Path.class, recursive); - - if(null != classes && classes.size() > 0){ - for(Class pathClazz : classes){ - parseRouter(pathClazz); - } - } - } - - } - - /** - * 解析拦截器 - * - * @param interceptor 要解析的拦截器class - */ - private static void parseInterceptor(final Class interceptor){ - - Method[] methods = interceptor.getMethods(); - if(null == methods || methods.length == 0){ - return; - } - - container.registBean(interceptor); - - for (Method method : methods) { - - Before before = method.getAnnotation(Before.class); - After after = method.getAnnotation(After.class); - - if (null != before) { - - String suffix = before.suffix(); - - String path = getRoutePath(before.value(), "", suffix); - - buildInterceptor(path, interceptor, method, HttpMethod.BEFORE); - - String[] paths = before.values(); - if(null != paths && paths.length > 0){ - for(String value : paths){ - String pathV = getRoutePath(value, "", suffix); - buildInterceptor(pathV, interceptor, method, HttpMethod.BEFORE); - } - } - } - - if (null != after) { - - String suffix = after.suffix(); - - String path = getRoutePath(after.value(), "", suffix); - - buildInterceptor(path, interceptor, method, HttpMethod.AFTER); - - String[] paths = after.values(); - if(null != paths && paths.length > 0){ - for(String value : paths){ - String pathV = getRoutePath(value, "", suffix); - buildInterceptor(pathV, interceptor, method, HttpMethod.AFTER); - } - } - } - } - } - - /** - * 解析一个控制器中的所有路由 - * - * @param controller 要解析的路由class - */ - private static void parseRouter(final Class router){ - - Method[] methods = router.getMethods(); - if(null == methods || methods.length == 0){ - return; - } - - container.registBean(router); - - final String nameSpace = router.getAnnotation(Path.class).value(); - - final String suffix = router.getAnnotation(Path.class).suffix(); - - for (Method method : methods) { - - Route mapping = method.getAnnotation(Route.class); - - //route方法 - if (null != mapping) { - - ////构建路由 - String path = getRoutePath(mapping.value(), nameSpace, suffix); - - HttpMethod methodType = mapping.method(); - - buildRoute(router, method, path, methodType); - - // 构建多个路由 - String[] paths = mapping.values(); - if(null != paths && paths.length > 0){ - for(String value : paths){ - String pathV = getRoutePath(value, nameSpace, suffix); - buildRoute(router, method, pathV, methodType); - } - } - } - } - } - - private static String getRoutePath(String value, String nameSpace, String suffix){ - String path = value.startsWith("/") ? value : "/" + value; - path = nameSpace + path; - path = path.replaceAll("[/]+", "/"); - - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - - path = path + suffix; - - return path; - } - - /** - * 构建一个路由 - * - * @param target 路由目标执行的class - * @param execMethod 路由执行方法 - * @param path 路由url - * @param method 路由http方法 - */ - private static void buildRoute(Class target, Method execMethod, String path, HttpMethod method){ - defaultRouteMatcher.addRoute(target, execMethod, path, method); - } - - /** - * 构建一个路由 - * - * @param path 路由url - * @param target 路由目标执行的class - * @param execMethod 路由执行方法 - * @param method 路由http方法 - */ - private static void buildInterceptor(String path, Class target, Method execMethod, HttpMethod method){ - defaultRouteMatcher.addInterceptor(target, execMethod, path, method); - } - - private static HttpMethod getHttpMethod(String name){ - try { - return Enum.valueOf(HttpMethod.class, name.toUpperCase()); - } catch (Exception e) { - LOGGER.error("HttpMethod conversion failure", e); - } - return null; - } -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/Router.java b/blade-core/src/main/java/com/blade/route/Router.java new file mode 100644 index 000000000..42e472cbc --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/Router.java @@ -0,0 +1,159 @@ +package com.blade.route; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import com.blade.http.HttpMethod; +import com.blade.http.HttpStatus; +import com.blade.http.Request; +import com.blade.http.Response; +import com.blade.ioc.Container; +import com.blade.ioc.SampleContainer; +import com.blade.ioc.Scope; + +import blade.kit.ReflectKit; +import blade.kit.log.Logger; + +/** + * 注册、管理路由 + * + * @author biezhi + * @since 1.0 + */ +public class Router { + + private Logger LOGGER = Logger.getLogger(Router.class); + + private final static Container container = SampleContainer.single(); + + private List routes = new CopyOnWriteArrayList(); + + private List interceptors = new CopyOnWriteArrayList(); + + private static final String METHOD_NAME = "handle"; + + public void handle(Request request, Response response, Route route) throws Exception { + request.setRoute(route); + response.status(HttpStatus.NOT_FOUND); + + Object controller = route.getTarget(); + Method method = route.getAction(); + try { + method.invoke(controller, request, response); + } catch (InvocationTargetException e) { + throw (Exception) e.getCause(); + } + } + + public List getRoutes() { + return routes; + } + + public void setRoutes(List routes) { + this.routes = routes; + } + + public void addRoute(Route route) { + this.routes.add(route); + } + + public List getInterceptors() { + return interceptors; + } + + public void setInterceptors(List interceptors) { + this.interceptors = interceptors; + } + + public void addRoute(HttpMethod httpMethod, String path, Object controller, String methodName) throws NoSuchMethodException { + Method method = controller.getClass().getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, controller, method); + } + + public void addRoute(HttpMethod httpMethod, String path, Object controller, Method method) { + Class[] paramTypes = method.getParameterTypes(); + if (paramTypes.length != 2 || !paramTypes[0].equals(Request.class) || !paramTypes[1].equals(Response.class)) { + throw new RoutesException("Expecting two params of type com.blade.servlet.Request and com.blade.servlet.Response respectively"); + } + method.setAccessible(true); + + Route route = new Route(httpMethod, path, controller, method); + if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ + interceptors.add(route); + LOGGER.debug("Add Interceptor:" + route); + } else { + routes.add(route); + LOGGER.debug("Add Route:" + route); + } + + } + + public void delete(String path, RouteHandler handler) { + try { + addRoute(HttpMethod.DELETE, path, handler, METHOD_NAME); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public void route(String path, RouteHandler handler, HttpMethod httpMethod) { + try { + addRoute(httpMethod, path, handler, METHOD_NAME); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) { + for(String path : paths){ + route(path, handler, httpMethod); + } + } + + public void route(String path, Object target, String methodName) { + try { + Method method = target.getClass().getMethod(methodName, Request.class, Response.class); + addRoute(HttpMethod.ALL, path, target, method); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + } + + public void route(String path, Class clazz, String methodName) { + try { + Object controller = container.getBean(clazz, Scope.SINGLE); + if(null == controller){ + controller = ReflectKit.newInstance(clazz); + container.registBean(controller); + } + Method method = clazz.getMethod(methodName, Request.class, Response.class); + + addRoute(HttpMethod.ALL, path, controller, method); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + } + + public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) { + try { + Object controller = container.getBean(clazz, Scope.SINGLE); + if(null == controller){ + controller = ReflectKit.newInstance(clazz); + container.registBean(controller); + } + Method method = clazz.getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, controller, method); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/route/RouterExecutor.java b/blade-core/src/main/java/com/blade/route/RouterExecutor.java deleted file mode 100644 index 0769e1e15..000000000 --- a/blade-core/src/main/java/com/blade/route/RouterExecutor.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -/** - * 多个路由的执行器 - * - * @author biezhi - * @since 1.0 - */ -public class RouterExecutor{ - - private String[] paths; - - private HttpMethod httpMethod; - - public RouterExecutor(String[] paths, HttpMethod httpMethod) { - this.paths = paths; - this.httpMethod = httpMethod; - } - - public void run(RouteHandler router) { - // 拦截器 - if(this.httpMethod == HttpMethod.BEFORE || this.httpMethod == HttpMethod.AFTER){ - for(String path : paths){ - RouteMatcherBuilder.buildInterceptor(path, router, httpMethod); - } - } else { - // 路由 - for(String path : paths){ - RouteMatcherBuilder.buildHandler(path, router, httpMethod); - } - } - } - -} diff --git a/blade-core/src/main/java/com/blade/route/RoutesException.java b/blade-core/src/main/java/com/blade/route/RoutesException.java new file mode 100644 index 000000000..76846acc5 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/RoutesException.java @@ -0,0 +1,24 @@ +package com.blade.route; + +/** + * Generally thrown when a problem occurs loading the routes (different from a parsing error) + * + * @author German Escobar + */ +public class RoutesException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public RoutesException(String message) { + super(message); + } + + public RoutesException(String message, Throwable cause) { + super(message, cause); + } + + public RoutesException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java new file mode 100644 index 000000000..7f65dca20 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java @@ -0,0 +1,360 @@ +package com.blade.route; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import com.blade.http.HttpMethod; +import com.blade.http.Path; + +import blade.kit.PathKit; + +public class SampleRouteMatcher { + +// private static final Logger LOGGER = Logger.getLogger(SampleRouteMatcher.class); + + // 存储所有路由 + private List routes; + + private List interceptors; + + public SampleRouteMatcher(Router router) { + this.routes = router.getRoutes(); + this.interceptors = router.getInterceptors(); + } + + public Route getRoute(String httpMethod, String path) { + String cleanPath = parsePath(path); + List matchRoutes = new ArrayList(); + for (Route route : this.routes) { + if (matchesPath(route.getPath(), cleanPath) && route.getHttpMethod().toString().equalsIgnoreCase(httpMethod)) { + matchRoutes.add(route); + } + } + // 优先匹配原则 + giveMatch(path, matchRoutes); + + return matchRoutes.size() > 0 ? matchRoutes.get(0) : null; + } + + private void giveMatch(final String uri, List routes) { + Collections.sort(routes, new Comparator() { + @Override + public int compare(Route o1, Route o2) { + if(o2.getPath().equals(uri)){ + return o2.getPath().indexOf(uri); + } + return -1; + } + }); + } + + private boolean matchesPath(String routePath, String pathToMatch) { + routePath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); + return pathToMatch.matches("(?i)" + routePath); + } + + private String parsePath(String path) { + path = Path.fixPath(path); + + try { + URI uri = new URI(path); + return uri.getPath(); + } catch (URISyntaxException e) { + return null; + } + } + + public List getBefore(String path) { + List befores = new ArrayList(); + String cleanPath = parsePath(path); + for (Route route : this.interceptors) { + if (matches(route, HttpMethod.BEFORE, cleanPath)) { + befores.add(route); + } + } + return befores; + } + + public List getAfter(String path) { + List afters = new ArrayList(); + String cleanPath = parsePath(path); + for (Route route : interceptors) { + if (matches(route, HttpMethod.AFTER, cleanPath)) { + afters.add(route); + } + } + return afters; + } + + public boolean matches(Route route, HttpMethod httpMethod, String path) { + + // 如果是拦截器的全部匹配模式则跳过,返回true + if ((httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER) + && (route.getHttpMethod() == httpMethod) + && route.getPath().equals(PathKit.ALL_PATHS)) { + return true; + } + + boolean match = false; + if (route.getHttpMethod() == HttpMethod.ALL || route.getHttpMethod() == httpMethod) { + match = matchPath(route.getPath(), path); + } + + return match; + } + + /** + * 继续匹配 + * + * @param uri + * @return + */ + private boolean matchPath(String path, String uri) { + + // /hello + if (!path.endsWith("*") && ((uri.endsWith("/") && !path.endsWith("/")) + || (path.endsWith("/") && !uri.endsWith("/")))) { + return false; + } + + if (path.equals(uri)) { + return true; + } + + // 检查参数 + List thisPathList = PathKit.convertRouteToList(path); + List uriList = PathKit.convertRouteToList(uri); + + int thisPathSize = thisPathList.size(); + int uriSize = uriList.size(); + + if (thisPathSize == uriSize) { + for (int i = 0; i < thisPathSize; i++) { + String thisPathPart = thisPathList.get(i); + String pathPart = uriList.get(i); + + if ((i == thisPathSize - 1) && (thisPathPart.equals("*") && path.endsWith("*"))) { + // 通配符匹配 + return true; + } + + if ((!thisPathPart.startsWith(":")) + && !thisPathPart.equals(pathPart) + && !thisPathPart.equals("*")) { + return false; + } + } + // 全部匹配 + return true; + } else { + if (path.endsWith("*")) { + if (uriSize == (thisPathSize - 1) && (path.endsWith("/"))) { + uriList.add(""); + uriList.add(""); + uriSize += 2; + } + + if (thisPathSize < uriSize) { + for (int i = 0; i < thisPathSize; i++) { + String thisPathPart = thisPathList.get(i); + String pathPart = uriList.get(i); + if (thisPathPart.equals("*") && (i == thisPathSize - 1) && path.endsWith("*")) { + return true; + } + if (!thisPathPart.startsWith(":") + && !thisPathPart.equals(pathPart) + && !thisPathPart.equals("*")) { + return false; + } + } + return true; + } + } + return false; + } + } + + /** + * 查询是否有路由 + * + * @param httpMethod http请求方法,GET/POST + * @param uri 请求路径 + * @return 返回一个路由匹配对象 + *//* + public Route findRoute(HttpMethod httpMethod, String uri) { + + uri = (uri.length() > 1 && uri.endsWith("/")) ? uri.substring(0, uri.length() - 1) : uri; + + List routeEntries = this.findRouteMatcher(httpMethod, uri); + + // 优先匹配原则 + giveMatch(uri, routeEntries); + + RouteMatcher entry = routeEntries.size() > 0 ? routeEntries.get(0) : null; + + return entry != null ? new RouteMatcher(entry.getRouterHandler(), entry.getTarget(), entry.getExecMethod(), entry.getHttpMethod(), entry.getPath(), uri) : null; + } + + private void giveMatch(final String uri, List routeEntries) { + Collections.sort(routeEntries, new Comparator() { + @Override + public int compare(RouteMatcher o1, RouteMatcher o2) { + if(o2.getPath().equals(uri)){ + return o2.getPath().indexOf(uri); + } + return -1; + } + }); + } + + *//** + * 查询一个路由集合 + * + * @param httpMethod http请求方法,GET/POST + * @param path 请求路径 + * @return 返回一个路由匹配对象集合 + *//* + public List findInterceptor(HttpMethod httpMethod, String uri) { + if(uri.length() > 1){ + uri = uri.endsWith("/") ? uri.substring(0, uri.length() - 1) : uri; + } + List matchSet = CollectionKit.newArrayList(); + List routeEntries = this.searchInterceptor(httpMethod, uri); + + for (RouteMatcher routeEntry : routeEntries) { + matchSet.add(routeEntry); + } + + return matchSet; + } + + *//** + * 清空路由集合 + *//* + public void clearRoutes() { + routes.clear(); + } + + *//** + * 添加一个路由对象 + * + * @param target 路由目标执行的class + * @param execMethod 路由执行方法 + * @param url 路由url + * @param method 路由http方法 + *//* + public void addRoute(Class target, Method execMethod, String url, HttpMethod httpMethod) { + RouteMatcher routeMatcher = new RouteMatcher(); + routeMatcher.setTarget(target); + routeMatcher.setExecMethod(execMethod); + routeMatcher.setHttpMethod(httpMethod); + routeMatcher.setPath(url); + + LOGGER.debug("Add Route:" + routeMatcher); + + // 添加到路由集合 + routes.add(routeMatcher); + } + + *//** + * 添加一个拦截器对象 + * + * @param target 路由目标执行的class + * @param execMethod 路由执行方法 + * @param url 路由url + * @param method 路由http方法 + *//* + public void addInterceptor(Class target, Method execMethod, String url, HttpMethod httpMethod) { + RouteMatcher routeMatcher = new RouteMatcher(); + routeMatcher.setTarget(target); + routeMatcher.setExecMethod(execMethod); + routeMatcher.setHttpMethod(httpMethod); + routeMatcher.setPath(url); + + LOGGER.debug("Add Interceptor:" + routeMatcher); + + // 添加到路由集合 + interceptors.add(routeMatcher); + } + + *//** + * 添加一个路由对象 + * + * @param router 执行的匿名类 + * @param url 路由url + * @param method 路由http方法 + *//* + public void addRoute(RouteHandler routerHandler, String url, HttpMethod httpMethod) { + + RouteMatcher routeMatcher = new RouteMatcher(); + routeMatcher.setRouterHandler(routerHandler); + routeMatcher.setHttpMethod(httpMethod); + routeMatcher.setPath(url); + + LOGGER.debug("Add Route:" + routeMatcher); + + // 添加到路由集合 + routes.add(routeMatcher); + } + + *//** + * 添加一个拦截器对象 + * + * @param router 执行的匿名类 + * @param url 路由url + * @param method 路由http方法 + *//* + public void addInterceptor(RouteHandler routerHandler, String url, HttpMethod httpMethod) { + + RouteMatcher routeMatcher = new RouteMatcher(); + routeMatcher.setRouterHandler(routerHandler); + routeMatcher.setHttpMethod(httpMethod); + routeMatcher.setPath(url); + + LOGGER.debug("Add Interceptor:" + routeMatcher); + + // 添加到路由集合 + interceptors.add(routeMatcher); + } + + *//** + * 查找所有匹配HttpMethod和path的路由 + * + * @param httpMethod http方法 + * @param path 路由路径 + * @return 返回匹配的所有路由集合 + *//* + private List findRouteMatcher(HttpMethod httpMethod, String path) { + path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + + List matchSet = CollectionKit.newArrayList(); + for (RouteMatcher entry : routes) { + if (entry.matches(httpMethod, path)) { + matchSet.add(entry); + } + } + return matchSet; + } + + *//** + * 查找所有匹配HttpMethod和path的路由 + * + * @param httpMethod http方法 + * @param path 路由路径 + * @return 返回匹配的所有路由集合 + *//* + private List searchInterceptor(HttpMethod httpMethod, String path) { + List matchSet = CollectionKit.newArrayList(); + for (RouteMatcher entry : interceptors) { + if (entry.matches(httpMethod, path)) { + matchSet.add(entry); + } + } + return matchSet; + } + */ +} diff --git a/blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java b/blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java deleted file mode 100644 index 88d0f721f..000000000 --- a/blade-core/src/main/java/com/blade/route/impl/DefaultRouteMatcher.java +++ /dev/null @@ -1,237 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route.impl; - -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import com.blade.route.HttpMethod; -import com.blade.route.RouteHandler; -import com.blade.route.RouteMatcher; - -import blade.kit.CollectionKit; -import blade.kit.log.Logger; - -/** - * 默认的路由匹配器 - * - * @author biezhi - * @since 1.0 - */ -public class DefaultRouteMatcher { - - private static final Logger LOGGER = Logger.getLogger(DefaultRouteMatcher.class); - - private static final DefaultRouteMatcher DEFAULT_ROUTE_MATCHER = new DefaultRouteMatcher(); - - // 存储所有路由 - private List routes; - - // 存储所有拦截器 - private List interceptors; - - private DefaultRouteMatcher() { - routes = CollectionKit.newArrayList(); - interceptors = CollectionKit.newArrayList(); - } - - public static DefaultRouteMatcher instance(){ - return DEFAULT_ROUTE_MATCHER; - } - - /** - * 查询是否有路由 - * - * @param httpMethod http请求方法,GET/POST - * @param uri 请求路径 - * @return 返回一个路由匹配对象 - */ - public RouteMatcher findRoute(HttpMethod httpMethod, String uri) { - - uri = (uri.length() > 1 && uri.endsWith("/")) ? uri.substring(0, uri.length() - 1) : uri; - - List routeEntries = this.findRouteMatcher(httpMethod, uri); - - // 优先匹配原则 - giveMatch(uri, routeEntries); - - RouteMatcher entry = routeEntries.size() > 0 ? routeEntries.get(0) : null; - - return entry != null ? new RouteMatcher(entry.getRouterHandler(), entry.getTarget(), entry.getExecMethod(), entry.getHttpMethod(), entry.getPath(), uri) : null; - } - - private void giveMatch(final String uri, List routeEntries) { - Collections.sort(routeEntries, new Comparator() { - @Override - public int compare(RouteMatcher o1, RouteMatcher o2) { - if(o2.getPath().equals(uri)){ - return o2.getPath().indexOf(uri); - } - return -1; - } - }); - } - - /** - * 查询一个路由集合 - * - * @param httpMethod http请求方法,GET/POST - * @param path 请求路径 - * @return 返回一个路由匹配对象集合 - */ - public List findInterceptor(HttpMethod httpMethod, String uri) { - if(uri.length() > 1){ - uri = uri.endsWith("/") ? uri.substring(0, uri.length() - 1) : uri; - } - List matchSet = CollectionKit.newArrayList(); - List routeEntries = this.searchInterceptor(httpMethod, uri); - - for (RouteMatcher routeEntry : routeEntries) { - matchSet.add(routeEntry); - } - - return matchSet; - } - - /** - * 清空路由集合 - */ - public void clearRoutes() { - routes.clear(); - } - - /** - * 添加一个路由对象 - * - * @param target 路由目标执行的class - * @param execMethod 路由执行方法 - * @param url 路由url - * @param method 路由http方法 - */ - public void addRoute(Class target, Method execMethod, String url, HttpMethod httpMethod) { - RouteMatcher routeMatcher = new RouteMatcher(); - routeMatcher.setTarget(target); - routeMatcher.setExecMethod(execMethod); - routeMatcher.setHttpMethod(httpMethod); - routeMatcher.setPath(url); - - LOGGER.debug("Add Route:" + routeMatcher); - - // 添加到路由集合 - routes.add(routeMatcher); - } - - /** - * 添加一个拦截器对象 - * - * @param target 路由目标执行的class - * @param execMethod 路由执行方法 - * @param url 路由url - * @param method 路由http方法 - */ - public void addInterceptor(Class target, Method execMethod, String url, HttpMethod httpMethod) { - RouteMatcher routeMatcher = new RouteMatcher(); - routeMatcher.setTarget(target); - routeMatcher.setExecMethod(execMethod); - routeMatcher.setHttpMethod(httpMethod); - routeMatcher.setPath(url); - - LOGGER.debug("Add Interceptor:" + routeMatcher); - - // 添加到路由集合 - interceptors.add(routeMatcher); - } - - /** - * 添加一个路由对象 - * - * @param router 执行的匿名类 - * @param url 路由url - * @param method 路由http方法 - */ - public void addRoute(RouteHandler routerHandler, String url, HttpMethod httpMethod) { - - RouteMatcher routeMatcher = new RouteMatcher(); - routeMatcher.setRouterHandler(routerHandler); - routeMatcher.setHttpMethod(httpMethod); - routeMatcher.setPath(url); - - LOGGER.debug("Add Route:" + routeMatcher); - - // 添加到路由集合 - routes.add(routeMatcher); - } - - /** - * 添加一个拦截器对象 - * - * @param router 执行的匿名类 - * @param url 路由url - * @param method 路由http方法 - */ - public void addInterceptor(RouteHandler routerHandler, String url, HttpMethod httpMethod) { - - RouteMatcher routeMatcher = new RouteMatcher(); - routeMatcher.setRouterHandler(routerHandler); - routeMatcher.setHttpMethod(httpMethod); - routeMatcher.setPath(url); - - LOGGER.debug("Add Interceptor:" + routeMatcher); - - // 添加到路由集合 - interceptors.add(routeMatcher); - } - - /** - * 查找所有匹配HttpMethod和path的路由 - * - * @param httpMethod http方法 - * @param path 路由路径 - * @return 返回匹配的所有路由集合 - */ - private List findRouteMatcher(HttpMethod httpMethod, String path) { - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - - List matchSet = CollectionKit.newArrayList(); - for (RouteMatcher entry : routes) { - if (entry.matches(httpMethod, path)) { - matchSet.add(entry); - } - } - return matchSet; - } - - /** - * 查找所有匹配HttpMethod和path的路由 - * - * @param httpMethod http方法 - * @param path 路由路径 - * @return 返回匹配的所有路由集合 - */ - private List searchInterceptor(HttpMethod httpMethod, String path) { - List matchSet = CollectionKit.newArrayList(); - for (RouteMatcher entry : interceptors) { - if (entry.matches(httpMethod, path)) { - matchSet.add(entry); - } - } - return matchSet; - } - - -} diff --git a/blade-core/src/main/java/com/blade/server/BladeServer.java b/blade-core/src/main/java/com/blade/server/Server.java similarity index 67% rename from blade-core/src/main/java/com/blade/server/BladeServer.java rename to blade-core/src/main/java/com/blade/server/Server.java index 62ea925cd..8db23149c 100644 --- a/blade-core/src/main/java/com/blade/server/BladeServer.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -4,26 +4,31 @@ import javax.servlet.DispatcherType; -import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import com.blade.CoreFilter; import blade.kit.log.Logger; -public class BladeServer { +/** + * Jetty服务 + * + * @author biezhi + * @since 1.0 + */ +public class Server { - private static final Logger LOGGER = Logger.getLogger(BladeServer.class); + private static final Logger LOGGER = Logger.getLogger(Server.class); private int port = 9000; - public BladeServer(int port) { + public Server(int port) { this.port = port; } public void run(String contextPath) throws Exception{ - Server server = new Server(port); + org.eclipse.jetty.server.Server server = new org.eclipse.jetty.server.Server(port); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath(contextPath); diff --git a/blade-core/src/main/java/com/blade/servlet/QueryParamsMap.java b/blade-core/src/main/java/com/blade/servlet/QueryParamsMap.java deleted file mode 100644 index 8dd83693e..000000000 --- a/blade-core/src/main/java/com/blade/servlet/QueryParamsMap.java +++ /dev/null @@ -1,269 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.http.HttpServletRequest; - -import blade.kit.CollectionKit; - -/** - * 查询参数封装 - *

- * 封装了URL上的查询参数和Path参数 - *

- * - * @author biezhi - * @since 1.0 - */ -public class QueryParamsMap { - - /** - * 一个空的参数查询map - */ - private static final QueryParamsMap NULL = new QueryParamsMap(); - - /** - * 查询参数字典,存放url上传输的参数 - */ - private Map queryMap = CollectionKit.newHashMap(); - - /** - * 所有的值数组 - */ - private String[] values; - - private Pattern p = Pattern.compile("\\A[\\[\\]]*([^\\[\\]]+)\\]*"); - - /** - * 根据request创建一个QueryParamsMap对象 - * 从request.getParameterMap()方法解析参数 - * - * @param request HttpServletRequest请求对象 - */ - public QueryParamsMap(HttpServletRequest request) { - if (request == null) { - throw new IllegalArgumentException("HttpServletRequest cannot be null."); - } - loadQueryString(request.getParameterMap()); - } - - /** - * 并没有什么卵用 _(:з」∠)_ - */ - private QueryParamsMap() { - } - - - /** - * 解析和创建键和值,一键多值 - * - * @param key 形如: user[info][name] - * @param values 所有值 - */ - protected QueryParamsMap(String key, String... values) { - loadKeys(key, values); - } - - /** - * 构造一个查询参数对象 - * - * @param params 要加载进的所有参数 - */ - protected QueryParamsMap(Map params) { - loadQueryString(params); - } - - /** - * 加载查询参数 - * - * @param params 要加载进的所有参数 - */ - protected final void loadQueryString(Map params) { - for (Map.Entry param : params.entrySet()) { - loadKeys(param.getKey(), param.getValue()); - } - } - - /** - * 加载所有key - * - * @param key 要加载的键 - * @param value 家加载的值 - */ - protected final void loadKeys(String key, String[] value) { - String[] parsed = parseKey(key); - - if (parsed == null) { - return; - } - - if (!queryMap.containsKey(parsed[0])) { - queryMap.put(parsed[0], new QueryParamsMap()); - } - if (!parsed[1].isEmpty()) { - queryMap.get(parsed[0]).loadKeys(parsed[1], value); - } else { - queryMap.get(parsed[0]).values = value.clone(); - } - } - - protected final String[] parseKey(String key) { - Matcher m = p.matcher(key); - - if (m.find()) { - return new String[] {cleanKey(m.group()), key.substring(m.end())}; - } else { - return null; - } - } - - protected static final String cleanKey(String group) { - if (group.startsWith("[")) { - return group.substring(1, group.length() - 1); - } else { - return group; - } - } - - /** - * 根据key返回QueryParamsMap - * 注入:user[name]=fede - * 获取:get("user").get("name").value() || get("user","name").value() - * - * @param keys 键列表 - * @return 返回一个查询参数map - */ - public QueryParamsMap get(String... keys) { - QueryParamsMap ret = this; - for (String key : keys) { - if (ret.queryMap.containsKey(key)) { - ret = ret.queryMap.get(key); - } else { - ret = NULL; - } - } - return ret; - } - - /** - * @return 返回键的值 - */ - public String value() { - if (hasValue()) { - return values[0]; - } else { - return null; - } - } - - /** - * 根据传入的keys获取值 - * - * @param keys keys - * @return 返回键的值 - */ - public String value(String... keys) { - return get(keys).value(); - } - - /** - * @return 是否包含该key - */ - public boolean hasKeys() { - return !this.queryMap.isEmpty(); - } - - /** - * @return 是否包含value - */ - public boolean hasValue() { - return this.values != null && this.values.length > 0; - } - - /** - * @return 返回Boolean类型值 - */ - public Boolean booleanValue() { - return hasValue() ? Boolean.valueOf(value()) : null; - } - - /** - * @return Integer类型的值 - */ - public Integer integerValue() { - return hasValue() ? Integer.valueOf(value()) : null; - } - - /** - * @return 返回Long类型值 - */ - public Long longValue() { - return hasValue() ? Long.valueOf(value()) : null; - } - - /** - * @return 返回Float类型值 - */ - public Float floatValue() { - return hasValue() ? Float.valueOf(value()) : null; - } - - /** - * @return 返回Double类型值 - */ - public Double doubleValue() { - return hasValue() ? Double.valueOf(value()) : null; - } - - /** - * @return 返回values - */ - public String[] values() { - return this.values.clone(); - } - - /** - * @return 返回queryMap - */ - Map getQueryMap() { - return queryMap; - } - - /** - * @return 返回values - */ - String[] getValues() { - return values; - } - - /** - * @return 将queryMap转换为map - */ - public Map toMap() { - Map map = CollectionKit.newHashMap(); - - for (Entry key : this.queryMap.entrySet()) { - map.put(key.getKey(), key.getValue().values); - } - - return map; - } -} diff --git a/blade-core/src/main/java/com/blade/servlet/Request.java b/blade-core/src/main/java/com/blade/servlet/Request.java deleted file mode 100644 index 9c859a4de..000000000 --- a/blade-core/src/main/java/com/blade/servlet/Request.java +++ /dev/null @@ -1,595 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet; - -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import com.blade.route.HttpMethod; -import com.blade.route.RouteMatcher; - -import blade.kit.CollectionKit; -import blade.kit.IOKit; -import blade.kit.PathKit; -import blade.kit.StringKit; -import blade.kit.log.Logger; - -/** - * HttpServletRequest请求包装类 - *

- * 提供对HttpServletRequest API的简单操作 - *

- * - * @author biezhi - * @since 1.0 - */ -public class Request { - - private static final Logger LOGGER = Logger.getLogger(Request.class); - - private static final String USER_AGENT = "user-agent"; - - protected Map pathParams; - protected List splat; - private QueryParamsMap queryMap; - - private HttpServletRequest servletRequest; - - private Session session = null; - - private String body = null; - private byte[] bodyAsBytes = null; - - private Set headers = null; - - protected Request() { - } - - public Request(HttpServletRequest request) { - this.servletRequest = request; - } - - /** - * 构造一个Request对象 - * - * @param match 路由匹配对象,用于存储URL参数等信息 - * @param request HttpServletRequest请求对象 - */ - public Request(RouteMatcher match, HttpServletRequest request) { - this.servletRequest = request; - initRequest(match); - } - - /** - * 初始化Request - * - * @param match 路由匹配对象,用于存储URL参数等信息 - */ - public void initRequest(RouteMatcher match) { - - List requestList = PathKit.convertRouteToList(match.getRequestURI()); - List pathList = PathKit.convertRouteToList(match.getPath()); - - this.pathParams = getPathParams(requestList, pathList); - this.splat = getSplat(requestList, pathList); - } - - /** - * @return 返回URL路径上的所有参数 - */ - public Map params() { - return Collections.unmodifiableMap(this.pathParams); - } - - /** - * 返回在URL路径上的参数值,如:/users/:name - * @param param 参数名称 - * @return 返回URL上对应的String参数值 - */ - public String param(String param) { - if (param == null) { - return null; - } - - if (param.startsWith(":")) { - return pathParams.get(param.toLowerCase()); - } else { - return pathParams.get(":" + param.toLowerCase()); - } - } - - /** - * 返回int类型的path param - * @param param 参数名称 - * @return 返回URL上对应的Integer参数值 - */ - public Integer paramToInt(String param) { - String value = param(param); - if(null != value){ - return Integer.valueOf(value); - } - return null; - } - - /** - * 返回long类型的参数值 - * @param param 参数名称 - * @return 返回URL上对应的Long参数值 - */ - public Long paramToLong(String param) { - String value = param(param); - if(null != value){ - return Long.valueOf(value); - } - return null; - } - - /** - * @return 返回通配符 - */ - public String[] splat() { - return splat.toArray(new String[splat.size()]); - } - - /** - * @return 返回请求method 如:GET, POST, PUT, ... - */ - public String requestMethod() { - return servletRequest.getMethod(); - } - - /** - * @return 返回请求scheme - */ - public String scheme() { - return servletRequest.getScheme(); - } - - /** - * @return 返回主机名称 - */ - public String host() { - return servletRequest.getHeader("host"); - } - - /** - * @return 返回请求UA - */ - public String userAgent() { - return servletRequest.getHeader(USER_AGENT); - } - - /** - * @return 返回服务端口 - */ - public int port() { - return servletRequest.getServerPort(); - } - - - /** - * @return 返回pathinfo 如:"/example/foo" - */ - public String pathInfo() { - return servletRequest.getPathInfo(); - } - - /** - * @return 返回servletPath - */ - public String servletPath() { - return servletRequest.getServletPath(); - } - - /** - * @return 返回contextpath - */ - public String contextPath() { - return servletRequest.getContextPath(); - } - - /** - * @return 返回url - */ - public String url() { - return servletRequest.getRequestURL().toString(); - } - - /** - * @return 返回contentType - */ - public String contentType() { - return servletRequest.getContentType(); - } - - /** - * @return 返回客户端IP - */ - public String ip() { - return servletRequest.getRemoteAddr(); - } - - /** - * @return 返回请求body - */ - public String body() { - if (body == null) { - readBody(); - } - return body; - } - - /** - * @return 返回转换为字节数组的请求body - */ - public byte[] bodyAsBytes() { - if (bodyAsBytes == null) { - readBody(); - } - return bodyAsBytes; - } - - private void readBody() { - try { - bodyAsBytes = IOKit.toByteArray(servletRequest.getInputStream()); - body = new String(bodyAsBytes); - } catch (Exception e) { - LOGGER.warn("Exception when reading body", e); - } - } - - /** - * @return 返回请求body的长度 - */ - public int contentLength() { - return servletRequest.getContentLength(); - } - - /** - * 获取query参数 - * - * @param queryParam 查询键 - * @return 返回查询到的value - */ - public String query(String queryParam) { - return servletRequest.getParameter(queryParam); - } - - /** - * 获取一个数组类型的query - * - * @param queryParam 查询键 - * @return 返回查询到的value数组 - */ - public String[] querys(String queryParam) { - return servletRequest.getParameterValues(queryParam); - } - - /** - * 获取query参数冰转换为Integer类型 - * @param queryParam 查询键 - * @return 返回查询到的int value - */ - public Integer queryToInt(String queryParam) { - String value = query(queryParam); - if(StringKit.isNotEmpty(value)){ - return Integer.valueOf(value); - } - return null; - } - - /** - * 获取query参数冰转换为Long类型 - * @param queryParam 查询键 - * @return 返回查询到的long value - */ - public Long queryToLong(String queryParam) { - String value = query(queryParam); - if(StringKit.isNotEmpty(value)){ - return Long.valueOf(value); - } - return null; - } - - /** - * 获取query参数冰转换为Boolean类型 - * @param queryParam 查询键 - * @return 返回查询到的boolean value - */ - public Boolean queryToBoolean(String queryParam) { - String value = query(queryParam); - if(StringKit.isNotEmpty(value)){ - return Boolean.valueOf(value); - } - return null; - } - - /** - * 获取query参数冰转换为Double类型 - * @param queryParam 查询键 - * @return 返回查询到的double value - */ - public Double queryToDouble(String queryParam) { - String value = query(queryParam); - if(StringKit.isNotEmpty(value)){ - return Double.valueOf(value); - } - return null; - } - - /** - * 获取query参数并转换为Float类型 - * @param queryParam 查询键 - * @return 返回查询到的float value - */ - public Float queryToFloat(String queryParam) { - String value = query(queryParam); - if(StringKit.isNotEmpty(value)){ - return Float.valueOf(value); - } - return null; - } - - /** - * 获取头信息 - * - * @param header 要查找的请求头 - * @return 返回请求头信息 - */ - public String header(String header) { - return servletRequest.getHeader(header); - } - - /** - * @return 返回查询参数集合 - */ - public Set querys() { - return servletRequest.getParameterMap().keySet(); - } - - /** - * @return 返回所有头信息 - */ - public Set headers() { - if (headers == null) { - headers = new TreeSet(); - Enumeration enumeration = servletRequest.getHeaderNames(); - while (enumeration.hasMoreElements()) { - headers.add(enumeration.nextElement()); - } - } - return headers; - } - - /** - * @return 返回查询字符串 - */ - public String queryString() { - return servletRequest.getQueryString(); - } - - /** - * 设置request属性 - * - * @param attribute 属性名称 - * @param value 属性值 - */ - public void attribute(String attribute, Object value) { - servletRequest.setAttribute(attribute, value); - } - - /** - * 获取request属性 - * - * @param attribute 属性名称 - * @return 返回属性值 - */ - public Object attribute(String attribute) { - return servletRequest.getAttribute(attribute); - } - - - /** - * @return 返回所有request属性 - */ - public Set attributes() { - Set attrList = new HashSet(); - Enumeration attributes = (Enumeration) servletRequest.getAttributeNames(); - while (attributes.hasMoreElements()) { - attrList.add(attributes.nextElement()); - } - return attrList; - } - - /** - * @return 返回原生HttpServletRequest对象 - */ - public HttpServletRequest servletRequest() { - return servletRequest; - } - - /** - * @return 返回查询map - */ - public QueryParamsMap queryMap() { - initQueryMap(); - - return queryMap; - } - - /** - * @param key the key - * @return the query map - */ - public QueryParamsMap queryMap(String key) { - return queryMap().get(key); - } - - private void initQueryMap() { - if (queryMap == null) { - queryMap = new QueryParamsMap(servletRequest()); - } - } - - /** - * @return 返回会话对象 - */ - public Session session() { - if (session == null) { - session = new Session(servletRequest.getSession()); - } - return session; - } - - /** - * 返回会话对象,如果不存在则创建一个 - * @param create true:创建,false:不创建 - * @return 返回一个会话对象 - */ - public Session session(boolean create) { - if (session == null) { - HttpSession httpSession = servletRequest.getSession(create); - if (httpSession != null) { - session = new Session(httpSession); - } - } - return session; - } - - /** - * @return 返回cookies - */ - public Map cookies() { - Map result = CollectionKit.newHashMap(); - Cookie[] cookies = servletRequest.getCookies(); - if (cookies != null) { - for (Cookie cookie : cookies) { - result.put(cookie.getName(), cookie.getValue()); - } - } - return result; - } - - /** - * 根据cookie名称获取cookie - * - * @param name cookie名称 - * @return 返回cookie值 - */ - public String cookie(String name) { - Cookie[] cookies = servletRequest.getCookies(); - if (cookies != null) { - for (Cookie cookie : cookies) { - if (cookie.getName().equals(name)) { - return cookie.getValue(); - } - } - } - return null; - } - - /** - * @return 返回uri - */ - public String uri() { - return servletRequest.getRequestURI(); - } - - /** - * @return 返回请求协议 - */ - public String protocol() { - return servletRequest.getProtocol(); - } - -protected static Map getPathParams(List request, List matched) { - - Map params = CollectionKit.newHashMap(); - - for (int i = 0; (i < request.size()) && (i < matched.size()); i++) { - String matchedPart = matched.get(i); - if (PathKit.isParam(matchedPart)) { - LOGGER.debug("matchedPart: " - + matchedPart - + " = " - + request.get(i)); - params.put(matchedPart.toLowerCase(), request.get(i)); - } - } - return Collections.unmodifiableMap(params); - } - - protected static List getSplat(List request, List matched) { - - int nbrOfRequestParts = request.size(); - int nbrOfMatchedParts = matched.size(); - - boolean sameLength = (nbrOfRequestParts == nbrOfMatchedParts); - - List splat = CollectionKit.newArrayList(); - - for (int i = 0; (i < nbrOfRequestParts) && (i < nbrOfMatchedParts); i++) { - String matchedPart = matched.get(i); - - if (PathKit.isSplat(matchedPart)) { - - StringBuilder splatParam = new StringBuilder(request.get(i)); - if (!sameLength && (i == (nbrOfMatchedParts - 1))) { - for (int j = i + 1; j < nbrOfRequestParts; j++) { - splatParam.append("/"); - splatParam.append(request.get(j)); - } - } - splat.add(splatParam.toString()); - } - } - return Collections.unmodifiableList(splat); - } - - /** - * 继续执行 - * @return - */ - public Object invoke(){ - return true; - } - - /** - * 跳转到一个页面 - * @param locaiton - * @return - */ - public Object invoke(String locaiton) { - return "redirect." + locaiton; - } - - /** - * 获取http method - * @return - */ - public HttpMethod method() { - return HttpMethod.valueOf(servletRequest.getMethod()); - } -} diff --git a/blade-core/src/main/java/com/blade/servlet/Response.java b/blade-core/src/main/java/com/blade/servlet/Response.java deleted file mode 100644 index 9db6bc5ed..000000000 --- a/blade-core/src/main/java/com/blade/servlet/Response.java +++ /dev/null @@ -1,309 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet; - -import java.io.IOException; -import java.io.PrintWriter; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import com.blade.BladeWebContext; -import com.blade.render.ModelAndView; -import com.blade.render.Render; -import com.blade.render.RenderFactory; - -import blade.kit.log.Logger; - -/** - * HttpServletResponse响应包装类 - *

- * 封装HttpServletResponse的一些方法 - *

- * - * @author biezhi - * @since 1.0 - */ -public class Response { - - private static final Logger LOGGER = Logger.getLogger(Response.class); - - private HttpServletResponse response; - - // 默认JSP引擎 - private Render render = RenderFactory.getRender(); - - private String body; - - protected Response() { - } - - public Response(HttpServletResponse response) { - this.response = response; - } - - /** - * 设置响应状态码 - * - * @param statusCode 状态码 - */ - public void status(int statusCode) { - response.setStatus(statusCode); - } - - /** - * 设置contentType - * - * @param contentType contentType - */ - public void contentType(String contentType) { - response.setContentType(contentType); - } - - /** - * 设置响应内容 - * - * @param body 响应主体 - */ - public void body(String body) { - this.body = body; - } - - /** - * @return 返回响应体内容 - */ - public String body() { - return this.body; - } - - /** - * @return 返回输出流 - * @throws IOException - */ - public ServletOutputStream outputStream() throws IOException { - return response.getOutputStream(); - } - - /** - * @return 返回PrintWriter - * @throws IOException - */ - public PrintWriter writer() throws IOException { - return response.getWriter(); - } - - /** - * @return 返回原生HttpServletResponse - */ - public HttpServletResponse servletResponse() { - return response; - } - - /** - * 重定向到location - * - * @param location 重定向的location - */ - public void go(String path) { - LOGGER.debug("Redirecting (%s %s to %s", "Found", HttpServletResponse.SC_FOUND, path); - try { - String ctx = BladeWebContext.servletContext().getContextPath(); - String location = (ctx + path).replaceAll("//", "/"); - response.sendRedirect(location); - } catch (IOException ioException) { - LOGGER.warn("Redirect failure", ioException); - } - } - - /** - * 重定向到location - * - * @param location 重定向的location - */ - public void redirect(String location) { - LOGGER.debug("Redirecting (%s %s to %s", "Found", HttpServletResponse.SC_FOUND, location); - try { - response.sendRedirect(location); - } catch (IOException ioException) { - LOGGER.warn("Redirect failure", ioException); - } - } - - /** - * 重定向并修改响应码 - * - * @param location 重定向的location - * @param statusCode 状态码 - */ - public void redirect(String location, int statusCode) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Redirecting ({} to {}", statusCode, location); - } - response.setStatus(statusCode); - response.setHeader("Location", location); - response.setHeader("Connection", "close"); - try { - response.sendError(statusCode); - } catch (IOException e) { - LOGGER.warn("Exception when trying to redirect permanently", e); - } - } - - /** - * 设置响应头 - * - * @param header 头信息键 - * @param value 头信息值 - */ - public void header(String header, String value) { - response.addHeader(header, value); - } - - /** - * 设置cookie - * - * @param name cookie name - * @param value cookie value - */ - public void cookie(String name, String value) { - cookie(name, value, -1, false); - } - - /** - * 设置cookie - * - * @param name cookie name - * @param value cookie name - * @param maxAge cookie有效期 - */ - public void cookie(String name, String value, int maxAge) { - cookie(name, value, maxAge, false); - } - - /** - * 设置cookie - * - * @param name cookie name - * @param value cookie name - * @param maxAge cookie有效期 - * @param secured 是否SSL - */ - public void cookie(String name, String value, int maxAge, boolean secured) { - cookie("", name, value, maxAge, secured); - } - - /** - * 设置cookie - * @param path cookie所在域 - * @param name cookie name - * @param value cookie 值 - * @param maxAge cookie有效期 - * @param secured 是否SSL - */ - public void cookie(String path, String name, String value, int maxAge, boolean secured) { - Cookie cookie = new Cookie(name, value); - cookie.setPath(path); - cookie.setMaxAge(maxAge); - cookie.setSecure(secured); - response.addCookie(cookie); - } - - /** - * 移除cookie - * - * @param name 要移除的cookie name - */ - public void removeCookie(String name) { - Cookie cookie = new Cookie(name, ""); - cookie.setMaxAge(0); - response.addCookie(cookie); - } - - /** - * 渲染一个视图 - * @param view - */ - public void render(String view){ - render.render(view); - } - - /** - * 根据ModelAndView进行渲染 - * @param modelAndView - */ - public void render(ModelAndView modelAndView){ - render.render(modelAndView); - } - - /** - * 返回文字格式 - * @param text - */ - public void text(String text){ - render.text(text); - } - - /** - * 返回json格式 - * @param json - */ - public void json(String json){ - render.json(json); - } - - /** - * 返回xml格式 - * @param xml - */ - public void xml(String xml){ - render.xml(xml); - } - - /** - * 返回js格式 - * @param javascript - */ - public void javascript(String javascript){ - render.javascript(javascript); - } - - /** - * 返回html格式 - * @param html - */ - public void html(String html){ - render.html(html); - } - - /** - * 404默认视图 - * - * @param viewName - */ - public void render404(String viewName){ - render.render404(this, viewName); - } - - /** - * 500默认视图 - * - * @param bodyContent - */ - public void render500(String bodyContent){ - render.render500(bodyContent); - } -} diff --git a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java new file mode 100644 index 000000000..696bf3a83 --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java @@ -0,0 +1,504 @@ +package com.blade.servlet; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.ServletContext; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import com.blade.Blade; +import com.blade.http.HttpException; +import com.blade.http.HttpMethod; +import com.blade.http.Path; +import com.blade.http.Request; +import com.blade.route.Route; +import com.blade.servlet.multipart.FileItem; +import com.blade.servlet.multipart.Multipart; +import com.blade.servlet.multipart.MultipartException; +import com.blade.servlet.multipart.MultipartHandler; + +import blade.kit.IOKit; +import blade.kit.text.HTMLFilter; + +/** + * ServletRequest + * + * @author biezhi + * @since 1.0 + */ +public class ServletRequest implements Request { + + private static final String USER_AGENT = "user-agent"; + + protected Route route; + + private HttpServletRequest request; + + protected Map pathParams = new HashMap(); + + private Map multipartParams = new HashMap(); + + private List files = new ArrayList(); + + private Session session = null; + + private Blade blade = Blade.me(); + + public ServletRequest(HttpServletRequest request) throws MultipartException, IOException { + this.request = request; + init(); + } + + public ServletRequest init() throws IOException, MultipartException { + // retrieve multipart/form-data parameters + if (Multipart.isMultipartContent(request)) { + Multipart multipart = new Multipart(); + multipart.parse(request, new MultipartHandler() { + + @Override + public void handleFormItem(String name, String value) { + multipartParams.put( name, value ); + } + + @Override + public void handleFileItem(String name, FileItem fileItem) { + files.add(fileItem); + } + + }); + } + return this; + } + + private String join(String[] arr) { + String ret = ""; + for (String item : arr) { + ret += "," + item; + } + + if (ret.length() > 0) { + ret = ret.substring(1); + } + + return ret; + } + + @Override + public void initPathParams(String routePath) { + pathParams.clear(); + + List variables = getPathParam(routePath); + String regexPath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); + + Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(path()); + matcher.matches(); + + // start index at 1 as group(0) always stands for the entire expression + for (int i=1; i <= variables.size(); i++) { + String value = matcher.group(i); + pathParams.put(variables.get(i-1), value); + } + } + + private List getPathParam(String routePath) { + List variables = new ArrayList(); + + Matcher matcher = Pattern.compile(Path.VAR_REGEXP).matcher(routePath); + while (matcher.find()) { + // group(0) always stands for the entire expression and we only want what is inside the {} + variables.add(matcher.group(1)); + } + + return variables; + } + + @Override + public HttpServletRequest raw() { + return request; + } + + @Override + public String host() { + return request.getServerName(); + } + + @Override + public String url() { + return request.getRequestURL().toString(); + } + + @Override + public String path() { + return Path.fixPath(request.getRequestURI()); + } + + @Override + public String userAgent() { + return request.getHeader(USER_AGENT); + } + + @Override + public String pathInfo() { + return request.getPathInfo(); + } + + @Override + public String protocol() { + return request.getProtocol(); + } + + @Override + public String servletPath() { + return request.getServletPath(); + } + + @Override + public String contextPath() { + return request.getContextPath(); + } + + @Override + public ServletContext context() { + return request.getServletContext(); + } + + @Override + public Map pathParams() { + return pathParams; + } + + @Override + public String param(String name) { + String val = pathParams.get(name); + if(blade.enableXSS()){ + return HTMLFilter.htmlSpecialChars(val); + } + return val; + } + + @Override + public Integer paramAsInt(String name) { + String value = param(name); + if (null != value) { + return Integer.valueOf(value); + } + return null; + } + + @Override + public Long paramAsLong(String name) { + String value = param(name); + if (null != value) { + return Long.valueOf(value); + } + return null; + } + + @Override + public Boolean paramAsBoolean(String name) { + String value = param(name); + if (null != value) { + return Boolean.valueOf(value); + } + return null; + } + + @Override + public String queryString() { + return request.getQueryString(); + } + + @Override + public Map querys() { + Map params = new HashMap(); + + Map requestParams = request.getParameterMap(); + for (Map.Entry entry : requestParams.entrySet()) { + params.put( entry.getKey(), join(entry.getValue()) ); + } + params.putAll(multipartParams); + return Collections.unmodifiableMap(params); + } + + @Override + public String query(String name) { + String[] param = request.getParameterValues(name); + if (param != null) { + return join(param); + } + + String val = multipartParams.get(name); + if(blade.enableXSS()){ + return HTMLFilter.htmlSpecialChars(val); + } + return val; + } + + @Override + public Integer queryAsInt(String name) { + String value = query(name); + if (null != value) { + return Integer.valueOf(value); + } + return null; + } + + @Override + public Long queryAsLong(String name) { + String value = query(name); + if (null != value) { + return Long.valueOf(value); + } + return null; + } + + @Override + public Boolean queryAsBoolean(String name) { + String value = query(name); + if (null != value) { + return Boolean.valueOf(value); + } + return null; + } + + @Override + public Float queryAsFloat(String name) { + String value = query(name); + if (null != value) { + return Float.valueOf(value); + } + return null; + } + + @Override + public Double queryAsDouble(String name) { + String value = query(name); + if (null != value) { + return Double.valueOf(value); + } + return null; + } + + @Override + public String method() { + return request.getMethod(); + } + + @Override + public HttpMethod httpMethod() { + return HttpMethod.valueOf(request.getMethod()); + } + + @Override + public String address() { + return request.getRemoteAddr(); + } + + @Override + public Session session() { + if (session == null) { + session = new Session(request.getSession()); + } + return session; + } + + @Override + public Session session(boolean create) { + if (session == null) { + HttpSession httpSession = request.getSession(create); + if (httpSession != null) { + session = new Session(httpSession); + } + } + return session; + } + + @Override + public void attribute(String name, Object value) { + request.setAttribute(name, value); + } + + @Override + public Object attribute(String name) { + return request.getAttribute(name); + } + + @Override + public Set attributes() { + Set attrList = new HashSet(); + Enumeration attributes = (Enumeration) request.getAttributeNames(); + while (attributes.hasMoreElements()) { + attrList.add(attributes.nextElement()); + } + return attrList; + } + + @Override + public String contentType() { + return request.getContentType(); + } + + @Override + public int port() { + return request.getServerPort(); + } + + @Override + public boolean isSecure() { + return request.isSecure(); + } + + @Override + public boolean isAjax() { + if (request.getHeader("x-requested-with") == null) { + return false; + } + return "XMLHttpRequest".equals(request.getHeader("x-requested-with")); + } + + @Override + public Map cookies() { + javax.servlet.http.Cookie[] servletCookies = request.getCookies(); + + Map cookies = new HashMap(); + for (javax.servlet.http.Cookie c : servletCookies) { + cookies.put( c.getName(), map(c) ); + } + + return Collections.unmodifiableMap(cookies); + } + + private Cookie map(Cookie servletCookie) { + Cookie cookie = new Cookie(servletCookie.getName(), servletCookie.getValue()); + cookie.setMaxAge(servletCookie.getMaxAge()); + cookie.setHttpOnly(servletCookie.isHttpOnly()); + cookie.setPath(servletCookie.getPath()); + cookie.setDomain(servletCookie.getDomain()); + cookie.setSecure(servletCookie.getSecure()); + return cookie; + } + + @Override + public String cookie(String name) { + Cookie cookie = cookieRaw(name); + if(null != cookie){ + return cookie.getValue(); + } + return null; + } + + @Override + public Cookie cookieRaw(String name) { + javax.servlet.http.Cookie[] servletCookies = request.getCookies(); + + if (servletCookies == null) { + return null; + } + + for (javax.servlet.http.Cookie c : servletCookies) { + if (c.getName().equals(name)) { + return map(c); + } + } + return null; + } + + @Override + public Map headers() { + Enumeration servletHeaders = request.getHeaderNames(); + Map headers = new HashMap(); + while(servletHeaders.hasMoreElements()) { + String headerName = servletHeaders.nextElement(); + headers.put(headerName, request.getHeader(headerName)); + } + return headers; + } + + @Override + public String header(String name) { + return request.getHeader(name); + } + + @Override + public void encoding(String encoding) { + try { + request.setCharacterEncoding(encoding); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + @Override + public FileItem[] files() { + FileItem[] fileParts = new FileItem[files.size()]; + for (int i=0; i < files.size(); i++) { + fileParts[i] = files.get(i); + } + return fileParts; + } + + @Override + public BodyParser body() { + return new BodyParser() { + @Override + public String asString() throws HttpException { + try { + BufferedReader reader = new BufferedReader( new InputStreamReader(request.getInputStream()) ); + StringBuilder sb = new StringBuilder(); + String line = reader.readLine(); + while (line != null) { + sb.append(line + "\n"); + line = reader.readLine(); + } + reader.close(); + String data = sb.toString(); + + return data; + } catch (IOException e) { + throw new HttpException(e); + } + } + + @Override + public InputStream asInputStream() throws HttpException { + try { + return request.getInputStream(); + } catch (IOException e) { + throw new HttpException(e); + } + } + + @Override + public byte[] asByte() { + try { + return IOKit.toByteArray(request.getInputStream()); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + }; + } + + @Override + public void setRoute(Route route) { + this.route = route; + initPathParams(route.getPath()); + } + +} diff --git a/blade-core/src/main/java/com/blade/servlet/ServletResponse.java b/blade-core/src/main/java/com/blade/servlet/ServletResponse.java new file mode 100644 index 000000000..0d7375d05 --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/ServletResponse.java @@ -0,0 +1,312 @@ +package com.blade.servlet; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import com.blade.context.BladeWebContext; +import com.blade.http.HttpException; +import com.blade.http.HttpStatus; +import com.blade.http.Path; +import com.blade.http.Request; +import com.blade.http.Response; +import com.blade.render.ModelAndView; +import com.blade.render.Render; + +/** + * ServletResponse + * + * @author biezhi + * @since 1.0 + */ +public class ServletResponse implements Response { + + private HttpServletResponse response; + + private Map attributes = new HashMap(); + + private boolean written = false; + + private Render render; + + public ServletResponse(HttpServletResponse response, Render render) { + this.response = response; + this.render = render; + } + + @Override + public HttpServletResponse raw() { + return response; + } + + @Override + public int status() { + return response.getStatus(); + } + + @Override + public Response status(int status) { + response.setStatus(status); + return this; + } + + @Override + public Response badRequest() { + response.setStatus(HttpStatus.BAD_REQUEST); + return this; + } + + @Override + public Response unauthorized() { + response.setStatus(HttpStatus.UNAUTHORIZED); + return this; + } + + @Override + public Response notFound() { + response.setStatus(HttpStatus.NOT_FOUND); + return this; + } + + @Override + public Response conflict() { + response.setStatus(HttpStatus.CONFLICT); + return this; + } + + @Override + public String contentType() { + return response.getContentType(); + } + + @Override + public Response contentType(String contentType) { + response.setContentType(contentType); + return this; + } + + @Override + public String header(String name) { + return response.getHeader(name); + } + + @Override + public Response header(String name, String value) { + response.setHeader(name, value); + return this; + } + + @Override + public Response cookie(Cookie cookie) { + response.addCookie(cookie); + return this; + } + + @Override + public Response cookie(String name, String value) { + return cookie(name, value); + } + + @Override + public Response cookie(String name, String value, int maxAge) { + return cookie(name, value, maxAge); + } + + @Override + public Response cookie(String name, String value, int maxAge, boolean secured) { + return cookie(name, value, maxAge, secured); + } + + @Override + public Response cookie(String path, String name, String value, int maxAge, boolean secured) { + Cookie cookie = new Cookie(name, value); + cookie.setPath(path); + cookie.setMaxAge(maxAge); + cookie.setSecure(secured); + response.addCookie(cookie); + return this; + } + + @Override + public Response removeCookie(Cookie cookie) { + cookie.setMaxAge(0); + response.addCookie(map(cookie)); + return this; + } + + javax.servlet.http.Cookie map(Cookie cookie) { + javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); + servletCookie.setMaxAge(cookie.getMaxAge()); + if (cookie.getPath() != null) { + servletCookie.setPath(cookie.getPath()); + } + if (cookie.getDomain() != null) { + servletCookie.setDomain(cookie.getDomain()); + } + servletCookie.setHttpOnly(cookie.isHttpOnly()); + servletCookie.setSecure(cookie.getSecure()); + return servletCookie; + } + + @Override + public Response removeCookie(String name) { + Cookie cookie = new Cookie(name, ""); + cookie.setMaxAge(0); + response.addCookie(cookie); + return this; + } + + @Override + public Map attributes() { + return attributes; + } + + @Override + public Response attribute(String name, Object object) { + attributes.put(name, object); + return this; + } + + @Override + public Response text(String text) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/plain;charset=utf-8"); + response.getWriter().print(text); + this.written = true; + return this; + } catch (IOException e) { + throw new HttpException(e); + } + } + + @Override + public Response html(String html) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/html;charset=utf-8"); + + PrintWriter out = response.getWriter(); + out.print(html); + out.flush(); + out.close(); + + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public Response json(String json) { + Request request = BladeWebContext.request(); + String userAgent = request.userAgent(); + if (userAgent.contains("MSIE")) { + response.setContentType("text/html;charset=utf-8"); + } else { + response.setContentType("application/json;charset=utf-8"); + } + try { + response.setHeader("Cache-Control", "no-cache"); + PrintWriter out = response.getWriter(); + out.print(json); + out.flush(); + out.close(); + + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Response xml(String xml) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/xml;charset=utf-8"); + + PrintWriter out = response.getWriter(); + out.print(xml); + out.flush(); + out.close(); + + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public ServletOutputStream outputStream() throws IOException { + return response.getOutputStream(); + } + + @Override + public Response render(String view) { + try { + ModelAndView modelAndView = new ModelAndView(view); + render.render(modelAndView, response.getWriter()); + return this; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Response render(ModelAndView modelAndView) { + try { + render.render(modelAndView, response.getWriter()); + return this; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void redirect(String path) { + try { + response.sendRedirect(path); + } catch (IOException e) { + throw new HttpException(e); + } + } + + @Override + public void go(String path) { + try { + String ctx = BladeWebContext.servletContext().getContextPath(); + String location = Path.fixPath(ctx + path); + response.sendRedirect(location); + } catch (IOException e) { + throw new HttpException(e); + } + } + + @Override + public boolean isWritten() { + return written; + } + +} diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java b/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java index 9e65c9d03..8fa409c0e 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java +++ b/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java @@ -1,120 +1,62 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet.multipart; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.util.Arrays; - -import blade.kit.io.FastByteArrayOutputStream; +import java.io.File; +import java.util.HashMap; +import java.util.Map; /** - * 文件上传Item + * HTTP multipart/form-data 请求 + * @author biezhi * - * @author biezhi - * @since 1.0 */ public class FileItem { private String name; - private boolean isFile; private String fileName; + private String contentType; - private InputStream inputStream; - - public static final String FORM_DATA = "form-data"; - - public static final String MULTIPART_FORM_DATA = "multipart/form-data"; - - // 数据体缓存 - private FastByteArrayOutputStream outputStream; - - public void write(byte[] buf, int off, int len) { - if (outputStream == null) { - outputStream = new FastByteArrayOutputStream(); + + private long contentLength; + + private File file; + + private Map headers; + + public FileItem(String fieldName, String fileName, String contentType, long contentLength, File file, Map headers) { + + this.fileName = fileName; + this.contentType = contentType; + this.contentLength = contentLength; + this.file = file; + this.headers = headers; + if (headers == null) { + this.headers = new HashMap(); } - outputStream.write(buf, off, len); } - // ----------------------------------------------------------------- public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - public String getFileName() { return fileName; } - public void setFileName(String fileName) { - this.fileName = fileName; - } - public String getContentType() { return contentType; } - public void setContentType(String contentType) { - this.contentType = contentType; - } - - public boolean isFile() { - return isFile; + public long getContentLength() { + return contentLength; } - public void setFile(boolean isFile) { - this.isFile = isFile; + public File getFile() { + return file; } - public byte[] getFileContent() { - byte[] buf = outputStream.toByteArray(); - int dirtyCount = 2; - - // 最后会多出一个\r\n, - // 根据ServletInputStream, \n 就算一行结束, 因此对于\r需要特殊判断 - if ('\r' != buf[buf.length - 2]) - dirtyCount = 1; - - return Arrays.copyOfRange(buf, 0, buf.length - dirtyCount); + public Map getHeaders() { + return headers; } - public String getString(String encoding){ - try { - return outputStream == null ? null : new String(getFileContent(), encoding); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return null; - } - - public String getString() { - return outputStream == null ? null : new String(getFileContent()); - } - - public InputStream getInputStream() { - return inputStream; - } - - public void setInputStream(InputStream inputStream) { - this.inputStream = inputStream; - } - } - diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java b/blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java new file mode 100644 index 000000000..d34026b4c --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java @@ -0,0 +1,306 @@ +package com.blade.servlet.multipart; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import blade.kit.IOKit; + +public class Multipart { + + public static final String CONTENT_TYPE = "Content-Type"; + + public static final String CONTENT_DISPOSITION = "Content-Disposition"; + + public static final String CONTENT_LENGTH = "Content-Length"; + + public static final String FORM_DATA = "form-data"; + + public static final String ATTACHMENT = "attachment"; + + public static final String MULTIPART = "multipart/"; + + public static final String MULTIPART_MIXED = "multipart/mixed"; + + public static boolean isMultipartContent(HttpServletRequest request) { + if (!"post".equals(request.getMethod().toLowerCase())) { + return false; + } + + String contentType = request.getContentType(); + if (contentType == null) { + return false; + } + if (contentType.toLowerCase().startsWith(MULTIPART)) { + return true; + } + + return false; + } + + public void parse(HttpServletRequest request, MultipartHandler partHandler) throws IOException, MultipartException { + if (!isMultipartContent(request)) { + throw new MultipartException("Not a multipart content. The HTTP method should be 'POST' and the " + + "Content-Type 'multipart/form-data' or 'multipart/mixed'."); + } + + InputStream inputStream = request.getInputStream(); + + String contentType = request.getContentType(); + String charEncoding = request.getCharacterEncoding(); + + byte[] boundary = getBoundary(contentType); + if (boundary == null) { + throw new MultipartException("the request was rejected because no multipart boundary was found"); + } + + // create a multipart reader + MultipartReader multipartReader = new MultipartReader(inputStream, boundary); + multipartReader.setHeaderEncoding(charEncoding); + + String currentFieldName = null; + boolean skipPreamble = true; + + for (;;) { + boolean nextPart; + if (skipPreamble) { + nextPart = multipartReader.skipPreamble(); + } else { + nextPart = multipartReader.readBoundary(); + } + if (!nextPart) { + if (currentFieldName == null) { + // outer multipart terminated -> no more data + return; + } + // inner multipart terminated -> return to parsing the outer + multipartReader.setBoundary(boundary); + currentFieldName = null; + continue; + } + + String headersString = multipartReader.readHeaders(); + Map headers = getHeadersMap(headersString); + + if (currentFieldName == null) { + + // we're parsing the outer multipart + String fieldName = getFieldName( headers.get(CONTENT_DISPOSITION) ); + if (fieldName != null) { + + String partContentType = headers.get(CONTENT_TYPE); + if (partContentType != null && partContentType.toLowerCase().startsWith(MULTIPART_MIXED)) { + + // multiple files associated with this field name + currentFieldName = fieldName; + multipartReader.setBoundary( getBoundary(partContentType)); + skipPreamble = true; + + continue; + } + + String fileName = getFileName( headers.get(CONTENT_DISPOSITION) ); + if (fileName == null) { + // call the part handler + String value = IOKit.toString(multipartReader.newInputStream()); + partHandler.handleFormItem(fieldName, value); + } else { + + // create the temp file + File tempFile = createTempFile(multipartReader); + + // call the part handler + FileItem fileItem = new FileItem(fieldName, fileName, partContentType, tempFile.length(), tempFile, headers); + partHandler.handleFileItem(fieldName, fileItem); + } + + continue; + } + } else { + String fileName = getFileName( headers.get(CONTENT_DISPOSITION) ); + String partContentType = headers.get(CONTENT_TYPE); + if (fileName != null) { + + // create the temp file + File tempFile = createTempFile(multipartReader); + + // call the part handler + FileItem fileItem = new FileItem(currentFieldName, fileName, partContentType, tempFile.length(), + tempFile, headers); + partHandler.handleFileItem(currentFieldName, fileItem); + continue; + } + } + multipartReader.discardBodyData(); + } + + } + + private File createTempFile(MultipartReader multipartReader) throws IOException { + File tempFile = File.createTempFile("com.blade.file_", null); + FileOutputStream outputStream = null; + try { + outputStream = new FileOutputStream(tempFile); + copy( multipartReader.newInputStream(), outputStream ); + } finally { + if (outputStream != null) { + try { outputStream.close(); } catch (Exception e) {} + } + } + + return tempFile; + } + + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + private static final int EOF = -1; + + private long copy(InputStream input, OutputStream output) throws IOException { + long count = 0; + int n = 0; + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + protected Map getHeadersMap(String headerPart) { + final int len = headerPart.length(); + final Map headers = new HashMap(); + + int start = 0; + for (;;) { + int end = parseEndOfLine(headerPart, start); + if (start == end) { + break; + } + String header = headerPart.substring(start, end); + start = end + 2; + while (start < len) { + int nonWs = start; + while (nonWs < len) { + char c = headerPart.charAt(nonWs); + if (c != ' ' && c != '\t') { + break; + } + ++nonWs; + } + if (nonWs == start) { + break; + } + // continuation line found + end = parseEndOfLine(headerPart, nonWs); + header += " " + headerPart.substring(nonWs, end); + start = end + 2; + } + + // parse header line + final int colonOffset = header.indexOf(':'); + if (colonOffset == -1) { + // this header line is malformed, skip it. + continue; + } + String headerName = header.substring(0, colonOffset).trim(); + String headerValue = header.substring(header.indexOf(':') + 1).trim(); + + if (headers.containsKey(headerName)) { + headers.put( headerName, headers.get(headerName) + "," + headerValue ); + } else { + headers.put(headerName, headerValue); + } + } + + return headers; + } + + private int parseEndOfLine(String headerPart, int end) { + int index = end; + for (;;) { + int offset = headerPart.indexOf('\r', index); + if (offset == -1 || offset + 1 >= headerPart.length()) { + throw new IllegalStateException("Expected headers to be terminated by an empty line."); + } + if (headerPart.charAt(offset + 1) == '\n') { + return offset; + } + index = offset + 1; + } + } + + private String getFieldName(String contentDisposition) { + String fieldName = null; + + if (contentDisposition != null && contentDisposition.toLowerCase().startsWith(FORM_DATA)) { + ParameterParser parser = new ParameterParser(); + parser.setLowerCaseNames(true); + + // parameter parser can handle null input + Map params = parser.parse(contentDisposition, ';'); + fieldName = (String) params.get("name"); + if (fieldName != null) { + fieldName = fieldName.trim(); + } + } + + return fieldName; + } + + protected byte[] getBoundary(String contentType) { + ParameterParser parser = new ParameterParser(); + parser.setLowerCaseNames(true); + // Parameter parser can handle null input + Map params = parser.parse(contentType, new char[] {';', ','}); + String boundaryStr = (String) params.get("boundary"); + + if (boundaryStr == null) { + return null; + } + + byte[] boundary; + try { + boundary = boundaryStr.getBytes("ISO-8859-1"); + } catch (UnsupportedEncodingException e) { + boundary = boundaryStr.getBytes(); + } + return boundary; + } + + private String getFileName(String contentDisposition) { + String fileName = null; + + if (contentDisposition != null) { + String cdl = contentDisposition.toLowerCase(); + + if (cdl.startsWith(FORM_DATA) || cdl.startsWith(ATTACHMENT)) { + + ParameterParser parser = new ParameterParser(); + parser.setLowerCaseNames(true); + + // parameter parser can handle null input + Map params = parser.parse(contentDisposition, ';'); + if (params.containsKey("filename")) { + fileName = (String) params.get("filename"); + if (fileName != null) { + fileName = fileName.trim(); + } else { + // even if there is no value, the parameter is present, + // so we return an empty file name rather than no file + // name. + fileName = ""; + } + } + } + } + + return fileName; + } + +} diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java new file mode 100644 index 000000000..940fab864 --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java @@ -0,0 +1,22 @@ +package com.blade.servlet.multipart; + +public class MultipartException extends Exception { + + private static final long serialVersionUID = 1L; + + public MultipartException() { + } + + public MultipartException(String message) { + super(message); + } + + public MultipartException(Throwable cause) { + super(cause); + } + + public MultipartException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java new file mode 100644 index 000000000..0a18e4400 --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java @@ -0,0 +1,9 @@ +package com.blade.servlet.multipart; + +public interface MultipartHandler { + + void handleFormItem(String name, String value); + + void handleFileItem(String name, FileItem fileItem); + +} diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java new file mode 100644 index 000000000..3d6994bed --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java @@ -0,0 +1,768 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE + * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.blade.servlet.multipart; + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +/** + *

+ * Low level API for processing file uploads. + * + *

+ * This class can be used to process data streams conforming to MIME 'multipart' format as defined in RFC 1867. Arbitrarily large amounts of data in the stream can be + * processed under constant memory usage. + * + *

+ * The format of the stream is defined in the following way:
+ * + * + * multipart-body := preamble 1*encapsulation close-delimiter epilogue
+ * encapsulation := delimiter body CRLF
+ * delimiter := "--" boundary CRLF
+ * close-delimiter := "--" boudary "--"
+ * preamble := <ignore>
+ * epilogue := <ignore>
+ * body := header-part CRLF body-part
+ * header-part := 1*header CRLF
+ * header := header-name ":" header-value
+ * header-name := <printable ascii characters except ":">
+ * header-value := <any ascii characters except CR & LF>
+ * body-data := <arbitrary data>
+ *
+ * + *

+ * Note that body-data can contain another mulipart entity. There is limited support for single pass processing of such + * nested streams. The nested stream is required to have a boundary token of the same length as the + * parent stream (see {@link #setBoundary(byte[])}). + * + *

+ * Here is an example of usage of this class.
+ * + *

+ * try {
+ * 	MultipartStream multipartStream = new MultipartStream(input, boundary);
+ * 	boolean nextPart = multipartStream.skipPreamble();
+ * 	OutputStream output;
+ * 	while (nextPart) {
+ * 		String header = multipartStream.readHeaders();
+ * 		// process headers
+ * 		// create some output stream
+ * 		multipartStream.readBodyData(output);
+ * 		nextPart = multipartStream.readBoundary();
+ * 	}
+ * } catch (MultipartStream.MalformedStreamException e) {
+ * 	// the stream failed to follow required syntax
+ * } catch (IOException e) {
+ * 	// a read or write error occurred
+ * }
+ * 
+ * + * @author Rafal Krzewski + * @author Martin Cooper + * @author Sean C. Sullivan + * + * @version $Id: MultipartStream.java 735374 2009-01-18 02:18:45Z jochen $ + */ +public class MultipartReader { + + /** + * The Carriage Return ASCII character value. + */ + public static final byte CR = 0x0D; + + /** + * The Line Feed ASCII character value. + */ + public static final byte LF = 0x0A; + + /** + * The dash (-) ASCII character value. + */ + public static final byte DASH = 0x2D; + + /** + * The maximum length of header-part that will be processed (10 kilobytes = 10240 bytes.). + */ + public static final int HEADER_PART_SIZE_MAX = 10240; + + /** + * The default length of the buffer used for processing a request. + */ + protected static final int DEFAULT_BUFSIZE = 4096; + + /** + * A byte sequence that marks the end of header-part (CRLFCRLF). + */ + protected static final byte[] HEADER_SEPARATOR = { CR, LF, CR, LF }; + + /** + * A byte sequence that that follows a delimiter that will be followed by an encapsulation (CRLF). + */ + protected static final byte[] FIELD_SEPARATOR = { CR, LF }; + + /** + * A byte sequence that that follows a delimiter of the last encapsulation in the stream (--). + */ + protected static final byte[] STREAM_TERMINATOR = { DASH, DASH }; + + /** + * A byte sequence that precedes a boundary (CRLF--). + */ + protected static final byte[] BOUNDARY_PREFIX = { CR, LF, DASH, DASH }; + + /** + * The input stream from which data is read. + */ + private final InputStream input; + + /** + * The length of the boundary token plus the leading CRLF--. + */ + private int boundaryLength; + + /** + * The amount of data, in bytes, that must be kept in the buffer in order to detect delimiters reliably. + */ + private int keepRegion; + + /** + * The byte sequence that partitions the stream. + */ + private byte[] boundary; + + /** + * The length of the buffer used for processing the request. + */ + private final int bufSize; + + /** + * The buffer used for processing the request. + */ + private final byte[] buffer; + + /** + * The index of first valid character in the buffer.
+ * 0 <= head < bufSize + */ + private int head; + + /** + * The index of last valid characer in the buffer + 1.
+ * 0 <= tail <= bufSize + */ + private int tail; + + /** + * The content encoding to use when reading headers. + */ + private String headerEncoding; + + /** + *

+ * Constructs a MultipartStream with a custom size buffer. + * + *

+ * Note that the buffer must be at least big enough to contain the boundary string, plus 4 characters for CR/LF and + * double dash, plus at least one byte of data. Too small a buffer size setting will degrade performance. + * + * @param input The InputStream to serve as a data source. + * @param boundary The token used for dividing the stream into encapsulations. + * @param bufSize The size of the buffer to be used, in bytes. + * + */ + public MultipartReader(InputStream input, byte[] boundary, int bufSize) { + this.input = input; + this.bufSize = bufSize; + this.buffer = new byte[bufSize]; + + // prepend CR/LF to the boundary to chop trailing CR/LF from body-data tokens. + this.boundary = new byte[boundary.length + BOUNDARY_PREFIX.length]; + this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length; + this.keepRegion = this.boundary.length; + System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0, BOUNDARY_PREFIX.length); + System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, boundary.length); + + head = 0; + tail = 0; + } + + /** + * Constructs a MultipartStream with a default size buffer. + * + * @param input The InputStream to serve as a data source. + * @param boundary The token used for dividing the stream into encapsulations. + */ + public MultipartReader(InputStream input, byte[] boundary) { + this(input, boundary, DEFAULT_BUFSIZE); + } + + /** + * Retrieves the character encoding used when reading the headers of an individual part. When not specified, or + * null, the platform default encoding is used. + * + * @return The encoding used to read part headers. + */ + public String getHeaderEncoding() { + return headerEncoding; + } + + /** + * Specifies the character encoding to be used when reading the headers of individual parts. When not specified, or + * null, the platform default encoding is used. + * + * @param encoding The encoding used to read part headers. + */ + public void setHeaderEncoding(String encoding) { + headerEncoding = encoding; + } + + /** + * Reads a byte from the buffer, and refills it as necessary. + * + * @return The next byte from the input stream. + * @throws IOException if there is no more data available. + */ + public byte readByte() throws IOException { + + // buffer depleted ? + if (head == tail) { + head = 0; + // Refill. + tail = input.read(buffer, head, bufSize); + if (tail == -1) { + // no more data available. + throw new IOException("No more data is available"); + } + } + + return buffer[head++]; + } + + /** + * Skips a boundary token, and checks whether more encapsulations are contained in the + * stream. + * + * @return true if there are more encapsulations in this stream; false otherwise. + * + * @throws MalformedStreamException if the stream ends unexpecetedly or fails to follow required syntax. + */ + public boolean readBoundary() throws MalformedStreamException { + byte[] marker = new byte[2]; + boolean nextChunk = false; + + head += boundaryLength; + try { + marker[0] = readByte(); + marker[1] = readByte(); + if (arrayequals(marker, STREAM_TERMINATOR, 2)) { + nextChunk = false; + } else if (arrayequals(marker, FIELD_SEPARATOR, 2)) { + nextChunk = true; + } else { + throw new MalformedStreamException("Unexpected characters follow a boundary"); + } + } catch (IOException e) { + throw new MalformedStreamException("Stream ended unexpectedly"); + } + return nextChunk; + } + + /** + *

Changes the boundary token used for partitioning the stream.

+ * + *

This method allows single pass processing of nested multipart streams.

+ * + *

The boundary token of the nested stream is required to be of the same length as the boundary token + * in parent stream.

+ * + *

Restoring the parent stream boundary token after processing of a nested stream is left to the application.

+ * + * @param boundary The boundary to be used for parsing of the nested stream. + * + * @throws IllegalBoundaryException if the boundary has a different length than the one being currently + * parsed. + */ + public void setBoundary(byte[] boundary) throws IllegalBoundaryException { + + if (boundary.length != boundaryLength - BOUNDARY_PREFIX.length) { + throw new IllegalBoundaryException("The length of a boundary token can not be changed"); + } + + System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, boundary.length); + } + + /** + *

Reads the header-part of the current encapsulation.

+ * + *

Headers are returned verbatim to the input stream, including the trailing CRLF marker. Parsing is + * left to the application.

+ * + * @return The header-part of the current encapsulation. + * @throws MalformedStreamException if the stream ends unexpecetedly. + */ + public String readHeaders() throws MalformedStreamException { + int i = 0; + byte b; + // to support multi-byte characters + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int size = 0; + while (i < HEADER_SEPARATOR.length) { + try { + b = readByte(); + } catch (IOException e) { + throw new MalformedStreamException("Stream ended unexpectedly"); + } + if (++size > HEADER_PART_SIZE_MAX) { + throw new MalformedStreamException("Header section has more than " + HEADER_PART_SIZE_MAX + + " bytes (maybe it is not properly terminated)"); + } + if (b == HEADER_SEPARATOR[i]) { + i++; + } else { + i = 0; + } + baos.write(b); + } + + String headers = null; + if (headerEncoding != null) { + try { + headers = baos.toString(headerEncoding); + } catch (UnsupportedEncodingException e) { + // fall back to platform default if specified encoding is not supported. + headers = baos.toString(); + } + } else { + headers = baos.toString(); + } + + return headers; + } + + /** + *

Reads body-data from the current encapsulation and writes its contents into the output + * Stream.

+ * + *

Arbitrary large amounts of data can be processed by this method using a constant size buffer.

+ * + * @param output The Stream to write data into. May be null, in which case this method is equivalent to + * {@link #discardBodyData()}. + * + * @return the amount of data written. + * + * @throws MalformedStreamException if the stream ends unexpectedly. + * @throws IOException if an i/o error occurs. + */ + public int readBodyData(OutputStream output) throws MalformedStreamException, IOException { + final InputStream istream = newInputStream(); + return (int) Streams.copy(istream, output, false); + } + + /** + * Creates a new {@link ItemInputStream}. + * + * @return A new instance of {@link ItemInputStream}. + */ + protected ItemInputStream newInputStream() { + return new ItemInputStream(); + } + + /** + *

Reads body-data from the current encapsulation and discards it.

+ * + *

Use this method to skip encapsulations you don't need or don't understand.

+ * + * @return The amount of data discarded. + * @throws MalformedStreamException if the stream ends unexpectedly. + * @throws IOException if an i/o error occurs. + */ + public int discardBodyData() throws MalformedStreamException, IOException { + return readBodyData(null); + } + + /** + * Finds the beginning of the first encapsulation. + * + * @return true if an encapsulation was found in the stream. + * @throws IOException if an i/o error occurs. + */ + public boolean skipPreamble() throws IOException { + + // first delimiter may be not preceded with a CRLF. + System.arraycopy(boundary, 2, boundary, 0, boundary.length - 2); + boundaryLength = boundary.length - 2; + try { + // discard all data up to the delimiter. + discardBodyData(); + + // read boundary - if succeded, the stream contains an encapsulation. + return readBoundary(); + } catch (MalformedStreamException e) { + return false; + } finally { + // restore delimiter. + System.arraycopy(boundary, 0, boundary, 2, boundary.length - 2); + boundaryLength = boundary.length; + boundary[0] = CR; + boundary[1] = LF; + } + } + + /** + * Compares count first bytes in the arrays a and b. + * + * @param a The first array to compare. + * @param b The second array to compare. + * @param count How many bytes should be compared. + * + * @return true if count first bytes in arrays a and b are + * equal. + */ + public static boolean arrayequals(byte[] a, byte[] b, int count) { + for (int i = 0; i < count; i++) { + if (a[i] != b[i]) { + return false; + } + } + return true; + } + + /** + * Searches for a byte of specified value in the buffer, starting at the specified + * position. + * + * @param value The value to find. + * @param pos The starting position for searching. + * + * @return The position of byte found, counting from beginning of the buffer, or -1 if not + * found. + */ + protected int findByte(byte value, int pos) { + for (int i = pos; i < tail; i++) { + if (buffer[i] == value) { + return i; + } + } + + return -1; + } + + /** + * Searches for the boundary in the buffer region delimited by head and + * tail. + * + * @return The position of the boundary found, counting from the beginning of the buffer, or + * -1 if not found. + */ + protected int findSeparator() { + int first; + int match = 0; + int maxpos = tail - boundaryLength; + for (first = head; (first <= maxpos) && (match != boundaryLength); first++) { + first = findByte(boundary[0], first); + if (first == -1 || (first > maxpos)) { + return -1; + } + for (match = 1; match < boundaryLength; match++) { + if (buffer[first + match] != boundary[match]) { + break; + } + } + } + if (match == boundaryLength) { + return first - 1; + } + return -1; + } + + /** + * Thrown to indicate that the input stream fails to follow the required syntax. + */ + @SuppressWarnings("serial") + public static class MalformedStreamException extends IOException { + + /** + * Constructs a MalformedStreamException with no detail message. + */ + public MalformedStreamException() { + super(); + } + + /** + * Constructs an MalformedStreamException with the specified detail message. + * + * @param message The detail message. + */ + public MalformedStreamException(String message) { + super(message); + } + } + + /** + * Thrown upon attempt of setting an invalid boundary token. + */ + @SuppressWarnings("serial") + public static class IllegalBoundaryException extends IOException { + + /** + * Constructs an IllegalBoundaryException with no detail message. + */ + public IllegalBoundaryException() { + super(); + } + + /** + * Constructs an IllegalBoundaryException with the specified detail message. + * + * @param message The detail message. + */ + public IllegalBoundaryException(String message) { + super(message); + } + + } + + /** + * An {@link InputStream} for reading an items contents. + */ + public class ItemInputStream extends InputStream implements Closeable { + + /* The number of bytes, which have been read so far */ + private long total; + + /* The number of bytes, which must be hold, because they might be a part of the boundary */ + private int pad; + + /* The current offset in the buffer */ + private int pos; + + /* Whether the stream is already closed. */ + private boolean closed; + + /** + * Creates a new instance. + */ + ItemInputStream() { + findSeparator(); + } + + /** + * Called for finding the separator. + */ + private void findSeparator() { + pos = MultipartReader.this.findSeparator(); + if (pos == -1) { + if (tail - head > keepRegion) { + pad = keepRegion; + } else { + pad = tail - head; + } + } + } + + /** + * Returns the number of bytes, which have been read by the stream. + * + * @return Number of bytes, which have been read so far. + */ + public long getBytesRead() { + return total; + } + + /** + * Returns the number of bytes, which are currently available, without blocking. + * + * @return Number of bytes in the buffer. + * @throws IOException An I/O error occurs. + */ + public int available() throws IOException { + if (pos == -1) { + return tail - head - pad; + } + return pos - head; + } + + /* Offset when converting negative bytes to integers */ + private static final int BYTE_POSITIVE_OFFSET = 256; + + /** + * Returns the next byte in the stream. + * + * @return The next byte in the stream, as a non-negative integer, or -1 for EOF. + * @throws IOException An I/O error occurred. + */ + public int read() throws IOException { + if (closed) { + throw new IOException("The stream is closed."); + } + if (available() == 0) { + if (makeAvailable() == 0) { + return -1; + } + } + ++total; + int b = buffer[head++]; + if (b >= 0) { + return b; + } + return b + BYTE_POSITIVE_OFFSET; + } + + /** + * Reads bytes into the given buffer. + * + * @param b The destination buffer, where to write to. + * @param off Offset of the first byte in the buffer. + * @param len Maximum number of bytes to read. + * + * @return Number of bytes, which have been actually read, or -1 for EOF. + * @throws IOException An I/O error occurred. + */ + public int read(byte[] b, int off, int len) throws IOException { + if (closed) { + throw new IOException("The stream is closed."); + } + if (len == 0) { + return 0; + } + int res = available(); + if (res == 0) { + res = makeAvailable(); + if (res == 0) { + return -1; + } + } + res = Math.min(res, len); + System.arraycopy(buffer, head, b, off, res); + head += res; + total += res; + return res; + } + + /** + * Closes the input stream. + * + * @throws IOException An I/O error occurred. + */ + public void close() throws IOException { + close(false); + } + + /** + * Closes the input stream. + * + * @param pCloseUnderlying Whether to close the underlying stream (hard close). + * + * @throws IOException An I/O error occurred. + */ + public void close(boolean pCloseUnderlying) throws IOException { + if (closed) { + return; + } + if (pCloseUnderlying) { + closed = true; + input.close(); + } else { + for (;;) { + int av = available(); + if (av == 0) { + av = makeAvailable(); + if (av == 0) { + break; + } + } + skip(av); + } + } + closed = true; + } + + /** + * Skips the given number of bytes. + * + * @param bytes Number of bytes to skip. + * + * @return The number of bytes, which have actually been skipped. + * @throws IOException An I/O error occurred. + */ + public long skip(long bytes) throws IOException { + if (closed) { + throw new IOException("The stream is closed."); + } + int av = available(); + if (av == 0) { + av = makeAvailable(); + if (av == 0) { + return 0; + } + } + long res = Math.min(av, bytes); + head += res; + return res; + } + + /** + * Attempts to read more data. + * + * @return Number of available bytes + * @throws IOException An I/O error occurred. + */ + private int makeAvailable() throws IOException { + if (pos != -1) { + return 0; + } + + // move the data to the beginning of the buffer + total += tail - head - pad; + System.arraycopy(buffer, tail - pad, buffer, 0, pad); + + // refill buffer with new data + head = 0; + tail = pad; + + for (;;) { + int bytesRead = input.read(buffer, tail, bufSize - tail); + if (bytesRead == -1) { + // the last pad amount is left in the buffer + // boundary can't be in there so signal an error condition. + final String msg = "Stream ended unexpectedly"; + throw new MalformedStreamException(msg); + } + + tail += bytesRead; + + findSeparator(); + int av = available(); + + if (av > 0 || pos != -1) { + return av; + } + } + } + + /** + * Returns, whether the stream is closed. + * + * @return true, if the stream is closed, otherwise false. + */ + public boolean isClosed() { + return closed; + } + } +} diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/ParameterParser.java b/blade-core/src/main/java/com/blade/servlet/multipart/ParameterParser.java new file mode 100644 index 000000000..6829d5028 --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/multipart/ParameterParser.java @@ -0,0 +1,298 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE + * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.blade.servlet.multipart; + +import java.util.HashMap; +import java.util.Map; + +/** + * A simple parser intended to parse sequences of name/value pairs. Parameter values are expected to be enclosed in + * quotes if they contain unsafe characters, such as '=' characters or separators. Parameter values are optional and can + * be omitted. + * + *

+ * param1 = value; param2 = "anything goes; really"; param3 + *

+ * + * @author Oleg Kalnichevski + */ +public class ParameterParser { + /** + * String to be parsed. + */ + private char[] chars = null; + + /** + * Current position in the string. + */ + private int pos = 0; + + /** + * Maximum position in the string. + */ + private int len = 0; + + /** + * Start of a token. + */ + private int i1 = 0; + + /** + * End of a token. + */ + private int i2 = 0; + + /** + * Whether names stored in the map should be converted to lower case. + */ + private boolean lowerCaseNames = false; + + /** + * Default ParameterParser constructor. + */ + public ParameterParser() { + super(); + } + + /** + * Are there any characters left to parse? + * + * @return true if there are unparsed characters, false otherwise. + */ + private boolean hasChar() { + return this.pos < this.len; + } + + /** + * A helper method to process the parsed token. This method removes leading and trailing blanks as well as enclosing + * quotation marks, when necessary. + * + * @param quoted true if quotation marks are expected, false otherwise. + * @return the token + */ + private String getToken(boolean quoted) { + // Trim leading white spaces + while ((i1 < i2) && (Character.isWhitespace(chars[i1]))) { + i1++; + } + // Trim trailing white spaces + while ((i2 > i1) && (Character.isWhitespace(chars[i2 - 1]))) { + i2--; + } + // Strip away quotation marks if necessary + if (quoted) { + if (((i2 - i1) >= 2) && (chars[i1] == '"') && (chars[i2 - 1] == '"')) { + i1++; + i2--; + } + } + String result = null; + if (i2 > i1) { + result = new String(chars, i1, i2 - i1); + } + return result; + } + + /** + * Tests if the given character is present in the array of characters. + * + * @param ch the character to test for presense in the array of characters + * @param charray the array of characters to test against + * + * @return true if the character is present in the array of characters, false otherwise. + */ + private boolean isOneOf(char ch, final char[] charray) { + boolean result = false; + for (int i = 0; i < charray.length; i++) { + if (ch == charray[i]) { + result = true; + break; + } + } + return result; + } + + /** + * Parses out a token until any of the given terminators is encountered. + * + * @param terminators the array of terminating characters. Any of these characters when encountered signify the end + * of the token + * + * @return the token + */ + private String parseToken(final char[] terminators) { + char ch; + i1 = pos; + i2 = pos; + while (hasChar()) { + ch = chars[pos]; + if (isOneOf(ch, terminators)) { + break; + } + i2++; + pos++; + } + return getToken(false); + } + + /** + * Parses out a token until any of the given terminators is encountered outside the quotation marks. + * + * @param terminators the array of terminating characters. Any of these characters when encountered outside the + * quotation marks signify the end of the token + * + * @return the token + */ + private String parseQuotedToken(final char[] terminators) { + char ch; + i1 = pos; + i2 = pos; + boolean quoted = false; + boolean charEscaped = false; + while (hasChar()) { + ch = chars[pos]; + if (!quoted && isOneOf(ch, terminators)) { + break; + } + if (!charEscaped && ch == '"') { + quoted = !quoted; + } + charEscaped = (!charEscaped && ch == '\\'); + i2++; + pos++; + + } + return getToken(true); + } + + /** + * Returns true if parameter names are to be converted to lower case when name/value pairs are parsed. + * + * @return true if parameter names are to be converted to lower case when name/value pairs are parsed. + * Otherwise returns false + */ + public boolean isLowerCaseNames() { + return this.lowerCaseNames; + } + + /** + * Sets the flag if parameter names are to be converted to lower case when name/value pairs are parsed. + * + * @param b true if parameter names are to be converted to lower case when name/value pairs are parsed. + * false otherwise. + */ + public void setLowerCaseNames(boolean b) { + this.lowerCaseNames = b; + } + + /** + * Extracts a map of name/value pairs from the given string. Names are expected to be unique. Multiple separators + * may be specified and the earliest found in the input string is used. + * + * @param str the string that contains a sequence of name/value pairs + * @param separators the name/value pairs separators + * + * @return a map of name/value pairs + */ + public Map parse(final String str, char[] separators) { + if (separators == null || separators.length == 0) { + return new HashMap(); + } + char separator = separators[0]; + if (str != null) { + int idx = str.length(); + for (int i = 0; i < separators.length; i++) { + int tmp = str.indexOf(separators[i]); + if (tmp != -1) { + if (tmp < idx) { + idx = tmp; + separator = separators[i]; + } + } + } + } + return parse(str, separator); + } + + /** + * Extracts a map of name/value pairs from the given string. Names are expected to be unique. + * + * @param str the string that contains a sequence of name/value pairs + * @param separator the name/value pairs separator + * + * @return a map of name/value pairs + */ + public Map parse(final String str, char separator) { + if (str == null) { + return new HashMap(); + } + return parse(str.toCharArray(), separator); + } + + /** + * Extracts a map of name/value pairs from the given array of characters. Names are expected to be unique. + * + * @param chars the array of characters that contains a sequence of name/value pairs + * @param separator the name/value pairs separator + * + * @return a map of name/value pairs + */ + public Map parse(final char[] chars, char separator) { + if (chars == null) { + return new HashMap(); + } + return parse(chars, 0, chars.length, separator); + } + + /** + * Extracts a map of name/value pairs from the given array of characters. Names are expected to be unique. + * + * @param chars the array of characters that contains a sequence of name/value pairs + * @param offset - the initial offset. + * @param length - the length. + * @param separator the name/value pairs separator + * + * @return a map of name/value pairs + */ + public Map parse(final char[] chars, int offset, int length, char separator) { + + if (chars == null) { + return new HashMap(); + } + HashMap params = new HashMap(); + this.chars = chars; + this.pos = offset; + this.len = length; + + String paramName = null; + String paramValue = null; + while (hasChar()) { + paramName = parseToken(new char[] { '=', separator }); + paramValue = null; + if (hasChar() && (chars[pos] == '=')) { + pos++; // skip '=' + paramValue = parseQuotedToken(new char[] { separator }); + } + if (hasChar() && (chars[pos] == separator)) { + pos++; // skip separator + } + if ((paramName != null) && (paramName.length() > 0)) { + if (this.lowerCaseNames) { + paramName = paramName.toLowerCase(); + } + params.put(paramName, paramValue); + } + } + return params; + } +} diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/ServletFileUpload.java b/blade-core/src/main/java/com/blade/servlet/multipart/ServletFileUpload.java deleted file mode 100644 index f6b63e4ed..000000000 --- a/blade-core/src/main/java/com/blade/servlet/multipart/ServletFileUpload.java +++ /dev/null @@ -1,270 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet.multipart; - -import java.io.IOException; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; - -import com.blade.route.HttpMethod; - -import blade.kit.CollectionKit; - -/** - * 文件上传对象 - * - * @author biezhi - * @since 1.0 - */ -public class ServletFileUpload { - - private static int BUF_SIZE = 1024 * 1024; - - private HttpServletRequest request; - - private static final String MULTIPART = "multipart/"; - - /** - * 所有的上传文本域 - */ - private Map> allFileItems; - - private ServletInputStream in; - private byte[] buf; - private String line; - - private ServletFileUpload(HttpServletRequest request) { - this.request = request; - } - - public boolean isMultipartContent(HttpServletRequest request) { - if (!HttpMethod.POST.toString().equalsIgnoreCase(request.getMethod())) { - return false; - } - String contentType = request.getContentType(); - if (contentType == null) { - return false; - } - if (contentType.toLowerCase(Locale.ENGLISH).startsWith(MULTIPART)) { - return true; - } - return false; - } - - /** - * 获取一个普通文本参数 - * - * @param name 参数名称 - * @return 返回要获取的参数 - */ - public String param(String name) { - FileItem part = fileItem(name); - return part != null && !part.isFile() ? part.getString() : null; - } - - /** - * 获取多个普通文本参数 - * - * @param name 参数名称 - * @return 返回要获取的参数数组 - */ - public String[] params(String name) { - String[] params = null; - - FileItem[] parts = fileItems(name); - - if (parts != null) { - params = new String[parts.length]; - for (int i = 0; i < parts.length; i++) { - FileItem part = parts[i]; - params[i] = part.isFile() ? part.getString() : null; - } - } - - return params; - } - - /** - * 获取一个参数 - * - * @param name 参数名称 - * @return 返回FileItem对象 - */ - public FileItem fileItem(String name) { - FileItem[] parts = fileItems(name); - return parts == null ? null : parts[0]; - } - - /** - * 获取多个个参数 - * - * @param name 参数名称 - * @return 返回FileItem对象数组 - */ - public FileItem[] fileItems(String name) { - try { - if (allFileItems == null) - parseMultiFileItem(); - - if (allFileItems == null) - return null; - - List list = allFileItems.get(name); - if (list == null || list.size() == 0) - return null; - - return list.toArray(new FileItem[list.size()]); - } catch (IOException e) { - // quiet - } - - return null; - } - - /** - * 设置缓冲大小 - * - * @param buffer 缓冲大小,用字节表示 - */ - public void setBufferSize(final int buffer){ - BUF_SIZE = buffer; - } - - public void parseMultiFileItem() throws IOException { - in = request.getInputStream(); - buf = new byte[BUF_SIZE]; - - String contentType = request.getContentType(); - int pos = contentType.indexOf("boundary="); - String boundary = contentType.substring(pos + 9); - - FileItem fileItem = null; - - int len = -1; - while ((len = readLine()) != -1) { - if (line.endsWith(boundary)) { // 开始一个域 - - putFileItem(fileItem); - - // 域名 - readLine(); - fileItem = checkFileItem(line); // disposition - - if (fileItem.isFile()) { - // 若是文件类型, 文件类型描述 - readLine(); - String type = line.substring("Content-Type: ".length()); - fileItem.setContentType(type); - } - - // 开始数据体前会有一个空行 - readLine(); - continue; - - } else if (line.indexOf(boundary) > -1) { // 全部结束 - putFileItem(fileItem); - break; - } - - // 数据体处理 - fileItem.write(buf, 0, len); - fileItem.setInputStream(in); - } - } - - - /** - * 产生一个域对象, 并判断是不是文件 - * - * @param disposition 匹配disposition - * @return 返回FileItem对象 - */ - private FileItem checkFileItem(String disposition) { - String regexFile = "^Content-Disposition: form-data; name=\"(.+)\"; filename=\"(.+)\"$"; - String regexComm = "^Content-Disposition: form-data; name=\"(.+)\"$"; - - FileItem fileItem = new FileItem(); - - // 文件域 - Matcher m = Pattern.compile(regexFile).matcher(disposition); - if (m.find()) { - fileItem.setFile(true); - fileItem.setName(m.group(1)); - fileItem.setFileName(m.group(2)); - return fileItem; - } - - // 普通文本域 - m = Pattern.compile(regexComm).matcher(disposition); - if (m.find()) { - fileItem.setFile(false); - fileItem.setName(m.group(1)); - return fileItem; - } - - return null; - } - - /** - * @return 读取一行到缓冲区, 返回读取字节数 - * @throws IOException - */ - private int readLine() throws IOException { - int len = in.readLine(buf, 0, buf.length); - line = new String(buf, 0, len).trim(); - - return len; - } - - /** - * 临时保存域对象 - * - * @param FileItem FileItem对象 - */ - private void putFileItem(FileItem fileItem) { - if (fileItem == null) - return; - - if (allFileItems == null) { - allFileItems = CollectionKit.newHashMap(); - } - - List list = allFileItems.get(fileItem.getName()); - if (list == null) { - list = CollectionKit.newArrayList(); - allFileItems.put(fileItem.getName(), list); - } - - list.add(fileItem); - } - - /** - * 生成一个上传文件对象 - * - * @param servletRequest 请求对象,用于解析表单文件 - * @return 返回一个上传文件对象 - */ - public static ServletFileUpload parseRequest(HttpServletRequest servletRequest) { - return new ServletFileUpload(servletRequest); - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/Streams.java b/blade-core/src/main/java/com/blade/servlet/multipart/Streams.java new file mode 100644 index 000000000..70ffb3d5b --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/multipart/Streams.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE + * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.blade.servlet.multipart; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Utility class for working with streams. + */ +public final class Streams { + + /** + * Private constructor, to prevent instantiation. This class has only static methods. + */ + private Streams() { + // does nothing + } + + /** + * Default buffer size for use in {@link #copy(InputStream, OutputStream, boolean)}. + */ + private static final int DEFAULT_BUFFER_SIZE = 8192; + + /** + * Copies the contents of the given {@link InputStream} to the given {@link OutputStream}. Shortcut for + * + *
copy(pInputStream, pOutputStream, new byte[8192]);
+ * + * @param pInputStream The input stream, which is being read. It is guaranteed, that {@link InputStream#close()} is + * called on the stream. + * @param pOutputStream The output stream, to which data should be written. May be null, in which case the input + * streams contents are simply discarded. + * @param pClose True guarantees, that {@link OutputStream#close()} is called on the stream. False indicates, that + * only {@link OutputStream#flush()} should be called finally. + * + * @return Number of bytes, which have been copied. + * @throws IOException An I/O error occurred. + */ + public static long copy(InputStream pInputStream, OutputStream pOutputStream, boolean pClose) throws IOException { + return copy(pInputStream, pOutputStream, pClose, new byte[DEFAULT_BUFFER_SIZE]); + } + + /** + * Copies the contents of the given {@link InputStream} to the given {@link OutputStream}. + * + * @param pIn The input stream, which is being read. It is guaranteed, that {@link InputStream#close()} is called on + * the stream. + * @param pOut The output stream, to which data should be written. May be null, in which case the input streams + * contents are simply discarded. + * @param pClose True guarantees, that {@link OutputStream#close()} is called on the stream. False indicates, that + * only {@link OutputStream#flush()} should be called finally. + * @param pBuffer Temporary buffer, which is to be used for copying data. + * + * @return Number of bytes, which have been copied. + * @throws IOException An I/O error occurred. + */ + public static long copy(InputStream pIn, OutputStream pOut, boolean pClose, byte[] pBuffer) throws IOException { + OutputStream out = pOut; + InputStream in = pIn; + try { + long total = 0; + for (;;) { + int res = in.read(pBuffer); + if (res == -1) { + break; + } + if (res > 0) { + total += res; + if (out != null) { + out.write(pBuffer, 0, res); + } + } + } + if (out != null) { + if (pClose) { + out.close(); + } else { + out.flush(); + } + out = null; + } + in.close(); + in = null; + return total; + } finally { + if (in != null) { + try { + in.close(); + } catch (Throwable t) { + /* Ignore me */ + } + } + if (pClose && out != null) { + try { + out.close(); + } catch (Throwable t) { + /* ignore me */ + } + } + } + } + + /** + * This convenience method allows to read a org.apache.commons.fileupload.FileItemStream's content into a + * string. The platform's default character encoding is used for converting bytes into characters. + * + * @param pStream The input stream to read. + * @see #asString(InputStream, String) + * + * @return The streams contents, as a string. + * @throws IOException An I/O error occurred. + */ + public static String asString(InputStream pStream) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + copy(pStream, baos, true); + return baos.toString(); + } + + /** + * This convenience method allows to read a org.apache.commons.fileupload.FileItemStream's content into a + * string, using the given character encoding. + * + * @param pStream The input stream to read. + * @param pEncoding The character encoding, typically "UTF-8". + * @see #asString(InputStream) + * + * @return The streams contents, as a string. + * @throws IOException An I/O error occurred. + */ + public static String asString(InputStream pStream, String pEncoding) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + copy(pStream, baos, true); + return baos.toString(pEncoding); + } + +} diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/RequestResponseBuilder.java b/blade-core/src/main/java/com/blade/servlet/wrapper/RequestResponseBuilder.java deleted file mode 100644 index a02c39005..000000000 --- a/blade-core/src/main/java/com/blade/servlet/wrapper/RequestResponseBuilder.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet.wrapper; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.blade.route.RouteMatcher; -import com.blade.servlet.Request; -import com.blade.servlet.Response; - -/** - * Request、Response构建器 - *

- * 构建Request和Response - *

- * - * @author biezhi - * @since 1.0 - */ -public final class RequestResponseBuilder { - - private RequestResponseBuilder() { - } - - /** - * 构建一个Request对象 - * - * @param match 匹配到的路由对象 - * @param request HttpServletRequest请求对象 - * @return Request 返回包装后的request - */ - public static Request build(RouteMatcher match, HttpServletRequest request) { - return new Request(match, request); - } - - /** - * 构建一个Response对象 - * - * @param response HttpServletResponse响应对象 - * @return Response 返回包装后的response - */ - public static Response build(HttpServletResponse response) { - return new Response(response); - } - -} diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java b/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java deleted file mode 100644 index e9c48d752..000000000 --- a/blade-core/src/main/java/com/blade/servlet/wrapper/RequestWrapper.java +++ /dev/null @@ -1,274 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet.wrapper; - -import java.util.Map; -import java.util.Set; - -import javax.servlet.http.HttpServletRequest; - -import com.blade.Blade; -import com.blade.route.HttpMethod; -import com.blade.route.RouteMatcher; -import com.blade.servlet.QueryParamsMap; -import com.blade.servlet.Request; -import com.blade.servlet.Session; - -import blade.kit.text.HTMLFilter; - -/** - * Request增强 - * - * @author biezhi - * @since 1.0 - */ -public final class RequestWrapper extends Request { - - private Request delegate; - - public RequestWrapper() { - } - - public void setDelegate(Request delegate) { - this.delegate = delegate; - } - - public Request getDelegate() { - return delegate; - } - - @Override - public String requestMethod() { - return delegate.requestMethod(); - } - - @Override - public String scheme() { - return delegate.scheme(); - } - - @Override - public int port() { - return delegate.port(); - } - - @Override - public String pathInfo() { - return delegate.pathInfo(); - } - - @Override - public String servletPath() { - return delegate.servletPath(); - } - - @Override - public String contextPath() { - return delegate.contextPath(); - } - - @Override - public String contentType() { - return delegate.contentType(); - } - - @Override - public String body() { - return delegate.body(); - } - - @Override - public byte[] bodyAsBytes() { - return delegate.bodyAsBytes(); - } - - @Override - public int contentLength() { - return delegate.contentLength(); - } - - @Override - public boolean equals(Object obj) { - return delegate.equals(obj); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public Map params() { - return delegate.params(); - } - - @Override - public String param(String param) { - String val = delegate.param(param); - // 是否启用xss防范 - if(Blade.me().enableXSS()){ - return HTMLFilter.htmlSpecialChars(val); - } - return val; - } - - @Override - public Integer paramToInt(String param) { - return delegate.paramToInt(param); - } - - @Override - public Long paramToLong(String param) { - return delegate.paramToLong(param); - } - - @Override - public String[] splat() { - return delegate.splat(); - } - - @Override - public String host() { - return delegate.host(); - } - - @Override - public String ip() { - return delegate.ip(); - } - - @Override - public String query(String queryParam) { - String val = delegate.query(queryParam); - // 是否启用xss防范 - if(Blade.me().enableXSS()){ - return HTMLFilter.htmlSpecialChars(val); - } - return val; - } - - @Override - public String header(String header) { - return delegate.header(header); - } - - @Override - public Set querys() { - return delegate.querys(); - } - - @Override - public Set headers() { - return delegate.headers(); - } - - @Override - public String queryString() { - return delegate.queryString(); - } - - @Override - public HttpServletRequest servletRequest() { - return delegate.servletRequest(); - } - - @Override - public String toString() { - return delegate.toString(); - } - - @Override - public String userAgent() { - return delegate.userAgent(); - } - - @Override - public String url() { - return delegate.url(); - } - - @Override - public String uri() { - return delegate.uri(); - } - - @Override - public String protocol() { - return delegate.protocol(); - } - - @Override - public void attribute(String attribute, Object value) { - delegate.attribute(attribute, value); - } - - @Override - public Object attribute(String attribute) { - return delegate.attribute(attribute); - } - - @Override - public Set attributes() { - return delegate.attributes(); - } - - @Override - public Session session() { - return delegate.session(); - } - - @Override - public Session session(boolean create) { - return delegate.session(create); - } - - @Override - public QueryParamsMap queryMap() { - return delegate.queryMap(); - } - - @Override - public QueryParamsMap queryMap(String key) { - return delegate.queryMap(key); - } - - @Override - public Map cookies() { - return delegate.cookies(); - } - - @Override - public String cookie(String name) { - return delegate.cookie(name); - } - - public HttpMethod method() { - return delegate.method(); - } - - public Object invoke(){ - return delegate.invoke(); - } - - public Object invoke(String locaiton) { - return delegate.invoke(locaiton); - } - - public void initRequest(RouteMatcher match) { - delegate.initRequest(match); - } - -} diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/ResponseWrapper.java b/blade-core/src/main/java/com/blade/servlet/wrapper/ResponseWrapper.java deleted file mode 100644 index b01e288cd..000000000 --- a/blade-core/src/main/java/com/blade/servlet/wrapper/ResponseWrapper.java +++ /dev/null @@ -1,217 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet.wrapper; - -import javax.servlet.http.HttpServletResponse; - -import com.blade.render.ModelAndView; -import com.blade.servlet.Response; - -/** - * Response增强 - * - * @author biezhi - * @since 1.0 - */ -public class ResponseWrapper extends Response { - - private Response delegate; - - private boolean redirected = false; - - public ResponseWrapper() { - // TODO Auto-generated constructor stub - } - - public ResponseWrapper(Response delegate) { - this.delegate = delegate; - } - - public void setDelegate(Response delegate) { - this.delegate = delegate; - } - - public Response getDelegate() { - return delegate; - } - - @Override - public void status(int statusCode) { - delegate.status(statusCode); - } - - @Override - public void body(String body) { - delegate.body(body); - } - - @Override - public String body() { - return delegate.body(); - } - - @Override - public boolean equals(Object obj) { - return delegate.equals(obj); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public HttpServletResponse servletResponse() { - return delegate.servletResponse(); - } - - public void go(String path) { - delegate.go(path); - } - - @Override - public void redirect(String location) { - redirected = true; - delegate.redirect(location); - } - - @Override - public void redirect(String location, int httpStatusCode) { - redirected = true; - delegate.redirect(location, httpStatusCode); - } - - /** - * @return true if redirected has been done - */ - boolean isRedirected() { - return redirected; - } - - @Override - public void header(String header, String value) { - delegate.header(header, value); - } - - @Override - public String toString() { - return delegate.toString(); - } - - @Override - public void contentType(String contentType) { - delegate.contentType(contentType); - } - - @Override - public void cookie(String name, String value) { - delegate.cookie(name, value); - } - - @Override - public void cookie(String name, String value, int maxAge) { - delegate.cookie(name, value, maxAge); - } - - @Override - public void cookie(String name, String value, int maxAge, boolean secured) { - delegate.cookie(name, value, maxAge, secured); - } - - @Override - public void cookie(String path, String name, String value, int maxAge, boolean secured) { - delegate.cookie(path, name, value, maxAge, secured); - } - - @Override - public void removeCookie(String name) { - delegate.removeCookie(name); - } - - /** - * 渲染一个视图 - * @param view - */ - public void render(String view){ - delegate.render(view); - } - - /** - * 根据ModelAndView进行渲染 - * @param modelAndView - */ - public void render(ModelAndView modelAndView){ - delegate.render(modelAndView); - } - - /** - * 返回文字格式 - * @param text - */ - public void text(String text){ - delegate.text(text); - } - - /** - * 返回json格式 - * @param json - */ - public void json(String json){ - delegate.json(json); - } - - /** - * 返回xml格式 - * @param xml - */ - public void xml(String xml){ - delegate.xml(xml); - } - - /** - * 返回js格式 - * @param javascript - */ - public void javascript(String javascript){ - delegate.javascript(javascript); - } - - /** - * 返回html格式 - * @param html - */ - public void html(String html){ - delegate.html(html); - } - - /** - * 404默认视图 - * - * @param viewName - */ - public void render404(String viewName){ - delegate.render404(viewName); - } - - /** - * 500默认视图 - * - * @param bodyContent - */ - public void render500(String bodyContent){ - delegate.render500(bodyContent); - } -} diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java b/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java deleted file mode 100644 index c530ba12f..000000000 --- a/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 对HttpServletRequest和HttpServletResponse的包装 - */ -package com.blade.servlet.wrapper; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java index 9b95482a1..f68a9286d 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java @@ -1,7 +1,7 @@ package com.blade.verify; -import com.blade.servlet.Request; -import com.blade.servlet.Response; +import com.blade.http.Request; +import com.blade.http.Response; import com.blade.servlet.Session; import blade.kit.HashidKit; diff --git a/blade-kit/bin/src/main/java/blade/exception/BladeException.class b/blade-kit/bin/src/main/java/blade/exception/BladeException.class new file mode 100644 index 0000000000000000000000000000000000000000..cf172cf9365b0977b37298be36d0e6389bcf064b GIT binary patch literal 1474 zcmb_bT~8D-6un(OW*K$?K~V9l;@6Vs>%2E9<#Xy1py+M7^Df6zjMz zvFnx5^`{|TKMErlWiV3|WRmU zX=j+bM?9Wrb&&gmF7g171ae8A9G60C<9QqT5lF%to-4nkC1YE%DT#K^HGqpe*rt^x)`c3TY(tn z7|hq210(cbwi=8w-BcQ1_wqK{R$$0rwrM08Pmuj6K1`1Kj&cl==2^VG%3!kA9BQ_3 z95s)hTCkX^ok+}(J+g-0@Z^Y=6_R*WYs*7LWw^nh@n;+NUHnhdGl(}#&q{nwwq!8( z`;ZofA`Kf_()cOoQTrDPt+29l5W#I4*OT6g;4Tei|LqanXF&6G$b>=Vm2!@})uQoo za0_T^!xY0JjKMhV5k(~^Q$)OAlGX}kR;Y^69)E%AyV>baaN%1~cahd`Dg=<3y10AlPqQk>ebQpn~#JdEX^bTK* M{xT`L1b5)xFZ;oGRsaA1 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/exception/ClassReaderException.class b/blade-kit/bin/src/main/java/blade/exception/ClassReaderException.class new file mode 100644 index 0000000000000000000000000000000000000000..5a92d43d344ec030b5409ddb2d7728ed62556e9c GIT binary patch literal 1407 zcmbtUT~8B16g^W43rkBY3JQLW_*K-jiQ!3%FNm>b)dUKOkJIf)2e&iL%oO3tpJk$n zzWbxpyDe-RLa@Y1c6RU0y=U${bMF57{p|;UH9QWGV|eOpTYy09r)S8KC$(lTj zW!EdCYa5AhZcCEWZk{*;gn+WY3dj6J!Wv`Qqq(mG1rslQ}kZy1UjMmsOG z-xWzuPX0Mw3{%gQR{jOUL}hiCA-`c-GQb=|X^6dPt+CT6GxlXiTj@-4AX_{(ovunm zS|RUR(@bQ?J>%g_qb+$$#)+^L)D`h3u_yUTzo%-}(+Y1H>9{tYcZ84I+*6i3>{1V- zS;R{<<)xYyQ$39l&TRFxR~?zL!egOR%%d#m)`KfuNc8u!FT z+nUdUI6VK*5Jk)v5aKe!LM0kr(V&?1^a@Ln((+xe)0DQ6A~MWJCMHP;5(e4F&b)6c z$FLS%Tzl&bbCoD-t$*rlB^s$=F|$sEl|QN^sq1Y|x@cGtQ+374YLvCVK8;%p_48#m zP}x|7F@)QuXJh$FrA#cHHA;PP5ubG((~v0VrS`9tw8F;iqX2gqhQbMOpJwc|>;gQb zNgDJYV3iWGh8PNOm2)Jg21(H24rtV9^cj{hi79#qWaThT78Q$G+6(<(!vuW+;dc~2 z%$L66($9X}724A*po|6D3xg;u;wo7w!Zq4Y5OU~q}^V$hU>U7f-vOa f<{3OZIfI7@+@@1=;KX;j9?=sbj}_d*162M3Q~75D literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/exception/ExceptionHandlerImpl.class b/blade-kit/bin/src/main/java/blade/exception/ExceptionHandlerImpl.class new file mode 100644 index 0000000000000000000000000000000000000000..9f44cdb4e00f58ba1afcdb885df5157d22441c55 GIT binary patch literal 2070 zcmd5-TTc@~6#k|Zwq46b6alXTqPCK>iQ&l-UI<2#q7SVkK2CRsc3?ZZnVlm14gZV@ zCi?D=GM?SSf}~DsI}K-j|+bn9AHX0};mzP9qiS48^AEXkq(C zGRzH5*H;@EczuIxCf1c!c7wq!pZZmH85T~JOXkU^{ATD&2U85w=VZ2w2~7brYz!Z? zk#QItN}qdSFH(U>LgJAL+kx!Guen=nbtU(u7YIW}k?;;gNAl$~3Dqo`W$uSE<~p>z zC#=`ymb~OqL_uHlqC{4cL{<|r)yo)eG0g?{gie6kl4s;>$OX5@k#vh$M*d=#ltFpQ z^0*&KL*ePzn!aa4!w1zUSGbCKU;A=TY3Wz_PCvE@>C`Pa=1L!i2a*dS)BPRcdYN8l z)HjWF)BhW_`mL@BKM88$tGmR-BxXw};tma6xp6)tO>30y)RP&SZcux?>-XByv=T&y z*+%GzU{@HG=%NPKa(#FbO8?-K94Z6H(Zng9x(#ISvJh=XN0Qrpo2Z-#y2$u}zLr^T$RFI*w% zj&$&hVLYv;gBR2$nWcjYsTo6t(vFH_>e&`;$vD3RhB3Os=nB9%Cg|;umP3Jb@`FqA z;N%uc>0LKQCxH7ElOJcNzu@-w)c!6#6K`M!bM!2wvWt6|CylsaAwycskP`a=()}Sw u{0~T1b9y)gX=NzVV>}^dXHlJV;X@G0LlAOUCjL1*#Y=h@D32?6j`A;J#8*K8 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/exception/ExceptionStack.class b/blade-kit/bin/src/main/java/blade/exception/ExceptionStack.class new file mode 100644 index 0000000000000000000000000000000000000000..d49dba70d34c05ded94ba27421d330a29d127384 GIT binary patch literal 4358 zcmeHKZBG+H5S}gAH(o>#-(MC~Yz10Se2GO8Lo}jAO}_3pin*x zZi&Ef=yRQU1WuLlf#OU>G#sV^iI{J-Y`MH@Gv8mHEr+3%R!VWby9nbXLYR|jT6eim9aqs7Q&y8I zwBkD+X207Cb6(K3RM62E{>Etg5-rb_iW-eT37cBX(YQ5Ecd0srB348M097t!RDJSz zHe<@AhfY{ZJ@jMxUVqpCKg z`%yQegI9^IQ#FN8V4$V@{YtLg*N@c6b!#kl0FL2epqnQp@GD01jI+Js64%#s63F7! zr*j=5@MM?%*cYJgn-qap(d-`yEe*HGz|8+leylr5U(2D-caM{`9a9e=@HE#o2pw_1 zinRoECxX_$-UF|_E_O0pF58Ycpiz6M;_aJ?&oDT0^wx@LIUP7?gSLzp{A+L8#Be3X#306+^(Sc|@xqJgbZiH=v(4-j;R$>Q zAHxe1P4wPp@Y=^Pe!DHDAt<13va>tiesku0XU@0Zet!A_U=1Y?8HPKtm6eXrrm`b; zMWqpnrmCntsk%-_rcw<<)e_+g;o6%AK@VdLvuS!LOsn#|v7@A;P^_#L;kL3dE#0a< zWMEGi3LBA$oiJ`&ggrGr|Kt6K;MK-=hKYOHXm_6>TP$rejBP|sw{7%RP+2GB{a3J4ZtA0exjcN#Gb|K?!=vhxSx=5~CeTJb>vbB+ z){`Xw{ z@<-hYN$d*6(nwMcR~V{)wp-tAr#dADzZUhZRF8C`#PV@1m70w7tQtwpqGLyndaRWd zR<`#&TxVGNo!>m%q*m%H;o&v|b-{oaL;k6bWAa;_ycgpdsMo0X8CEck33_@o%OFQH zVu>jl^Xb1KOK*Vx8HJZ~Gaqs8YnpeS#$;83us~zJpM^zSNMk;hC~|<1>~wa7jgBf>>o8bLVJ;qoy$@MCny;wtgZfRo`Sq6~51Lte-gKw=E=XJWkq1c2hZNp@G<>$g-Tuk)_m<-TVM%ERF4nM>Fco zD0L{5zZNR~%HKIGSa!jR6${P*PP<~m;jm>1TefU_4shR$^ybNW(mcE4ketIJp3%(x z?swn4_uV(|=KcBKzyAOLJ`KN!!4QEnj$NIqtGYRLSG}iBtr==fo7&Rdsf^=jwi|r!``dpVyel)K+P*?C(mRaR#Und0>>@LB$KZt+It z)@o*HDRZk!XtGx*`$}eMwVZo(Iakbf6P_0cmkNbkwvsP(`$6fIT+H0)VrC*Z@JzX! zzgEo57P|SyJ6cdAUo2NL)S%LQmzt3o-PGNy1P-JoRtOAdt(q2t#|Rt=f|#>y%Z|en z*{YrqZyjHAAaASCnL;vZ*QV{f4Gc1!~5T}5{k-K^<0CW>(%U#)AlW>%45-L~rZ`}HQit10QKp*oJTt{a-;v(z+v zL|--3>Xy2pDQCTOOk+BpRce;zD3q?Qy46j^MXR*!26FK7n9OOK%xTZo0PXA7>kZ3x z{c$v1-4G057lQeE!_cd`t2oVuW~2K|$F-YP*RmCVmZT=AE1G6aTh~oGe0+oVYSVCe z>9n%gbX@udr4-eq!}1k#DwB!6K37~zQN0NLUr2j6U63~nZ9_FO_C~X=nQm^osx`cM z);ojvX!>a+$WmTNDlhiafMU}yZdkhMYPRga@;E29OHH@5K5OCpaAa|`6xB6%)2b31+V*&j!M*yNhY!ue$7=SKHnb2SW6FXQEi0OkZ_6YrfQdQJ4knjA8wYH82K$$UQ)rB%Fj#jlwZFMc}bi zA?Ww`i`F#l2OTM3lcCtGuW5FLCNqKK1*@tWE2^#2-|dIP?xyY#Pzr;)gV@#^(VdFj zL_MRa+nr|L#7Z2_5_n6Zxzu+({rK5TAcpNCT7(Ha#k<2_&!%~6pC$0VgtgJFgnLWN z9dT_Bgt~iz!2I9=&{m#|{TRvWrdHi5c6|4&z;_c|cD1b_kSOaLrs_6r%!V^Fl`Fk6 zS5uYB^aTEk!xVu^xWT($LJ6Go%-_)*z(h^u^Lgs37YTegnAvN4KFmD|oVC6E4+4k1 zA$IaQ4wngONQ_i!4nFW!#LfZkPg^DOh6ny{$xh2LB{49auuODr;(+B-rs_z=M@nd~ zRcFL^6M<(^9qaG(&TejGFB38xRpv>JOs2B+Z=vs7Zw8Cvrs@ zp6cU>B?2Es<%lTF=Ms898+rsTi98dMJ0&#>K=a1s-Eo)@NW49VXw5m*@PVY=Uububp1Q~~={ zUPMQ|+nLFBEL8&8aHh~^7lCs=#lV3PI3KWwNFGC%aSb#t@zx0x!j0u&gENo7g&iy* zM$v*ji)Tc(@H<#Ht47n&?`gA|`-Y~O1YQ&^b3vb?y_3W#*6Fo*0lCEuJ3M4A=*Y#3kwUh@Yn=yhR1(zpE3l-Da}Ar;?R_8M93@| zbjvP{XH<*3+RF5%305>uIW?4|`<7bF>LzxJw6Pf}9v zew{!r+`AGTKLVHg+Y&O)D+A380Uy;JJP1MCG}!B#$KzN8Xc_Un;$Nu0pWr#X$NtLZ zmjhlpgzp8Rq7YEBY&GqwHjf9x2psYcZg>Z}V(>0@r}*j>gYV-8%Cj&AKO~S0Dt-)p z?EUUc@fiFB55-}fj=|3`wfqc3b&LKPkP4n~bB4zOW$<+5AvgsGVFd3^L9Bg^x37uz zHQBx%YF|g&*Te1WC)(E|?dwtRI*AO&;5hz0;hn-ffOi1NKfuXb#~=S4eDXv5H3X;e z?}+yX(-!YXeJOYf&fu>EjDgbDFp2gK;WJ;uxIn|Cr-8~O;2b-FKdkCKQMojGu@M!^lhQnWkOB^qaj6cp71h^c-CGm9YXN0(y1h_oI z#o@E?IU(+f09RqScVPxT&*6f2TovGShD*Q~AS1+y_*xupwom-C0>1Y++!*9Iz90_s z0^Bbdu7&yb3Wp2gkQd;7#c&C@z6-wh8LovmdA?tBxN}et+PNsO^EV8afD+u`aDiW5 z72tl$a4p1@Ib7hEiU9XVhNFBdY+k%3m=`w%_&+f`<-N`DcNjk4|Dpi@SB9tjUuO7K zh7ZR56#@Ql3{Uyj7{1Ez0lx_U4~D1wHO_AVuO{IAC&N+R4GtIZiE#g7xCCtOg6|`S zYavdWj|?+h0(7{`{IezSkI_3$a+u*;h&LJDV)%os{)zA>7@qPsI6u*K%&(iT3wTd6 z9OZR5T%6%t0d9=pDBnE}H<<4{!%@CBINV^q=NK*l+k5cuC5CSye)s;p%sYh literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/Base64.class b/blade-kit/bin/src/main/java/blade/kit/Base64.class new file mode 100644 index 0000000000000000000000000000000000000000..39b3e70fbddd73d379c60116ee4f83de7577bbdb GIT binary patch literal 4282 zcmeHKUvC>l5TA9E_)k)jrnHn&$|i+km)0)S6lhw&|5_}$Zit--6rpH+-q_dN-CBEl zQS-{D;3M$BI}%9n4txMU21q<3X75UTm9NJY8^i+-zVqJB{AT7ivpc&#{Qk{%08oYx z(~u%?(UnHYW~Nhm$PQVlXR$sn9hjT0ONbU;jkoTz}?2&0PWeSImr07}Pc5l&K zwmams&kc)76dEz(fDJfZ_sJ5obgAd``M&A!ev#hyT&3Oh)vP0GI)~zbQ-=13Pa-6AA(5Yngti@wLi57=4F^+< z#nE_V@R6UPNs7We=$zSH4Mm@Ft;(xMio5w9K6gJW(0wUvKTn!98dNt@z0akqQFI1v z({<6H&npewO-Mkj?W;(z@*n@O7l{~7Bs4`D65+Q!%i0u33ztdL+q5h`U{*yAJexb} zzp3`r;IWR5T*d8(wVbfTrcO!K+s9&$a3H*hf&iXDG!fok2u&SYJbn&N!?`6`ffos! z$xk*P-7}V3xHYytyT@ghVH?n0N*K)AVbav&#~H{%=;HGb!#%creD(m0mZKiv~A1-20B3vzvyu30#QFbOzob z@N={~L5>W!_fG)gy+#>MPtm6E4$cSeQ6WtM>H27UpH_XN0OzmHG z(tx+I(6upem%!5f;E3JDGq?+DfLAuWD9*uon1=-%rE!#k434vqJ036M_#`}sb2(V{ z-x-uzfm0~4ieJl!LiFsnaQf5LGhf3C-}^Y{@u^V(WnaSQQXmBv;AI@;;3B;87~u*c z%OcvJRQb=!X`PB%$&qI2b;q^$pe1zT?Pv~6<>1oCSKi`PZ`zoY& z4T_O^r3k$rLwaw*TgdMXv@?hLWuIfs&^XeY5eUD95Z*kdOU;@ua*bbsS4eke>G76_bjeIbkYx{rs?d0+?}-xRSheFDc??Og&3cjbuJ zp-Et6j=iUpR1G*m8t5*EB* zdz@~#fI1k^1|3PRX)FzmmDVwjbL-5%h!Uv`&H8YHng%Sk zE{B}{A7C{|yO^a0PmKsG0&Yb~C<0-qP7|(hqhf7T8W^c)w(YGp6`H2;h>t~#t3Jja zY_l{pd31+vr`p&aL{S#oZORG9uO2WxsdBud;;2owQMUJc+&Fa5bNdLS^*eO?q*vZF*eB_LHsT;*6f&JQuw`w|Cl`E5E@GIG^~WBRo2 z!E#{Cm9}ZniXakN+oQ-q(9ZLq0VkJW5ta#@YYpZ_Pe$UNEs9nKc>X;~qajy5!#an+ z>Ocl8++|AG_vw!dW+F6!^}zw9SdTz6Vu>$phy-YBfPwS|PQ1N#E`*Hz7QQ3)VrEi> zL;tzy-}xBRcTP5Q9n<)8zf9frr$cS}ey`taN>RW_Q)=J9d6-m63({{zkG1z zl+_04Vmm9seEdVAVI2^S7g+!c*jj|+_^i8&tz*~%@cx0u(^c;;SbBqRHCVx?#Q>bb z55Q7}g43{yZ%sG@XAyM{+ch}vJl#V7HGI!JT`2H$!+ElpCR~CaX7-n7_VY-t6xjE3 l_Sax-W={+3*9+{Q&FpJ%-9>%_ZsWJDOK-wY(8d}3{2$u!h}!@F literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/CharKit.class b/blade-kit/bin/src/main/java/blade/kit/CharKit.class new file mode 100644 index 0000000000000000000000000000000000000000..3e0e621f5b1d8ccd924aee1063b531cae6100b6a GIT binary patch literal 8477 zcmd^DNpl-T6n^bE))L2d_QXlZWS6p7S)A3`Y{gELD0bo{o3o8aZK>_ij55=T?Q8^! z166PUiUXYB#(^7`R6!L`IZ|-v&JW-ZP!w-QvegrJcdx5~pbVXu-JIu;<5LlkHEtl&Szpk4_8iojg_kMms>Xy_mZ3u-U z(PfRxo0?lztX#Ev&DwSAH?(ftwE3Ma+SYB`ckJA?I~L!wci;ZD#DRl{4!0jUdhGa# zlO3l{pE-N3vnzSNyXV5i)TPVmE4_VJuk{ZM4qd--^VaR*J9qEhf1r;T89JKHv9WP8 zZ`p;1j?0UWCMKsIKY9A>`MU&G2+Z$y_V;(*BCu*$=0Mb!EQ>S_r@fHq2B!`>*Kmqi zjGrN}Bo@C;pgw75Xb4skXs$$}+i`3s468{bG-Nr{warH~qZxL-z)YPp+tLb-Jz~E+#-^@j*<8!(+{kGh<>_Prvmwf3I@`Q- zws|z#D(I4amM_>2*ZetVYld!l`bMZW%`O^A~aV;qpR7NAE)gob{aa+?hK2@L#DKwM9 zIV`HmEgXGSi~lz{r3kAAC1sj4tDBupwwR|D@18Vh!7s$wl_0J^RrN|-=gDC)b*uU} zPwJ}bm0WzwLJP`0WpSGIHdWcay9jeiu~PNWlN+E9i_|ix#DmxCMNxFf!gIzulxU{g zGVBbt4yskDB10<+W1HX>1sJi}?}i4C>e& zdEKRL=;n3ZVcvUru%73bOJHkyjs_NcwGg*EU4t=f(_+bZDhyi?SG^;{hKxWXb8qAr zr!ID5NW%l)#{QApGbJn_iCxKVhE%-g(j3R}C@;lGBD~F#4vLppOjS;XH z&{LIFgxz;32VPFP;zJIwlP)$j7j}_PddQ8LYa`kh7_e9?)P*hs@i|z*| zLr4vJ)g|)^Pl~$)e*KSlrI^A9ex&H8+h<|V)(}f#Sz*`Kgx64+9)_2J-QFyLFeW;M zbGUzpyhs0O`Ha+gHad!h%G|U)K^;SPX_|7p`t!$z3V1apj)hUKJRM^0d6s2(McO<) z*yof-qS#Q{PR2_N);V*pIyNfeQ@whgmIe`BZdF^#Pgn6am6!V9rt%Qpt8&LiA0o_6 z=CE6K(bGn5`?Q2k7Yi9jeFw^;(E+>Y7_^6ZZFQq(60dmutHKZz%OlepNC+m-f+yp5 zo*}?ZO1KCvEpx@waY+HU4Yo^hJ0$il1aP~gxZM(5uYijqKUJPX0o-0GZlA>7 ztpKh~zY?i$*wgMO^@dW_G2WJesD9a*v}py7s8LuIYslxS!bG~7n+wR6}S&@e33P~mV# z!XYMTxCi%z^-;k|)(1%lxCfvMIPc^u?UyoKM*ugXjJqh{j2i3>25{>3#C<)Zeohio zut#ga6$IR94LB~~vNhnu^B`9P?x|pp)qr~;;KpjeiRZ|84Y&^ldu9!|j|E)52HYnC w&Z+_Txq!2wAk;(Uypz?@7Xt2K4Y;pnaCP8drPhH9kG+b;y^q5q-2Ep10p?(AJpcdz literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/CloneKit.class b/blade-kit/bin/src/main/java/blade/kit/CloneKit.class new file mode 100644 index 0000000000000000000000000000000000000000..52a2c9a6e431eec7d0c627e08c4387cad499345e GIT binary patch literal 7690 zcmeHMTXP#V6h2DQ`jWH>p)HhK)c|cAz~=fwGKDs61`kena2kg4r0mMJ+O@RoYBSBx z;EA8XBQwCjJ3oryNbA_{bYqF&@c@&T_3rA^cXW=9R-bkL`19xA0N`Wzqy%#WXqp6# zJ`=L>m>sdkVZ=h-cp`LTJ5rK=DRc=I2&~w~h{a{*A56QY^#u$;1Yr5k(~!gqLMN! zla-Z+GU2I;j(A7|)sIEQv`~`9i8_pUKmC+eEBif8^>NIpA*h>y*6lE8z@$`~9&&oZ zQKwB!MM{MXMS`wG$Jo^236}vH=p?F-&);R(7SeiP{GuI!j^;)}j;~Bp%z`JZ%jud8 zSsg>RMnlC@YRvVS4tiAMp!m}mZH(hF;B^!5x*h7Mcg`>Ru}bvFjRFT|0nD_ByiETa zf$c1gakkU1St5n(rUi~rtthh@Q>`@naU=qvX`016!4#9JPO?C&gyzY<#mY3s0^1-xqg3dX7vqW1t^o|$yo>CEK z(ghyCT$DYQFid}p>T~PxIe)jdPtZ=|$C`UF-b0{^Y!IRzE;|>rZ9opgO{sa;)8PTu zWi}sSOUbSaX)uoQSKCZn61xTL-GoT7pNIUyvw4yL4e=c2TubY+bwzWDsSS4l}Rn^_U+y2ES9`{ z@B+=yQF){S8=8HVbh-8o(4J~%L2sAqo(g^Y*aUXvox;cm9@Dz*3-k*3blLn&;$E#J z>Og@z6~nDX9pMKYU$P`&#}s#aycafk18nS!)LFf0df=xIxAmz;;jXbAec@26(uKSF3SB0V@ z3e_$Ck2=dveU?sDSb`UppaQD|uCBL6X9oHIoK174u-w8wVS8EskSF`*15IGHh1+X% zz!G7e2QL?NPvEJ=TFZ3|f~OYCBHbH5^B_=N9~^en9uc@ScrZsCwMS)mmB9BNCl_8@ zu|0*DEUt28>XLv2mV$)i9+zhefm`G8%U^ER#zH!Hg}x58MOp$%;9Bv_m0^vLMGwEd z($x!8JP^lsduCdcz=gmZr4hJY5b9<@tV?jqgtt&EmtdX1_2y|(u>>2qBnlN_8QvwO zAO5csb6P+gSx^`$M<1^R>njGQs~V@v=C$~?&$aWcbh_7k%osF5Pq@{p8!9`69E zzrfNrtCxR*mESGyMZ6lMVYq_Vr5puU;Tk@b;U#z(*>cY7mT3d+jhJ33V5(cDIotm= zcpdw{f%gm8>qY^?%>stchYS^X6W$syRFUHbybZUZHsmo@a-ZHQ;Cc8A&&f!Nct#$* lSHSb*7*Av9(ckC!b;vUZ@8ihl-~+7p0$j#9_;Bdk{9k%p=?MS; literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/CollectionKit.class b/blade-kit/bin/src/main/java/blade/kit/CollectionKit.class new file mode 100644 index 0000000000000000000000000000000000000000..ebf5f4c7e7b65929a7d1be9e40733819441ceba5 GIT binary patch literal 23258 zcmeI4cX%Ad6~O16ZSExZiVHSpF!*GHMKJ~}AtTGOEp*65XBpc8vpQ|;vrl*8?qm>2 zAS8jrX{13&4}m~J5=bE-gcedM>78`aD=9zVT0?g0{z9#_t6VJF`C6e|>Mhig zY&@`OLZWDu_Oxyq+=tJA&0W{MzH?hPx4WmWC)d-N-QCr>xwES$w*wgT0Gr%ZE>&w* zsWxC0N9}QFb{epG9@Dj{uWQ@Zt=)ZHJ9cNg2fDLd0PP&nUMLl69l*wAS_XiP?rBbe>*mRh-Xj`dbSIfl%_E0)s9v&$aE$(!Bq*5L%+QZe=>E@=~UOPQx z=ZjVag+{FWeru1NK1Rg40%JWUJyf=<=~B6t9=2-vz3Cdt+n0=Bh^jnhY6Z{K3hu@V zNjv%r!z1NNEiImn)(XXR-YRj8gLc~U@37$E^c?OKVyGS-3WtZn|LIWJXjS)~YmFG{ zd%9LmTj|=^h~3;2O)6U`?YD=XeOa7$^P`oDU8+UX9ap}yQnALeg=#G%3sL2`m;H8_ zwrEnhifxDM3U9%1iT=@%5uDqr+pS8eP})-sNk+Irx#kK{6?h~{IKgos+Za9?9Z8FSCRU_WkZ?4j^n@G`0BlCKoVSVtR;9qN-J9cUdka-yOS6%VOxl1om+Xt(9uI6{rX}lM;G?Gg z!k&^<8?B(Rv)X%CD~>s5D{TXYdmU0od#<-FH_+D6mST&5Z3sRD;b$O`h90mS!{SV#fhHH#`%X?ci>RJ%Q&#BhcG*F}$tE z$z5QxFgJ2^QBRqT`DwU~RyV}3YS2K2Q|ts_Tf+0y;6qrh=I~rKQ0V!_7@nI{kn7k# zF=wlgzE+>Y~sla-|lR#Kl@Kbp3B#o}L__(5qIljnBf%B}a z6nKGZj`vaHj8c^G;#nQJ41~_+N*QpRSnA^h#=^TTdErFj?!cT#+>5|STp2Ht&Pb8C zP*}SptGI%}X#x+cGg&vut;l`(qM;b^Dp6kCsV zF1*KuPHDiBg=+WkNNo&Q%899EC$QCr8Uu&tWOg-9LHxl&pO)W+qo`$Pik%B=acE3< zrk}?X2@5-So5_&Lw&5PIB>~7pi^bnw$7ZBJu6ZmSHnv znxkaoo(G}*zM05fZUjsuyWTcAnazIJn6o>RIihN9h&q%X3_h!nKPVz>aiNgiB5JF{(YoPpwD} z%KIrzvHj7LjC#V7oHh+xB^31aWaHQzSk0%~%r0E3D&pR}H_d4~XMM%bCxA_%)giwQ zXd-V}#>JdWrdTD?_>$(r!k%B(KyT6`yI$WQPP$ zEnmZ^n3vJT=7!SrpJLRnwUm_i6dz$#od#OqXF;@<-%3GLXAG0Km9zeO0j{INs{kj$ zT4}P=i`bG#t8u0|9vwX|ybS6^F zGn!(rh`CpbuxMRk&ZlM`Lpsfv3q$uOkDXL3&~jU^wcV)IlwpnZhL_uiY3c0KH{@!% z)o4$PLR(gg;}4~8NKMiEMx8=2D3rCdRC$KcIZTFJd$*tH)-X+Jid`3}giAeP#bKFh zw9T-pY{^Q$JB@z3No{oAnbouaa5=0QREMLqv(aeBlpo@$=GU2q8L`D%jwfu(#St5+QEWEUMPYZQh)oV~C&KO+rg?-Kuh_(IvRBb4VkB0_$6r` z6wWO-2)iYL?=f*&7aJgH7e}r803$q!7cqY6z@kEW+ib6Vxzb+wx;N6gl0#wL=P31k zL08eLRyE&FYw%6JT@cbn2Pt}9sl|}uZwA~8j5yxg0GFe-OtH^KK0HI?VHq&Z@Vo>8 z+Z3nd$k`fa{a&$isdro)U~tuHF8-sM-DrWP%6dCn;soPNe5isa-J2j9jZJqJ&f9Hk zKVL_pJU=CB$tpK6jh!(pYb>=mPaN)7bhT?^sMTRb?<{Y+(RFW*p}S$SQB*0Gri*D) zd4`#ZGpX=NQ=t{jvz=Dx8NyGY3biq6iJ90EbvMywoO;^8D^_Rm7HL$!K1Svm6)5`M zlWdcXTnrlxtyAZ+Vo|Bsq9^;7Mn1HFiGk~sZ9d%1?=qDGXSZBBrGazq@Dj@}r8KyY z(1Ms(LoK*!yiwYy*>pc3?NNLq%NIG?Ei~xAz11Y0n(rYxdsz78LK>ZI$PI%=$EU{R(AWtA%5BELklG4;5g7Fm2_e#&m z*rw8UTmYzV5$B4^)A$7aJ=NFWu5u&bS;Op0heY}tWl?#zk8%a3XoAcwH=l-^5VU%_ zkJVk+(!8fMy6S~B&zwZ;VtixY$U1}Q6d!v=dC%0bAsKX3`*vTMecuG42G5uqm(yw2 z7R&kl_`RUpdHDiSyM-C_Um$9do_g_Nnf3&A1S}9WQBO(z0#Oq}eQ_3u8tWODWbt2m zi~XklF|B<_X(wXsP5jwZ-0t7g%da>Bi{XCSK>1}dbYyv1e`y2UWz!f-V2gR zg%Tc8Rh^%t@+Eqfx3>7FMf?lQ_eF+iRsIr(3wp}wPyC9eIyzXZSo{~Q6Glt;>rr$+ zFFshoZ$xZ-sf=4;;dfmSzVCcQ5Y9_lfna~*=G};#i-7mMG6xQ=!s2iI7^S~FTFKk% z3*vKC*|YJ-y5je#NjMFK{0{>1%xOcJ)^Qwjus!7MI>=q^0E zsoNVT0l%Y3d54`z*zH~6cP~k>Fb&$ddJ^*5Euj`S5zUU2(5{`grW55MA= ztnGJ_FpOb}GL(ceiU~~@@h^(Sm->Rj&w<=a@pKepaSy1HaIt$Kp5Tz4s2rRm;dvNo z-6>`g@J+q)+iz!t<0pdW7OGV&i8=heTXpPji5q~oA(*7w1`&Er!N&IQVOZz7N zQiWf|PAC2h;-&pF4fe0l_%`C(iI?_G{L2*nEY?B%8seq>vkmsIR`|87i}-cK^S4;y%s|GmUFu@Wm2KSI3B-$e%d7ixT!_!{vtf2R2NY5XYh2MoL^{!55I zi2h$p{3Qn71 z-#ZNcw<-Mf@z>vpb2L8o`a3b8@$Vx4Zy^6={tWB)L|)-q@Lj3!P503wOg?~T$ z0P(jHFYC{3hW__KjsFnwA0|H7{@oh?5#nz*@Fx3T(D;uM|1sia{!IKM#HZLD?Bm4W zY2Z!u=Lf_$u}`qOh`*b78UHn8tsX`0qvJ zuT=Q&vmX%u!-)K=H2z1#|2QJA*3U=TPl*31@xl31_wSFgpAr9a;)C;dtK$Eo>=(rU zG9rJc#{Y`=UlSkPe;(BM-w^*>;)DJFj>i9v_}@q5)%y1s`vdWRBtAI*Pb&5wV}Bz4 z&%_7%Kb~p)y3jY-Q2l4+TKG=S% z#{Y}>r-=`?udY9zV$XOyLi{9|pZ^B)>i+vF0OAu7`CZa~7zg8tpFn(Y{L20t`6Gx= z5+CgU0nL7j_@;=w+`#Kp#7`kUIQ|K9ChIm90sk$*(7KNsc^KcDzu|CRa$b72ATM-d^ zg|LYDqlpi;|5wHTg^(tGG4a9n|Do~p{siRvlVJWCg4Iy`@}=wH!A!JXeIwois-+(@9tB0`Q9fue)--h z0jFRWOTejc8UDAA9SO4hG;n*a^>p3*bT+ cgdun??1g<$gc6KE1!`~rE`dwgIC%cQ0Vu-h)N6n-57`$K?$1SI}21ceP?B8q~3c>VRvSonI&08 z#a~qX!JAc{Jm|?PtGrl+l#~Y#TII!yRo<+!%9B-A>Dlsi&nD9$oor9J#^5DMcfarb zeDA%P?&*B@*VV58-~hZIf(8QH9Xs1u)D5$9N^+K7hLL&qx=j6uX@#Aa~ zjjo@Y92_1>_p{kmqUd}g`c!W=`Ca}TBCx%ASaVEP)oKD4ihKG9DbcjIM zrNt5phrpU7``v|q95PJ9JwjkrtbLR~V~>@iA-D~7_@Tya+p@!O2iY(_V%pTP3g>A~ z%UZ>fQP5q(GPROzWeT+D9Mqzb^d!}CG+WSZ6e{W2b9$a?ZJf^z?}bTBtMe6*+ED3&bS)%coAXIw3-n@nSdYP0?=hhW(?3QDGz zQ7};~6^yLmYEHRCZOjsuqFv6qmaTau8*A4LM=P5-I$@Yd`2?=u-+H-#H2TsV+F;pn z*$PT&y2*0nDHepH5mrVL3N+W!bj_`lsFFz1GV?XGq{^id=GGb0ZPPIGP7U$;__dO> zq+A>0t`WAH5VlW&ve^188=J6}&S2v8;p~KNJ2XC%r6vA=S=iqJD@=_TC5nU5kqRch zB12Y4sT#k*xCls{k_#%K1oN`~8vmoX6#`jFB0*USmQ~e0OjR7*RY{(pO7Fe;@VVld zs8?qy&=rsi6^$w{g=N%}G;mw?kKcz14kt{P=GhifvbR=%-((_6HL4`Ek^;Z!9R5F& zr;>yyw8Hi#*a{kfmRQn1e0$(7b~xXV#G}|yxtO7LTF3J?flWy(s~1Lf+hF7BWTQK2 zI0SYiYkbkb(|^ct(pFBd5QxOQF9PkS!Vn{HRpFq&LQiA_*7oWZ=NNUTDK(L`YGl>; z2Ewq9z-5K_ma7!eVfHNrzn3tJ1a?c(FDVF2)V+ipRtQ9;{vv8Z!8TF#e;F&}B*@8; zKr}aZ3?{Hojd`zVcd3%V!)bjDh)5>zt zC269CQ(-tr;5P;LlyX+L-2a=6hu@(yhV4$`i@^IJ#Pi1~YnKspgpk(dBq&(yDwGG) z7_3Rca8#|n>r_B^1z|YxnUaCu+wsL0h8_Zw3h7bcskR6j&r^4t;vv}P`-pICuFW4K zWZ!c6q4FI%SQ;Y%#T6fok;Ok4;L8ZP9HaDHci!>_Y$L-5EwO~O6_W(6DR5k;Qma49 zxc9-B(^k>KJErL{3=`;GIv#e#q*9mbQ13B{mm7Rn6^4@p`f6)dA&S6e<}+@xS*}v9 zZo6rth#R*s4~4hEF6sMk!LHs5pR2%BW6om<%rgrQH|HDYA{eK-&5r$Sn~v-3Ph7_e z&6~Pgw$b$F+4)1s>ao4+NLLu1RHC!?7X>^i@_APgjG+b z9j`;#6M~;ISQz}GF%bszxyII&C3=ZZ5O{TodWWoOyc%WZy*JlM2Twk&8E@}j%7|&qcv^Ugut_YDO}O4uwry&ez7D}gPs(+gkt?C8ln7{ZHIUZv}2&x*5^8Zu{>xSTcZ$H&xXD&BaO3%_t8 z75~lAj3&JH!=!qE&G<5r(7^&o;f1j=!4;=ymcZ)RK%#vB8v#2Wue5F?Wp`{~p(d&F zXv!+vS=wi?^K}!`gO~sO7CHoP;srUI3BhH|W3@O#@D5J19ty#G^ZrG^iw3m}8jgc^ zcWJy1bzlcz58#D-7`DM`Sc9VwjvDwlB8;QBzE&7F;dq@eUXSAq!nhg78-?*E9N!|0 zH{-YkwxF#Jw7C^-#h=@7bO5~}_&fR~w2p7O{R_DBI`?M>{$$<(G(#KyZ1SXFC)|aj z2;2?3sv7pp)395j;W*dOz;W%cN5HW;&+=Xg?u>xDhx^SuX7+qsrvx`8;P%6PQhWDH zaL>=fJs{wGh8~pQuFS(dEZ}@UACcfb6mVT|NWl5_4oh&K3b_4?;2xFWz7}xZi{$T^ z1ow@A>xH=BC#IvCzdi}>djZ!U0QZxCOTd6&&*$a1#NMw0Zg3HMLlWGd0`3IJ^Zxik z9R6ER8^+Ia9D$U&J<=rL(l8>8PiAkcfE$G|0q575BtFt6;GTeS^!OC_`!s(7%hnK`cP7*4St^%dvfb;ua5?{l(fOEiA#uWuzd67Dk*|P=Q`2c=i5OC8lBlT0p%S8cKfoG*SnV**g z+;ahN9|*V$>V4GkiGUjnVDEDQ*B=0PO~5@5F9^IW*?$e+3b+>o*!xky^#;KGBH%8< zOM;*N^Gufa-v!*u@QQ$2^0|wPZK#-W5P?_WH7QPFZ{6h31Db~X-4Q|J#+It>(@{@7gfs;MeL0O87nmV`)Lj&~37gxQ(Z%&bLt zoW4P?Dz#F%M1nWy8}Jf{v%866u$3KdxZ+~hyR+YX^PO|%c)k~}|M?F9eu8cj8VtJ5 z#=TTX-P;pm(Hkm}VDGW?y<2JK_ub{qT&drch;d|8g0=~B43N$f`zep|puMAFf)^-@oZI}d` zaGJr=5%(=?jcvg)Yn^_eEjpvdnDE%7nN-5lGCZ?ps4#Uu^Jsp1ggn7m2}__%#E-=; z^3^h)F2%FT6N8Rx<9RB4JmQ}4_#`9slX%KTx5!4fkkLJwUGd8_GuHF+n>0KYy5Jik zKU5dZ_tQ+tSbFaA3@xdp_-!70V|kUU&Kj4F=Q_bhQq$6p=nFlIT=_|Km*35uFTN0p z3tecfh$kqc`5XHlXXxPGaKZh4hCz_6Q4!X3IFmFXn7;P7TSPsTm`SEE)WGQ78lnKm zZDmAVWFeTFCa0ZNqbCToF%nkLrmM?RDDH+a3Tb~FpYt$OwL@#Dfw!AdSkOU7{{_)}P$PWc^I)qyhUL>jVNLtp z8>6){se=VIS5PW~Kq1RTum~${h~QHOXFG!<$52gPFC4|vfX>a$JRPFlE|S4uWnf}* zCQ8JvTYaEgAL^wxkDjW%e9F3?E3wA&}>2_X6x79XxG z{SBWyD{*J&Ud#emhO=~US19-lKBqSZU%;2dbM63jzC;w}eUk0M3^ts>)_{xfHE~Ys o;WHTaW-!dbDk*5dCAdt#0N>IT5hH^u&>@vS(t8p48eQMN0qWQ9`Tzg` literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/Emptys.class b/blade-kit/bin/src/main/java/blade/kit/Emptys.class new file mode 100644 index 0000000000000000000000000000000000000000..af9f792daccbedc2fcc3f407671f74fb97b9e1b5 GIT binary patch literal 3905 zcmeHKTXWk)6h3m&$Wq)UO(;!DThve>DPVIcwm97H1DZp*cG4}NOWHi$>1Xzg<#Aj!ln$dH;0H-f-R<#zHTovHn zq+8up>#g{7xv5p1fOe^e21eR7y|z0Rmuc=#w6p&Bbkwf7PIs!kqUpuR@|B5pJ`kUc z+AFq8LhVaj0QdR)u)kPtTysFK zsg--gBWA!{u*}&dUDwoNZEEOr;>Yn&TnYNIsuVRt z#jlTecQItQ4z*%g-P5%lwT{vAGS}w#R&sB|ITJVBEW3^$5GOb$_K;=);|0(mTb5%5 z+XBq2ZyXCSTXs8CggrcA(;ZYj&-JpfFJx~WIUe<0`;vAP)9nu|n*^5YCi{!Kl#dxHA7-R{ zC?h|e&Fx$L0p{@rMKIp<4WSZ)gUtr||r>zM)vY zGIToh%yMw)GaSJ-8QMXVomUQqeh`izOCe6El^c$jl%+7Oy+nr+xC&8%s{u_#Vd*Ww zOd8H8&m~w&#|oo8!B7ecI~@sT(r|bVOfZy+G)aXC#?taeIWfUnIu?)61XHOj zXIsC83KLF^en~yg>Lk%p9j;WaNJUDsoD935`@yXn1edhW$46 z8lf}7>clmPeLUK}QRi&XvwQ&*?bS~ato&rd9eO6MSfQ5ms+A z_=tM|t8fG6u(b*zWEn~zGn|JU!<%r6;Q}l&ybVhXm*F*rci?q~cVUI$D%@lE2Ha=( z03I@Y6BLGzV2$Bh@R;G-@D9UwVI5U%U^@d(P|thtKI{Jg@(c^`A;XX0V}_sL6ExKQ zDSXE8bNGVcm+*|?CTubM3bq-34d0;sBDOP7!j^!sr{ez#_B=&zU`Y$|pRjwfRQ(;k z{hRS>_rN9v6h2c5?XJaE6uj#IiY;mzjT)oGMDC5PM5siAiJ5MPc3^Lroh9%zK8A@V z`rn5#p502nks%y0trwwkHOd`l-#x84eIu(Xj z#PFtQ!{Hva9Yrmsj22ah=ld>3){94Rih(%Az>Q+py3H>v*O7{bYaTazDbxWqm>saz zIsNOSu9Yp<6oydL^Ia~{XVgXdhH@lrtC=rQ;Zfgi@NHqE1KYTQede307hR-P-&4T~ zqA0TikK4pOl)BbFfe25iawwzfz~yHSs&dc6BUltojuG^W)a%-DSY2D%H@F*~`O!@4 zzO97C*$D1;-!IS`ZabKhU}F&;4bmYCmokunaRTG{ z{%jRwooogFs<*yX=d#8ykpyYYF_^i@qzJ}`lS$PQ9)an~v6&Nd;0U)3%w+_gM{FA5 zM*mbAZW8h=M#hVENd^ZR>Z>67G>SXit=ycTSL9cfNL-eBREQhqco0nIEVdVoXfx{ zw&%lYa0q(<`gh2F9J}xpF8&Ph6W9jU06DmfZKjQaD{vJ@8nRtKWSGVM5;)gpxDmmS z4;ccC2DjjLk6m|X8euorvD0A+rX%g{MA*IS*l95HpZ)Gd*nR5QC7^)bCSVpG;x~yq G-~R(WRCbvF literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/ExceptionKit.class b/blade-kit/bin/src/main/java/blade/kit/ExceptionKit.class new file mode 100644 index 0000000000000000000000000000000000000000..5f62a031ba9c20fd40119f8018303906dd25958e GIT binary patch literal 9351 zcmeHN-FFj36u(mn*@Ob+OF>b#h?r1mP(GBVR-qO_Qob6fl&9@x+73;2b7m(6x1F6P(`KTnEeHFM?r!eycR%LNow<|!<*#SY0pL75 z%s?N3lM(leb&mzbN8V$vI9Kzkw7A4Xaq@{z8-j(w4JIsCmIc@z&fU>I(w9 z##q3_IDsAc!hHh$6JeERAWL9hDm%$}$Q{^C_MW;Ia2kcR$F%DDVZFg>p5%8MJe;f1 zdNk_hvXw>ZR;gd}I0`j9f5}^*?upo{5wz-rTMcRC2BC24p70l4f%5c81Fg~J(WepV z(}*-5GuN$uQ;%E{oh|P^I%Mz$nh+H+bzeYeJVEai^M*kl&z`>jg6G39&|*%T5c~1_FTR^p~ zRR&A6+QYC}eN$1d#d7v8Per?v`NdHEv?O5?b4$cS==^kUHYip-b~NSG=b?oP=zKGaL~rA6Us#b^OXk3VJp-^4 z_7XUpFQ=VkVpd6Zn)|S_(woit9OV_c5hZY-9Qt1EzQ>uoUwPOs7Fk5#RN1DKhM7HL4Bke_Y0;Gy;?*$ALf4!lC(Pm31UYE-xNew4s&El>^|CGfR{d9VjQW|eAz@2*qbk_>KhN_n*_eM@JE3GkA;s`$!Z&j zZJyNo{g87!Ntza`{ScOpe7SY_N`>}E4!lj^SBrSIlJz!qQp^8sCr7~Xy=FwKSC$DJ z*C&Wp`{JEpsW3|*JIxjXPc%7Br!yN#j}2?7IgVHdh6%Ad8GPwmO9BH6RNM_iF(Jo> zz!5#v1ue1;6bbxfk&m`h*H*4~T^A-5IvYEROZdUHo=P>iUc2p2$FwMnmmD}x;9HA0 z^v-VEGY|rYbn9meS!f}aH9h14h zj}ch52ze`YhbSne8_N+mn=dQbQhN<v8)-2Rk1g{&`~UGn zRX+_>Nw9Ikba}>votBVCw~GB1kGo|8IrS*Yz^7Q0)x85(3AtpE7`8KAF?VpS=W<(e zc0k}*9P-v#xDt5>t`l;+m(kr4FT2dcF2xD#!97B{>uuSp7PLCKa(Ljt6d^|~!rIfu zCn2*sCh0=d`a~sbEs67eI&5;EUS;x7Wxtwg_!2<;V|oVe;P3o$r;>qbd?%nadoyqk zYlNEd8JJn~GC*9+Gw@)|+XRWrxVfETQG`Dp%N0NB9|C->0AEx97{sfcunRvk@rw&P z@CqRJBRCHZ4rH#wYdjv;lud!@mn>jCw~5xT=Ob3-2kt z?<>8j-RBJW#v1$ug}_H4orb@RdC><~ zFy8&Be?l>&o=+MWo@or9t&>^T47lGk+~;t^=yBPA`(5Gs;AWf~w_q0k52C#ja2xJI K1@2>>eDOCxW4*8d literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/FileKit$FileNameAndExtension.class b/blade-kit/bin/src/main/java/blade/kit/FileKit$FileNameAndExtension.class new file mode 100644 index 0000000000000000000000000000000000000000..1a918a27b1a256a1dea456b3e095eea40fd24fcd GIT binary patch literal 5046 zcmeHL&rcIU6n;|*ZI^1Xg1=B15EU-%g?Lb7LI@^}6$}&-y-jzAc3^k5&Q2@*Lms?% zG|@!w{uTZu#y49kkQNw7LqI%qcW36C?|tv>?C$jY`TOg40GNZvDM%2Qi-x{dl}P1#@=_vE04cZGI6nLZ#cOh_HwJ%M6oTTUEpw zXIbH<7QR*Bz5?T=(KBrO>FY5>bx2wKFgTg>2wGby_d~ULf%SvOszm(?X2D|tId77! z^jLu`k}oYUZo9k@e*wB*?E4r0ML}9srhg!d8e0Xk;IV-8E7Y0tlzgApnE!_9y7gi_ z`4p>^tUza@_g{))RaPs|DXL<{`yX^JcQ+UIw&2T5b0v@2QXP(RGKY_~zsfD9g!w<# z&u!`Po5_o^3%JBO9Tp9RYqM)H)(C;onb~g3A`Q0*Odjn?pd~>di(G%b6?9Q_*nT+>7++~h zEdpMWEfERKX5JVSv8#dNo$_*vD37;=UVjb034jwHa=8GYo$0$#CZc z44-;3j3Yw=?qY1C^q$dxzd6kNXg!~MunoX{oST3NpfL|Yj!Afcb$W#DB(|pi01o7J A-v9sr literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/FileKit.class b/blade-kit/bin/src/main/java/blade/kit/FileKit.class new file mode 100644 index 0000000000000000000000000000000000000000..0e745e1fb150cce08768d476c93e34cbce00d1cb GIT binary patch literal 12692 zcmeHMU2q#$6+SD;mgG2&V>=-YwB4jlYK2CIB+xbqDYh&V)rxHN`SGFzQbvN^8AG>hMYrb^ZH+`x#c7nP z6f%pm#q3mWUV@=~KvS|!RbM%ifPM)gV`CEZl=9=H^9k64Y&h(5h7LWY!kK}I@yv91 z_Av=|Wh%vDwoqQ2%oP)`AHit}`YW@G`RrUa@6O(VD$+PToSiRc3#A;IUCPdm7styp zMM{oK1C>Hn2r3A<*X_H2CaT%kv*fhzqx^Wye zS+!NtAhXVRRJlXL-q$k{^qy69)jlUdbTl<5K`dj`NgVEzU{4UEtZ5o%0#eeR zKUZ{T=C!G*wNpRYRAXrm>`vhILx*OO{uOY;QJ+ObOC-uhQjJ)3~Ofgj`c} z-LT~)B5(1e<(w_6maOV^)x;guHgRd0m_)Ckl4a9q;P~nquGQsqO;apOraoG(qB_AT zy3|x^SCkbZA9fNajfrzut{cRXsk(+@*H&d44I>*()WOPQ+NEjQr5$qvw9BtHnuck+ zuBZmb{CBgMPHdrw2+IjZc+FNdA;mi?=%fZ$t$T-XmSo$I73VPYC2vKcN-@6^R?{1L zCwPQHv{T9icmzalHIs$x5fTz`J~xxysF9}g1Zch3+2p@nB!wcgb3y_!7E&g_BOtO< zs@_qaoTiZ#MZ_QNpL9Nrm;ht5Vk?<6YSlL<}r=Vr1Er#O_@^?WVUZP z(2hgf%)_n@*-$O)7IA&5Cg4E{rrIkKxlypaGU}S2LSA%kvORD6;!J}3IJ?2wpDMPZ zRBO^{r5NTW##Xi5*bZqJ0bD4pEn{Eab?f031Y=60=}KWD;7NAB&teBnr>POBbwqpXL?bqmCEYKM#2~id><4f2|T(b!+-X%E7i+pQd#^I9^jPOdi1T0BV7TAT3>wo^~ ztEO75L(_csE@Dg5xMsQD?e(WCy1L=c1(7Hc+DKjZBC*?-b>&i=$W*I*_5G-nY|Jc| zaGNlw@zI4$uA0gvK*Ph{Ha3_ym}>04Oehwq&tTK|L5>lv{&Pce1UXBa7WStnNt2*` zI$y)T~4!EvS(_LQ@qyAcQ6t~PH7kg|4@(+s{6TB92tAR5C!$~m)$G!kHST{1x#T|G= zH#9?Ebx=|F4miScJ8M`awb+7JbxB>(72I;nrO_75*<ZkwkEuQn11z(Kibe))v8w4Mx-;m%`n=0{MNdPALvOkqi{kLZ(3?hg zpV8Iz5aXiF~ zhv5zwVdVGW_&v<{0LmX^<_c3G2cPBF*#_?SY{%#x}g2QNQ1#P?s?#0g|I68&i zNcg|+Z8-Yq(CE+M*smRbj^iiw4)8CHpZ%^BjKK$Rl!On$37nw}$3hGzISf^YA>!aZ z1Rv(&9^l}N5bhx^?lcFt8N!`qaMT9ZQ=Y!38Qe!Yu=9-&PTbD77~HuI^!+r16W8}k z2KO+0lp7abJbxF$jdO9lc>dMLJqHtz;o>;@q-Y2?$;EN>Nuvxd+kw965KdfQ)5j%Y z3O>fz8JsAdoiBuN=NVj(pS-xd#^7@B2;Mr=n9ni9=Q$^_(0VeYABPxbyI}Yk!|-t^ zcERv_hM|O6-?5-EmobXAH zJP^W(`!^B7UF61vlbMl67~DLF+c_V?iN|x9!9Ci6K0AaH*T@y@_1y;E`7xU{F&dx=Hx~UITxXkPvtz6yu z=SpkNMBnx`C!qm4SM#Htp z#Vw9K&fu&LaL+I}y93J}!YfB5vnD zd|VPX#BYtBpmw7;;mqlo3+WTi)E*^-6ZWr1V{n@t`1cZnyWRngt=S*PIxRR+!4r#< zFFk)^^nI!W99xrpT0CER-CvjVc1Xe#;x%;d0mjZJ#D9zSvX$7AsITMdv-bp}`7>QH zuvOMm@L8@6!F|c8UwaFT4Nt-6xD3I)z+)(e7@qEefjvPt;PYGt+*a>-!?WQMW5W%2 zhRYCSE02LajW@cABnjE@EZ2tZBdLZMy4j0Hh@stHaGu<~S3?ZXalHs?1|Gv&h~W!e zFkJT;67W29rZ(e1Xz64+9dJ~*59>Y%iG6h4iFy@UipE^54Wh$g!+?vjKgQeq7!NtBp)nK&n(%cwt>Ndt+nJ~=hAcf>vQXKPM`hr@1K7IfKe!? zpohSPz}Jd4Go9ipTW7_Z#dKa=GevQh1%|0VG(`$}2@FPGE#}mVk87)36FBr>YPz&k zsXi}N7G_HmQ&j>(l_uGu@J*+FkHCpZ*9io3#4@u&o`wv8aaPlGzEU^L)iuj@T<(`(mnjNZI;d+g2#f!=^w$U>S~ zp22DyAA1At1-O`PI+F7Wck03*K*|LA>LK%W{MdKjbWAZ$;H6xC8K+FTI#0nF0s~F9 zr+nY_({PRqe7EHIJaDabu2apmJ=0>sbRFvXZq4F$aF=E?RfAKVYZmj7$Ya_Xt8+RW zDY1Y`9HzR<1M0Yf+DvE$6-duFJk(z+J({2(O;C_*6q>VReAD(^U(o1VC`^lL%#nyS zPPh0w48qucip8jKDWhW3l zY)9z0Fx}`B9pXy3d0-cE;!-C;EyE!UM1v>VMb&xD~! zMn}P|OS5nyA38GX_Bw9gxge32502;LMO9R?NT469lq#E|#&gid}L7XL3q$vWsr$ zYkb<2dOZ1}HygFSQ!s^`O8!$Yv+X~J*i;1i=i_E=70&?yTmWq4<9``_a2}4~6}<)D zdLWIzEWXR<?H}RI76d8N{t@14LFnB#!dE~eeYQ(6tkA=kNZN`zZ*J2AqD5@8JPv>-J7LB+$265%e~YeCpuimC!31NY(m2ErBGSxtW!SLi{H j5F`zO524hua&t$jcy|;l_rL_=^uQ#{;=K=_9>DZJrT^0= literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/IOKit.class b/blade-kit/bin/src/main/java/blade/kit/IOKit.class new file mode 100644 index 0000000000000000000000000000000000000000..5fe171865bcc00cc70a4928aaf8c7c38d69b811d GIT binary patch literal 10601 zcmeHN+f&?B82=8?X4wLzS8J~+R$ZzEtMyju1?X;Y1;NlZ>?sh8@D z5B>pt@XZ$=^bhEaozZc8(iz`<_0>1WN3UO!Wj85j$q6p%j4}i4Cg1lv-~D{&OTPX6 z^DhA46ud7%8-YWvqYYM7-5k8GE~|rchFYP6OFA1Ymd11@K?i}};Eti13xlP(>r`U| zdX(bD{A@XYX?S9IvNSs8xwm>k^GEm>1dA8(GztJ3{X z_FpiFNtuxE|1mnj*fa&{Jf<5-3J0meB?_wr=a$SYS(Vv}O|zXL(G^E$)M*{*C9G3S z2vnR>NS$KUHgrvAvg_HtLVj^{JdIh799Gy|zpT5mXIALEZqmwtJnp&7uSWr!u_Ei{ zvb98I74vB^j<9O11Tz&)+hZs!RjWyqrTk5e+CfEKThcb)OF|Yc=mu?>9wXlTJjH!t zg5qYF6mO}BeKCblL#0PN-AI-|$UsG5FHU$S)2lR{)5RoBWh-%s(;G`n+@^-jc5X`g zc(#q5f_p`EOl+Xsgm^BfE*n{4bl7p!m6FFq^Le9u;wq;QM%>Bb%L`TX4J|B`x)DKz z=!J+{tdl^wOyNWyEd_ZB(;Eg|P>nKEnQ%Q4P_1cRM>n(4Mb&YebaDb~G-r=4lEP{! zjVz?&=6XU%1OZbD;WW3mU_&GzNb@x|=+hMT7v8=%1M`}03z(;DX-nLMiCU*jon`6> zk{WpY#-4cnu5)Ta!RdmDr2d(IecDmOa;b_#fdo2XBW7`2v8M~VVK0F_xwS(Oe|oW9 z!5;piSDmBIq`$U5EwMD!m{uL#|6aS;!4`Fwz!7ELi42ZaGRz87g22(764`Es`qv6T zAY1R`TnUa4*cMSP14jw`BrrY^%E5>zt+Matocsvv&nbRH^DLHuV}yLwDw_!8O~fAw zW=qvSry};n6lz4mK=_OObF?6cYoG35LSV0h=eL4mRpXWjvL=2B!yu;DPzG{@>=TXw zF>}P%OmMZhSz?kWpr)tg0A{gc5bICkTApQaeUh;5c_fsfiPMUnc_l?o%f`whZ-8XW$fpUs|e2 zi;qN+NE9lBDe3WXM@|WWhm=*bpnsnwa7Vx_LL#-+A_TVF@CUA#?YWte+IESK#17;) z0f_}Rz7(P8qop7hub##9M@)QZmYW$34YIc3@?#wzTz$|Q6NLpkAy1p1OR!Y$Zpd1r z3(|3zkn^n(vH9xJT9U$fDSa(uqD>Bn6P(t6y#P5&;4=a13#lfMXhJy6{fJR?ths{G zs5(dB-ruNKbCEX|dKtiH)nn@`;6F?jjwS-f`8y(~Zd_P%oLk)|l)8zLrc3kBu$MiZ zG6Q$quAEXkod;=MB5*EQexdWcU-y;ppdLWuQ~p9Sw8+Um=oq7efB=7rfFgh|JU_s< z4p4p?&JcnXULlZB^L*#7vaDZp@erR=Vxxy(i5UXp$x6idlGf?TDfO{Mu*T~Iipgu# zd6MuC*839v_@Hcgjz;||gR_L-t&rgD2MIKM46MYy7 zmi#G1;{l`uRSe|l4k3YsFM)(jj|6Yx%wyFn65x!aD;hi!ct{(@odh?~?P0mA9m*uY zEa{F}T!OcdBkYzWcn3wUC4>aGW3Rh}K)Bwx?z;F$W)dGpyKoX;P{H?9@b^L30$cIZ zevlx8S3B`@8)WhNw#fG`*oRlUp$93p2e00=<0pXZJ?Oowi-fT0>VQagt0n81|Eh-5)dBc zAWYX0I-wtqCm=k=K~N(ICt!e!;OiLLbdZBkjUb$aCle5!;vlR<5Kh3;2?)<{5N<~h zo`dJnbACMdK5WQ-n#1>DjPFc@&yT}U=NCA9cVc`mars{6@O>2H8{zVea`--p@#VRE z1rFb*5x$d&-aXGjxEn*b!1YbTRy>5SV+dm#K=>wxkQ5(08NQ1kC@>zeUn9paa3yP3&52c(ygQMJ^*AD-XA%qRed3484okr*Qk|I$wz+ zo6Hc33zeiYBOU-bm9{lfbw_x@t>%K;{SckXD{I3xnq4358orB>c!v`^XpoCFA4t1B zw99)ghN+T_!4lXj7skQpuA=}@jqTEjwJS{(MM3|AO@$kDNKDRg+vQ?@J*D}xG!xQ4=S zh76`_Bcfp79F;{>f}51(_VHpV!z^Rp&nnK}$j>0ie9b4nWOJ0(U@hc;|6i3zifHTD zxcE{gCFZ2(dwNcmV4jL*Sg9qrbL{ZXq{*PVBBO}Tg>`EG5zGVK0_Z{k^kh`%K;CzPi+bQQGRKL=w02A~~FaVSE1*m2yxCB!)s=#HKK45r|G9EI_j9|E*G89s~ rt8k6juhV;x>~Ew#Bn-(X^WoMAhDS#X1-MPf0?ff(`Yn?sCzgd@?l9_g literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/MailKit.class b/blade-kit/bin/src/main/java/blade/kit/MailKit.class new file mode 100644 index 0000000000000000000000000000000000000000..788e13791d5049e67ab3bc50ec0787acff772a1d GIT binary patch literal 10335 zcmeHN-Ba9D6hD^&n=G_cYSn7Bfm(%DcP*{h0;OH~mgO@GwbT|b*~@ZEHrXawro21j z@aVHM{s%rgqcb{v?H}N~Grs%ogX6hb$cEXl8zC^PvoA?*&iS2la?ZKue&oLT=jUGm z;5N`0G!eLBTUs(txsiNEw`g)rr&*TVP04jOrXuqJB7sa=LyZs6Odf|&Hh^wv=eA| zY1rCF?CY1H!z1?fmx!{9RHtTB5_F;_7ix2ZmdJ6JJTa4+N=tB&z&V$m!%x(Ag^!F+ ztO_OqvN|?9y1Jx}EutLvc|N7859by~3A7GzgFC|n&h+#y6KEbWvn&Sh66h#@?wDnn zmIPNw$Gs)PVz#Mov8;mMSKvBzxM?T_%Usi0-X2ima%O`mS*GdKLZ$-MHffG2-LA(I z=<#kPYcg9gOh?I6N83;wl@Mkm%IK1Oo-de|qqwx9!*xZYhLE_% zls)?zjK|;}Hx9L&eK6BhzMylBJBnQ_FbgvXJC9Y=9Me)t9j>QW;kHsVvTU6jm=5bm z!Dm|39Y1$MnJLqFr zRo^5vvU;t#OL)%4gy_Gl59YR*W$|nc_s8KfbhX1J=q7Nnr*c0*EWkU`xTKja=GT~& zp}3|N8xN*N^<`>t(cXR8>}+tGKv%lPz6S15wBnj*o#zPL4NzHWMCF^_WeKhm0wLD^ zp$b;LGU4us&5SI8t37Fd_ZSRt*@^@S0)K>XnO{=<)vzOE)e3?1Av5xEu*drdc@Vd{;cT!M!z!yhXHchTVf9jvB5kNL&cmodg3kzNrdYYs4b5wL-NL zx)50`%SDw%EAzn8`Z*!_I!%*$t-o!e{?1#b#%!F^e;Zw(D{6A(cpC7=8^^yt4VE03 zs1t;|tkXn2;Q=VBei456AT%fbA*c4Xp@v;o;Zk%O*A3OhaEnP(kDaG|D`Y0UGoFApxU$wz|hK!lbJl zZr_SPTs4c9#>TnWkZKow3(w5BM>AsZ823d)g^9tFUE1D{)EKPpJ5*CLNicC6PqO4P z_ygXCF2KVlcvMHijjR5xYquf&tgn3z+vk1l*RXxT*M1%1@CLR4?{Dtj z-*WGrsN)j6jn{YFBSL5J3AuiO%a1zW`w5iaT>V$^Dy#w2@;+YMOI&abKERd?A41Qr zgzIR(_=1vz-T(;$u7oBRcLP51;l#TV?&APldLJ(7!&TS!#KY~t4fw=|YxeZr4A8gf z;bg?!!YJHE{wDa;^_2L|GQK|m|H6mA19t=U4g}!7@o+nE2ZnsO7SG;$0l4oxoQ$~p zp1lt|d&~G#0R9IbegsB6{FsNAJpJPV_#b`vNtp84U5@J)0l44y;ezuh9f14Ohns~t zpT2Tjf^dI%xE+{;`Ovt(J)DfV1vWgvvA#Bu%k%emO+4)*X6O7ONtL#=JC<1y(~wEW*yQx9eE%3Qci8|v zsa2Fwi#`rY^(2i&C@eKu$~AgO8mqI=Doyj%QeL9M&`d_WB_x`=g(LXPve@>cD|9V0 z){P*FGU@!26ZcUDB`=x0Kx-`BMKv!PFVN#{uC<8x=w5g~YqgxYe^`V4zR6`90_w## z3ebp*KO!10A9{gMpyeERJ#SWavDQOoI)9xOzeiOs)_)r`^zs;b!YXD+rWt0&T^62~ zp@$9bUxN78&>inkA-C0*i{}b+?sw_IGnTKaIL18fGQLl+`wwc5!URLFyT5RP*9zZf z(9mY`lJ5`fk%qvJwO?<@hLBr4@&b;I%gbK-4C=YZ3@}+xs>O;8GNxyQ+-GfmF72Z% zX>wgt8jGw4uR@-BMD5?2VFH+j!&7h&ju2QV|5%K=>T?E{DbFR}aB0(3ttw>kCey<8 zzx+9FJHimS)!0K7jYV(CRjyc_ZYTn`%X=bOsu$rjf%CsEhp`$a5Ui_AhrA}7I@90k z`)*x}vaE}?WH!?{_^i(;dAWAC(ffp0-jkp!sP95uy0Q&}1ef-q;F{^MvqNC2E+yBi zF*Amn0$fCWb~Px0xd8_gS5VEKqy<>|?w}&y6ZpP0VGN!-xbp}D6bKx^BN2B^z$D%Q z3Q+8}B?zz`!{0%eLfj$j-9)6r2Jc|{`TXn~nE%klEZ}_-F#xl06z>j?C^!bku_bT< zPWCa3xv?(8sR0bH2QW;)8Jsf)XW?A8rEnfwfJM9lWF~L{F5%Nv>=#kO%XpPP1J1Sh ARR910 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/MimeParse$ParseResults.class b/blade-kit/bin/src/main/java/blade/kit/MimeParse$ParseResults.class new file mode 100644 index 0000000000000000000000000000000000000000..f2918471c8ec47570f2d6ca8cb2fd6de124adb6d GIT binary patch literal 4922 zcmeHL-EY${5I>L6uAyvWY&y~6vYl%DWk?`_ zc;$~moRgJpYGIC4#)NoCocMlsKA$glx%>A0<7WVP0P|%SAy79uY{X2+#yi$!jaJ0k zys;&0V@1ULCDVrA$nLMWNh52@FiK!DgGNkt8mp~$JhTKx?fZlim}>5l)~pt?^N2v% zq^+p5I9zwdxPsQsx~jf zB!P)t4W4PO^cYN$@rSRa=0-(b-ln076A>{hl%$DPt%%3wAq^_)o1C_J7%`2YgoRtI z!|7~hkUAPbX6TZ8(RI3#8tW*CqD;E;$p!Bb8C1M<@&cj99`3 zbNBh+-m}SdD**M9Hw@5_j6WnXUT5e9a$ztB-pz-F1FZF&nav}&i$AkfFRA}FsIYq! zW>~}wiHRCB;{lH6W$2>8eJ6I0nqlHtza zy_8WV;VeE^a}=C|^Y}*K0$fBnmv&H>aqO3NWq`E%1Ed{8?VWDdU>3&!r4zUgH}UBX LzL$`43u-?Ai??YD literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/MimeParse.class b/blade-kit/bin/src/main/java/blade/kit/MimeParse.class new file mode 100644 index 0000000000000000000000000000000000000000..43e47f307dde18c9518c1959111528dad2d1b3b7 GIT binary patch literal 5487 zcmds5Uvt|;5Z`m!ST;$M2HH~oUef|L6dT&|uQ7qt#M8{!O=;51l$Xv~I>#5wlIHG| zX+8m;fH%GeGcZHndEkKuJ`Tf5N^KP@vBZcr<;7>6_P4vYx4YWi-~RgfR{*#HUl*Z3 z;F6MNeaM7U-(&l%-nE&<>jRz&DjiY_&aAu`8i^ z_qg(Htx(vhrfZ?LX9z5eRauwPl?E)5!rFaDa^>3l+@hvC^n}f{a2@JNw`=pEx=G8W zNO5X1$8k07aymk2molnR-IPQf<~1U2SEFTh3fJ3A^$|3MDnAADdnPW02 zZHZlnXdNF^b#lvqE2OaZ0!MXQC_N>G;J0kR ztyF~h@j8iaI!?MO!DQu9%XV3kF;iBJX^u>wDAX-1#Ro?eAKw{JLGM1^Bhyy9C{4TJ zsR*1;_>Q)!Ed#C+_~CeQ>8tCbEf^J3EmsbiUVmhAFD&1Wt&W_I^haw)_yUSkv8|al)~cq3B2X^ zdV#r9G`tx|Q}N4#C@16R#HNW;1tx>$E|0Tijfg|ff8y`<0Ts@^JKz`uE+(p{Vyc`u z-ZF8=S&Z%rMd0%E)(Q);@|NpMlea|BC7&4$p2GZzbEXZ);j(EnrMN1>rv$D~9}P{k zgapn`>=oe)0=4PP;&Ud{C;nK32I@bq3W|Uuf!MGt3Tp&)gi<&Y3kF^aF5wVt28VD2 zF2ZS;#kGh}1u$?mpbRhJ&K&N%k5o7@gYqvh|6pn1Cph~!q&tVd0SaIZ&WAgIxC=+% zUQNK+G2CnLI?8?{$*rTL1t6 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/PathKit.class b/blade-kit/bin/src/main/java/blade/kit/PathKit.class new file mode 100644 index 0000000000000000000000000000000000000000..e05e2ef1c9f3099c4cd1856bfc98db32b483e08d GIT binary patch literal 3110 zcmd5;TTc@~6h2d`y@-M+Uhu+ziUqax_9P7nQ3&dagccHgG1KkP4(!gXv$GBSD4$I< z(RY7^zr=WE3sSO0*93_#+nvt2pYMEozWw<01ppqyqa0)ijECB-_)N&kChM?D!(&Ze z*%GF*!c6<6FgeH)7>@5eCR>%)jZN+v0)=_UdABlOU#bxparWfQc*JB!m0_JY97N?VOVr5Khk~S3& zsZ@sg%(!i8P@ZoGm{qSlmZfaVQnq1~_qDtBg&!zwXnZFWb(ysG8l3J$mlTuSq>_t_ z@X`ow_Z8}vzt0sliZW_;0$wbn5_;|jo^XYsVH9wU)y8h>$TdpSE(S`|RD?8=O}-%{ zZnXer67mLrE8oVVr3 zZ*W~_NPCummCL+!riDH4{+Tsx5fYei{=o3a)k7^iVU|lf-10twQprh9-|TcUpgdeB zWFrMFr^&vM^tspk9&YWOfmBwHS?HflJT`iF23A#McwJe%6Bz4<6UW|RYYR2elFURJ zVNyO+u$pY_+-x3h67nHMYptvQt4~K2(J`{ak+>p|6X6Qe%s+%a-sYi1VDa}&wOdr0 znTfsC0^|(>#hQw=%NK>^qru(fFa1Vi-oa`Ln`j@qx%E5yJJ7(86nt3I{5I=~v zG$A|yToQ3}&A??i0Vna4i%)qNgJRG56y9c#LC>JXP`v35;2S{kGYr2O8Tkn3zs7nO z@oB99Qtl;u4tAx``WT)Ha0RaJT9`q<`xdVCu`m@|$i#Z%K+*pMzGq-Ej^LpFjXwI- o9{pP|)z|OsK6)>D^rrtpZ~2#A24><&@4!R+&10r_p$zwb0<>|zDF6Tf literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/PatternKit.class b/blade-kit/bin/src/main/java/blade/kit/PatternKit.class new file mode 100644 index 0000000000000000000000000000000000000000..5fafd5122ce49fe999fb1902e530470ad30fc2ca GIT binary patch literal 3571 zcmeH}%Wu;#9LIm@y7jR_$6&l4rVQu?YBh-yLrCm_G|`Q*Zj*qMn|Q6aB#vxnVqCd! z;mnycXM_Y2yYojOen|>7Xh0%ytSY5`d_O<`>^S!K>$gu|0N@VXDnQPHnv!sJ%zK zjMU{$bc>ML2E2>lDTy)t*Tu`pd?$pvcvVvq+^Ar@rE$ z{fHY^MTbXAg7aDL2|p<<@h(RfROV`l+1#Tpu1kfh1@uUJZ8R^aDsi>g!*x|yM%@OZ z?i%&5f&(RM9V2ZWI?UJD63Z62)IEnDSTM@f)~9H50mO9*fROQSG`&q8bwN3aA? z{tU&ZljV<4ImB8Hs`!jF02BBFs3a<+C$Uz7lW?jZVHV>KB1|0-p%zET#oU<;+--w9 zn}M4%xN{k}1%o@EfqPgS(P}du4DW1NX+@u4drg r8eA;{_s-z1W#HZ$+;j%+gTY}%Q?BfGxgt<$wUX8{{#y~g z(5nO{YV{og<-cTyTQE&vcA&qelvEWsMW)}s@f8oHyU#n+kzOENriJurpk&+SUig&S z)$Jaq9qzbHp-{k_kF3k-V&Z569bKdy$wTT(O+BWa9@Qw%KLzMvRvxF>h^N_z-DnK7 zQ~SaTq|!9$6Oua2kL|TN{o&nji$z+vM)r=mV6tMl6Iu5HS2#k`Fham!82wPI$k9^K z6ezVi6(NoM4&N0%#$*?Ju+1V@XQdl-BMNoggHn|FaS&6(8IyK3MOuz0R7=XJJ_z^` zLUy%}Yk`;<4s+JVmR7>=ju2Y+gGi$!XWj@&<8h4zw|h7&=1mS**EiQbIXp;mX}CW- zOQYr7U_s6>Su;k9Rh*FdvX9gCZNwh+M40f<(;q8_=-o#mrMpUc^lujS(500$GnUfV zYP^#1-*kbN(${LtIlqkX>&Vx_ek7RT%zf?gIAYra+oBV^JAC_-pmbH!rP zIohewcqq=L@h(7d*;Sk+BX%(-tKu9R4TIvwGES*+I#oDVo$!HktO(Ht8)j#~f;j@` zYpp@`odSC~uFhv$SZckDyf#adZ>o{4jU}TKb^}-4J2oRnWm+^%}<~(^) zT$&t)jk2paArk_u8uMwoZ@m?6$6=~N;C3$m4Q-)q!>*Ndx!cZ UxRZEXgNOLGp$v7n2lt`*9n}>*9smFU literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/ReflectKit.class b/blade-kit/bin/src/main/java/blade/kit/ReflectKit.class new file mode 100644 index 0000000000000000000000000000000000000000..21b33cebc56bced218a8c175b4c39e6c9c3656f7 GIT binary patch literal 10638 zcmeHN&2to05bw8y><5tq6x4`1L_QLf1O?<{V~~U-ENnt#mmpulWOkAanVnf?W&`Ne z3m2>O;MFSs0S}g1rB!7ftW zrMuX`ptpKyc6RzQgF>}xudL`!nL%HrcDr_MzJ7kXUYX)8bGo-`H?XC5+^`I9g29&I zkwpeQQ+7ko!!r!}BhAx}V><=tXWRd}VmZ2No9lW*(d=f+Fjdd6Ev4nyOQzm*Pb;Nj zeN|T)x@M{l3bj;iOGoLZxCbJ|&(go~@{g_pqfW2$hO~Pbv7C=NQtQ7LAZJO_{3erdW%UN$7{@ z$MgeDZ}}yqdrXURnfY762&ExflV`qE_|8!(V77Oqi zgKx7UiBuU#SxV7_EUbtuoFuUzNw5MO%#ei4`bQe{cxb4pE*?CdNbY^Y=$aa@pYG0$ z34*@ydcBNe4?hd=2Frax$fN)Fmzz#XV>7)}jN3bkH78Ccai12ubrdzn3MHzJ-#Lo9 z<1-Es6?B|XKkOCZI@OxJAqL34teqxSN*dd*UFxX*O>-L&H zr{j&%bRo3!R1uEcP=brz!c$VE1NcD;7ToVX#-?a+Nog ztG?fSUwb@RM(RGt?dmp)=P$VP9jW)BWw(~P)XQgcktIo#eaB)tR)A{^rqk<=uOs<5j%T48omgS1 zAI4Q7KWQqDV12tq%%}7NHa>~CwTBkInt`#v(+|U4z$-c3!ipz7_qvYnl%NdW8FBG# zcq^{yfulYk^0`AE-}YnOSxBd4Gc=8%Qq69o@u05tM{mpc?~&xez>>XLWggaW56cmG zXfnumDncG?{F~RmJlx~2)%Y*d!7#)y z&Ka(Ycbj#*;CFlW0=|8N@BZXq5Vk@uJ`F-13i$mzwiKa+pWFO*gSOxkKs6#_}S~X48U{v+!si}F4&E~im2sEL#~5+3AOLR=N!E3 zd$1AziUfa7z$?Ie#y#ga-owE2Aqj3l!0m(m0*?C<;0{P|ivn&KMnZoNg?1zS>k|A; z0e=`qrFO?8xO*FLZ-#c?lGr^e!G9d$AHi{WTd*7PbV7prT)>@z(^6bng8N3my#o^h zF5>5m1ow-8JNpE<-$GmwCSfY%=Um87l!wz2yMKiE0?fks5MK%L5l=Gwp91~@TnzD5 z34X5IKI;$hkKht42z*6$-;>}DZot(-yY|i_7#velh z3B)Tu3UQJwTO=yALFx;dD!Fm|oiE2e=X^fDet-QA0MCIIp+MlV(N4=}Lbi_B32Ti! z=JM9Du&n{tf_dUIe=2lLqg-BuGJ)kw z?3UI_mtcu3eEKLgH_AKVE_IY22#;BzBn`A0dE7TIXr(+nBR86t)(OAx1EnpE*My=DlM&yD)6~2F z0@n2dPdLI-69!!4flFg`=vbv`625wa3PVHb@_ixk^!9NDpIPYHEV@azLt~>AL{TQA z<4%Y(l$CPAIp#2_Rg_VC7Vs3*4{Z?Ifz_P(6AU_MmcQ1Toz2)L@jk~#woV-$#M%3I z`eb+fA(U45d|G(7KP@sRaazp`D{aD==YS^1)|I)#Ia8CoUgg;EjG{BEuvef2*Q&4p z*9olEdzYe&#V6!JI}+{X9@h2y&>wLHS*r>0&H>FU2p5@gB~xxTFJ>iE1S$g+YKOlSk^Zcvp^aM4xP>di0|M3b zb)r($ZD9PdH?5;oN+OlVf{o{O=J>wsdw%@<@(loZw?{{?|LZj3hRdHJPK!o4C;s<#{aIBe*ESKumv#q*1s349KgNcGbPh4fk; z@qqd|jD%!PXhkEVyOM|YIrXZ015N|(OJ)!hG5?VDIbBVCYoc$fG|=2qr5z2K^9R%+ zo*zf(Ngj`pX(o|rCT29xZ)f}>jI?nyJrkPxOeK6>PKVb0Be2*Bd7*XfFp|O-j@mfl z24ktLGqLZqp;=bz4Js^+Rls{fVPJZAf^&vtkViM^R%~5zf+)&V63L7>N0|j9Rus)JX?1zkjPnAg zlUpps{&7%8V2s9#` z3;uVo2*01^b#gwjH}Dc6f`kaDvS{v2r5BNRN4TnI$-*QJKFN z*p!dErbJ|XZ zO+=nhp^o%n(pfb2>5)d|Revx0R1W?Jd9VP>HSpj%ftC8W+)Gs5Vh7d1yEyD}v&T@V zCAv`iOztxylJ)6k$qj@h@U%0VEJa0GueZnFJie3I;_d3#`23AX%vcyIi&W+jsI`^i zWeK4_Y7XWI5L}sB7E;)I1SX56Z33AU)#6!rjlk?lG*zvY&cSt(|M`j3+$jHm zx2UIrj_{ckO45#2O`iv5krwh>ZBAR<^O;7a4)gZe9;fpTlrn-cPg{x`DwU-HvtFB8 z)aQpC1SF}Ckd`Az%TXBR6YJQ&2s%nz>ehs!9+Q#3Ca2x#{wHdo75>2JYC*>rp0Lz} z9j*~e%(4zWt2B*^qgbNC&``Gcu8;`KF0SA;3w@i^F4MKp*k}c{D3cMAvEzix7>t11 zwrZgQ_f}L8Fxe``Wwt<@O8K103jKMOcv5qU* zLO%96;Lwp3bGm1)R2PU*f06u$5k(J4B16Xrmyc4j$qi<@D5PDW-7Lkwr8G%+td+-& z8FJCNcVPO&WJw-`?MpBMLeGm$NxZ_cDSD9rSq3whgtvCyY#Jm|wD*{Bi z?_}dF!4ZRs&pRNdB--Ov8hKl z08=TA+GdX0Nw&On)!=TCa7DJ*Ikxk_>f17C$$wxOcwk-^S`T8(Ei^TMDo0(0e>|?GS4N%fi$ekSA zAn@ahX=0Zpo(&@*a52Go2vi4vv{M>-<{Leoc_{})0{)B7>FDs-DwM#(L6MIhI)TMv zJ)%TQJEt+uH^iP~Hq=-~>#?Kd{<6Dw8s|AE6Zk0wsAoy&2s|qO(0{;FV3&hCB-2W9 zyi_%FP9gvCI+2d!jL6o`DP)%_r-L^x-E_L=6!PeGc-J%Azy@IAnrCLcWOdOhSGIUwy8fQOsT!-TW@0B$Di zqI>bq9}ci9_1KjXb`cW)Zg;!K?iQl-5$aFCf;({(?}`2G0sG$Rv9Ao=_u~O}caQBR d;S;yxr#SJ%NYTUR`1ulXTSj>bWBCde{{|8s$&vs7 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/StreamKit$SynchronizedOutputStream.class b/blade-kit/bin/src/main/java/blade/kit/StreamKit$SynchronizedOutputStream.class new file mode 100644 index 0000000000000000000000000000000000000000..487220b4f266f874d8bfe28629d76b7f18512250 GIT binary patch literal 5550 zcmeHL*=`dt6uk~fvoz3!rR#x}xR&V*N z&FdS&)>o|NtoumV*_AEnb+nS=9d9p(HVAF6FArG)oxZ*fnzGf_lag4 zyFei8D{q6qWb@Av*f+8$q_B4hOjLd!R(*~GmsFeQ;W&Y@UqkO}t#kp#$oTtbQgfsH zH@r@;mFZm3k2cA51$ z)FPg5253$kkFKgYSJj*vwO^xq{GuBuZE4ge6!n;Nd@W9YYIg)X;0}paM8ApuM^K|1 z_`(yGnlRuR7rZo9hn`iM_TsNnrNYoqw)vWnxO&&H2kR{KZ5&;rk3(Z!527fOZn^h} zW0a+0LvDwAf??Du%BbB6c&QkV_CC9|)iKSpw;2cYr8yatDAPVuSEFBINpknxlPVQmXChzlKn%{nklL z1>EoYr{8+gBL~=Z27soQe}qhRHcEerIzpy7YYx>*OTIFk;f1x&XKa9g8w46%-G?Ij zzy*5=$}mxeB1{rEU5RBodf)T~m(mz(;;rjR*llsW>L%T#MU=<<=S&ON{_$tlc7!3Y z*xY-P29ql@f8>%eusd z?7p-J>m{EV!_k~7fvbHzO5p6@6JNKHGag>pd@PK?Q|KyQh7C|a z#WBm4!CwwWqFNpbSmyC5LJ9jvu{MXO43?!&P<}ai;scC-!Bz%N;(G)!0ON29-{q)Y zg41vYTaIBW#^59k#(>7bIh1oAM`n@fLV`Azc50KEO3=n}UD*TIrN3~|M6T?%jY)dV zBywGa=|nE)*Pg$UxT=XEpm6vyABX}!A*O}`2KbkY`f3uH?hpma;22~AnDX`o5JQobDTByqcIFSfTd zNSwGLaVi&1NSwHGKq?Y&-~<;=T(}@4I3R9_BZxP4x}M3t*xnE+>W8XEw&%@n{_oAa znYZ@$|K9!@0EXbY23-vLJ=ZMO4a+WGGj15gnVM1M#p{+|ob+98)W+*$*47x|0D%T*(pf|ETDQ0^s2)>-FAGvZusWB z?xQ`w*+4b2JvuZf92yid2BY2~->Nqp*VltK%h6547Q7j*-%>dwDup*Ks{(l;k z>y4UaTE6Zz8{EYOZ+pJmG=0a_!}Q4)bj#D5c9qXsHm=@TY{6@zS@UJd_#fYg4?{@v^x1RKt9qc+Cn5G~9fn}=ND18<6z%os(xu#JXsW~1u@CR$c zG1fuCbz&O)@?Mjn@3~~pK?WY`f%UM7!H#?-dSwxw=_T<>qql;;y3RH0Gu)jLlg?mk z#W9WAMZ>kk{o=!Jf8O#K9H=C|N+~huvK$8c@)fBNELG$+5R9B_{q*uQc$mRPDgGIF zgu$mNUZ+SytlpZDgv3J`?2q%ZECReOUkOk4QY9<{(D@APW$?(pTWVT_=I8H60OD7a(kS?uPLIID(hBtrKL(?F=84+WzPwG z4d^#sYl z5Q9pxT$vG{!win()iI|M>H*ZhUe^daVxLvkcKlCg@|ZhZ;H~M z!6uY+r^pYE;nx_HlT)eHCn=9|lTOn$xzLM);o=WJvIQTj81$5Fo4X@5!}B;+e(27L z#G>-xJ@Fa8xa0Gsh2Ku>4|TVN~RWnmj^N2?up-Hk0f1J+?2p$ngc ztUiJ@6tIMiAnYOuLgn&=(+XiXNr*J;Av9c82>VDvq=6!Eg|MF_bjNz}zCzFw2$Y6f z3Zb7QL~$4(;_#V5I7kvAFDSz23gHk*h%`J(Xt=Eq@+2YBKoP!G2nCW5X*f)1_)#G| zK@uVj6yYa@@FYoyGz=0Nepd)bNJ6B6BK#>4o`R#8lOnrCMn>6vtbJtGrSyAR>K7@d z`fZZ>Jp<2@ildPU#ca1iI8G8G4HTiE5S}9mQ6^J_;|k%#3J7NvLWv~AdvQS_oFobH zk(^Zs&y$3B4ZcJ;1uu|Uo}p|S$PZwg_2 z1%y8&!a10bcE@NHyh`k<|Frt8gY&o#cflk~iHZOT7x4cjyt;<>eXtQO!!*1OZ(~p?zwl)hfS>?EzW_&$rG^ukvD}uIiU~k3a$F!lAfFl8G7`(L4ZvIhy88MA=#3Y$+2nA( zF+C3%akgi;uwgKX`VT*!XFyLpn~dd?0XPC#iy9LRhJ!>hoirzp#&LhsjkKNm$S@j_b9O1?@hskj!ohzzG6$Z?7|L62Ft#Y$h9klW@p1P1OYO=L+$7 zGM5WL6bZdvEHYh3DMPVTI++N-DL9@GC7G3QZK;s}pijDWLrc~0huCm#EQ#{Y5Fm(i zF-70WP-b^JvnDkhfHQF@t7S>SZ}ehvV*t*C*sYgt`8LqA^{Scd$~p zs8(x|EEA{+|lD=b`MMOoC4sU{Y;iDec(-b(F0Ozq>tC6(!6MK!`z z(I{5J2J*9AHOy+tj~k=U+!%eP8GTK(EnlkERLuxmze#GiC@QABaTcDkuAL2)Ra`L| zY?tx!GS&@Ab|rC!v117Td-vF7krRusp@zkoQ{en>Z;(cR=H zb{`}?rc5>zE{t&6J5f}JT*Io-;6eiju}`(l2Fo%bl*uN6fCe!KyBA_zHc}JAby*hR zB%U|h9W1~(9L9FOX!{g4Ik34_MQ55{F;gjjZ5YF#$&xcf4I4HVds4xMQOKOltG2X>9fdn%*gIKmOci((3!cMgmS zi}HfblYq8h=wouNB4VGgG0I{02dy}yK`Qks)1)HmYMp4X1u>7NI1thpH-1EsV-?9@ zx-D|Hp%!X2rrAqIDy?FR&Za^|u_hU!EbT_!y>+F9#Ksi)HK6YlYc^`mgr-*GVwK4@ z&5J>t8#ce8<|^2YGSjF%+j7wy_67|#rA)(+ilX;>%oQkQzKC_vb!PUdL$WGPBV;H# zgdJN$O{jIN((o)vM6rPwG}J*=m6?dmOCHl^Gpl;b%t$bKNY$`u_L41WpOGs$o(RBo zu4<2)Qx^Ny)CO$Cw$Mwly5jG471QhEx`FLkUc~qt&BSI!rKDEv@@%>y#b;d*;m@1q z*dpQ;5tRq5gvC;imKkcif~8+?6o1?R#R@BKOX*3aEK7RD+8_-UT!IBoGs7^!zDPWZ zRs2KvYT%$%95<33q68~SRZ+IxVY|j&*i-};MAmTvhIXLi@HNAbBwNbo+vIvSIi_lI zX==K`mBVhYgz4a}#6>w(0;6baz;_ag^%i3}ufDWzBChcPGX!egEXck{!rVpOT9Y($ z-6CacUzr@Zi+W_Hlnsmk_xMB+jkFq^G{dShTy7}2tH^3*ms|J4T>>0aQ1p7uY(KM7 zQYoq>bfCjx3uwf4a1tYeJ^Pv|35Qk*2wAz%*vfv5)nuziuH%%Bc0aVwa6J>W->Bf( zjoQ&m7)YjIX%pZuu~w5Ov&?MU?_eX?5=S=`&2nIm=U^?fQX-~lBBB>Z(s5OmF;=+# zmHe0nb5dCmjk<>N&!qeV?dGnUM#j--u~fzSUP?>4k#99({eS8kZVE0cIt$9HSmkWB z_NoOKr3+Zuz5q8f+?Z^lf(MqYdO2mEL1l9Ua}8<@71tmx?vM!yUonx>*SA$QUxl@9 z<;F45?k=v(QzB_I?ru$AGmu|FBsX-evV{!f^DBAY#Afb6#x^b`I^$+!(68|OkC!HeIRY#$S{?#rd#VDR^#}_6JIdm z4ZX*j!K*Cqh8^dxA<9vH{xrNRIK1sEP4N}sJ#ea=t#0gzcC70y5^gCj+(bdQHcts| zthunEgTmU)<_Zes)Vfw=<}rttEqm?w*9q&@u^*nnGrVb@AO3_FuBol;hd)nIxOx2W z9Ns0&T=BzS%@HPmAO6oiL&n5I~qz4HdM>;|1 zB>HKH&}(2T`Zxva@N>QOf0|i10toGe^rm^kcfrVgmj843X+{Ik%X$3lwYi`Gqeul| z3^q0-EW!9SC2ZnI7_lUDA#M+x4;Q$`?CGd6Yx@Z$G0!7=yxgjobP0cE1EW4;I>f@9#?P9Z{Y z6%TgCT5#_5Z6r9!gTC!8IQROlAh@j_^xf2gbFXhN!EN)P??4OAy}suhTmTrzBwx%E zV%q%dn(N?#Pz8nHI_7oP7{RF?aJ0VEV7qI57ZH7$2i#Qzr-JTU-^~PPxUVl=4-;J7 z1MUTa+uGL2w=G znQuSA?SZ!vT*rFmdxGGugsTXyvp#yhUk%p~TxWg%B>LV4Zzs6s`F?HteXu)7aPRPd zn@@1>^ng2#;NAuACU$mQUpLL`>)}1Fapw|!*TZ`WuIU%fJ*zuIa5s3sT}W{6b6=Ob z={@BA9@cj$(f0ul`W_{?8$IBjCAbg5OKIIyBF~Qvqceut~O>lR@ zr(NT2Ah^%KX9=#k|9I=Wh2TDi&mCRxdAxV}5dQ`1S=oHjZDs&Z!o5Vo7pI9N5BDI! z-R%MQ2*KSm%?*~P?_UJB7w#nRuKL09$yU&BZA%gp| z2Yoq$`wDy&qkTVSKo@+?iGRlo@?TEy4@|QodH$i9{s27aIv&>&eP4%fIQD+ivDfE3 zIq~$~)`EY?!GFuacg%M`eM0=U2S49O^zL_Gf&BNk;J!or)Y(qj`PdKNb=LVkm+O4S z(Ypus!^1>x$9xEMIk+I=zVGP$fjhkc+6mbYk2v^8UE&WT`hN&NB6ee1G@htAc@a2~ z;2xXiCc?v=PH+d{amU^tyR?_?+XL_fvA46I%S7)_;HQq>pSjel5&X~H@7usN1oxx| z+^sFRUyyZn%;NyP;Xet#bc+kp8_fZ5tuI(0b{=rQzF@N>8iWJzD`IEI^CfsY(f1VD zr@wX=$IzS>JpYM=leZyyt~~|6aq{Q4j^2*>7do~@Z?lg6&cSz#Yp8j1?1JB0C(hIG Zcl@4*??L_me}re@FYr9xLT14W{|2t5BJ%(M literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/SystemKit$HostInfo.class b/blade-kit/bin/src/main/java/blade/kit/SystemKit$HostInfo.class new file mode 100644 index 0000000000000000000000000000000000000000..f6b7a05bf646fad335792855960cf0c81d0f429a GIT binary patch literal 8690 zcmeHNTTc@~6g~@uUZ`9usCdBvF)4<$G4V-_2>}c!P-82JPiDG1v;(_4&CEdLkN5}t z1HKtG(RY88@yu?a))p)Z$iuvJcXrNvXKp>0`R4nN&tC!H0o+YOp9A-lbc+GyVR4)8 z(PGu79xLu}T`cb_&4TA#&#nliSHmrlgoFd5k(f`zTCr5!X0CQ1y;3Sy-fS$aFFTN1 zYt@&vzTgLr6`cIxdJyLxWdk({77g98s)cg4uVV+cl@EHx~$d(jAGgN&Q`vXf<>{V6y9Q@{GgorHi?j=9|Z+M`xL*Wj(B>_LU?ShidK+eYWQ~VxV>hTW zS)oW)8+u&0)Ze6%n{xAGLf5%+V1BK4DjrGoB(l95G(gbt{9LF06ihlWeLQ!L)VTv0 z#98n>WU;XiDJ|l`)fS} zF!HV03Q*eAjKXF7&BjtN4ii`!gDY^gE5fx-gn{>65w4#A;X_x18z(^c)CHj*ZboCh W1ylIU;CLLk4bw0Qvsg}GY33(zJ<8nx literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaInfo.class b/blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaInfo.class new file mode 100644 index 0000000000000000000000000000000000000000..4b217e4dacba2a675cf2327e12f962c3114dcb96 GIT binary patch literal 10207 zcmeHN-E$i?5MQ|_PF%N%odjAwf*J}qZLo2he$bYJN#hv@H)i70Gcdz=&bH!Qdw25O zsh#GTKY%v|{t6ypUlb~{i>2L@ep;<$X;-^{{PW9i0I&wN z45SELaO_^$)O4$SUwfpLyN1?hUq39u35=lvyv-DY1G@t*Ucff z1@*q^oc1)!#p^N}N_VuG#l%y!^VeAdK?SE875hWx4{9>8$NO}^gulPOu=$YLV!!Ak ztkN#$2Ggt+x@&XOo4(tb9_&V(#4fWP7uVH|sXGqtFmD9vV`OKPG)gxt*b?C>ruL2c zPvL#0&Kq?W4_=mg$~6W?7vd(~m2F%0yEpnljOp+Y`9~l}o7HW#zmd^RN-M;hL?uc4E_cGAmJyAb(&|>yX^z zPhEP_)be%~%y<}9pWB$ya8UQM4W@O+#i?Mb0gi{s1|b784Z

8H82LF$k-e zU=UU@yCAG$YQZ7d0#9zj3gL(gz6gOHtD?a)2Pc{?)?9hg#kwb!;Qo$4rMLJ)yT@v} zyO^gB!slMb0M4&&SZ!%j~ak=F7tCKf#;7Bb9=;@psDmG6xjvIlmR0gJq=h@D7}pBD{MPfqWxHcpr+f z5q^*&tiXlX2tP^?3UD!j3_nW|RujnZrvxDnA0*J^Us8lp0))S%2xa&%t|n7yDMBRy zLSBk+DFMQg6yb6Lgo{#ywFC&)r3hCNAZ$nxt|ma(mLSZ*HMl;unkoFh`u}dpe>3&9 z1R)O}!Hw7mk0&79jE(TE6ya96h0e=I5BRVI4w}1MGXZU2sVN8TZWlUY$gu=$=Hsk9WFfbTCum?U3s)h zr+E=xg_$w~7u<2l8}J4^0dTat`7zl9Z~y3pZY=5S(RYrdW9b|n{r1%k1}yKGU9;EPYjmphO0QwoD+c6iCwy%wY;SnmfXfq%-Ab!nZ8i*82*}$_)$dYJ zuiWYM%GFjIal&?^+-$Wg<%pOIh+8$Y-R|w0o$VvGkaCP0>Q$?5w#?Suh;gO8*XV6F zo1Nb2?g7PL)+4eX-n(Twdwg$=F{3ew4{r# zt^e;`uj_-7Qr{g;v-#xGRZgTH@hJoaB6ExKhIt^0>R^YWPEWuR+t`yE@7or<Lzd`psnJiG*RSj$5?D(9neAu2Ob`Epcd zqw-QzE=FZ8D047_wz`b?`QWWe3Tr6mCs?_gzw#rz`U|#Z;C1|+3%)GD8(7bVT<|7b z!`3ofhqq!8$XSG$N3jU22@rmbMR+>_!tb#NHxnTI5sUCn0)#(f5#CLJ@OLc2d($JN z7Gn_#2@tNuBCNst)7nF7Jr?1E1UlS~MOaUOP>n_SFu^G9#3B?E=rD{$C?!A`#~`HO bqu?LB0Uu+T!BxQn1wMtV@CCMKvGv(M#QTB# literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaSpecInfo.class b/blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaSpecInfo.class new file mode 100644 index 0000000000000000000000000000000000000000..7988dc99e19cd19a6a633a5c954a0452ab863b28 GIT binary patch literal 8844 zcmeHNTTc@~6h1=>y;!+a5JANeQAi}G+2^yX$h@Od?M5B&@SxmG_wPdKjL38 z(L~?D#xzk_J*mJ*0H0~=0?%k6ETPqnDj|4<}`EV`aU-lf!XzZEx%jYF02;U zimUl*v0U0M<+ln1(wklCijt<&d_iD7guGVRso*dIbD^E3H{~4yV=qm|RIdp{GRrjr z(N)plF}O}(qRXWqrI2x$APXPfI+DA>I^qp#2)k`sOqs%=Z7J#&x83J7nW(lnZE(Y4 z5{cT(IABdq7kxQoQ4Wi=A-GE&p{UK2(V`0J`Fj+H`k5Z3nDwNX^`?>Sjt=lmyDg-m zexE6*!5j~-&gseQ`pF!w{)#RTbqEAif-wT*Mxiu7~T%#x`9SH`(Vv1B_%s&qm9JcaFq~UeV`9e^Y2- zw7${0xOr9Vl;;d|4dOc5@*0{pbQ!ih+t1yOQ9RQYX1yVvpEQVa)6C9tDYO{TgZkAy z`^TqIyJ*@)(=M70dwMLO4heO*tb_M+E;f37xN>DsKe6oonU|;J7)E^>c#e5d0(9pCBr?y};$UfuZ*1IbHcG>`@zgeVCq zm`Xtc(gbEQ{rPb(vpunCI=pmf*SV}ROjdh|bYU>7#-!=BJAX!1%XA4m*&Hs7k16;V zW_(M`M&Rkpa{nCSFi+tA`T289pA$$TPUn)GK*Dc04Iv4{l?a4^G!=0u4Zdc2>li=H z9Q(;~0;!_oaJgzR*X3>u7Lo67SA(Ox`_S&Qgoi!P5>6PWwt{SQ6*JZ@JOz9=fNvin zkcLqh!&(|*oigs1qcDQol0>>|{u_x1)&P>9A@wdj{t+g>Vrv9$;P05a!V8NHxJ)l^6GR2LB2QUYZ JupPzL(hrSM<_Z7+ literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmInfo.class b/blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmInfo.class new file mode 100644 index 0000000000000000000000000000000000000000..086dd2a37047634503d9be08e9b5be1027866dfd GIT binary patch literal 8895 zcmeHN-A)rh6h2dG|15tM{1*pAZ6j%8;*}Z`f{+wxYbZAHicGgdyRf^{%nn3e#8)xV zMDKk8pTH;Z-gtJmrBoJd6_AU$>Fn&D`Ocg()AKWDzW)69833L@E)Ed_IaeA5o0(2w zo9(ee-C_-1*fCY1y6-A(zcSVQ>YiP6wnQAF1SWhci#g3grM}G#MIgPpSX&F^NQN zX6&#gr*po*c@%h#HUxL6BNVlnGFnt2J%86m84uH=y7Hd7^4>J^z0m=_X}5(`)c>3X=HZfw(aadmwTG{8tD^=!0mcxOv=4T#=1`agxPMB5u} zi<=k4PkF&W&mpd&FR!6%!;qom`F`$poZ_**Fz*fVqM|{Jn`U-gNTJn;5!CPD*%|Lf z9ir(FO^0YY?dkJ?IwjQUvQFMlIN0cq;VRWZJz5y|D%<00ro+p-cAd)&hQ(^Hf-VeZ)tEHBe&=OWwM>`5qqTwS^;mX~W3ji) zY{Z<(=8m#Yz%2r^CzsB#a!w$HIGyux0!hE)G=vNoc=-*1gc5;9kh&^%rNLKBPnfZT z^08kr$2xz}akyNvnCo&k4)ZvJKZ=Bm4lW@)?7M`}<(V!8)#weZSiA5T@ZJDka)?3( zEXcPcZs6GyVZ4zhEx{Q}`S6zf8b1KBogJ zxC+;>Hwo9_MkvC~5QJ}`2)Bno_#TRIX9$EJp$IdBBM{urA$qtw1VSnVVFW0mMqn1^ UuuY*(3EYGGh?>QI6nhVT0U`?HZ~y=R literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmSpecInfo.class b/blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmSpecInfo.class new file mode 100644 index 0000000000000000000000000000000000000000..f05b08ed43ebd708caebcc6e624a514ecfd89e11 GIT binary patch literal 8850 zcmeHNPfrs;6n{etEv53Of(n9;hzbd|G4Z6vq^Tt-LQ80E;)zVRL%XoM)65P;zJy0l zegdx^Of=EEAIkW4w@@n!whG8$F6<8b=J#gaOy8gR&G#RlzXHHxco2gD0uNnjWNc6Jg+4Veu)LN%QSxM7rJS8v}-lLk|EMrdsvnPEoz9?-H7vOrlVW8M~~(>AY``G}>dH)&+N|BNVlnGMZGOJb#0BQNPNgHPfCo)7~)B zo!$YyX}5$_)cqfXIuil$REUG{WEKwT2*a#mtOHsVe$E*&329A*gIIh{U7_MAWhaoT6(1cv>FQx}pzT#3LIC{q@D z(%>tmH;vIF;@IcP2_y@S!)4B5uFKsR%%k2vPKLlp*X@LRUAGes^(NN?F1mtzwF{2` zZw=rLhzO)$5QgwA1+n%s?mq`%02d{JawGmti3q*{B)&lMb!zkzjDN${09?htL;ja> zn8f#FAO%x!4O-uzt?e~l=K~}Zt?fy?sl8+E zZrbL~Kfr|}cW&GeAhmad_y_n05Ld(%@n&~oJMlPp1t}oS#c$@#+uwY8KHm?2eD@Rp zu0c5rBMQVFyOwGhrj^<;9vP`>)2NfwL(@&^dyY$54@~!x=H#p`8itSpGoDe?u(nfL zb%)ek1tOZhxt1;KIjyKbEZ;TIUE8#_Zz~W+i*z}&;)jaqLRNu^oW9A_xeW!BPZXH+ z<13}jRn$cMSgy>Hc~U-CWJ&zPLOP?sly8P%WOdUteX*0KYx#6Jrz;TkZS~b6+IEuH zbH#hwI>uvuGLLUAE-WlyZ4WAMUhh{e^{H6x4t-dx^r<#V3Y=Wd<+Gc5wv;ZXD_R*9 zSjU5kQo6FzYcY1mv`qJ|0;BQ7ngXE=t&=cZRA9Q>?pfQW_BgzzT=-(uvWY{Rk4Rmu z(N^1R8m>t#wQbXCleC;$YGk6)AZne|nud)=ZKL+k*e2?nHw=wE2S5GC0lO0r@kyI=c!v(=`yt9ofBRcnUDcvYhAm#*K;BJSU^^9P>* zp}JHxRCljU{7hTKZP2>9O%`pH}6#k^d=NVC8%x=i=@E$~wh11KkDjKCb0! zxU}Jxp}^LD;_yXr;98hupRmp1Fq50iY|xfMHY4t!4sXwnc{Iu`n%ttvEt)*`99RM6 zkx(9&<>CE^i;aVOI87gRpXgsH2Hz#h9K;t)vLEDFVz=#sPiFt0f80F3Ha-5j$efP8 zw*I$gm4C8-Gw3iz5m4dvD7*r1C~!L7?=iq$ zwx{!^MT)zvDzPgDK2|f=0$MYgYldyII9G<;hUqA9B|oee19L~fx8Af}YbbCkp6Jhg z9FhuLJo@DvAI^PF(P&}OB1q&HrYlLCYN22ra?)e%p#}3OPcBW}K4spUzz|Q;2!GPVd@6>{o?s00_ z&oWx@pYbdB)bGGm!0tq!nKKZB6EKFM7=*bT=W+rfo_>yiAtNN*4nQag z33mbzJ{1z)4M5lt67B{dJQfn(3qbfxNO(U0;d3D&9f0tqfG`6eK&EGY7{Qs(pC<*g zTd@CT#LU#CBF7%_2upEFOp5;CaK=@TyhLr$>-voqF$YI-!zZ*f7?g3!jqCnY9LK|o4NXiLHq*=yu~H~+Y#A`{KD(LSUMX&u*VY66 zo_Wi)5o7#g#TCrw_5rIAlRKVeQ)zLRc!F1L z=J>BkqPM)uNR62`70BdKbD!23nGAH0MjcF&8fQLnxg-vi<}Q)Q&pvoK>tFd%gK4F~ zwEB$n$>>F6-d^f{TsQK3uWXs-IZ&|ISO) z5~44d^g6U3ap=8tGxySL^V;7W0>tNPzOOrQ`2YV$KjCy6Bp;sF?DW00&$kP!xk)oseB}I4I!8- z16p;Knd1dS9};;i7-(R2Jsg+g4OfaotOk%gR2sf7@rE$jJ4?-X;5fq^B-ODtV8wNr z$l28QnID4`e&Zi!t%?nfOBY_8DqT1dnp_Jr)@96U`|uL5wg77*dSC>)@fWa-HQRWz z?QOP+X4@CEap=G$?Z@#0L2X4RJ^>`Yz~I)%@F%$S4XF;ejlVrX&k)?f=VZtQci|pV z!*CxSL?S#qi_kqDi7?&1ttu~=FX-iwRU=?T(Xdp;JuvJgpBm-=l-Obq@IPypQ zE1sk0=r=$3#XsV2@OWou7d9m!)1y>9XTIdlX6JeCyxco;XXpO*=Z`-Fz+L#pfF1%9 zzE{iHrsd?Gn+ImD+A!-Z_rl`2(xK0p{n+9L^b!~e-Zo5UH&?7aXEjb>aJ91bthA9| ze73T_R3wlqbfvnsdSI8DthVCpxU&Qjf8nER|mYy6pNqgpLON+}v6(udL-miW!Aw zui|iR?mOJFS;*8sXE_#sNZ?#LQz6j1=+>D5mk10W8%N&rTrUCdkjvk1IUe)f#sRC- znrk<$hRH40p-s=NHkj={ps8eekI_1-HB1jHHO<-!bC=P{zy`BugOjxGGM_pwr?$y! zdz52+_8l4!kJm@D%L)t5ie_Yw(URY?o36)c@Xm5+&2$7`mC>kmC#yM(|E+o@?pe-m z8w$!@YEpjKWKyZk_?}y*yNpY3+wj~b^Y~#}GECE|>o%C_Way6P+CldPm>&5ic4CKl zzTg#OV_Uv2G|NgsD^f|_8a*~FG>K?U*LI_Q3U_zC-srXXKeJDXVBmN|6yZk&w>AtJ z*2Lb={BTq3xEE#xM1(3TiOS{eL`en#x%G?E9iMo&MSS-(FSz z$@$UeJAJ;>=R1AAdtK+d*0u8t50bAh&-)>6x zmE$;)E^J_^&9^;^GcPdKQEXwWhZDHo#;~7eP8vIbezVzRPMyI0bU}K+!oJn0BlpSL zC;t)7k}A3TUX3kT!cT@|OE7CFNX8&Au;Mt(TWpxV&wK+uB{0=JODGxv%n*u-1}rE+ zqdOpxTohgh8IVVB>#kMQkJ$|_126q!z%tIE8qu-$3<#F!(SXMUG71z2ww!PS*9=iI zU>#jq2^i@@AB-(H27Eyv-JKxvlYUt+psY0Rkr0bjM` zmdTfBHfu7IrHt7we(wZe&JpIUC14!-pdU-)VBnLGNk|3qJPZVK5QYLd3?qRYg|R@s z0dJxlgdSY_-$K5(@#!wI5|pW*;Np|9@gLybU+}31uHbKf@MZ)kmIq`ln1D%qx&&9@ zTF5XJv@2qGzYW7oz|a%mu0vWGHy6WYU`iR6kKt~>v@&izhPw$_W!!cQmxEi%xNl>) z+i*u2XT@+cID>K~yU&9c!`(ZwfUdZ{Ut4hZWBLfrskEFn^WOLS5iS8A!bdTju!YXJ zKVrC#;Xw>1JfI^Eor2*9gVG#)f^q@<6=ebC a8po<{~%NS~}mSbIzW#d-mwh|9<%m z02ZL6zz~5Mmm7te&g{Y?{ZKFLS-MFJ2TT;ox_fYs2?d4;O#06(-L4e2_8w6~5E!+b zN`-O)DNXZ7MFQgjF(so)P0x~#u4~OdX1U6#Zf-k{wR%JiPdFUq(}L9~*O)8$G{gnx5UD@(cJ5sIwn=%Srl!lxXQW1Q*ech|NFq^ z)OD;wYO01)t20X%%(2xvclIn=b8oAebh%1ZlNy%JQK+sP2YQ97bG{$)=!ZGgbf~M^ zj!Im`}hRMx@Y0+ zwWRavrsoRz1f^8nmZ1?4M}#uzAVp#{QH7)GsyMFGE<%}fmptl0+CNg}V-IpaFMG%= zbFLo`h$}Q^&65j6k2mjlwyk5H_YjjtJitZeM6pAiGszQ~hBJMC5FMfIolEJ7ng_^) zekcjf>`D)=p3Vwhxvg`Tt{xe*?yt9<%Uv|?S9H;9juM)XfGME?Ng_M3jND3l_;u@$ za?Z?Ne&|0429$vVq6zId(?q&R$$pW@ekmQPS;9m<^{(_ZkONx1 z&WCDa|o-YqwGJHEs@zDsu_UYCTTNctXA6HV(kcVvQY9a|f#%0ynZ+ zb1sV;xz@Qj*#8hV+f`t3eyNy(83I2fIMIeqe>$5hfn3y<4gd5m3+!T?-8YlU1}=Do zz+dOq1y5M06PS-UqcdKkp2X12g!Q$nz#9ZEx9`;{$PxHEfv=iz8Ix+!D*YTE58Bg9 zlc#`Uo3m1IlaPM~=ZlMTMqBSH8YXAAHzqiK5tweS#$Pf~_1EJSYU#(=(!|CadrVtp z3pNw8>$%+&yiMS%?x7;vhT$UHVrX_YyC)L9xIZ6@NIXk z{BCBGGp6C%U9BfEXw;;2$E7LwkdTK7lss24l1`va(j~I7^Pk@NNy;z+BN($3d*u@t zKzFDsWIMftLF{+K*HiE@f&B#TA3$k^yHCmSxIx#LteM7SIOE3xzx%DgGUk$8A{Drc zBk5lSR%MId|4^X7XZY2i=~4yO(V#GFgOWvodjzh9H#-wTflcISo?#W(Lg)DFfdXH& zeXa<0E!1$6xh}T1%Ghajhi3s@h95yLK?X)(6h|3QAmv}vI41B6j)!0jF5`II|DC`) z3y2_6>Q|V2I5qVXJomdV_dNcN`cEd|1ssnBQt%?Yg#XfT4PHjJfb%*?rg>zN8U#!? zVwi6EOhXO48scX|ysx*f$y^M+*oJ=<@vkA*FlzRC$S@LWkd0wjYh##4WK;7N?#&q7 zP6YQ>AC{YK_|seNwBh@){BavYa?8Jo;POz2c&rsQw_-f@T?F?Iyc@yc1T|u0AqMw- z1owUzr82f!xDR4*KSppLoq&sb-_Ic~1Gk|VtLI|O`~C=VL$HLZ4Z$a{gV$-ywNK#= RtYA#8!RN368r+BN{{aK>@-6@X literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/TimeKit.class b/blade-kit/bin/src/main/java/blade/kit/TimeKit.class new file mode 100644 index 0000000000000000000000000000000000000000..a1a5cc945a760d27f651fe4349b117f309b5b285 GIT binary patch literal 2453 zcmd5;T~8B16unchUsOQ^6h#?OVT;=O;DZrj(g01sB8e>|K9T8mXa{z8n%QXsKgC~S zqKUp6f0OafZn34Twj>yRX?J(dx%bYQbMNlAAD_MezzcYmfEa;!U)gz=2`_)d+ALpn zSdHh8h0a%m%ijo{fKdVy!J5OodVaTh#BELB*2ZSBuve-aY!oV+2gTiYJB12?$x>Ok zO^0tV&5KgGOs^ul2NJ*u#Mgu;^lJhmR(7Aj=(?=&1Y`(|cQb7&B~=n`kdg0up5nfA z+Pp?>={AMKw2&TcDp_^7>%XGuRHeabjoS`W2x>C>nAJI547QWQ?JUxo&Wp3ZJ&T8b1^sujS}Y%hyKmfaaW1 z;kD&4rwsLLoR5%B6?~s7bHafI2I-=e@als=eXbk;H})L>DgTAE1_1uAy>Zfm}v%A_`VS`fQ0FWOnW(JreO>w zGLVFu1g5Q0x8K8@t7aaIm(VnCTW*!B3d0sRgGJiR*=I_a`_98r-4H&3h0=f-hBGM9 z5rn|9wS93&WiQr|gjoU~hL}7<9nIx5N)0xk5pO%P>^TDMe^WMrDU^A=r4;u9`)zq8 z^j|RLx065#to^w#Gsu761O#UK!-v{qUMo_HM^|`)SKeF%maL(iNFZI7EoJkfFs+d3 z^l$KvNI~zz>{+??K7D&J7JSoa18jc0C+O^DG-BMxCU{&nuSF0AIE1&Na1=q z_*59dD}eN87<)f?{UeNj4Oo--8xL0Sa{#Y1Aqu8o8t+mt1GhU7Rxppr6h^oc5n(Qf z5bN;n_VCQJkasVFx75SC4-a~HNbB(CBY4kycnh!?$$J>VdwGucxQEwOD5}oFFJ26m Qu(B8|!&Ce>N?Wk<6M!?)5dZ)H literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/TimwKit.class b/blade-kit/bin/src/main/java/blade/kit/TimwKit.class new file mode 100644 index 0000000000000000000000000000000000000000..30ecc9a05e2373d7ab63a2611e7b327b91153ed4 GIT binary patch literal 5122 zcmeHLTW{P%6h5;_*IqX?A++3~lN8D>lwB_2)}*EBRaG4-H6ao&NVE3DJFV?mjmHb+ zg+IYNKcf;z@Xn7w;*TKC*qiR6OuBxsR(a^lde(FN%{kv3pYwVC`uDd#0AK^IJJ29- zK2t$2VIu84WFyw=$1LQ%M?&}ZMDoKup&eKxuu{y$ERA~i`ww}b2{irtckbMJK*05V z8AV)e5^&Ny@kNHSr~PfE*kkht@3(eElro(wPT<^RX3PI3Px|=eRkUetiB#yT1Qyzz zeFBR&WXK&@Ca^qN`<7Btx$q)!*|(|UnT$s~q=8I^B4%31ln#~b$2`d{Q?Io*;56hx z%oG|8S@4KOoURuEb}_(p8cLqgRBDOd;a4Pqnoxzdb)<5u5qI~dAh_G$xtdy zi#bFY(14`|vCrwDe@6{-E#le?3y-X5cavc(0-9xu%uy{hXq>SpvL;egSuk|!xWu=%f8tNXQrnKya{_w%P~{wvnX>HOWl9ZNQA8*2^m?(fHO5NS zw31tuvdi?!gzJF}DH}!D7!H(7ijHXNHXUmL>}dyFWu~B;W|@dAGu#y>KqY3>C;PN zMN@p$JMbl*Q9Ml%2QK6JgJ}Q`Y?*_O;&{UWJez2i>^pGne`g|P3L@%GsfhMaGi9&_ zShDb>r2((QDQFfW2VA_{D#jjOvDd>A{=QJ0$SmLp!22D}e7Cyt1Xlkn?9SnDvzS?d zmvLfp<(6o^do&6g!WApRI$S`e zN@m`%@bRw2mups}_nvR@;e%rkE?E$EtO#A`S$+7(g7Cc+;ge$!KD8hS b3qk`v!%S$v=dg{}CCtDt;49dKEAaJyNr4)| literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/base/ThrowableKit.class b/blade-kit/bin/src/main/java/blade/kit/base/ThrowableKit.class new file mode 100644 index 0000000000000000000000000000000000000000..c0e172b1f1b9519f8872535398db506dc8255719 GIT binary patch literal 4137 zcmcgwTW=dh6h7mo@r6Lzl%|Dp8PW@JTkIx4DRC63ii#A)y{K{1^aW|Wp4ii@cUCjA zY5NF20wg3J`3FcyAi)D~{26`$h%>wCdhKlJBz5~@@2t=H&Uemyd(Mvk`uEr00pK(E zvIqqNRjs^wpNXLUnC-H9+h-kK-w~$XW}4SqJtd#8w$ImvDZ&JS6S0-gf^Pk8`!V+n zfyreN2(v=q*nD-9z{INT@FJ86Ob={tDJ4}2-XO=nc@QYBrN7HN)RX;C_{<0y&`?PX z)7MM1Qf~D)?QqX$3XMYM?XWJVb1}6VQma{NbF?G5rhzoH&y3fj2A%lR5GiGyFuR(~ zu4cK^Mj(<%q900SXlx)P^;lp*+nheKGS+k zSg{CRfOS6#jOg=QPdy&Sy4b%RM@hrAEaObqHKwbb3pW>=n_6?!`~JdK%CD&UuRo$| zOV231gq$eeEU-c?i>c$k4ceR-goLPQh__i@@pm=AcO@!5X%S zPdBmk+==>au3EPJ6PRgAkNKNS3A^6AIbnK26S&fJ9wH5liLE|lU1s>&_8K-n7I^&b zHcp}}mvmzq8G^C8V}6yiLFgi!A#iGtMe0eQydk;)Gm%36>&sh98K~5%vEmkXxwX|; z!PsBpcL~lB_|9pNz4mU5waC=>p43{z`*$`!&FW?eJ|ytt7?T-)noEHt10MQN literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/http/ConnectionFactory.class b/blade-kit/bin/src/main/java/blade/kit/http/ConnectionFactory.class new file mode 100644 index 0000000000000000000000000000000000000000..266a301cb40668f8b69047ac4befeee25f4ce9fb GIT binary patch literal 1847 zcmcgtTTc`*6h4JzXBkjn6%f1?eAzW-#s{B-m>7g;GK!I15+A#r$`)qYNvDet2yOF^fAHOGSJn zZQQlCh_|#-f?KK84&zpv(*P<2<~=lH>LA|j9O6EK;K}yR<95;_a6dVp#SH?rO`b_5 z?IQw{jpjaq%9c(=05b&U2ClY^(WVBMNab5w8Byx&SfrHeypS1lA=1L=PA2m5Aq}Tn zT|ra9GiDG}Fn+`i1YP&(MVMaX(p#sg79~~M(wte|r52UMNr4#+D`7s7t5D=(iGDND z_ayT|8%sSvYRZ{%MmvK3jB^yGguM{lQ%tn|DjA&QAG}hlDWmqZ5aBdp|ABb6yM4k% z;Y&W6>9DQw`+jNk$?4eQb0pzfmDcneyJ?@zjV6^P?Wt6}kxHcfqjSZfO1!0mLY}om zqxtSV&3mP#$O5FFP}UPks;)57F^P511NINih3)Ee)I`LMU{*A+_V=hyv3apx(cSpZ z>i_X%{IQOgSLci`gb?OtVICF;R5#Bi;bJ2h%)UKqq&nDevvDp#QoiWr9bsAw#~p!s zqB+a8#dC z+AqdAa1Ollp*YOiGTwxjetCy6wke7#?r{y|DWCd7I;M&9WDzMRDZoSd%m~dw*0E&wp3VAV3VY26b6KcNnAeF zPfkwse!@ojm_;-Wk{<1yANsuG*ea}HjPlTXuQlT;DKFtL>?9Q-MVz2xy9#-8^IS^E_2}LxI()MmL9qWfZly&T41hQ{hbo)^f2W z0>^?VaAT(KdUeNb92j0h1pf}kV~qJQVd1Mu=5wWKn03n+wQ`-N3Y(&)Bp6a1E6Z6D zDR4XYIjiS9g!ix}LPle*&tsTnH`6yQyXMtZ_yDt;shcz&@Sy_N&-oT}rNW0|@^io5 z%akgxoa-uvhjtySTp?U~Z+S*dg-`Ik$qv z*p}ZiJQD-_5_50#bvucv-Xc7}_-6HN8XeDX;Y?Q>Rz-!cQQ0IJ*IQWkekj(=TK>hR zW9CJFqJY{=rYlW>yScsXI(z%Radv*5VI|ruIen?0o26MEu2r>M%T?h!%)_O9$|%Da za-SW`-4#X)*I0+LV_{p*ZCy0_Mh!QD3UvjF-HbBb7~quQ__pC1t@--<9-RlXg}3-5 zj6?oZfy>)FyI5Eg_eKHQnCW~UT8t%31y@Pc3zAV9Mw4}>r7Ss&=qP)n z6_>mr)p|6D2t!dyf)`{!wXI1{C}B@1iJq{f^%9zCal*Bcm;#OCAbOf&N00|$TPcaQ zQWCM0&bcTqHAZ5Ohg{3XDPrtL@zNG#$$q}qR_;E6^wj!XDLbWwtfRq)yyp$HCmE6{{4 zo|fDHKlw#RT5IB_w8x`E$~=NiMqClF-A22Fg@W^!3w#)2&%fV%jjIUWD2knA%mP{s zg~R3P4Q0}03h>LBYsz%f<4M&DvkVVkaZqKj3D_|40(2Yhz!g|TDj;0~6}c$!GV)c4 zSCOwtypDWb;v2}fBo_YfNPHLREs5Voepg}*c}wDZ$oD0FA9-8i9psNB{usF=aT)nj zi9bVrAn_N-UrGEB`H{qrk-w4nDe|`x8_1@_738YKHROiG&#}@9u9p@*?a2l7GX4T6 t{sGSZ#t*+i=dZ~;?BY|*3gF+5_*|K)U=Q{u_JhguC-@crFQDz`e*x%b;0OQ! literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$CloseOperation.class b/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$CloseOperation.class new file mode 100644 index 0000000000000000000000000000000000000000..61dd420d71c09b0fdf6de179efdd526fd66e0f7e GIT binary patch literal 5783 zcmeHLZEsUI6h1DYX)YOsu(B5zbIV)UOCn8^rje@B6j8NOMx-W0f^W`^X-x06?`+@F z{xYOZ+P?2cO*?kmOEN0zA&69z54rdH`0;sp?D*K{?|**(699gMW*HU;{A6_8Oqr0) z7i^z3hY1_;=AN+4v9(!q3m-fDx11Y$r=2LnyBXKa3MI=>BJe}-;9?wsO6(M|VZsSq z>UgcL(IT)ScBRtXiyj@sJadK&0rHH%;<}K+ZV*_mPmFo?U_hYMRwG`9Pq5F&kTAL1 ze5AF~OR!98x1LDNjY{_Uh{h_-MB)RWnO0~vH4kZ2>5n-b@i<``K^cqp*e<7Qo{R>P z(Qss}(UIbYN@Z!vY&@nG2l0c9$98fMQqpjIHk>bw|EM^!B+^W2OFckxOJgRT)*+`S zj?QtRya*LU-yDXEb#mR!3HkU43H{H^aV{C0vd0GgDGZNuE$m^?&T}5YxfMxJaC6{W zllD2F=OARBKVFbOpPfoU&uSrePwApoQAX`y#-qyl1@$^T74LDo$zrSYXsi_g3O)!lORr~X zD=7FN&@8>4r7gFuKiTQDm6W(0VpZpijR>)4AcE)&0Yy-St5v8#4GU29&g%-&(cqS= zFfDh47_I*i zf03q6LSNaQ$c9@d8I(YE8<(SQyYm7^9v%>=ht3><%hPj*F%)*o@I5w*q>F}r6~^Fc zvXAp=N~?g=fF;-ksKG^8#IG8ZVaZEMxDX@kzl5z#L^)ja2UMTdF28~+e_`taT*K!g zVgRngr}(V;?+8|~4e;5N8(iO&VMHx5Hnh+}O3vC^e%_!Zou($ug7(JoIMH`3O{Yogg-dIDw1p zOsX3+3CyhvDeMM;OSJ<1UY|gzrG~r=7YQt6W=2fzHJ)m%^gMh)7H__gni~}z@F5LV zoQNp1ktSN9l3N-w>7))gJvMZT^Nov8Ug4XDT z4+g4svxw5do8oCciT7i7IkqFMew9s%qxXz%9cY}I?E1{8Ne6g~H^vFz+GC z2`si%$f7>e!j0b%OLim-fyZs{%Gda@idC-Vak-e>-pSthSfT5^escpQmxfBB;j=a8 zP>?5AQ-&K@YTNGQ6aqJPQfWoZx8;E_0{#2R)u*zm8M+s=I|p2AG33p8_>REJhwE!t zUPGR)N_EILg^S(gLXyv_WLWm=iap6}s&Trr-hWb9hNFzp{1^V`iSXF#R@UI(&mYC*fOck2N`YN1AS))I@&v(sThRN|}KbSk2m7u!b$bZTu}F YoxmNam8xjV9k_?>1EkL({XSfO3&&fN%m4rY literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$Operation.class b/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$Operation.class new file mode 100644 index 0000000000000000000000000000000000000000..f58fcecbf494518d6b63cba1c8b924c67138c091 GIT binary patch literal 5637 zcmeHL-)|E+5FR&Mk}QFiLb-$Ehg%Ayhm=SN=>)C%618fjKqV3)@#t*a#&l!v*KPHMNyPZ#{PEZo3Yn3JAZxt?GFHW22b)ZL*S{=QMJc} ztiEIKS+yOr4zC^vTkTq#RJZZ+n*W+|V^?+)u9+1|<{=<3pTT1$_p7_@cRaELF0BhG z>;{2cd9_6#sHqOmLy^GTF?LgHr3-MGEZln|H8(1L&pR|yy+p*Ba++w>j(N|#pkcAu z<+Q`2m}vwhEIMHOoGxb^E6B0pI4;wU;)Y6PX^+{cOD*2SKPE_N^d@w(;@qq_E|q_& z=vxxKL}^PifaI1&OggP?P6tG%IN!Jkh;>86u z>J1egaJ$7KtMs^|Y}C(fWvpa9-r`#939kQ-u)I=OJx4rol|EH_Sw!i`d%)&!66<4E z9NVr|ALJTE>G(#s4z!n=tbAtFq;0I?jd2Q_4$rX04~yS|zt`ILUs=uxSB=H7<9QCu zy`*$8_)JIL!z^MrkojMWmEptJCMpaSGE&kAW4W|pF`NHS7PjKlbkDGm&3jnzipL~( zhSw^3fhNg%lD52@_X16l^(1Y1IqwCUBx3c*Y%o`65A#2z(3vd7|l0`JqO_x zP9IPR1-MdzS-47Iv0OjyAoXuva~-C+x{&-;+G}&&bcY;)g}RDZ++tcd`Die(U1113 ztABZ`YmLColPWQ<9jSf(75dhjt+fqQn$xKyaHG6B;#mI-#>sG)Voe@y5xBgwI~*ZU zY>0iyY^u@S+43qX#8z8JNfZP0Jubj~0!wE%*RZ#SW*REh5#JInaPuP>K5LN?_+`EI z;xxUD(?j(^q8xa)xHFRGwg;(^Kxqf}nXb7)fTL@V2$X%71pOYSxjd{AC=86E+Lyu@ zEDD>rHYQjC3@1c?0+ZsWfh_z7q3WSWj=2;4<%F2l|s>IgZ8&%H5x{`TR6 k9@5PI(vkLMcz`m%3VuW6N8lkm4odJd$_3<7M#i~+03}Ocy#N3J literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest.class b/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest.class new file mode 100644 index 0000000000000000000000000000000000000000..bb2cbf6dcf42201c211f81f159c6663ffed60998 GIT binary patch literal 23165 zcmeHOdw3jIbw5{HX?E9=ABy9|F~n=&KnRgAKuQB2TUcTiq0E(}f0-D_kWLGh8PLzDZ4XO0N!OV?k| zI<{F{*e$4c)GC%8z33d)^A#gb2|??3?8sV0$0#~G=B!FFr`t>+`oAah& zV_YAYn;aX>OiWGI5qG3RwFk+I(2;2s>+>ZcdG#SUPfGsAm*M?7CUA8HAG*-jV3qVU0DtX5&={5kwQK)v_vI~MPG#84N zZH(rvvN3itYm_9@WkJbGF>4h{wo#ThbCvmd!=5!y86chjm}5D5zIuN^P>*|mr)@e| zTW~H-Xxg?;E=hd`@24#}f4pQ{3m)|La9IwO@|Kx&qtJ%V1pyi}7`%BZb;%9?k@ zNCo`gN0fp~shvgJy1%$Pg}XYT6h2h|k8*^bDp%&RdA(egfEhVniUSw!tBX?eF;A8j z&x_M-f~J>eznL(6dEobYE;p?^i?artK}RrvLov&f_7;1jV&-#*15mab*J}5IR=YU1 zUYNFxdGjQ!y7oZOz966%FLwt_vi77AvU!R)-5$v*J+$S-UJqxf2OHmvcJ_xmU<=9a zfx~fnsh};(u8g2nx^3%A87pndC~yg*l!3H-C&SY$0+H@iZ1})n+ktypmADtg-3EeH z4wT(`sbmxpE3Xbhcxv9AKB$+lj&;YcD7EqfS|n$ z!a(?11bh-gzog&I6G}7X~O&=*R);}SiCy)(l zSaMpt8`F6Oo zmSu9wEE=htfuL<80haXaaecu^ZFS4SL6n7qGN*4%p6|uM701j+67KxKz(%;$puPvxb27?0fBz10>oZmbUfs&P zO4a)vk(wg^KL<7S1ecLhtH|R^5weH0pMCamnqz;DOsqaa(dz*eG~y zD6^b0vCA!%v0q02G?{SUpVJKE`AT^)WCr(rgc;=KtD%*-jLaCj%!u!r;bG(EESlJm zZByA=qf;SUu*^25aVLrv*ppW4?tg7??zUZJV_DBt+tuiw zLB4T$Du7Y=dCqZWQBlW*I&p+vtL>fo>I;>dG!wir{NIcJeB8$+;!R zz+$0|E@&g>9KrptY-}}k*kf~64tx4rYO0$t&@)G8%0LTAfzLZy=!0D^&uVtdwv+pzhxJF9D;2C!y(4;d5K>X*cJw^lEj(KU}r7&Y3tUVmD_t?zVc z7{_ZBPcdNNSYWK^;G9&+298vz{x3Mv;4D%>g0Ay^ag)fy1m^i(#7mhxkhb?%je{&=!l8J-RDVxaP9w_*+rk-n3`e7w zLPPJ_#33x+VKkjSsu#^sN5wRpJhYX>`AV@iB7tvEY-!v`5^L_4c}D)Ox$+$2I;}3!`b0^N z7#tb1J1d;)9B02P+O#W4U+j6JdeL$?8i(q@i_w5vwqGkKyk5#p6{r@~GO5L(wX)gz zWW_VeWaE29tn8km5BA?ZqGaeOAXm%)s=#U-Qkt^cb!nuF4JZqOrEj&Ql=XstHm!tw zL#>+ez5)o1a*gNDW3}q(96fg;$iX>cHB`a14^Zm%jU5GCHCM6|hA2_#LIu1R5sxsQensC~G1v=!U3^e0gIN5=CC) z15K<_L2GO{0dLN|cz18L&LXjHg+CrxZd{U(=16Ip61gVup<_=lAZh|%Irasgcp*{~ zJ27Ekxhnm3Fs@H2vRX>i?#4X?lPN0cfL0y|=7}WKE z<57UcgJ!vm{emot%d~|+iI0>oq)Vuax^buBu7l#ZPvV|%T@`rVgZtIA2G5hUme#q~ zKDxlYt_O;w-9Q)N+D8}DM)!J&i_<}y=tb`P7t^Kgb#wKas$RELuUqLd_x=#-D%IpFdR3;*3v!n(m-XK<;q5Pxy2RIz)$+`TkM^{hiA6Uu~ej z%a{9zFL!;t8T%41`1Gg2|IvWlp>!SVeYynQtuA**s)1fv?vAS)=#}N}xW%VG4gRCc zJ>%0Q=m%CH_dN~t>T(}%pbwXu@zah6efrbjpO>4Xd&s9t(94#Qo1?G$m!uDuo1=eE z!~E)Uf7GWxjrpU?{gh9apqH;e?$0;StIPeB26}b5zvI)N2LF-e?(FmF5_C*m?#|5( z^vZH~2L1b<70iEqVE%j5?X7bpK(EtWATHMP5M!sE2Lp6j%0;HTD?n$^b&=_E0lImG z`R?=SPSXM{MxO7LK3$wlx;H>q&y$>9-t5x}{IkySraZR`bz42(hWy{BB&aE*Sg4U&xJYWDF$8>BaYhZ>T%ul`9tH-z%mwWDwBBk}R-4E>Ta(zjTiemQyu=+;<-Ur|8t_Lq(ETcDf!?m+wwjYHj+ zvOGLYk3>e;#v(jQ?}0|WDEq5^OboTW?(0~jhv_jN>Aew=ynSb@UYa|i%Vwo+ZztM} z^eDZrCG!88&s(Ucc6)o&X2kc?2UIPv+hFzee)@F=DTY0e*RN)>QMb(^Jx(8Fkiyr{ z+u1ft_c;9qgA{I=Z(w89|Y_nG%9L*b@qn} zJa}h{&5`F*3JCnZ@{bgx;A7UO6%gLSYVwa2q<9C5@Fxlu^(c$*rwRyd3xoEcPrxo;)Ii6y9_-ypGhL%RY zUdLj6(Z`aqL^>6SzmrA!l8>aq)%#eizgrO&7awEvWyA$eTj7@U6wB9_>F-&r(49p5 z3k;T^v(e*K{2Of$YTN|ZE|ix9zVgF5H~Z^Z`iH7qL8Pv*{ZV3F8>B}Vq)=Ta_`3Hj z{Ud`EF5S*HJpB`c6wVVDN#vUSGlLY)6JO1qrLQnZ;TnH=8|nUqK?;|Si%e3wuQEvC zJiVIb>1)2v1??%EC%(#iPQ6=~co)mlbM&u_bdtZeJ%Gdq+aUd$G7`5#74#f^T^Z@K zZFoAYjKuGG|DC?UAcf|ZWCzRBX7sz7PZz%F=a^8u9&RPCVtIQW zND*u1gCgfkoh*pA%iNxqv!5TYZ%L-=a5J3-MIy-SniqDiNameC=)g!grI zr_e}O3^R2iEG55 X*deYJyTtY4Msc&)Blc3Kxb1%d&Lo`y literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/http/HttpRequestException.class b/blade-kit/bin/src/main/java/blade/kit/http/HttpRequestException.class new file mode 100644 index 0000000000000000000000000000000000000000..70cfec7853bf3921d761d5b3f3dedabca0b8d92d GIT binary patch literal 1370 zcmd5+TTc@~6h1?NmZexMq5@uqdI`LAWAw=y6N4CPsw7aF_&D7?X$N*^)|qKT|B^pI z6EzwiHU1ZWfyT2-xk#D-Z$8Y~os;i;b1vV^k3S#30Kg--pNBC953C9NSV-mXioWpM zkqFV>lg{rtm-riGw(xBaty|v@FmY0=Jd87#&Croh9e=aEi-9ATMI%MjLSqTFQ-98Y zy<{-6rj>OYGROwbd4b@iiS{9xgE`9UruA zj5Yf^$%7dv7r}!$2JG2 zBULAxe5oN7zV5|sG)+OnWKeGCfMg{|T(loL$6Z%i1`it-mT!$gp@VKs^emB=R#yKJ zAA_Y~O?B0mR?>;j(otsmq659gVYh1qxXIw>Ih1%9@!!vf%G=gG6W|M(Hhy8$?a%H2 zjjyf(y4TV=RBl6}5hmyk@=#$geL_BYxJ&o@v`QEhUrB3efgc5S>kv#&HwUrUYpDT2i11hge9Q03lVWflB#O<3{4RvA4;#&aSmySMbY_ zK!Q6z3NdyNF>v7raPWBF&fD?m?L2?`{^<(yFGG>QcE$;roI9i01@{es&11LkdM<%Rf1R8dE#&+Kfm%<=*f43P zEKIlsB?237T+f0Ef#O^D=-7fS0_D-zI~ffp7SwQiJenY(j?D2HE_Mi%ywjteYr!s3 zd!ymd?cshCzx`53VO}A#-I?Oao(izf+XU+CR$Q%>w%{%)9GpqbV-;TUfck0~iI5qg zB#pG1g?t%5r*_3#a2jwwWEx2k^Do()(^e)*7e(o&qO@qBcub`-bjggrpau`|_YumG zKZLq=Q(e1hFWo;%*p-uI6bfG$8YdCg*bwTZ6W=IJSJJjSRKzrq0Y4WK3!h^K*DMK5 zp53K`BsOUVS(M4NlU3ndNxQPT5$ZFU_C4eDmlQ@(Mh)KZe-gKC*oXU7xCxX%v;Fr( zr(;&{qte4ZWhf#!~{D1e>51n#h$1{`~0;?i`LiP%SNaS z?cWTzx={kvfrw*tTWZo6o&vf7?QOvxlwcE48Brm_l^nJ)zm>yP#I+p0hPa-?+lY5^ zxPf>#hp!`U=I{;tGC>`0Vcg4pHygMDus_58yT+Z5aPMo@*8_}cmw-}i>!f~=)uFz%+5UXyx;G9{r>SYfX7&HP-1wP7~czpio6}MC%kqbI?~%! z*6Udtd#~iXzD(>!-^P8rX^j-2g9^h`1`b5j^)}i&(zgtbjC|dZh7Ox6Jz)}QR|h*w z45Lp~r0g?>`GsblY^ixnMD!}^F0C(aF;rHF%E36p<}Y;-%2Ve*8#)mBgPj`Raz2owu{S9B$>XZAJ7zD8hn|y)DW0 z`Dhoog{=ijI*RYohx~#EFV}o z@MVFtJaA|Oe#`2*a4}hfgDHmDh0`UPR_J6?Me=1oY)jJ;RCEl}P3?}^H`BEbnD~-mF48zknDpi} zjkRp;;u2=Ey;)o)rYp3r(8=5pSBZ88T-OS?77Mt_xIuSHxQSad0}tq{k*>E%_c`3f Fy&vfZPmBNn literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/http/UploadProgress.class b/blade-kit/bin/src/main/java/blade/kit/http/UploadProgress.class new file mode 100644 index 0000000000000000000000000000000000000000..fe3f9f847da3be1e15dda7ade392cdfd29cd743b GIT binary patch literal 599 zcmb7?!A=`75Qcx#kPTZP5K5spi&H3K_reJf5-Q07tqKwe5=Y1DCI+v)@;Zq3;(%17 z_Rd39*c+s@y>YPR8P7kSZ^kcwe*OY*fb9qi1bda`X~CpUZ`nOdM~dYly^}7TI9H~_ zQW=(CS~IqysvhV$FZ)aZfeOio!9WakX(8&yE z>Y7;@>^Eo2=-Frp7Q5%?K^b3}spXKl9B@bg2d$P z#Pn3%%)GRGb_Nzk1_7|DoW#6zegCAa)Z`LI2Cm@z(xT*4x6GVWMg~D-9eN1n?r!yH_3UbQCI9yOPrm@b4fx!H0)f>?`K^G7 zu=S8lSgSW=ecsv^x+P?5eKg`>pY?|PYb7*S9ux^&h~JGvNOIhScrYDeDco zt7H&+ftfZ8F=pOJC7WDr2{qdmUC8c?$jKorRg|1rxlzD4msZTlz|h-fKv)R)jr_FKzqQ{ z7XNO{Lq9LtKPBtbljUw=XUPgw;n^ybp+;b--c2_SNswMM8;ixR2>Hf1=yA1eaw~ya zSNd$Y!;~=3PhJ-FKtu$tb!XTM;r8b2_hwf_z^i}T?sUv}mA}f;$b-uS&Shpp;PRK_ zP>X@;4)IC3u67+ecw7S53?FF1B6qTouHllR5^T5;O?> zaTH7*qj*t*)wu>um+(_Qk&%_avL#<88Ek>YXMUKv>g`51sq`=(y)##8oeIbkO6|pZ zH(SlEWk`IFkj?omQYR9#s^p~p6Uz6czwwQ3JatTk% zE1%yJrVd?7LwsV$_`Dh4cS2u=k%%-8^?kt=Q~uzw2e+_)+QkDrN3Uj$>%pgZ#GXKT z@Y#W5`XrKJhcA*d%xygGjDP|bP54JZ0cvm-7UGr%CA^=*s|*$VZdx}`s(|;(&rtoQ zcK%1W@GCwQ;5qzVKpDX6dHk)$?FuZx3-P;UxQIPp#C8$CT!NRdW#nJR`xLi`?F9D~ z3+@#wE``@}agA09?urF>)rxy{CfwI8xYw;vBEdU93UOxA%OFe$XeAypp0STVpYxsX9OvEp|K0$=-*Df90)b0L2d#(+*?P`K ztknxypSN~}Z3)#{A6verH5+?SB5)!z2$>wTy1nN-umq0v(83TXY_AiTQ#(6`<1A_8 zN66*C4)JAGNMZj$+xqr;;~9a{1J&mq94D}N1h}EK(q%Y7iu|e6+^BHG`!rBdEJ9|5 zk~G$;7xKv5qkd&;$Z4MkA=79SvtXAEI9<+MZ=&l>p_XZ1aYLoDG-5UwQj1&oix|Dm zZ^77`Y3$9^ljcVNlT$<#D{X1EEEElxOd)%m9{BkE%`&f@p0%ar1Fjuw)GEs8h-tx) zRKL=W;!p&_Qj^5#1|^NvNnn+xlT_CmR2Z7bKHm|N_nY)lVr)uiwk;e}AxCPLQ-<^m zKSuB?YsPRS(M8^rrP;lo0x`~|?z1`h- z5%4$@`KJ`+{pgOk)}qfH;pELQCLssYjeJ;uS`~aaMc_=mb5w|v%`0i4E_N{0kCUj! z^;Rkq0=13`SomyTHv5w$I~3RgE_Y^WBr60w>;vs~dcgdE+b3)-_zcGPMlp0s2#s^P#c(v8wBJmk^Fzv zgbr+~L@^*+=chgS!N(c_ux;!pPmP2V_(q31hIBx3CWxSONk? zyt<1}gJUp(TUzY1^~pL1vf_&bBo zYWD8K5Ab6)=fl|?LJ8--7U3M6&mp8IO%N_Pd}ug*_!)kg8R41};n%M~xb8%tpNV40 z5yc%R!bP~`jN&&3!hI*g6{usz8pvP?k*+%O`iBE+&56~77GnL0SZVgJ<9MKwqYVA! bK-+Mj74Q#as->H-ildL-U4>h42kw0Uy4Smg literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/ByteArrayOutputStream.class b/blade-kit/bin/src/main/java/blade/kit/io/ByteArrayOutputStream.class new file mode 100644 index 0000000000000000000000000000000000000000..4ab6283141f29d8534d6d15654871e7941522da4 GIT binary patch literal 3590 zcmds3TW=dh6#m9>;TC_3>iw^H723pWscnBco){5jth z?s6Jjje@I5wd@8;#BQXF+u_Dzol}0 z9wm@1;SPO#`C_TpR?o6^wFtOIx!g5_uBeo~<^yStmFaUWIc2|6ZuW)NG7!g#4&mp%CF+(PF!xu3Kno-7IS!$;X<`BrYGV?8SSnm^flj* zk$Bkaw1nPH_5{OXL-{;>a=1qh7mKDXV}_fJ(-QC+F=W+CEKToeX$ZeEN_Sksdkp6? z@i1I^+>4Ct2ruf(Sdv2<2}PxxN%kv^Vg1(}ywC7^4t5=CoKUii7iT7Ud>=EEs!umP zN{oZ6jIFBAy@%nFRv+oZ;8WKxz0Hr4ynb z#gkiw>P{CIVH|wL(9h${*^?}h(w6FJUwkJM_PjWXB3t+LLPjL)MZSt+Nhg0~?n|M$ z_S=IJzDZbce7KZwhha9WPt)&Z92048)BPsK66pF#_u^?3=$WCf0!nbwv3xjIa4wzC zrem2j=I|Q5=V^77v>A<+Ke6!R;^J?3yn~B0OAs#6dx%h= zwbLS8CWI-xOPWPOx&oKJ5{pYT9>ra@cy`_D*=2liB5sjv9Qga81^2EM_ZsD_VD)mG zzp4eTWkvf4*9mPL{n3a&wqWgAv1+JiYBBcah6N$CBHYAhR)kdx!p~NOFVgHBjc4r5 emlmu&3)U3Ars@=M3u`n2-_qkyMX%sC*8c+%sq(@A literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/CharStreams$NullWriter.class b/blade-kit/bin/src/main/java/blade/kit/io/CharStreams$NullWriter.class new file mode 100644 index 0000000000000000000000000000000000000000..d321e90dab8d15a46a352c21c28153fbabfe2282 GIT binary patch literal 6301 zcmdT}&u<$=6n>MYvAs1-D3q3zA44d`hGJ7FznW4hwNllRn^a8*LKTO}?l_)icgM`m zhU8B{{0Ce(Z~%b-i3<`ECnVGZ2mTVoo87o}$gVvtTNMtmch_&f`QDrFy_q-p<*#pl z0Dz0|ehH=sT!@t0444R;ci0YVZu-pQ&26EZLN;4Hrq;CLEQrpo#J>Nb5}K6Y|(362q%9S*jv zlvHJSj2!>{gHZ8E`a9gCt_=FZXIjXR_Lbc9c@SNqPG!BvsmEQPDKzRccbjc-x{&zT zKpz`IE>KVMh=x+rfN8f!HNL`k`{>c=E9g$c1gT+|G!6iyqllm{m8QwhLQmtOO$5nt)*$0ei>NQLo0r_a-{< zNC&?kq8)*n8b2A2CfY?2TT+Vc6$NG$3RCI>u6xqMlFPgfCNHLPSIHnL=_c{0d1y3( zLQ)*_Au{SW1wRl`WVD@FrNdb#v%Qo@D7roFZm&pfR@IuJbyG=~N0C&Q*RLF`K(vds z$&gIQjV#HQ896d)fq|Kri}qnzUcF{p<kmsA|i0~Q`5F%KV55^m(SdaLoEW{4tGQ((0a+Vs!8vR#!hDt$i*@|P2l?Y zF55KOgBQjx%gCd4yH(#P!!ravACH>!?sl+Ai@(3`D`x2>P(q?@j8z$)C-B9?qgwQ0 zU4|D3gvIf-DcS^1Wr);756^R0(&rL5UF(dlv5WOiT6a-m=LmdO9Am3;K1yYhX6OIG z932~QCvdFRx_4KGR|<{2jVG8=T|bU``0bivg-38&rjthC$y)tz@xc6Eld*F7HDRj8 zToQ`(fG;`O!jjVt&6x=Hr##fx1y@YDy*&ceb{KNi@)@2pL?yUL;GEqN9}YR(*OuTN zgc_ZI61;~(Nxdxr9s-UWEDl_$-bmZCb?o6HcpdP75Dzd3%)?Qb!K*4vVZAKllS*>1 zc?7QjobSN-=tT8vIQ}EvO~K>%Ig|W?a42WV4xouZx2 zK>IQWZGIx!nGCeAa?qa5L7TqE?YRuJZ*tJ)a?pmJ(hRikbI=xY(1zTy(0%i9JH5n(1zTy(0FsVN+W7}W`y&(W wHE2xamNln;W}r<&6E!-8d3yoB0p7qr2XhbqO8{?S4qwLmGG_GK@Ge~X8|S2F&Hw-a literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/CharStreams.class b/blade-kit/bin/src/main/java/blade/kit/io/CharStreams.class new file mode 100644 index 0000000000000000000000000000000000000000..b7e29ca06c97bda9d56b9b6a205c95a0f74c8cfb GIT binary patch literal 8117 zcmeHMUvt|;5Z_BeZJCso&=%T45v3Hn6q`c%SBF3n5}M*BZR3UkhG7)x5?>?h#7W9D z--6+Z2j2Mz%#;~;WQGsG=irUu1=y1kOPUC4Dekm%=u8#M-uvy|?r-mQ?|%N{&JO@^ z5pGssjKSGJ*{!}Myw)vi+iI=5mcv_HB5VoSn(tX^HB{W{2NjrLa5xrmEpM~6vVM!( zA%p7N&Bf1Gmp)lwz?K*soR?k@T3)zjxe*@+r~-on)4~(s41@7{V~xSYymWX44l+2D z;w>m8RTU1g$9}o#DIQ37n>(g0`@V3kP)N`8m0WjuKe%MpjBbyc4!2!Pp^$IcTh=Bw zPsg@5(e|d0r%gxl!1QEj_N~zFnIR70w|z7^I|L`+)RS*&OPV==M2qPAQiW#xvyi53 zc^Yz^n|n6?x5PZ+9HLOTq{&hQW4D%}{Y#;xzV8ZKgk})=Tp@9ghAOf{smz3`^@b?| zGx8k1Aw2Fh&8txmYDUDv+#OSR+j5JW7RI-iN2nP$xaC;LzJf`Zp)@Ts-0^wMnDu?` zQ3RJ(7H-?zk9obHQaQ*V;K;xILN!BY=UlY0p^e=~%PhuF!J2^?F1*bW45A0<6HBzt zMZ$GTCvabt{}V$y0y#B282889qcUt(DQjm`U?f-QrM}O@o^)`@wVVznFQ)Q_lKpr| z*NJE9FEvMyNQz@V1e*PN!S9P8(A6*0KzjBiF5Kv#u#=^B|CF zx;v9!fy@nDo3xR!aha`_n2{N+BXmq@F4Enyu(C*9Wz zoQtfDOYf(j5#!m^WJrv!8F#7pnhb>AEtYWqy3K>S@WS)BV)yte+m`+ggX8ti9-Z5rG~wEfD-3Fby&8M{lMEis zc(e-7F!+hpjwcB@K&Q0aqq#Gg3E@M?}dR7=I zOxUyg1g7`XV+LLN5@SCRTso>=Yt$SvMrGJT&`~nDoQe9dRXNuYwzCUIa!7?_>P~kr zWf-&j{mk7cnC^DlGwlXGtI%SsO`zMzY4Ud+RL&C*es7FP9&8DJ5j#2DM<qFX9Hhy~fSm8?>PKQg3vU`WSifCWFP{w(IkDN;!@DqZK5A435=v z^+l==8GdKDzW9KjqL6;vN?E6fX7YdYk-wSB^jnzpt1?nHUlh8lIILZTHJ-lMi*LSgNn7$fuI60} z>u78M-e+)u)?J)QPq$D@`ci=p@I9^cD}dL76S``sz=xPed(^JLRlFfgcvpcHyh6+s zpB1={KPS0afz{j{WFm;RUrmmAyLc8Hzy-W<#EVCKo`6T-0RFAu+Zf(N*6?ZI6Pug( z0(2Zd0o1;S$&aTV`wkBO7|T6@Pd!Q_9Kq*gA_Yg`7`_?sBs_&U$MN$7{&FJ5I)@s^ z@S6nd=>n`)jHP7^I0erZBBa)s1qcfRgeshd=SvXI6d+t5AQ*5KUPPPIS=7<8F=z~C zliG5w0LjTAoi9Lod4QDqrCETqlR?TWjC%{-&WuaveyL#GuY++_n1*)>$ITRs`+YEO9Nt6A#$Xoaw1tQ;kN+2tOI>_F Uf(%*2&zIo}bYK~-;Y@D)1%MwbN&o-= literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/FastByteArrayOutputStream.class b/blade-kit/bin/src/main/java/blade/kit/io/FastByteArrayOutputStream.class new file mode 100644 index 0000000000000000000000000000000000000000..3ca77094ddb04820a9367a7632a567d423d4c585 GIT binary patch literal 2975 zcmcguYflqF6g>llZI>$I`^|!it&bMp4~&U55F4u`f+WUI)9nbO?apR)isIk!$CzlM z-;KY?cz3aM4MSOt@x#9FJ@?!@_uScUKR$f{a2@v?3^81fv|sIT8B|~MbzW_@c}rB^ zNK=)ny1*k-+c4sR)_h~JYr?KsGFtGCgB-)Y#G%cD)#_sNweStYXtVq3mCy_q8yR40 ziSZn{-IIYd_Zfyu_R)v3fxD!&12MvQp^MBOm%5z(3teAOa?S+mZ<)P;-j zA{^{vI8(N{QT=>&aBCZ;bs=?ZW{?C z<6Nm8M;m#orJ)#3>1C~+ygBi#8yMLU^IozTZ|6IgOBj1gha63~vXAOr}*Db#O|B6#QUIqGHt6@QxR!{IbT7H)^vn7!H=o+uJ3N3d4sioU_fA zEG=BfV#F|G>+bCtIJm-aa**osxW@23LylQ^Wg=e~L}&0iX2K^CEvc^d#e$60eR{`@ zJK4r)P}FG>1(A%52+SiXG}r#xhJ)J-#dI?|xcl2a-)o)X6B$J`$d+lFi7*9{82wVv zSiuNJ>28ef9pvd;NPabj=?-u|!+o*8_z`=*($f$o=scQyi9LbhrWFq0AU(whhv?ix z7@~K7if|Z5D9+JeagNcohnCwyJ8t1KY2|a6_}J0<+-zuPt!O84DwSQoKBp~w%2ouA zDs1P|N3-#nwW3Y!uwFJkH>?QLI758SQe|_L*}1J+_p5W>lG`0CRv8yESEpu0xQI); uR_C&X&%zF9)l_b?mfWsdupV2mhUwQk?*1FNNmpQw4wou+4!1CiJ3j$z{QO`5 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/FastByteBuffer.class b/blade-kit/bin/src/main/java/blade/kit/io/FastByteBuffer.class new file mode 100644 index 0000000000000000000000000000000000000000..ed899eaf47577bb71f6c1d68fd194a0ba1c42dd4 GIT binary patch literal 3179 zcmchYOK%%D5XXm#WXXzLr*hKwgLYr5q}4X9`-+VMk>LOWl=$G(Na_={OIeI}$px3| zT0QmL&(M1hy%uQE0xgh35B(1PB0U71rJPDeC_xgCT$an7)4g}e-F1Xf3~cC}Wz0#``k->;OVh1KPDoJ1lJhNfA$R`pq=u7@RAt+syQxhW$Zmc^8} zpD*(F2&_+!9Ir_NO>ZtPfqUK@8!(S#d--EeDT{PBPRzj0za~%;!?sdlS~L7w!Xub> zloH;sc|$21b#rJbdT6M?CW@RMx$O{B3VN~$kE4fYF!z7q$hI?7gFe3?aDTebyeTbs z%m`HXRi*=eOXStOcD{Yv#suqtim?4-?}rjB;adUUD|TEy8>?{9&TD7$6+719IXhlL z!Ybs?=kc#iq!ApezeD|g{qisH!k>2S%lKTf76Px}du{j^yb7=3EGN8<&&PxUew&X_ zfHx)(-gIc#c4}CMjWG?y|24ejAl#ckcxQ|-isD@d;kyY0Z)U>x69|o&2|qXqD{ys; zFxpL56hAr%*Wmq`2|qarAIzcQXD6XH2jN#Ip$Yz26w`O}p_B08gt~BL@-HXhI(#&y vVYC+?J5JO;69}J-5%O9eR+g(S9ytl0!e?WIQ64^jQUh6Y5^kW^0&M*UG$Z%V literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/LineBuffer.class b/blade-kit/bin/src/main/java/blade/kit/io/LineBuffer.class new file mode 100644 index 0000000000000000000000000000000000000000..8799f6c09eafe42af9ff94a936cb84397e8aa03e GIT binary patch literal 3114 zcmeHJ%Wl&^6upzWb>gP96w0F%7y_jUk7UyoMJ!qs6e$IXmLke(Vo#cBZI3k`m-1yu zAi=^RU=ivj6bQ_R%5Hc}_>CR5 z#~N*yIlQqebVJBSOZa>_>U6j=!5}b|M7Ye~ZoFyla9a~FTnr&F*;?01_}j~oa2>9e z2$Vwh=`Gih@(GYF0%OmGFZ2rnBh}g_u3M1~H(>&o_CQyalBx)kWOVMGuXrfkJ?>Cj zdVz467SgAIl5LlJ;WKKLHoBZT+;*A5pn%!CY@5?c!oQCE>q1tjBY8-Dsj0`b-K83r z@cjUpXP2M=^;m#<%%t82kUm9tfmE6%(?U|4`7vah)BhZ;Qqv1uVGB*eDBub?`=M5m zt)-%=RMi?4A&q>8cTh2hc5nvAEOK==x=z=kP{%VEMVTMdO@T9zR;f?z970q}%BcPv z@Zn;cZ&vqh9wb^HO*4xctM75$m6!@vHtfc|Qf*7=a^}})M@cV{JLW)peT0%>H-#}$ zTntZyA+}Azlx7}29P0}%y;jWDC?n_z_Q?77-Y^W#rZ)zX_n4r8t7SnME|;MM(*$O! zt)73Tx-7;1IvKxmuOqL`)doY$Brx5QHgh+b67l`PpN8&=kibG~piKa6eS|p<0kisX zrP++1V;%ZMXu>T5Gm zaF4*R6YYdyJm8dK@lcayT7(A#exF-~{E+b|0mm;>G z#E{anWOB|j;Sqs}zRH;Jr0C0^EVSxmblmESiJ$DhJDe3TBqatC!>b9IW?8u?z#|;UQ+-%dr3p$fy8S Oc#78|DmM!?c>E9MW62f( literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/LineProcessor.class b/blade-kit/bin/src/main/java/blade/kit/io/LineProcessor.class new file mode 100644 index 0000000000000000000000000000000000000000..e353de65bfb247837f0fc7b3b4af35d343268c27 GIT binary patch literal 834 zcmZuvO>fjN5FNMM&BrcmS-O0Gn4Yp6k_)GH)e9;T(n1j%D#6Whtki81N4B?We;E=; zaOX!=Op=AB+8*L~o}Xu)-^`z@AHM+L4ZLz-gFs+3j|wKs=#-taD9KqWqBChDsiL_o z#V4(}Fh*$ydIYu`QqIaOI!aCjw*=f7&t)m?0fEh6dQ71AR;9uLkHF}feWHp(b+6##!uoMxtt7mWpsgZ{N@+`*W2q=-Wt}n+^q)rGTUag2?3N>H z6=l?3R>Jq*A01wBQ8h1FPtsxf;KH3D+=UT={%mF3B$!`Y)z;gutsK=I__!<*p<{;b z5E#!DXZbPHvW{2a0KKc5RI>@(n(P|^|Gz@xzyktpHjDSxvmLBM4!pcEV66`Xh99Ic*nt?0 zHhls(XE?urs|#Du$JoK>^$PWWg8Oyse~003L^og?*O~+P-D{9~j>m8x;~k89_@5y1 c5FX*~al?3mxt=z=XDj46P>lPSZvrp=0@94*I{*Lx literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/LineReader.class b/blade-kit/bin/src/main/java/blade/kit/io/LineReader.class new file mode 100644 index 0000000000000000000000000000000000000000..9052ed3526cea0e10f81f19b2f687e5c460525e0 GIT binary patch literal 3257 zcmeHJ%}*3D6n|Y|XLnfy5%2>)DvInX?h4{X2nPu!B#T5r5<@(6XS%zEndzj{A#m{T zGSNiup8Si9uN`C|knBYF$YI(}`|Iz$zP^wC{QdPi04%~w2XX{vV&&EYCc^q2J7D#u z&pck=7rHKFy&*#Wp5ugaV1U4=Mffai*EgGc+|>jM3YS^a=LAX(12y9%0(mpf6$0!m zS2%a2nY0Mxc2@}uxOQA_tag}sowQmOFzBPan1IuGm+-{U6t_e>WI9pEKb6idH@aGE zX(ht;(h4FSvlp2N%r<(Q=tN$AS%gBb5E!m>b+7KAdaKgo4%{Fx(iOI*lvD+{Me@Hs zgo?+~Kj0p9We^FUX(2-zDT${K;#ag(-0pDdao1-GK@oHJS)0>oYuy@Jw_6)Ql#zGX$v=5kyjHYL|tiE(;B1lheOC{xdAhNSA2g zXOf!*Xis<{+h6y(V3BG`8P!J-FBJ`ps~(`P-~A7;RJ4xTgCh0P9v}?0eeN|xta|`6 zv27l3rG&@(!Iep1-|Vm+M80r^rg0LPTa;m}RpM%?Xqs~>RVredgdT5U#CtWmk)X{m zZtOPyh>Gw)?sLj83OZ*QQr|Ecs)t?r>1mnVF%u}$MXYbG9lAWS`RIHqI2|W_yRyu& zlJQ8`~=O-&pz7I>QkO|G`n zfhf?ciShM15Xjr%|s47BQR(q*MU0vzrmX8 za9|$a&FM}DUYvPur`}7Typd*`ZA?iq%mY5E@hP8&F&M-auy>$f`y!NVKLlml55rYN zkKi~5qlmkPpBWR3`f+S0@NW^>a@d!?!Q{uWn_uAe4~w~rZ5}az-#u*0c3gt{K<(TE tn8tk%aXf%4k50JEj+E>11zZakaOI$advZ`kT>v%C!xQA2gBm=Cg+J-(3e*4q literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/StringBuilderWriter.class b/blade-kit/bin/src/main/java/blade/kit/io/StringBuilderWriter.class new file mode 100644 index 0000000000000000000000000000000000000000..1ae5a8ef03b05df713139ea210323b715fe8a08c GIT binary patch literal 4150 zcmeHKU2_{X6g^6utm8PO2@Qm_z&7P$1JrJzeAVTnb%B~ObOxtp7@p*{h?TBau2v4T z`~rReFFf!!Is*ed^@ShB^zLpQ+o@dJ#f2G$2WxlbtD|$zm2|KE{OgzB0i4Gb2XhRC zNc+V$mtk?AAMj!$;7w7yAx%-LV$En7?p^N6pegj1S{k7pWEhSmrU4K4iq{(Z!Z*|v z2`zb07dnzEyk5D&z&>SIDXTCtJT!G4bj8Bmb9McjSiZyHG*VQC)#}hRC5FX|GL+_h zhIwzN&X6gqrf_hKO#AbGq_xsnth2>4*F!BL6B>#KH02HX$@x1&`f5bfxKn_Jp# z3AZWyfNL`9aQ_D16Yh56Yk_<%NVV-Ym5AI>8Mn=i-*OEN5#M#lxxpbMRv{Lv5Hl$Z z0i?6Yc1LOBCVxxi`aFyw8^Y~zoY*YY+k)U4<#N~D>WJJ@Em2+G=H%)))4^c=Z<{W^ z8R~HDKxi$S~`w1oWvlJ(s)v64|=iPQg=-v2WWmvB&pOPD=6i46pJ2R#w zBZjlp=`tuKxQthc=UMlTq`tUwk#{;GY%(l+<(+DJTF{UaUvxtw+oBR4$Vd{2OL1aJ zG97WqReN%lvN*-?(*!xOH)724oAr6cu<2C?&zaJpmsz~PaQ7dkK1gMZ6jN*khOHxB zRw{>nGA#IkibNJ3!_|lT8&@xrMT$_r3A#~>p5Ml$S{AR(bRneP&r%}C`?^fB)Uzlu zbRVumQpQat#L`r8%Iyhrzrtl$^LCDG$t>PrxIF>4DJGqcVAiMl?{zs(O#l>**)#Y?qv(N zeJk3|Bck23qP>ER5#0K#;#CW`??<4W8G+W!HRYk=LXhTU#r(G2tQg8&g0Dy keEMiM?|!zR&EqYK{T$xLJM;v~^vlyOeHSIXhYxV+9_Fxo9smFU literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/package-info.class b/blade-kit/bin/src/main/java/blade/kit/io/package-info.class new file mode 100644 index 0000000000000000000000000000000000000000..2368967f8bf44fd4de417ee5ee3f55c2498031d3 GIT binary patch literal 132 zcmX^0Z`VEs1_l!bc6J6PMh5lbqGbKt#LPVXti-ZJ{iK}4lvMrf%o6>~eEovNI*|k%1LRGBL0L0ADF0(*OVf literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JSONKit.class b/blade-kit/bin/src/main/java/blade/kit/json/JSONKit.class new file mode 100644 index 0000000000000000000000000000000000000000..d935e812c05893734ea330d57f57ca8d183027b3 GIT binary patch literal 3048 zcmdT`T~8B16urZTZPzM@qWC?cVyoDq(HGkE#b}}wc%U}%!H4N~fPvke&Fn1EKjDAz z$wU*4ul^|Got;t^*+NMg6JKC==bn4-Irq$Te*OOX9RQxe(;SQuxECq6>N62kci0}Q zc0AVQ)m@>hJCO{kZ#LG~R)o&M1cB)!z+=Hyb-lC0T}|LjT?9fm2#lA?Z2}W7WS8fl zKw#=1_N7u%<>4$D|M@mhJd)lX?^0L#q41a%GN7T79gq9bGIa{AZBDz~^_aq-kh!~T zi_`g}s|t2iFzhrE2J1iTE(uGidw-+Whx>X2VK4?0&H~?SMZs|o=!(s z=xQ8kvw~5S1%{hVoJ#2wR#}+QFV&JVsy~L@DQsvZf~`>mji^=&+oHaRlCdrCH-@bC zIF4acNuOe+y6t<>iquNjOhnw$wb>I>SYgpu_4abAL90luF$i5x#rDXw+ODhz=40MJ>&5oRuBznD$3s z!6QD;10~=ML3fyO7Hpl9W{$=;E-xQ7DuI>yN`~17YyiwsZ>`i4duL?J!#x6GRNPM7 z76h)9n&xE8X7;?^%3y}u*g)#77H-i@4kbdIQE~YH&us$EhK!ZVUkP&{7kk&bI};9CJM!X=EFO=2&D$@CEOA7r|cktv^K8tdV&_VL#; z@Ygf&#T5P~+`?){>)y`5O&`MD>DQglz~9ZlUpj=p-^VXx;2&h*=lb|DC?|?NgeUml MfeCm7k5RYkALDe9TmS$7 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/Json.class b/blade-kit/bin/src/main/java/blade/kit/json/Json.class new file mode 100644 index 0000000000000000000000000000000000000000..d80a70feeb8288897cb44b3d93c8002771d94c40 GIT binary patch literal 9220 zcmeHMTW=dh6h7mo@uh~AmKMTwd!cpGVwX~Gu~P_X3~rnYiIdWnQcczqXPfn|wU^NT z0VE{E3*xyvAR+hxAb|wW^qn{U1Ft+G&g^dO-DbQyjto?V7u)MO-?`73b7t@U`NK~D za2{@?Aw}S*ZKv|Ldw@G27I)SyNHXc1P2xqnU=%vCMUywe3kImu+k^rO8yCT1eEP>K1J=<(Owv z5p61Rn~o_>li7-4I!c>5>Zal#h~4U-O<@okRpf3da$Sn|vG65n?T%?VibtTCib@U6 zbe$>p^xQQW_p=l~X+qc0bSaKQCG^}T6uaVfI_M_*GPMlNXxRcH#W5ACIJY}2m#wus zx~6K5V!It?Vf+o-v0T+LEyYjA!nmT@ifc64hGwv4QJHsbhlkaJ>9-Zl*fzJALNP>} zQ4W5T!Yp~#*ENS(R4=SJ7V0;SG2LL6&2{4W($;Jn|Ms*~e3A!^P0esvi(4v4%evVo zzpA=P9U-LuN=?^Ui|W%>%WX5mnZ2d5j<+*+N)Cs#Kf{Zri#uAVMa&T?th0i-DezK)mXO_}{W*ZwQJ>`wbKH%r54RzB+)T$MH%fQ8Mm7YFYF)fr)}NZvtlu*JO6zR|4$PUD)5=xk0 z67y0b1M`G@I+Q?5H3-T1BE{w*9{UN5g^!CMSogA_+AkY+4%$3_`iK2J0-ybJVV4Oi z-V3O%v$(P0y?waKER(=Vp(}RSnt@dUx`a70dPsJpxfRp3R94ma{Y92vpnGpt({Kgf z|Dx;Da1GxG`yEXhu1DTD`)Ux#&-<_48h8h9!%Kije3QKg#$Ydu;;%7C2j3a*`v|1) zW+jJo`@A>ad+--P?nlU9Ir!-JaNuWrO2Hxg9Q9U?z~lHk?^D5HID$`EcmkdbI830d z9)~djhZ`P;RDgRrgyaADlAjUawj#LaLb#s1=LNWrBDkX=TuiLzejNAWN{=F!M!ZRo!{vfa;S^T!mIFF2p1a%aw3F#9mM(ahCtrA2(FB~ zt%8C^Q0|n#LvIQ=EJZj>hcxbGz}o`c^$6}FN}ff@DX0qMz9YbgcSsE`b@6iod|iP5 zA|$^C3tjx80KX)_f7!)nU>R0~b~gmLue!Jtta%n+h7a*Ok2P`%-iNDL!#?;6l`j=- literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonArray.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonArray.class new file mode 100644 index 0000000000000000000000000000000000000000..35653d9f6d49ed8d534d7b4b1a42ef954d4d6f78 GIT binary patch literal 8627 zcmeI1OLH4V5P*9W#d^dz4+yUi*aQf2609VI0I_2*eh>vE4w3B;69{AN*cxXaVt1t^ zoH%fxxaCgq2e@znszMc9IPnYk4V*Y}peTx-S;<=PXm=JXsZf=JSG#iWH{Crw-94k9 z|GM)70Gx!i9ApR_^1XW5rras7(>5)ySkz?Y>pUp0`>sm-92jc_^HNNK1pylCzkI645s)-{@+V~{CJ~Y7{9!wJ0RvKL*kezl-mV<`~ z?37wt)LARfdYBEwVzb)jWh7hUe4ZnHP*tSKX7^Mpk0(4bDcmW5$~QKoWAu^3o}c9ygOJLSpG-1kKmky4S7JM}Ah1|m8LJjFMZqf6al2k*QcHUpc? zs<9^RPfuxEMCqR6rY+ZJO5Ib^HRpM-Vj3Z?JK)MX7W0IK7xCa43#KjV`{+9E8!g9V ztK7jBaTQmu2(gU-lpzpy0||6tjCR9Ngkjh{3xsjhJ}!FZomEunLd#xZ z-hyb#2<)l4b!sh9kBjHdm)W4fv2iaYcjwX;?9Gp8%L+A)YD+H*@!c)Qc1^x2Rg@zV zxTK93)wLoIPZ2l}ziq%>1MWYlX$q4oDbNOinMAbg5aVM)jC)RdTp>M|N_r-h^l}R6 z2~|w$&&>-2*5e&0w{!z)VDthk+?#6qAP}HR;;ZNft`tubZ%9uQ za44Q8;!r$I$ek%w6nRiL<_OgAea!<3?I6H&43F7v8*^{g=O5z-9%obt5M%rP1zL%ZbiyiW8PRoFVX;MtEw}*sZs|Xic|~A~1~BR630jR-03i z$5aNsN#J)41G_`Tr{eHvBe^xyaF^zQTj;t8Y?m#bUhxe(J=ro8H@a{?2X7JB5$TQz z?7P%*0&cU4)8;^|DsU?!=#Ew9ezxY)CdZ2Tf2PumGxO`hhk zM21BK(^QJ8fs;~k>UgG$n=$4DXF2Zfy?O(G4S64Hl+4@+%)zzp6IO&AP%Q5v@#mmU zU{`N57P>wMXh!7QuxrIScRoCaSir*y9}WPv0r)cw?$Tg84B=-EpE8h#{dix1B3^gM zpK-R~9YFDW7{0P+S0FU9dOUU4N=?EDlJRTtk zUDFW?@B}>BAsj|qdsggISg|gx5PA~yz|)bDd%8cPc<+YN`u)rSyU2E!pjjIdRaj+o8+33a0*`0CNz|USK+k?A$DbvwvwFrt>+ZnFBDt? zRrGg8N$c5rUO`jmqeu6V@}!%-F#1 z;HCehQY*oG|4&~l&a7i%l7U@CQH8MNotfS5eCN!Z+x+w2U#|gR4sHZ6L7;AQ9QBxx z(Iy+PsGYD5kDdw}Z5kz`-|*2AmTQ&-P$F>18Mw>9X5v^D)n9w_cWPR~Q1bt=y8iRba6&PCnOIYzbVd=Sw|uP(AO;VfZe4OaP||930Ch0@Dxr z(uy8mk^^A`8hFbUpR6LHePL@9N%Iw;1pX*cJ4X^Zt{bx=2U#S^2vn>Z0tpYgwLuMw+wBQQV#y^oi^64YQ4 z$~db*0F`X4ZjE6!hWHMv9OA#g*&Iqu;28c5haT6C{0X%;xSD`t_$(s^;43(ePlrbo zu1??xa1u_Th($ literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonNumber.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonNumber.class new file mode 100644 index 0000000000000000000000000000000000000000..9a0516d1c40aceaf94bc75dba3b30850229a2ec1 GIT binary patch literal 4256 zcmdUyTXP#V6vvNp^JW`JDYRTlK?K^^5NryiKwU~pE>mYr(`nLl;7wjDw$inp>S1bMW*OB}`XMg|m=U)Nf60B8Viomkb zQDeY_Z0xfG*675n%NzHFZR{H*8=H8!H5_!fuD}d|3%Q+lSv=$f=8V-s_6VG6r`VXu zUSm6LYvR+ZLJE70!0GDY$F*GoGpnl0D{z9q;&}MF)=CHP6q)_{uGHM9_<(n5qy~wI znH5UXM5|8B2j&V5=Xd&?c6k&tjhzw}-Df>cm(u0cad~yOyd~OI+)$}39WWd9sl`G3 zLBbu`PSh&O zsC}65jM^7mGadCGQniejOEheBx#6q(1kkP8piQ$C8Xtg{XxW& zG{A?~H7U6eck6&_ExNo6jb%>Q+WIe+Suh$c+=d?4o|qNf@`CfUmFyk+Bpb0}_Sk1x zQ$zHEW1ptXBe>PsN9XZKp8S(JUmI}SS6$lUb~R?kRBO%%hO*1|ghb=oQ`+Yi1&>OR z6@?JO;sR74K!kNv1LAe`D zpPyRz37-B9@221+Ugxk6z!`W3uM6q#5Gl{%9p*tejlIr1>h(N+k7#a8Mti|STlUZZ zUV^iz@?{)3gY0u&?pWok9`1^VOW-wF%2oNghj!6RI}aCfY0DnkWiPD;Z|2h8^3a-I z+S^dir8PXX>t5PLcsG~!o`<&XrM+JuZkIi@O)u?3_~>7>jZerG4{ggsn}(}+=BD6d SxQ5>VtN01Z*q5g+TF8~ ze~4$^kctF6^G6|O?}Fkcr`|Le(Mo->?#|zQ^X<(3n4LfWdi)yzdRMLwEaIVJCw$lE-^u6w4MYFjy^2Vv&yfC5Sx|9;QZG9ZzM%L!D$Q z7EbAuXGWvb#D2+x_TEJDNQSX62+BlwB*v1j7s7ieyyu0l^GHj}Q|)*nTsYwljpT8L z1DQ3#vG@GgdtOWL97X9#C7Cvk7XYPsC{j;4lKdZ?mxkp|#U#G}2UtX-Qr~W#WjK2K zgD|N|$F>5*o#ukOlS~Hffs@8hnHt!(Oh(ewfQHJt8py6QD5?fT;2}UruD&uxoXm@i zz(e)-AdlnkwMsEN_m4xF73=Kc^q$Qm!8<7=n>vnhCE~)anma+;`?*^(-TU{6Bzf~2 z-M)x(IR}TN7*NwhBAai(sL~3rzLIRa%P0hq0G5Mn;k#3?RKK04(lvZ7SV02QP z8GZ}nevG)^A4p^Ua`0zKqOA4XO!0qd6|_k{2e{(KwHw_9Ww=ngT&3qksq%~ySr)6X z*klj1DKNr}^F*f3^3JKpE^fsn-$Pxyf6h~$cZb>tUPW+ye#3Rw=j!O zuzHy4Bgq9`U?)#9U}f;1vXf#;D(fhq00LN9h8C;*GQ=1?$o-Y` zv|F(@)S-y?g;BnaI{modCdxASVtBbO$p(Xs&Sh=A%%+GU1~)1OG3f3u!CMTrp58I> z4HHWAu~B1WqNfsDG@XL`JqEXGxl!R*x^rPJbF|SNEWs_3KuS^>T=A`?-B`OVZ5RZ* zIya%*QZY(i@fCW>QnYdyEDzFDn$1{PD{TwzFt|fZA%m;uTU{SN(dsJ0i7vLwJHQ@Z z5iD@PSYTg`!5X{*i}^}5~l+JWQJD72jPLqbAZ}P5UE7_G6N$Y7| zc;Jyg#0<>9J3oryXg4NFy<|158R$$Ovfhn8edp+tbaZt7`161cf`>3CG`cT6di<-DfCrOCnB`wlo6>MFS=s>5$W@pU(|T zt%$t%{u^MXMxlSZX_DaR&9_WTTv4U~M6IHX+T(;b>V3;K!`Ul= zScNn@6We*O4n5E+&dv-M!l)Y~#`^=VjoS|HEQy6N82hpiNAq5dx|hv9?zj=xCGO97 zh8wj*g?z>-k)LraNg@$sLH0oD48!y&jk&ajwofc}Fcf>)9w;2x#gSm1?m2Vln}<~| zeP4n6*5OO5({mhLFYQ=gIqtWZJu;K|K(b`kVvM~wK6=gDV`(sx#@huCcM{BzT|(rW zitS9e)*>uRs{hY0FOB*;zKVFvub0L7f#xfIKXzxluoM@KOCKmTFeuoHs%M0 zrZVIQLh`Unw^F<;;iWh079C^uFi}UGGQ7Z!&of|V@UOCaY3h~M`G6YGgg2W|hZcd$ z1@#J7hgcb)M%$??q3pT5$(2e}z@mMoh5J7F=b{}8L*Q0a8j6k{WxvEGOz)-EmV7l@*YH*dn*QF-v(+(GhRjfnt?^70`jdSywYroNX zg0^>6sssK&xG7z6iF@9dRd@(A`%-ef88KtHslrVH*Gt993DEYm;?_M^am!~2skibg z!5-ci46Ffag=M`8v|tIA@vQ|_sNwGt{?(y@?XTh6ZA3X-<5y^Y*Lve;Sp6NpD)1IQ zmk|T-HeAAIGkb5qW&8$we+S+@!{Bf^!+Wy~3uz(475Jc#;ll!k9|{>h28y1pp>5~s zI{r>abn4G11#CYSvR#8u|ADRY_vnh)ekx#Ffa}<&0&VEHzUUop4EPLn@8S0{wk*Ks Fe*q(m`Gf!f literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonObject.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonObject.class new file mode 100644 index 0000000000000000000000000000000000000000..876de3fd9316fd07474588a7d4417e83d238ae71 GIT binary patch literal 11454 zcmeI2O>i7X6~|w%B+qIiTaF-xBu*F`<7ne#Wx)BAEaF&JyvoW7mTV`20HfX3?%4B{ z`H<~E_zHvo38ab(2Z{?fj$A09DqJb9TsXmvD+j8m;zIH7nf(}hduDoNQAw(N@M>oF z^{-#Qe(&|`ZvXkezki>IPSJZBl^8t|_{}-nFrB%p#*Q(!Wf?6#cg+mvt_H3%w}Owg zt*g8lYBbL1c%krR!-_bg3CFN`z-V8iVFuwmqseu%?HFO?mm1rGZcuea(j#W1wz943q%svFA!4TD2OO^b;kFNn|lRQ;HdU@A+oHO zT+_kqoV(HFUL0q`?wy`Vh2E7+a@MshL?QxP<~x;1(a%CcTD0*q? z_uJeLL^z1G#5RKfxi3y}deW*gsnlm35!WtEbVHgUP^-G>+@_S7tZ|0tS!Od%vfHj7 z%NTw;vbhrm`fRtyDpIjh-whW7%g+RRsh;Q#x+(OkWZ%0&YJT{UwbL#Zu8-_k?<%h5 z%nFss-iXA-Y=|72pC6Ux?UECqlE&_Wx7Iw=$f6)pEydP$xbK^-qN4i4ET&|m`kJam z6y{f{$GsEUTjSSlvBsOB4yO_21B&O+kD9_4lY(d#^+BLV*nDrB4sX@;)d-s$2gSqK@i*IUaUQ9Gz5E&p&YB@z|`guu$Z2b@5FhKNC5&+cLLfEfZ@n z+E9n652Z{xqa*nTGB}UH$&S%#F`u?b zJ{T_`I5=Q*NW!UC>x>?f{7`Ll4;!!~Y9NU1y&SPpUBMNG6d@X+eHrbSE!W7F+#BG!s!SV}~-SMIjQrxg%PK``N^I6LXf(vfA>|+1a zH*cA)F?zAsLMi(f8EHE5T1LqG*Q8K#-HrSvUp7TI7qdLfJQ&L<=e!&V87Mm0$>C80|6Z&iYLMAa2kd^Z}Q1j6AIL5yKE!X!OJ4|fTVV*GFAHpXQYJV62i|j2(u}|cz^UV9sZs{sHO-5`^gCZ&LBLR zBIN48_Gb`IqzJh>uwxm7$CL^48HC4`2^Xb=nz}zQFN2^wo9wL&g7R##Ut|!}XY)51 z1ohecQwBkOHvg7EP@m0zNeOdwGUX40%p{46(g7*qv;Dks3VCHf_}p-GmySybr|1b~ z9iEaBo}{Nzgxts~t!5COP7wy9kl8^V7theMDMD_3D0QSdJVWy-LcR{Rl(0ajQ-pjw zyqQ5*OcC;Rcw0*N0zH=^$LL|#~KoXPTSOm zK4M1q;qS}Tk<8;&$vj??&`M-wRQ!^-8GBVim>?UPl*sA&y-Ob6iC)9M8GP?!v>|pK o5&mAs&f}-}{$cca1A4zs-+=z#q;F#n@;!Qs-liYYkLlh20etJ?ssI20 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonParser.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonParser.class new file mode 100644 index 0000000000000000000000000000000000000000..be20a447110c968bcf20d72ac7855add472c2815 GIT binary patch literal 17043 zcmeHOOLyBu6u#pmwc{pDNn0Lmp=x>5Ng;+(UQH=YQk%MUk~VQt+Cs}%9>+>#Nl0>= zZdkBj1HXVBOO~uSr zwh2ru7MAYKujTW(m3ym&+c^THKwx}9*DRZA_BvG?YzXH|6F77^m!DfJmV)H?*Dw&+ zXEL1EB#u`d!hk}3L+><*fp zTF3bo^a@MDaeRLN|D0*+W(uAo$7^ev$t+#H&nl9v*9}FbwxVm2Vd`a-)vfbVdbCty zQiaJXHIc}m@)q4-(kVy&GbsNVF8@9$m-wp^2J9K^N_lzeays&Iy@aE9|T zvkStVNvRvUX-f`)qDwN>IB1zkO+KS0bJZxANV0W_O7=s8rAJ%T5Q;VwQK-2Wsa+GG zrAPnvk5I6Mx}hqvVoO%TU?yrG{lIL zQndT}7LzC{sMd;*9u37pD5Ao0Zd+!CW0sFwLr_WFQ0vUD=@m24r}qj+)(R^Wuccjx|Ra-xu)hpT3d>7v!>W=6@7q349@v=B2dJ*(KEfIqX{(i zp;uj*Igz(TP26McnyEj~X3;p-P;dV%%wwJLADB<2qn> z8g<8}M+2G__|qPiwA4`5h!w*XUNReT*ioLURvfsl7-NvboN3aBG2rfmu_(g;SKLyg zUS?(#9QWRvyqx^+I#d**3q5^9JFYG6zoQSJ(x5ikE@-{AMhR@3V8Hu_4Xn(L8f_Cd^XPCC2FR zHraQ25FPvjTrnAJ^wGiHc6GM2UmBF|oFjexmi?XMu!AFk{-Mm46D?6EgBVj-pXZqr z7c~ze1P)`C@eg;q!3fjI1wy_EkxoJdukdd$`dX|(=jQTtWfM&i5L*TumEl>^6ud{s zFClajUhKOZCE|?$XFQHt&MvO|a|%zf{4}q(HFQqkreJ|2&J2{i+o$?d$vt=q>{{CG zXV|}!S(sW+!TW@;I87_A6FSt1MSb zY#ViwUez0>%<>AafKB+vXr1P`By3`L-wG;;cQj(-;CPGFlYn**XmWJ_M0OY5R;Cj6 zJ6RxM!y<2K9D}1U0{ieTiFXM|;r(dfJ`IzwAE^MZ<8Z*CnZW-!?LqJQgm<0vu7|wq zVefhbo^6Uxi?m%IS$kr3-jTfPbcte=Ef*V^h)g!Qu!s|bt2XY_qYg!P*cYpJVe z{8Nav4A(p7i%bZyZghopOo+7tt3tkfn-Iv0Obf9}UGa5Rh_%*@9?5wj)_PZ1mxNe1 z5zEgszEyqjxV4jYA;Rqr5bg>Q?x4Sjc=%AjLs@_Ta2M_c5PV&W5JYht;NuPu9te0y z07YvNJw;jY6rTzaDjgt*GYIPd;d3Dm)eaE86e4V3c27VJbe`og^G|~UTTuTC!|CdB literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonString.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonString.class new file mode 100644 index 0000000000000000000000000000000000000000..abda669fb4f4adb56f8ea747fda6254e07e7b57d GIT binary patch literal 2908 zcmdT`TT>G;6h5Iq%YuRkc)?3Vg;uc@Zx7aS#$j;4L2v|N^ex>68rUXlk|O*LU;HP| z=#0MmL;M9kJDzMUt+KNF!07m}yUFI{JKwqFoP7EI;S&JdfxB7gA~0pNU#c@9OIvJ* zl_~+N^3t}jr7fdm=?T78tQK-J3*7`J6NT4U(BK4mO|*%?@L~iTFu7T30+n&~fsn#J zBruvkxLjBx&^@cFJPZ8<2HV@`v{pI?$4KVu3#qwL!49udU)4hqFe{X#p;ncE*Uf$E z^{v)8t#UtL8ihjUZ?jEKCnEETXkO8oH$kh48!DBhb!Pnv|rn! zY9r$2mS{UBR2V9xucQ&ia%oXXPH?|FJ#}tts!BJxoeh{V`GQNghOF`pA@O)@ zC>@uRN0@^icrZ8sS;%1>SVW~uje3RaRfdP$RTky5V2x?v=0AUS+nO*03X6$_su>| zssE>T;2~R44ej&C!WE0bcGHZyI67>hqjAo+8f_M42n@CF98H6>aQm0PtrIcuR2YN3 zd==ZW0ScH2c(cON1U=A;BllqS!ase{jVl9P`1L-5_i}jPJskgxvo09IcQ48SjKK+f z4@6@RQBL9vU<5`HcMM0}xN-{4;K<3J#qUAf@fh5x7+eD9;R0%pLvvi3EHB2OO~;~L zf{8@5%Q0v(v1nIeG7)Vm2JK!fS^=*80j(X6>oI8M7_7%Q6n>Ms@lQk2mKNwAYzwqbTViNSfu>N>CZ-8)QW7Vn<#)24#FMOd-Tg@$ zxN?L8S5DkGA|xavkcyBvfrL14;mm~taDyZ8W+%4S@pwHh5u~UG+w0vo-@N(WoAE%s3QMGK7>22}%wbC5L$i zYH3ucZid& zYMDoSA+t7a91*KoX$m(`m^XB3jd-c=NVSxX8YbB|Kdl9;yUMf+<9C_4Bbd?Jn|E#5 z&X!kPQQ&ll{rXvAgW)Cv%ew4v8&%Yekhd`;5>!o>VJ9J1k(EE|>i~K8f@3f6#kdG7 zjd5i?}cQ!C7Md8t$JtF=8M1k|%ibeZcZsJC%( z+SW3RmIhKt&e_2kyAX{K)&aE3>PC}%Sq^uYdLyy47o33s*wqJpu$#c{Y@yNNN_K}u z2Ru-~>U}b(%rmzr+AIP)3yw*xIf|_p{$IP9@XH*V>lE&sQXVU20w=NsS)30KcG1Vz zH@KIC0|d53){=sU2>hneackFLo4!ytNtxC@jzp3T>!Ko#&|xce zw~GlRSH!!hsRaVZvg6vmnu5awCgQ0TuYYu%QOrJ}J-d+3cO^ZlEuDg61gh~X3*T(% zE-kI&G-5^9v~|Qt!@b(;LVQ(sEd`GgI2f-qnggxPy%E=?t097nYvHBTkwBVz=N-pl z)W(;A+$*{PhCCdUrcKbFl&-qs;9KWD}mE>CF0YNoL82} zp}sE>^6tN`Z~8V`f!i1oNqKin_kcUBR_NmiN}*PQVvL$4@U4cWY9l%%WUcKNA+V;@ zTI(e}=$~{S1kQChOKSF2Rj7HHz#kfvXsuNWY3<7{M76hYy4wn=mt7Aq{jF;f)-syN zy{{6mHOSHQ7oCO)eYZ@#vN)c@G;>1)NCL+@SXp$elJ&5)$;>!`YqC5ST}^+zoefXd zaINFEI0oXL&usr9$5*tjSzb*79x(RG#vutw)|5Tg(D@bw7UhNhx>$?*h)f2lhe&_ThB`pX^uYCeV*Ip+BfV zw?g!uHB1BLTUXhNbWnlxb_D5RctjKFQ3cX_O-M&#k%Z=wI~CFgO-R{Tq=pq#NFOyJ z4aOqH>-1?8k}l&%6+C^_gmgSsr}))4PIZCsmlEMgeFTzHBAo65VTTgosV)%qDiNNBXO#YMrqv(F5hcP| zcvc(Xq!QsdIH!$}S0X$QBiaa8l?dnIf;IwIB8S4Q>A3an3*SkuT&Pdz)&AVN*EM(isp z(7tYiHWy*Kv9>D;gzuFISK(S4eHv)5DA0aZqP>PYpwsG9Xur0iB>-NBH*j?g8*YI& ak*^-0Fps|g%lPTXN@G8mz+e$G3;!E0)5+2R literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonWriter.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonWriter.class new file mode 100644 index 0000000000000000000000000000000000000000..7c2abe7e9af4d6fea378775b23295acd739d7250 GIT binary patch literal 4410 zcmeHK{camY5TA9^*uJJoNYfSyrQ1-bUBE6Olr|})&e=qlHJ#Hxi7tBVz-E7o$ z%#BjBWVS2K)=s5fCP1nL&YG^{E9R(eW)Ju&-1Z6qQ%E*uIwz|T)wSi-Wf8DjmlR$jdUT_Ew~HWd<&h=^wWo$$i&8;9Y9DeNWg-3D=>XbUQZh z`>WK*wtJj*xn(nnLLRgB*)FF`p>qr9+(O{oCE9hlPaRj$K2uhYDqO^$dFa;hMHrt# z5T8PzOW|)2(N3c8xl++kK)BRmP5|2Bbf{-yvB)(V1gc!hs5GJP{!@C8#Iq+3rTDZ(Uq{2CH_c>*#X78^EMmCWOiG*58 z3TO8?V;Yrb7Wcvk{?l>eX205VEC&)fqx#?a_7&XGf&O3QMzt)mYAvXBb2Yr7>w|uW%QnOEMPQ-kTFl;NQUvpuIi-5SCy=it>=v-N z&O8kYZY}5?n2lBc=$iG@@Gh3zvD2J^>jZvCP*zVM9H?n%NaUm8EK(!`?-O|bV(Oi! zjuMy+jVnpX4jUeK2%O60w=+;A@O=Wi#$tF(nN5N9%(Qco^+F1b$E8l@rL)MA1$p zgf8FZs>wZ@S-j63W%iiFqklSQ=AW1u_>92SfA<0Qzj)kR?m$}nfe5aYxzRHs>|)bU z!sh#N{I0+Uz}UMYavokEo5J_8eQRUO=>rAKOng2Va0yPsG|tjEO93|IkVP&aJrmQJ zn4XR4Y)t23Iv>;5Lb?bGa1Phc;Yx15Pfb!Hdz8GDTVUw7LZyYvKJ1BA`VnVL<$tq55&=N+{Ep!y|SIE{bfiX z!JQw4m`x(mR#8z8YtLA3p5DBf{r%_rPXI6QG{PLiGw)=Q32l-CaU_y%Dtan8)FCV^J?>0syt|GB9s~CN4Qj&ezMg)P%2`41^w-<%_SzoRY}lTPaE+lcg={)!T@?++8oS0RZ_^{yUptkV_2Bj+G+a6HXWTp@og-fVkmH9hC4GDl9>$mF2V3} eCd2(pFua|?P{IS!J%@*QL^tq+z6#|WD}MoZ(h9Wz literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint$PrettyPrintWriter.class b/blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint$PrettyPrintWriter.class new file mode 100644 index 0000000000000000000000000000000000000000..42854ad5bc8f78eb19ae68cae4afb3fcfa84aa34 GIT binary patch literal 5017 zcmeHLTW=Fb6h328Ulv0`fL@?2(?G!~t=&s{BdAhjQOT7ds7a{+32D50Vo%tewPwc& zQQ!L1$3FG1RBF}sy}zNqrRteko2lE_&gAcZfBO>vR^ZDD zlo(t~wBL$^RIP2XBU-&s1lW2gO=~-eRqM7!WA<)qsm!HJ`+F@7>I%#;xboEb-w;S@ z%;30G0V>lT2%Rt}-ET7}r$Y=_hdS4#lIAN0CmP*!&g%X4@*M_q?Kr>+oM15Td<=!^ zw{B=1>nhB%>ObEpjY%BtV8H!28p==@87n^2aWBLuxyHTP<^Xwseke2<4Tb+u^pP() zvP~k}v}Bif5M#nsYr3+qh;$_x4P$M%GmtU&g|eVM z) z^fd~D=};qmEPJ(17-C<9Yq~$OfHxlbICN4UWXMg-1-Bk~wKc89UXttf`VML>1I&4u zMMyoEg;Bu;JL^Ts6>`m{-&p2dtNtzA?Mj7>Wxl23$OY!f;59RW9Iv5q3w2_3v6&gk zB$2A`H0Bw9z1qw<9+l3Sywhk8>`$-`i=8~Y->Beb;r z@!*^pNGiOpcb{6ZWsaSL72hg@le_i+b4U965EX-C4eNvV_`FOiaGr|2j8+WJe>+k} zM%Yn1GLhucnyrXjnMNLY-ARV6R^b9;wVY`wQl_nh>LUU0&uBQEb4 zoN+@p(e5!BvEO6x$B`Ag82yx4O7<}`26abxT&KHD?p_sI41OsqXq-=gOP*UnCH-_F5(kc-Qw!hI(P7jtnhPKA3Z2RF>c zy*w3eo(?7#_sUebc{==%i`$qAcR5FgA9Hc9PKBGN?@u|nC3qh`plsaFvxB+S%<=K( h9IRvTA?0HUK7x;JUQ(_y_yj(s))&+-)0=bf*?&XF>Zbqz literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint.class b/blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint.class new file mode 100644 index 0000000000000000000000000000000000000000..68447a1cf8f93923d112ec83d2d9ec3dc865a0ca GIT binary patch literal 3625 zcmeHKU2hXd6usj(vAr0Q(9+WKHAzFePQjL1o=DXyvZ&-@2x?Lg;%U5lV-M`kSTo~5 zep#hfYTx+{{FbVBcI~nPH!PKv_Ms2<&W`WLIrq+Z&b<8Nm)`*37Tl~sg+XXd)JcU@ zou}eRbOwotvGYv2&Qq&Z=Yc`zjvpAQTn(xWS|?gRGSZ>xYIP`w49-XuqjKGmFqT2( zNteOOH&RLWEraFoNw@WoLA9%6tic%ut6BO)sA1=hG1}DOEUUlzNg1>{Il`DnIvvYI zIH?sM8$C!cwYPcDI2a+1F-n9Xqp^sdi6QdMj7OVzv^|ea9&5B*X~$FHq7irGgfGSz zxuO%1Yx`2PJ(l(xA@WQz9c$xwW*{|>gz`ZL$Y(hJvDw7QE^I~7xkwM`wp9=FwD`@nR1cxHoHN%Myc;`igxul{{}-j@o) z7C$sP%^LG&^V)?*PIDMML}Ptj{K`zFwNeeU8uJ3)ps{d{rwhMSMHkMoRM!6sG2POq zTZn}>`*h)#T3QR|SSo8Nqkjk5f3Qb|f7wNxMP-T~Kme;vsKFY83t|7Y{@Hh=w}v}j zAFcYcqsOIg^~V!I$3oiNg8Xrf1*4q96LJ<0)NCL=o2uw5w^sVeh>%U1s1;&XkG3h07NP=U#)SDiic(Q8_XA zI_&3N-gyV1A4q^sEg4+;aiW||v8RrtmDIsqFCa5jODTf>Y(wtU;WGxR1ofH60+uZS z*w+&i;rG%nwY9>6$s{q=pr;fm{6tubwgw@C+hv#BRv}tm4hHLQ&DG#bx+ctiZ{Ew5 z&;f}}3md>-iLNfR31AskXtWGf+CO!gX=GQLC8*Fd_!WZ3=bJynx!>un0_*g>LN)*& zktaYi8wci$*u-y-MTlKLG{^ BiRb_T literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/WriterConfig.class b/blade-kit/bin/src/main/java/blade/kit/json/WriterConfig.class new file mode 100644 index 0000000000000000000000000000000000000000..e2092f533a3a5da392b33d12b4231e1bb3d76c23 GIT binary patch literal 1043 zcmb_bO>Yx15FMwXX|{p1g_h5Q=_wJ??g35|A)%^BK}lP+p{OV1c&CZmU3+DF3kdPM zkU)YvKMFD4Eowjrap2;wd4BU|{QT|vr!N5T2=29@!JzM~Omd-gaw^V6GRZ`W$(i!W zsWUoxWtB&}ZS;wnwxG#ir9x#wPm{gLDN4_vH5%*=M$d)}9t{7PY>Po>|6pf4K7PG_ zFxVY4SbUg3#x4X64e!l zCdENZ{2N7`N#%vHo>u^6xD+~&PLTi98MOy_ktwM>cV&T=bZh5rDZR10Zf38~mE)yO z@kD9Le?k#ji!$@`=$Ma6=R<^0T<9RUCZ40LRrz-Xa*c2J{7d%w??3Q7P>^Wq7HVJB zt@I4TgQr|fNSTn-6!bHb{&G8(7KO)}uvbt0sJ(ZN)~Xc$P&xO83m&9I?Hd0dKoKm% zN(Yu;mBD&%cxjSDZ|!%#bMLWlp{mV7slXW zZ&-`n>i^x>FUUt1NCwfNDXqlkDr8%&kL&+ad8Y+;$m;bmWgIEzNbHze@8ZxK8U%je;A2qY1DM R8x`(mHQs`|G&c!z`v+-=I86Wm literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/WritingBuffer.class b/blade-kit/bin/src/main/java/blade/kit/json/WritingBuffer.class new file mode 100644 index 0000000000000000000000000000000000000000..d16b1bf8218cac7369f12eb21826acc424842a72 GIT binary patch literal 3500 zcmds3Yi|=r6g}gZtg}f;Y66r7$`EMl1h9doFM^QT2!tg=B$B48@}XL<$MJ;S9cyNs z$3NkpRBEO6JHMg7rRtsCCb(s(H&P-VvevVYGv}VU_wLzw@z<}v16aa09!d<0Mu&|! zkV#`Z*a;f#DCmgBGie*!MkS3OwX`zX`hL*u3hklHFq6WfAlYiHwzoxS8OC=BB{V~& z$!cgwYC}LnudT>uB(%xs7tR0{iHVCnzI>N&=!}QAl542Xgf)82w z&mR&kjEZ(dhleWe%P6o?CA_ayI})+E%l(PTW^v zyrYESiLyKnY}n(LCW*a1tz&o+<)rR%Qg>SF|Dnht$+)kyO{cBD*GQyNF$su)XS=vkUCJ`~fRcvo~5s`1*su_De%dEs@gS?%)l|D_m8 z;0WXi6|GP*j=i#PB&v_oI5UMw%rcyrAaBO;8Vu@_h)6r zJ~pp6B8KxhU7TgA#@OufW$OL0GJ5OMPaeZq&2`ibhUdqZr{eEQ5d$QxVWfK{jPGX&Q90nXz65211p^8%&r?V63){9IAMTu^h1g#6wc!#x^fH`h8SGLqcJdij5&&Zk!F^O=@Kr}nTyD2d{x<% z9A&q2lsVq3BYDddBhz~=hxgmp@P2j#-p_M*ALjBdU~wd`t3#&udJgYKF7M4F@z!&A bf6n0@!!6QM!fo845%`*p3hBRuFYx8x_ptFq literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/log/JdkLogger.class b/blade-kit/bin/src/main/java/blade/kit/log/JdkLogger.class new file mode 100644 index 0000000000000000000000000000000000000000..d826351037864d1a4b5de4a3eae388a212596f72 GIT binary patch literal 4142 zcmeHKU2hXP6g>`Ulgt*%7Fd>VQ?_jaOR^8_3q_R>3Mi{kq$U(0o}7tEO=rfD#|iMr zZ`dER5=gu6{3yhoNs~_1NjqJleOU33nTdUUeD3x2x%THTAO8k$55EMiHt;RH_FNM)N4YuZ`t#|G+AbyCR5CJCcuiI;E&LrGs0|1-I|}(kaDZ zI>x4DjS70RFro<1(oRJh3Zn#tb1HME6vrY1z~jbdz12=L)P}3k3JCsMNw0e{&>2Iv zX%)Dy!Z;i5kHK9X3?(h^YomRx0voMZQx2t-K-TcL>f80L zddA659D`>R9HY824L_0F&pK~tU(Lj5h7-1TjD8zs`7DTK+L~EsoVq(B$;n1Kt6j^I zJhqK+Wu4ShQidPaucS<6@-w5+$!0zxDAT(fI9Oc39L_RaNS2%t#kk-sHdP=u2YyGI zc9aebOHJ(xZ+lM!_ZstdM}-V)&7(@;q-w4+6noOfTEVbdZd8sO7u&5D@iWV}S3Xuz?K(3lLGhiXfbxNh zRD8`S;5NhA{oB=OcNXyLf!5J_7f@w5w{JUHV1|XKDh%mD5*-^u+yp5S-7bN7`kJF> z4h8y`LlGr<-=p3fy`4{RUM?;Cg){%ey+6`38Ugw((Q_gGc5n{o<2I_@)bj5Ua=3t> zQV}kuaJZbp;R7z=GI77M$Mh<_$9(eiJ@V*U3R-0f+Knk_a}zY4f>upI194kUc(>2z bRtm!JDF`{N(5yMEq881LJl0Ub9o+p2^Ns`k literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/log/JdkLoggerFactory.class b/blade-kit/bin/src/main/java/blade/kit/log/JdkLoggerFactory.class new file mode 100644 index 0000000000000000000000000000000000000000..59a8c8d507777a4ce2cbe88fb4a7002dc9318c44 GIT binary patch literal 1319 zcma)+TW`}a6vvNC*EFH9F&OuYH$Z9;N?wpa+q4I!RRVSJ&~6fsZsKL$QaiGpiG4C8 zkl>vUg*Z;w){av85XUDz{^frz_Rn8mzXQN4c zk6Fs;S{Y1;!Gsvh8ch^8R4PkH%*Kb*;vW7v#{kCnU>KoGN9d%4lZ3#3H_9^+3rkIr zbB%JOvAS@%p;a#09V!ehWWo=GMD78u;G7ki9rq6DZegrjK`+Xr6H^~pt_D~oCVQ*HwFZay`0YBxoY6AkV$0d|8Zgghys*R4)7pY{n&?s;H zFUsbNt@%JrxKChbc3-)+nj`-N-i+%wOXxh|G~p3}?*CQHQ(*!@Ulls$UExZ%a=8L! zJA1G?amLEFOPb)qPcy+k92TdIP@*;6IK=2KMPs^<@ zaQz2bHMoIeqg=sG!g;Imf}3y)EtCki(d$m>d-t4FL%Sl~n?hRn2k8Ow&a_+*9!??n UQwTM9T&j2i&+y$qRTS2K1GSrP{{R30 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/log/Level.class b/blade-kit/bin/src/main/java/blade/kit/log/Level.class new file mode 100644 index 0000000000000000000000000000000000000000..31e1b6e251ff86e368d0640a5394cda0b7e26e9a GIT binary patch literal 793 zcmaiy&u$Yj5XQ%8+K?qBCD20o>!z1fLc2ohi6W#B5)^4kq%;k1bavgut=C?8y%CSW z+aQ4iSH$yh;er@%kh+|>%+7B;{yg*9KYoAy3INA&Sc3|IgUm!h!h{Mg*op;n$zmQ{ z3L8kh2tvN%vIbQGJH@JGY7va*7d)~AHm8$ruTOvs32gVY$}CfM#$?VnP(Q|kSN)e~ zuN{0RP#um2W6a4D%-?n=BbR@~qW)wuo;di4Fz8OZAwuOHfvx943HyS;M(1dTn|eCt zHMm2ddDTnb7;Ub>K7n6n%J59f6_078lT=7%g;q2*dMTIy5uzGkz@voQWjmZ z1*h#|WFJTNapX3QHP5KhmL|+bOKNcs|B&LuM^+oUHm`F;MMiTK^K+q4_Z(L+XSuZHYM;KzGwW8ciZbOISqqmWJrDNaegkg7 z0|L99@XDN1YlK>yIP;nzDva`E&drpe9|T&Vj+mS=BOL$zS+z@%5jYJ0`zTHbc&9oy z5g!OA=M_(-umhd~-WlHd7VN_&MgldY3gA6Ky~G~!^%6Ibw@Z8jxmn^JE73V(0=(@l+29Gc{)>ZHrXz}j=V+GoO0HG$n0RR91 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/log/Log4jLogger.class b/blade-kit/bin/src/main/java/blade/kit/log/Log4jLogger.class new file mode 100644 index 0000000000000000000000000000000000000000..37a3b6db03b82f26e21404f165ee655c4f1accdc GIT binary patch literal 9128 zcmeI1&u`pB6vy9elk5-Drlc*Ulpk)Obhp4RKT-ii`IC0{HghVB{^DpqfAl}$BQ`gbOZk-jpmul{6zw1s)y;dEo^&T$bI+lIxR z9%`P?C)Ur*1M(D*&vqO!UK$kk|Qb(6&j5ep9;d0+_OyBAn zK0ZVDderiVpFy$eQrWt6rG76VY==2LE_?$!Y*?l%c`a&09%`9v?Dl&2fcJ?hT$I>T za15Utrs3c2(MmZCM2gXpZF=53iXO#&G39|Mj45X7ZVtPr3DPv%?}r?0X+2opvuH0E z3WwwHZ#dXD1v7ETX+}gVY~d`)6oX3nMxP47+BD^HEl0GBG-DXdnnb5!8ApwaTh7hH zBV;)>im^tT1NKI12Uq390Tix^T1HyaOKa%M4C7G0%iBhW`av?RGS{ye+k!hmE|G2- zLklqGgl#H3xf01#<1o*|#XeZmjYu=?Ijq&&&930L~Y5vVm&${Nu*7%LD(+_9~j z4iZmSYlmwP1kQi7>-x;0Yi^%;4BNgg&-Fo>0h_8cqa}W>1Wyt8PNN_ZJ(02#)7pCK z7!fE%+fo9@t82BmOjCjjq|nmvIogz__?+9>DO^o+!^OvpBjkNmsjwOn3zQn^ET#mG z*}Q`@v${4k$HFyz?(@U9YFj0^NXQk9k*PVG^2;9&{kf6AqDtl=l@HQZlJ-?Xz8JCg z2R@}NF?|O>x7H*=V%vgl$XcNDV3VTz8rF-s% zJF_Az6F3#y9z?$g?-4kg@Mes_mU>DGyRL~3stpHEMGfIC91>vHCFn}3&Ho>1U>387Ia|+tk1lscnwDAMlB?WCk zLBp*KTuz|H%DaIqi&xmXal5W)9p(IP5PEiw`~PY`j$;MTR|gmHKT4qK^q_~n{Imwn)EH3ZeJ;A z(zk57eXXDocq5~3-zaDUq-E3XTLn$}mQA-i3YzpSn{MALXawHW(CwOH*8iZO4Um?u xn~L_Mf+l@S*G)zHNkNmorR%1m{j8uBU>?`&0xZBPeokVxUWB*d9e5X3{su(NCRG3c literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/log/Log4jLoggerFactory.class b/blade-kit/bin/src/main/java/blade/kit/log/Log4jLoggerFactory.class new file mode 100644 index 0000000000000000000000000000000000000000..f89dcb9d6598928c2d3abce2143f8346abbbea8d GIT binary patch literal 1325 zcma)+U2oGc6o!vW*EFH9F+RpO-T~ZXq|S!v`R=FTx?9@(oMb8U1~?RGqGQW z1QOiyqY%dlTU%DvUc||XkDt8f_;r5${`La^HsPfQ6#}8raWrB=MniVWqF&1SJUS6J zN>vhdRkAt6A>q2iVypC-2UP+qMQX}q5`F9qd2BtX5opaJjUfbT+d>MvL*QDobwr@L ztNPr7>jaj^=sm5KuEPyN-hGmq8*6I$|~+P>XB$mkbM-T!UqVt|6h55>68W|NSUSMJy~e zdB!!$k;dxW^@f(cXtt;@G?#sTEF^M|aR#4Rp4!RmknZQkx*5!(OgbSYcmf&tyD2k< z#!NcZJx(wBU=?N5o@G4n53Ck4xjHF;0G1oz!3u%9&F;9%<>I#6h2<_v`H+u#Tpu!Q zEP>UoidlNZv~cm?msL9uhQRCYoc;dCIc)-d!foj$0&gZo6jioc^N8pmM>!CQWH#3* zaO)Cf`_;~3pgKGxuy?hyoUsv!ySy!i*OIK){5Nw7o-ZtCF#Ko($arOkC1n+WlVTH WgW%5~RN!f$;u*Zadks}l*!TnTZ*lqn literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/log/Logger.class b/blade-kit/bin/src/main/java/blade/kit/log/Logger.class new file mode 100644 index 0000000000000000000000000000000000000000..be83dbca63bbaa79f22126ed8918c4452ff94c8a GIT binary patch literal 7210 zcmchb&vV;E6vy8>PHZb_64I7m<%bf|Vy9q32>p?yDUcuFlB9*CVfb-b%Ns|nEO{h3 zZ8_l?h7%`-11C|47&o$PyLPz3U?^YM z!_ZZ)Dl#y^V4@qm?)#pfg{PQt?zZcTz;g~o)wH~N!*+ORd#>5=y^161!J=v8b`OME z6_&$&3~F%eF0To5Cd#>pITtbK8MEq%z;wOPtn<)1Fhgu3?l&;wWE;%4C|xT`DaBrb zkt^35j&0eY88jQhM>%c~`b}w;8Jm|cn08<`-KyBPUF7cL9sJLmPMC}?np@2vly@-7 zer2#uu%zwHVTf@@W_BDj+Ig;`s~$5(mH>%!t~{+kEAt0tuTE# z>LY1QP%BJdj`~Pi6VwXRm!m$C)&#Y}^yR2T(yILlzsCA@XBaRJr^jFv&M-KeKU!5Mf-mw<~T2#k_*r$Mtz(FAFa-m_ELo#%h{DuJ*Vq23IIs z6}nx@!Yd3mPV7yo$YpRjDI==qmI^8=Fqs{@=JK%VsDZMOXRv;9ItsNW zg9~{j@maXYpmKbl(f3c^CnQ2e2RGPT!I&+u7*p?jxxEHmH8z@0~8c-+hoDG2i!!UyXQjmcx9@CJ+ zYXGwtF$!b&dkW7MFp}ZXcnIU4PEGy}Q-9%E3eMv1NOXt6)A(P;V-!3C&myV?&%yKU z<2k&ZgBRdMjF7~+9^y*`aXKQVqIM=o#YfxC5be(Qw3|hh=aG?u3q<=@iS~t__Ju^h zh-o`8N3<(;+A(+yUT?SSb*@OXn~&P{IEQWDfHxBa=|b#1< z@C`wb8q|IGmLNzC>OOo&5E#5SfDb26Z2PCJCzpWbtbs zg1Uy^2*TH}2J4AcuDjB15Ubong23PdC?^QrcQy6C_?sl$7=ZAIBz!mk;UAK)IRN2b af{=nOd_$yQ8*a-t1y(aRvCjAicK!!6(l0gu literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/log/LoggerFactory.class b/blade-kit/bin/src/main/java/blade/kit/log/LoggerFactory.class new file mode 100644 index 0000000000000000000000000000000000000000..05524a676f4ee582da8a9e3e2fe185f36c9a386d GIT binary patch literal 831 zcma)4O>Yx15FMA2{UDGwP`*J{PfZWI7bH*<^-|H(0*8c39KBv^>(*lw{Fzvp@1e}4W7059Nq1RDfK&horrQs-yvg5{-RmB`Pf&y}h3 z!ql~}$BcVpFC*9_uob!#({=u?JQLg#h$mc0E&U;Z8+)S@0-Hys5)mW>23Os$tu;1= zTLgZ**H$>AE<{DSXi!*dnLZ8I+fG^0JOfwvLb{M~XQ|Iny0XDd-HT>aEoE zznfBs;dUSHz<@w+vV4u5z2Zv$0%hF2&!CW6yq!0turr2|2@DIvnL1%scKNcH)WRwPt>9@tT9bP$v6_*9CgDI{aJB^*E$cGq+qE%ca&8Q-!re z@OaHDL0|+=*X*{ql0g5BbPg9X!{xXh0dyVO88F6h6MC3OnC&mC=@*DU4AW20|Ay5K m*uvQL0Djw{(z$vFcQL;g@|}?159bFVK7?oZ@8R?#c=8KL2kNf? literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/log/SimpleLogger.class b/blade-kit/bin/src/main/java/blade/kit/log/SimpleLogger.class new file mode 100644 index 0000000000000000000000000000000000000000..e2d28ee7eee81748cbe6e2d94dc718daa1335dc1 GIT binary patch literal 4274 zcmeHLNpBM|6n-AsP8tHGWiOj4Tf&mCUI;>Bl`4frv{XWzoEbMU%#0(C6X3{|3kOd8 z5+o|YogamGp2;%MNi!8G0*Omz#{T^IJwN+<&-wQK^A`ZP3fF9~2oyu*RD33a$_v(E zmAc1VUU?~W#gmQ7lJHv|ugOM(D;p*VENq01aRj!7?ka(~T0HtL)BL_vKGRhKIoZ}N zB?3)gNA0nBS<;F#AG@Y*h(PF@IJ{U|Auw@Ay4;2x1ZE<`JQg%6_mq+<2Qy@9?P;KR zD7_AMsU!WC@R$}dpe-fq9{0oRG(WxEK7Ni~k)uUp*F$ua14*{o67m{R_kA)W^pN-9mGej%yD0>fG7v}fgdnC7o_CSY3& zFBSOf0;hnemXuNbrp5Eqn}jFAGm7|4sJTBB)L}|6j0#$yG31S*z^<8N14V%vI@`dk zza6&)k;v+DwunVCF*xW$mpl%z0giw?>TsomI}%oZfhTnoS0>OHCtPkS`O0kgaTpc{ z;C5ShE>|N6H-k0e=yTnaE~?+FVu`LQ=|}Qsf<%+bj~cehRcNHd$fGa9(468J7ai7E z+`4oPu4}x*y&|gn@6%#-K!qP7r-K^LZ%1YyqZWj=dSjuQAdu3&AlL>R5)Xgii!1WLul z#727*Npki1`X;mY4?SrITKIf1=!j6@=D%f%si?lgy`Hc2l0!8ICkcGW;CpXGijX7= zq}Z%6fC$`7^EcscKS!i5LJrOl>-``0tZ&m8R-jwz{m)ye*MNUBZ{gWnl5OSi`@$ro z*<@acZbmkoBd|Rolr~%-usiRIfXsb_=ToL_ug&zhP`W0cs9556YTnmUl#1{A_05% z;CmrP!Cu&hUxr~0e|roTwr!5Vg8gtHmEmBD4f82BSa1jqCm04^97$ogl)~^9jsZnq zk9U1tz-P~+iM~fCQrNByVLLU1ZL-gHI)$y8!e&7c$5>Fpef3#izYes@sszQ^Ey9&ef8u1JzcD)i}kcJg`xeXxo$YR@ws_(Q9OOqM4F5J0m59;_3%-5yN4TyE~UDKrNt<$XRGaec_J zu>>{-Dq`so)567n{;b-uFa%x>md$&Cb$SH+gxk^y1YXaoD9Y@0mLkiIjxrR9WH#5R zaQiRH&WqjEKy|oJV1K!_oU>LK0f9HOIxc#;N;!3SM41{3; zLSbqTw&qS+QK1J<=T3I{LIRBgVGR1~5WQw#3-HY1Zwa{B-?-#N_P6 z^i$c&UdLYGO3=E76 R%s>l4fRTX}NHQ_70RWPcBR&8C literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/mail/EmailHandle.class b/blade-kit/bin/src/main/java/blade/kit/mail/EmailHandle.class new file mode 100644 index 0000000000000000000000000000000000000000..a0f6b2536115a74e8cf8052fdd05aba66fcdb270 GIT binary patch literal 9075 zcmeHMOLN>r5bjwV?<1Qy2?-?OCCnps056XaATMwd+cC(F$=W6f&#^RKE7oI6nswP1 zegju7RB_`MkSd_yNLBs<#eowSegFrGqDR{7%6Me;R;fa&$YG_Cw)IWFrl+U-&fnkt z2mq%*l%d36EDEiL#~r_Mi*NA8ipy=$Sa+m)=QgI)^$PcG7paFB9Egcr?zb9OS8fSQ zG8i_m&df|*V^A^8pw$xLSq5d#@x)xzVzAGgQ$rC&yd~5>5e}WeXHYep$q?V}X@@~O zVo*01a3DhIhzMWTBjMXikqGCxCm0+u`?EJ?==iNP%>s`Qq2#q0>^0{)u5{WwlnQ*+ zaRvT0Y?@A_UR0Y-%jdEaBIeQf^17%%tg%_PMYSqOxVc5cQ zd5A=9Zmpx1jM3N#6KI49rT$UF4n$=5fiyfWtu;g9M`E*$+E0Ikc2wm4gyLo5Ul7Sm zj@J%CX~YB_>9~f)eFeKBjJurPPlTHk{vHtV`%MM0?`dt91PIMvh71gD$gQ@hRWpfd z)l@9W0qMq;9IAe_$stU_O%X)B$dm)7VpR^w_L!AJY&!nBu!}~W_1dmuInsza7`8FY z`H>7emJC88*&oKn4JR@>zAaWAU)U4ITnFXC=oNqFZW)fh5v&V?V;oxBj!>%>r}g5H z$Sy-BY;HwTcpCH7s&tHGE7gFcS623-7+@;;8l+QZGnQtbx^&`s?1bwnNlgd$3aqFizB)WT%jZ9I+#lYTLz|1m7V~RT}>Amw+lJ=== z(K1=DMGF` z=-t&d5GFy)f$$2@3CYvxA!OD^wfRC$+BP1Qq8#Os`KJUNI+NXFb|!NhJajmoJ!{o` zacb2Tka8c<B?i9{3`h1eGGR8S^wSY_ zvaak{Y)p!YCp3jWT`8~vuQ2$QpdQkqzPCgSYAQT+y4755trHjS>kPguO2AZH$lR)u zQV`Ld~a&*B~U@WvczE)s{!Fo}G=i3O^q?-Iv(B4v7f0x1Z?vtx_A;puh z=i0+ng2nUrcHGIu&A#UkQ5mk{f4%1lyw6}ZpNHNDyYJmNRnkjUF$5dOsZMg-p)A7^ zgZc20Wl(Q@jGlVGj)Bs03wvQuiv<;`?5x$M=1(KfaH2?+4&u z{Co%=MwG+x_y~;P7|)e>J&JEmA$ke#weR8BjYE&!h9`cC>7K&tFwy}247}FkaSizy z#V3GgG7z5CAe`4AFnAtLqB|MC25N5OpC*g$@LSKp(H3-+W2oumqAt*g3JiM$y zu(b%U!fPpnJ`blf2!R&ibOyp38idca2ybN|oY5eBp+z{CVTKd#PT*Gfl&;%RrhcRBv!y+uhb+`#1!6)z;to#Gcs2!mI literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/mail/MailTemplate.class b/blade-kit/bin/src/main/java/blade/kit/mail/MailTemplate.class new file mode 100644 index 0000000000000000000000000000000000000000..8d10d3b96ed3d3836c38bb82a9611d252a00bd54 GIT binary patch literal 7324 zcmds6OK%)S5U$=V-iMvoF$s@6pkrRU1a=__kHn4>+XQ4-V-#;9Ax^zBZM);ynN?4Z zWgn5aa6{t2e}EeoB#_|FmH&fMJ+m)oTiRaHHjv9~ckkCOecvwACFKCkZyrQ3q~27a2n-3gfD1;`VaOHly}cj}w1N8D2cW>goj z8u^C=<{JaZmXadeStL;KJWUl7m})dctgxxHC3Zrl63Gc%NE??%doJs~D(dzvZi|5H z?ntvFLZOxkoT^kG63DMbJ_>l2!0cf3ds0TS2+xu;2M$^9ZnZgd(_Y#HEoXt>PI}LVWeoADQ}l5?8FZ`XoulW zXi^OiYg(4t6BOARJpDqgV|o*wP&7_DTw;C*VaSx15HLgs{qv9jRDxHuiRzOJI$6_1r+tU&*znf%`gY#*2FVJA_jA7^btU=By{ z5b{39O(AB+kxj}lel^+N=D2sV0_#{A!)F1pnkUUOq|2C5hmcl^Or*7yyzW4@x!P*P z&3!JV@W;)X6_-1Zt32k4C)4b>R{<;gxl+j$&&im^m9&m{$}k7#XW%qEN8o&A^n9z& zuCoo?ReqkdTU<679!K>NI`UZXkV&EI-NwAy6?lHW+OR&b7i8yPvy+_b!sJW$1p~90x65IK;S2f6S|e#YnhHY{s#>LmB0D}9H8+J0+fk95C@ve*||K&+-&^9*eW|4pr}v-%aG_n47h%@^Pt&$G(UT_EXSiaJ=9*EO zSKw8YCbPh62By~yOv?tQub~1}qbzS47(O*Jyfp#C0|Ntrx6vLZ+YT&KGf1;-dmq^bGc{oNz`*dWk>Tb94Br_UZoy)Iu9pnjnCAKi X15*xeqcw7{3~TsX#HhLqcVOi)?M(4b literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/mail/package-info.class b/blade-kit/bin/src/main/java/blade/kit/mail/package-info.class new file mode 100644 index 0000000000000000000000000000000000000000..8719173cac74c166e561cea4a0163b32ce0798f7 GIT binary patch literal 134 zcmX^0Z`VEs1_l!bc6J6PMh4B|qGbKt#LPVXti-ZJ{iK}4lvMrf%o31Tj($O6a&}^R zs%~apT0T1i3nPO7SXEA9Ub?=2QdVkm2_pknaDHh~a;jTqPAVgVAhHfUkYX_g21W*E Ppp78F$iNCDnHbmr!xtl< literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/package-info.class b/blade-kit/bin/src/main/java/blade/kit/package-info.class new file mode 100644 index 0000000000000000000000000000000000000000..e9ff61b110b55ccbf9cd4ecf9d0815fecc85394d GIT binary patch literal 129 zcmX^0Z`VEs1_l!bc6J6PMh2DQqGbKt#LPVXti-ZJ{iK}4lvMrf%o6>A#N_P6^i$c&UdLYGO3=E76%s|UP NfRTX}NHQ_70RYb5GS&f$;3t9HK?*^X5%PUo1dd!k*HuL>$j`uwSG6bfg0XB2$ z<*n)?Zb<{i3Cs`0OW+U~H@EKGS>Gm*HBGl(=iVazRuPVnO9ajoiVp~6*4!F5;2eR; z?u_f6=XzO~BrrNJzNU zVonHL<+Q!t(-sSTqcyF=WvX(46t)(ij$mZpVQ5b&w9#zY!V;4DL5q9HBL_JjSkm=q z%a1BuW+jX?aTx54 zI!U*s!;ss;9!5nC5v@(3fukXE>dwgLA~$Wi^0tdXWBrN6TTxaT?2ZwdK*LI*2)<+( z5PNc0l0_O=BaIK6tciTYa;33A!_?p8vfOpsZ6k;mO)5u?yWenJoJ2jtn zMV97i)pc#ooFaAiqToywH4$wvKdKk}aCYu7KkzUG_-RfXEix{_Xf?n*)2>$Bc0v#` zpG%G1T^kG`z_a3Abmc$m=Myhr#2$~P8{%wjR;>6w$NIN7b|6JlNxW;WZDVPU)&3V) zx+&+;$-3)K(8T?!5ufjGn~G_Yp>Vh1VTYs;%IAg;*4nrTbBkNp5~-qcT9)0|N;75U zVFF&9fE-K{xL7c|U0kg2V%X(PnpiP!2F)t>b{RHq1g1^bV)g^(iSYa3j~UqzK7pI& z&^A*MqOrHkwvzyX8O2H-7EPok%H?)M-C+_#IDu<@1uF?%;=posX>kdMU)~NJDVlu4 z*%!XR<##s?u0C(J1Lk5D-XQRUMhn{>p`cchf9Y&29U>B#Q`qIWK^8j}y`>>tLG#4} z`dBs#vjqNl7R?nGgoC|@oX5Vg7BOk{;9mTkg22vT%N=f_9?SRq@G#xFLBBjy#5xCIKxyiFxc#JYt_O=GxL8XU~k4@qYAKg87&ceaZ9 z{HY$HoOl5d=|=Z3B~6a!p10OVj?wQtYbel+u8YQM6m88}KQf ztcHUO2#;LjD$an<@YEHnO9PgV9JfZ~HDKk)sc&445tz6ud>@1SE*@L?nJa)0_&STP z889G=hs_3F=OB;oFGNSr;eCMo&oJ@j^!XoQ>R0?W1~1|Jcywn9F5vYqbmu@CB-9aO4B&2&(&C{V8}Pyyb8w^5^bt?zW! zXLOL>RUj=ZkqS^m-Fr2>szCT!fq+Ny(ADt$AsUtxsNeKKz1FeYbtUTAjDp+fd#0*5`6v_pGc*A literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/resource/ClassPathClassReader.class b/blade-kit/bin/src/main/java/blade/kit/resource/ClassPathClassReader.class new file mode 100644 index 0000000000000000000000000000000000000000..1e637397f7f45b4ea57de278de90fb14601901d4 GIT binary patch literal 1275 zcmc&!-)j>=5T0#gu05k^<1c($`; z-9Jj4-Aic_FM9v`?w1-kjcfer1zk9}@ zb*yuY;4Xu1;9LqdNnabI%?8|K>zxnEb1yG2=b5f*Sqdk$;~`k3McUzCZ12S#7%RfK{qvu zyQ`Xf($!olPmt&lG5$%L;9jZ%jr9I2bcN0>pA#dQV54UL#2Kk3gXVB}crf5&txFVY zcfgnEejDIFWcioeuFV@pUa%(4g)-#T)H*J!n(~UuEyyQk)i={|sf@3#jud4#RLBxZ zgYv^eO1VQtnYb~Y)BC@YTtO{{7`h#ZV2i<{{^+J(n)2EA{nQ;vg>R?T7|p4mN@UO* z=}eSo!brcKZMIw?ErS=M+cob(s`eSgC*eVPBmEUmgR~1qp?}~RP^Z&>hn^`$Uj!R8 sZiYw8?*qi&ApY3ve1ZEvXtf60G`7RZ7W8P|X{_J@Jfsyx9;_b!2J@Gn2LJ#7 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/resource/ClassReader.class b/blade-kit/bin/src/main/java/blade/kit/resource/ClassReader.class new file mode 100644 index 0000000000000000000000000000000000000000..d0d876c21610b9f4fd6d92774cca3510c226c8fb GIT binary patch literal 1864 zcmd5-+iuf95S?w)I5B~Q&~hoaCER*JF%LYEC=wKS3Q&Gby&YV5RJG=Ai_qQJa@C+VXut4BRB3&n7B6RlH0dodE^SHAw zlp}c(jik$+EuSUH2ab7ZL4iQc0DTq?o%e%1?kWPMw(E;fs1AX}we=kWg{{cr7L*B8 zr|8#GMzRDK$fEifYI^^Gd(@4BSolndD5SBB20jmx=hQCucRBUA>obX53wVBdMqXX^Yflp{5>i zdZhR?aHNEv3G8u|k*6x6jH<(!+hy}{&%pGQ6q!n9iOzAUT$<0%c^)}0^d_b~c6vkq ze_;PI1F(2Ex3Pd3YbC*9v&McY3C8BycJ1;mt7w($D~LADR5Q+EMf01 zK@npMqm6Oa{tl&2b^9w+eqwe3YWUO`z_-gLqvur}u3&E2#49GgI*G4gd>y9o4HK_U X{=bQ=w@l@2c!a+;6yOd}XuyL%o69|n literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/resource/JarReaderImpl.class b/blade-kit/bin/src/main/java/blade/kit/resource/JarReaderImpl.class new file mode 100644 index 0000000000000000000000000000000000000000..2190716198e77529969eb19055cd3bdd684eb70b GIT binary patch literal 9596 zcmeHN>2e!I5bp629XPQu35Nq@VlH1u0n8CgIAx5JGAuS_J1NM&ku*p{_E61^T=9$W zB2YyYRKb6qfOp^#sG{hd)v>mBy<=E}?eY&vtKDzD>FMe2>FJ%{{`%<`09b~5IT#^O z@@2j3FyWTJW&5mLvsr_ep9oc!-1j=N&dZ-Mxx?|U+;rM@4#o&9r?y$E`AV|7TDO_+ zhplsPg}_p3%Sa0XSFG&^4>ooPfriACxw)AQ?cl;GvEbO&7ZScCyB!b$k{)9C- zozY&Z(A)ld6$5#~R8x4-TN}G*v zTU?63ZdlheZ(2vR5y5V*ljNdwgKQ3%^Ie)lg z#SABk*lS7L)x>~`h4jYRXk~MI<7u6@4Th7L0YyiYjZg-IH<_x;B7LTYo{fqy%G?)r zTF!|m)aAP8x}oLAm|Ar9P6;=61ti{Zl{`rA-vnkfuSOt~iA};33;M~Hr|x?lw~?tE zY38tIVal7WBNt%;o}GXKOcS^nkC+s} z|L)B()e=5|J63Al1+8RI<-sybzLy*mn2C|$@w|n;gt)@4Xu3>cMvdJh0;`cxX#G|f zRx7L6{N_%_Rl?z$?!NE^3O-2eQ0}7DOW!Jac$L5p2GyKiixhLuCK8w!I)TL)y&P3Y zrLWOX4bXx5!UhSN&BH8#-_N7ELeD;V_6S_>nP;>#Lf}gi-7Q)JBSRxh(c_zBr%g$NaKoh7M_*5l1oHY!Z2jT1}L-llSx zA)YD0SdfFec!BPm11wNPPL=4`mxGT9OdYMs5SaKv_&&au-@`Z7KHLVRz|S~-W*`T7 zJaKacuM1Gb?`QP+o8UP>@n@L$divUrF!d|`8-eG#NPsE0j@J_*3U0vj_>aH~@FFt5 zq_Hz_vx|Nie|xN>cpb9762rQXzg)Z+ZoqU2Ql zg2d$P#Pn3%%)GRGb_Nzk1_7|joW#6zegCAa)Z`LI2CiVRTDQ!cR7M6tWF2}S#bOK$ Tj10^`TS0)4ffYzHF|Yvup=c#( literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/text/HTMLFilter.class b/blade-kit/bin/src/main/java/blade/kit/text/HTMLFilter.class new file mode 100644 index 0000000000000000000000000000000000000000..c1bfc58bf21d610944db86256ca4e3e3fd688ac0 GIT binary patch literal 7953 zcmeHMUw0El6u%owlcuFD1w`=Qf&wjKB7(?&Op~;YB+Zg+3k5Y!Hbb*?vm19Oq1A8X z7w{+^eer?gXYd@qfsa1;fZo}i{G$U&4iy!7XztG4xxahw+&jBFzyAF2yB`4H415)a zkOId&*NE4MX~*x9CW)6VQlaq;lf@a`Wbq|Emt8O|M%^%sC@}5Mv537M&zJ8~gDEgs zNH3;umKL&!#bT+LQ9!}Js8&kmbGh`gUQ}Q#s}Y6>_C>sI-%wywE9q$DE7Qv zD;4!bK@UcIwbJ#Kyq->#61rZ<%&+KaoWEZytt?CQ=v6D^^?Wj)RUo33(0xWC)A zXqHLlQ)zKGxWv1wiEJhnOwVu!lP#6+1Qi$+k1$av<5vCF-3z@~Gwsx0RO5`*J!Xi-xCbS+i^wneF`_`8NRE%sN z-cRT9tLc)K$P`NR*~IcSR8M7-j%_qtm)a~x>U`yk=DJN-!=(zG?7e#_+bL_2xu(5- zv0bt&Xxi~nOlKF`J|fM8WjXg~MS)$}z{zPYWpG*3V-o$9iyS}N)X93%Y1qtD;K<`3 zGB%^@)b%Z@>)2exx<|IW9NC~jZhp9EfjH=4eh;G(#Q+FHT(;>#64ly1}>=B5-lUb`fE>ryp4Q5)ZL2M3NrfMtF z7ZacP@`z`yq!=o5RH8PCYZC03=-AH9WLxzo;{CgP{okT}`g~s?1bgTCSck!%0MAFh zFS7VAb#Kr2>to+yK}~~?);^Q^z2*X_j@u>TRq<=K59;6I`X6%p%roAhJo({bC(5)# z;fRAupNMvFu?KTFP^UiMlQOlsWf~?^y+)n7czm)w<~9uGxN1OW%+9H%r#9>gy<^(6 z5>s;xY%M$$`DWIZYT8X_gQ^72H`QK*=vc8)uj7HoyFpwVkELFp2H2r)d&U(T>?t}( zP*FG!S0>;rTt!A_cKhL-pM|HgScc_BtxR2=A6AfC$vOtHR>k2(C`VY;#3S}xc0eu* zIfs$iTiiip)@LsGWz4^nkQ7~^1zmy^1UJ})#ilF*$af{5d?@E<^1kIpzzSywB7p4G zLVv(P))+Yjqw4bY&CGSB5t!mCOjlXWD&m>nBv!IYTwKIsvQo%wNALK&AcB});t@&% znT%TzSW)0`-#oC$rpE(nu_qYAB=rnZr-DvF#dw(@_hL{^MTpccO=6i9!n#!B{z~{$wiGxgDcwNXA;o2Ss~o)rCEbunYK2WZ;kpE! z%}Sg}D7ZOp)MneJ#T9aGu32s{tj%!=jwEP=i58uPYfz-4(QK;2O#9SS7#z%^^Ywwa88;-W`AA=dpxig-{@f@5$+ZlLA$df|8 zD`ZT_xRCD&c?#b5?N0kLg#U;L#vl0dAo@HDAL8#hoOK3QTR|DU59ilrE`9@-f5cG; zKEmHo{|;_$yq*YV!8{~!#1T^X+d>GTZg_+=`UzHN;VFzem-+ie60rgWD0b!C z=>c7m^Y2oG)gci6kRSlucuW?u7#>OyZVry1M5PF8Lm(WLBHS7R;j#oF0=MClt}fuu zzhF0gy1f=k&PU)C2Ph5UxghZj@c9r3UrQ0l5D53B2<0IVew8Ae9s=PvDS`o&uHDe7 zfTRfgc5S>laI5B~Q0Oea+^?*_i_Jso?RWB8lr~*hNRN}Z^56L$6uC==k^p_!l z1o!?Z#Mo`s0s&DjqnVwVx9`o&@%PVP0pJNd44}ba=&X!$p>%vGmLg6vkz%}1KK3gA z5KqbMno@hT0W=x(>!M8PS^PRVMClncsSp{keFm*=~LkZ;x`BO)19 zBsY0#&~a@%&xMzB?x_hs7R2si6X}d9ol(Ul`UN8FyvU18N#(gK3$#Q?J8w(rjpZjw zhg)1ZUg{LzD~)NyUzW~S|I}^S5m$O?7RUt=ng5Isb|y#8W6q_}70m?snezWkg%Coo z3jy>Q+!~J0$2;*>>Dj0ne{W1YUzK@+b}DG13x;Z9Eb-U zG=m1LLyNp7`2n=acIrc4BM%__0^z$s_Y++EMo|NajNxJeO>6*kEJ ej&OSg!lRW4cQ1hutwgwY352IB5$@MoAN&AM?fSw1 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/timw/TimwManager.class b/blade-kit/bin/src/main/java/blade/kit/timw/TimwManager.class new file mode 100644 index 0000000000000000000000000000000000000000..a173c27d64f69966ba86de976e4e0527a56e4765 GIT binary patch literal 766 zcma)4U5gVj6g}y7x9wPMt*#$$aebLC%M5}~R(uf!q1A`23qGcq*k(JE3`wTyFB25> z-Jjx*5bsP2yNbvXxa5X&PtLvP{`mFf8-T~S-$9EZ_D-gS&?Y?>8<8$@k*Rd8LmG7P zA)Qm02_u%ub~Oa55La1xKNK(Iwmy12ve z;QwxsSq#yst(;UZb*+AQXV0hRtw5X2ZF2xq^{RUkY)7t<5 literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/main/java/blade/kit/timw/TimwMonitor.class b/blade-kit/bin/src/main/java/blade/kit/timw/TimwMonitor.class new file mode 100644 index 0000000000000000000000000000000000000000..9367e82328ac7b7be06e03e200704b2c3ad6a561 GIT binary patch literal 2867 zcmdT_TTc@~6h2cfy-=Vcc)tvIYZ1FDc%#OI5H(0qBbCGlAEvuwJ9KxpnVnYgU-)ZG zG|_i|l=19t2_QpVlD?RxGqXEqzw@1Q=6v((_qQJaumqJfqzDuPWm_H-(%NQSX4PHh zaH}P>rG@v=s^PHVOQC(0hG7DQ$jD`~VZEwvb6XP_LqopmcckWuzVJy_->aw)b_o$ zaG4gqq;2KbUG4?TG?%S4Id!=0GKEHMX17>_)43?rGKN|XY0Oc_=K+&v`1|wL&!R(yDZTt4%M(nwNDw`jMGk1py+4WnTG9=JEh>(;+ zGN%8x)ys}o53_TqQ2UFKEW`mqZE7WCV<4;s2$d)eImp9_JY->tz)Z2a*R(N_O4!ts zRXnnBx@rvjl)zNgx0$=eln9@DFNbwg1c^kYCsHUM6AiAB=bj`j6idlPDFf#S%=Xt5 zloSHF*i9^7W9Xunn@R>Q5s>{6VpU2c1Bp^jU?k8?p^y%7>11Gz!1MkLB3VpAfWSCH zu1Mz%-*r(ey+BzG#AhrUYV;b8tlPkpU>4$O6vNf=zq;B{hml;RSzFp85C zUPseN>CgepfR&8g;5r9yxR}yPn5Yrk2}0c+scuHv*&4Dh(N&^Z3s~4)@1!wS-m# z=iGP5znhx)3WcBel!B8ujz&8Ln8tNJwt^Wrg---d!xQ%-nMQg2d$P z#Pn3%%)GRGb_Nzk1_7|DoW#6zegCAa)Z`LI2Cm@z(xT*4x6GVWMg~D-9eNLb1Y literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/test/java/blade/test/HttpTest.class b/blade-kit/bin/src/test/java/blade/test/HttpTest.class new file mode 100644 index 0000000000000000000000000000000000000000..afeae6e9319b1d9318c74f55176b67be8ce981e1 GIT binary patch literal 1693 zcmeHI&u`N(6n@USwaq#@3L8HU-neue+RIK1aX}!EI*?eIggCj5*Loy&W;+x6%aA~V zE8_p)-#|Pkpk`9EMB>UJj_voo&!7GLo`3xM{1pK9;eHze0z205u@lyfPuV#e&tevd zV*J9nbc%*Hv$WeqFg7bjG2>K(bVW!EE4;OhTZ8x&`9u@83d(_e_(S#cXLT2FL9SfT3D*I zqX~0-K^;1Xk15J2JK&CT_{i%RmE4OJWRhy*Xl|66a;7}tOwhmjF2Qp5O3=$BjU|_k z+AI|YH>IpI8F$*y;)sTOR9c#;NSsK80#DF_eU`hz{C~%yuv-)2tJ0&v1!@4P5kMe3(wX7HQxVwka9^kM za@U5tmx^@}Q3Aa~X)V@|DV7NfJAhRi9|3>>d#kX9Z99JyRI3|kcp>p4S!*Z^+j?QOV+{}%e)`3;lF7y1AI literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/test/java/blade/test/JSONTest.class b/blade-kit/bin/src/test/java/blade/test/JSONTest.class new file mode 100644 index 0000000000000000000000000000000000000000..b100c3dbaedfdeb3fba473567c78c4fe544a7625 GIT binary patch literal 3874 zcmeHK%}*3D6n|Y7_QORG1wRi3E{liVizhKA#%L55IIxfyPu-a=Tb!9r+76Mce~~v6 zP4w;`Wqj>GSY=pxm=F>m5i>$2G*xmC@mN2l%|?I3X~=_!DFme~_{jD-U2!ILtcfc$ zlw8w98X7YbjHp2d{wYOs#u;!&4&JeLbjH|o4I)mZGSm?>BO)5G#EKkndSc;K0Xo|+ zvhT`(-o|Mp0%54mQm!z{i8d+=j8rtwnf4kLnr2DJha$m<4UvL#mPKY9-JzSAHkN`Y z$`TvmT=1C4W@E=Fk?a?EhZ;#4HAgA;1Z}dk3^85?y^P|4UeJzL!9uEr{> z_>e1YO|Z={7Fye)=;%4uWFMX%`6kq1wguC0lfYuTciPi)vFomi^h2$D(_4 z)!@NjFUCC02(&iy_SDDjrC}NH>4+~;fC|p0VFt&Vdznt*450ZP>hBktU!nEWVdikO x7{K2=j;$O8w_pKR4Y&<=@Qao380DTySS*k*?<7Yx15FMu>n_U7ag%&7ZCa07`a^XY~7gQ>wEtN>9gg7}~H*wjuSGG5z|A{*i zNO0#zA!fZnS)`~GIB?xL(6&W4keC8FBL zdOAjb08Ikx{xD@~Iy{`52<`~9;=}#@y_W>qF-A^>*+t)Dsib>CV6DG%M4mE(CuvBSBGv@e=I!qAna->*Kz@PNtgObOfmR?nmS+0$v-cLDGCEP^NAMB#= zd6uV=OGj;y3xjNxb*A7>8(Q5*e}_s-3zdjtsj%`fo}kT&)YYR0^q{b=Ji#c+R7tf0 zu0cj&b)hSmP^T%Q?lc!?1V!P<8L6g!nt!e$za2C>wN7L!IGyn)^&*YMK%#;%&>(CY{Z(g^oSW*?ibFcn@LNc7yoMXaH5(SlZwDr z|IMnBZMZ?m{2XKSzabVnQ=6Z^Y$yWJNEe2SXR>_h&O$D|!US-;6i6?N0o?sbKdYy} zgac_UPU#qj*}{E5(L`A$uniZWg;oRY0NS{QUar^B0*F3A^m?Q70WN>>F;{SH`4en5 rv^!N4T!m}63tw_H*V$)zWXxS%3cB=pcw32}0~ZsM|QuWWDBJ_=8Q z1QOhN1>OZQ_BKiisemGJ;;>%Z^Ude^|MKm_Cji)i2N6^VY+A#+PFUAHVH4IJrYsTV zxzA)eKtTjm0&78sI_88lMBEiL1u| uervckN)+6H7M|*G6K>&+XLy9XGlumA3~^wnAhrUx!+Hnqn1L{_R98F)|mEErIpNLJIqYK)JnpNTBjeMZ5}i0?jG*xz5z~-KM>*v5)WZt~dY1~# z?k8z1LSd=NQm!#j(pa5^R%x1ty}e6?p_z>Mk&t-lBb4BtWwD(_cj!T8tdk&$GU=j} z6VFfv^*qT1o=~eOqjr+=WkC~Tc~Zc1s{ax%RTStIT$oES-}Y0j*~AnZp0AbrbPjWW zSL_K)$=Mjp#(G~`K5~gaQ3=jzVD$^lGVTC^FHn2i3O+&Oo5wV9br`^B1J_25f~(NN kQys3sb^PKO9w6_OVY7gt;TcMZEx`@H-h?~&uAttnUqwp1>Hq)$ literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/test/java/blade/test/TaskTest.class b/blade-kit/bin/src/test/java/blade/test/TaskTest.class new file mode 100644 index 0000000000000000000000000000000000000000..37b8fa0ab479747a1dcd86efef8e0ee35374ab5d GIT binary patch literal 2006 zcmeHIO>Yx15FICJlWbE`0xh2hx4onsk_#t_xbPt%QX-LUCB(_`x{2Fedu4kg`b+pJ zNFc$TABC9RO_fDjkqB|ffx~+3o#*E_v*Vc`KfinffXDE#4iy6X*6_X)*7YygjP=JM z3q-#5nZ5MUP=^|Uoy;0CHR%t>7lJzin@^>Z?iqn<_vnm3?YRy_9hwB%3+zi{v}wQ= zseU?DMpzxrL_oQYVi__gwW6`n<4{EQ3H6%(RM0^1kQoHUj9;>epa+?xUMlf`23lCE zw4)Jod`cZ|5FcZdQ`~?aW$<3AqgU9TpCF@H8%Hx^;$%oUQz_+G&})T%2h2_?WqTdP zq2$t0o5aGP|H?X(aHkE;quD*8($Yi);#?~9utV=D3qD-aE=fnj{ zuQ_r?s!53w>NI84UBv=D#NYb{C6#&qE>Vi%Zz(YrDTXs)j0~2+MpxE}sDx`>M94^- zVk(y?%)Om4BhzrKiQX5?EepB7vP&K`V7mnyaD%{Zcd)p+c@iC`SGzsHbbFgbV`2O> z4g@*_%~^OhkIVdH%}u2xa5z|6QjW1)L`*6Id)*IZXEtDuRE8^*jQ^=Vuc?Kb{ipl3 za$c-QefX!TPQV-K#BlLSra8QQ-Qco5QHT4#b-6sT2((V5wOCDkESeVf0oxsRPk;)} zHeeISde%*=I0Nv$LgRhM`wXq`8K#Y6iUE9faBSr$xCtFxHQ^TA#xE(uBjjB$?3OTW VWegR>R^U!H-h~JFuHn9WzW^zHgC76@ literal 0 HcmV?d00001 diff --git a/blade-kit/bin/src/test/java/blade/test/User.class b/blade-kit/bin/src/test/java/blade/test/User.class new file mode 100644 index 0000000000000000000000000000000000000000..d2b0b70925c60f873fed32f2cbc7713e257b5c07 GIT binary patch literal 1744 zcmcgsU2oGc6us_BKSE%mY%tiyyz$inYF~I_2x&qfZR$3Ob(45>6VrN2?8tU1_B;47 zNFc#GKMHZ3thCdjv4;soitYHG<8x2$^{?OGegMErcu|ECffb{Jj^)O7j@XEG`Vk9x zzCJKqSD{Q`F58Ki9CY^jM?A0u%96#LK%+a^+P7NB!3KdDHoz^iO`!5xNMYaLr)KLA zL2p&at8jzB>;(2sYo%*2OG^HM)ZD0O#6udWI1v%ELP?rv)sJ{=UQw^!8*&=*AYvMW z5*8feS#&)U-F8W=(@=3krLr_;HW*Ti0RA~a(bE9TISX$)9qlQ&SI^U+0h5lT&*@)H zR#8UnNy5GQR-8m45SE%W;TqLSV|5x>rD^U^vqgoWsSNoiA$i!QJE^fwNCt~esE{Ld z%qhb|hG!WrDdAE&uP$hB#I+V7|A#SGcAy77-14Cg4FU_z^JV7hX|{{r?xt~{>mI`r zarLMI79BDz-1_um*$#yvu-d(_(y?%>18#S-x}I;g&L3HW`vjs(6zP?jfRfBuQU%3r zy2ip@+OEMWfwhaJV7p)kB0fWvo7>K^npL?v0!trKX+_Mp!m~5C);MKbR1cfjz#5>L zcoUZJxdxSNR)rdl72K(VhwtmzO*w-z0Pj2a9~(En!rad+_V#Hc;O;!m{X7a5;0~?` z+=WGapJ%vNz~C1$EJ0(6p@gith9ZW!LWX5nnPQk^@t{D%d?5qPd>Uur{K_>HF)S7` mtfLPlc!)^n>mwY;Y!f|?3-l}(u$AB`;!Dtk=Qx&;uk{DtFu$?@ literal 0 HcmV?d00001 From 7d1fd4d0b6fb486d1f86e06435d5ed89d15cc58a Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 10:51:37 +0800 Subject: [PATCH 197/545] add config route --- blade-core/src/main/java/com/blade/Blade.java | 35 +++++++++++++- .../main/java/com/blade/IocApplication.java | 3 -- .../loader/AbstractFileRoutesLoader.java | 1 - .../blade/loader/ClassPathRoutesLoader.java | 47 +++++++++++++++++++ .../src/main/java/com/blade/route/Route.java | 12 +---- .../src/main/java/com/blade/route/Router.java | 33 +++++++++++-- 6 files changed, 111 insertions(+), 20 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/loader/ClassPathRoutesLoader.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 7aca1efbc..0e7b29bca 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -17,18 +17,23 @@ import java.io.IOException; import java.io.InputStream; +import java.text.ParseException; +import java.util.List; import java.util.Map; import com.blade.http.HttpMethod; import com.blade.ioc.Container; import com.blade.ioc.SampleContainer; +import com.blade.loader.ClassPathRoutesLoader; import com.blade.loader.Config; import com.blade.loader.Configurator; import com.blade.plugin.Plugin; import com.blade.render.JspRender; import com.blade.render.Render; +import com.blade.route.Route; import com.blade.route.RouteHandler; import com.blade.route.Router; +import com.blade.route.RoutesException; import com.blade.server.Server; import blade.kit.IOKit; @@ -72,6 +77,9 @@ public void init() { */ private Container container = SampleContainer.single(); + /** + * 默认JSP渲染 + */ private Render render = new JspRender(); /** @@ -225,6 +233,14 @@ public Blade route(String path, Object target, String method){ return this; } + public Blade addRoute(String path, Object target, String method){ + return route(path, target, method); + } + + public Blade addRoute(String path, Object target, String method, HttpMethod httpMethod){ + return route(path, target, method, httpMethod); + } + /** * 注册一个函数式的路由
*

@@ -251,6 +267,11 @@ public Blade route(String path, Class clazz, String method, HttpMethod httpMe return this; } + public Blade route(String path, Object target, String method, HttpMethod httpMethod){ + router.route(path, target, method, httpMethod); + return this; + } + /** * get请求 * @param path @@ -641,8 +662,18 @@ public T plugin(Class pluginClazz){ return (T) object; } - public Blade routeConf(String conf) { - + public Blade routeConf(String basePackage, String conf) { + try { + InputStream ins = Blade.class.getResourceAsStream("/" + conf); + ClassPathRoutesLoader routesLoader = new ClassPathRoutesLoader(ins); + routesLoader.setBasePackage(basePackage); + List routes = routesLoader.load(); + router.addRoutes(routes); + } catch (RoutesException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } return this; } } diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index dd1b1e6e1..f1c1bc611 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -24,7 +24,6 @@ import com.blade.plugin.Plugin; import blade.kit.CollectionKit; -import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; @@ -39,8 +38,6 @@ */ public final class IocApplication { - private static final Logger LOGGER = Logger.getLogger(IocApplication.class); - /** * IOC容器,单例获取默认的容器实现 */ diff --git a/blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java b/blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java index 8cb60ecc9..2e243d750 100644 --- a/blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java +++ b/blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java @@ -162,7 +162,6 @@ private Route buildRoute(String httpMethod, String path, String controllerName, private Method getMethod(Object controller, String methodName) throws RoutesException { try { - // try to retrieve the method and check if an exception is thrown return controller.getClass().getMethod(methodName, Request.class, Response.class); } catch (Exception e) { throw new RoutesException(e); diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathRoutesLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathRoutesLoader.java new file mode 100644 index 000000000..f5393533a --- /dev/null +++ b/blade-core/src/main/java/com/blade/loader/ClassPathRoutesLoader.java @@ -0,0 +1,47 @@ +package com.blade.loader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +public class ClassPathRoutesLoader extends AbstractFileRoutesLoader { + + private File file; + + private InputStream inputStream; + + public ClassPathRoutesLoader() { + } + + public ClassPathRoutesLoader(String filePath) { + this(new File(filePath)); + } + + public ClassPathRoutesLoader(File file) { + this.file = file; + } + + public ClassPathRoutesLoader(InputStream inputStream) { + this.inputStream = inputStream; + } + + @Override + protected InputStream getInputStream() throws Exception { + if(null != this.inputStream){ + return this.inputStream; + } + return new FileInputStream(file); + } + + protected void setInputStream(InputStream inputStream) { + this.inputStream = inputStream; + } + + public void setFile(File file) { + this.file = file; + } + + public void setFilePath(String filePath) { + this.file = new File(filePath); + } +} diff --git a/blade-core/src/main/java/com/blade/route/Route.java b/blade-core/src/main/java/com/blade/route/Route.java index 608f94125..1f58e9202 100644 --- a/blade-core/src/main/java/com/blade/route/Route.java +++ b/blade-core/src/main/java/com/blade/route/Route.java @@ -78,11 +78,6 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; Route other = (Route) obj; - if (action == null) { - if (other.action != null) - return false; - } else if (!action.equals(other.action)) - return false; if (httpMethod != other.httpMethod) return false; if (path == null) { @@ -90,17 +85,12 @@ public boolean equals(Object obj) { return false; } else if (!path.equals(other.path)) return false; - if (target == null) { - if (other.target != null) - return false; - } else if (!target.equals(other.target)) - return false; return true; } @Override public String toString() { - return "Route [httpMethod=" + httpMethod + ", path=" + path + ", target=" + target + ", action=" + action + "]"; + return "[ " + httpMethod + " --> " + path + " ]"; } } diff --git a/blade-core/src/main/java/com/blade/route/Router.java b/blade-core/src/main/java/com/blade/route/Router.java index 42e472cbc..702ee88ff 100644 --- a/blade-core/src/main/java/com/blade/route/Router.java +++ b/blade-core/src/main/java/com/blade/route/Router.java @@ -59,12 +59,23 @@ public void addRoute(Route route) { this.routes.add(route); } + public void addRoutes(List routes) { + for(Route route : routes){ + if(this.routes.contains(route)){ + LOGGER.warn("\tRoute "+ route +" has exist"); + continue; + } + this.routes.add(route); + LOGGER.debug("Add Route:" + route); + } + } + public List getInterceptors() { return interceptors; } - - public void setInterceptors(List interceptors) { - this.interceptors = interceptors; + + public void addInterceptors(List interceptors) { + this.interceptors.addAll(interceptors); } public void addRoute(HttpMethod httpMethod, String path, Object controller, String methodName) throws NoSuchMethodException { @@ -80,6 +91,10 @@ public void addRoute(HttpMethod httpMethod, String path, Object controller, Meth method.setAccessible(true); Route route = new Route(httpMethod, path, controller, method); + if(this.routes.contains(route)){ + LOGGER.warn("\tRoute "+ route +" has exist"); + } + if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ interceptors.add(route); LOGGER.debug("Add Interceptor:" + route); @@ -156,4 +171,16 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt } } + public void route(String path, Object target, String methodName, HttpMethod httpMethod) { + try { + Class clazz = target.getClass(); + container.registBean(target); + Method method = clazz.getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, target, method); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + } } From a8fdf703db3a6ff476eaa967b24160ff766dd61b Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 11:15:39 +0800 Subject: [PATCH 198/545] add building route --- blade-core/src/main/java/com/blade/Blade.java | 5 +- .../src/main/java/com/blade/CoreFilter.java | 22 +- .../com/blade/route/RouteMatcherBuilder.java | 351 ++++++++++++++++++ .../src/main/java/com/blade/route/Router.java | 21 +- 4 files changed, 379 insertions(+), 20 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 0e7b29bca..513fa3d93 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -82,6 +82,8 @@ public void init() { */ private Render render = new JspRender(); + private Router router = new Router(); + /** * 默认启动端口 */ @@ -89,7 +91,6 @@ public void init() { private int port = DEFAULT_PORT; - private Router router = new Router(); private Blade() { } @@ -109,7 +110,7 @@ public Server createServer(int port){ public Router router() { return router; } - + /** *

 	 * 手动注册一个对象到ioc容器中
diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java
index eb31fe8e4..398787033 100644
--- a/blade-core/src/main/java/com/blade/CoreFilter.java
+++ b/blade-core/src/main/java/com/blade/CoreFilter.java
@@ -27,9 +27,12 @@
 import javax.servlet.http.HttpServletResponse;
 
 import com.blade.context.BladeWebContext;
+import com.blade.route.RouteMatcherBuilder;
 
+import blade.kit.StringKit;
 import blade.kit.TaskKit;
 import blade.kit.log.Logger;
+og.Logger;
 
 /**
  * blade核心过滤器,mvc总线
@@ -49,7 +52,7 @@ public class CoreFilter implements Filter {
     
     private Blade blade;
     
-    private ActionHandler filterHandler;
+    private ActionHandler actionHandler;
     
     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
@@ -60,25 +63,24 @@ public void init(FilterConfig filterConfig) throws ServletException {
 			if(!blade.isInit){
 				
 				blade.webRoot(filterConfig.getServletContext().getRealPath("/"));
-				
 				Bootstrap bootstrap = blade.bootstrap();
-				if(null == bootstrap){
+				String bootStrapClassName = filterConfig.getInitParameter(BOOSTRAP_CLASS);
+				if(StringKit.isNotBlank(bootStrapClassName)){
 					bootstrap = getBootstrap(filterConfig.getInitParameter(BOOSTRAP_CLASS));
+					bootstrap.init();
+					blade.app(bootstrap);
 				}
 				
-				bootstrap.init();
-				blade.app(bootstrap);
-			    
 			    // 构建路由
-//			    RouteMatcherBuilder.building(blade);
-			    
+				new RouteMatcherBuilder(blade).building();
+				
 			    IocApplication.init(blade);
 			    
 			    bootstrap.contextInitialized();
 			    
 			    blade.setInit(true);
 			    
-			    filterHandler = new ActionHandler(blade);
+			    actionHandler = new ActionHandler(blade);
 			    LOGGER.info("blade init complete!");
 			}
 		} catch (Exception e) {
@@ -124,7 +126,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
         /**
          * 是否被RequestHandler执行
          */
-        boolean isHandler = filterHandler.handle(httpRequest, httpResponse);
+        boolean isHandler = actionHandler.handle(httpRequest, httpResponse);
         if(!isHandler){
         	chain.doFilter(httpRequest, httpResponse);
         }
diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java
new file mode 100644
index 000000000..4370979ef
--- /dev/null
+++ b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java
@@ -0,0 +1,351 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route;
+
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import com.blade.Blade;
+import com.blade.annotation.After;
+import com.blade.annotation.Before;
+import com.blade.annotation.Interceptor;
+import com.blade.annotation.Path;
+import com.blade.annotation.Route;
+import com.blade.http.HttpMethod;
+import com.blade.ioc.Container;
+import com.blade.ioc.SampleContainer;
+
+import blade.exception.BladeException;
+import blade.kit.ReflectKit;
+import blade.kit.StringKit;
+import blade.kit.resource.ClassPathClassReader;
+import blade.kit.resource.ClassReader;
+
+/**
+ * 路由构造器
+ *
+ * @author	biezhi
+ * @since	1.0
+ */
+public class RouteMatcherBuilder {
+    
+    /**
+	 * 默认路由后缀包,用户扫描路由所在位置,默认为route,用户可自定义
+	 */
+    private String PACKAGE_ROUTE = "route";
+	
+	/**
+	 * 默认拦截器后缀包,用户扫描拦截器所在位置,默认为interceptor,用户可自定义
+	 */
+    private String PACKAGE_INTERCEPTOR = "interceptor";
+	
+    /**
+     * 类读取器,用于在指定规则中扫描类
+     */
+    private ClassReader classReader = new ClassPathClassReader();
+    
+    /**
+     * IOC容器,存储路由到ioc中
+     */
+    private Container container = SampleContainer.single();
+    
+    private Blade blade;
+    
+    private Router router;
+    
+    public RouteMatcherBuilder(Blade blade) {
+    	this.blade = blade;
+    	this.router = blade.router();
+    }
+    
+    /**
+     * 开始构建路由
+     * 
+     * @return	返回构建路由后的构造器
+     */
+    public void building() {
+        String basePackage = blade.basePackage();
+        
+        if(StringKit.isNotBlank(basePackage)){
+        	
+        	// 处理如:com.xxx.* 表示递归扫描包
+        	String suffix = basePackage.endsWith(".*") ? ".*" : "";
+        	basePackage = basePackage.endsWith(".*") ? basePackage.substring(0, basePackage.length() - 2) : basePackage;
+        	
+			String routePackage = basePackage + "." + PACKAGE_ROUTE + suffix;
+			String interceptorPackage = basePackage + "." + PACKAGE_INTERCEPTOR + suffix;
+			
+        	buildRoute(routePackage);
+        	
+        	buildInterceptor(interceptorPackage);
+        	
+        } else {
+        	
+        	// 路由
+	    	String[] routePackages = blade.routes();
+	    	if(null != routePackages && routePackages.length > 0){
+	    		buildRoute(routePackages);
+	    	}
+	    	
+			// 拦截器
+	    	String interceptorPackage = blade.interceptor();
+	    	if(StringKit.isNotBlank(interceptorPackage)){
+	    		buildInterceptor(interceptorPackage);
+	    	}
+		}
+    }
+    
+    /**
+     * Handler路由构建
+     */
+    public void buildHandler(String path, RouteHandler handler, HttpMethod httpMethod){
+    	if(StringKit.isNotBlank(path) && null != handler){
+    		this.router.route(path, handler, httpMethod);
+    	} else {
+			 throw new BladeException("an unqualified configuration");
+		}
+    }
+    
+    /**
+     * 函数式构建拦截器
+     */
+    public void buildInterceptor(String path, RouteHandler handler, HttpMethod httpMethod){
+    	if(StringKit.isNotBlank(path) && null != handler){
+    		this.router.route(path, handler, httpMethod);
+    	} else {
+			 throw new BladeException("an unqualified configuration");
+		}
+    }
+    
+    /**
+     * 函数式拦截器构建
+     */
+    public void buildInterceptor(String path, Class clazz, String methodName){
+    	if(StringKit.isNotBlank(path) && null != clazz && StringKit.isNotBlank(methodName)){
+
+    		// 字符串上写请求   hello
+    		if(methodName.indexOf(":") != -1){
+    			String[] methodArr = StringKit.split(methodName, ":");
+    			methodName = methodArr[1];
+    		}
+    		
+    		// 查找
+    		Object target = container.getBean(clazz, null);
+    		if(null == target){
+    			container.registBean(clazz);
+    		}
+    		
+    		Method execMethod = ReflectKit.getMethodByName(clazz, methodName);
+    		this.router.route(path, clazz, execMethod, HttpMethod.BEFORE);
+    	} else {
+			 throw new BladeException("an unqualified configuration");
+		}
+    }
+    
+    /**
+     * 构建拦截器
+     * 
+     * @param interceptorPackages	要添加的拦截器包
+     */
+    private void buildInterceptor(String... interceptorPackages){
+    	// 扫描所有的Interceptor
+		Set> classes = null;
+    	// 拦截器
+		for(String packageName : interceptorPackages){
+			
+			boolean recursive = false;
+			
+			if (packageName.endsWith(".*")) {
+				packageName = packageName.substring(0, packageName.length() - 2);
+				recursive = true;
+			}
+			
+    		// 扫描所有的Interceptor
+    		classes = classReader.getClassByAnnotation(packageName, Interceptor.class, recursive);
+    		
+    		if(null != classes && classes.size() > 0){
+    			for(Class interceptorClazz : classes){
+    				parseInterceptor(interceptorClazz);
+    			}
+    		}
+    	}
+    }
+    
+    /**
+     * 构建路由
+     * 
+     * @param routePackages		要添加的路由包
+     */
+    private void buildRoute(String... routePackages){
+    	Set> classes = null;
+    	// 路由
+		for(String packageName : routePackages){
+			
+			boolean recursive = false;
+			
+			if (packageName.endsWith(".*")) {
+				packageName = packageName.substring(0, packageName.length() - 2);
+				recursive = true;
+			}
+			
+    		// 扫描所有的Controoler
+    		classes = classReader.getClassByAnnotation(packageName, Path.class, recursive);
+    		
+    		if(null != classes && classes.size() > 0){
+    			for(Class pathClazz : classes){
+    				parseRouter(pathClazz);
+    			}
+    		}
+    	}
+    	
+    }
+    
+    /**
+     * 解析拦截器
+     * 
+     * @param interceptor		要解析的拦截器class
+     */
+    private void parseInterceptor(final Class interceptor){
+    	
+    	Method[] methods = interceptor.getMethods();
+    	if(null == methods || methods.length == 0){
+    		return;
+    	}
+    	
+    	container.registBean(interceptor);
+    	
+    	for (Method method : methods) {
+			
+			Before before = method.getAnnotation(Before.class);
+			After after = method.getAnnotation(After.class);
+			
+			if (null != before) {
+				
+				String suffix = before.suffix();
+				
+				String path = getRoutePath(before.value(), "", suffix);
+				
+				buildInterceptor(path, interceptor, method, HttpMethod.BEFORE);
+				
+				String[] paths = before.values();
+				if(null != paths && paths.length > 0){
+					for(String value : paths){
+						String pathV = getRoutePath(value, "", suffix);
+						buildInterceptor(pathV, interceptor, method, HttpMethod.BEFORE);
+					}
+				}
+			}
+			
+			if (null != after) {
+				
+				String suffix = after.suffix();
+				
+				String path = getRoutePath(after.value(), "", suffix);
+				
+				buildInterceptor(path, interceptor, method, HttpMethod.AFTER);
+				
+				String[] paths = after.values();
+				if(null != paths && paths.length > 0){
+					for(String value : paths){
+						String pathV = getRoutePath(value, "", suffix);
+						buildInterceptor(pathV, interceptor, method, HttpMethod.AFTER);
+					}
+				}
+			}
+		}
+    }
+    
+    /**
+     * 解析一个控制器中的所有路由
+     * 
+     * @param controller		要解析的路由class
+     */
+    private void parseRouter(final Class router){
+    	
+    	Method[] methods = router.getMethods();
+    	if(null == methods || methods.length == 0){
+    		return;
+    	}
+    	
+    	container.registBean(router);
+    	
+		final String nameSpace = router.getAnnotation(Path.class).value();
+		
+		final String suffix = router.getAnnotation(Path.class).suffix();
+		
+		for (Method method : methods) {
+			
+			Route mapping = method.getAnnotation(Route.class);
+			
+			//route方法
+			if (null != mapping) {
+				
+				////构建路由
+				String path = getRoutePath(mapping.value(), nameSpace, suffix);
+				
+				HttpMethod methodType = mapping.method();
+				
+				buildRoute(router, method, path, methodType);
+				
+				// 构建多个路由
+				String[] paths = mapping.values();
+				if(null != paths && paths.length > 0){
+					for(String value : paths){
+						String pathV = getRoutePath(value, nameSpace, suffix);
+						buildRoute(router, method, pathV, methodType);
+					}
+				}
+			}
+		}
+    }
+    
+    private String getRoutePath(String value, String nameSpace, String suffix){
+    	String path = value.startsWith("/") ? value : "/" + value;
+		path = nameSpace + path;
+		path = path.replaceAll("[/]+", "/");
+		
+		path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
+		
+		path = path + suffix;
+		
+		return path;
+    }
+    
+    /**
+     * 构建一个路由
+     * 
+     * @param target		路由目标执行的class
+     * @param execMethod	路由执行方法
+     * @param path			路由url
+     * @param method		路由http方法
+     */
+    private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){
+    	this.router.route(path, clazz, execMethod, HttpMethod.BEFORE);
+    }
+    
+    /**
+     * 构建一个路由
+     * 
+     * @param path			路由url
+     * @param target		路由目标执行的class
+     * @param execMethod	路由执行方法
+     * @param method		路由http方法
+     */
+    private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){
+    	this.router.route(path, clazz, execMethod, method);
+    }
+    
+}
\ No newline at end of file
diff --git a/blade-core/src/main/java/com/blade/route/Router.java b/blade-core/src/main/java/com/blade/route/Router.java
index 702ee88ff..af2c6f60b 100644
--- a/blade-core/src/main/java/com/blade/route/Router.java
+++ b/blade-core/src/main/java/com/blade/route/Router.java
@@ -105,14 +105,6 @@ public void addRoute(HttpMethod httpMethod, String path, Object controller, Meth
 		
 	}
 	
-	public void delete(String path, RouteHandler handler) {
-		try {
-			addRoute(HttpMethod.DELETE, path, handler, METHOD_NAME);
-		} catch (NoSuchMethodException e) {
-			throw new RuntimeException(e);
-		}
-	}
-	
 	public void route(String path, RouteHandler handler, HttpMethod httpMethod) {
 		try {
 			addRoute(httpMethod, path, handler, METHOD_NAME);
@@ -171,6 +163,19 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt
 		}
 	}
 	
+	public void route(String path, Class clazz, Method method, HttpMethod httpMethod) {
+		try {
+			Object controller = container.getBean(clazz, Scope.SINGLE);
+			if(null == controller){
+				controller = ReflectKit.newInstance(clazz);
+				container.registBean(controller);
+			}
+			addRoute(httpMethod, path, controller, method);
+		} catch (SecurityException e) {
+			e.printStackTrace();
+		}
+	}
+	
 	public void route(String path, Object target, String methodName, HttpMethod httpMethod) {
 		try {
 			Class clazz = target.getClass();

From 31ffaa05e294d6e413fb8d14d17c5dcb952a09d5 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Wed, 28 Oct 2015 11:39:29 +0800
Subject: [PATCH 199/545] fix ioc repetition object bug

---
 .../main/java/com/blade/ActionHandler.java    |  15 --
 .../src/main/java/com/blade/CoreFilter.java   |   1 -
 .../main/java/com/blade/IocApplication.java   |   9 +
 .../java/com/blade/ioc/SampleContainer.java   |   4 +-
 .../com/blade/route/RouteMatcherBuilder.java  |  21 ++-
 .../src/main/java/com/blade/route/Router.java |  13 +-
 pom.xml                                       | 156 +++++++++---------
 7 files changed, 108 insertions(+), 111 deletions(-)

diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java
index c9e3f01ad..27e5e1861 100644
--- a/blade-core/src/main/java/com/blade/ActionHandler.java
+++ b/blade-core/src/main/java/com/blade/ActionHandler.java
@@ -250,21 +250,6 @@ private Object executeMethod(Object object, Method method, Request request, Resp
 		}
 	}
 	
-	/**
-	 * 渲染视图
-	 * 
-	 * @param response
-	 * @param result
-	 * @return
-	 */
-	/*private void render(Response response, Object result){
-		if(result instanceof String){
-			response.render(result.toString());
-		} else if(result instanceof ModelAndView){
-			response.render( (ModelAndView) result );
-		}
-	}*/
-	
 	/**
 	 * 要过滤掉的目录
 	 * @param uri
diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java
index 398787033..0dd10651f 100644
--- a/blade-core/src/main/java/com/blade/CoreFilter.java
+++ b/blade-core/src/main/java/com/blade/CoreFilter.java
@@ -32,7 +32,6 @@
 import blade.kit.StringKit;
 import blade.kit.TaskKit;
 import blade.kit.log.Logger;
-og.Logger;
 
 /**
  * blade核心过滤器,mvc总线
diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java
index f1c1bc611..3372b0cf0 100644
--- a/blade-core/src/main/java/com/blade/IocApplication.java
+++ b/blade-core/src/main/java/com/blade/IocApplication.java
@@ -15,6 +15,7 @@
  */
 package com.blade;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
@@ -24,6 +25,7 @@
 import com.blade.plugin.Plugin;
 
 import blade.kit.CollectionKit;
+import blade.kit.log.Logger;
 import blade.kit.resource.ClassPathClassReader;
 import blade.kit.resource.ClassReader;
 
@@ -38,6 +40,8 @@
  */
 public final class IocApplication {
 
+	private static final Logger LOGGER = Logger.getLogger(IocApplication.class);
+	
 	/**
 	 * IOC容器,单例获取默认的容器实现
 	 */
@@ -64,6 +68,11 @@ public static void init(Blade blade){
 		// 初始化注入
 		container.initWired();
 		
+		Collection beans = container.getBeans();
+		for(Object object : beans){
+			LOGGER.info("Add Object:" + object.getClass() + "=" + object);
+		}
+		
 	}
 	
 	/**
diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java
index 534ecf7bf..30bdb0712 100644
--- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java
+++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java
@@ -170,7 +170,6 @@ public Object registBean(Class clazz) {
 		    if(null != clazz.getDeclaredAnnotations()){
 		    	putAnnotationMap(clazz, object);
 		    }
-		    LOGGER.info("register object:" + name + "=" + object);
 		}
 		return object;
 	}
@@ -182,7 +181,7 @@ public Object registBean(Class clazz) {
      * @param object		要进入IOC容器的bean对象
      */
     private void put(String name, Object object){
-    	if(null == BEAN_CONTAINER.get(name)){
+    	if(!BEAN_CONTAINER.containsValue(object)){
     		BEAN_CONTAINER.put(name, object);
     	}
     }
@@ -299,7 +298,6 @@ public void registBean(Set> classes) {
 	public Object registBean(Object object) {
 		String name = object.getClass().getName();
 		put(name, object);
-	    LOGGER.info("register object:" + name + "=" + object);
 		return object;
 	}
 
diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java
index 4370979ef..d47c53721 100644
--- a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java
+++ b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java
@@ -25,11 +25,11 @@
 import com.blade.annotation.Path;
 import com.blade.annotation.Route;
 import com.blade.http.HttpMethod;
+import com.blade.http.Request;
+import com.blade.http.Response;
 import com.blade.ioc.Container;
 import com.blade.ioc.SampleContainer;
 
-import blade.exception.BladeException;
-import blade.kit.ReflectKit;
 import blade.kit.StringKit;
 import blade.kit.resource.ClassPathClassReader;
 import blade.kit.resource.ClassReader;
@@ -115,7 +115,7 @@ public void buildHandler(String path, RouteHandler handler, HttpMethod httpMetho
     	if(StringKit.isNotBlank(path) && null != handler){
     		this.router.route(path, handler, httpMethod);
     	} else {
-			 throw new BladeException("an unqualified configuration");
+			 throw new RoutesException("an unqualified configuration");
 		}
     }
     
@@ -126,7 +126,7 @@ public void buildInterceptor(String path, RouteHandler handler, HttpMethod httpM
     	if(StringKit.isNotBlank(path) && null != handler){
     		this.router.route(path, handler, httpMethod);
     	} else {
-			 throw new BladeException("an unqualified configuration");
+			 throw new RoutesException("an unqualified configuration");
 		}
     }
     
@@ -147,11 +147,16 @@ public void buildInterceptor(String path, Class clazz, String methodName){
     		if(null == target){
     			container.registBean(clazz);
     		}
-    		
-    		Method execMethod = ReflectKit.getMethodByName(clazz, methodName);
-    		this.router.route(path, clazz, execMethod, HttpMethod.BEFORE);
+			try {
+				Method method = clazz.getMethod(methodName, Request.class, Response.class);
+				this.router.route(path, clazz, method, HttpMethod.BEFORE);
+			} catch (NoSuchMethodException e) {
+				throw new RoutesException(e);
+			} catch (SecurityException e) {
+				throw new RoutesException(e);
+			}
     	} else {
-			 throw new BladeException("an unqualified configuration");
+			 throw new RoutesException("an unqualified configuration");
 		}
     }
     
diff --git a/blade-core/src/main/java/com/blade/route/Router.java b/blade-core/src/main/java/com/blade/route/Router.java
index af2c6f60b..36d622b22 100644
--- a/blade-core/src/main/java/com/blade/route/Router.java
+++ b/blade-core/src/main/java/com/blade/route/Router.java
@@ -14,6 +14,7 @@
 import com.blade.ioc.Scope;
 
 import blade.kit.ReflectKit;
+import blade.kit.StringKit;
 import blade.kit.log.Logger;
 
 /**
@@ -84,12 +85,7 @@ public void addRoute(HttpMethod httpMethod, String path, Object controller, Stri
 	}
 	
 	public void addRoute(HttpMethod httpMethod, String path, Object controller, Method method) {
-		Class[] paramTypes = method.getParameterTypes();
-		if (paramTypes.length != 2 || !paramTypes[0].equals(Request.class) || !paramTypes[1].equals(Response.class)) {
-			throw new RoutesException("Expecting two params of type com.blade.servlet.Request and com.blade.servlet.Response respectively");
-		}
-		method.setAccessible(true);
-		
+//		method.setAccessible(true);
 		Route route = new Route(httpMethod, path, controller, method);
 		if(this.routes.contains(route)){
 			LOGGER.warn("\tRoute "+ route +" has exist");
@@ -132,11 +128,16 @@ public void route(String path, Object target, String methodName) {
 
 	public void route(String path, Class clazz, String methodName) {
 		try {
+			if(methodName.indexOf(":") != -1){
+    			String[] methodArr = StringKit.split(methodName, ":");
+    			methodName = methodArr[1];
+    		}
 			Object controller = container.getBean(clazz, Scope.SINGLE);
 			if(null == controller){
 				controller = ReflectKit.newInstance(clazz);
 				container.registBean(controller);
 			}
+			
 			Method method = clazz.getMethod(methodName, Request.class, Response.class);
 			
 			addRoute(HttpMethod.ALL, path, controller, method);
diff --git a/pom.xml b/pom.xml
index e7fea3786..dae248cbd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,79 +1,79 @@
-
-
-	4.0.0
-
-	com.bladejava
-	blade-root
-	1.0
-	pom
-
-	blade-root
-	https://github.com/biezhi/blade
-
-	
-		1.6
-		1.6
-		UTF-8
-		4.11
-		3.0.1
-		1.4.0
-	
-
-	
-		blade-kit
-		blade-core
-		blade-cache
-		blade-jetbrick
-		blade-sql2o
-		blade-velocity
-		blade-beetl
-		blade-redis
-    blade-startup
-  
-		
-	
-		
-			
-				junit
-				junit
-				${junit.version}
-				test
-			
-		
-	
-	
-	
-	 
-	   oss-snapshots
-	   https://oss.sonatype.org/content/repositories/snapshots
-	   
-	     false
-	   
-	   
-	     true
-	   
-	 
-	
-	
-	
-		
-			
-				org.apache.maven.plugin
-				maven-compiler-plugin
-				2.1
-				
-					true
-				
-			
-			
-				org.apache.maven.plugins
-				maven-surefire-plugin
-				2.5
-				
-					true
-				
-			
-		
-	
-
+
+
+	4.0.0
+
+	com.bladejava
+	blade-root
+	1.0
+	pom
+
+	blade-root
+	https://github.com/biezhi/blade
+
+	
+		1.6
+		1.6
+		UTF-8
+		4.11
+		3.0.1
+		1.4.1-alpha
+	
+
+	
+		blade-kit
+		blade-core
+		blade-cache
+		blade-jetbrick
+		blade-sql2o
+		blade-velocity
+		blade-beetl
+		blade-redis
+    blade-startup
+  
+		
+	
+		
+			
+				junit
+				junit
+				${junit.version}
+				test
+			
+		
+	
+	
+	
+	 
+	   oss-snapshots
+	   https://oss.sonatype.org/content/repositories/snapshots
+	   
+	     false
+	   
+	   
+	     true
+	   
+	 
+	
+	
+	
+		
+			
+				org.apache.maven.plugin
+				maven-compiler-plugin
+				2.1
+				
+					true
+				
+			
+			
+				org.apache.maven.plugins
+				maven-surefire-plugin
+				2.5
+				
+					true
+				
+			
+		
+	
+
 
\ No newline at end of file

From e139416e01a9e63dfa5c478ea6861411c53f7c22 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Wed, 28 Oct 2015 13:11:01 +0800
Subject: [PATCH 200/545] fix route repetition bug

---
 .../main/java/com/blade/ActionHandler.java    |  8 +-
 blade-core/src/main/java/com/blade/Blade.java |  4 +-
 .../com/blade/route/RouteMatcherBuilder.java  | 78 +++----------------
 .../src/main/java/com/blade/route/Router.java |  7 +-
 .../com/blade/route/SampleRouteMatcher.java   |  7 +-
 5 files changed, 26 insertions(+), 78 deletions(-)

diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java
index 27e5e1861..3fad2b3bb 100644
--- a/blade-core/src/main/java/com/blade/ActionHandler.java
+++ b/blade-core/src/main/java/com/blade/ActionHandler.java
@@ -190,14 +190,14 @@ private void invokeInterceptor(Request request, Response response, List i
 	 * @return	object
 	 */
 	private void handle(Request request, Response response, Route route){
-		RouteHandler router = (RouteHandler) route.getTarget();
+		Object target = route.getTarget();
 		request.initPathParams(request.path());
 		// 初始化context
 		BladeWebContext.setContext(request, response);
-		if(null != router){
-			router.handle(request, response);
+		if(target instanceof RouteHandler){
+			RouteHandler routeHandler = (RouteHandler)target;
+			routeHandler.handle(request, response);
 		} else {
-			Object target = route.getTarget();
 			// 要执行的路由方法
 			Method actionMethod = route.getAction();
 			// 执行route方法
diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java
index 513fa3d93..79ef41501 100644
--- a/blade-core/src/main/java/com/blade/Blade.java
+++ b/blade-core/src/main/java/com/blade/Blade.java
@@ -556,7 +556,7 @@ public String basePackage(){
 	/**
      * @return	返回路由包数组
      */
-    public String[] routes(){
+    public String[] routePackages(){
     	return config.getRoutePackages();
     }
     
@@ -570,7 +570,7 @@ public String[] iocs(){
     /**
      * @return	返回拦截器包数组,只有一个元素 这里统一用String[]
      */
-    public String interceptor(){
+    public String interceptorPackage(){
     	return config.getInterceptorPackage();
     }
     
diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java
index d47c53721..69e40dbd6 100644
--- a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java
+++ b/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java
@@ -25,8 +25,6 @@
 import com.blade.annotation.Path;
 import com.blade.annotation.Route;
 import com.blade.http.HttpMethod;
-import com.blade.http.Request;
-import com.blade.http.Response;
 import com.blade.ioc.Container;
 import com.blade.ioc.SampleContainer;
 
@@ -89,74 +87,20 @@ public void building() {
 			String interceptorPackage = basePackage + "." + PACKAGE_INTERCEPTOR + suffix;
 			
         	buildRoute(routePackage);
-        	
         	buildInterceptor(interceptorPackage);
         	
         } else {
-        	
         	// 路由
-	    	String[] routePackages = blade.routes();
-	    	if(null != routePackages && routePackages.length > 0){
-	    		buildRoute(routePackages);
-	    	}
-	    	
-			// 拦截器
-	    	String interceptorPackage = blade.interceptor();
-	    	if(StringKit.isNotBlank(interceptorPackage)){
-	    		buildInterceptor(interceptorPackage);
-	    	}
-		}
-    }
-    
-    /**
-     * Handler路由构建
-     */
-    public void buildHandler(String path, RouteHandler handler, HttpMethod httpMethod){
-    	if(StringKit.isNotBlank(path) && null != handler){
-    		this.router.route(path, handler, httpMethod);
-    	} else {
-			 throw new RoutesException("an unqualified configuration");
-		}
-    }
-    
-    /**
-     * 函数式构建拦截器
-     */
-    public void buildInterceptor(String path, RouteHandler handler, HttpMethod httpMethod){
-    	if(StringKit.isNotBlank(path) && null != handler){
-    		this.router.route(path, handler, httpMethod);
-    	} else {
-			 throw new RoutesException("an unqualified configuration");
-		}
-    }
-    
-    /**
-     * 函数式拦截器构建
-     */
-    public void buildInterceptor(String path, Class clazz, String methodName){
-    	if(StringKit.isNotBlank(path) && null != clazz && StringKit.isNotBlank(methodName)){
-
-    		// 字符串上写请求   hello
-    		if(methodName.indexOf(":") != -1){
-    			String[] methodArr = StringKit.split(methodName, ":");
-    			methodName = methodArr[1];
-    		}
-    		
-    		// 查找
-    		Object target = container.getBean(clazz, null);
-    		if(null == target){
-    			container.registBean(clazz);
-    		}
-			try {
-				Method method = clazz.getMethod(methodName, Request.class, Response.class);
-				this.router.route(path, clazz, method, HttpMethod.BEFORE);
-			} catch (NoSuchMethodException e) {
-				throw new RoutesException(e);
-			} catch (SecurityException e) {
-				throw new RoutesException(e);
-			}
-    	} else {
-			 throw new RoutesException("an unqualified configuration");
+        	String[] routePackages = blade.routePackages();
+        	if(null != routePackages && routePackages.length > 0){
+        		buildRoute(routePackages);
+        	}
+        	
+    		// 拦截器
+        	String interceptorPackage = blade.interceptorPackage();
+        	if(StringKit.isNotBlank(interceptorPackage)){
+        		buildInterceptor(interceptorPackage);
+        	}
 		}
     }
     
@@ -338,7 +282,7 @@ private String getRoutePath(String value, String nameSpace, String suffix){
      * @param method		路由http方法
      */
     private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){
-    	this.router.route(path, clazz, execMethod, HttpMethod.BEFORE);
+    	this.router.route(path, clazz, execMethod, method);
     }
     
     /**
diff --git a/blade-core/src/main/java/com/blade/route/Router.java b/blade-core/src/main/java/com/blade/route/Router.java
index 36d622b22..9e82d44cf 100644
--- a/blade-core/src/main/java/com/blade/route/Router.java
+++ b/blade-core/src/main/java/com/blade/route/Router.java
@@ -14,7 +14,6 @@
 import com.blade.ioc.Scope;
 
 import blade.kit.ReflectKit;
-import blade.kit.StringKit;
 import blade.kit.log.Logger;
 
 /**
@@ -128,8 +127,10 @@ public void route(String path, Object target, String methodName) {
 
 	public void route(String path, Class clazz, String methodName) {
 		try {
+			HttpMethod httpMethod = HttpMethod.ALL;
 			if(methodName.indexOf(":") != -1){
-    			String[] methodArr = StringKit.split(methodName, ":");
+    			String[] methodArr = methodName.split(":");
+    			httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase());
     			methodName = methodArr[1];
     		}
 			Object controller = container.getBean(clazz, Scope.SINGLE);
@@ -140,7 +141,7 @@ public void route(String path, Class clazz, String methodName) {
 			
 			Method method = clazz.getMethod(methodName, Request.class, Response.class);
 			
-			addRoute(HttpMethod.ALL, path, controller, method);
+			addRoute(httpMethod, path, controller, method);
 		} catch (NoSuchMethodException e) {
 			e.printStackTrace();
 		} catch (SecurityException e) {
diff --git a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java
index 7f65dca20..07ee5913f 100644
--- a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java
+++ b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java
@@ -30,8 +30,11 @@ public Route getRoute(String httpMethod, String path) {
 		String cleanPath = parsePath(path);
 		List matchRoutes = new ArrayList();
 		for (Route route : this.routes) {
-			if (matchesPath(route.getPath(), cleanPath) && route.getHttpMethod().toString().equalsIgnoreCase(httpMethod)) {
-				matchRoutes.add(route);
+			if (matchesPath(route.getPath(), cleanPath)) {
+				if (route.getHttpMethod() == HttpMethod.ALL
+						|| HttpMethod.valueOf(httpMethod) == route.getHttpMethod()) {
+					matchRoutes.add(route);
+				}
 			}
 		}
 		// 优先匹配原则

From 97e02ac9bc4c2de220888c0c3020291d9b8bdef4 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Wed, 28 Oct 2015 13:19:21 +0800
Subject: [PATCH 201/545] update readme

---
 README.md                                          | 10 +++-------
 README_CN.md                                       | 14 +++++---------
 blade-core/src/main/java/com/blade/CoreFilter.java |  4 ++--
 .../src/main/java/com/blade/route/Route.java       |  2 +-
 ...{RouteMatcherBuilder.java => RouteBuilder.java} |  4 ++--
 5 files changed, 13 insertions(+), 21 deletions(-)
 rename blade-core/src/main/java/com/blade/route/{RouteMatcherBuilder.java => RouteBuilder.java} (95%)

diff --git a/README.md b/README.md
index ecd468f28..a416b8625 100644
--- a/README.md
+++ b/README.md
@@ -32,16 +32,12 @@ If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks!
 To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) and then create a class with a main method like this:
 
 ```java
-public class App extends Bootstrap {
+public class App {
 	
-	@Override
-	public void init() {}
-	
-	public static void main(String[] args) throws Exception {
+	public static void main(String[] args) {
 		Blade blade = Blade.me();
-		blade.get("/").run(request, response) -> {
+		blade.get("/", (request, response) -> {
 			response.html("

Hello blade!

"); - return null; }); blade.app(App.class).listen(9001).start(); } diff --git a/README_CN.md b/README_CN.md index 18c0be38e..2d38f137c 100644 --- a/README_CN.md +++ b/README_CN.md @@ -29,19 +29,15 @@ ## 快速入门 -开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) ,然后创建一个类继承自 `Bootstrap` ,编写 `Main` 函数: +开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) ,然后创建一个类 ,编写 `Main` 函数: ```java -public class App extends Bootstrap { - - @Override - public void init() {} - - public static void main(String[] args) throws Exception { +public class App { + + public static void main(String[] args) { Blade blade = Blade.me(); - blade.get("/").run(request, response) -> { + blade.get("/", (request, response) -> { response.html("

Hello blade!

"); - return null; }); blade.app(App.class).listen(9001).start(); } diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 0dd10651f..2ef2aeecf 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -27,7 +27,7 @@ import javax.servlet.http.HttpServletResponse; import com.blade.context.BladeWebContext; -import com.blade.route.RouteMatcherBuilder; +import com.blade.route.RouteBuilder; import blade.kit.StringKit; import blade.kit.TaskKit; @@ -71,7 +71,7 @@ public void init(FilterConfig filterConfig) throws ServletException { } // 构建路由 - new RouteMatcherBuilder(blade).building(); + new RouteBuilder(blade).building(); IocApplication.init(blade); diff --git a/blade-core/src/main/java/com/blade/route/Route.java b/blade-core/src/main/java/com/blade/route/Route.java index 1f58e9202..14b1f309c 100644 --- a/blade-core/src/main/java/com/blade/route/Route.java +++ b/blade-core/src/main/java/com/blade/route/Route.java @@ -90,7 +90,7 @@ public boolean equals(Object obj) { @Override public String toString() { - return "[ " + httpMethod + " --> " + path + " ]"; + return httpMethod + "\t" + path; } } diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java similarity index 95% rename from blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java rename to blade-core/src/main/java/com/blade/route/RouteBuilder.java index 69e40dbd6..a95d8b72a 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcherBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -38,7 +38,7 @@ * @author biezhi * @since 1.0 */ -public class RouteMatcherBuilder { +public class RouteBuilder { /** * 默认路由后缀包,用户扫描路由所在位置,默认为route,用户可自定义 @@ -64,7 +64,7 @@ public class RouteMatcherBuilder { private Router router; - public RouteMatcherBuilder(Blade blade) { + public RouteBuilder(Blade blade) { this.blade = blade; this.router = blade.router(); } From 59304a7e2efd4028e159aea6107cefdf92d0d6b0 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 14:34:51 +0800 Subject: [PATCH 202/545] fix jetty no servletContext --- blade-core/pom.xml | 2 +- blade-core/src/main/java/com/blade/ActionHandler.java | 10 +++++++--- blade-core/src/main/java/com/blade/CoreFilter.java | 2 +- .../main/java/com/blade/context/BladeWebContext.java | 4 ++-- .../main/java/com/blade/servlet/ServletRequest.java | 2 ++ 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 0d4e70c28..845ddf891 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -34,7 +34,7 @@ javax.servlet javax.servlet-api - 3.0.1 + ${servlet.version} provided diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java index 3fad2b3bb..30271e8e9 100644 --- a/blade-core/src/main/java/com/blade/ActionHandler.java +++ b/blade-core/src/main/java/com/blade/ActionHandler.java @@ -19,6 +19,7 @@ import java.lang.reflect.Method; import java.util.List; +import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -70,9 +71,12 @@ public class ActionHandler { private static final String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + Blade.VERSION +"
"; - public ActionHandler(Blade blade){ + private ServletContext context; + + public ActionHandler(ServletContext context, Blade blade){ this.blade = blade; this.router = blade.router(); + this.context = context; this.sampleRouteMatcher = new SampleRouteMatcher(router); } @@ -112,7 +116,7 @@ public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpRe response = new ServletResponse(httpResponse, blade.render()); // 初始化context - BladeWebContext.setContext(request, response); + BladeWebContext.setContext(context, request, response); Route route = sampleRouteMatcher.getRoute(method, uri); @@ -193,7 +197,7 @@ private void handle(Request request, Response response, Route route){ Object target = route.getTarget(); request.initPathParams(request.path()); // 初始化context - BladeWebContext.setContext(request, response); + BladeWebContext.setContext(context, request, response); if(target instanceof RouteHandler){ RouteHandler routeHandler = (RouteHandler)target; routeHandler.handle(request, response); diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 2ef2aeecf..531e3e9d7 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -79,7 +79,7 @@ public void init(FilterConfig filterConfig) throws ServletException { blade.setInit(true); - actionHandler = new ActionHandler(blade); + actionHandler = new ActionHandler(filterConfig.getServletContext(), blade); LOGGER.info("blade init complete!"); } } catch (Exception e) { diff --git a/blade-core/src/main/java/com/blade/context/BladeWebContext.java b/blade-core/src/main/java/com/blade/context/BladeWebContext.java index 595ecc217..cab37e482 100644 --- a/blade-core/src/main/java/com/blade/context/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/context/BladeWebContext.java @@ -47,10 +47,10 @@ public static BladeWebContext me(){ return BLADE_WEB_CONTEXT.get(); } - public static void setContext(Request request, Response response) { + public static void setContext(ServletContext context, Request request, Response response) { BladeWebContext bladeWebContext = new BladeWebContext(); + bladeWebContext.context = context; bladeWebContext.request = request; - bladeWebContext.context = request.context(); bladeWebContext.response = response; BLADE_WEB_CONTEXT.set(bladeWebContext); } diff --git a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java index 696bf3a83..c0f6f814b 100644 --- a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java @@ -169,6 +169,8 @@ public String servletPath() { @Override public String contextPath() { + System.out.println(request); + System.out.println(request.getServletContext()); return request.getContextPath(); } From 28543867b61404375f22d1d6e6411bff46fa5dd8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 15:09:37 +0800 Subject: [PATCH 203/545] add comment --- .../main/java/com/blade/ActionHandler.java | 51 ++++++++++----- blade-core/src/main/java/com/blade/Blade.java | 40 +++++++++--- .../src/main/java/com/blade/http/Path.java | 65 ++++++++++++++++++- .../java/com/blade/render/ModelAndView.java | 16 +++++ .../com/blade/route/SampleRouteMatcher.java | 3 +- .../com/blade/servlet/ServletRequest.java | 2 - .../com/blade/servlet/ServletResponse.java | 24 ++++++- 7 files changed, 169 insertions(+), 32 deletions(-) diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java index 30271e8e9..cbfee00d2 100644 --- a/blade-core/src/main/java/com/blade/ActionHandler.java +++ b/blade-core/src/main/java/com/blade/ActionHandler.java @@ -25,6 +25,7 @@ import com.blade.context.BladeWebContext; import com.blade.http.HttpStatus; +import com.blade.http.Path; import com.blade.http.Request; import com.blade.http.Response; import com.blade.render.ModelAndView; @@ -36,7 +37,6 @@ import com.blade.servlet.ServletResponse; import blade.exception.BladeException; -import blade.kit.PathKit; import blade.kit.ReflectKit; import blade.kit.StringKit; import blade.kit.base.ThrowableKit; @@ -64,13 +64,18 @@ public class ActionHandler { /** * 服务器500错误时返回的HTML */ - private static final String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + Blade.VERSION +"
"; + /** + * 服务器404错误HTML + */ private static final String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + Blade.VERSION +"
"; + /** + * 全局的ServletContext对象 + */ private ServletContext context; public ActionHandler(ServletContext context, Blade blade){ @@ -81,11 +86,10 @@ public ActionHandler(ServletContext context, Blade blade){ } /** - * handler执行方法 - * - * @param httpRequest HttpServletRequest请求对象 - * @param httpResponse HttpServletResponse响应对象 - * @return 是否拦截到请求 + * 处理请求 + * @param httpRequest + * @param httpResponse + * @return */ public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ @@ -96,7 +100,7 @@ public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpRe String method = httpRequest.getMethod(); // 请求的uri - String uri = PathKit.getRelativePath(httpRequest); + String uri = Path.getRelativePath(httpRequest); // 如果是静态资源则交给filter处理 if(null != blade.staticFolder() && blade.staticFolder().length > 0){ @@ -109,10 +113,10 @@ public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpRe LOGGER.debug("Request : " + method + "\t" + uri); } - // 创建RequestWrapper And RequestWrapper + // 创建请求对象 Request request = new ServletRequest(httpRequest); - // 构建一个包装后的response + // 创建响应对象 response = new ServletResponse(httpResponse, blade.render()); // 初始化context @@ -150,7 +154,9 @@ public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpRe response.html(INTERNAL_ERROR); return true; } + } catch (Exception e) { + String error = ThrowableKit.getStackTraceAsString(e); LOGGER.error(error); ThrowableKit.propagate(e); @@ -161,11 +167,18 @@ public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpRe response.html(INTERNAL_ERROR); return true; } + } return false; } + /** + * 404视图渲染 + * @param response + * @param uri + * @throws IOException + */ private void render404(Response response, String uri) throws IOException{ String view404 = blade.view404(); if(StringKit.isNotBlank(view404)){ @@ -178,6 +191,12 @@ private void render404(Response response, String uri) throws IOException{ } } + /** + * 执行拦截器方法 + * @param request + * @param response + * @param interceptors + */ private void invokeInterceptor(Request request, Response response, List interceptors) { for(Route route : interceptors){ handle(request, response, route); @@ -185,17 +204,15 @@ private void invokeInterceptor(Request request, Response response, List i } /** - * * 实际的路由方法执行 - * @param httpRequest http请求对象 - * @param requestWrapper request包装对象 - * @param responseWrapper response包装对象 - * @param match 路由匹配对象 - * @return object + * @param request 请求对象 + * @param response 响应对象 + * @param route 路由对象 */ private void handle(Request request, Response response, Route route){ Object target = route.getTarget(); - request.initPathParams(request.path()); + request.initPathParams(route.getPath()); + // 初始化context BladeWebContext.setContext(context, request, response); if(target instanceof RouteHandler){ diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 79ef41501..9bd8e5091 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -49,8 +49,14 @@ */ public class Blade { + /** + * 当前最新版本 + */ public static final String VERSION = "1.4.1-alpha"; + /** + * Blade单例 + */ private static final Blade ME = new Blade(); /** @@ -82,6 +88,9 @@ public void init() { */ private Render render = new JspRender(); + /** + * 路由管理对象 + */ private Router router = new Router(); /** @@ -91,7 +100,6 @@ public void init() { private int port = DEFAULT_PORT; - private Blade() { } @@ -130,7 +138,7 @@ public void regObject(Object object){ * * @param confName 配置文件路径 */ - public void appConf(String confName){ + public void setAppConf(String confName){ Map configMap = PropertyKit.getPropertyMap(confName); configuration(configMap); } @@ -143,7 +151,7 @@ public void appConf(String confName){ * * @param jsonPath json文件路径 */ - public void appJsonPath(String jsonPath){ + public void setJsonConf(String jsonPath){ InputStream inputStream = Blade.class.getResourceAsStream(jsonPath); if(null != inputStream){ try { @@ -163,7 +171,7 @@ public void appJsonPath(String jsonPath){ * * @param json json配置 */ - public void appJson(String json){ + public void setAppJson(String json){ Map configMap = JSONKit.toMap(json); configuration(configMap); } @@ -486,7 +494,7 @@ public Blade app(Class bootstrap){ * * @param view404 404视图页面 */ - public Blade view404(final String view404){ + public Blade setView404(final String view404){ config.setView404(view404); return this; } @@ -496,7 +504,7 @@ public Blade view404(final String view404){ * * @param view500 500视图页面 */ - public Blade view500(final String view500){ + public Blade setView500(final String view500){ config.setView500(view500); return this; } @@ -520,11 +528,20 @@ public Blade debug(boolean isdebug){ return this; } + /** + * 设置监听端口 + * @param port + * @return + */ public Blade listen(int port){ this.port = port; return this; } + /** + * 设置启动上下文 + * @param contextPath + */ public void start(String contextPath) { try { Server bladeServer = new Server(this.port); @@ -534,14 +551,17 @@ public void start(String contextPath) { } } + /** + * 启动服务 + */ public void start() { this.start("/"); } - public void handle(){ - - } - + /** + * 返回系统配制 + * @return + */ public Config config(){ return config; } diff --git a/blade-core/src/main/java/com/blade/http/Path.java b/blade-core/src/main/java/com/blade/http/Path.java index 7ca5352aa..25b73ff27 100644 --- a/blade-core/src/main/java/com/blade/http/Path.java +++ b/blade-core/src/main/java/com/blade/http/Path.java @@ -15,17 +15,73 @@ */ package com.blade.http; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import blade.kit.CollectionKit; +import blade.kit.StringKit; + /** * PATH处理 * * @author biezhi * @since 1.0 */ -public class Path { +public final class Path { public static final String VAR_REGEXP = ":(\\w+)"; public static final String VAR_REPLACE = "([^#/?]+)"; + public static final String ALL_PATHS = "/*"; + private static final String SLASH = "/"; + + public static String getRelativePath(HttpServletRequest request) { + + String path = request.getRequestURI(); + String contextPath = request.getContextPath(); + + path = path.substring(contextPath.length()); + + if (path.length() > 0) { + path = path.substring(1); + } + + if (!path.startsWith(SLASH)) { + path = SLASH + path; + } + + try { + path = URLDecoder.decode(path, "UTF-8"); + } catch (UnsupportedEncodingException ex) { + } + return path; + } + + public static List convertRouteToList(String route) { + String[] pathArray = StringKit.split(route, "/"); + if(null != pathArray && pathArray.length > 0){ + List path = CollectionKit.newArrayList(); + for (String p : pathArray) { + if (p.length() > 0) { + path.add(p); + } + } + return path; + } + return CollectionKit.newArrayList(0); + } + + public static boolean isParam(String routePart) { + return routePart.startsWith(":"); + } + + public static boolean isSplat(String routePart) { + return routePart.equals("*"); + } + public static String fixPath(String path) { if (path == null) { return "/"; @@ -39,4 +95,11 @@ public static String fixPath(String path) { return path; } + public static String cleanPath(String path){ + if (path == null) { + return null; + } + return path.replaceAll("[/]+", "/"); + } + } diff --git a/blade-core/src/main/java/com/blade/render/ModelAndView.java b/blade-core/src/main/java/com/blade/render/ModelAndView.java index fed21bac8..082940354 100644 --- a/blade-core/src/main/java/com/blade/render/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/render/ModelAndView.java @@ -86,6 +86,14 @@ public void remove(String key){ public String getView() { return view; } + + /** + * 设置视图 + * @param view + */ + public void setView(String view) { + this.view = view; + } /** * @return 获取模型 @@ -94,6 +102,14 @@ public Map getModel() { return model; } + /** + * 设置model + * @param model + */ + public void setModel(Map model) { + this.model = model; + } + @Override public String toString() { return "view = " + view + ", model = " + model; diff --git a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java index 07ee5913f..0c89c07bd 100644 --- a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java @@ -62,7 +62,6 @@ private boolean matchesPath(String routePath, String pathToMatch) { private String parsePath(String path) { path = Path.fixPath(path); - try { URI uri = new URI(path); return uri.getPath(); @@ -79,6 +78,7 @@ public List getBefore(String path) { befores.add(route); } } + giveMatch(path, befores); return befores; } @@ -90,6 +90,7 @@ public List getAfter(String path) { afters.add(route); } } + giveMatch(path, afters); return afters; } diff --git a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java index c0f6f814b..696bf3a83 100644 --- a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java @@ -169,8 +169,6 @@ public String servletPath() { @Override public String contextPath() { - System.out.println(request); - System.out.println(request.getServletContext()); return request.getContextPath(); } diff --git a/blade-core/src/main/java/com/blade/servlet/ServletResponse.java b/blade-core/src/main/java/com/blade/servlet/ServletResponse.java index 0d7375d05..039e4dbfb 100644 --- a/blade-core/src/main/java/com/blade/servlet/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/servlet/ServletResponse.java @@ -10,6 +10,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; +import com.blade.Blade; import com.blade.context.BladeWebContext; import com.blade.http.HttpException; import com.blade.http.HttpStatus; @@ -19,6 +20,8 @@ import com.blade.render.ModelAndView; import com.blade.render.Render; +import blade.kit.Assert; + /** * ServletResponse * @@ -264,7 +267,15 @@ public ServletOutputStream outputStream() throws IOException { @Override public Response render(String view) { try { - ModelAndView modelAndView = new ModelAndView(view); + Assert.notBlank(view, "view not is null"); + + Blade blade = Blade.me(); + String viewPath = blade.viewPrefix() + view + blade.viewSuffix(); + if(view.endsWith(blade.viewSuffix())){ + viewPath = blade.viewPrefix() + view; + } + viewPath = Path.cleanPath(viewPath); + ModelAndView modelAndView = new ModelAndView(viewPath); render.render(modelAndView, response.getWriter()); return this; } catch (IOException e) { @@ -276,6 +287,17 @@ public Response render(String view) { @Override public Response render(ModelAndView modelAndView) { try { + Assert.notNull(modelAndView, "ModelAndView not is null!"); + Assert.notBlank(modelAndView.getView(), "view not is null"); + + Blade blade = Blade.me(); + String viewPath = blade.viewPrefix() + modelAndView.getView() + blade.viewSuffix(); + if(modelAndView.getView().endsWith(blade.viewSuffix())){ + viewPath = blade.viewPrefix() + modelAndView.getView(); + } + viewPath = Path.cleanPath(viewPath); + modelAndView.setView(viewPath); + render.render(modelAndView, response.getWriter()); return this; } catch (IOException e) { From 3fb5fbb2b705dff20029f8a10f8b7b8df16bcb2f Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 15:10:07 +0800 Subject: [PATCH 204/545] update last version --- LAST_VERSION.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index dc6834eef..9206fbe7f 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -23,7 +23,7 @@     com.bladejava     blade-kit -    1.2.7-beta +    1.2.7 ``` @@ -32,7 +32,7 @@     com.bladejava     blade-core -    1.4.0-beta +    1.4.1-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) From c261926129ab7e90793bb57d21d9dacd62d9f203 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 15:13:14 +0800 Subject: [PATCH 205/545] remove spring loader --- blade-core/pom.xml | 7 ----- .../blade/loader/SpringControllerLoader.java | 27 ------------------- 2 files changed, 34 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/loader/SpringControllerLoader.java diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 845ddf891..bbd95b214 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -25,19 +25,12 @@ blade-kit 1.2.7 - - org.springframework - spring-context - 3.2.10.RELEASE - provided - javax.servlet javax.servlet-api ${servlet.version} provided - org.eclipse.jetty jetty-server diff --git a/blade-core/src/main/java/com/blade/loader/SpringControllerLoader.java b/blade-core/src/main/java/com/blade/loader/SpringControllerLoader.java deleted file mode 100644 index 11d82dc6d..000000000 --- a/blade-core/src/main/java/com/blade/loader/SpringControllerLoader.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.blade.loader; - -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -import com.blade.route.RoutesException; - -public class SpringControllerLoader implements ControllerLoader, ApplicationContextAware { - - private ApplicationContext applicationContext; - - @Override - public Object load(String controllerName) throws RoutesException { - Object bean = applicationContext.getBean(controllerName); - if (bean == null) { - throw new RoutesException("Bean '" + controllerName + "' was not found."); - } - return bean; - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - -} From d3c9d809b66b1433dc569479343fe49fba5898c2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 15:17:49 +0800 Subject: [PATCH 206/545] remove bin dir --- .../java/blade/exception/BladeException.class | Bin 1474 -> 0 bytes .../exception/ClassReaderException.class | Bin 1407 -> 0 bytes .../exception/ExceptionHandlerImpl.class | Bin 2070 -> 0 bytes .../java/blade/exception/ExceptionStack.class | Bin 4358 -> 0 bytes .../exception/IllegalPathException.class | Bin 1406 -> 0 bytes .../java/blade/exception/package-info.class | Bin 135 -> 0 bytes .../bin/src/main/java/blade/kit/Assert.class | Bin 13122 -> 0 bytes .../bin/src/main/java/blade/kit/Base64.class | Bin 4282 -> 0 bytes .../bin/src/main/java/blade/kit/BeanKit.class | Bin 5105 -> 0 bytes .../bin/src/main/java/blade/kit/CharKit.class | Bin 8477 -> 0 bytes .../src/main/java/blade/kit/CloneKit.class | Bin 7690 -> 0 bytes .../main/java/blade/kit/CollectionKit.class | Bin 23258 -> 0 bytes .../bin/src/main/java/blade/kit/DateKit.class | Bin 11063 -> 0 bytes .../blade/kit/Emptys$NullPlaceholder.class | Bin 3177 -> 0 bytes .../bin/src/main/java/blade/kit/Emptys.class | Bin 3905 -> 0 bytes .../src/main/java/blade/kit/EncrypKit.class | Bin 2878 -> 0 bytes .../main/java/blade/kit/ExceptionKit.class | Bin 9351 -> 0 bytes .../kit/FileKit$FileNameAndExtension.class | Bin 5046 -> 0 bytes .../bin/src/main/java/blade/kit/FileKit.class | Bin 12692 -> 0 bytes .../src/main/java/blade/kit/HashidKit.class | Bin 7416 -> 0 bytes .../bin/src/main/java/blade/kit/IOKit.class | Bin 10601 -> 0 bytes .../bin/src/main/java/blade/kit/IpKit.class | Bin 2351 -> 0 bytes .../bin/src/main/java/blade/kit/MailKit.class | Bin 10335 -> 0 bytes .../kit/MimeParse$FitnessAndQuality.class | Bin 4591 -> 0 bytes .../blade/kit/MimeParse$ParseResults.class | Bin 4922 -> 0 bytes .../src/main/java/blade/kit/MimeParse.class | Bin 5487 -> 0 bytes .../bin/src/main/java/blade/kit/PathKit.class | Bin 3110 -> 0 bytes .../src/main/java/blade/kit/PatternKit.class | Bin 3571 -> 0 bytes .../src/main/java/blade/kit/PropertyKit.class | Bin 6376 -> 0 bytes .../src/main/java/blade/kit/ReflectKit.class | Bin 10638 -> 0 bytes .../main/java/blade/kit/SerializeKit.class | Bin 2985 -> 0 bytes .../blade/kit/ShellKit$CommandResult.class | Bin 3156 -> 0 bytes .../src/main/java/blade/kit/ShellKit.class | Bin 5396 -> 0 bytes .../StreamKit$SynchronizedOutputStream.class | Bin 5550 -> 0 bytes .../src/main/java/blade/kit/StreamKit.class | Bin 9807 -> 0 bytes .../src/main/java/blade/kit/StringKit.class | Bin 15112 -> 0 bytes .../java/blade/kit/SystemKit$HostInfo.class | Bin 8690 -> 0 bytes .../java/blade/kit/SystemKit$JavaInfo.class | Bin 10207 -> 0 bytes .../blade/kit/SystemKit$JavaRuntimeInfo.class | Bin 9896 -> 0 bytes .../blade/kit/SystemKit$JavaSpecInfo.class | Bin 8844 -> 0 bytes .../java/blade/kit/SystemKit$JvmInfo.class | Bin 8895 -> 0 bytes .../blade/kit/SystemKit$JvmSpecInfo.class | Bin 8850 -> 0 bytes .../java/blade/kit/SystemKit$OsInfo.class | Bin 10950 -> 0 bytes .../java/blade/kit/SystemKit$UserInfo.class | Bin 9098 -> 0 bytes .../src/main/java/blade/kit/SystemKit.class | Bin 10816 -> 0 bytes .../bin/src/main/java/blade/kit/TaskKit.class | Bin 7331 -> 0 bytes .../bin/src/main/java/blade/kit/TimeKit.class | Bin 2453 -> 0 bytes .../bin/src/main/java/blade/kit/TimwKit.class | Bin 5122 -> 0 bytes .../java/blade/kit/base/ThrowableKit.class | Bin 4137 -> 0 bytes .../blade/kit/http/ConnectionFactory.class | Bin 1847 -> 0 bytes .../src/main/java/blade/kit/http/Header.class | Bin 2769 -> 0 bytes .../kit/http/HttpRequest$CloseOperation.class | Bin 5783 -> 0 bytes .../kit/http/HttpRequest$FlushOperation.class | Bin 5746 -> 0 bytes .../kit/http/HttpRequest$Operation.class | Bin 5637 -> 0 bytes .../java/blade/kit/http/HttpRequest.class | Bin 23165 -> 0 bytes .../blade/kit/http/HttpRequestException.class | Bin 1370 -> 0 bytes .../main/java/blade/kit/http/MethodType.class | Bin 1215 -> 0 bytes .../blade/kit/http/RequestOutputStream.class | Bin 1900 -> 0 bytes .../java/blade/kit/http/UploadProgress.class | Bin 599 -> 0 bytes .../java/blade/kit/http/package-info.class | Bin 134 -> 0 bytes .../java/blade/kit/io/AppendableWriter.class | Bin 7147 -> 0 bytes .../main/java/blade/kit/io/ByteArray.class | Bin 2655 -> 0 bytes .../blade/kit/io/ByteArrayOutputStream.class | Bin 3590 -> 0 bytes .../blade/kit/io/CharStreams$NullWriter.class | Bin 6301 -> 0 bytes .../main/java/blade/kit/io/CharStreams.class | Bin 8117 -> 0 bytes .../kit/io/FastByteArrayOutputStream.class | Bin 2975 -> 0 bytes .../java/blade/kit/io/FastByteBuffer.class | Bin 3179 -> 0 bytes .../main/java/blade/kit/io/LineBuffer.class | Bin 3114 -> 0 bytes .../java/blade/kit/io/LineProcessor.class | Bin 834 -> 0 bytes .../main/java/blade/kit/io/LineReader.class | Bin 3257 -> 0 bytes .../blade/kit/io/StringBuilderWriter.class | Bin 4150 -> 0 bytes .../main/java/blade/kit/io/package-info.class | Bin 132 -> 0 bytes .../main/java/blade/kit/json/JSONKit.class | Bin 3048 -> 0 bytes .../src/main/java/blade/kit/json/Json.class | Bin 9220 -> 0 bytes .../main/java/blade/kit/json/JsonArray.class | Bin 8627 -> 0 bytes .../java/blade/kit/json/JsonLiteral.class | Bin 3399 -> 0 bytes .../main/java/blade/kit/json/JsonNumber.class | Bin 4256 -> 0 bytes .../kit/json/JsonObject$HashIndexTable.class | Bin 5404 -> 0 bytes .../blade/kit/json/JsonObject$Member.class | Bin 5497 -> 0 bytes .../main/java/blade/kit/json/JsonObject.class | Bin 11454 -> 0 bytes .../main/java/blade/kit/json/JsonParser.class | Bin 17043 -> 0 bytes .../main/java/blade/kit/json/JsonString.class | Bin 2908 -> 0 bytes .../main/java/blade/kit/json/JsonValue.class | Bin 9800 -> 0 bytes .../main/java/blade/kit/json/JsonWriter.class | Bin 4410 -> 0 bytes .../java/blade/kit/json/ParseException.class | Bin 1104 -> 0 bytes .../json/PrettyPrint$PrettyPrintWriter.class | Bin 5017 -> 0 bytes .../java/blade/kit/json/PrettyPrint.class | Bin 3625 -> 0 bytes .../java/blade/kit/json/WriterConfig.class | Bin 1043 -> 0 bytes .../java/blade/kit/json/WritingBuffer.class | Bin 3500 -> 0 bytes .../main/java/blade/kit/log/JdkLogger.class | Bin 4142 -> 0 bytes .../java/blade/kit/log/JdkLoggerFactory.class | Bin 1319 -> 0 bytes .../src/main/java/blade/kit/log/Level.class | Bin 793 -> 0 bytes .../main/java/blade/kit/log/Log4jLogger.class | Bin 9128 -> 0 bytes .../blade/kit/log/Log4jLoggerFactory.class | Bin 1325 -> 0 bytes .../src/main/java/blade/kit/log/Logger.class | Bin 7210 -> 0 bytes .../java/blade/kit/log/LoggerFactory.class | Bin 831 -> 0 bytes .../java/blade/kit/log/SimpleLogger.class | Bin 4274 -> 0 bytes .../blade/kit/log/SimpleLoggerFactory.class | Bin 1328 -> 0 bytes .../java/blade/kit/log/package-info.class | Bin 133 -> 0 bytes .../java/blade/kit/mail/EmailHandle.class | Bin 9075 -> 0 bytes .../java/blade/kit/mail/MailTemplate.class | Bin 7324 -> 0 bytes .../java/blade/kit/mail/package-info.class | Bin 134 -> 0 bytes .../main/java/blade/kit/package-info.class | Bin 129 -> 0 bytes .../kit/resource/AbstractClassReader.class | Bin 8377 -> 0 bytes .../kit/resource/ClassPathClassReader.class | Bin 1275 -> 0 bytes .../java/blade/kit/resource/ClassReader.class | Bin 1864 -> 0 bytes .../blade/kit/resource/JarReaderImpl.class | Bin 9596 -> 0 bytes .../blade/kit/resource/package-info.class | Bin 138 -> 0 bytes .../main/java/blade/kit/text/HTMLFilter.class | Bin 7953 -> 0 bytes .../java/blade/kit/timw/TimwCounter.class | Bin 1013 -> 0 bytes .../java/blade/kit/timw/TimwManager.class | Bin 766 -> 0 bytes .../java/blade/kit/timw/TimwMonitor.class | Bin 2867 -> 0 bytes .../java/blade/kit/timw/package-info.class | Bin 134 -> 0 bytes .../src/test/java/blade/test/HttpTest.class | Bin 1693 -> 0 bytes .../src/test/java/blade/test/JSONTest.class | Bin 3874 -> 0 bytes .../src/test/java/blade/test/LogTest.class | Bin 1593 -> 0 bytes .../src/test/java/blade/test/MailTest.class | Bin 1636 -> 0 bytes .../src/test/java/blade/test/StringTest.class | Bin 2161 -> 0 bytes .../src/test/java/blade/test/TaskTest.class | Bin 2006 -> 0 bytes .../bin/src/test/java/blade/test/User.class | Bin 1744 -> 0 bytes .../src/main/java/blade/kit/PathKit.java | 82 ------------------ 121 files changed, 82 deletions(-) delete mode 100644 blade-kit/bin/src/main/java/blade/exception/BladeException.class delete mode 100644 blade-kit/bin/src/main/java/blade/exception/ClassReaderException.class delete mode 100644 blade-kit/bin/src/main/java/blade/exception/ExceptionHandlerImpl.class delete mode 100644 blade-kit/bin/src/main/java/blade/exception/ExceptionStack.class delete mode 100644 blade-kit/bin/src/main/java/blade/exception/IllegalPathException.class delete mode 100644 blade-kit/bin/src/main/java/blade/exception/package-info.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/Assert.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/Base64.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/BeanKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/CharKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/CloneKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/CollectionKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/DateKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/Emptys$NullPlaceholder.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/Emptys.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/EncrypKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/ExceptionKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/FileKit$FileNameAndExtension.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/FileKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/HashidKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/IOKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/IpKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/MailKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/MimeParse$FitnessAndQuality.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/MimeParse$ParseResults.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/MimeParse.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/PathKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/PatternKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/PropertyKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/ReflectKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/SerializeKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/ShellKit$CommandResult.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/ShellKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/StreamKit$SynchronizedOutputStream.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/StreamKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/StringKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$HostInfo.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaInfo.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaRuntimeInfo.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaSpecInfo.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmInfo.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmSpecInfo.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$OsInfo.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit$UserInfo.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/SystemKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/TaskKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/TimeKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/TimwKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/base/ThrowableKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/ConnectionFactory.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/Header.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$CloseOperation.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$FlushOperation.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$Operation.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/HttpRequest.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/HttpRequestException.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/MethodType.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/RequestOutputStream.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/UploadProgress.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/http/package-info.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/AppendableWriter.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/ByteArray.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/ByteArrayOutputStream.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/CharStreams$NullWriter.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/CharStreams.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/FastByteArrayOutputStream.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/FastByteBuffer.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/LineBuffer.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/LineProcessor.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/LineReader.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/StringBuilderWriter.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/io/package-info.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JSONKit.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/Json.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonArray.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonLiteral.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonNumber.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonObject$HashIndexTable.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonObject$Member.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonObject.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonParser.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonString.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonValue.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/JsonWriter.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/ParseException.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint$PrettyPrintWriter.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/WriterConfig.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/json/WritingBuffer.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/log/JdkLogger.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/log/JdkLoggerFactory.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/log/Level.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/log/Log4jLogger.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/log/Log4jLoggerFactory.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/log/Logger.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/log/LoggerFactory.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/log/SimpleLogger.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/log/SimpleLoggerFactory.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/log/package-info.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/mail/EmailHandle.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/mail/MailTemplate.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/mail/package-info.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/package-info.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/resource/AbstractClassReader.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/resource/ClassPathClassReader.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/resource/ClassReader.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/resource/JarReaderImpl.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/resource/package-info.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/text/HTMLFilter.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/timw/TimwCounter.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/timw/TimwManager.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/timw/TimwMonitor.class delete mode 100644 blade-kit/bin/src/main/java/blade/kit/timw/package-info.class delete mode 100644 blade-kit/bin/src/test/java/blade/test/HttpTest.class delete mode 100644 blade-kit/bin/src/test/java/blade/test/JSONTest.class delete mode 100644 blade-kit/bin/src/test/java/blade/test/LogTest.class delete mode 100644 blade-kit/bin/src/test/java/blade/test/MailTest.class delete mode 100644 blade-kit/bin/src/test/java/blade/test/StringTest.class delete mode 100644 blade-kit/bin/src/test/java/blade/test/TaskTest.class delete mode 100644 blade-kit/bin/src/test/java/blade/test/User.class delete mode 100644 blade-kit/src/main/java/blade/kit/PathKit.java diff --git a/blade-kit/bin/src/main/java/blade/exception/BladeException.class b/blade-kit/bin/src/main/java/blade/exception/BladeException.class deleted file mode 100644 index cf172cf9365b0977b37298be36d0e6389bcf064b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1474 zcmb_bT~8D-6un(OW*K$?K~V9l;@6Vs>%2E9<#Xy1py+M7^Df6zjMz zvFnx5^`{|TKMErlWiV3|WRmU zX=j+bM?9Wrb&&gmF7g171ae8A9G60C<9QqT5lF%to-4nkC1YE%DT#K^HGqpe*rt^x)`c3TY(tn z7|hq210(cbwi=8w-BcQ1_wqK{R$$0rwrM08Pmuj6K1`1Kj&cl==2^VG%3!kA9BQ_3 z95s)hTCkX^ok+}(J+g-0@Z^Y=6_R*WYs*7LWw^nh@n;+NUHnhdGl(}#&q{nwwq!8( z`;ZofA`Kf_()cOoQTrDPt+29l5W#I4*OT6g;4Tei|LqanXF&6G$b>=Vm2!@})uQoo za0_T^!xY0JjKMhV5k(~^Q$)OAlGX}kR;Y^69)E%AyV>baaN%1~cahd`Dg=<3y10AlPqQk>ebQpn~#JdEX^bTK* M{xT`L1b5)xFZ;oGRsaA1 diff --git a/blade-kit/bin/src/main/java/blade/exception/ClassReaderException.class b/blade-kit/bin/src/main/java/blade/exception/ClassReaderException.class deleted file mode 100644 index 5a92d43d344ec030b5409ddb2d7728ed62556e9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1407 zcmbtUT~8B16g^W43rkBY3JQLW_*K-jiQ!3%FNm>b)dUKOkJIf)2e&iL%oO3tpJk$n zzWbxpyDe-RLa@Y1c6RU0y=U${bMF57{p|;UH9QWGV|eOpTYy09r)S8KC$(lTj zW!EdCYa5AhZcCEWZk{*;gn+WY3dj6J!Wv`Qqq(mG1rslQ}kZy1UjMmsOG z-xWzuPX0Mw3{%gQR{jOUL}hiCA-`c-GQb=|X^6dPt+CT6GxlXiTj@-4AX_{(ovunm zS|RUR(@bQ?J>%g_qb+$$#)+^L)D`h3u_yUTzo%-}(+Y1H>9{tYcZ84I+*6i3>{1V- zS;R{<<)xYyQ$39l&TRFxR~?zL!egOR%%d#m)`KfuNc8u!FT z+nUdUI6VK*5Jk)v5aKe!LM0kr(V&?1^a@Ln((+xe)0DQ6A~MWJCMHP;5(e4F&b)6c z$FLS%Tzl&bbCoD-t$*rlB^s$=F|$sEl|QN^sq1Y|x@cGtQ+374YLvCVK8;%p_48#m zP}x|7F@)QuXJh$FrA#cHHA;PP5ubG((~v0VrS`9tw8F;iqX2gqhQbMOpJwc|>;gQb zNgDJYV3iWGh8PNOm2)Jg21(H24rtV9^cj{hi79#qWaThT78Q$G+6(<(!vuW+;dc~2 z%$L66($9X}724A*po|6D3xg;u;wo7w!Zq4Y5OU~q}^V$hU>U7f-vOa f<{3OZIfI7@+@@1=;KX;j9?=sbj}_d*162M3Q~75D diff --git a/blade-kit/bin/src/main/java/blade/exception/ExceptionHandlerImpl.class b/blade-kit/bin/src/main/java/blade/exception/ExceptionHandlerImpl.class deleted file mode 100644 index 9f44cdb4e00f58ba1afcdb885df5157d22441c55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2070 zcmd5-TTc@~6#k|Zwq46b6alXTqPCK>iQ&l-UI<2#q7SVkK2CRsc3?ZZnVlm14gZV@ zCi?D=GM?SSf}~DsI}K-j|+bn9AHX0};mzP9qiS48^AEXkq(C zGRzH5*H;@EczuIxCf1c!c7wq!pZZmH85T~JOXkU^{ATD&2U85w=VZ2w2~7brYz!Z? zk#QItN}qdSFH(U>LgJAL+kx!Guen=nbtU(u7YIW}k?;;gNAl$~3Dqo`W$uSE<~p>z zC#=`ymb~OqL_uHlqC{4cL{<|r)yo)eG0g?{gie6kl4s;>$OX5@k#vh$M*d=#ltFpQ z^0*&KL*ePzn!aa4!w1zUSGbCKU;A=TY3Wz_PCvE@>C`Pa=1L!i2a*dS)BPRcdYN8l z)HjWF)BhW_`mL@BKM88$tGmR-BxXw};tma6xp6)tO>30y)RP&SZcux?>-XByv=T&y z*+%GzU{@HG=%NPKa(#FbO8?-K94Z6H(Zng9x(#ISvJh=XN0Qrpo2Z-#y2$u}zLr^T$RFI*w% zj&$&hVLYv;gBR2$nWcjYsTo6t(vFH_>e&`;$vD3RhB3Os=nB9%Cg|;umP3Jb@`FqA z;N%uc>0LKQCxH7ElOJcNzu@-w)c!6#6K`M!bM!2wvWt6|CylsaAwycskP`a=()}Sw u{0~T1b9y)gX=NzVV>}^dXHlJV;X@G0LlAOUCjL1*#Y=h@D32?6j`A;J#8*K8 diff --git a/blade-kit/bin/src/main/java/blade/exception/ExceptionStack.class b/blade-kit/bin/src/main/java/blade/exception/ExceptionStack.class deleted file mode 100644 index d49dba70d34c05ded94ba27421d330a29d127384..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4358 zcmeHKZBG+H5S}gAH(o>#-(MC~Yz10Se2GO8Lo}jAO}_3pin*x zZi&Ef=yRQU1WuLlf#OU>G#sV^iI{J-Y`MH@Gv8mHEr+3%R!VWby9nbXLYR|jT6eim9aqs7Q&y8I zwBkD+X207Cb6(K3RM62E{>Etg5-rb_iW-eT37cBX(YQ5Ecd0srB348M097t!RDJSz zHe<@AhfY{ZJ@jMxUVqpCKg z`%yQegI9^IQ#FN8V4$V@{YtLg*N@c6b!#kl0FL2epqnQp@GD01jI+Js64%#s63F7! zr*j=5@MM?%*cYJgn-qap(d-`yEe*HGz|8+leylr5U(2D-caM{`9a9e=@HE#o2pw_1 zinRoECxX_$-UF|_E_O0pF58Ycpiz6M;_aJ?&oDT0^wx@LIUP7?gSLzp{A+L8#Be3X#306+^(Sc|@xqJgbZiH=v(4-j;R$>Q zAHxe1P4wPp@Y=^Pe!DHDAt<13va>tiesku0XU@0Zet!A_U=1Y?8HPKtm6eXrrm`b; zMWqpnrmCntsk%-_rcw<<)e_+g;o6%AK@VdLvuS!LOsn#|v7@A;P^_#L;kL3dE#0a< zWMEGi3LBA$oiJ`&ggrGr|Kt6K;MK-=hKYOHXm_6>TP$rejBP|sw{7%RP+2GB{a3J4ZtA0exjcN#Gb|K?!=vhxSx=5~CeTJb>vbB+ z){`Xw{ z@<-hYN$d*6(nwMcR~V{)wp-tAr#dADzZUhZRF8C`#PV@1m70w7tQtwpqGLyndaRWd zR<`#&TxVGNo!>m%q*m%H;o&v|b-{oaL;k6bWAa;_ycgpdsMo0X8CEck33_@o%OFQH zVu>jl^Xb1KOK*Vx8HJZ~Gaqs8YnpeS#$;83us~zJpM^zSNMk;hC~|<1>~wa7jgBf>>o8bLVJ;qoy$@MCny;wtgZfRo`Sq6~51Lte-gKw=E=XJWkq1c2hZNp@G<>$g-Tuk)_m<-TVM%ERF4nM>Fco zD0L{5zZNR~%HKIGSa!jR6${P*PP<~m;jm>1TefU_4shR$^ybNW(mcE4ketIJp3%(x z?swn4_uV(|=KcBKzyAOLJ`KN!!4QEnj$NIqtGYRLSG}iBtr==fo7&Rdsf^=jwi|r!``dpVyel)K+P*?C(mRaR#Und0>>@LB$KZt+It z)@o*HDRZk!XtGx*`$}eMwVZo(Iakbf6P_0cmkNbkwvsP(`$6fIT+H0)VrC*Z@JzX! zzgEo57P|SyJ6cdAUo2NL)S%LQmzt3o-PGNy1P-JoRtOAdt(q2t#|Rt=f|#>y%Z|en z*{YrqZyjHAAaASCnL;vZ*QV{f4Gc1!~5T}5{k-K^<0CW>(%U#)AlW>%45-L~rZ`}HQit10QKp*oJTt{a-;v(z+v zL|--3>Xy2pDQCTOOk+BpRce;zD3q?Qy46j^MXR*!26FK7n9OOK%xTZo0PXA7>kZ3x z{c$v1-4G057lQeE!_cd`t2oVuW~2K|$F-YP*RmCVmZT=AE1G6aTh~oGe0+oVYSVCe z>9n%gbX@udr4-eq!}1k#DwB!6K37~zQN0NLUr2j6U63~nZ9_FO_C~X=nQm^osx`cM z);ojvX!>a+$WmTNDlhiafMU}yZdkhMYPRga@;E29OHH@5K5OCpaAa|`6xB6%)2b31+V*&j!M*yNhY!ue$7=SKHnb2SW6FXQEi0OkZ_6YrfQdQJ4knjA8wYH82K$$UQ)rB%Fj#jlwZFMc}bi zA?Ww`i`F#l2OTM3lcCtGuW5FLCNqKK1*@tWE2^#2-|dIP?xyY#Pzr;)gV@#^(VdFj zL_MRa+nr|L#7Z2_5_n6Zxzu+({rK5TAcpNCT7(Ha#k<2_&!%~6pC$0VgtgJFgnLWN z9dT_Bgt~iz!2I9=&{m#|{TRvWrdHi5c6|4&z;_c|cD1b_kSOaLrs_6r%!V^Fl`Fk6 zS5uYB^aTEk!xVu^xWT($LJ6Go%-_)*z(h^u^Lgs37YTegnAvN4KFmD|oVC6E4+4k1 zA$IaQ4wngONQ_i!4nFW!#LfZkPg^DOh6ny{$xh2LB{49auuODr;(+B-rs_z=M@nd~ zRcFL^6M<(^9qaG(&TejGFB38xRpv>JOs2B+Z=vs7Zw8Cvrs@ zp6cU>B?2Es<%lTF=Ms898+rsTi98dMJ0&#>K=a1s-Eo)@NW49VXw5m*@PVY=Uububp1Q~~={ zUPMQ|+nLFBEL8&8aHh~^7lCs=#lV3PI3KWwNFGC%aSb#t@zx0x!j0u&gENo7g&iy* zM$v*ji)Tc(@H<#Ht47n&?`gA|`-Y~O1YQ&^b3vb?y_3W#*6Fo*0lCEuJ3M4A=*Y#3kwUh@Yn=yhR1(zpE3l-Da}Ar;?R_8M93@| zbjvP{XH<*3+RF5%305>uIW?4|`<7bF>LzxJw6Pf}9v zew{!r+`AGTKLVHg+Y&O)D+A380Uy;JJP1MCG}!B#$KzN8Xc_Un;$Nu0pWr#X$NtLZ zmjhlpgzp8Rq7YEBY&GqwHjf9x2psYcZg>Z}V(>0@r}*j>gYV-8%Cj&AKO~S0Dt-)p z?EUUc@fiFB55-}fj=|3`wfqc3b&LKPkP4n~bB4zOW$<+5AvgsGVFd3^L9Bg^x37uz zHQBx%YF|g&*Te1WC)(E|?dwtRI*AO&;5hz0;hn-ffOi1NKfuXb#~=S4eDXv5H3X;e z?}+yX(-!YXeJOYf&fu>EjDgbDFp2gK;WJ;uxIn|Cr-8~O;2b-FKdkCKQMojGu@M!^lhQnWkOB^qaj6cp71h^c-CGm9YXN0(y1h_oI z#o@E?IU(+f09RqScVPxT&*6f2TovGShD*Q~AS1+y_*xupwom-C0>1Y++!*9Iz90_s z0^Bbdu7&yb3Wp2gkQd;7#c&C@z6-wh8LovmdA?tBxN}et+PNsO^EV8afD+u`aDiW5 z72tl$a4p1@Ib7hEiU9XVhNFBdY+k%3m=`w%_&+f`<-N`DcNjk4|Dpi@SB9tjUuO7K zh7ZR56#@Ql3{Uyj7{1Ez0lx_U4~D1wHO_AVuO{IAC&N+R4GtIZiE#g7xCCtOg6|`S zYavdWj|?+h0(7{`{IezSkI_3$a+u*;h&LJDV)%os{)zA>7@qPsI6u*K%&(iT3wTd6 z9OZR5T%6%t0d9=pDBnE}H<<4{!%@CBINV^q=NK*l+k5cuC5CSye)s;p%sYh diff --git a/blade-kit/bin/src/main/java/blade/kit/Base64.class b/blade-kit/bin/src/main/java/blade/kit/Base64.class deleted file mode 100644 index 39b3e70fbddd73d379c60116ee4f83de7577bbdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4282 zcmeHKUvC>l5TA9E_)k)jrnHn&$|i+km)0)S6lhw&|5_}$Zit--6rpH+-q_dN-CBEl zQS-{D;3M$BI}%9n4txMU21q<3X75UTm9NJY8^i+-zVqJB{AT7ivpc&#{Qk{%08oYx z(~u%?(UnHYW~Nhm$PQVlXR$sn9hjT0ONbU;jkoTz}?2&0PWeSImr07}Pc5l&K zwmams&kc)76dEz(fDJfZ_sJ5obgAd``M&A!ev#hyT&3Oh)vP0GI)~zbQ-=13Pa-6AA(5Yngti@wLi57=4F^+< z#nE_V@R6UPNs7We=$zSH4Mm@Ft;(xMio5w9K6gJW(0wUvKTn!98dNt@z0akqQFI1v z({<6H&npewO-Mkj?W;(z@*n@O7l{~7Bs4`D65+Q!%i0u33ztdL+q5h`U{*yAJexb} zzp3`r;IWR5T*d8(wVbfTrcO!K+s9&$a3H*hf&iXDG!fok2u&SYJbn&N!?`6`ffos! z$xk*P-7}V3xHYytyT@ghVH?n0N*K)AVbav&#~H{%=;HGb!#%creD(m0mZKiv~A1-20B3vzvyu30#QFbOzob z@N={~L5>W!_fG)gy+#>MPtm6E4$cSeQ6WtM>H27UpH_XN0OzmHG z(tx+I(6upem%!5f;E3JDGq?+DfLAuWD9*uon1=-%rE!#k434vqJ036M_#`}sb2(V{ z-x-uzfm0~4ieJl!LiFsnaQf5LGhf3C-}^Y{@u^V(WnaSQQXmBv;AI@;;3B;87~u*c z%OcvJRQb=!X`PB%$&qI2b;q^$pe1zT?Pv~6<>1oCSKi`PZ`zoY& z4T_O^r3k$rLwaw*TgdMXv@?hLWuIfs&^XeY5eUD95Z*kdOU;@ua*bbsS4eke>G76_bjeIbkYx{rs?d0+?}-xRSheFDc??Og&3cjbuJ zp-Et6j=iUpR1G*m8t5*EB* zdz@~#fI1k^1|3PRX)FzmmDVwjbL-5%h!Uv`&H8YHng%Sk zE{B}{A7C{|yO^a0PmKsG0&Yb~C<0-qP7|(hqhf7T8W^c)w(YGp6`H2;h>t~#t3Jja zY_l{pd31+vr`p&aL{S#oZORG9uO2WxsdBud;;2owQMUJc+&Fa5bNdLS^*eO?q*vZF*eB_LHsT;*6f&JQuw`w|Cl`E5E@GIG^~WBRo2 z!E#{Cm9}ZniXakN+oQ-q(9ZLq0VkJW5ta#@YYpZ_Pe$UNEs9nKc>X;~qajy5!#an+ z>Ocl8++|AG_vw!dW+F6!^}zw9SdTz6Vu>$phy-YBfPwS|PQ1N#E`*Hz7QQ3)VrEi> zL;tzy-}xBRcTP5Q9n<)8zf9frr$cS}ey`taN>RW_Q)=J9d6-m63({{zkG1z zl+_04Vmm9seEdVAVI2^S7g+!c*jj|+_^i8&tz*~%@cx0u(^c;;SbBqRHCVx?#Q>bb z55Q7}g43{yZ%sG@XAyM{+ch}vJl#V7HGI!JT`2H$!+ElpCR~CaX7-n7_VY-t6xjE3 l_Sax-W={+3*9+{Q&FpJ%-9>%_ZsWJDOK-wY(8d}3{2$u!h}!@F diff --git a/blade-kit/bin/src/main/java/blade/kit/CharKit.class b/blade-kit/bin/src/main/java/blade/kit/CharKit.class deleted file mode 100644 index 3e0e621f5b1d8ccd924aee1063b531cae6100b6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8477 zcmd^DNpl-T6n^bE))L2d_QXlZWS6p7S)A3`Y{gELD0bo{o3o8aZK>_ij55=T?Q8^! z166PUiUXYB#(^7`R6!L`IZ|-v&JW-ZP!w-QvegrJcdx5~pbVXu-JIu;<5LlkHEtl&Szpk4_8iojg_kMms>Xy_mZ3u-U z(PfRxo0?lztX#Ev&DwSAH?(ftwE3Ma+SYB`ckJA?I~L!wci;ZD#DRl{4!0jUdhGa# zlO3l{pE-N3vnzSNyXV5i)TPVmE4_VJuk{ZM4qd--^VaR*J9qEhf1r;T89JKHv9WP8 zZ`p;1j?0UWCMKsIKY9A>`MU&G2+Z$y_V;(*BCu*$=0Mb!EQ>S_r@fHq2B!`>*Kmqi zjGrN}Bo@C;pgw75Xb4skXs$$}+i`3s468{bG-Nr{warH~qZxL-z)YPp+tLb-Jz~E+#-^@j*<8!(+{kGh<>_Prvmwf3I@`Q- zws|z#D(I4amM_>2*ZetVYld!l`bMZW%`O^A~aV;qpR7NAE)gob{aa+?hK2@L#DKwM9 zIV`HmEgXGSi~lz{r3kAAC1sj4tDBupwwR|D@18Vh!7s$wl_0J^RrN|-=gDC)b*uU} zPwJ}bm0WzwLJP`0WpSGIHdWcay9jeiu~PNWlN+E9i_|ix#DmxCMNxFf!gIzulxU{g zGVBbt4yskDB10<+W1HX>1sJi}?}i4C>e& zdEKRL=;n3ZVcvUru%73bOJHkyjs_NcwGg*EU4t=f(_+bZDhyi?SG^;{hKxWXb8qAr zr!ID5NW%l)#{QApGbJn_iCxKVhE%-g(j3R}C@;lGBD~F#4vLppOjS;XH z&{LIFgxz;32VPFP;zJIwlP)$j7j}_PddQ8LYa`kh7_e9?)P*hs@i|z*| zLr4vJ)g|)^Pl~$)e*KSlrI^A9ex&H8+h<|V)(}f#Sz*`Kgx64+9)_2J-QFyLFeW;M zbGUzpyhs0O`Ha+gHad!h%G|U)K^;SPX_|7p`t!$z3V1apj)hUKJRM^0d6s2(McO<) z*yof-qS#Q{PR2_N);V*pIyNfeQ@whgmIe`BZdF^#Pgn6am6!V9rt%Qpt8&LiA0o_6 z=CE6K(bGn5`?Q2k7Yi9jeFw^;(E+>Y7_^6ZZFQq(60dmutHKZz%OlepNC+m-f+yp5 zo*}?ZO1KCvEpx@waY+HU4Yo^hJ0$il1aP~gxZM(5uYijqKUJPX0o-0GZlA>7 ztpKh~zY?i$*wgMO^@dW_G2WJesD9a*v}py7s8LuIYslxS!bG~7n+wR6}S&@e33P~mV# z!XYMTxCi%z^-;k|)(1%lxCfvMIPc^u?UyoKM*ugXjJqh{j2i3>25{>3#C<)Zeohio zut#ga6$IR94LB~~vNhnu^B`9P?x|pp)qr~;;KpjeiRZ|84Y&^ldu9!|j|E)52HYnC w&Z+_Txq!2wAk;(Uypz?@7Xt2K4Y;pnaCP8drPhH9kG+b;y^q5q-2Ep10p?(AJpcdz diff --git a/blade-kit/bin/src/main/java/blade/kit/CloneKit.class b/blade-kit/bin/src/main/java/blade/kit/CloneKit.class deleted file mode 100644 index 52a2c9a6e431eec7d0c627e08c4387cad499345e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7690 zcmeHMTXP#V6h2DQ`jWH>p)HhK)c|cAz~=fwGKDs61`kena2kg4r0mMJ+O@RoYBSBx z;EA8XBQwCjJ3oryNbA_{bYqF&@c@&T_3rA^cXW=9R-bkL`19xA0N`Wzqy%#WXqp6# zJ`=L>m>sdkVZ=h-cp`LTJ5rK=DRc=I2&~w~h{a{*A56QY^#u$;1Yr5k(~!gqLMN! zla-Z+GU2I;j(A7|)sIEQv`~`9i8_pUKmC+eEBif8^>NIpA*h>y*6lE8z@$`~9&&oZ zQKwB!MM{MXMS`wG$Jo^236}vH=p?F-&);R(7SeiP{GuI!j^;)}j;~Bp%z`JZ%jud8 zSsg>RMnlC@YRvVS4tiAMp!m}mZH(hF;B^!5x*h7Mcg`>Ru}bvFjRFT|0nD_ByiETa zf$c1gakkU1St5n(rUi~rtthh@Q>`@naU=qvX`016!4#9JPO?C&gyzY<#mY3s0^1-xqg3dX7vqW1t^o|$yo>CEK z(ghyCT$DYQFid}p>T~PxIe)jdPtZ=|$C`UF-b0{^Y!IRzE;|>rZ9opgO{sa;)8PTu zWi}sSOUbSaX)uoQSKCZn61xTL-GoT7pNIUyvw4yL4e=c2TubY+bwzWDsSS4l}Rn^_U+y2ES9`{ z@B+=yQF){S8=8HVbh-8o(4J~%L2sAqo(g^Y*aUXvox;cm9@Dz*3-k*3blLn&;$E#J z>Og@z6~nDX9pMKYU$P`&#}s#aycafk18nS!)LFf0df=xIxAmz;;jXbAec@26(uKSF3SB0V@ z3e_$Ck2=dveU?sDSb`UppaQD|uCBL6X9oHIoK174u-w8wVS8EskSF`*15IGHh1+X% zz!G7e2QL?NPvEJ=TFZ3|f~OYCBHbH5^B_=N9~^en9uc@ScrZsCwMS)mmB9BNCl_8@ zu|0*DEUt28>XLv2mV$)i9+zhefm`G8%U^ER#zH!Hg}x58MOp$%;9Bv_m0^vLMGwEd z($x!8JP^lsduCdcz=gmZr4hJY5b9<@tV?jqgtt&EmtdX1_2y|(u>>2qBnlN_8QvwO zAO5csb6P+gSx^`$M<1^R>njGQs~V@v=C$~?&$aWcbh_7k%osF5Pq@{p8!9`69E zzrfNrtCxR*mESGyMZ6lMVYq_Vr5puU;Tk@b;U#z(*>cY7mT3d+jhJ33V5(cDIotm= zcpdw{f%gm8>qY^?%>stchYS^X6W$syRFUHbybZUZHsmo@a-ZHQ;Cc8A&&f!Nct#$* lSHSb*7*Av9(ckC!b;vUZ@8ihl-~+7p0$j#9_;Bdk{9k%p=?MS; diff --git a/blade-kit/bin/src/main/java/blade/kit/CollectionKit.class b/blade-kit/bin/src/main/java/blade/kit/CollectionKit.class deleted file mode 100644 index ebf5f4c7e7b65929a7d1be9e40733819441ceba5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23258 zcmeI4cX%Ad6~O16ZSExZiVHSpF!*GHMKJ~}AtTGOEp*65XBpc8vpQ|;vrl*8?qm>2 zAS8jrX{13&4}m~J5=bE-gcedM>78`aD=9zVT0?g0{z9#_t6VJF`C6e|>Mhig zY&@`OLZWDu_Oxyq+=tJA&0W{MzH?hPx4WmWC)d-N-QCr>xwES$w*wgT0Gr%ZE>&w* zsWxC0N9}QFb{epG9@Dj{uWQ@Zt=)ZHJ9cNg2fDLd0PP&nUMLl69l*wAS_XiP?rBbe>*mRh-Xj`dbSIfl%_E0)s9v&$aE$(!Bq*5L%+QZe=>E@=~UOPQx z=ZjVag+{FWeru1NK1Rg40%JWUJyf=<=~B6t9=2-vz3Cdt+n0=Bh^jnhY6Z{K3hu@V zNjv%r!z1NNEiImn)(XXR-YRj8gLc~U@37$E^c?OKVyGS-3WtZn|LIWJXjS)~YmFG{ zd%9LmTj|=^h~3;2O)6U`?YD=XeOa7$^P`oDU8+UX9ap}yQnALeg=#G%3sL2`m;H8_ zwrEnhifxDM3U9%1iT=@%5uDqr+pS8eP})-sNk+Irx#kK{6?h~{IKgos+Za9?9Z8FSCRU_WkZ?4j^n@G`0BlCKoVSVtR;9qN-J9cUdka-yOS6%VOxl1om+Xt(9uI6{rX}lM;G?Gg z!k&^<8?B(Rv)X%CD~>s5D{TXYdmU0od#<-FH_+D6mST&5Z3sRD;b$O`h90mS!{SV#fhHH#`%X?ci>RJ%Q&#BhcG*F}$tE z$z5QxFgJ2^QBRqT`DwU~RyV}3YS2K2Q|ts_Tf+0y;6qrh=I~rKQ0V!_7@nI{kn7k# zF=wlgzE+>Y~sla-|lR#Kl@Kbp3B#o}L__(5qIljnBf%B}a z6nKGZj`vaHj8c^G;#nQJ41~_+N*QpRSnA^h#=^TTdErFj?!cT#+>5|STp2Ht&Pb8C zP*}SptGI%}X#x+cGg&vut;l`(qM;b^Dp6kCsV zF1*KuPHDiBg=+WkNNo&Q%899EC$QCr8Uu&tWOg-9LHxl&pO)W+qo`$Pik%B=acE3< zrk}?X2@5-So5_&Lw&5PIB>~7pi^bnw$7ZBJu6ZmSHnv znxkaoo(G}*zM05fZUjsuyWTcAnazIJn6o>RIihN9h&q%X3_h!nKPVz>aiNgiB5JF{(YoPpwD} z%KIrzvHj7LjC#V7oHh+xB^31aWaHQzSk0%~%r0E3D&pR}H_d4~XMM%bCxA_%)giwQ zXd-V}#>JdWrdTD?_>$(r!k%B(KyT6`yI$WQPP$ zEnmZ^n3vJT=7!SrpJLRnwUm_i6dz$#od#OqXF;@<-%3GLXAG0Km9zeO0j{INs{kj$ zT4}P=i`bG#t8u0|9vwX|ybS6^F zGn!(rh`CpbuxMRk&ZlM`Lpsfv3q$uOkDXL3&~jU^wcV)IlwpnZhL_uiY3c0KH{@!% z)o4$PLR(gg;}4~8NKMiEMx8=2D3rCdRC$KcIZTFJd$*tH)-X+Jid`3}giAeP#bKFh zw9T-pY{^Q$JB@z3No{oAnbouaa5=0QREMLqv(aeBlpo@$=GU2q8L`D%jwfu(#St5+QEWEUMPYZQh)oV~C&KO+rg?-Kuh_(IvRBb4VkB0_$6r` z6wWO-2)iYL?=f*&7aJgH7e}r803$q!7cqY6z@kEW+ib6Vxzb+wx;N6gl0#wL=P31k zL08eLRyE&FYw%6JT@cbn2Pt}9sl|}uZwA~8j5yxg0GFe-OtH^KK0HI?VHq&Z@Vo>8 z+Z3nd$k`fa{a&$isdro)U~tuHF8-sM-DrWP%6dCn;soPNe5isa-J2j9jZJqJ&f9Hk zKVL_pJU=CB$tpK6jh!(pYb>=mPaN)7bhT?^sMTRb?<{Y+(RFW*p}S$SQB*0Gri*D) zd4`#ZGpX=NQ=t{jvz=Dx8NyGY3biq6iJ90EbvMywoO;^8D^_Rm7HL$!K1Svm6)5`M zlWdcXTnrlxtyAZ+Vo|Bsq9^;7Mn1HFiGk~sZ9d%1?=qDGXSZBBrGazq@Dj@}r8KyY z(1Ms(LoK*!yiwYy*>pc3?NNLq%NIG?Ei~xAz11Y0n(rYxdsz78LK>ZI$PI%=$EU{R(AWtA%5BELklG4;5g7Fm2_e#&m z*rw8UTmYzV5$B4^)A$7aJ=NFWu5u&bS;Op0heY}tWl?#zk8%a3XoAcwH=l-^5VU%_ zkJVk+(!8fMy6S~B&zwZ;VtixY$U1}Q6d!v=dC%0bAsKX3`*vTMecuG42G5uqm(yw2 z7R&kl_`RUpdHDiSyM-C_Um$9do_g_Nnf3&A1S}9WQBO(z0#Oq}eQ_3u8tWODWbt2m zi~XklF|B<_X(wXsP5jwZ-0t7g%da>Bi{XCSK>1}dbYyv1e`y2UWz!f-V2gR zg%Tc8Rh^%t@+Eqfx3>7FMf?lQ_eF+iRsIr(3wp}wPyC9eIyzXZSo{~Q6Glt;>rr$+ zFFshoZ$xZ-sf=4;;dfmSzVCcQ5Y9_lfna~*=G};#i-7mMG6xQ=!s2iI7^S~FTFKk% z3*vKC*|YJ-y5je#NjMFK{0{>1%xOcJ)^Qwjus!7MI>=q^0E zsoNVT0l%Y3d54`z*zH~6cP~k>Fb&$ddJ^*5Euj`S5zUU2(5{`grW55MA= ztnGJ_FpOb}GL(ceiU~~@@h^(Sm->Rj&w<=a@pKepaSy1HaIt$Kp5Tz4s2rRm;dvNo z-6>`g@J+q)+iz!t<0pdW7OGV&i8=heTXpPji5q~oA(*7w1`&Er!N&IQVOZz7N zQiWf|PAC2h;-&pF4fe0l_%`C(iI?_G{L2*nEY?B%8seq>vkmsIR`|87i}-cK^S4;y%s|GmUFu@Wm2KSI3B-$e%d7ixT!_!{vtf2R2NY5XYh2MoL^{!55I zi2h$p{3Qn71 z-#ZNcw<-Mf@z>vpb2L8o`a3b8@$Vx4Zy^6={tWB)L|)-q@Lj3!P503wOg?~T$ z0P(jHFYC{3hW__KjsFnwA0|H7{@oh?5#nz*@Fx3T(D;uM|1sia{!IKM#HZLD?Bm4W zY2Z!u=Lf_$u}`qOh`*b78UHn8tsX`0qvJ zuT=Q&vmX%u!-)K=H2z1#|2QJA*3U=TPl*31@xl31_wSFgpAr9a;)C;dtK$Eo>=(rU zG9rJc#{Y`=UlSkPe;(BM-w^*>;)DJFj>i9v_}@q5)%y1s`vdWRBtAI*Pb&5wV}Bz4 z&%_7%Kb~p)y3jY-Q2l4+TKG=S% z#{Y}>r-=`?udY9zV$XOyLi{9|pZ^B)>i+vF0OAu7`CZa~7zg8tpFn(Y{L20t`6Gx= z5+CgU0nL7j_@;=w+`#Kp#7`kUIQ|K9ChIm90sk$*(7KNsc^KcDzu|CRa$b72ATM-d^ zg|LYDqlpi;|5wHTg^(tGG4a9n|Do~p{siRvlVJWCg4Iy`@}=wH!A!JXeIwois-+(@9tB0`Q9fue)--h z0jFRWOTejc8UDAA9SO4hG;n*a^>p3*bT+ cgdun??1g<$gc6KE1!`~rE`dwgIC%cQ0Vu-h)N6n-57`$K?$1SI}21ceP?B8q~3c>VRvSonI&08 z#a~qX!JAc{Jm|?PtGrl+l#~Y#TII!yRo<+!%9B-A>Dlsi&nD9$oor9J#^5DMcfarb zeDA%P?&*B@*VV58-~hZIf(8QH9Xs1u)D5$9N^+K7hLL&qx=j6uX@#Aa~ zjjo@Y92_1>_p{kmqUd}g`c!W=`Ca}TBCx%ASaVEP)oKD4ihKG9DbcjIM zrNt5phrpU7``v|q95PJ9JwjkrtbLR~V~>@iA-D~7_@Tya+p@!O2iY(_V%pTP3g>A~ z%UZ>fQP5q(GPROzWeT+D9Mqzb^d!}CG+WSZ6e{W2b9$a?ZJf^z?}bTBtMe6*+ED3&bS)%coAXIw3-n@nSdYP0?=hhW(?3QDGz zQ7};~6^yLmYEHRCZOjsuqFv6qmaTau8*A4LM=P5-I$@Yd`2?=u-+H-#H2TsV+F;pn z*$PT&y2*0nDHepH5mrVL3N+W!bj_`lsFFz1GV?XGq{^id=GGb0ZPPIGP7U$;__dO> zq+A>0t`WAH5VlW&ve^188=J6}&S2v8;p~KNJ2XC%r6vA=S=iqJD@=_TC5nU5kqRch zB12Y4sT#k*xCls{k_#%K1oN`~8vmoX6#`jFB0*USmQ~e0OjR7*RY{(pO7Fe;@VVld zs8?qy&=rsi6^$w{g=N%}G;mw?kKcz14kt{P=GhifvbR=%-((_6HL4`Ek^;Z!9R5F& zr;>yyw8Hi#*a{kfmRQn1e0$(7b~xXV#G}|yxtO7LTF3J?flWy(s~1Lf+hF7BWTQK2 zI0SYiYkbkb(|^ct(pFBd5QxOQF9PkS!Vn{HRpFq&LQiA_*7oWZ=NNUTDK(L`YGl>; z2Ewq9z-5K_ma7!eVfHNrzn3tJ1a?c(FDVF2)V+ipRtQ9;{vv8Z!8TF#e;F&}B*@8; zKr}aZ3?{Hojd`zVcd3%V!)bjDh)5>zt zC269CQ(-tr;5P;LlyX+L-2a=6hu@(yhV4$`i@^IJ#Pi1~YnKspgpk(dBq&(yDwGG) z7_3Rca8#|n>r_B^1z|YxnUaCu+wsL0h8_Zw3h7bcskR6j&r^4t;vv}P`-pICuFW4K zWZ!c6q4FI%SQ;Y%#T6fok;Ok4;L8ZP9HaDHci!>_Y$L-5EwO~O6_W(6DR5k;Qma49 zxc9-B(^k>KJErL{3=`;GIv#e#q*9mbQ13B{mm7Rn6^4@p`f6)dA&S6e<}+@xS*}v9 zZo6rth#R*s4~4hEF6sMk!LHs5pR2%BW6om<%rgrQH|HDYA{eK-&5r$Sn~v-3Ph7_e z&6~Pgw$b$F+4)1s>ao4+NLLu1RHC!?7X>^i@_APgjG+b z9j`;#6M~;ISQz}GF%bszxyII&C3=ZZ5O{TodWWoOyc%WZy*JlM2Twk&8E@}j%7|&qcv^Ugut_YDO}O4uwry&ez7D}gPs(+gkt?C8ln7{ZHIUZv}2&x*5^8Zu{>xSTcZ$H&xXD&BaO3%_t8 z75~lAj3&JH!=!qE&G<5r(7^&o;f1j=!4;=ymcZ)RK%#vB8v#2Wue5F?Wp`{~p(d&F zXv!+vS=wi?^K}!`gO~sO7CHoP;srUI3BhH|W3@O#@D5J19ty#G^ZrG^iw3m}8jgc^ zcWJy1bzlcz58#D-7`DM`Sc9VwjvDwlB8;QBzE&7F;dq@eUXSAq!nhg78-?*E9N!|0 zH{-YkwxF#Jw7C^-#h=@7bO5~}_&fR~w2p7O{R_DBI`?M>{$$<(G(#KyZ1SXFC)|aj z2;2?3sv7pp)395j;W*dOz;W%cN5HW;&+=Xg?u>xDhx^SuX7+qsrvx`8;P%6PQhWDH zaL>=fJs{wGh8~pQuFS(dEZ}@UACcfb6mVT|NWl5_4oh&K3b_4?;2xFWz7}xZi{$T^ z1ow@A>xH=BC#IvCzdi}>djZ!U0QZxCOTd6&&*$a1#NMw0Zg3HMLlWGd0`3IJ^Zxik z9R6ER8^+Ia9D$U&J<=rL(l8>8PiAkcfE$G|0q575BtFt6;GTeS^!OC_`!s(7%hnK`cP7*4St^%dvfb;ua5?{l(fOEiA#uWuzd67Dk*|P=Q`2c=i5OC8lBlT0p%S8cKfoG*SnV**g z+;ahN9|*V$>V4GkiGUjnVDEDQ*B=0PO~5@5F9^IW*?$e+3b+>o*!xky^#;KGBH%8< zOM;*N^Gufa-v!*u@QQ$2^0|wPZK#-W5P?_WH7QPFZ{6h31Db~X-4Q|J#+It>(@{@7gfs;MeL0O87nmV`)Lj&~37gxQ(Z%&bLt zoW4P?Dz#F%M1nWy8}Jf{v%866u$3KdxZ+~hyR+YX^PO|%c)k~}|M?F9eu8cj8VtJ5 z#=TTX-P;pm(Hkm}VDGW?y<2JK_ub{qT&drch;d|8g0=~B43N$f`zep|puMAFf)^-@oZI}d` zaGJr=5%(=?jcvg)Yn^_eEjpvdnDE%7nN-5lGCZ?ps4#Uu^Jsp1ggn7m2}__%#E-=; z^3^h)F2%FT6N8Rx<9RB4JmQ}4_#`9slX%KTx5!4fkkLJwUGd8_GuHF+n>0KYy5Jik zKU5dZ_tQ+tSbFaA3@xdp_-!70V|kUU&Kj4F=Q_bhQq$6p=nFlIT=_|Km*35uFTN0p z3tecfh$kqc`5XHlXXxPGaKZh4hCz_6Q4!X3IFmFXn7;P7TSPsTm`SEE)WGQ78lnKm zZDmAVWFeTFCa0ZNqbCToF%nkLrmM?RDDH+a3Tb~FpYt$OwL@#Dfw!AdSkOU7{{_)}P$PWc^I)qyhUL>jVNLtp z8>6){se=VIS5PW~Kq1RTum~${h~QHOXFG!<$52gPFC4|vfX>a$JRPFlE|S4uWnf}* zCQ8JvTYaEgAL^wxkDjW%e9F3?E3wA&}>2_X6x79XxG z{SBWyD{*J&Ud#emhO=~US19-lKBqSZU%;2dbM63jzC;w}eUk0M3^ts>)_{xfHE~Ys o;WHTaW-!dbDk*5dCAdt#0N>IT5hH^u&>@vS(t8p48eQMN0qWQ9`Tzg` diff --git a/blade-kit/bin/src/main/java/blade/kit/Emptys.class b/blade-kit/bin/src/main/java/blade/kit/Emptys.class deleted file mode 100644 index af9f792daccbedc2fcc3f407671f74fb97b9e1b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3905 zcmeHKTXWk)6h3m&$Wq)UO(;!DThve>DPVIcwm97H1DZp*cG4}NOWHi$>1Xzg<#Aj!ln$dH;0H-f-R<#zHTovHn zq+8up>#g{7xv5p1fOe^e21eR7y|z0Rmuc=#w6p&Bbkwf7PIs!kqUpuR@|B5pJ`kUc z+AFq8LhVaj0QdR)u)kPtTysFK zsg--gBWA!{u*}&dUDwoNZEEOr;>Yn&TnYNIsuVRt z#jlTecQItQ4z*%g-P5%lwT{vAGS}w#R&sB|ITJVBEW3^$5GOb$_K;=);|0(mTb5%5 z+XBq2ZyXCSTXs8CggrcA(;ZYj&-JpfFJx~WIUe<0`;vAP)9nu|n*^5YCi{!Kl#dxHA7-R{ zC?h|e&Fx$L0p{@rMKIp<4WSZ)gUtr||r>zM)vY zGIToh%yMw)GaSJ-8QMXVomUQqeh`izOCe6El^c$jl%+7Oy+nr+xC&8%s{u_#Vd*Ww zOd8H8&m~w&#|oo8!B7ecI~@sT(r|bVOfZy+G)aXC#?taeIWfUnIu?)61XHOj zXIsC83KLF^en~yg>Lk%p9j;WaNJUDsoD935`@yXn1edhW$46 z8lf}7>clmPeLUK}QRi&XvwQ&*?bS~ato&rd9eO6MSfQ5ms+A z_=tM|t8fG6u(b*zWEn~zGn|JU!<%r6;Q}l&ybVhXm*F*rci?q~cVUI$D%@lE2Ha=( z03I@Y6BLGzV2$Bh@R;G-@D9UwVI5U%U^@d(P|thtKI{Jg@(c^`A;XX0V}_sL6ExKQ zDSXE8bNGVcm+*|?CTubM3bq-34d0;sBDOP7!j^!sr{ez#_B=&zU`Y$|pRjwfRQ(;k z{hRS>_rN9v6h2c5?XJaE6uj#IiY;mzjT)oGMDC5PM5siAiJ5MPc3^Lroh9%zK8A@V z`rn5#p502nks%y0trwwkHOd`l-#x84eIu(Xj z#PFtQ!{Hva9Yrmsj22ah=ld>3){94Rih(%Az>Q+py3H>v*O7{bYaTazDbxWqm>saz zIsNOSu9Yp<6oydL^Ia~{XVgXdhH@lrtC=rQ;Zfgi@NHqE1KYTQede307hR-P-&4T~ zqA0TikK4pOl)BbFfe25iawwzfz~yHSs&dc6BUltojuG^W)a%-DSY2D%H@F*~`O!@4 zzO97C*$D1;-!IS`ZabKhU}F&;4bmYCmokunaRTG{ z{%jRwooogFs<*yX=d#8ykpyYYF_^i@qzJ}`lS$PQ9)an~v6&Nd;0U)3%w+_gM{FA5 zM*mbAZW8h=M#hVENd^ZR>Z>67G>SXit=ycTSL9cfNL-eBREQhqco0nIEVdVoXfx{ zw&%lYa0q(<`gh2F9J}xpF8&Ph6W9jU06DmfZKjQaD{vJ@8nRtKWSGVM5;)gpxDmmS z4;ccC2DjjLk6m|X8euorvD0A+rX%g{MA*IS*l95HpZ)Gd*nR5QC7^)bCSVpG;x~yq G-~R(WRCbvF diff --git a/blade-kit/bin/src/main/java/blade/kit/ExceptionKit.class b/blade-kit/bin/src/main/java/blade/kit/ExceptionKit.class deleted file mode 100644 index 5f62a031ba9c20fd40119f8018303906dd25958e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9351 zcmeHN-FFj36u(mn*@Ob+OF>b#h?r1mP(GBVR-qO_Qob6fl&9@x+73;2b7m(6x1F6P(`KTnEeHFM?r!eycR%LNow<|!<*#SY0pL75 z%s?N3lM(leb&mzbN8V$vI9Kzkw7A4Xaq@{z8-j(w4JIsCmIc@z&fU>I(w9 z##q3_IDsAc!hHh$6JeERAWL9hDm%$}$Q{^C_MW;Ia2kcR$F%DDVZFg>p5%8MJe;f1 zdNk_hvXw>ZR;gd}I0`j9f5}^*?upo{5wz-rTMcRC2BC24p70l4f%5c81Fg~J(WepV z(}*-5GuN$uQ;%E{oh|P^I%Mz$nh+H+bzeYeJVEai^M*kl&z`>jg6G39&|*%T5c~1_FTR^p~ zRR&A6+QYC}eN$1d#d7v8Per?v`NdHEv?O5?b4$cS==^kUHYip-b~NSG=b?oP=zKGaL~rA6Us#b^OXk3VJp-^4 z_7XUpFQ=VkVpd6Zn)|S_(woit9OV_c5hZY-9Qt1EzQ>uoUwPOs7Fk5#RN1DKhM7HL4Bke_Y0;Gy;?*$ALf4!lC(Pm31UYE-xNew4s&El>^|CGfR{d9VjQW|eAz@2*qbk_>KhN_n*_eM@JE3GkA;s`$!Z&j zZJyNo{g87!Ntza`{ScOpe7SY_N`>}E4!lj^SBrSIlJz!qQp^8sCr7~Xy=FwKSC$DJ z*C&Wp`{JEpsW3|*JIxjXPc%7Br!yN#j}2?7IgVHdh6%Ad8GPwmO9BH6RNM_iF(Jo> zz!5#v1ue1;6bbxfk&m`h*H*4~T^A-5IvYEROZdUHo=P>iUc2p2$FwMnmmD}x;9HA0 z^v-VEGY|rYbn9meS!f}aH9h14h zj}ch52ze`YhbSne8_N+mn=dQbQhN<v8)-2Rk1g{&`~UGn zRX+_>Nw9Ikba}>votBVCw~GB1kGo|8IrS*Yz^7Q0)x85(3AtpE7`8KAF?VpS=W<(e zc0k}*9P-v#xDt5>t`l;+m(kr4FT2dcF2xD#!97B{>uuSp7PLCKa(Ljt6d^|~!rIfu zCn2*sCh0=d`a~sbEs67eI&5;EUS;x7Wxtwg_!2<;V|oVe;P3o$r;>qbd?%nadoyqk zYlNEd8JJn~GC*9+Gw@)|+XRWrxVfETQG`Dp%N0NB9|C->0AEx97{sfcunRvk@rw&P z@CqRJBRCHZ4rH#wYdjv;lud!@mn>jCw~5xT=Ob3-2kt z?<>8j-RBJW#v1$ug}_H4orb@RdC><~ zFy8&Be?l>&o=+MWo@or9t&>^T47lGk+~;t^=yBPA`(5Gs;AWf~w_q0k52C#ja2xJI K1@2>>eDOCxW4*8d diff --git a/blade-kit/bin/src/main/java/blade/kit/FileKit$FileNameAndExtension.class b/blade-kit/bin/src/main/java/blade/kit/FileKit$FileNameAndExtension.class deleted file mode 100644 index 1a918a27b1a256a1dea456b3e095eea40fd24fcd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5046 zcmeHL&rcIU6n;|*ZI^1Xg1=B15EU-%g?Lb7LI@^}6$}&-y-jzAc3^k5&Q2@*Lms?% zG|@!w{uTZu#y49kkQNw7LqI%qcW36C?|tv>?C$jY`TOg40GNZvDM%2Qi-x{dl}P1#@=_vE04cZGI6nLZ#cOh_HwJ%M6oTTUEpw zXIbH<7QR*Bz5?T=(KBrO>FY5>bx2wKFgTg>2wGby_d~ULf%SvOszm(?X2D|tId77! z^jLu`k}oYUZo9k@e*wB*?E4r0ML}9srhg!d8e0Xk;IV-8E7Y0tlzgApnE!_9y7gi_ z`4p>^tUza@_g{))RaPs|DXL<{`yX^JcQ+UIw&2T5b0v@2QXP(RGKY_~zsfD9g!w<# z&u!`Po5_o^3%JBO9Tp9RYqM)H)(C;onb~g3A`Q0*Odjn?pd~>di(G%b6?9Q_*nT+>7++~h zEdpMWEfERKX5JVSv8#dNo$_*vD37;=UVjb034jwHa=8GYo$0$#CZc z44-;3j3Yw=?qY1C^q$dxzd6kNXg!~MunoX{oST3NpfL|Yj!Afcb$W#DB(|pi01o7J A-v9sr diff --git a/blade-kit/bin/src/main/java/blade/kit/FileKit.class b/blade-kit/bin/src/main/java/blade/kit/FileKit.class deleted file mode 100644 index 0e745e1fb150cce08768d476c93e34cbce00d1cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12692 zcmeHMU2q#$6+SD;mgG2&V>=-YwB4jlYK2CIB+xbqDYh&V)rxHN`SGFzQbvN^8AG>hMYrb^ZH+`x#c7nP z6f%pm#q3mWUV@=~KvS|!RbM%ifPM)gV`CEZl=9=H^9k64Y&h(5h7LWY!kK}I@yv91 z_Av=|Wh%vDwoqQ2%oP)`AHit}`YW@G`RrUa@6O(VD$+PToSiRc3#A;IUCPdm7styp zMM{oK1C>Hn2r3A<*X_H2CaT%kv*fhzqx^Wye zS+!NtAhXVRRJlXL-q$k{^qy69)jlUdbTl<5K`dj`NgVEzU{4UEtZ5o%0#eeR zKUZ{T=C!G*wNpRYRAXrm>`vhILx*OO{uOY;QJ+ObOC-uhQjJ)3~Ofgj`c} z-LT~)B5(1e<(w_6maOV^)x;guHgRd0m_)Ckl4a9q;P~nquGQsqO;apOraoG(qB_AT zy3|x^SCkbZA9fNajfrzut{cRXsk(+@*H&d44I>*()WOPQ+NEjQr5$qvw9BtHnuck+ zuBZmb{CBgMPHdrw2+IjZc+FNdA;mi?=%fZ$t$T-XmSo$I73VPYC2vKcN-@6^R?{1L zCwPQHv{T9icmzalHIs$x5fTz`J~xxysF9}g1Zch3+2p@nB!wcgb3y_!7E&g_BOtO< zs@_qaoTiZ#MZ_QNpL9Nrm;ht5Vk?<6YSlL<}r=Vr1Er#O_@^?WVUZP z(2hgf%)_n@*-$O)7IA&5Cg4E{rrIkKxlypaGU}S2LSA%kvORD6;!J}3IJ?2wpDMPZ zRBO^{r5NTW##Xi5*bZqJ0bD4pEn{Eab?f031Y=60=}KWD;7NAB&teBnr>POBbwqpXL?bqmCEYKM#2~id><4f2|T(b!+-X%E7i+pQd#^I9^jPOdi1T0BV7TAT3>wo^~ ztEO75L(_csE@Dg5xMsQD?e(WCy1L=c1(7Hc+DKjZBC*?-b>&i=$W*I*_5G-nY|Jc| zaGNlw@zI4$uA0gvK*Ph{Ha3_ym}>04Oehwq&tTK|L5>lv{&Pce1UXBa7WStnNt2*` zI$y)T~4!EvS(_LQ@qyAcQ6t~PH7kg|4@(+s{6TB92tAR5C!$~m)$G!kHST{1x#T|G= zH#9?Ebx=|F4miScJ8M`awb+7JbxB>(72I;nrO_75*<ZkwkEuQn11z(Kibe))v8w4Mx-;m%`n=0{MNdPALvOkqi{kLZ(3?hg zpV8Iz5aXiF~ zhv5zwVdVGW_&v<{0LmX^<_c3G2cPBF*#_?SY{%#x}g2QNQ1#P?s?#0g|I68&i zNcg|+Z8-Yq(CE+M*smRbj^iiw4)8CHpZ%^BjKK$Rl!On$37nw}$3hGzISf^YA>!aZ z1Rv(&9^l}N5bhx^?lcFt8N!`qaMT9ZQ=Y!38Qe!Yu=9-&PTbD77~HuI^!+r16W8}k z2KO+0lp7abJbxF$jdO9lc>dMLJqHtz;o>;@q-Y2?$;EN>Nuvxd+kw965KdfQ)5j%Y z3O>fz8JsAdoiBuN=NVj(pS-xd#^7@B2;Mr=n9ni9=Q$^_(0VeYABPxbyI}Yk!|-t^ zcERv_hM|O6-?5-EmobXAH zJP^W(`!^B7UF61vlbMl67~DLF+c_V?iN|x9!9Ci6K0AaH*T@y@_1y;E`7xU{F&dx=Hx~UITxXkPvtz6yu z=SpkNMBnx`C!qm4SM#Htp z#Vw9K&fu&LaL+I}y93J}!YfB5vnD zd|VPX#BYtBpmw7;;mqlo3+WTi)E*^-6ZWr1V{n@t`1cZnyWRngt=S*PIxRR+!4r#< zFFk)^^nI!W99xrpT0CER-CvjVc1Xe#;x%;d0mjZJ#D9zSvX$7AsITMdv-bp}`7>QH zuvOMm@L8@6!F|c8UwaFT4Nt-6xD3I)z+)(e7@qEefjvPt;PYGt+*a>-!?WQMW5W%2 zhRYCSE02LajW@cABnjE@EZ2tZBdLZMy4j0Hh@stHaGu<~S3?ZXalHs?1|Gv&h~W!e zFkJT;67W29rZ(e1Xz64+9dJ~*59>Y%iG6h4iFy@UipE^54Wh$g!+?vjKgQeq7!NtBp)nK&n(%cwt>Ndt+nJ~=hAcf>vQXKPM`hr@1K7IfKe!? zpohSPz}Jd4Go9ipTW7_Z#dKa=GevQh1%|0VG(`$}2@FPGE#}mVk87)36FBr>YPz&k zsXi}N7G_HmQ&j>(l_uGu@J*+FkHCpZ*9io3#4@u&o`wv8aaPlGzEU^L)iuj@T<(`(mnjNZI;d+g2#f!=^w$U>S~ zp22DyAA1At1-O`PI+F7Wck03*K*|LA>LK%W{MdKjbWAZ$;H6xC8K+FTI#0nF0s~F9 zr+nY_({PRqe7EHIJaDabu2apmJ=0>sbRFvXZq4F$aF=E?RfAKVYZmj7$Ya_Xt8+RW zDY1Y`9HzR<1M0Yf+DvE$6-duFJk(z+J({2(O;C_*6q>VReAD(^U(o1VC`^lL%#nyS zPPh0w48qucip8jKDWhW3l zY)9z0Fx}`B9pXy3d0-cE;!-C;EyE!UM1v>VMb&xD~! zMn}P|OS5nyA38GX_Bw9gxge32502;LMO9R?NT469lq#E|#&gid}L7XL3q$vWsr$ zYkb<2dOZ1}HygFSQ!s^`O8!$Yv+X~J*i;1i=i_E=70&?yTmWq4<9``_a2}4~6}<)D zdLWIzEWXR<?H}RI76d8N{t@14LFnB#!dE~eeYQ(6tkA=kNZN`zZ*J2AqD5@8JPv>-J7LB+$265%e~YeCpuimC!31NY(m2ErBGSxtW!SLi{H j5F`zO524hua&t$jcy|;l_rL_=^uQ#{;=K=_9>DZJrT^0= diff --git a/blade-kit/bin/src/main/java/blade/kit/IOKit.class b/blade-kit/bin/src/main/java/blade/kit/IOKit.class deleted file mode 100644 index 5fe171865bcc00cc70a4928aaf8c7c38d69b811d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10601 zcmeHN+f&?B82=8?X4wLzS8J~+R$ZzEtMyju1?X;Y1;NlZ>?sh8@D z5B>pt@XZ$=^bhEaozZc8(iz`<_0>1WN3UO!Wj85j$q6p%j4}i4Cg1lv-~D{&OTPX6 z^DhA46ud7%8-YWvqYYM7-5k8GE~|rchFYP6OFA1Ymd11@K?i}};Eti13xlP(>r`U| zdX(bD{A@XYX?S9IvNSs8xwm>k^GEm>1dA8(GztJ3{X z_FpiFNtuxE|1mnj*fa&{Jf<5-3J0meB?_wr=a$SYS(Vv}O|zXL(G^E$)M*{*C9G3S z2vnR>NS$KUHgrvAvg_HtLVj^{JdIh799Gy|zpT5mXIALEZqmwtJnp&7uSWr!u_Ei{ zvb98I74vB^j<9O11Tz&)+hZs!RjWyqrTk5e+CfEKThcb)OF|Yc=mu?>9wXlTJjH!t zg5qYF6mO}BeKCblL#0PN-AI-|$UsG5FHU$S)2lR{)5RoBWh-%s(;G`n+@^-jc5X`g zc(#q5f_p`EOl+Xsgm^BfE*n{4bl7p!m6FFq^Le9u;wq;QM%>Bb%L`TX4J|B`x)DKz z=!J+{tdl^wOyNWyEd_ZB(;Eg|P>nKEnQ%Q4P_1cRM>n(4Mb&YebaDb~G-r=4lEP{! zjVz?&=6XU%1OZbD;WW3mU_&GzNb@x|=+hMT7v8=%1M`}03z(;DX-nLMiCU*jon`6> zk{WpY#-4cnu5)Ta!RdmDr2d(IecDmOa;b_#fdo2XBW7`2v8M~VVK0F_xwS(Oe|oW9 z!5;piSDmBIq`$U5EwMD!m{uL#|6aS;!4`Fwz!7ELi42ZaGRz87g22(764`Es`qv6T zAY1R`TnUa4*cMSP14jw`BrrY^%E5>zt+Matocsvv&nbRH^DLHuV}yLwDw_!8O~fAw zW=qvSry};n6lz4mK=_OObF?6cYoG35LSV0h=eL4mRpXWjvL=2B!yu;DPzG{@>=TXw zF>}P%OmMZhSz?kWpr)tg0A{gc5bICkTApQaeUh;5c_fsfiPMUnc_l?o%f`whZ-8XW$fpUs|e2 zi;qN+NE9lBDe3WXM@|WWhm=*bpnsnwa7Vx_LL#-+A_TVF@CUA#?YWte+IESK#17;) z0f_}Rz7(P8qop7hub##9M@)QZmYW$34YIc3@?#wzTz$|Q6NLpkAy1p1OR!Y$Zpd1r z3(|3zkn^n(vH9xJT9U$fDSa(uqD>Bn6P(t6y#P5&;4=a13#lfMXhJy6{fJR?ths{G zs5(dB-ruNKbCEX|dKtiH)nn@`;6F?jjwS-f`8y(~Zd_P%oLk)|l)8zLrc3kBu$MiZ zG6Q$quAEXkod;=MB5*EQexdWcU-y;ppdLWuQ~p9Sw8+Um=oq7efB=7rfFgh|JU_s< z4p4p?&JcnXULlZB^L*#7vaDZp@erR=Vxxy(i5UXp$x6idlGf?TDfO{Mu*T~Iipgu# zd6MuC*839v_@Hcgjz;||gR_L-t&rgD2MIKM46MYy7 zmi#G1;{l`uRSe|l4k3YsFM)(jj|6Yx%wyFn65x!aD;hi!ct{(@odh?~?P0mA9m*uY zEa{F}T!OcdBkYzWcn3wUC4>aGW3Rh}K)Bwx?z;F$W)dGpyKoX;P{H?9@b^L30$cIZ zevlx8S3B`@8)WhNw#fG`*oRlUp$93p2e00=<0pXZJ?Oowi-fT0>VQagt0n81|Eh-5)dBc zAWYX0I-wtqCm=k=K~N(ICt!e!;OiLLbdZBkjUb$aCle5!;vlR<5Kh3;2?)<{5N<~h zo`dJnbACMdK5WQ-n#1>DjPFc@&yT}U=NCA9cVc`mars{6@O>2H8{zVea`--p@#VRE z1rFb*5x$d&-aXGjxEn*b!1YbTRy>5SV+dm#K=>wxkQ5(08NQ1kC@>zeUn9paa3yP3&52c(ygQMJ^*AD-XA%qRed3484okr*Qk|I$wz+ zo6Hc33zeiYBOU-bm9{lfbw_x@t>%K;{SckXD{I3xnq4358orB>c!v`^XpoCFA4t1B zw99)ghN+T_!4lXj7skQpuA=}@jqTEjwJS{(MM3|AO@$kDNKDRg+vQ?@J*D}xG!xQ4=S zh76`_Bcfp79F;{>f}51(_VHpV!z^Rp&nnK}$j>0ie9b4nWOJ0(U@hc;|6i3zifHTD zxcE{gCFZ2(dwNcmV4jL*Sg9qrbL{ZXq{*PVBBO}Tg>`EG5zGVK0_Z{k^kh`%K;CzPi+bQQGRKL=w02A~~FaVSE1*m2yxCB!)s=#HKK45r|G9EI_j9|E*G89s~ rt8k6juhV;x>~Ew#Bn-(X^WoMAhDS#X1-MPf0?ff(`Yn?sCzgd@?l9_g diff --git a/blade-kit/bin/src/main/java/blade/kit/MailKit.class b/blade-kit/bin/src/main/java/blade/kit/MailKit.class deleted file mode 100644 index 788e13791d5049e67ab3bc50ec0787acff772a1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10335 zcmeHN-Ba9D6hD^&n=G_cYSn7Bfm(%DcP*{h0;OH~mgO@GwbT|b*~@ZEHrXawro21j z@aVHM{s%rgqcb{v?H}N~Grs%ogX6hb$cEXl8zC^PvoA?*&iS2la?ZKue&oLT=jUGm z;5N`0G!eLBTUs(txsiNEw`g)rr&*TVP04jOrXuqJB7sa=LyZs6Odf|&Hh^wv=eA| zY1rCF?CY1H!z1?fmx!{9RHtTB5_F;_7ix2ZmdJ6JJTa4+N=tB&z&V$m!%x(Ag^!F+ ztO_OqvN|?9y1Jx}EutLvc|N7859by~3A7GzgFC|n&h+#y6KEbWvn&Sh66h#@?wDnn zmIPNw$Gs)PVz#Mov8;mMSKvBzxM?T_%Usi0-X2ima%O`mS*GdKLZ$-MHffG2-LA(I z=<#kPYcg9gOh?I6N83;wl@Mkm%IK1Oo-de|qqwx9!*xZYhLE_% zls)?zjK|;}Hx9L&eK6BhzMylBJBnQ_FbgvXJC9Y=9Me)t9j>QW;kHsVvTU6jm=5bm z!Dm|39Y1$MnJLqFr zRo^5vvU;t#OL)%4gy_Gl59YR*W$|nc_s8KfbhX1J=q7Nnr*c0*EWkU`xTKja=GT~& zp}3|N8xN*N^<`>t(cXR8>}+tGKv%lPz6S15wBnj*o#zPL4NzHWMCF^_WeKhm0wLD^ zp$b;LGU4us&5SI8t37Fd_ZSRt*@^@S0)K>XnO{=<)vzOE)e3?1Av5xEu*drdc@Vd{;cT!M!z!yhXHchTVf9jvB5kNL&cmodg3kzNrdYYs4b5wL-NL zx)50`%SDw%EAzn8`Z*!_I!%*$t-o!e{?1#b#%!F^e;Zw(D{6A(cpC7=8^^yt4VE03 zs1t;|tkXn2;Q=VBei456AT%fbA*c4Xp@v;o;Zk%O*A3OhaEnP(kDaG|D`Y0UGoFApxU$wz|hK!lbJl zZr_SPTs4c9#>TnWkZKow3(w5BM>AsZ823d)g^9tFUE1D{)EKPpJ5*CLNicC6PqO4P z_ygXCF2KVlcvMHijjR5xYquf&tgn3z+vk1l*RXxT*M1%1@CLR4?{Dtj z-*WGrsN)j6jn{YFBSL5J3AuiO%a1zW`w5iaT>V$^Dy#w2@;+YMOI&abKERd?A41Qr zgzIR(_=1vz-T(;$u7oBRcLP51;l#TV?&APldLJ(7!&TS!#KY~t4fw=|YxeZr4A8gf z;bg?!!YJHE{wDa;^_2L|GQK|m|H6mA19t=U4g}!7@o+nE2ZnsO7SG;$0l4oxoQ$~p zp1lt|d&~G#0R9IbegsB6{FsNAJpJPV_#b`vNtp84U5@J)0l44y;ezuh9f14Ohns~t zpT2Tjf^dI%xE+{;`Ovt(J)DfV1vWgvvA#Bu%k%emO+4)*X6O7ONtL#=JC<1y(~wEW*yQx9eE%3Qci8|v zsa2Fwi#`rY^(2i&C@eKu$~AgO8mqI=Doyj%QeL9M&`d_WB_x`=g(LXPve@>cD|9V0 z){P*FGU@!26ZcUDB`=x0Kx-`BMKv!PFVN#{uC<8x=w5g~YqgxYe^`V4zR6`90_w## z3ebp*KO!10A9{gMpyeERJ#SWavDQOoI)9xOzeiOs)_)r`^zs;b!YXD+rWt0&T^62~ zp@$9bUxN78&>inkA-C0*i{}b+?sw_IGnTKaIL18fGQLl+`wwc5!URLFyT5RP*9zZf z(9mY`lJ5`fk%qvJwO?<@hLBr4@&b;I%gbK-4C=YZ3@}+xs>O;8GNxyQ+-GfmF72Z% zX>wgt8jGw4uR@-BMD5?2VFH+j!&7h&ju2QV|5%K=>T?E{DbFR}aB0(3ttw>kCey<8 zzx+9FJHimS)!0K7jYV(CRjyc_ZYTn`%X=bOsu$rjf%CsEhp`$a5Ui_AhrA}7I@90k z`)*x}vaE}?WH!?{_^i(;dAWAC(ffp0-jkp!sP95uy0Q&}1ef-q;F{^MvqNC2E+yBi zF*Amn0$fCWb~Px0xd8_gS5VEKqy<>|?w}&y6ZpP0VGN!-xbp}D6bKx^BN2B^z$D%Q z3Q+8}B?zz`!{0%eLfj$j-9)6r2Jc|{`TXn~nE%klEZ}_-F#xl06z>j?C^!bku_bT< zPWCa3xv?(8sR0bH2QW;)8Jsf)XW?A8rEnfwfJM9lWF~L{F5%Nv>=#kO%XpPP1J1Sh ARR910 diff --git a/blade-kit/bin/src/main/java/blade/kit/MimeParse$ParseResults.class b/blade-kit/bin/src/main/java/blade/kit/MimeParse$ParseResults.class deleted file mode 100644 index f2918471c8ec47570f2d6ca8cb2fd6de124adb6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4922 zcmeHL-EY${5I>L6uAyvWY&y~6vYl%DWk?`_ zc;$~moRgJpYGIC4#)NoCocMlsKA$glx%>A0<7WVP0P|%SAy79uY{X2+#yi$!jaJ0k zys;&0V@1ULCDVrA$nLMWNh52@FiK!DgGNkt8mp~$JhTKx?fZlim}>5l)~pt?^N2v% zq^+p5I9zwdxPsQsx~jf zB!P)t4W4PO^cYN$@rSRa=0-(b-ln076A>{hl%$DPt%%3wAq^_)o1C_J7%`2YgoRtI z!|7~hkUAPbX6TZ8(RI3#8tW*CqD;E;$p!Bb8C1M<@&cj99`3 zbNBh+-m}SdD**M9Hw@5_j6WnXUT5e9a$ztB-pz-F1FZF&nav}&i$AkfFRA}FsIYq! zW>~}wiHRCB;{lH6W$2>8eJ6I0nqlHtza zy_8WV;VeE^a}=C|^Y}*K0$fBnmv&H>aqO3NWq`E%1Ed{8?VWDdU>3&!r4zUgH}UBX LzL$`43u-?Ai??YD diff --git a/blade-kit/bin/src/main/java/blade/kit/MimeParse.class b/blade-kit/bin/src/main/java/blade/kit/MimeParse.class deleted file mode 100644 index 43e47f307dde18c9518c1959111528dad2d1b3b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5487 zcmds5Uvt|;5Z`m!ST;$M2HH~oUef|L6dT&|uQ7qt#M8{!O=;51l$Xv~I>#5wlIHG| zX+8m;fH%GeGcZHndEkKuJ`Tf5N^KP@vBZcr<;7>6_P4vYx4YWi-~RgfR{*#HUl*Z3 z;F6MNeaM7U-(&l%-nE&<>jRz&DjiY_&aAu`8i^ z_qg(Htx(vhrfZ?LX9z5eRauwPl?E)5!rFaDa^>3l+@hvC^n}f{a2@JNw`=pEx=G8W zNO5X1$8k07aymk2molnR-IPQf<~1U2SEFTh3fJ3A^$|3MDnAADdnPW02 zZHZlnXdNF^b#lvqE2OaZ0!MXQC_N>G;J0kR ztyF~h@j8iaI!?MO!DQu9%XV3kF;iBJX^u>wDAX-1#Ro?eAKw{JLGM1^Bhyy9C{4TJ zsR*1;_>Q)!Ed#C+_~CeQ>8tCbEf^J3EmsbiUVmhAFD&1Wt&W_I^haw)_yUSkv8|al)~cq3B2X^ zdV#r9G`tx|Q}N4#C@16R#HNW;1tx>$E|0Tijfg|ff8y`<0Ts@^JKz`uE+(p{Vyc`u z-ZF8=S&Z%rMd0%E)(Q);@|NpMlea|BC7&4$p2GZzbEXZ);j(EnrMN1>rv$D~9}P{k zgapn`>=oe)0=4PP;&Ud{C;nK32I@bq3W|Uuf!MGt3Tp&)gi<&Y3kF^aF5wVt28VD2 zF2ZS;#kGh}1u$?mpbRhJ&K&N%k5o7@gYqvh|6pn1Cph~!q&tVd0SaIZ&WAgIxC=+% zUQNK+G2CnLI?8?{$*rTL1t6 diff --git a/blade-kit/bin/src/main/java/blade/kit/PathKit.class b/blade-kit/bin/src/main/java/blade/kit/PathKit.class deleted file mode 100644 index e05e2ef1c9f3099c4cd1856bfc98db32b483e08d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3110 zcmd5;TTc@~6h2d`y@-M+Uhu+ziUqax_9P7nQ3&dagccHgG1KkP4(!gXv$GBSD4$I< z(RY7^zr=WE3sSO0*93_#+nvt2pYMEozWw<01ppqyqa0)ijECB-_)N&kChM?D!(&Ze z*%GF*!c6<6FgeH)7>@5eCR>%)jZN+v0)=_UdABlOU#bxparWfQc*JB!m0_JY97N?VOVr5Khk~S3& zsZ@sg%(!i8P@ZoGm{qSlmZfaVQnq1~_qDtBg&!zwXnZFWb(ysG8l3J$mlTuSq>_t_ z@X`ow_Z8}vzt0sliZW_;0$wbn5_;|jo^XYsVH9wU)y8h>$TdpSE(S`|RD?8=O}-%{ zZnXer67mLrE8oVVr3 zZ*W~_NPCummCL+!riDH4{+Tsx5fYei{=o3a)k7^iVU|lf-10twQprh9-|TcUpgdeB zWFrMFr^&vM^tspk9&YWOfmBwHS?HflJT`iF23A#McwJe%6Bz4<6UW|RYYR2elFURJ zVNyO+u$pY_+-x3h67nHMYptvQt4~K2(J`{ak+>p|6X6Qe%s+%a-sYi1VDa}&wOdr0 znTfsC0^|(>#hQw=%NK>^qru(fFa1Vi-oa`Ln`j@qx%E5yJJ7(86nt3I{5I=~v zG$A|yToQ3}&A??i0Vna4i%)qNgJRG56y9c#LC>JXP`v35;2S{kGYr2O8Tkn3zs7nO z@oB99Qtl;u4tAx``WT)Ha0RaJT9`q<`xdVCu`m@|$i#Z%K+*pMzGq-Ej^LpFjXwI- o9{pP|)z|OsK6)>D^rrtpZ~2#A24><&@4!R+&10r_p$zwb0<>|zDF6Tf diff --git a/blade-kit/bin/src/main/java/blade/kit/PatternKit.class b/blade-kit/bin/src/main/java/blade/kit/PatternKit.class deleted file mode 100644 index 5fafd5122ce49fe999fb1902e530470ad30fc2ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3571 zcmeH}%Wu;#9LIm@y7jR_$6&l4rVQu?YBh-yLrCm_G|`Q*Zj*qMn|Q6aB#vxnVqCd! z;mnycXM_Y2yYojOen|>7Xh0%ytSY5`d_O<`>^S!K>$gu|0N@VXDnQPHnv!sJ%zK zjMU{$bc>ML2E2>lDTy)t*Tu`pd?$pvcvVvq+^Ar@rE$ z{fHY^MTbXAg7aDL2|p<<@h(RfROV`l+1#Tpu1kfh1@uUJZ8R^aDsi>g!*x|yM%@OZ z?i%&5f&(RM9V2ZWI?UJD63Z62)IEnDSTM@f)~9H50mO9*fROQSG`&q8bwN3aA? z{tU&ZljV<4ImB8Hs`!jF02BBFs3a<+C$Uz7lW?jZVHV>KB1|0-p%zET#oU<;+--w9 zn}M4%xN{k}1%o@EfqPgS(P}du4DW1NX+@u4drg r8eA;{_s-z1W#HZ$+;j%+gTY}%Q?BfGxgt<$wUX8{{#y~g z(5nO{YV{og<-cTyTQE&vcA&qelvEWsMW)}s@f8oHyU#n+kzOENriJurpk&+SUig&S z)$Jaq9qzbHp-{k_kF3k-V&Z569bKdy$wTT(O+BWa9@Qw%KLzMvRvxF>h^N_z-DnK7 zQ~SaTq|!9$6Oua2kL|TN{o&nji$z+vM)r=mV6tMl6Iu5HS2#k`Fham!82wPI$k9^K z6ezVi6(NoM4&N0%#$*?Ju+1V@XQdl-BMNoggHn|FaS&6(8IyK3MOuz0R7=XJJ_z^` zLUy%}Yk`;<4s+JVmR7>=ju2Y+gGi$!XWj@&<8h4zw|h7&=1mS**EiQbIXp;mX}CW- zOQYr7U_s6>Su;k9Rh*FdvX9gCZNwh+M40f<(;q8_=-o#mrMpUc^lujS(500$GnUfV zYP^#1-*kbN(${LtIlqkX>&Vx_ek7RT%zf?gIAYra+oBV^JAC_-pmbH!rP zIohewcqq=L@h(7d*;Sk+BX%(-tKu9R4TIvwGES*+I#oDVo$!HktO(Ht8)j#~f;j@` zYpp@`odSC~uFhv$SZckDyf#adZ>o{4jU}TKb^}-4J2oRnWm+^%}<~(^) zT$&t)jk2paArk_u8uMwoZ@m?6$6=~N;C3$m4Q-)q!>*Ndx!cZ UxRZEXgNOLGp$v7n2lt`*9n}>*9smFU diff --git a/blade-kit/bin/src/main/java/blade/kit/ReflectKit.class b/blade-kit/bin/src/main/java/blade/kit/ReflectKit.class deleted file mode 100644 index 21b33cebc56bced218a8c175b4c39e6c9c3656f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10638 zcmeHN&2to05bw8y><5tq6x4`1L_QLf1O?<{V~~U-ENnt#mmpulWOkAanVnf?W&`Ne z3m2>O;MFSs0S}g1rB!7ftW zrMuX`ptpKyc6RzQgF>}xudL`!nL%HrcDr_MzJ7kXUYX)8bGo-`H?XC5+^`I9g29&I zkwpeQQ+7ko!!r!}BhAx}V><=tXWRd}VmZ2No9lW*(d=f+Fjdd6Ev4nyOQzm*Pb;Nj zeN|T)x@M{l3bj;iOGoLZxCbJ|&(go~@{g_pqfW2$hO~Pbv7C=NQtQ7LAZJO_{3erdW%UN$7{@ z$MgeDZ}}yqdrXURnfY762&ExflV`qE_|8!(V77Oqi zgKx7UiBuU#SxV7_EUbtuoFuUzNw5MO%#ei4`bQe{cxb4pE*?CdNbY^Y=$aa@pYG0$ z34*@ydcBNe4?hd=2Frax$fN)Fmzz#XV>7)}jN3bkH78Ccai12ubrdzn3MHzJ-#Lo9 z<1-Es6?B|XKkOCZI@OxJAqL34teqxSN*dd*UFxX*O>-L&H zr{j&%bRo3!R1uEcP=brz!c$VE1NcD;7ToVX#-?a+Nog ztG?fSUwb@RM(RGt?dmp)=P$VP9jW)BWw(~P)XQgcktIo#eaB)tR)A{^rqk<=uOs<5j%T48omgS1 zAI4Q7KWQqDV12tq%%}7NHa>~CwTBkInt`#v(+|U4z$-c3!ipz7_qvYnl%NdW8FBG# zcq^{yfulYk^0`AE-}YnOSxBd4Gc=8%Qq69o@u05tM{mpc?~&xez>>XLWggaW56cmG zXfnumDncG?{F~RmJlx~2)%Y*d!7#)y z&Ka(Ycbj#*;CFlW0=|8N@BZXq5Vk@uJ`F-13i$mzwiKa+pWFO*gSOxkKs6#_}S~X48U{v+!si}F4&E~im2sEL#~5+3AOLR=N!E3 zd$1AziUfa7z$?Ie#y#ga-owE2Aqj3l!0m(m0*?C<;0{P|ivn&KMnZoNg?1zS>k|A; z0e=`qrFO?8xO*FLZ-#c?lGr^e!G9d$AHi{WTd*7PbV7prT)>@z(^6bng8N3my#o^h zF5>5m1ow-8JNpE<-$GmwCSfY%=Um87l!wz2yMKiE0?fks5MK%L5l=Gwp91~@TnzD5 z34X5IKI;$hkKht42z*6$-;>}DZot(-yY|i_7#velh z3B)Tu3UQJwTO=yALFx;dD!Fm|oiE2e=X^fDet-QA0MCIIp+MlV(N4=}Lbi_B32Ti! z=JM9Du&n{tf_dUIe=2lLqg-BuGJ)kw z?3UI_mtcu3eEKLgH_AKVE_IY22#;BzBn`A0dE7TIXr(+nBR86t)(OAx1EnpE*My=DlM&yD)6~2F z0@n2dPdLI-69!!4flFg`=vbv`625wa3PVHb@_ixk^!9NDpIPYHEV@azLt~>AL{TQA z<4%Y(l$CPAIp#2_Rg_VC7Vs3*4{Z?Ifz_P(6AU_MmcQ1Toz2)L@jk~#woV-$#M%3I z`eb+fA(U45d|G(7KP@sRaazp`D{aD==YS^1)|I)#Ia8CoUgg;EjG{BEuvef2*Q&4p z*9olEdzYe&#V6!JI}+{X9@h2y&>wLHS*r>0&H>FU2p5@gB~xxTFJ>iE1S$g+YKOlSk^Zcvp^aM4xP>di0|M3b zb)r($ZD9PdH?5;oN+OlVf{o{O=J>wsdw%@<@(loZw?{{?|LZj3hRdHJPK!o4C;s<#{aIBe*ESKumv#q*1s349KgNcGbPh4fk; z@qqd|jD%!PXhkEVyOM|YIrXZ015N|(OJ)!hG5?VDIbBVCYoc$fG|=2qr5z2K^9R%+ zo*zf(Ngj`pX(o|rCT29xZ)f}>jI?nyJrkPxOeK6>PKVb0Be2*Bd7*XfFp|O-j@mfl z24ktLGqLZqp;=bz4Js^+Rls{fVPJZAf^&vtkViM^R%~5zf+)&V63L7>N0|j9Rus)JX?1zkjPnAg zlUpps{&7%8V2s9#` z3;uVo2*01^b#gwjH}Dc6f`kaDvS{v2r5BNRN4TnI$-*QJKFN z*p!dErbJ|XZ zO+=nhp^o%n(pfb2>5)d|Revx0R1W?Jd9VP>HSpj%ftC8W+)Gs5Vh7d1yEyD}v&T@V zCAv`iOztxylJ)6k$qj@h@U%0VEJa0GueZnFJie3I;_d3#`23AX%vcyIi&W+jsI`^i zWeK4_Y7XWI5L}sB7E;)I1SX56Z33AU)#6!rjlk?lG*zvY&cSt(|M`j3+$jHm zx2UIrj_{ckO45#2O`iv5krwh>ZBAR<^O;7a4)gZe9;fpTlrn-cPg{x`DwU-HvtFB8 z)aQpC1SF}Ckd`Az%TXBR6YJQ&2s%nz>ehs!9+Q#3Ca2x#{wHdo75>2JYC*>rp0Lz} z9j*~e%(4zWt2B*^qgbNC&``Gcu8;`KF0SA;3w@i^F4MKp*k}c{D3cMAvEzix7>t11 zwrZgQ_f}L8Fxe``Wwt<@O8K103jKMOcv5qU* zLO%96;Lwp3bGm1)R2PU*f06u$5k(J4B16Xrmyc4j$qi<@D5PDW-7Lkwr8G%+td+-& z8FJCNcVPO&WJw-`?MpBMLeGm$NxZ_cDSD9rSq3whgtvCyY#Jm|wD*{Bi z?_}dF!4ZRs&pRNdB--Ov8hKl z08=TA+GdX0Nw&On)!=TCa7DJ*Ikxk_>f17C$$wxOcwk-^S`T8(Ei^TMDo0(0e>|?GS4N%fi$ekSA zAn@ahX=0Zpo(&@*a52Go2vi4vv{M>-<{Leoc_{})0{)B7>FDs-DwM#(L6MIhI)TMv zJ)%TQJEt+uH^iP~Hq=-~>#?Kd{<6Dw8s|AE6Zk0wsAoy&2s|qO(0{;FV3&hCB-2W9 zyi_%FP9gvCI+2d!jL6o`DP)%_r-L^x-E_L=6!PeGc-J%Azy@IAnrCLcWOdOhSGIUwy8fQOsT!-TW@0B$Di zqI>bq9}ci9_1KjXb`cW)Zg;!K?iQl-5$aFCf;({(?}`2G0sG$Rv9Ao=_u~O}caQBR d;S;yxr#SJ%NYTUR`1ulXTSj>bWBCde{{|8s$&vs7 diff --git a/blade-kit/bin/src/main/java/blade/kit/StreamKit$SynchronizedOutputStream.class b/blade-kit/bin/src/main/java/blade/kit/StreamKit$SynchronizedOutputStream.class deleted file mode 100644 index 487220b4f266f874d8bfe28629d76b7f18512250..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5550 zcmeHL*=`dt6uk~fvoz3!rR#x}xR&V*N z&FdS&)>o|NtoumV*_AEnb+nS=9d9p(HVAF6FArG)oxZ*fnzGf_lag4 zyFei8D{q6qWb@Av*f+8$q_B4hOjLd!R(*~GmsFeQ;W&Y@UqkO}t#kp#$oTtbQgfsH zH@r@;mFZm3k2cA51$ z)FPg5253$kkFKgYSJj*vwO^xq{GuBuZE4ge6!n;Nd@W9YYIg)X;0}paM8ApuM^K|1 z_`(yGnlRuR7rZo9hn`iM_TsNnrNYoqw)vWnxO&&H2kR{KZ5&;rk3(Z!527fOZn^h} zW0a+0LvDwAf??Du%BbB6c&QkV_CC9|)iKSpw;2cYr8yatDAPVuSEFBINpknxlPVQmXChzlKn%{nklL z1>EoYr{8+gBL~=Z27soQe}qhRHcEerIzpy7YYx>*OTIFk;f1x&XKa9g8w46%-G?Ij zzy*5=$}mxeB1{rEU5RBodf)T~m(mz(;;rjR*llsW>L%T#MU=<<=S&ON{_$tlc7!3Y z*xY-P29ql@f8>%eusd z?7p-J>m{EV!_k~7fvbHzO5p6@6JNKHGag>pd@PK?Q|KyQh7C|a z#WBm4!CwwWqFNpbSmyC5LJ9jvu{MXO43?!&P<}ai;scC-!Bz%N;(G)!0ON29-{q)Y zg41vYTaIBW#^59k#(>7bIh1oAM`n@fLV`Azc50KEO3=n}UD*TIrN3~|M6T?%jY)dV zBywGa=|nE)*Pg$UxT=XEpm6vyABX}!A*O}`2KbkY`f3uH?hpma;22~AnDX`o5JQobDTByqcIFSfTd zNSwGLaVi&1NSwHGKq?Y&-~<;=T(}@4I3R9_BZxP4x}M3t*xnE+>W8XEw&%@n{_oAa znYZ@$|K9!@0EXbY23-vLJ=ZMO4a+WGGj15gnVM1M#p{+|ob+98)W+*$*47x|0D%T*(pf|ETDQ0^s2)>-FAGvZusWB z?xQ`w*+4b2JvuZf92yid2BY2~->Nqp*VltK%h6547Q7j*-%>dwDup*Ks{(l;k z>y4UaTE6Zz8{EYOZ+pJmG=0a_!}Q4)bj#D5c9qXsHm=@TY{6@zS@UJd_#fYg4?{@v^x1RKt9qc+Cn5G~9fn}=ND18<6z%os(xu#JXsW~1u@CR$c zG1fuCbz&O)@?Mjn@3~~pK?WY`f%UM7!H#?-dSwxw=_T<>qql;;y3RH0Gu)jLlg?mk z#W9WAMZ>kk{o=!Jf8O#K9H=C|N+~huvK$8c@)fBNELG$+5R9B_{q*uQc$mRPDgGIF zgu$mNUZ+SytlpZDgv3J`?2q%ZECReOUkOk4QY9<{(D@APW$?(pTWVT_=I8H60OD7a(kS?uPLIID(hBtrKL(?F=84+WzPwG z4d^#sYl z5Q9pxT$vG{!win()iI|M>H*ZhUe^daVxLvkcKlCg@|ZhZ;H~M z!6uY+r^pYE;nx_HlT)eHCn=9|lTOn$xzLM);o=WJvIQTj81$5Fo4X@5!}B;+e(27L z#G>-xJ@Fa8xa0Gsh2Ku>4|TVN~RWnmj^N2?up-Hk0f1J+?2p$ngc ztUiJ@6tIMiAnYOuLgn&=(+XiXNr*J;Av9c82>VDvq=6!Eg|MF_bjNz}zCzFw2$Y6f z3Zb7QL~$4(;_#V5I7kvAFDSz23gHk*h%`J(Xt=Eq@+2YBKoP!G2nCW5X*f)1_)#G| zK@uVj6yYa@@FYoyGz=0Nepd)bNJ6B6BK#>4o`R#8lOnrCMn>6vtbJtGrSyAR>K7@d z`fZZ>Jp<2@ildPU#ca1iI8G8G4HTiE5S}9mQ6^J_;|k%#3J7NvLWv~AdvQS_oFobH zk(^Zs&y$3B4ZcJ;1uu|Uo}p|S$PZwg_2 z1%y8&!a10bcE@NHyh`k<|Frt8gY&o#cflk~iHZOT7x4cjyt;<>eXtQO!!*1OZ(~p?zwl)hfS>?EzW_&$rG^ukvD}uIiU~k3a$F!lAfFl8G7`(L4ZvIhy88MA=#3Y$+2nA( zF+C3%akgi;uwgKX`VT*!XFyLpn~dd?0XPC#iy9LRhJ!>hoirzp#&LhsjkKNm$S@j_b9O1?@hskj!ohzzG6$Z?7|L62Ft#Y$h9klW@p1P1OYO=L+$7 zGM5WL6bZdvEHYh3DMPVTI++N-DL9@GC7G3QZK;s}pijDWLrc~0huCm#EQ#{Y5Fm(i zF-70WP-b^JvnDkhfHQF@t7S>SZ}ehvV*t*C*sYgt`8LqA^{Scd$~p zs8(x|EEA{+|lD=b`MMOoC4sU{Y;iDec(-b(F0Ozq>tC6(!6MK!`z z(I{5J2J*9AHOy+tj~k=U+!%eP8GTK(EnlkERLuxmze#GiC@QABaTcDkuAL2)Ra`L| zY?tx!GS&@Ab|rC!v117Td-vF7krRusp@zkoQ{en>Z;(cR=H zb{`}?rc5>zE{t&6J5f}JT*Io-;6eiju}`(l2Fo%bl*uN6fCe!KyBA_zHc}JAby*hR zB%U|h9W1~(9L9FOX!{g4Ik34_MQ55{F;gjjZ5YF#$&xcf4I4HVds4xMQOKOltG2X>9fdn%*gIKmOci((3!cMgmS zi}HfblYq8h=wouNB4VGgG0I{02dy}yK`Qks)1)HmYMp4X1u>7NI1thpH-1EsV-?9@ zx-D|Hp%!X2rrAqIDy?FR&Za^|u_hU!EbT_!y>+F9#Ksi)HK6YlYc^`mgr-*GVwK4@ z&5J>t8#ce8<|^2YGSjF%+j7wy_67|#rA)(+ilX;>%oQkQzKC_vb!PUdL$WGPBV;H# zgdJN$O{jIN((o)vM6rPwG}J*=m6?dmOCHl^Gpl;b%t$bKNY$`u_L41WpOGs$o(RBo zu4<2)Qx^Ny)CO$Cw$Mwly5jG471QhEx`FLkUc~qt&BSI!rKDEv@@%>y#b;d*;m@1q z*dpQ;5tRq5gvC;imKkcif~8+?6o1?R#R@BKOX*3aEK7RD+8_-UT!IBoGs7^!zDPWZ zRs2KvYT%$%95<33q68~SRZ+IxVY|j&*i-};MAmTvhIXLi@HNAbBwNbo+vIvSIi_lI zX==K`mBVhYgz4a}#6>w(0;6baz;_ag^%i3}ufDWzBChcPGX!egEXck{!rVpOT9Y($ z-6CacUzr@Zi+W_Hlnsmk_xMB+jkFq^G{dShTy7}2tH^3*ms|J4T>>0aQ1p7uY(KM7 zQYoq>bfCjx3uwf4a1tYeJ^Pv|35Qk*2wAz%*vfv5)nuziuH%%Bc0aVwa6J>W->Bf( zjoQ&m7)YjIX%pZuu~w5Ov&?MU?_eX?5=S=`&2nIm=U^?fQX-~lBBB>Z(s5OmF;=+# zmHe0nb5dCmjk<>N&!qeV?dGnUM#j--u~fzSUP?>4k#99({eS8kZVE0cIt$9HSmkWB z_NoOKr3+Zuz5q8f+?Z^lf(MqYdO2mEL1l9Ua}8<@71tmx?vM!yUonx>*SA$QUxl@9 z<;F45?k=v(QzB_I?ru$AGmu|FBsX-evV{!f^DBAY#Afb6#x^b`I^$+!(68|OkC!HeIRY#$S{?#rd#VDR^#}_6JIdm z4ZX*j!K*Cqh8^dxA<9vH{xrNRIK1sEP4N}sJ#ea=t#0gzcC70y5^gCj+(bdQHcts| zthunEgTmU)<_Zes)Vfw=<}rttEqm?w*9q&@u^*nnGrVb@AO3_FuBol;hd)nIxOx2W z9Ns0&T=BzS%@HPmAO6oiL&n5I~qz4HdM>;|1 zB>HKH&}(2T`Zxva@N>QOf0|i10toGe^rm^kcfrVgmj843X+{Ik%X$3lwYi`Gqeul| z3^q0-EW!9SC2ZnI7_lUDA#M+x4;Q$`?CGd6Yx@Z$G0!7=yxgjobP0cE1EW4;I>f@9#?P9Z{Y z6%TgCT5#_5Z6r9!gTC!8IQROlAh@j_^xf2gbFXhN!EN)P??4OAy}suhTmTrzBwx%E zV%q%dn(N?#Pz8nHI_7oP7{RF?aJ0VEV7qI57ZH7$2i#Qzr-JTU-^~PPxUVl=4-;J7 z1MUTa+uGL2w=G znQuSA?SZ!vT*rFmdxGGugsTXyvp#yhUk%p~TxWg%B>LV4Zzs6s`F?HteXu)7aPRPd zn@@1>^ng2#;NAuACU$mQUpLL`>)}1Fapw|!*TZ`WuIU%fJ*zuIa5s3sT}W{6b6=Ob z={@BA9@cj$(f0ul`W_{?8$IBjCAbg5OKIIyBF~Qvqceut~O>lR@ zr(NT2Ah^%KX9=#k|9I=Wh2TDi&mCRxdAxV}5dQ`1S=oHjZDs&Z!o5Vo7pI9N5BDI! z-R%MQ2*KSm%?*~P?_UJB7w#nRuKL09$yU&BZA%gp| z2Yoq$`wDy&qkTVSKo@+?iGRlo@?TEy4@|QodH$i9{s27aIv&>&eP4%fIQD+ivDfE3 zIq~$~)`EY?!GFuacg%M`eM0=U2S49O^zL_Gf&BNk;J!or)Y(qj`PdKNb=LVkm+O4S z(Ypus!^1>x$9xEMIk+I=zVGP$fjhkc+6mbYk2v^8UE&WT`hN&NB6ee1G@htAc@a2~ z;2xXiCc?v=PH+d{amU^tyR?_?+XL_fvA46I%S7)_;HQq>pSjel5&X~H@7usN1oxx| z+^sFRUyyZn%;NyP;Xet#bc+kp8_fZ5tuI(0b{=rQzF@N>8iWJzD`IEI^CfsY(f1VD zr@wX=$IzS>JpYM=leZyyt~~|6aq{Q4j^2*>7do~@Z?lg6&cSz#Yp8j1?1JB0C(hIG Zcl@4*??L_me}re@FYr9xLT14W{|2t5BJ%(M diff --git a/blade-kit/bin/src/main/java/blade/kit/SystemKit$HostInfo.class b/blade-kit/bin/src/main/java/blade/kit/SystemKit$HostInfo.class deleted file mode 100644 index f6b7a05bf646fad335792855960cf0c81d0f429a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8690 zcmeHNTTc@~6g~@uUZ`9usCdBvF)4<$G4V-_2>}c!P-82JPiDG1v;(_4&CEdLkN5}t z1HKtG(RY88@yu?a))p)Z$iuvJcXrNvXKp>0`R4nN&tC!H0o+YOp9A-lbc+GyVR4)8 z(PGu79xLu}T`cb_&4TA#&#nliSHmrlgoFd5k(f`zTCr5!X0CQ1y;3Sy-fS$aFFTN1 zYt@&vzTgLr6`cIxdJyLxWdk({77g98s)cg4uVV+cl@EHx~$d(jAGgN&Q`vXf<>{V6y9Q@{GgorHi?j=9|Z+M`xL*Wj(B>_LU?ShidK+eYWQ~VxV>hTW zS)oW)8+u&0)Ze6%n{xAGLf5%+V1BK4DjrGoB(l95G(gbt{9LF06ihlWeLQ!L)VTv0 z#98n>WU;XiDJ|l`)fS} zF!HV03Q*eAjKXF7&BjtN4ii`!gDY^gE5fx-gn{>65w4#A;X_x18z(^c)CHj*ZboCh W1ylIU;CLLk4bw0Qvsg}GY33(zJ<8nx diff --git a/blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaInfo.class b/blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaInfo.class deleted file mode 100644 index 4b217e4dacba2a675cf2327e12f962c3114dcb96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10207 zcmeHN-E$i?5MQ|_PF%N%odjAwf*J}qZLo2he$bYJN#hv@H)i70Gcdz=&bH!Qdw25O zsh#GTKY%v|{t6ypUlb~{i>2L@ep;<$X;-^{{PW9i0I&wN z45SELaO_^$)O4$SUwfpLyN1?hUq39u35=lvyv-DY1G@t*Ucff z1@*q^oc1)!#p^N}N_VuG#l%y!^VeAdK?SE875hWx4{9>8$NO}^gulPOu=$YLV!!Ak ztkN#$2Ggt+x@&XOo4(tb9_&V(#4fWP7uVH|sXGqtFmD9vV`OKPG)gxt*b?C>ruL2c zPvL#0&Kq?W4_=mg$~6W?7vd(~m2F%0yEpnljOp+Y`9~l}o7HW#zmd^RN-M;hL?uc4E_cGAmJyAb(&|>yX^z zPhEP_)be%~%y<}9pWB$ya8UQM4W@O+#i?Mb0gi{s1|b784Z

8H82LF$k-e zU=UU@yCAG$YQZ7d0#9zj3gL(gz6gOHtD?a)2Pc{?)?9hg#kwb!;Qo$4rMLJ)yT@v} zyO^gB!slMb0M4&&SZ!%j~ak=F7tCKf#;7Bb9=;@psDmG6xjvIlmR0gJq=h@D7}pBD{MPfqWxHcpr+f z5q^*&tiXlX2tP^?3UD!j3_nW|RujnZrvxDnA0*J^Us8lp0))S%2xa&%t|n7yDMBRy zLSBk+DFMQg6yb6Lgo{#ywFC&)r3hCNAZ$nxt|ma(mLSZ*HMl;unkoFh`u}dpe>3&9 z1R)O}!Hw7mk0&79jE(TE6ya96h0e=I5BRVI4w}1MGXZU2sVN8TZWlUY$gu=$=Hsk9WFfbTCum?U3s)h zr+E=xg_$w~7u<2l8}J4^0dTat`7zl9Z~y3pZY=5S(RYrdW9b|n{r1%k1}yKGU9;EPYjmphO0QwoD+c6iCwy%wY;SnmfXfq%-Ab!nZ8i*82*}$_)$dYJ zuiWYM%GFjIal&?^+-$Wg<%pOIh+8$Y-R|w0o$VvGkaCP0>Q$?5w#?Suh;gO8*XV6F zo1Nb2?g7PL)+4eX-n(Twdwg$=F{3ew4{r# zt^e;`uj_-7Qr{g;v-#xGRZgTH@hJoaB6ExKhIt^0>R^YWPEWuR+t`yE@7or<Lzd`psnJiG*RSj$5?D(9neAu2Ob`Epcd zqw-QzE=FZ8D047_wz`b?`QWWe3Tr6mCs?_gzw#rz`U|#Z;C1|+3%)GD8(7bVT<|7b z!`3ofhqq!8$XSG$N3jU22@rmbMR+>_!tb#NHxnTI5sUCn0)#(f5#CLJ@OLc2d($JN z7Gn_#2@tNuBCNst)7nF7Jr?1E1UlS~MOaUOP>n_SFu^G9#3B?E=rD{$C?!A`#~`HO bqu?LB0Uu+T!BxQn1wMtV@CCMKvGv(M#QTB# diff --git a/blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaSpecInfo.class b/blade-kit/bin/src/main/java/blade/kit/SystemKit$JavaSpecInfo.class deleted file mode 100644 index 7988dc99e19cd19a6a633a5c954a0452ab863b28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8844 zcmeHNTTc@~6h1=>y;!+a5JANeQAi}G+2^yX$h@Od?M5B&@SxmG_wPdKjL38 z(L~?D#xzk_J*mJ*0H0~=0?%k6ETPqnDj|4<}`EV`aU-lf!XzZEx%jYF02;U zimUl*v0U0M<+ln1(wklCijt<&d_iD7guGVRso*dIbD^E3H{~4yV=qm|RIdp{GRrjr z(N)plF}O}(qRXWqrI2x$APXPfI+DA>I^qp#2)k`sOqs%=Z7J#&x83J7nW(lnZE(Y4 z5{cT(IABdq7kxQoQ4Wi=A-GE&p{UK2(V`0J`Fj+H`k5Z3nDwNX^`?>Sjt=lmyDg-m zexE6*!5j~-&gseQ`pF!w{)#RTbqEAif-wT*Mxiu7~T%#x`9SH`(Vv1B_%s&qm9JcaFq~UeV`9e^Y2- zw7${0xOr9Vl;;d|4dOc5@*0{pbQ!ih+t1yOQ9RQYX1yVvpEQVa)6C9tDYO{TgZkAy z`^TqIyJ*@)(=M70dwMLO4heO*tb_M+E;f37xN>DsKe6oonU|;J7)E^>c#e5d0(9pCBr?y};$UfuZ*1IbHcG>`@zgeVCq zm`Xtc(gbEQ{rPb(vpunCI=pmf*SV}ROjdh|bYU>7#-!=BJAX!1%XA4m*&Hs7k16;V zW_(M`M&Rkpa{nCSFi+tA`T289pA$$TPUn)GK*Dc04Iv4{l?a4^G!=0u4Zdc2>li=H z9Q(;~0;!_oaJgzR*X3>u7Lo67SA(Ox`_S&Qgoi!P5>6PWwt{SQ6*JZ@JOz9=fNvin zkcLqh!&(|*oigs1qcDQol0>>|{u_x1)&P>9A@wdj{t+g>Vrv9$;P05a!V8NHxJ)l^6GR2LB2QUYZ JupPzL(hrSM<_Z7+ diff --git a/blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmInfo.class b/blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmInfo.class deleted file mode 100644 index 086dd2a37047634503d9be08e9b5be1027866dfd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8895 zcmeHN-A)rh6h2dG|15tM{1*pAZ6j%8;*}Z`f{+wxYbZAHicGgdyRf^{%nn3e#8)xV zMDKk8pTH;Z-gtJmrBoJd6_AU$>Fn&D`Ocg()AKWDzW)69833L@E)Ed_IaeA5o0(2w zo9(ee-C_-1*fCY1y6-A(zcSVQ>YiP6wnQAF1SWhci#g3grM}G#MIgPpSX&F^NQN zX6&#gr*po*c@%h#HUxL6BNVlnGFnt2J%86m84uH=y7Hd7^4>J^z0m=_X}5(`)c>3X=HZfw(aadmwTG{8tD^=!0mcxOv=4T#=1`agxPMB5u} zi<=k4PkF&W&mpd&FR!6%!;qom`F`$poZ_**Fz*fVqM|{Jn`U-gNTJn;5!CPD*%|Lf z9ir(FO^0YY?dkJ?IwjQUvQFMlIN0cq;VRWZJz5y|D%<00ro+p-cAd)&hQ(^Hf-VeZ)tEHBe&=OWwM>`5qqTwS^;mX~W3ji) zY{Z<(=8m#Yz%2r^CzsB#a!w$HIGyux0!hE)G=vNoc=-*1gc5;9kh&^%rNLKBPnfZT z^08kr$2xz}akyNvnCo&k4)ZvJKZ=Bm4lW@)?7M`}<(V!8)#weZSiA5T@ZJDka)?3( zEXcPcZs6GyVZ4zhEx{Q}`S6zf8b1KBogJ zxC+;>Hwo9_MkvC~5QJ}`2)Bno_#TRIX9$EJp$IdBBM{urA$qtw1VSnVVFW0mMqn1^ UuuY*(3EYGGh?>QI6nhVT0U`?HZ~y=R diff --git a/blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmSpecInfo.class b/blade-kit/bin/src/main/java/blade/kit/SystemKit$JvmSpecInfo.class deleted file mode 100644 index f05b08ed43ebd708caebcc6e624a514ecfd89e11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8850 zcmeHNPfrs;6n{etEv53Of(n9;hzbd|G4Z6vq^Tt-LQ80E;)zVRL%XoM)65P;zJy0l zegdx^Of=EEAIkW4w@@n!whG8$F6<8b=J#gaOy8gR&G#RlzXHHxco2gD0uNnjWNc6Jg+4Veu)LN%QSxM7rJS8v}-lLk|EMrdsvnPEoz9?-H7vOrlVW8M~~(>AY``G}>dH)&+N|BNVlnGMZGOJb#0BQNPNgHPfCo)7~)B zo!$YyX}5$_)cqfXIuil$REUG{WEKwT2*a#mtOHsVe$E*&329A*gIIh{U7_MAWhaoT6(1cv>FQx}pzT#3LIC{q@D z(%>tmH;vIF;@IcP2_y@S!)4B5uFKsR%%k2vPKLlp*X@LRUAGes^(NN?F1mtzwF{2` zZw=rLhzO)$5QgwA1+n%s?mq`%02d{JawGmti3q*{B)&lMb!zkzjDN${09?htL;ja> zn8f#FAO%x!4O-uzt?e~l=K~}Zt?fy?sl8+E zZrbL~Kfr|}cW&GeAhmad_y_n05Ld(%@n&~oJMlPp1t}oS#c$@#+uwY8KHm?2eD@Rp zu0c5rBMQVFyOwGhrj^<;9vP`>)2NfwL(@&^dyY$54@~!x=H#p`8itSpGoDe?u(nfL zb%)ek1tOZhxt1;KIjyKbEZ;TIUE8#_Zz~W+i*z}&;)jaqLRNu^oW9A_xeW!BPZXH+ z<13}jRn$cMSgy>Hc~U-CWJ&zPLOP?sly8P%WOdUteX*0KYx#6Jrz;TkZS~b6+IEuH zbH#hwI>uvuGLLUAE-WlyZ4WAMUhh{e^{H6x4t-dx^r<#V3Y=Wd<+Gc5wv;ZXD_R*9 zSjU5kQo6FzYcY1mv`qJ|0;BQ7ngXE=t&=cZRA9Q>?pfQW_BgzzT=-(uvWY{Rk4Rmu z(N^1R8m>t#wQbXCleC;$YGk6)AZne|nud)=ZKL+k*e2?nHw=wE2S5GC0lO0r@kyI=c!v(=`yt9ofBRcnUDcvYhAm#*K;BJSU^^9P>* zp}JHxRCljU{7hTKZP2>9O%`pH}6#k^d=NVC8%x=i=@E$~wh11KkDjKCb0! zxU}Jxp}^LD;_yXr;98hupRmp1Fq50iY|xfMHY4t!4sXwnc{Iu`n%ttvEt)*`99RM6 zkx(9&<>CE^i;aVOI87gRpXgsH2Hz#h9K;t)vLEDFVz=#sPiFt0f80F3Ha-5j$efP8 zw*I$gm4C8-Gw3iz5m4dvD7*r1C~!L7?=iq$ zwx{!^MT)zvDzPgDK2|f=0$MYgYldyII9G<;hUqA9B|oee19L~fx8Af}YbbCkp6Jhg z9FhuLJo@DvAI^PF(P&}OB1q&HrYlLCYN22ra?)e%p#}3OPcBW}K4spUzz|Q;2!GPVd@6>{o?s00_ z&oWx@pYbdB)bGGm!0tq!nKKZB6EKFM7=*bT=W+rfo_>yiAtNN*4nQag z33mbzJ{1z)4M5lt67B{dJQfn(3qbfxNO(U0;d3D&9f0tqfG`6eK&EGY7{Qs(pC<*g zTd@CT#LU#CBF7%_2upEFOp5;CaK=@TyhLr$>-voqF$YI-!zZ*f7?g3!jqCnY9LK|o4NXiLHq*=yu~H~+Y#A`{KD(LSUMX&u*VY66 zo_Wi)5o7#g#TCrw_5rIAlRKVeQ)zLRc!F1L z=J>BkqPM)uNR62`70BdKbD!23nGAH0MjcF&8fQLnxg-vi<}Q)Q&pvoK>tFd%gK4F~ zwEB$n$>>F6-d^f{TsQK3uWXs-IZ&|ISO) z5~44d^g6U3ap=8tGxySL^V;7W0>tNPzOOrQ`2YV$KjCy6Bp;sF?DW00&$kP!xk)oseB}I4I!8- z16p;Knd1dS9};;i7-(R2Jsg+g4OfaotOk%gR2sf7@rE$jJ4?-X;5fq^B-ODtV8wNr z$l28QnID4`e&Zi!t%?nfOBY_8DqT1dnp_Jr)@96U`|uL5wg77*dSC>)@fWa-HQRWz z?QOP+X4@CEap=G$?Z@#0L2X4RJ^>`Yz~I)%@F%$S4XF;ejlVrX&k)?f=VZtQci|pV z!*CxSL?S#qi_kqDi7?&1ttu~=FX-iwRU=?T(Xdp;JuvJgpBm-=l-Obq@IPypQ zE1sk0=r=$3#XsV2@OWou7d9m!)1y>9XTIdlX6JeCyxco;XXpO*=Z`-Fz+L#pfF1%9 zzE{iHrsd?Gn+ImD+A!-Z_rl`2(xK0p{n+9L^b!~e-Zo5UH&?7aXEjb>aJ91bthA9| ze73T_R3wlqbfvnsdSI8DthVCpxU&Qjf8nER|mYy6pNqgpLON+}v6(udL-miW!Aw zui|iR?mOJFS;*8sXE_#sNZ?#LQz6j1=+>D5mk10W8%N&rTrUCdkjvk1IUe)f#sRC- znrk<$hRH40p-s=NHkj={ps8eekI_1-HB1jHHO<-!bC=P{zy`BugOjxGGM_pwr?$y! zdz52+_8l4!kJm@D%L)t5ie_Yw(URY?o36)c@Xm5+&2$7`mC>kmC#yM(|E+o@?pe-m z8w$!@YEpjKWKyZk_?}y*yNpY3+wj~b^Y~#}GECE|>o%C_Way6P+CldPm>&5ic4CKl zzTg#OV_Uv2G|NgsD^f|_8a*~FG>K?U*LI_Q3U_zC-srXXKeJDXVBmN|6yZk&w>AtJ z*2Lb={BTq3xEE#xM1(3TiOS{eL`en#x%G?E9iMo&MSS-(FSz z$@$UeJAJ;>=R1AAdtK+d*0u8t50bAh&-)>6x zmE$;)E^J_^&9^;^GcPdKQEXwWhZDHo#;~7eP8vIbezVzRPMyI0bU}K+!oJn0BlpSL zC;t)7k}A3TUX3kT!cT@|OE7CFNX8&Au;Mt(TWpxV&wK+uB{0=JODGxv%n*u-1}rE+ zqdOpxTohgh8IVVB>#kMQkJ$|_126q!z%tIE8qu-$3<#F!(SXMUG71z2ww!PS*9=iI zU>#jq2^i@@AB-(H27Eyv-JKxvlYUt+psY0Rkr0bjM` zmdTfBHfu7IrHt7we(wZe&JpIUC14!-pdU-)VBnLGNk|3qJPZVK5QYLd3?qRYg|R@s z0dJxlgdSY_-$K5(@#!wI5|pW*;Np|9@gLybU+}31uHbKf@MZ)kmIq`ln1D%qx&&9@ zTF5XJv@2qGzYW7oz|a%mu0vWGHy6WYU`iR6kKt~>v@&izhPw$_W!!cQmxEi%xNl>) z+i*u2XT@+cID>K~yU&9c!`(ZwfUdZ{Ut4hZWBLfrskEFn^WOLS5iS8A!bdTju!YXJ zKVrC#;Xw>1JfI^Eor2*9gVG#)f^q@<6=ebC a8po<{~%NS~}mSbIzW#d-mwh|9<%m z02ZL6zz~5Mmm7te&g{Y?{ZKFLS-MFJ2TT;ox_fYs2?d4;O#06(-L4e2_8w6~5E!+b zN`-O)DNXZ7MFQgjF(so)P0x~#u4~OdX1U6#Zf-k{wR%JiPdFUq(}L9~*O)8$G{gnx5UD@(cJ5sIwn=%Srl!lxXQW1Q*ech|NFq^ z)OD;wYO01)t20X%%(2xvclIn=b8oAebh%1ZlNy%JQK+sP2YQ97bG{$)=!ZGgbf~M^ zj!Im`}hRMx@Y0+ zwWRavrsoRz1f^8nmZ1?4M}#uzAVp#{QH7)GsyMFGE<%}fmptl0+CNg}V-IpaFMG%= zbFLo`h$}Q^&65j6k2mjlwyk5H_YjjtJitZeM6pAiGszQ~hBJMC5FMfIolEJ7ng_^) zekcjf>`D)=p3Vwhxvg`Tt{xe*?yt9<%Uv|?S9H;9juM)XfGME?Ng_M3jND3l_;u@$ za?Z?Ne&|0429$vVq6zId(?q&R$$pW@ekmQPS;9m<^{(_ZkONx1 z&WCDa|o-YqwGJHEs@zDsu_UYCTTNctXA6HV(kcVvQY9a|f#%0ynZ+ zb1sV;xz@Qj*#8hV+f`t3eyNy(83I2fIMIeqe>$5hfn3y<4gd5m3+!T?-8YlU1}=Do zz+dOq1y5M06PS-UqcdKkp2X12g!Q$nz#9ZEx9`;{$PxHEfv=iz8Ix+!D*YTE58Bg9 zlc#`Uo3m1IlaPM~=ZlMTMqBSH8YXAAHzqiK5tweS#$Pf~_1EJSYU#(=(!|CadrVtp z3pNw8>$%+&yiMS%?x7;vhT$UHVrX_YyC)L9xIZ6@NIXk z{BCBGGp6C%U9BfEXw;;2$E7LwkdTK7lss24l1`va(j~I7^Pk@NNy;z+BN($3d*u@t zKzFDsWIMftLF{+K*HiE@f&B#TA3$k^yHCmSxIx#LteM7SIOE3xzx%DgGUk$8A{Drc zBk5lSR%MId|4^X7XZY2i=~4yO(V#GFgOWvodjzh9H#-wTflcISo?#W(Lg)DFfdXH& zeXa<0E!1$6xh}T1%Ghajhi3s@h95yLK?X)(6h|3QAmv}vI41B6j)!0jF5`II|DC`) z3y2_6>Q|V2I5qVXJomdV_dNcN`cEd|1ssnBQt%?Yg#XfT4PHjJfb%*?rg>zN8U#!? zVwi6EOhXO48scX|ysx*f$y^M+*oJ=<@vkA*FlzRC$S@LWkd0wjYh##4WK;7N?#&q7 zP6YQ>AC{YK_|seNwBh@){BavYa?8Jo;POz2c&rsQw_-f@T?F?Iyc@yc1T|u0AqMw- z1owUzr82f!xDR4*KSppLoq&sb-_Ic~1Gk|VtLI|O`~C=VL$HLZ4Z$a{gV$-ywNK#= RtYA#8!RN368r+BN{{aK>@-6@X diff --git a/blade-kit/bin/src/main/java/blade/kit/TimeKit.class b/blade-kit/bin/src/main/java/blade/kit/TimeKit.class deleted file mode 100644 index a1a5cc945a760d27f651fe4349b117f309b5b285..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2453 zcmd5;T~8B16unchUsOQ^6h#?OVT;=O;DZrj(g01sB8e>|K9T8mXa{z8n%QXsKgC~S zqKUp6f0OafZn34Twj>yRX?J(dx%bYQbMNlAAD_MezzcYmfEa;!U)gz=2`_)d+ALpn zSdHh8h0a%m%ijo{fKdVy!J5OodVaTh#BELB*2ZSBuve-aY!oV+2gTiYJB12?$x>Ok zO^0tV&5KgGOs^ul2NJ*u#Mgu;^lJhmR(7Aj=(?=&1Y`(|cQb7&B~=n`kdg0up5nfA z+Pp?>={AMKw2&TcDp_^7>%XGuRHeabjoS`W2x>C>nAJI547QWQ?JUxo&Wp3ZJ&T8b1^sujS}Y%hyKmfaaW1 z;kD&4rwsLLoR5%B6?~s7bHafI2I-=e@als=eXbk;H})L>DgTAE1_1uAy>Zfm}v%A_`VS`fQ0FWOnW(JreO>w zGLVFu1g5Q0x8K8@t7aaIm(VnCTW*!B3d0sRgGJiR*=I_a`_98r-4H&3h0=f-hBGM9 z5rn|9wS93&WiQr|gjoU~hL}7<9nIx5N)0xk5pO%P>^TDMe^WMrDU^A=r4;u9`)zq8 z^j|RLx065#to^w#Gsu761O#UK!-v{qUMo_HM^|`)SKeF%maL(iNFZI7EoJkfFs+d3 z^l$KvNI~zz>{+??K7D&J7JSoa18jc0C+O^DG-BMxCU{&nuSF0AIE1&Na1=q z_*59dD}eN87<)f?{UeNj4Oo--8xL0Sa{#Y1Aqu8o8t+mt1GhU7Rxppr6h^oc5n(Qf z5bN;n_VCQJkasVFx75SC4-a~HNbB(CBY4kycnh!?$$J>VdwGucxQEwOD5}oFFJ26m Qu(B8|!&Ce>N?Wk<6M!?)5dZ)H diff --git a/blade-kit/bin/src/main/java/blade/kit/TimwKit.class b/blade-kit/bin/src/main/java/blade/kit/TimwKit.class deleted file mode 100644 index 30ecc9a05e2373d7ab63a2611e7b327b91153ed4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5122 zcmeHLTW{P%6h5;_*IqX?A++3~lN8D>lwB_2)}*EBRaG4-H6ao&NVE3DJFV?mjmHb+ zg+IYNKcf;z@Xn7w;*TKC*qiR6OuBxsR(a^lde(FN%{kv3pYwVC`uDd#0AK^IJJ29- zK2t$2VIu84WFyw=$1LQ%M?&}ZMDoKup&eKxuu{y$ERA~i`ww}b2{irtckbMJK*05V z8AV)e5^&Ny@kNHSr~PfE*kkht@3(eElro(wPT<^RX3PI3Px|=eRkUetiB#yT1Qyzz zeFBR&WXK&@Ca^qN`<7Btx$q)!*|(|UnT$s~q=8I^B4%31ln#~b$2`d{Q?Io*;56hx z%oG|8S@4KOoURuEb}_(p8cLqgRBDOd;a4Pqnoxzdb)<5u5qI~dAh_G$xtdy zi#bFY(14`|vCrwDe@6{-E#le?3y-X5cavc(0-9xu%uy{hXq>SpvL;egSuk|!xWu=%f8tNXQrnKya{_w%P~{wvnX>HOWl9ZNQA8*2^m?(fHO5NS zw31tuvdi?!gzJF}DH}!D7!H(7ijHXNHXUmL>}dyFWu~B;W|@dAGu#y>KqY3>C;PN zMN@p$JMbl*Q9Ml%2QK6JgJ}Q`Y?*_O;&{UWJez2i>^pGne`g|P3L@%GsfhMaGi9&_ zShDb>r2((QDQFfW2VA_{D#jjOvDd>A{=QJ0$SmLp!22D}e7Cyt1Xlkn?9SnDvzS?d zmvLfp<(6o^do&6g!WApRI$S`e zN@m`%@bRw2mups}_nvR@;e%rkE?E$EtO#A`S$+7(g7Cc+;ge$!KD8hS b3qk`v!%S$v=dg{}CCtDt;49dKEAaJyNr4)| diff --git a/blade-kit/bin/src/main/java/blade/kit/base/ThrowableKit.class b/blade-kit/bin/src/main/java/blade/kit/base/ThrowableKit.class deleted file mode 100644 index c0e172b1f1b9519f8872535398db506dc8255719..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4137 zcmcgwTW=dh6h7mo@r6Lzl%|Dp8PW@JTkIx4DRC63ii#A)y{K{1^aW|Wp4ii@cUCjA zY5NF20wg3J`3FcyAi)D~{26`$h%>wCdhKlJBz5~@@2t=H&Uemyd(Mvk`uEr00pK(E zvIqqNRjs^wpNXLUnC-H9+h-kK-w~$XW}4SqJtd#8w$ImvDZ&JS6S0-gf^Pk8`!V+n zfyreN2(v=q*nD-9z{INT@FJ86Ob={tDJ4}2-XO=nc@QYBrN7HN)RX;C_{<0y&`?PX z)7MM1Qf~D)?QqX$3XMYM?XWJVb1}6VQma{NbF?G5rhzoH&y3fj2A%lR5GiGyFuR(~ zu4cK^Mj(<%q900SXlx)P^;lp*+nheKGS+k zSg{CRfOS6#jOg=QPdy&Sy4b%RM@hrAEaObqHKwbb3pW>=n_6?!`~JdK%CD&UuRo$| zOV231gq$eeEU-c?i>c$k4ceR-goLPQh__i@@pm=AcO@!5X%S zPdBmk+==>au3EPJ6PRgAkNKNS3A^6AIbnK26S&fJ9wH5liLE|lU1s>&_8K-n7I^&b zHcp}}mvmzq8G^C8V}6yiLFgi!A#iGtMe0eQydk;)Gm%36>&sh98K~5%vEmkXxwX|; z!PsBpcL~lB_|9pNz4mU5waC=>p43{z`*$`!&FW?eJ|ytt7?T-)noEHt10MQN diff --git a/blade-kit/bin/src/main/java/blade/kit/http/ConnectionFactory.class b/blade-kit/bin/src/main/java/blade/kit/http/ConnectionFactory.class deleted file mode 100644 index 266a301cb40668f8b69047ac4befeee25f4ce9fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1847 zcmcgtTTc`*6h4JzXBkjn6%f1?eAzW-#s{B-m>7g;GK!I15+A#r$`)qYNvDet2yOF^fAHOGSJn zZQQlCh_|#-f?KK84&zpv(*P<2<~=lH>LA|j9O6EK;K}yR<95;_a6dVp#SH?rO`b_5 z?IQw{jpjaq%9c(=05b&U2ClY^(WVBMNab5w8Byx&SfrHeypS1lA=1L=PA2m5Aq}Tn zT|ra9GiDG}Fn+`i1YP&(MVMaX(p#sg79~~M(wte|r52UMNr4#+D`7s7t5D=(iGDND z_ayT|8%sSvYRZ{%MmvK3jB^yGguM{lQ%tn|DjA&QAG}hlDWmqZ5aBdp|ABb6yM4k% z;Y&W6>9DQw`+jNk$?4eQb0pzfmDcneyJ?@zjV6^P?Wt6}kxHcfqjSZfO1!0mLY}om zqxtSV&3mP#$O5FFP}UPks;)57F^P511NINih3)Ee)I`LMU{*A+_V=hyv3apx(cSpZ z>i_X%{IQOgSLci`gb?OtVICF;R5#Bi;bJ2h%)UKqq&nDevvDp#QoiWr9bsAw#~p!s zqB+a8#dC z+AqdAa1Ollp*YOiGTwxjetCy6wke7#?r{y|DWCd7I;M&9WDzMRDZoSd%m~dw*0E&wp3VAV3VY26b6KcNnAeF zPfkwse!@ojm_;-Wk{<1yANsuG*ea}HjPlTXuQlT;DKFtL>?9Q-MVz2xy9#-8^IS^E_2}LxI()MmL9qWfZly&T41hQ{hbo)^f2W z0>^?VaAT(KdUeNb92j0h1pf}kV~qJQVd1Mu=5wWKn03n+wQ`-N3Y(&)Bp6a1E6Z6D zDR4XYIjiS9g!ix}LPle*&tsTnH`6yQyXMtZ_yDt;shcz&@Sy_N&-oT}rNW0|@^io5 z%akgxoa-uvhjtySTp?U~Z+S*dg-`Ik$qv z*p}ZiJQD-_5_50#bvucv-Xc7}_-6HN8XeDX;Y?Q>Rz-!cQQ0IJ*IQWkekj(=TK>hR zW9CJFqJY{=rYlW>yScsXI(z%Radv*5VI|ruIen?0o26MEu2r>M%T?h!%)_O9$|%Da za-SW`-4#X)*I0+LV_{p*ZCy0_Mh!QD3UvjF-HbBb7~quQ__pC1t@--<9-RlXg}3-5 zj6?oZfy>)FyI5Eg_eKHQnCW~UT8t%31y@Pc3zAV9Mw4}>r7Ss&=qP)n z6_>mr)p|6D2t!dyf)`{!wXI1{C}B@1iJq{f^%9zCal*Bcm;#OCAbOf&N00|$TPcaQ zQWCM0&bcTqHAZ5Ohg{3XDPrtL@zNG#$$q}qR_;E6^wj!XDLbWwtfRq)yyp$HCmE6{{4 zo|fDHKlw#RT5IB_w8x`E$~=NiMqClF-A22Fg@W^!3w#)2&%fV%jjIUWD2knA%mP{s zg~R3P4Q0}03h>LBYsz%f<4M&DvkVVkaZqKj3D_|40(2Yhz!g|TDj;0~6}c$!GV)c4 zSCOwtypDWb;v2}fBo_YfNPHLREs5Voepg}*c}wDZ$oD0FA9-8i9psNB{usF=aT)nj zi9bVrAn_N-UrGEB`H{qrk-w4nDe|`x8_1@_738YKHROiG&#}@9u9p@*?a2l7GX4T6 t{sGSZ#t*+i=dZ~;?BY|*3gF+5_*|K)U=Q{u_JhguC-@crFQDz`e*x%b;0OQ! diff --git a/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$CloseOperation.class b/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$CloseOperation.class deleted file mode 100644 index 61dd420d71c09b0fdf6de179efdd526fd66e0f7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5783 zcmeHLZEsUI6h1DYX)YOsu(B5zbIV)UOCn8^rje@B6j8NOMx-W0f^W`^X-x06?`+@F z{xYOZ+P?2cO*?kmOEN0zA&69z54rdH`0;sp?D*K{?|**(699gMW*HU;{A6_8Oqr0) z7i^z3hY1_;=AN+4v9(!q3m-fDx11Y$r=2LnyBXKa3MI=>BJe}-;9?wsO6(M|VZsSq z>UgcL(IT)ScBRtXiyj@sJadK&0rHH%;<}K+ZV*_mPmFo?U_hYMRwG`9Pq5F&kTAL1 ze5AF~OR!98x1LDNjY{_Uh{h_-MB)RWnO0~vH4kZ2>5n-b@i<``K^cqp*e<7Qo{R>P z(Qss}(UIbYN@Z!vY&@nG2l0c9$98fMQqpjIHk>bw|EM^!B+^W2OFckxOJgRT)*+`S zj?QtRya*LU-yDXEb#mR!3HkU43H{H^aV{C0vd0GgDGZNuE$m^?&T}5YxfMxJaC6{W zllD2F=OARBKVFbOpPfoU&uSrePwApoQAX`y#-qyl1@$^T74LDo$zrSYXsi_g3O)!lORr~X zD=7FN&@8>4r7gFuKiTQDm6W(0VpZpijR>)4AcE)&0Yy-St5v8#4GU29&g%-&(cqS= zFfDh47_I*i zf03q6LSNaQ$c9@d8I(YE8<(SQyYm7^9v%>=ht3><%hPj*F%)*o@I5w*q>F}r6~^Fc zvXAp=N~?g=fF;-ksKG^8#IG8ZVaZEMxDX@kzl5z#L^)ja2UMTdF28~+e_`taT*K!g zVgRngr}(V;?+8|~4e;5N8(iO&VMHx5Hnh+}O3vC^e%_!Zou($ug7(JoIMH`3O{Yogg-dIDw1p zOsX3+3CyhvDeMM;OSJ<1UY|gzrG~r=7YQt6W=2fzHJ)m%^gMh)7H__gni~}z@F5LV zoQNp1ktSN9l3N-w>7))gJvMZT^Nov8Ug4XDT z4+g4svxw5do8oCciT7i7IkqFMew9s%qxXz%9cY}I?E1{8Ne6g~H^vFz+GC z2`si%$f7>e!j0b%OLim-fyZs{%Gda@idC-Vak-e>-pSthSfT5^escpQmxfBB;j=a8 zP>?5AQ-&K@YTNGQ6aqJPQfWoZx8;E_0{#2R)u*zm8M+s=I|p2AG33p8_>REJhwE!t zUPGR)N_EILg^S(gLXyv_WLWm=iap6}s&Trr-hWb9hNFzp{1^V`iSXF#R@UI(&mYC*fOck2N`YN1AS))I@&v(sThRN|}KbSk2m7u!b$bZTu}F YoxmNam8xjV9k_?>1EkL({XSfO3&&fN%m4rY diff --git a/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$Operation.class b/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest$Operation.class deleted file mode 100644 index f58fcecbf494518d6b63cba1c8b924c67138c091..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5637 zcmeHL-)|E+5FR&Mk}QFiLb-$Ehg%Ayhm=SN=>)C%618fjKqV3)@#t*a#&l!v*KPHMNyPZ#{PEZo3Yn3JAZxt?GFHW22b)ZL*S{=QMJc} ztiEIKS+yOr4zC^vTkTq#RJZZ+n*W+|V^?+)u9+1|<{=<3pTT1$_p7_@cRaELF0BhG z>;{2cd9_6#sHqOmLy^GTF?LgHr3-MGEZln|H8(1L&pR|yy+p*Ba++w>j(N|#pkcAu z<+Q`2m}vwhEIMHOoGxb^E6B0pI4;wU;)Y6PX^+{cOD*2SKPE_N^d@w(;@qq_E|q_& z=vxxKL}^PifaI1&OggP?P6tG%IN!Jkh;>86u z>J1egaJ$7KtMs^|Y}C(fWvpa9-r`#939kQ-u)I=OJx4rol|EH_Sw!i`d%)&!66<4E z9NVr|ALJTE>G(#s4z!n=tbAtFq;0I?jd2Q_4$rX04~yS|zt`ILUs=uxSB=H7<9QCu zy`*$8_)JIL!z^MrkojMWmEptJCMpaSGE&kAW4W|pF`NHS7PjKlbkDGm&3jnzipL~( zhSw^3fhNg%lD52@_X16l^(1Y1IqwCUBx3c*Y%o`65A#2z(3vd7|l0`JqO_x zP9IPR1-MdzS-47Iv0OjyAoXuva~-C+x{&-;+G}&&bcY;)g}RDZ++tcd`Die(U1113 ztABZ`YmLColPWQ<9jSf(75dhjt+fqQn$xKyaHG6B;#mI-#>sG)Voe@y5xBgwI~*ZU zY>0iyY^u@S+43qX#8z8JNfZP0Jubj~0!wE%*RZ#SW*REh5#JInaPuP>K5LN?_+`EI z;xxUD(?j(^q8xa)xHFRGwg;(^Kxqf}nXb7)fTL@V2$X%71pOYSxjd{AC=86E+Lyu@ zEDD>rHYQjC3@1c?0+ZsWfh_z7q3WSWj=2;4<%F2l|s>IgZ8&%H5x{`TR6 k9@5PI(vkLMcz`m%3VuW6N8lkm4odJd$_3<7M#i~+03}Ocy#N3J diff --git a/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest.class b/blade-kit/bin/src/main/java/blade/kit/http/HttpRequest.class deleted file mode 100644 index bb2cbf6dcf42201c211f81f159c6663ffed60998..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23165 zcmeHOdw3jIbw5{HX?E9=ABy9|F~n=&KnRgAKuQB2TUcTiq0E(}f0-D_kWLGh8PLzDZ4XO0N!OV?k| zI<{F{*e$4c)GC%8z33d)^A#gb2|??3?8sV0$0#~G=B!FFr`t>+`oAah& zV_YAYn;aX>OiWGI5qG3RwFk+I(2;2s>+>ZcdG#SUPfGsAm*M?7CUA8HAG*-jV3qVU0DtX5&={5kwQK)v_vI~MPG#84N zZH(rvvN3itYm_9@WkJbGF>4h{wo#ThbCvmd!=5!y86chjm}5D5zIuN^P>*|mr)@e| zTW~H-Xxg?;E=hd`@24#}f4pQ{3m)|La9IwO@|Kx&qtJ%V1pyi}7`%BZb;%9?k@ zNCo`gN0fp~shvgJy1%$Pg}XYT6h2h|k8*^bDp%&RdA(egfEhVniUSw!tBX?eF;A8j z&x_M-f~J>eznL(6dEobYE;p?^i?artK}RrvLov&f_7;1jV&-#*15mab*J}5IR=YU1 zUYNFxdGjQ!y7oZOz966%FLwt_vi77AvU!R)-5$v*J+$S-UJqxf2OHmvcJ_xmU<=9a zfx~fnsh};(u8g2nx^3%A87pndC~yg*l!3H-C&SY$0+H@iZ1})n+ktypmADtg-3EeH z4wT(`sbmxpE3Xbhcxv9AKB$+lj&;YcD7EqfS|n$ z!a(?11bh-gzog&I6G}7X~O&=*R);}SiCy)(l zSaMpt8`F6Oo zmSu9wEE=htfuL<80haXaaecu^ZFS4SL6n7qGN*4%p6|uM701j+67KxKz(%;$puPvxb27?0fBz10>oZmbUfs&P zO4a)vk(wg^KL<7S1ecLhtH|R^5weH0pMCamnqz;DOsqaa(dz*eG~y zD6^b0vCA!%v0q02G?{SUpVJKE`AT^)WCr(rgc;=KtD%*-jLaCj%!u!r;bG(EESlJm zZByA=qf;SUu*^25aVLrv*ppW4?tg7??zUZJV_DBt+tuiw zLB4T$Du7Y=dCqZWQBlW*I&p+vtL>fo>I;>dG!wir{NIcJeB8$+;!R zz+$0|E@&g>9KrptY-}}k*kf~64tx4rYO0$t&@)G8%0LTAfzLZy=!0D^&uVtdwv+pzhxJF9D;2C!y(4;d5K>X*cJw^lEj(KU}r7&Y3tUVmD_t?zVc z7{_ZBPcdNNSYWK^;G9&+298vz{x3Mv;4D%>g0Ay^ag)fy1m^i(#7mhxkhb?%je{&=!l8J-RDVxaP9w_*+rk-n3`e7w zLPPJ_#33x+VKkjSsu#^sN5wRpJhYX>`AV@iB7tvEY-!v`5^L_4c}D)Ox$+$2I;}3!`b0^N z7#tb1J1d;)9B02P+O#W4U+j6JdeL$?8i(q@i_w5vwqGkKyk5#p6{r@~GO5L(wX)gz zWW_VeWaE29tn8km5BA?ZqGaeOAXm%)s=#U-Qkt^cb!nuF4JZqOrEj&Ql=XstHm!tw zL#>+ez5)o1a*gNDW3}q(96fg;$iX>cHB`a14^Zm%jU5GCHCM6|hA2_#LIu1R5sxsQensC~G1v=!U3^e0gIN5=CC) z15K<_L2GO{0dLN|cz18L&LXjHg+CrxZd{U(=16Ip61gVup<_=lAZh|%Irasgcp*{~ zJ27Ekxhnm3Fs@H2vRX>i?#4X?lPN0cfL0y|=7}WKE z<57UcgJ!vm{emot%d~|+iI0>oq)Vuax^buBu7l#ZPvV|%T@`rVgZtIA2G5hUme#q~ zKDxlYt_O;w-9Q)N+D8}DM)!J&i_<}y=tb`P7t^Kgb#wKas$RELuUqLd_x=#-D%IpFdR3;*3v!n(m-XK<;q5Pxy2RIz)$+`TkM^{hiA6Uu~ej z%a{9zFL!;t8T%41`1Gg2|IvWlp>!SVeYynQtuA**s)1fv?vAS)=#}N}xW%VG4gRCc zJ>%0Q=m%CH_dN~t>T(}%pbwXu@zah6efrbjpO>4Xd&s9t(94#Qo1?G$m!uDuo1=eE z!~E)Uf7GWxjrpU?{gh9apqH;e?$0;StIPeB26}b5zvI)N2LF-e?(FmF5_C*m?#|5( z^vZH~2L1b<70iEqVE%j5?X7bpK(EtWATHMP5M!sE2Lp6j%0;HTD?n$^b&=_E0lImG z`R?=SPSXM{MxO7LK3$wlx;H>q&y$>9-t5x}{IkySraZR`bz42(hWy{BB&aE*Sg4U&xJYWDF$8>BaYhZ>T%ul`9tH-z%mwWDwBBk}R-4E>Ta(zjTiemQyu=+;<-Ur|8t_Lq(ETcDf!?m+wwjYHj+ zvOGLYk3>e;#v(jQ?}0|WDEq5^OboTW?(0~jhv_jN>Aew=ynSb@UYa|i%Vwo+ZztM} z^eDZrCG!88&s(Ucc6)o&X2kc?2UIPv+hFzee)@F=DTY0e*RN)>QMb(^Jx(8Fkiyr{ z+u1ft_c;9qgA{I=Z(w89|Y_nG%9L*b@qn} zJa}h{&5`F*3JCnZ@{bgx;A7UO6%gLSYVwa2q<9C5@Fxlu^(c$*rwRyd3xoEcPrxo;)Ii6y9_-ypGhL%RY zUdLj6(Z`aqL^>6SzmrA!l8>aq)%#eizgrO&7awEvWyA$eTj7@U6wB9_>F-&r(49p5 z3k;T^v(e*K{2Of$YTN|ZE|ix9zVgF5H~Z^Z`iH7qL8Pv*{ZV3F8>B}Vq)=Ta_`3Hj z{Ud`EF5S*HJpB`c6wVVDN#vUSGlLY)6JO1qrLQnZ;TnH=8|nUqK?;|Si%e3wuQEvC zJiVIb>1)2v1??%EC%(#iPQ6=~co)mlbM&u_bdtZeJ%Gdq+aUd$G7`5#74#f^T^Z@K zZFoAYjKuGG|DC?UAcf|ZWCzRBX7sz7PZz%F=a^8u9&RPCVtIQW zND*u1gCgfkoh*pA%iNxqv!5TYZ%L-=a5J3-MIy-SniqDiNameC=)g!grI zr_e}O3^R2iEG55 X*deYJyTtY4Msc&)Blc3Kxb1%d&Lo`y diff --git a/blade-kit/bin/src/main/java/blade/kit/http/HttpRequestException.class b/blade-kit/bin/src/main/java/blade/kit/http/HttpRequestException.class deleted file mode 100644 index 70cfec7853bf3921d761d5b3f3dedabca0b8d92d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1370 zcmd5+TTc@~6h1?NmZexMq5@uqdI`LAWAw=y6N4CPsw7aF_&D7?X$N*^)|qKT|B^pI z6EzwiHU1ZWfyT2-xk#D-Z$8Y~os;i;b1vV^k3S#30Kg--pNBC953C9NSV-mXioWpM zkqFV>lg{rtm-riGw(xBaty|v@FmY0=Jd87#&Croh9e=aEi-9ATMI%MjLSqTFQ-98Y zy<{-6rj>OYGROwbd4b@iiS{9xgE`9UruA zj5Yf^$%7dv7r}!$2JG2 zBULAxe5oN7zV5|sG)+OnWKeGCfMg{|T(loL$6Z%i1`it-mT!$gp@VKs^emB=R#yKJ zAA_Y~O?B0mR?>;j(otsmq659gVYh1qxXIw>Ih1%9@!!vf%G=gG6W|M(Hhy8$?a%H2 zjjyf(y4TV=RBl6}5hmyk@=#$geL_BYxJ&o@v`QEhUrB3efgc5S>kv#&HwUrUYpDT2i11hge9Q03lVWflB#O<3{4RvA4;#&aSmySMbY_ zK!Q6z3NdyNF>v7raPWBF&fD?m?L2?`{^<(yFGG>QcE$;roI9i01@{es&11LkdM<%Rf1R8dE#&+Kfm%<=*f43P zEKIlsB?237T+f0Ef#O^D=-7fS0_D-zI~ffp7SwQiJenY(j?D2HE_Mi%ywjteYr!s3 zd!ymd?cshCzx`53VO}A#-I?Oao(izf+XU+CR$Q%>w%{%)9GpqbV-;TUfck0~iI5qg zB#pG1g?t%5r*_3#a2jwwWEx2k^Do()(^e)*7e(o&qO@qBcub`-bjggrpau`|_YumG zKZLq=Q(e1hFWo;%*p-uI6bfG$8YdCg*bwTZ6W=IJSJJjSRKzrq0Y4WK3!h^K*DMK5 zp53K`BsOUVS(M4NlU3ndNxQPT5$ZFU_C4eDmlQ@(Mh)KZe-gKC*oXU7xCxX%v;Fr( zr(;&{qte4ZWhf#!~{D1e>51n#h$1{`~0;?i`LiP%SNaS z?cWTzx={kvfrw*tTWZo6o&vf7?QOvxlwcE48Brm_l^nJ)zm>yP#I+p0hPa-?+lY5^ zxPf>#hp!`U=I{;tGC>`0Vcg4pHygMDus_58yT+Z5aPMo@*8_}cmw-}i>!f~=)uFz%+5UXyx;G9{r>SYfX7&HP-1wP7~czpio6}MC%kqbI?~%! z*6Udtd#~iXzD(>!-^P8rX^j-2g9^h`1`b5j^)}i&(zgtbjC|dZh7Ox6Jz)}QR|h*w z45Lp~r0g?>`GsblY^ixnMD!}^F0C(aF;rHF%E36p<}Y;-%2Ve*8#)mBgPj`Raz2owu{S9B$>XZAJ7zD8hn|y)DW0 z`Dhoog{=ijI*RYohx~#EFV}o z@MVFtJaA|Oe#`2*a4}hfgDHmDh0`UPR_J6?Me=1oY)jJ;RCEl}P3?}^H`BEbnD~-mF48zknDpi} zjkRp;;u2=Ey;)o)rYp3r(8=5pSBZ88T-OS?77Mt_xIuSHxQSad0}tq{k*>E%_c`3f Fy&vfZPmBNn diff --git a/blade-kit/bin/src/main/java/blade/kit/http/UploadProgress.class b/blade-kit/bin/src/main/java/blade/kit/http/UploadProgress.class deleted file mode 100644 index fe3f9f847da3be1e15dda7ade392cdfd29cd743b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 599 zcmb7?!A=`75Qcx#kPTZP5K5spi&H3K_reJf5-Q07tqKwe5=Y1DCI+v)@;Zq3;(%17 z_Rd39*c+s@y>YPR8P7kSZ^kcwe*OY*fb9qi1bda`X~CpUZ`nOdM~dYly^}7TI9H~_ zQW=(CS~IqysvhV$FZ)aZfeOio!9WakX(8&yE z>Y7;@>^Eo2=-Frp7Q5%?K^b3}spXKl9B@bg2d$P z#Pn3%%)GRGb_Nzk1_7|DoW#6zegCAa)Z`LI2Cm@z(xT*4x6GVWMg~D-9eN1n?r!yH_3UbQCI9yOPrm@b4fx!H0)f>?`K^G7 zu=S8lSgSW=ecsv^x+P?5eKg`>pY?|PYb7*S9ux^&h~JGvNOIhScrYDeDco zt7H&+ftfZ8F=pOJC7WDr2{qdmUC8c?$jKorRg|1rxlzD4msZTlz|h-fKv)R)jr_FKzqQ{ z7XNO{Lq9LtKPBtbljUw=XUPgw;n^ybp+;b--c2_SNswMM8;ixR2>Hf1=yA1eaw~ya zSNd$Y!;~=3PhJ-FKtu$tb!XTM;r8b2_hwf_z^i}T?sUv}mA}f;$b-uS&Shpp;PRK_ zP>X@;4)IC3u67+ecw7S53?FF1B6qTouHllR5^T5;O?> zaTH7*qj*t*)wu>um+(_Qk&%_avL#<88Ek>YXMUKv>g`51sq`=(y)##8oeIbkO6|pZ zH(SlEWk`IFkj?omQYR9#s^p~p6Uz6czwwQ3JatTk% zE1%yJrVd?7LwsV$_`Dh4cS2u=k%%-8^?kt=Q~uzw2e+_)+QkDrN3Uj$>%pgZ#GXKT z@Y#W5`XrKJhcA*d%xygGjDP|bP54JZ0cvm-7UGr%CA^=*s|*$VZdx}`s(|;(&rtoQ zcK%1W@GCwQ;5qzVKpDX6dHk)$?FuZx3-P;UxQIPp#C8$CT!NRdW#nJR`xLi`?F9D~ z3+@#wE``@}agA09?urF>)rxy{CfwI8xYw;vBEdU93UOxA%OFe$XeAypp0STVpYxsX9OvEp|K0$=-*Df90)b0L2d#(+*?P`K ztknxypSN~}Z3)#{A6verH5+?SB5)!z2$>wTy1nN-umq0v(83TXY_AiTQ#(6`<1A_8 zN66*C4)JAGNMZj$+xqr;;~9a{1J&mq94D}N1h}EK(q%Y7iu|e6+^BHG`!rBdEJ9|5 zk~G$;7xKv5qkd&;$Z4MkA=79SvtXAEI9<+MZ=&l>p_XZ1aYLoDG-5UwQj1&oix|Dm zZ^77`Y3$9^ljcVNlT$<#D{X1EEEElxOd)%m9{BkE%`&f@p0%ar1Fjuw)GEs8h-tx) zRKL=W;!p&_Qj^5#1|^NvNnn+xlT_CmR2Z7bKHm|N_nY)lVr)uiwk;e}AxCPLQ-<^m zKSuB?YsPRS(M8^rrP;lo0x`~|?z1`h- z5%4$@`KJ`+{pgOk)}qfH;pELQCLssYjeJ;uS`~aaMc_=mb5w|v%`0i4E_N{0kCUj! z^;Rkq0=13`SomyTHv5w$I~3RgE_Y^WBr60w>;vs~dcgdE+b3)-_zcGPMlp0s2#s^P#c(v8wBJmk^Fzv zgbr+~L@^*+=chgS!N(c_ux;!pPmP2V_(q31hIBx3CWxSONk? zyt<1}gJUp(TUzY1^~pL1vf_&bBo zYWD8K5Ab6)=fl|?LJ8--7U3M6&mp8IO%N_Pd}ug*_!)kg8R41};n%M~xb8%tpNV40 z5yc%R!bP~`jN&&3!hI*g6{usz8pvP?k*+%O`iBE+&56~77GnL0SZVgJ<9MKwqYVA! bK-+Mj74Q#as->H-ildL-U4>h42kw0Uy4Smg diff --git a/blade-kit/bin/src/main/java/blade/kit/io/ByteArrayOutputStream.class b/blade-kit/bin/src/main/java/blade/kit/io/ByteArrayOutputStream.class deleted file mode 100644 index 4ab6283141f29d8534d6d15654871e7941522da4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3590 zcmds3TW=dh6#m9>;TC_3>iw^H723pWscnBco){5jth z?s6Jjje@I5wd@8;#BQXF+u_Dzol}0 z9wm@1;SPO#`C_TpR?o6^wFtOIx!g5_uBeo~<^yStmFaUWIc2|6ZuW)NG7!g#4&mp%CF+(PF!xu3Kno-7IS!$;X<`BrYGV?8SSnm^flj* zk$Bkaw1nPH_5{OXL-{;>a=1qh7mKDXV}_fJ(-QC+F=W+CEKToeX$ZeEN_Sksdkp6? z@i1I^+>4Ct2ruf(Sdv2<2}PxxN%kv^Vg1(}ywC7^4t5=CoKUii7iT7Ud>=EEs!umP zN{oZ6jIFBAy@%nFRv+oZ;8WKxz0Hr4ynb z#gkiw>P{CIVH|wL(9h${*^?}h(w6FJUwkJM_PjWXB3t+LLPjL)MZSt+Nhg0~?n|M$ z_S=IJzDZbce7KZwhha9WPt)&Z92048)BPsK66pF#_u^?3=$WCf0!nbwv3xjIa4wzC zrem2j=I|Q5=V^77v>A<+Ke6!R;^J?3yn~B0OAs#6dx%h= zwbLS8CWI-xOPWPOx&oKJ5{pYT9>ra@cy`_D*=2liB5sjv9Qga81^2EM_ZsD_VD)mG zzp4eTWkvf4*9mPL{n3a&wqWgAv1+JiYBBcah6N$CBHYAhR)kdx!p~NOFVgHBjc4r5 emlmu&3)U3Ars@=M3u`n2-_qkyMX%sC*8c+%sq(@A diff --git a/blade-kit/bin/src/main/java/blade/kit/io/CharStreams$NullWriter.class b/blade-kit/bin/src/main/java/blade/kit/io/CharStreams$NullWriter.class deleted file mode 100644 index d321e90dab8d15a46a352c21c28153fbabfe2282..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6301 zcmdT}&u<$=6n>MYvAs1-D3q3zA44d`hGJ7FznW4hwNllRn^a8*LKTO}?l_)icgM`m zhU8B{{0Ce(Z~%b-i3<`ECnVGZ2mTVoo87o}$gVvtTNMtmch_&f`QDrFy_q-p<*#pl z0Dz0|ehH=sT!@t0444R;ci0YVZu-pQ&26EZLN;4Hrq;CLEQrpo#J>Nb5}K6Y|(362q%9S*jv zlvHJSj2!>{gHZ8E`a9gCt_=FZXIjXR_Lbc9c@SNqPG!BvsmEQPDKzRccbjc-x{&zT zKpz`IE>KVMh=x+rfN8f!HNL`k`{>c=E9g$c1gT+|G!6iyqllm{m8QwhLQmtOO$5nt)*$0ei>NQLo0r_a-{< zNC&?kq8)*n8b2A2CfY?2TT+Vc6$NG$3RCI>u6xqMlFPgfCNHLPSIHnL=_c{0d1y3( zLQ)*_Au{SW1wRl`WVD@FrNdb#v%Qo@D7roFZm&pfR@IuJbyG=~N0C&Q*RLF`K(vds z$&gIQjV#HQ896d)fq|Kri}qnzUcF{p<kmsA|i0~Q`5F%KV55^m(SdaLoEW{4tGQ((0a+Vs!8vR#!hDt$i*@|P2l?Y zF55KOgBQjx%gCd4yH(#P!!ravACH>!?sl+Ai@(3`D`x2>P(q?@j8z$)C-B9?qgwQ0 zU4|D3gvIf-DcS^1Wr);756^R0(&rL5UF(dlv5WOiT6a-m=LmdO9Am3;K1yYhX6OIG z932~QCvdFRx_4KGR|<{2jVG8=T|bU``0bivg-38&rjthC$y)tz@xc6Eld*F7HDRj8 zToQ`(fG;`O!jjVt&6x=Hr##fx1y@YDy*&ceb{KNi@)@2pL?yUL;GEqN9}YR(*OuTN zgc_ZI61;~(Nxdxr9s-UWEDl_$-bmZCb?o6HcpdP75Dzd3%)?Qb!K*4vVZAKllS*>1 zc?7QjobSN-=tT8vIQ}EvO~K>%Ig|W?a42WV4xouZx2 zK>IQWZGIx!nGCeAa?qa5L7TqE?YRuJZ*tJ)a?pmJ(hRikbI=xY(1zTy(0%i9JH5n(1zTy(0FsVN+W7}W`y&(W wHE2xamNln;W}r<&6E!-8d3yoB0p7qr2XhbqO8{?S4qwLmGG_GK@Ge~X8|S2F&Hw-a diff --git a/blade-kit/bin/src/main/java/blade/kit/io/CharStreams.class b/blade-kit/bin/src/main/java/blade/kit/io/CharStreams.class deleted file mode 100644 index b7e29ca06c97bda9d56b9b6a205c95a0f74c8cfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8117 zcmeHMUvt|;5Z_BeZJCso&=%T45v3Hn6q`c%SBF3n5}M*BZR3UkhG7)x5?>?h#7W9D z--6+Z2j2Mz%#;~;WQGsG=irUu1=y1kOPUC4Dekm%=u8#M-uvy|?r-mQ?|%N{&JO@^ z5pGssjKSGJ*{!}Myw)vi+iI=5mcv_HB5VoSn(tX^HB{W{2NjrLa5xrmEpM~6vVM!( zA%p7N&Bf1Gmp)lwz?K*soR?k@T3)zjxe*@+r~-on)4~(s41@7{V~xSYymWX44l+2D z;w>m8RTU1g$9}o#DIQ37n>(g0`@V3kP)N`8m0WjuKe%MpjBbyc4!2!Pp^$IcTh=Bw zPsg@5(e|d0r%gxl!1QEj_N~zFnIR70w|z7^I|L`+)RS*&OPV==M2qPAQiW#xvyi53 zc^Yz^n|n6?x5PZ+9HLOTq{&hQW4D%}{Y#;xzV8ZKgk})=Tp@9ghAOf{smz3`^@b?| zGx8k1Aw2Fh&8txmYDUDv+#OSR+j5JW7RI-iN2nP$xaC;LzJf`Zp)@Ts-0^wMnDu?` zQ3RJ(7H-?zk9obHQaQ*V;K;xILN!BY=UlY0p^e=~%PhuF!J2^?F1*bW45A0<6HBzt zMZ$GTCvabt{}V$y0y#B282889qcUt(DQjm`U?f-QrM}O@o^)`@wVVznFQ)Q_lKpr| z*NJE9FEvMyNQz@V1e*PN!S9P8(A6*0KzjBiF5Kv#u#=^B|CF zx;v9!fy@nDo3xR!aha`_n2{N+BXmq@F4Enyu(C*9Wz zoQtfDOYf(j5#!m^WJrv!8F#7pnhb>AEtYWqy3K>S@WS)BV)yte+m`+ggX8ti9-Z5rG~wEfD-3Fby&8M{lMEis zc(e-7F!+hpjwcB@K&Q0aqq#Gg3E@M?}dR7=I zOxUyg1g7`XV+LLN5@SCRTso>=Yt$SvMrGJT&`~nDoQe9dRXNuYwzCUIa!7?_>P~kr zWf-&j{mk7cnC^DlGwlXGtI%SsO`zMzY4Ud+RL&C*es7FP9&8DJ5j#2DM<qFX9Hhy~fSm8?>PKQg3vU`WSifCWFP{w(IkDN;!@DqZK5A435=v z^+l==8GdKDzW9KjqL6;vN?E6fX7YdYk-wSB^jnzpt1?nHUlh8lIILZTHJ-lMi*LSgNn7$fuI60} z>u78M-e+)u)?J)QPq$D@`ci=p@I9^cD}dL76S``sz=xPed(^JLRlFfgcvpcHyh6+s zpB1={KPS0afz{j{WFm;RUrmmAyLc8Hzy-W<#EVCKo`6T-0RFAu+Zf(N*6?ZI6Pug( z0(2Zd0o1;S$&aTV`wkBO7|T6@Pd!Q_9Kq*gA_Yg`7`_?sBs_&U$MN$7{&FJ5I)@s^ z@S6nd=>n`)jHP7^I0erZBBa)s1qcfRgeshd=SvXI6d+t5AQ*5KUPPPIS=7<8F=z~C zliG5w0LjTAoi9Lod4QDqrCETqlR?TWjC%{-&WuaveyL#GuY++_n1*)>$ITRs`+YEO9Nt6A#$Xoaw1tQ;kN+2tOI>_F Uf(%*2&zIo}bYK~-;Y@D)1%MwbN&o-= diff --git a/blade-kit/bin/src/main/java/blade/kit/io/FastByteArrayOutputStream.class b/blade-kit/bin/src/main/java/blade/kit/io/FastByteArrayOutputStream.class deleted file mode 100644 index 3ca77094ddb04820a9367a7632a567d423d4c585..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2975 zcmcguYflqF6g>llZI>$I`^|!it&bMp4~&U55F4u`f+WUI)9nbO?apR)isIk!$CzlM z-;KY?cz3aM4MSOt@x#9FJ@?!@_uScUKR$f{a2@v?3^81fv|sIT8B|~MbzW_@c}rB^ zNK=)ny1*k-+c4sR)_h~JYr?KsGFtGCgB-)Y#G%cD)#_sNweStYXtVq3mCy_q8yR40 ziSZn{-IIYd_Zfyu_R)v3fxD!&12MvQp^MBOm%5z(3teAOa?S+mZ<)P;-j zA{^{vI8(N{QT=>&aBCZ;bs=?ZW{?C z<6Nm8M;m#orJ)#3>1C~+ygBi#8yMLU^IozTZ|6IgOBj1gha63~vXAOr}*Db#O|B6#QUIqGHt6@QxR!{IbT7H)^vn7!H=o+uJ3N3d4sioU_fA zEG=BfV#F|G>+bCtIJm-aa**osxW@23LylQ^Wg=e~L}&0iX2K^CEvc^d#e$60eR{`@ zJK4r)P}FG>1(A%52+SiXG}r#xhJ)J-#dI?|xcl2a-)o)X6B$J`$d+lFi7*9{82wVv zSiuNJ>28ef9pvd;NPabj=?-u|!+o*8_z`=*($f$o=scQyi9LbhrWFq0AU(whhv?ix z7@~K7if|Z5D9+JeagNcohnCwyJ8t1KY2|a6_}J0<+-zuPt!O84DwSQoKBp~w%2ouA zDs1P|N3-#nwW3Y!uwFJkH>?QLI758SQe|_L*}1J+_p5W>lG`0CRv8yESEpu0xQI); uR_C&X&%zF9)l_b?mfWsdupV2mhUwQk?*1FNNmpQw4wou+4!1CiJ3j$z{QO`5 diff --git a/blade-kit/bin/src/main/java/blade/kit/io/FastByteBuffer.class b/blade-kit/bin/src/main/java/blade/kit/io/FastByteBuffer.class deleted file mode 100644 index ed899eaf47577bb71f6c1d68fd194a0ba1c42dd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3179 zcmchYOK%%D5XXm#WXXzLr*hKwgLYr5q}4X9`-+VMk>LOWl=$G(Na_={OIeI}$px3| zT0QmL&(M1hy%uQE0xgh35B(1PB0U71rJPDeC_xgCT$an7)4g}e-F1Xf3~cC}Wz0#``k->;OVh1KPDoJ1lJhNfA$R`pq=u7@RAt+syQxhW$Zmc^8} zpD*(F2&_+!9Ir_NO>ZtPfqUK@8!(S#d--EeDT{PBPRzj0za~%;!?sdlS~L7w!Xub> zloH;sc|$21b#rJbdT6M?CW@RMx$O{B3VN~$kE4fYF!z7q$hI?7gFe3?aDTebyeTbs z%m`HXRi*=eOXStOcD{Yv#suqtim?4-?}rjB;adUUD|TEy8>?{9&TD7$6+719IXhlL z!Ybs?=kc#iq!ApezeD|g{qisH!k>2S%lKTf76Px}du{j^yb7=3EGN8<&&PxUew&X_ zfHx)(-gIc#c4}CMjWG?y|24ejAl#ckcxQ|-isD@d;kyY0Z)U>x69|o&2|qXqD{ys; zFxpL56hAr%*Wmq`2|qarAIzcQXD6XH2jN#Ip$Yz26w`O}p_B08gt~BL@-HXhI(#&y vVYC+?J5JO;69}J-5%O9eR+g(S9ytl0!e?WIQ64^jQUh6Y5^kW^0&M*UG$Z%V diff --git a/blade-kit/bin/src/main/java/blade/kit/io/LineBuffer.class b/blade-kit/bin/src/main/java/blade/kit/io/LineBuffer.class deleted file mode 100644 index 8799f6c09eafe42af9ff94a936cb84397e8aa03e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3114 zcmeHJ%Wl&^6upzWb>gP96w0F%7y_jUk7UyoMJ!qs6e$IXmLke(Vo#cBZI3k`m-1yu zAi=^RU=ivj6bQ_R%5Hc}_>CR5 z#~N*yIlQqebVJBSOZa>_>U6j=!5}b|M7Ye~ZoFyla9a~FTnr&F*;?01_}j~oa2>9e z2$Vwh=`Gih@(GYF0%OmGFZ2rnBh}g_u3M1~H(>&o_CQyalBx)kWOVMGuXrfkJ?>Cj zdVz467SgAIl5LlJ;WKKLHoBZT+;*A5pn%!CY@5?c!oQCE>q1tjBY8-Dsj0`b-K83r z@cjUpXP2M=^;m#<%%t82kUm9tfmE6%(?U|4`7vah)BhZ;Qqv1uVGB*eDBub?`=M5m zt)-%=RMi?4A&q>8cTh2hc5nvAEOK==x=z=kP{%VEMVTMdO@T9zR;f?z970q}%BcPv z@Zn;cZ&vqh9wb^HO*4xctM75$m6!@vHtfc|Qf*7=a^}})M@cV{JLW)peT0%>H-#}$ zTntZyA+}Azlx7}29P0}%y;jWDC?n_z_Q?77-Y^W#rZ)zX_n4r8t7SnME|;MM(*$O! zt)73Tx-7;1IvKxmuOqL`)doY$Brx5QHgh+b67l`PpN8&=kibG~piKa6eS|p<0kisX zrP++1V;%ZMXu>T5Gm zaF4*R6YYdyJm8dK@lcayT7(A#exF-~{E+b|0mm;>G z#E{anWOB|j;Sqs}zRH;Jr0C0^EVSxmblmESiJ$DhJDe3TBqatC!>b9IW?8u?z#|;UQ+-%dr3p$fy8S Oc#78|DmM!?c>E9MW62f( diff --git a/blade-kit/bin/src/main/java/blade/kit/io/LineProcessor.class b/blade-kit/bin/src/main/java/blade/kit/io/LineProcessor.class deleted file mode 100644 index e353de65bfb247837f0fc7b3b4af35d343268c27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 834 zcmZuvO>fjN5FNMM&BrcmS-O0Gn4Yp6k_)GH)e9;T(n1j%D#6Whtki81N4B?We;E=; zaOX!=Op=AB+8*L~o}Xu)-^`z@AHM+L4ZLz-gFs+3j|wKs=#-taD9KqWqBChDsiL_o z#V4(}Fh*$ydIYu`QqIaOI!aCjw*=f7&t)m?0fEh6dQ71AR;9uLkHF}feWHp(b+6##!uoMxtt7mWpsgZ{N@+`*W2q=-Wt}n+^q)rGTUag2?3N>H z6=l?3R>Jq*A01wBQ8h1FPtsxf;KH3D+=UT={%mF3B$!`Y)z;gutsK=I__!<*p<{;b z5E#!DXZbPHvW{2a0KKc5RI>@(n(P|^|Gz@xzyktpHjDSxvmLBM4!pcEV66`Xh99Ic*nt?0 zHhls(XE?urs|#Du$JoK>^$PWWg8Oyse~003L^og?*O~+P-D{9~j>m8x;~k89_@5y1 c5FX*~al?3mxt=z=XDj46P>lPSZvrp=0@94*I{*Lx diff --git a/blade-kit/bin/src/main/java/blade/kit/io/LineReader.class b/blade-kit/bin/src/main/java/blade/kit/io/LineReader.class deleted file mode 100644 index 9052ed3526cea0e10f81f19b2f687e5c460525e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3257 zcmeHJ%}*3D6n|Y|XLnfy5%2>)DvInX?h4{X2nPu!B#T5r5<@(6XS%zEndzj{A#m{T zGSNiup8Si9uN`C|knBYF$YI(}`|Iz$zP^wC{QdPi04%~w2XX{vV&&EYCc^q2J7D#u z&pck=7rHKFy&*#Wp5ugaV1U4=Mffai*EgGc+|>jM3YS^a=LAX(12y9%0(mpf6$0!m zS2%a2nY0Mxc2@}uxOQA_tag}sowQmOFzBPan1IuGm+-{U6t_e>WI9pEKb6idH@aGE zX(ht;(h4FSvlp2N%r<(Q=tN$AS%gBb5E!m>b+7KAdaKgo4%{Fx(iOI*lvD+{Me@Hs zgo?+~Kj0p9We^FUX(2-zDT${K;#ag(-0pDdao1-GK@oHJS)0>oYuy@Jw_6)Ql#zGX$v=5kyjHYL|tiE(;B1lheOC{xdAhNSA2g zXOf!*Xis<{+h6y(V3BG`8P!J-FBJ`ps~(`P-~A7;RJ4xTgCh0P9v}?0eeN|xta|`6 zv27l3rG&@(!Iep1-|Vm+M80r^rg0LPTa;m}RpM%?Xqs~>RVredgdT5U#CtWmk)X{m zZtOPyh>Gw)?sLj83OZ*QQr|Ecs)t?r>1mnVF%u}$MXYbG9lAWS`RIHqI2|W_yRyu& zlJQ8`~=O-&pz7I>QkO|G`n zfhf?ciShM15Xjr%|s47BQR(q*MU0vzrmX8 za9|$a&FM}DUYvPur`}7Typd*`ZA?iq%mY5E@hP8&F&M-auy>$f`y!NVKLlml55rYN zkKi~5qlmkPpBWR3`f+S0@NW^>a@d!?!Q{uWn_uAe4~w~rZ5}az-#u*0c3gt{K<(TE tn8tk%aXf%4k50JEj+E>11zZakaOI$advZ`kT>v%C!xQA2gBm=Cg+J-(3e*4q diff --git a/blade-kit/bin/src/main/java/blade/kit/io/StringBuilderWriter.class b/blade-kit/bin/src/main/java/blade/kit/io/StringBuilderWriter.class deleted file mode 100644 index 1ae5a8ef03b05df713139ea210323b715fe8a08c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4150 zcmeHKU2_{X6g^6utm8PO2@Qm_z&7P$1JrJzeAVTnb%B~ObOxtp7@p*{h?TBau2v4T z`~rReFFf!!Is*ed^@ShB^zLpQ+o@dJ#f2G$2WxlbtD|$zm2|KE{OgzB0i4Gb2XhRC zNc+V$mtk?AAMj!$;7w7yAx%-LV$En7?p^N6pegj1S{k7pWEhSmrU4K4iq{(Z!Z*|v z2`zb07dnzEyk5D&z&>SIDXTCtJT!G4bj8Bmb9McjSiZyHG*VQC)#}hRC5FX|GL+_h zhIwzN&X6gqrf_hKO#AbGq_xsnth2>4*F!BL6B>#KH02HX$@x1&`f5bfxKn_Jp# z3AZWyfNL`9aQ_D16Yh56Yk_<%NVV-Ym5AI>8Mn=i-*OEN5#M#lxxpbMRv{Lv5Hl$Z z0i?6Yc1LOBCVxxi`aFyw8^Y~zoY*YY+k)U4<#N~D>WJJ@Em2+G=H%)))4^c=Z<{W^ z8R~HDKxi$S~`w1oWvlJ(s)v64|=iPQg=-v2WWmvB&pOPD=6i46pJ2R#w zBZjlp=`tuKxQthc=UMlTq`tUwk#{;GY%(l+<(+DJTF{UaUvxtw+oBR4$Vd{2OL1aJ zG97WqReN%lvN*-?(*!xOH)724oAr6cu<2C?&zaJpmsz~PaQ7dkK1gMZ6jN*khOHxB zRw{>nGA#IkibNJ3!_|lT8&@xrMT$_r3A#~>p5Ml$S{AR(bRneP&r%}C`?^fB)Uzlu zbRVumQpQat#L`r8%Iyhrzrtl$^LCDG$t>PrxIF>4DJGqcVAiMl?{zs(O#l>**)#Y?qv(N zeJk3|Bck23qP>ER5#0K#;#CW`??<4W8G+W!HRYk=LXhTU#r(G2tQg8&g0Dy keEMiM?|!zR&EqYK{T$xLJM;v~^vlyOeHSIXhYxV+9_Fxo9smFU diff --git a/blade-kit/bin/src/main/java/blade/kit/io/package-info.class b/blade-kit/bin/src/main/java/blade/kit/io/package-info.class deleted file mode 100644 index 2368967f8bf44fd4de417ee5ee3f55c2498031d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmX^0Z`VEs1_l!bc6J6PMh5lbqGbKt#LPVXti-ZJ{iK}4lvMrf%o6>~eEovNI*|k%1LRGBL0L0ADF0(*OVf diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JSONKit.class b/blade-kit/bin/src/main/java/blade/kit/json/JSONKit.class deleted file mode 100644 index d935e812c05893734ea330d57f57ca8d183027b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3048 zcmdT`T~8B16urZTZPzM@qWC?cVyoDq(HGkE#b}}wc%U}%!H4N~fPvke&Fn1EKjDAz z$wU*4ul^|Got;t^*+NMg6JKC==bn4-Irq$Te*OOX9RQxe(;SQuxECq6>N62kci0}Q zc0AVQ)m@>hJCO{kZ#LG~R)o&M1cB)!z+=Hyb-lC0T}|LjT?9fm2#lA?Z2}W7WS8fl zKw#=1_N7u%<>4$D|M@mhJd)lX?^0L#q41a%GN7T79gq9bGIa{AZBDz~^_aq-kh!~T zi_`g}s|t2iFzhrE2J1iTE(uGidw-+Whx>X2VK4?0&H~?SMZs|o=!(s z=xQ8kvw~5S1%{hVoJ#2wR#}+QFV&JVsy~L@DQsvZf~`>mji^=&+oHaRlCdrCH-@bC zIF4acNuOe+y6t<>iquNjOhnw$wb>I>SYgpu_4abAL90luF$i5x#rDXw+ODhz=40MJ>&5oRuBznD$3s z!6QD;10~=ML3fyO7Hpl9W{$=;E-xQ7DuI>yN`~17YyiwsZ>`i4duL?J!#x6GRNPM7 z76h)9n&xE8X7;?^%3y}u*g)#77H-i@4kbdIQE~YH&us$EhK!ZVUkP&{7kk&bI};9CJM!X=EFO=2&D$@CEOA7r|cktv^K8tdV&_VL#; z@Ygf&#T5P~+`?){>)y`5O&`MD>DQglz~9ZlUpj=p-^VXx;2&h*=lb|DC?|?NgeUml MfeCm7k5RYkALDe9TmS$7 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/Json.class b/blade-kit/bin/src/main/java/blade/kit/json/Json.class deleted file mode 100644 index d80a70feeb8288897cb44b3d93c8002771d94c40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9220 zcmeHMTW=dh6h7mo@uh~AmKMTwd!cpGVwX~Gu~P_X3~rnYiIdWnQcczqXPfn|wU^NT z0VE{E3*xyvAR+hxAb|wW^qn{U1Ft+G&g^dO-DbQyjto?V7u)MO-?`73b7t@U`NK~D za2{@?Aw}S*ZKv|Ldw@G27I)SyNHXc1P2xqnU=%vCMUywe3kImu+k^rO8yCT1eEP>K1J=<(Owv z5p61Rn~o_>li7-4I!c>5>Zal#h~4U-O<@okRpf3da$Sn|vG65n?T%?VibtTCib@U6 zbe$>p^xQQW_p=l~X+qc0bSaKQCG^}T6uaVfI_M_*GPMlNXxRcH#W5ACIJY}2m#wus zx~6K5V!It?Vf+o-v0T+LEyYjA!nmT@ifc64hGwv4QJHsbhlkaJ>9-Zl*fzJALNP>} zQ4W5T!Yp~#*ENS(R4=SJ7V0;SG2LL6&2{4W($;Jn|Ms*~e3A!^P0esvi(4v4%evVo zzpA=P9U-LuN=?^Ui|W%>%WX5mnZ2d5j<+*+N)Cs#Kf{Zri#uAVMa&T?th0i-DezK)mXO_}{W*ZwQJ>`wbKH%r54RzB+)T$MH%fQ8Mm7YFYF)fr)}NZvtlu*JO6zR|4$PUD)5=xk0 z67y0b1M`G@I+Q?5H3-T1BE{w*9{UN5g^!CMSogA_+AkY+4%$3_`iK2J0-ybJVV4Oi z-V3O%v$(P0y?waKER(=Vp(}RSnt@dUx`a70dPsJpxfRp3R94ma{Y92vpnGpt({Kgf z|Dx;Da1GxG`yEXhu1DTD`)Ux#&-<_48h8h9!%Kije3QKg#$Ydu;;%7C2j3a*`v|1) zW+jJo`@A>ad+--P?nlU9Ir!-JaNuWrO2Hxg9Q9U?z~lHk?^D5HID$`EcmkdbI830d z9)~djhZ`P;RDgRrgyaADlAjUawj#LaLb#s1=LNWrBDkX=TuiLzejNAWN{=F!M!ZRo!{vfa;S^T!mIFF2p1a%aw3F#9mM(ahCtrA2(FB~ zt%8C^Q0|n#LvIQ=EJZj>hcxbGz}o`c^$6}FN}ff@DX0qMz9YbgcSsE`b@6iod|iP5 zA|$^C3tjx80KX)_f7!)nU>R0~b~gmLue!Jtta%n+h7a*Ok2P`%-iNDL!#?;6l`j=- diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonArray.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonArray.class deleted file mode 100644 index 35653d9f6d49ed8d534d7b4b1a42ef954d4d6f78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8627 zcmeI1OLH4V5P*9W#d^dz4+yUi*aQf2609VI0I_2*eh>vE4w3B;69{AN*cxXaVt1t^ zoH%fxxaCgq2e@znszMc9IPnYk4V*Y}peTx-S;<=PXm=JXsZf=JSG#iWH{Crw-94k9 z|GM)70Gx!i9ApR_^1XW5rras7(>5)ySkz?Y>pUp0`>sm-92jc_^HNNK1pylCzkI645s)-{@+V~{CJ~Y7{9!wJ0RvKL*kezl-mV<`~ z?37wt)LARfdYBEwVzb)jWh7hUe4ZnHP*tSKX7^Mpk0(4bDcmW5$~QKoWAu^3o}c9ygOJLSpG-1kKmky4S7JM}Ah1|m8LJjFMZqf6al2k*QcHUpc? zs<9^RPfuxEMCqR6rY+ZJO5Ib^HRpM-Vj3Z?JK)MX7W0IK7xCa43#KjV`{+9E8!g9V ztK7jBaTQmu2(gU-lpzpy0||6tjCR9Ngkjh{3xsjhJ}!FZomEunLd#xZ z-hyb#2<)l4b!sh9kBjHdm)W4fv2iaYcjwX;?9Gp8%L+A)YD+H*@!c)Qc1^x2Rg@zV zxTK93)wLoIPZ2l}ziq%>1MWYlX$q4oDbNOinMAbg5aVM)jC)RdTp>M|N_r-h^l}R6 z2~|w$&&>-2*5e&0w{!z)VDthk+?#6qAP}HR;;ZNft`tubZ%9uQ za44Q8;!r$I$ek%w6nRiL<_OgAea!<3?I6H&43F7v8*^{g=O5z-9%obt5M%rP1zL%ZbiyiW8PRoFVX;MtEw}*sZs|Xic|~A~1~BR630jR-03i z$5aNsN#J)41G_`Tr{eHvBe^xyaF^zQTj;t8Y?m#bUhxe(J=ro8H@a{?2X7JB5$TQz z?7P%*0&cU4)8;^|DsU?!=#Ew9ezxY)CdZ2Tf2PumGxO`hhk zM21BK(^QJ8fs;~k>UgG$n=$4DXF2Zfy?O(G4S64Hl+4@+%)zzp6IO&AP%Q5v@#mmU zU{`N57P>wMXh!7QuxrIScRoCaSir*y9}WPv0r)cw?$Tg84B=-EpE8h#{dix1B3^gM zpK-R~9YFDW7{0P+S0FU9dOUU4N=?EDlJRTtk zUDFW?@B}>BAsj|qdsggISg|gx5PA~yz|)bDd%8cPc<+YN`u)rSyU2E!pjjIdRaj+o8+33a0*`0CNz|USK+k?A$DbvwvwFrt>+ZnFBDt? zRrGg8N$c5rUO`jmqeu6V@}!%-F#1 z;HCehQY*oG|4&~l&a7i%l7U@CQH8MNotfS5eCN!Z+x+w2U#|gR4sHZ6L7;AQ9QBxx z(Iy+PsGYD5kDdw}Z5kz`-|*2AmTQ&-P$F>18Mw>9X5v^D)n9w_cWPR~Q1bt=y8iRba6&PCnOIYzbVd=Sw|uP(AO;VfZe4OaP||930Ch0@Dxr z(uy8mk^^A`8hFbUpR6LHePL@9N%Iw;1pX*cJ4X^Zt{bx=2U#S^2vn>Z0tpYgwLuMw+wBQQV#y^oi^64YQ4 z$~db*0F`X4ZjE6!hWHMv9OA#g*&Iqu;28c5haT6C{0X%;xSD`t_$(s^;43(ePlrbo zu1??xa1u_Th($ diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonNumber.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonNumber.class deleted file mode 100644 index 9a0516d1c40aceaf94bc75dba3b30850229a2ec1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4256 zcmdUyTXP#V6vvNp^JW`JDYRTlK?K^^5NryiKwU~pE>mYr(`nLl;7wjDw$inp>S1bMW*OB}`XMg|m=U)Nf60B8Viomkb zQDeY_Z0xfG*675n%NzHFZR{H*8=H8!H5_!fuD}d|3%Q+lSv=$f=8V-s_6VG6r`VXu zUSm6LYvR+ZLJE70!0GDY$F*GoGpnl0D{z9q;&}MF)=CHP6q)_{uGHM9_<(n5qy~wI znH5UXM5|8B2j&V5=Xd&?c6k&tjhzw}-Df>cm(u0cad~yOyd~OI+)$}39WWd9sl`G3 zLBbu`PSh&O zsC}65jM^7mGadCGQniejOEheBx#6q(1kkP8piQ$C8Xtg{XxW& zG{A?~H7U6eck6&_ExNo6jb%>Q+WIe+Suh$c+=d?4o|qNf@`CfUmFyk+Bpb0}_Sk1x zQ$zHEW1ptXBe>PsN9XZKp8S(JUmI}SS6$lUb~R?kRBO%%hO*1|ghb=oQ`+Yi1&>OR z6@?JO;sR74K!kNv1LAe`D zpPyRz37-B9@221+Ugxk6z!`W3uM6q#5Gl{%9p*tejlIr1>h(N+k7#a8Mti|STlUZZ zUV^iz@?{)3gY0u&?pWok9`1^VOW-wF%2oNghj!6RI}aCfY0DnkWiPD;Z|2h8^3a-I z+S^dir8PXX>t5PLcsG~!o`<&XrM+JuZkIi@O)u?3_~>7>jZerG4{ggsn}(}+=BD6d SxQ5>VtN01Z*q5g+TF8~ ze~4$^kctF6^G6|O?}Fkcr`|Le(Mo->?#|zQ^X<(3n4LfWdi)yzdRMLwEaIVJCw$lE-^u6w4MYFjy^2Vv&yfC5Sx|9;QZG9ZzM%L!D$Q z7EbAuXGWvb#D2+x_TEJDNQSX62+BlwB*v1j7s7ieyyu0l^GHj}Q|)*nTsYwljpT8L z1DQ3#vG@GgdtOWL97X9#C7Cvk7XYPsC{j;4lKdZ?mxkp|#U#G}2UtX-Qr~W#WjK2K zgD|N|$F>5*o#ukOlS~Hffs@8hnHt!(Oh(ewfQHJt8py6QD5?fT;2}UruD&uxoXm@i zz(e)-AdlnkwMsEN_m4xF73=Kc^q$Qm!8<7=n>vnhCE~)anma+;`?*^(-TU{6Bzf~2 z-M)x(IR}TN7*NwhBAai(sL~3rzLIRa%P0hq0G5Mn;k#3?RKK04(lvZ7SV02QP z8GZ}nevG)^A4p^Ua`0zKqOA4XO!0qd6|_k{2e{(KwHw_9Ww=ngT&3qksq%~ySr)6X z*klj1DKNr}^F*f3^3JKpE^fsn-$Pxyf6h~$cZb>tUPW+ye#3Rw=j!O zuzHy4Bgq9`U?)#9U}f;1vXf#;D(fhq00LN9h8C;*GQ=1?$o-Y` zv|F(@)S-y?g;BnaI{modCdxASVtBbO$p(Xs&Sh=A%%+GU1~)1OG3f3u!CMTrp58I> z4HHWAu~B1WqNfsDG@XL`JqEXGxl!R*x^rPJbF|SNEWs_3KuS^>T=A`?-B`OVZ5RZ* zIya%*QZY(i@fCW>QnYdyEDzFDn$1{PD{TwzFt|fZA%m;uTU{SN(dsJ0i7vLwJHQ@Z z5iD@PSYTg`!5X{*i}^}5~l+JWQJD72jPLqbAZ}P5UE7_G6N$Y7| zc;Jyg#0<>9J3oryXg4NFy<|158R$$Ovfhn8edp+tbaZt7`161cf`>3CG`cT6di<-DfCrOCnB`wlo6>MFS=s>5$W@pU(|T zt%$t%{u^MXMxlSZX_DaR&9_WTTv4U~M6IHX+T(;b>V3;K!`Ul= zScNn@6We*O4n5E+&dv-M!l)Y~#`^=VjoS|HEQy6N82hpiNAq5dx|hv9?zj=xCGO97 zh8wj*g?z>-k)LraNg@$sLH0oD48!y&jk&ajwofc}Fcf>)9w;2x#gSm1?m2Vln}<~| zeP4n6*5OO5({mhLFYQ=gIqtWZJu;K|K(b`kVvM~wK6=gDV`(sx#@huCcM{BzT|(rW zitS9e)*>uRs{hY0FOB*;zKVFvub0L7f#xfIKXzxluoM@KOCKmTFeuoHs%M0 zrZVIQLh`Unw^F<;;iWh079C^uFi}UGGQ7Z!&of|V@UOCaY3h~M`G6YGgg2W|hZcd$ z1@#J7hgcb)M%$??q3pT5$(2e}z@mMoh5J7F=b{}8L*Q0a8j6k{WxvEGOz)-EmV7l@*YH*dn*QF-v(+(GhRjfnt?^70`jdSywYroNX zg0^>6sssK&xG7z6iF@9dRd@(A`%-ef88KtHslrVH*Gt993DEYm;?_M^am!~2skibg z!5-ci46Ffag=M`8v|tIA@vQ|_sNwGt{?(y@?XTh6ZA3X-<5y^Y*Lve;Sp6NpD)1IQ zmk|T-HeAAIGkb5qW&8$we+S+@!{Bf^!+Wy~3uz(475Jc#;ll!k9|{>h28y1pp>5~s zI{r>abn4G11#CYSvR#8u|ADRY_vnh)ekx#Ffa}<&0&VEHzUUop4EPLn@8S0{wk*Ks Fe*q(m`Gf!f diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonObject.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonObject.class deleted file mode 100644 index 876de3fd9316fd07474588a7d4417e83d238ae71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11454 zcmeI2O>i7X6~|w%B+qIiTaF-xBu*F`<7ne#Wx)BAEaF&JyvoW7mTV`20HfX3?%4B{ z`H<~E_zHvo38ab(2Z{?fj$A09DqJb9TsXmvD+j8m;zIH7nf(}hduDoNQAw(N@M>oF z^{-#Qe(&|`ZvXkezki>IPSJZBl^8t|_{}-nFrB%p#*Q(!Wf?6#cg+mvt_H3%w}Owg zt*g8lYBbL1c%krR!-_bg3CFN`z-V8iVFuwmqseu%?HFO?mm1rGZcuea(j#W1wz943q%svFA!4TD2OO^b;kFNn|lRQ;HdU@A+oHO zT+_kqoV(HFUL0q`?wy`Vh2E7+a@MshL?QxP<~x;1(a%CcTD0*q? z_uJeLL^z1G#5RKfxi3y}deW*gsnlm35!WtEbVHgUP^-G>+@_S7tZ|0tS!Od%vfHj7 z%NTw;vbhrm`fRtyDpIjh-whW7%g+RRsh;Q#x+(OkWZ%0&YJT{UwbL#Zu8-_k?<%h5 z%nFss-iXA-Y=|72pC6Ux?UECqlE&_Wx7Iw=$f6)pEydP$xbK^-qN4i4ET&|m`kJam z6y{f{$GsEUTjSSlvBsOB4yO_21B&O+kD9_4lY(d#^+BLV*nDrB4sX@;)d-s$2gSqK@i*IUaUQ9Gz5E&p&YB@z|`guu$Z2b@5FhKNC5&+cLLfEfZ@n z+E9n652Z{xqa*nTGB}UH$&S%#F`u?b zJ{T_`I5=Q*NW!UC>x>?f{7`Ll4;!!~Y9NU1y&SPpUBMNG6d@X+eHrbSE!W7F+#BG!s!SV}~-SMIjQrxg%PK``N^I6LXf(vfA>|+1a zH*cA)F?zAsLMi(f8EHE5T1LqG*Q8K#-HrSvUp7TI7qdLfJQ&L<=e!&V87Mm0$>C80|6Z&iYLMAa2kd^Z}Q1j6AIL5yKE!X!OJ4|fTVV*GFAHpXQYJV62i|j2(u}|cz^UV9sZs{sHO-5`^gCZ&LBLR zBIN48_Gb`IqzJh>uwxm7$CL^48HC4`2^Xb=nz}zQFN2^wo9wL&g7R##Ut|!}XY)51 z1ohecQwBkOHvg7EP@m0zNeOdwGUX40%p{46(g7*qv;Dks3VCHf_}p-GmySybr|1b~ z9iEaBo}{Nzgxts~t!5COP7wy9kl8^V7theMDMD_3D0QSdJVWy-LcR{Rl(0ajQ-pjw zyqQ5*OcC;Rcw0*N0zH=^$LL|#~KoXPTSOm zK4M1q;qS}Tk<8;&$vj??&`M-wRQ!^-8GBVim>?UPl*sA&y-Ob6iC)9M8GP?!v>|pK o5&mAs&f}-}{$cca1A4zs-+=z#q;F#n@;!Qs-liYYkLlh20etJ?ssI20 diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonParser.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonParser.class deleted file mode 100644 index be20a447110c968bcf20d72ac7855add472c2815..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17043 zcmeHOOLyBu6u#pmwc{pDNn0Lmp=x>5Ng;+(UQH=YQk%MUk~VQt+Cs}%9>+>#Nl0>= zZdkBj1HXVBOO~uSr zwh2ru7MAYKujTW(m3ym&+c^THKwx}9*DRZA_BvG?YzXH|6F77^m!DfJmV)H?*Dw&+ zXEL1EB#u`d!hk}3L+><*fp zTF3bo^a@MDaeRLN|D0*+W(uAo$7^ev$t+#H&nl9v*9}FbwxVm2Vd`a-)vfbVdbCty zQiaJXHIc}m@)q4-(kVy&GbsNVF8@9$m-wp^2J9K^N_lzeays&Iy@aE9|T zvkStVNvRvUX-f`)qDwN>IB1zkO+KS0bJZxANV0W_O7=s8rAJ%T5Q;VwQK-2Wsa+GG zrAPnvk5I6Mx}hqvVoO%TU?yrG{lIL zQndT}7LzC{sMd;*9u37pD5Ao0Zd+!CW0sFwLr_WFQ0vUD=@m24r}qj+)(R^Wuccjx|Ra-xu)hpT3d>7v!>W=6@7q349@v=B2dJ*(KEfIqX{(i zp;uj*Igz(TP26McnyEj~X3;p-P;dV%%wwJLADB<2qn> z8g<8}M+2G__|qPiwA4`5h!w*XUNReT*ioLURvfsl7-NvboN3aBG2rfmu_(g;SKLyg zUS?(#9QWRvyqx^+I#d**3q5^9JFYG6zoQSJ(x5ikE@-{AMhR@3V8Hu_4Xn(L8f_Cd^XPCC2FR zHraQ25FPvjTrnAJ^wGiHc6GM2UmBF|oFjexmi?XMu!AFk{-Mm46D?6EgBVj-pXZqr z7c~ze1P)`C@eg;q!3fjI1wy_EkxoJdukdd$`dX|(=jQTtWfM&i5L*TumEl>^6ud{s zFClajUhKOZCE|?$XFQHt&MvO|a|%zf{4}q(HFQqkreJ|2&J2{i+o$?d$vt=q>{{CG zXV|}!S(sW+!TW@;I87_A6FSt1MSb zY#ViwUez0>%<>AafKB+vXr1P`By3`L-wG;;cQj(-;CPGFlYn**XmWJ_M0OY5R;Cj6 zJ6RxM!y<2K9D}1U0{ieTiFXM|;r(dfJ`IzwAE^MZ<8Z*CnZW-!?LqJQgm<0vu7|wq zVefhbo^6Uxi?m%IS$kr3-jTfPbcte=Ef*V^h)g!Qu!s|bt2XY_qYg!P*cYpJVe z{8Nav4A(p7i%bZyZghopOo+7tt3tkfn-Iv0Obf9}UGa5Rh_%*@9?5wj)_PZ1mxNe1 z5zEgszEyqjxV4jYA;Rqr5bg>Q?x4Sjc=%AjLs@_Ta2M_c5PV&W5JYht;NuPu9te0y z07YvNJw;jY6rTzaDjgt*GYIPd;d3Dm)eaE86e4V3c27VJbe`og^G|~UTTuTC!|CdB diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonString.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonString.class deleted file mode 100644 index abda669fb4f4adb56f8ea747fda6254e07e7b57d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2908 zcmdT`TT>G;6h5Iq%YuRkc)?3Vg;uc@Zx7aS#$j;4L2v|N^ex>68rUXlk|O*LU;HP| z=#0MmL;M9kJDzMUt+KNF!07m}yUFI{JKwqFoP7EI;S&JdfxB7gA~0pNU#c@9OIvJ* zl_~+N^3t}jr7fdm=?T78tQK-J3*7`J6NT4U(BK4mO|*%?@L~iTFu7T30+n&~fsn#J zBruvkxLjBx&^@cFJPZ8<2HV@`v{pI?$4KVu3#qwL!49udU)4hqFe{X#p;ncE*Uf$E z^{v)8t#UtL8ihjUZ?jEKCnEETXkO8oH$kh48!DBhb!Pnv|rn! zY9r$2mS{UBR2V9xucQ&ia%oXXPH?|FJ#}tts!BJxoeh{V`GQNghOF`pA@O)@ zC>@uRN0@^icrZ8sS;%1>SVW~uje3RaRfdP$RTky5V2x?v=0AUS+nO*03X6$_su>| zssE>T;2~R44ej&C!WE0bcGHZyI67>hqjAo+8f_M42n@CF98H6>aQm0PtrIcuR2YN3 zd==ZW0ScH2c(cON1U=A;BllqS!ase{jVl9P`1L-5_i}jPJskgxvo09IcQ48SjKK+f z4@6@RQBL9vU<5`HcMM0}xN-{4;K<3J#qUAf@fh5x7+eD9;R0%pLvvi3EHB2OO~;~L zf{8@5%Q0v(v1nIeG7)Vm2JK!fS^=*80j(X6>oI8M7_7%Q6n>Ms@lQk2mKNwAYzwqbTViNSfu>N>CZ-8)QW7Vn<#)24#FMOd-Tg@$ zxN?L8S5DkGA|xavkcyBvfrL14;mm~taDyZ8W+%4S@pwHh5u~UG+w0vo-@N(WoAE%s3QMGK7>22}%wbC5L$i zYH3ucZid& zYMDoSA+t7a91*KoX$m(`m^XB3jd-c=NVSxX8YbB|Kdl9;yUMf+<9C_4Bbd?Jn|E#5 z&X!kPQQ&ll{rXvAgW)Cv%ew4v8&%Yekhd`;5>!o>VJ9J1k(EE|>i~K8f@3f6#kdG7 zjd5i?}cQ!C7Md8t$JtF=8M1k|%ibeZcZsJC%( z+SW3RmIhKt&e_2kyAX{K)&aE3>PC}%Sq^uYdLyy47o33s*wqJpu$#c{Y@yNNN_K}u z2Ru-~>U}b(%rmzr+AIP)3yw*xIf|_p{$IP9@XH*V>lE&sQXVU20w=NsS)30KcG1Vz zH@KIC0|d53){=sU2>hneackFLo4!ytNtxC@jzp3T>!Ko#&|xce zw~GlRSH!!hsRaVZvg6vmnu5awCgQ0TuYYu%QOrJ}J-d+3cO^ZlEuDg61gh~X3*T(% zE-kI&G-5^9v~|Qt!@b(;LVQ(sEd`GgI2f-qnggxPy%E=?t097nYvHBTkwBVz=N-pl z)W(;A+$*{PhCCdUrcKbFl&-qs;9KWD}mE>CF0YNoL82} zp}sE>^6tN`Z~8V`f!i1oNqKin_kcUBR_NmiN}*PQVvL$4@U4cWY9l%%WUcKNA+V;@ zTI(e}=$~{S1kQChOKSF2Rj7HHz#kfvXsuNWY3<7{M76hYy4wn=mt7Aq{jF;f)-syN zy{{6mHOSHQ7oCO)eYZ@#vN)c@G;>1)NCL+@SXp$elJ&5)$;>!`YqC5ST}^+zoefXd zaINFEI0oXL&usr9$5*tjSzb*79x(RG#vutw)|5Tg(D@bw7UhNhx>$?*h)f2lhe&_ThB`pX^uYCeV*Ip+BfV zw?g!uHB1BLTUXhNbWnlxb_D5RctjKFQ3cX_O-M&#k%Z=wI~CFgO-R{Tq=pq#NFOyJ z4aOqH>-1?8k}l&%6+C^_gmgSsr}))4PIZCsmlEMgeFTzHBAo65VTTgosV)%qDiNNBXO#YMrqv(F5hcP| zcvc(Xq!QsdIH!$}S0X$QBiaa8l?dnIf;IwIB8S4Q>A3an3*SkuT&Pdz)&AVN*EM(isp z(7tYiHWy*Kv9>D;gzuFISK(S4eHv)5DA0aZqP>PYpwsG9Xur0iB>-NBH*j?g8*YI& ak*^-0Fps|g%lPTXN@G8mz+e$G3;!E0)5+2R diff --git a/blade-kit/bin/src/main/java/blade/kit/json/JsonWriter.class b/blade-kit/bin/src/main/java/blade/kit/json/JsonWriter.class deleted file mode 100644 index 7c2abe7e9af4d6fea378775b23295acd739d7250..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4410 zcmeHK{camY5TA9^*uJJoNYfSyrQ1-bUBE6Olr|})&e=qlHJ#Hxi7tBVz-E7o$ z%#BjBWVS2K)=s5fCP1nL&YG^{E9R(eW)Ju&-1Z6qQ%E*uIwz|T)wSi-Wf8DjmlR$jdUT_Ew~HWd<&h=^wWo$$i&8;9Y9DeNWg-3D=>XbUQZh z`>WK*wtJj*xn(nnLLRgB*)FF`p>qr9+(O{oCE9hlPaRj$K2uhYDqO^$dFa;hMHrt# z5T8PzOW|)2(N3c8xl++kK)BRmP5|2Bbf{-yvB)(V1gc!hs5GJP{!@C8#Iq+3rTDZ(Uq{2CH_c>*#X78^EMmCWOiG*58 z3TO8?V;Yrb7Wcvk{?l>eX205VEC&)fqx#?a_7&XGf&O3QMzt)mYAvXBb2Yr7>w|uW%QnOEMPQ-kTFl;NQUvpuIi-5SCy=it>=v-N z&O8kYZY}5?n2lBc=$iG@@Gh3zvD2J^>jZvCP*zVM9H?n%NaUm8EK(!`?-O|bV(Oi! zjuMy+jVnpX4jUeK2%O60w=+;A@O=Wi#$tF(nN5N9%(Qco^+F1b$E8l@rL)MA1$p zgf8FZs>wZ@S-j63W%iiFqklSQ=AW1u_>92SfA<0Qzj)kR?m$}nfe5aYxzRHs>|)bU z!sh#N{I0+Uz}UMYavokEo5J_8eQRUO=>rAKOng2Va0yPsG|tjEO93|IkVP&aJrmQJ zn4XR4Y)t23Iv>;5Lb?bGa1Phc;Yx15Pfb!Hdz8GDTVUw7LZyYvKJ1BA`VnVL<$tq55&=N+{Ep!y|SIE{bfiX z!JQw4m`x(mR#8z8YtLA3p5DBf{r%_rPXI6QG{PLiGw)=Q32l-CaU_y%Dtan8)FCV^J?>0syt|GB9s~CN4Qj&ezMg)P%2`41^w-<%_SzoRY}lTPaE+lcg={)!T@?++8oS0RZ_^{yUptkV_2Bj+G+a6HXWTp@og-fVkmH9hC4GDl9>$mF2V3} eCd2(pFua|?P{IS!J%@*QL^tq+z6#|WD}MoZ(h9Wz diff --git a/blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint$PrettyPrintWriter.class b/blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint$PrettyPrintWriter.class deleted file mode 100644 index 42854ad5bc8f78eb19ae68cae4afb3fcfa84aa34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5017 zcmeHLTW=Fb6h328Ulv0`fL@?2(?G!~t=&s{BdAhjQOT7ds7a{+32D50Vo%tewPwc& zQQ!L1$3FG1RBF}sy}zNqrRteko2lE_&gAcZfBO>vR^ZDD zlo(t~wBL$^RIP2XBU-&s1lW2gO=~-eRqM7!WA<)qsm!HJ`+F@7>I%#;xboEb-w;S@ z%;30G0V>lT2%Rt}-ET7}r$Y=_hdS4#lIAN0CmP*!&g%X4@*M_q?Kr>+oM15Td<=!^ zw{B=1>nhB%>ObEpjY%BtV8H!28p==@87n^2aWBLuxyHTP<^Xwseke2<4Tb+u^pP() zvP~k}v}Bif5M#nsYr3+qh;$_x4P$M%GmtU&g|eVM z) z^fd~D=};qmEPJ(17-C<9Yq~$OfHxlbICN4UWXMg-1-Bk~wKc89UXttf`VML>1I&4u zMMyoEg;Bu;JL^Ts6>`m{-&p2dtNtzA?Mj7>Wxl23$OY!f;59RW9Iv5q3w2_3v6&gk zB$2A`H0Bw9z1qw<9+l3Sywhk8>`$-`i=8~Y->Beb;r z@!*^pNGiOpcb{6ZWsaSL72hg@le_i+b4U965EX-C4eNvV_`FOiaGr|2j8+WJe>+k} zM%Yn1GLhucnyrXjnMNLY-ARV6R^b9;wVY`wQl_nh>LUU0&uBQEb4 zoN+@p(e5!BvEO6x$B`Ag82yx4O7<}`26abxT&KHD?p_sI41OsqXq-=gOP*UnCH-_F5(kc-Qw!hI(P7jtnhPKA3Z2RF>c zy*w3eo(?7#_sUebc{==%i`$qAcR5FgA9Hc9PKBGN?@u|nC3qh`plsaFvxB+S%<=K( h9IRvTA?0HUK7x;JUQ(_y_yj(s))&+-)0=bf*?&XF>Zbqz diff --git a/blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint.class b/blade-kit/bin/src/main/java/blade/kit/json/PrettyPrint.class deleted file mode 100644 index 68447a1cf8f93923d112ec83d2d9ec3dc865a0ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3625 zcmeHKU2hXd6usj(vAr0Q(9+WKHAzFePQjL1o=DXyvZ&-@2x?Lg;%U5lV-M`kSTo~5 zep#hfYTx+{{FbVBcI~nPH!PKv_Ms2<&W`WLIrq+Z&b<8Nm)`*37Tl~sg+XXd)JcU@ zou}eRbOwotvGYv2&Qq&Z=Yc`zjvpAQTn(xWS|?gRGSZ>xYIP`w49-XuqjKGmFqT2( zNteOOH&RLWEraFoNw@WoLA9%6tic%ut6BO)sA1=hG1}DOEUUlzNg1>{Il`DnIvvYI zIH?sM8$C!cwYPcDI2a+1F-n9Xqp^sdi6QdMj7OVzv^|ea9&5B*X~$FHq7irGgfGSz zxuO%1Yx`2PJ(l(xA@WQz9c$xwW*{|>gz`ZL$Y(hJvDw7QE^I~7xkwM`wp9=FwD`@nR1cxHoHN%Myc;`igxul{{}-j@o) z7C$sP%^LG&^V)?*PIDMML}Ptj{K`zFwNeeU8uJ3)ps{d{rwhMSMHkMoRM!6sG2POq zTZn}>`*h)#T3QR|SSo8Nqkjk5f3Qb|f7wNxMP-T~Kme;vsKFY83t|7Y{@Hh=w}v}j zAFcYcqsOIg^~V!I$3oiNg8Xrf1*4q96LJ<0)NCL=o2uw5w^sVeh>%U1s1;&XkG3h07NP=U#)SDiic(Q8_XA zI_&3N-gyV1A4q^sEg4+;aiW||v8RrtmDIsqFCa5jODTf>Y(wtU;WGxR1ofH60+uZS z*w+&i;rG%nwY9>6$s{q=pr;fm{6tubwgw@C+hv#BRv}tm4hHLQ&DG#bx+ctiZ{Ew5 z&;f}}3md>-iLNfR31AskXtWGf+CO!gX=GQLC8*Fd_!WZ3=bJynx!>un0_*g>LN)*& zktaYi8wci$*u-y-MTlKLG{^ BiRb_T diff --git a/blade-kit/bin/src/main/java/blade/kit/json/WriterConfig.class b/blade-kit/bin/src/main/java/blade/kit/json/WriterConfig.class deleted file mode 100644 index e2092f533a3a5da392b33d12b4231e1bb3d76c23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1043 zcmb_bO>Yx15FMwXX|{p1g_h5Q=_wJ??g35|A)%^BK}lP+p{OV1c&CZmU3+DF3kdPM zkU)YvKMFD4Eowjrap2;wd4BU|{QT|vr!N5T2=29@!JzM~Omd-gaw^V6GRZ`W$(i!W zsWUoxWtB&}ZS;wnwxG#ir9x#wPm{gLDN4_vH5%*=M$d)}9t{7PY>Po>|6pf4K7PG_ zFxVY4SbUg3#x4X64e!l zCdENZ{2N7`N#%vHo>u^6xD+~&PLTi98MOy_ktwM>cV&T=bZh5rDZR10Zf38~mE)yO z@kD9Le?k#ji!$@`=$Ma6=R<^0T<9RUCZ40LRrz-Xa*c2J{7d%w??3Q7P>^Wq7HVJB zt@I4TgQr|fNSTn-6!bHb{&G8(7KO)}uvbt0sJ(ZN)~Xc$P&xO83m&9I?Hd0dKoKm% zN(Yu;mBD&%cxjSDZ|!%#bMLWlp{mV7slXW zZ&-`n>i^x>FUUt1NCwfNDXqlkDr8%&kL&+ad8Y+;$m;bmWgIEzNbHze@8ZxK8U%je;A2qY1DM R8x`(mHQs`|G&c!z`v+-=I86Wm diff --git a/blade-kit/bin/src/main/java/blade/kit/json/WritingBuffer.class b/blade-kit/bin/src/main/java/blade/kit/json/WritingBuffer.class deleted file mode 100644 index d16b1bf8218cac7369f12eb21826acc424842a72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3500 zcmds3Yi|=r6g}gZtg}f;Y66r7$`EMl1h9doFM^QT2!tg=B$B48@}XL<$MJ;S9cyNs z$3NkpRBEO6JHMg7rRtsCCb(s(H&P-VvevVYGv}VU_wLzw@z<}v16aa09!d<0Mu&|! zkV#`Z*a;f#DCmgBGie*!MkS3OwX`zX`hL*u3hklHFq6WfAlYiHwzoxS8OC=BB{V~& z$!cgwYC}LnudT>uB(%xs7tR0{iHVCnzI>N&=!}QAl542Xgf)82w z&mR&kjEZ(dhleWe%P6o?CA_ayI})+E%l(PTW^v zyrYESiLyKnY}n(LCW*a1tz&o+<)rR%Qg>SF|Dnht$+)kyO{cBD*GQyNF$su)XS=vkUCJ`~fRcvo~5s`1*su_De%dEs@gS?%)l|D_m8 z;0WXi6|GP*j=i#PB&v_oI5UMw%rcyrAaBO;8Vu@_h)6r zJ~pp6B8KxhU7TgA#@OufW$OL0GJ5OMPaeZq&2`ibhUdqZr{eEQ5d$QxVWfK{jPGX&Q90nXz65211p^8%&r?V63){9IAMTu^h1g#6wc!#x^fH`h8SGLqcJdij5&&Zk!F^O=@Kr}nTyD2d{x<% z9A&q2lsVq3BYDddBhz~=hxgmp@P2j#-p_M*ALjBdU~wd`t3#&udJgYKF7M4F@z!&A bf6n0@!!6QM!fo845%`*p3hBRuFYx8x_ptFq diff --git a/blade-kit/bin/src/main/java/blade/kit/log/JdkLogger.class b/blade-kit/bin/src/main/java/blade/kit/log/JdkLogger.class deleted file mode 100644 index d826351037864d1a4b5de4a3eae388a212596f72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4142 zcmeHKU2hXP6g>`Ulgt*%7Fd>VQ?_jaOR^8_3q_R>3Mi{kq$U(0o}7tEO=rfD#|iMr zZ`dER5=gu6{3yhoNs~_1NjqJleOU33nTdUUeD3x2x%THTAO8k$55EMiHt;RH_FNM)N4YuZ`t#|G+AbyCR5CJCcuiI;E&LrGs0|1-I|}(kaDZ zI>x4DjS70RFro<1(oRJh3Zn#tb1HME6vrY1z~jbdz12=L)P}3k3JCsMNw0e{&>2Iv zX%)Dy!Z;i5kHK9X3?(h^YomRx0voMZQx2t-K-TcL>f80L zddA659D`>R9HY824L_0F&pK~tU(Lj5h7-1TjD8zs`7DTK+L~EsoVq(B$;n1Kt6j^I zJhqK+Wu4ShQidPaucS<6@-w5+$!0zxDAT(fI9Oc39L_RaNS2%t#kk-sHdP=u2YyGI zc9aebOHJ(xZ+lM!_ZstdM}-V)&7(@;q-w4+6noOfTEVbdZd8sO7u&5D@iWV}S3Xuz?K(3lLGhiXfbxNh zRD8`S;5NhA{oB=OcNXyLf!5J_7f@w5w{JUHV1|XKDh%mD5*-^u+yp5S-7bN7`kJF> z4h8y`LlGr<-=p3fy`4{RUM?;Cg){%ey+6`38Ugw((Q_gGc5n{o<2I_@)bj5Ua=3t> zQV}kuaJZbp;R7z=GI77M$Mh<_$9(eiJ@V*U3R-0f+Knk_a}zY4f>upI194kUc(>2z bRtm!JDF`{N(5yMEq881LJl0Ub9o+p2^Ns`k diff --git a/blade-kit/bin/src/main/java/blade/kit/log/JdkLoggerFactory.class b/blade-kit/bin/src/main/java/blade/kit/log/JdkLoggerFactory.class deleted file mode 100644 index 59a8c8d507777a4ce2cbe88fb4a7002dc9318c44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1319 zcma)+TW`}a6vvNC*EFH9F&OuYH$Z9;N?wpa+q4I!RRVSJ&~6fsZsKL$QaiGpiG4C8 zkl>vUg*Z;w){av85XUDz{^frz_Rn8mzXQN4c zk6Fs;S{Y1;!Gsvh8ch^8R4PkH%*Kb*;vW7v#{kCnU>KoGN9d%4lZ3#3H_9^+3rkIr zbB%JOvAS@%p;a#09V!ehWWo=GMD78u;G7ki9rq6DZegrjK`+Xr6H^~pt_D~oCVQ*HwFZay`0YBxoY6AkV$0d|8Zgghys*R4)7pY{n&?s;H zFUsbNt@%JrxKChbc3-)+nj`-N-i+%wOXxh|G~p3}?*CQHQ(*!@Ulls$UExZ%a=8L! zJA1G?amLEFOPb)qPcy+k92TdIP@*;6IK=2KMPs^<@ zaQz2bHMoIeqg=sG!g;Imf}3y)EtCki(d$m>d-t4FL%Sl~n?hRn2k8Ow&a_+*9!??n UQwTM9T&j2i&+y$qRTS2K1GSrP{{R30 diff --git a/blade-kit/bin/src/main/java/blade/kit/log/Level.class b/blade-kit/bin/src/main/java/blade/kit/log/Level.class deleted file mode 100644 index 31e1b6e251ff86e368d0640a5394cda0b7e26e9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 793 zcmaiy&u$Yj5XQ%8+K?qBCD20o>!z1fLc2ohi6W#B5)^4kq%;k1bavgut=C?8y%CSW z+aQ4iSH$yh;er@%kh+|>%+7B;{yg*9KYoAy3INA&Sc3|IgUm!h!h{Mg*op;n$zmQ{ z3L8kh2tvN%vIbQGJH@JGY7va*7d)~AHm8$ruTOvs32gVY$}CfM#$?VnP(Q|kSN)e~ zuN{0RP#um2W6a4D%-?n=BbR@~qW)wuo;di4Fz8OZAwuOHfvx943HyS;M(1dTn|eCt zHMm2ddDTnb7;Ub>K7n6n%J59f6_078lT=7%g;q2*dMTIy5uzGkz@voQWjmZ z1*h#|WFJTNapX3QHP5KhmL|+bOKNcs|B&LuM^+oUHm`F;MMiTK^K+q4_Z(L+XSuZHYM;KzGwW8ciZbOISqqmWJrDNaegkg7 z0|L99@XDN1YlK>yIP;nzDva`E&drpe9|T&Vj+mS=BOL$zS+z@%5jYJ0`zTHbc&9oy z5g!OA=M_(-umhd~-WlHd7VN_&MgldY3gA6Ky~G~!^%6Ibw@Z8jxmn^JE73V(0=(@l+29Gc{)>ZHrXz}j=V+GoO0HG$n0RR91 diff --git a/blade-kit/bin/src/main/java/blade/kit/log/Log4jLogger.class b/blade-kit/bin/src/main/java/blade/kit/log/Log4jLogger.class deleted file mode 100644 index 37a3b6db03b82f26e21404f165ee655c4f1accdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9128 zcmeI1&u`pB6vy9elk5-Drlc*Ulpk)Obhp4RKT-ii`IC0{HghVB{^DpqfAl}$BQ`gbOZk-jpmul{6zw1s)y;dEo^&T$bI+lIxR z9%`P?C)Ur*1M(D*&vqO!UK$kk|Qb(6&j5ep9;d0+_OyBAn zK0ZVDderiVpFy$eQrWt6rG76VY==2LE_?$!Y*?l%c`a&09%`9v?Dl&2fcJ?hT$I>T za15Utrs3c2(MmZCM2gXpZF=53iXO#&G39|Mj45X7ZVtPr3DPv%?}r?0X+2opvuH0E z3WwwHZ#dXD1v7ETX+}gVY~d`)6oX3nMxP47+BD^HEl0GBG-DXdnnb5!8ApwaTh7hH zBV;)>im^tT1NKI12Uq390Tix^T1HyaOKa%M4C7G0%iBhW`av?RGS{ye+k!hmE|G2- zLklqGgl#H3xf01#<1o*|#XeZmjYu=?Ijq&&&930L~Y5vVm&${Nu*7%LD(+_9~j z4iZmSYlmwP1kQi7>-x;0Yi^%;4BNgg&-Fo>0h_8cqa}W>1Wyt8PNN_ZJ(02#)7pCK z7!fE%+fo9@t82BmOjCjjq|nmvIogz__?+9>DO^o+!^OvpBjkNmsjwOn3zQn^ET#mG z*}Q`@v${4k$HFyz?(@U9YFj0^NXQk9k*PVG^2;9&{kf6AqDtl=l@HQZlJ-?Xz8JCg z2R@}NF?|O>x7H*=V%vgl$XcNDV3VTz8rF-s% zJF_Az6F3#y9z?$g?-4kg@Mes_mU>DGyRL~3stpHEMGfIC91>vHCFn}3&Ho>1U>387Ia|+tk1lscnwDAMlB?WCk zLBp*KTuz|H%DaIqi&xmXal5W)9p(IP5PEiw`~PY`j$;MTR|gmHKT4qK^q_~n{Imwn)EH3ZeJ;A z(zk57eXXDocq5~3-zaDUq-E3XTLn$}mQA-i3YzpSn{MALXawHW(CwOH*8iZO4Um?u xn~L_Mf+l@S*G)zHNkNmorR%1m{j8uBU>?`&0xZBPeokVxUWB*d9e5X3{su(NCRG3c diff --git a/blade-kit/bin/src/main/java/blade/kit/log/Log4jLoggerFactory.class b/blade-kit/bin/src/main/java/blade/kit/log/Log4jLoggerFactory.class deleted file mode 100644 index f89dcb9d6598928c2d3abce2143f8346abbbea8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1325 zcma)+U2oGc6o!vW*EFH9F+RpO-T~ZXq|S!v`R=FTx?9@(oMb8U1~?RGqGQW z1QOiyqY%dlTU%DvUc||XkDt8f_;r5${`La^HsPfQ6#}8raWrB=MniVWqF&1SJUS6J zN>vhdRkAt6A>q2iVypC-2UP+qMQX}q5`F9qd2BtX5opaJjUfbT+d>MvL*QDobwr@L ztNPr7>jaj^=sm5KuEPyN-hGmq8*6I$|~+P>XB$mkbM-T!UqVt|6h55>68W|NSUSMJy~e zdB!!$k;dxW^@f(cXtt;@G?#sTEF^M|aR#4Rp4!RmknZQkx*5!(OgbSYcmf&tyD2k< z#!NcZJx(wBU=?N5o@G4n53Ck4xjHF;0G1oz!3u%9&F;9%<>I#6h2<_v`H+u#Tpu!Q zEP>UoidlNZv~cm?msL9uhQRCYoc;dCIc)-d!foj$0&gZo6jioc^N8pmM>!CQWH#3* zaO)Cf`_;~3pgKGxuy?hyoUsv!ySy!i*OIK){5Nw7o-ZtCF#Ko($arOkC1n+WlVTH WgW%5~RN!f$;u*Zadks}l*!TnTZ*lqn diff --git a/blade-kit/bin/src/main/java/blade/kit/log/Logger.class b/blade-kit/bin/src/main/java/blade/kit/log/Logger.class deleted file mode 100644 index be83dbca63bbaa79f22126ed8918c4452ff94c8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7210 zcmchb&vV;E6vy8>PHZb_64I7m<%bf|Vy9q32>p?yDUcuFlB9*CVfb-b%Ns|nEO{h3 zZ8_l?h7%`-11C|47&o$PyLPz3U?^YM z!_ZZ)Dl#y^V4@qm?)#pfg{PQt?zZcTz;g~o)wH~N!*+ORd#>5=y^161!J=v8b`OME z6_&$&3~F%eF0To5Cd#>pITtbK8MEq%z;wOPtn<)1Fhgu3?l&;wWE;%4C|xT`DaBrb zkt^35j&0eY88jQhM>%c~`b}w;8Jm|cn08<`-KyBPUF7cL9sJLmPMC}?np@2vly@-7 zer2#uu%zwHVTf@@W_BDj+Ig;`s~$5(mH>%!t~{+kEAt0tuTE# z>LY1QP%BJdj`~Pi6VwXRm!m$C)&#Y}^yR2T(yILlzsCA@XBaRJr^jFv&M-KeKU!5Mf-mw<~T2#k_*r$Mtz(FAFa-m_ELo#%h{DuJ*Vq23IIs z6}nx@!Yd3mPV7yo$YpRjDI==qmI^8=Fqs{@=JK%VsDZMOXRv;9ItsNW zg9~{j@maXYpmKbl(f3c^CnQ2e2RGPT!I&+u7*p?jxxEHmH8z@0~8c-+hoDG2i!!UyXQjmcx9@CJ+ zYXGwtF$!b&dkW7MFp}ZXcnIU4PEGy}Q-9%E3eMv1NOXt6)A(P;V-!3C&myV?&%yKU z<2k&ZgBRdMjF7~+9^y*`aXKQVqIM=o#YfxC5be(Qw3|hh=aG?u3q<=@iS~t__Ju^h zh-o`8N3<(;+A(+yUT?SSb*@OXn~&P{IEQWDfHxBa=|b#1< z@C`wb8q|IGmLNzC>OOo&5E#5SfDb26Z2PCJCzpWbtbs zg1Uy^2*TH}2J4AcuDjB15Ubong23PdC?^QrcQy6C_?sl$7=ZAIBz!mk;UAK)IRN2b af{=nOd_$yQ8*a-t1y(aRvCjAicK!!6(l0gu diff --git a/blade-kit/bin/src/main/java/blade/kit/log/LoggerFactory.class b/blade-kit/bin/src/main/java/blade/kit/log/LoggerFactory.class deleted file mode 100644 index 05524a676f4ee582da8a9e3e2fe185f36c9a386d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 831 zcma)4O>Yx15FMA2{UDGwP`*J{PfZWI7bH*<^-|H(0*8c39KBv^>(*lw{Fzvp@1e}4W7059Nq1RDfK&horrQs-yvg5{-RmB`Pf&y}h3 z!ql~}$BcVpFC*9_uob!#({=u?JQLg#h$mc0E&U;Z8+)S@0-Hys5)mW>23Os$tu;1= zTLgZ**H$>AE<{DSXi!*dnLZ8I+fG^0JOfwvLb{M~XQ|Iny0XDd-HT>aEoE zznfBs;dUSHz<@w+vV4u5z2Zv$0%hF2&!CW6yq!0turr2|2@DIvnL1%scKNcH)WRwPt>9@tT9bP$v6_*9CgDI{aJB^*E$cGq+qE%ca&8Q-!re z@OaHDL0|+=*X*{ql0g5BbPg9X!{xXh0dyVO88F6h6MC3OnC&mC=@*DU4AW20|Ay5K m*uvQL0Djw{(z$vFcQL;g@|}?159bFVK7?oZ@8R?#c=8KL2kNf? diff --git a/blade-kit/bin/src/main/java/blade/kit/log/SimpleLogger.class b/blade-kit/bin/src/main/java/blade/kit/log/SimpleLogger.class deleted file mode 100644 index e2d28ee7eee81748cbe6e2d94dc718daa1335dc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4274 zcmeHLNpBM|6n-AsP8tHGWiOj4Tf&mCUI;>Bl`4frv{XWzoEbMU%#0(C6X3{|3kOd8 z5+o|YogamGp2;%MNi!8G0*Omz#{T^IJwN+<&-wQK^A`ZP3fF9~2oyu*RD33a$_v(E zmAc1VUU?~W#gmQ7lJHv|ugOM(D;p*VENq01aRj!7?ka(~T0HtL)BL_vKGRhKIoZ}N zB?3)gNA0nBS<;F#AG@Y*h(PF@IJ{U|Auw@Ay4;2x1ZE<`JQg%6_mq+<2Qy@9?P;KR zD7_AMsU!WC@R$}dpe-fq9{0oRG(WxEK7Ni~k)uUp*F$ua14*{o67m{R_kA)W^pN-9mGej%yD0>fG7v}fgdnC7o_CSY3& zFBSOf0;hnemXuNbrp5Eqn}jFAGm7|4sJTBB)L}|6j0#$yG31S*z^<8N14V%vI@`dk zza6&)k;v+DwunVCF*xW$mpl%z0giw?>TsomI}%oZfhTnoS0>OHCtPkS`O0kgaTpc{ z;C5ShE>|N6H-k0e=yTnaE~?+FVu`LQ=|}Qsf<%+bj~cehRcNHd$fGa9(468J7ai7E z+`4oPu4}x*y&|gn@6%#-K!qP7r-K^LZ%1YyqZWj=dSjuQAdu3&AlL>R5)Xgii!1WLul z#727*Npki1`X;mY4?SrITKIf1=!j6@=D%f%si?lgy`Hc2l0!8ICkcGW;CpXGijX7= zq}Z%6fC$`7^EcscKS!i5LJrOl>-``0tZ&m8R-jwz{m)ye*MNUBZ{gWnl5OSi`@$ro z*<@acZbmkoBd|Rolr~%-usiRIfXsb_=ToL_ug&zhP`W0cs9556YTnmUl#1{A_05% z;CmrP!Cu&hUxr~0e|roTwr!5Vg8gtHmEmBD4f82BSa1jqCm04^97$ogl)~^9jsZnq zk9U1tz-P~+iM~fCQrNByVLLU1ZL-gHI)$y8!e&7c$5>Fpef3#izYes@sszQ^Ey9&ef8u1JzcD)i}kcJg`xeXxo$YR@ws_(Q9OOqM4F5J0m59;_3%-5yN4TyE~UDKrNt<$XRGaec_J zu>>{-Dq`so)567n{;b-uFa%x>md$&Cb$SH+gxk^y1YXaoD9Y@0mLkiIjxrR9WH#5R zaQiRH&WqjEKy|oJV1K!_oU>LK0f9HOIxc#;N;!3SM41{3; zLSbqTw&qS+QK1J<=T3I{LIRBgVGR1~5WQw#3-HY1Zwa{B-?-#N_P6 z^i$c&UdLYGO3=E76 R%s>l4fRTX}NHQ_70RWPcBR&8C diff --git a/blade-kit/bin/src/main/java/blade/kit/mail/EmailHandle.class b/blade-kit/bin/src/main/java/blade/kit/mail/EmailHandle.class deleted file mode 100644 index a0f6b2536115a74e8cf8052fdd05aba66fcdb270..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9075 zcmeHMOLN>r5bjwV?<1Qy2?-?OCCnps056XaATMwd+cC(F$=W6f&#^RKE7oI6nswP1 zegju7RB_`MkSd_yNLBs<#eowSegFrGqDR{7%6Me;R;fa&$YG_Cw)IWFrl+U-&fnkt z2mq%*l%d36EDEiL#~r_Mi*NA8ipy=$Sa+m)=QgI)^$PcG7paFB9Egcr?zb9OS8fSQ zG8i_m&df|*V^A^8pw$xLSq5d#@x)xzVzAGgQ$rC&yd~5>5e}WeXHYep$q?V}X@@~O zVo*01a3DhIhzMWTBjMXikqGCxCm0+u`?EJ?==iNP%>s`Qq2#q0>^0{)u5{WwlnQ*+ zaRvT0Y?@A_UR0Y-%jdEaBIeQf^17%%tg%_PMYSqOxVc5cQ zd5A=9Zmpx1jM3N#6KI49rT$UF4n$=5fiyfWtu;g9M`E*$+E0Ikc2wm4gyLo5Ul7Sm zj@J%CX~YB_>9~f)eFeKBjJurPPlTHk{vHtV`%MM0?`dt91PIMvh71gD$gQ@hRWpfd z)l@9W0qMq;9IAe_$stU_O%X)B$dm)7VpR^w_L!AJY&!nBu!}~W_1dmuInsza7`8FY z`H>7emJC88*&oKn4JR@>zAaWAU)U4ITnFXC=oNqFZW)fh5v&V?V;oxBj!>%>r}g5H z$Sy-BY;HwTcpCH7s&tHGE7gFcS623-7+@;;8l+QZGnQtbx^&`s?1bwnNlgd$3aqFizB)WT%jZ9I+#lYTLz|1m7V~RT}>Amw+lJ=== z(K1=DMGF` z=-t&d5GFy)f$$2@3CYvxA!OD^wfRC$+BP1Qq8#Os`KJUNI+NXFb|!NhJajmoJ!{o` zacb2Tka8c<B?i9{3`h1eGGR8S^wSY_ zvaak{Y)p!YCp3jWT`8~vuQ2$QpdQkqzPCgSYAQT+y4755trHjS>kPguO2AZH$lR)u zQV`Ld~a&*B~U@WvczE)s{!Fo}G=i3O^q?-Iv(B4v7f0x1Z?vtx_A;puh z=i0+ng2nUrcHGIu&A#UkQ5mk{f4%1lyw6}ZpNHNDyYJmNRnkjUF$5dOsZMg-p)A7^ zgZc20Wl(Q@jGlVGj)Bs03wvQuiv<;`?5x$M=1(KfaH2?+4&u z{Co%=MwG+x_y~;P7|)e>J&JEmA$ke#weR8BjYE&!h9`cC>7K&tFwy}247}FkaSizy z#V3GgG7z5CAe`4AFnAtLqB|MC25N5OpC*g$@LSKp(H3-+W2oumqAt*g3JiM$y zu(b%U!fPpnJ`blf2!R&ibOyp38idca2ybN|oY5eBp+z{CVTKd#PT*Gfl&;%RrhcRBv!y+uhb+`#1!6)z;to#Gcs2!mI diff --git a/blade-kit/bin/src/main/java/blade/kit/mail/MailTemplate.class b/blade-kit/bin/src/main/java/blade/kit/mail/MailTemplate.class deleted file mode 100644 index 8d10d3b96ed3d3836c38bb82a9611d252a00bd54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7324 zcmds6OK%)S5U$=V-iMvoF$s@6pkrRU1a=__kHn4>+XQ4-V-#;9Ax^zBZM);ynN?4Z zWgn5aa6{t2e}EeoB#_|FmH&fMJ+m)oTiRaHHjv9~ckkCOecvwACFKCkZyrQ3q~27a2n-3gfD1;`VaOHly}cj}w1N8D2cW>goj z8u^C=<{JaZmXadeStL;KJWUl7m})dctgxxHC3Zrl63Gc%NE??%doJs~D(dzvZi|5H z?ntvFLZOxkoT^kG63DMbJ_>l2!0cf3ds0TS2+xu;2M$^9ZnZgd(_Y#HEoXt>PI}LVWeoADQ}l5?8FZ`XoulW zXi^OiYg(4t6BOARJpDqgV|o*wP&7_DTw;C*VaSx15HLgs{qv9jRDxHuiRzOJI$6_1r+tU&*znf%`gY#*2FVJA_jA7^btU=By{ z5b{39O(AB+kxj}lel^+N=D2sV0_#{A!)F1pnkUUOq|2C5hmcl^Or*7yyzW4@x!P*P z&3!JV@W;)X6_-1Zt32k4C)4b>R{<;gxl+j$&&im^m9&m{$}k7#XW%qEN8o&A^n9z& zuCoo?ReqkdTU<679!K>NI`UZXkV&EI-NwAy6?lHW+OR&b7i8yPvy+_b!sJW$1p~90x65IK;S2f6S|e#YnhHY{s#>LmB0D}9H8+J0+fk95C@ve*||K&+-&^9*eW|4pr}v-%aG_n47h%@^Pt&$G(UT_EXSiaJ=9*EO zSKw8YCbPh62By~yOv?tQub~1}qbzS47(O*Jyfp#C0|Ntrx6vLZ+YT&KGf1;-dmq^bGc{oNz`*dWk>Tb94Br_UZoy)Iu9pnjnCAKi X15*xeqcw7{3~TsX#HhLqcVOi)?M(4b diff --git a/blade-kit/bin/src/main/java/blade/kit/mail/package-info.class b/blade-kit/bin/src/main/java/blade/kit/mail/package-info.class deleted file mode 100644 index 8719173cac74c166e561cea4a0163b32ce0798f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 134 zcmX^0Z`VEs1_l!bc6J6PMh4B|qGbKt#LPVXti-ZJ{iK}4lvMrf%o31Tj($O6a&}^R zs%~apT0T1i3nPO7SXEA9Ub?=2QdVkm2_pknaDHh~a;jTqPAVgVAhHfUkYX_g21W*E Ppp78F$iNCDnHbmr!xtl< diff --git a/blade-kit/bin/src/main/java/blade/kit/package-info.class b/blade-kit/bin/src/main/java/blade/kit/package-info.class deleted file mode 100644 index e9ff61b110b55ccbf9cd4ecf9d0815fecc85394d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 129 zcmX^0Z`VEs1_l!bc6J6PMh2DQqGbKt#LPVXti-ZJ{iK}4lvMrf%o6>A#N_P6^i$c&UdLYGO3=E76%s|UP NfRTX}NHQ_70RYb5GS&f$;3t9HK?*^X5%PUo1dd!k*HuL>$j`uwSG6bfg0XB2$ z<*n)?Zb<{i3Cs`0OW+U~H@EKGS>Gm*HBGl(=iVazRuPVnO9ajoiVp~6*4!F5;2eR; z?u_f6=XzO~BrrNJzNU zVonHL<+Q!t(-sSTqcyF=WvX(46t)(ij$mZpVQ5b&w9#zY!V;4DL5q9HBL_JjSkm=q z%a1BuW+jX?aTx54 zI!U*s!;ss;9!5nC5v@(3fukXE>dwgLA~$Wi^0tdXWBrN6TTxaT?2ZwdK*LI*2)<+( z5PNc0l0_O=BaIK6tciTYa;33A!_?p8vfOpsZ6k;mO)5u?yWenJoJ2jtn zMV97i)pc#ooFaAiqToywH4$wvKdKk}aCYu7KkzUG_-RfXEix{_Xf?n*)2>$Bc0v#` zpG%G1T^kG`z_a3Abmc$m=Myhr#2$~P8{%wjR;>6w$NIN7b|6JlNxW;WZDVPU)&3V) zx+&+;$-3)K(8T?!5ufjGn~G_Yp>Vh1VTYs;%IAg;*4nrTbBkNp5~-qcT9)0|N;75U zVFF&9fE-K{xL7c|U0kg2V%X(PnpiP!2F)t>b{RHq1g1^bV)g^(iSYa3j~UqzK7pI& z&^A*MqOrHkwvzyX8O2H-7EPok%H?)M-C+_#IDu<@1uF?%;=posX>kdMU)~NJDVlu4 z*%!XR<##s?u0C(J1Lk5D-XQRUMhn{>p`cchf9Y&29U>B#Q`qIWK^8j}y`>>tLG#4} z`dBs#vjqNl7R?nGgoC|@oX5Vg7BOk{;9mTkg22vT%N=f_9?SRq@G#xFLBBjy#5xCIKxyiFxc#JYt_O=GxL8XU~k4@qYAKg87&ceaZ9 z{HY$HoOl5d=|=Z3B~6a!p10OVj?wQtYbel+u8YQM6m88}KQf ztcHUO2#;LjD$an<@YEHnO9PgV9JfZ~HDKk)sc&445tz6ud>@1SE*@L?nJa)0_&STP z889G=hs_3F=OB;oFGNSr;eCMo&oJ@j^!XoQ>R0?W1~1|Jcywn9F5vYqbmu@CB-9aO4B&2&(&C{V8}Pyyb8w^5^bt?zW! zXLOL>RUj=ZkqS^m-Fr2>szCT!fq+Ny(ADt$AsUtxsNeKKz1FeYbtUTAjDp+fd#0*5`6v_pGc*A diff --git a/blade-kit/bin/src/main/java/blade/kit/resource/ClassPathClassReader.class b/blade-kit/bin/src/main/java/blade/kit/resource/ClassPathClassReader.class deleted file mode 100644 index 1e637397f7f45b4ea57de278de90fb14601901d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1275 zcmc&!-)j>=5T0#gu05k^<1c($`; z-9Jj4-Aic_FM9v`?w1-kjcfer1zk9}@ zb*yuY;4Xu1;9LqdNnabI%?8|K>zxnEb1yG2=b5f*Sqdk$;~`k3McUzCZ12S#7%RfK{qvu zyQ`Xf($!olPmt&lG5$%L;9jZ%jr9I2bcN0>pA#dQV54UL#2Kk3gXVB}crf5&txFVY zcfgnEejDIFWcioeuFV@pUa%(4g)-#T)H*J!n(~UuEyyQk)i={|sf@3#jud4#RLBxZ zgYv^eO1VQtnYb~Y)BC@YTtO{{7`h#ZV2i<{{^+J(n)2EA{nQ;vg>R?T7|p4mN@UO* z=}eSo!brcKZMIw?ErS=M+cob(s`eSgC*eVPBmEUmgR~1qp?}~RP^Z&>hn^`$Uj!R8 sZiYw8?*qi&ApY3ve1ZEvXtf60G`7RZ7W8P|X{_J@Jfsyx9;_b!2J@Gn2LJ#7 diff --git a/blade-kit/bin/src/main/java/blade/kit/resource/ClassReader.class b/blade-kit/bin/src/main/java/blade/kit/resource/ClassReader.class deleted file mode 100644 index d0d876c21610b9f4fd6d92774cca3510c226c8fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1864 zcmd5-+iuf95S?w)I5B~Q&~hoaCER*JF%LYEC=wKS3Q&Gby&YV5RJG=Ai_qQJa@C+VXut4BRB3&n7B6RlH0dodE^SHAw zlp}c(jik$+EuSUH2ab7ZL4iQc0DTq?o%e%1?kWPMw(E;fs1AX}we=kWg{{cr7L*B8 zr|8#GMzRDK$fEifYI^^Gd(@4BSolndD5SBB20jmx=hQCucRBUA>obX53wVBdMqXX^Yflp{5>i zdZhR?aHNEv3G8u|k*6x6jH<(!+hy}{&%pGQ6q!n9iOzAUT$<0%c^)}0^d_b~c6vkq ze_;PI1F(2Ex3Pd3YbC*9v&McY3C8BycJ1;mt7w($D~LADR5Q+EMf01 zK@npMqm6Oa{tl&2b^9w+eqwe3YWUO`z_-gLqvur}u3&E2#49GgI*G4gd>y9o4HK_U X{=bQ=w@l@2c!a+;6yOd}XuyL%o69|n diff --git a/blade-kit/bin/src/main/java/blade/kit/resource/JarReaderImpl.class b/blade-kit/bin/src/main/java/blade/kit/resource/JarReaderImpl.class deleted file mode 100644 index 2190716198e77529969eb19055cd3bdd684eb70b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9596 zcmeHN>2e!I5bp629XPQu35Nq@VlH1u0n8CgIAx5JGAuS_J1NM&ku*p{_E61^T=9$W zB2YyYRKb6qfOp^#sG{hd)v>mBy<=E}?eY&vtKDzD>FMe2>FJ%{{`%<`09b~5IT#^O z@@2j3FyWTJW&5mLvsr_ep9oc!-1j=N&dZ-Mxx?|U+;rM@4#o&9r?y$E`AV|7TDO_+ zhplsPg}_p3%Sa0XSFG&^4>ooPfriACxw)AQ?cl;GvEbO&7ZScCyB!b$k{)9C- zozY&Z(A)ld6$5#~R8x4-TN}G*v zTU?63ZdlheZ(2vR5y5V*ljNdwgKQ3%^Ie)lg z#SABk*lS7L)x>~`h4jYRXk~MI<7u6@4Th7L0YyiYjZg-IH<_x;B7LTYo{fqy%G?)r zTF!|m)aAP8x}oLAm|Ar9P6;=61ti{Zl{`rA-vnkfuSOt~iA};33;M~Hr|x?lw~?tE zY38tIVal7WBNt%;o}GXKOcS^nkC+s} z|L)B()e=5|J63Al1+8RI<-sybzLy*mn2C|$@w|n;gt)@4Xu3>cMvdJh0;`cxX#G|f zRx7L6{N_%_Rl?z$?!NE^3O-2eQ0}7DOW!Jac$L5p2GyKiixhLuCK8w!I)TL)y&P3Y zrLWOX4bXx5!UhSN&BH8#-_N7ELeD;V_6S_>nP;>#Lf}gi-7Q)JBSRxh(c_zBr%g$NaKoh7M_*5l1oHY!Z2jT1}L-llSx zA)YD0SdfFec!BPm11wNPPL=4`mxGT9OdYMs5SaKv_&&au-@`Z7KHLVRz|S~-W*`T7 zJaKacuM1Gb?`QP+o8UP>@n@L$divUrF!d|`8-eG#NPsE0j@J_*3U0vj_>aH~@FFt5 zq_Hz_vx|Nie|xN>cpb9762rQXzg)Z+ZoqU2Ql zg2d$P#Pn3%%)GRGb_Nzk1_7|joW#6zegCAa)Z`LI2CiVRTDQ!cR7M6tWF2}S#bOK$ Tj10^`TS0)4ffYzHF|Yvup=c#( diff --git a/blade-kit/bin/src/main/java/blade/kit/text/HTMLFilter.class b/blade-kit/bin/src/main/java/blade/kit/text/HTMLFilter.class deleted file mode 100644 index c1bfc58bf21d610944db86256ca4e3e3fd688ac0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7953 zcmeHMUw0El6u%owlcuFD1w`=Qf&wjKB7(?&Op~;YB+Zg+3k5Y!Hbb*?vm19Oq1A8X z7w{+^eer?gXYd@qfsa1;fZo}i{G$U&4iy!7XztG4xxahw+&jBFzyAF2yB`4H415)a zkOId&*NE4MX~*x9CW)6VQlaq;lf@a`Wbq|Emt8O|M%^%sC@}5Mv537M&zJ8~gDEgs zNH3;umKL&!#bT+LQ9!}Js8&kmbGh`gUQ}Q#s}Y6>_C>sI-%wywE9q$DE7Qv zD;4!bK@UcIwbJ#Kyq->#61rZ<%&+KaoWEZytt?CQ=v6D^^?Wj)RUo33(0xWC)A zXqHLlQ)zKGxWv1wiEJhnOwVu!lP#6+1Qi$+k1$av<5vCF-3z@~Gwsx0RO5`*J!Xi-xCbS+i^wneF`_`8NRE%sN z-cRT9tLc)K$P`NR*~IcSR8M7-j%_qtm)a~x>U`yk=DJN-!=(zG?7e#_+bL_2xu(5- zv0bt&Xxi~nOlKF`J|fM8WjXg~MS)$}z{zPYWpG*3V-o$9iyS}N)X93%Y1qtD;K<`3 zGB%^@)b%Z@>)2exx<|IW9NC~jZhp9EfjH=4eh;G(#Q+FHT(;>#64ly1}>=B5-lUb`fE>ryp4Q5)ZL2M3NrfMtF z7ZacP@`z`yq!=o5RH8PCYZC03=-AH9WLxzo;{CgP{okT}`g~s?1bgTCSck!%0MAFh zFS7VAb#Kr2>to+yK}~~?);^Q^z2*X_j@u>TRq<=K59;6I`X6%p%roAhJo({bC(5)# z;fRAupNMvFu?KTFP^UiMlQOlsWf~?^y+)n7czm)w<~9uGxN1OW%+9H%r#9>gy<^(6 z5>s;xY%M$$`DWIZYT8X_gQ^72H`QK*=vc8)uj7HoyFpwVkELFp2H2r)d&U(T>?t}( zP*FG!S0>;rTt!A_cKhL-pM|HgScc_BtxR2=A6AfC$vOtHR>k2(C`VY;#3S}xc0eu* zIfs$iTiiip)@LsGWz4^nkQ7~^1zmy^1UJ})#ilF*$af{5d?@E<^1kIpzzSywB7p4G zLVv(P))+Yjqw4bY&CGSB5t!mCOjlXWD&m>nBv!IYTwKIsvQo%wNALK&AcB});t@&% znT%TzSW)0`-#oC$rpE(nu_qYAB=rnZr-DvF#dw(@_hL{^MTpccO=6i9!n#!B{z~{$wiGxgDcwNXA;o2Ss~o)rCEbunYK2WZ;kpE! z%}Sg}D7ZOp)MneJ#T9aGu32s{tj%!=jwEP=i58uPYfz-4(QK;2O#9SS7#z%^^Ywwa88;-W`AA=dpxig-{@f@5$+ZlLA$df|8 zD`ZT_xRCD&c?#b5?N0kLg#U;L#vl0dAo@HDAL8#hoOK3QTR|DU59ilrE`9@-f5cG; zKEmHo{|;_$yq*YV!8{~!#1T^X+d>GTZg_+=`UzHN;VFzem-+ie60rgWD0b!C z=>c7m^Y2oG)gci6kRSlucuW?u7#>OyZVry1M5PF8Lm(WLBHS7R;j#oF0=MClt}fuu zzhF0gy1f=k&PU)C2Ph5UxghZj@c9r3UrQ0l5D53B2<0IVew8Ae9s=PvDS`o&uHDe7 zfTRfgc5S>laI5B~Q0Oea+^?*_i_Jso?RWB8lr~*hNRN}Z^56L$6uC==k^p_!l z1o!?Z#Mo`s0s&DjqnVwVx9`o&@%PVP0pJNd44}ba=&X!$p>%vGmLg6vkz%}1KK3gA z5KqbMno@hT0W=x(>!M8PS^PRVMClncsSp{keFm*=~LkZ;x`BO)19 zBsY0#&~a@%&xMzB?x_hs7R2si6X}d9ol(Ul`UN8FyvU18N#(gK3$#Q?J8w(rjpZjw zhg)1ZUg{LzD~)NyUzW~S|I}^S5m$O?7RUt=ng5Isb|y#8W6q_}70m?snezWkg%Coo z3jy>Q+!~J0$2;*>>Dj0ne{W1YUzK@+b}DG13x;Z9Eb-U zG=m1LLyNp7`2n=acIrc4BM%__0^z$s_Y++EMo|NajNxJeO>6*kEJ ej&OSg!lRW4cQ1hutwgwY352IB5$@MoAN&AM?fSw1 diff --git a/blade-kit/bin/src/main/java/blade/kit/timw/TimwManager.class b/blade-kit/bin/src/main/java/blade/kit/timw/TimwManager.class deleted file mode 100644 index a173c27d64f69966ba86de976e4e0527a56e4765..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 766 zcma)4U5gVj6g}y7x9wPMt*#$$aebLC%M5}~R(uf!q1A`23qGcq*k(JE3`wTyFB25> z-Jjx*5bsP2yNbvXxa5X&PtLvP{`mFf8-T~S-$9EZ_D-gS&?Y?>8<8$@k*Rd8LmG7P zA)Qm02_u%ub~Oa55La1xKNK(Iwmy12ve z;QwxsSq#yst(;UZb*+AQXV0hRtw5X2ZF2xq^{RUkY)7t<5 diff --git a/blade-kit/bin/src/main/java/blade/kit/timw/TimwMonitor.class b/blade-kit/bin/src/main/java/blade/kit/timw/TimwMonitor.class deleted file mode 100644 index 9367e82328ac7b7be06e03e200704b2c3ad6a561..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2867 zcmdT_TTc@~6h2cfy-=Vcc)tvIYZ1FDc%#OI5H(0qBbCGlAEvuwJ9KxpnVnYgU-)ZG zG|_i|l=19t2_QpVlD?RxGqXEqzw@1Q=6v((_qQJaumqJfqzDuPWm_H-(%NQSX4PHh zaH}P>rG@v=s^PHVOQC(0hG7DQ$jD`~VZEwvb6XP_LqopmcckWuzVJy_->aw)b_o$ zaG4gqq;2KbUG4?TG?%S4Id!=0GKEHMX17>_)43?rGKN|XY0Oc_=K+&v`1|wL&!R(yDZTt4%M(nwNDw`jMGk1py+4WnTG9=JEh>(;+ zGN%8x)ys}o53_TqQ2UFKEW`mqZE7WCV<4;s2$d)eImp9_JY->tz)Z2a*R(N_O4!ts zRXnnBx@rvjl)zNgx0$=eln9@DFNbwg1c^kYCsHUM6AiAB=bj`j6idlPDFf#S%=Xt5 zloSHF*i9^7W9Xunn@R>Q5s>{6VpU2c1Bp^jU?k8?p^y%7>11Gz!1MkLB3VpAfWSCH zu1Mz%-*r(ey+BzG#AhrUYV;b8tlPkpU>4$O6vNf=zq;B{hml;RSzFp85C zUPseN>CgepfR&8g;5r9yxR}yPn5Yrk2}0c+scuHv*&4Dh(N&^Z3s~4)@1!wS-m# z=iGP5znhx)3WcBel!B8ujz&8Ln8tNJwt^Wrg---d!xQ%-nMQg2d$P z#Pn3%%)GRGb_Nzk1_7|DoW#6zegCAa)Z`LI2Cm@z(xT*4x6GVWMg~D-9eNLb1Y diff --git a/blade-kit/bin/src/test/java/blade/test/HttpTest.class b/blade-kit/bin/src/test/java/blade/test/HttpTest.class deleted file mode 100644 index afeae6e9319b1d9318c74f55176b67be8ce981e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1693 zcmeHI&u`N(6n@USwaq#@3L8HU-neue+RIK1aX}!EI*?eIggCj5*Loy&W;+x6%aA~V zE8_p)-#|Pkpk`9EMB>UJj_voo&!7GLo`3xM{1pK9;eHze0z205u@lyfPuV#e&tevd zV*J9nbc%*Hv$WeqFg7bjG2>K(bVW!EE4;OhTZ8x&`9u@83d(_e_(S#cXLT2FL9SfT3D*I zqX~0-K^;1Xk15J2JK&CT_{i%RmE4OJWRhy*Xl|66a;7}tOwhmjF2Qp5O3=$BjU|_k z+AI|YH>IpI8F$*y;)sTOR9c#;NSsK80#DF_eU`hz{C~%yuv-)2tJ0&v1!@4P5kMe3(wX7HQxVwka9^kM za@U5tmx^@}Q3Aa~X)V@|DV7NfJAhRi9|3>>d#kX9Z99JyRI3|kcp>p4S!*Z^+j?QOV+{}%e)`3;lF7y1AI diff --git a/blade-kit/bin/src/test/java/blade/test/JSONTest.class b/blade-kit/bin/src/test/java/blade/test/JSONTest.class deleted file mode 100644 index b100c3dbaedfdeb3fba473567c78c4fe544a7625..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3874 zcmeHK%}*3D6n|Y7_QORG1wRi3E{liVizhKA#%L55IIxfyPu-a=Tb!9r+76Mce~~v6 zP4w;`Wqj>GSY=pxm=F>m5i>$2G*xmC@mN2l%|?I3X~=_!DFme~_{jD-U2!ILtcfc$ zlw8w98X7YbjHp2d{wYOs#u;!&4&JeLbjH|o4I)mZGSm?>BO)5G#EKkndSc;K0Xo|+ zvhT`(-o|Mp0%54mQm!z{i8d+=j8rtwnf4kLnr2DJha$m<4UvL#mPKY9-JzSAHkN`Y z$`TvmT=1C4W@E=Fk?a?EhZ;#4HAgA;1Z}dk3^85?y^P|4UeJzL!9uEr{> z_>e1YO|Z={7Fye)=;%4uWFMX%`6kq1wguC0lfYuTciPi)vFomi^h2$D(_4 z)!@NjFUCC02(&iy_SDDjrC}NH>4+~;fC|p0VFt&Vdznt*450ZP>hBktU!nEWVdikO x7{K2=j;$O8w_pKR4Y&<=@Qao380DTySS*k*?<7Yx15FMu>n_U7ag%&7ZCa07`a^XY~7gQ>wEtN>9gg7}~H*wjuSGG5z|A{*i zNO0#zA!fZnS)`~GIB?xL(6&W4keC8FBL zdOAjb08Ikx{xD@~Iy{`52<`~9;=}#@y_W>qF-A^>*+t)Dsib>CV6DG%M4mE(CuvBSBGv@e=I!qAna->*Kz@PNtgObOfmR?nmS+0$v-cLDGCEP^NAMB#= zd6uV=OGj;y3xjNxb*A7>8(Q5*e}_s-3zdjtsj%`fo}kT&)YYR0^q{b=Ji#c+R7tf0 zu0cj&b)hSmP^T%Q?lc!?1V!P<8L6g!nt!e$za2C>wN7L!IGyn)^&*YMK%#;%&>(CY{Z(g^oSW*?ibFcn@LNc7yoMXaH5(SlZwDr z|IMnBZMZ?m{2XKSzabVnQ=6Z^Y$yWJNEe2SXR>_h&O$D|!US-;6i6?N0o?sbKdYy} zgac_UPU#qj*}{E5(L`A$uniZWg;oRY0NS{QUar^B0*F3A^m?Q70WN>>F;{SH`4en5 rv^!N4T!m}63tw_H*V$)zWXxS%3cB=pcw32}0~ZsM|QuWWDBJ_=8Q z1QOhN1>OZQ_BKiisemGJ;;>%Z^Ude^|MKm_Cji)i2N6^VY+A#+PFUAHVH4IJrYsTV zxzA)eKtTjm0&78sI_88lMBEiL1u| uervckN)+6H7M|*G6K>&+XLy9XGlumA3~^wnAhrUx!+Hnqn1L{_R98F)|mEErIpNLJIqYK)JnpNTBjeMZ5}i0?jG*xz5z~-KM>*v5)WZt~dY1~# z?k8z1LSd=NQm!#j(pa5^R%x1ty}e6?p_z>Mk&t-lBb4BtWwD(_cj!T8tdk&$GU=j} z6VFfv^*qT1o=~eOqjr+=WkC~Tc~Zc1s{ax%RTStIT$oES-}Y0j*~AnZp0AbrbPjWW zSL_K)$=Mjp#(G~`K5~gaQ3=jzVD$^lGVTC^FHn2i3O+&Oo5wV9br`^B1J_25f~(NN kQys3sb^PKO9w6_OVY7gt;TcMZEx`@H-h?~&uAttnUqwp1>Hq)$ diff --git a/blade-kit/bin/src/test/java/blade/test/TaskTest.class b/blade-kit/bin/src/test/java/blade/test/TaskTest.class deleted file mode 100644 index 37b8fa0ab479747a1dcd86efef8e0ee35374ab5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2006 zcmeHIO>Yx15FICJlWbE`0xh2hx4onsk_#t_xbPt%QX-LUCB(_`x{2Fedu4kg`b+pJ zNFc$TABC9RO_fDjkqB|ffx~+3o#*E_v*Vc`KfinffXDE#4iy6X*6_X)*7YygjP=JM z3q-#5nZ5MUP=^|Uoy;0CHR%t>7lJzin@^>Z?iqn<_vnm3?YRy_9hwB%3+zi{v}wQ= zseU?DMpzxrL_oQYVi__gwW6`n<4{EQ3H6%(RM0^1kQoHUj9;>epa+?xUMlf`23lCE zw4)Jod`cZ|5FcZdQ`~?aW$<3AqgU9TpCF@H8%Hx^;$%oUQz_+G&})T%2h2_?WqTdP zq2$t0o5aGP|H?X(aHkE;quD*8($Yi);#?~9utV=D3qD-aE=fnj{ zuQ_r?s!53w>NI84UBv=D#NYb{C6#&qE>Vi%Zz(YrDTXs)j0~2+MpxE}sDx`>M94^- zVk(y?%)Om4BhzrKiQX5?EepB7vP&K`V7mnyaD%{Zcd)p+c@iC`SGzsHbbFgbV`2O> z4g@*_%~^OhkIVdH%}u2xa5z|6QjW1)L`*6Id)*IZXEtDuRE8^*jQ^=Vuc?Kb{ipl3 za$c-QefX!TPQV-K#BlLSra8QQ-Qco5QHT4#b-6sT2((V5wOCDkESeVf0oxsRPk;)} zHeeISde%*=I0Nv$LgRhM`wXq`8K#Y6iUE9faBSr$xCtFxHQ^TA#xE(uBjjB$?3OTW VWegR>R^U!H-h~JFuHn9WzW^zHgC76@ diff --git a/blade-kit/bin/src/test/java/blade/test/User.class b/blade-kit/bin/src/test/java/blade/test/User.class deleted file mode 100644 index d2b0b70925c60f873fed32f2cbc7713e257b5c07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1744 zcmcgsU2oGc6us_BKSE%mY%tiyyz$inYF~I_2x&qfZR$3Ob(45>6VrN2?8tU1_B;47 zNFc#GKMHZ3thCdjv4;soitYHG<8x2$^{?OGegMErcu|ECffb{Jj^)O7j@XEG`Vk9x zzCJKqSD{Q`F58Ki9CY^jM?A0u%96#LK%+a^+P7NB!3KdDHoz^iO`!5xNMYaLr)KLA zL2p&at8jzB>;(2sYo%*2OG^HM)ZD0O#6udWI1v%ELP?rv)sJ{=UQw^!8*&=*AYvMW z5*8feS#&)U-F8W=(@=3krLr_;HW*Ti0RA~a(bE9TISX$)9qlQ&SI^U+0h5lT&*@)H zR#8UnNy5GQR-8m45SE%W;TqLSV|5x>rD^U^vqgoWsSNoiA$i!QJE^fwNCt~esE{Ld z%qhb|hG!WrDdAE&uP$hB#I+V7|A#SGcAy77-14Cg4FU_z^JV7hX|{{r?xt~{>mI`r zarLMI79BDz-1_um*$#yvu-d(_(y?%>18#S-x}I;g&L3HW`vjs(6zP?jfRfBuQU%3r zy2ip@+OEMWfwhaJV7p)kB0fWvo7>K^npL?v0!trKX+_Mp!m~5C);MKbR1cfjz#5>L zcoUZJxdxSNR)rdl72K(VhwtmzO*w-z0Pj2a9~(En!rad+_V#Hc;O;!m{X7a5;0~?` z+=WGapJ%vNz~C1$EJ0(6p@gith9ZW!LWX5nnPQk^@t{D%d?5qPd>Uur{K_>HF)S7` mtfLPlc!)^n>mwY;Y!f|?3-l}(u$AB`;!Dtk=Qx&;uk{DtFu$?@ diff --git a/blade-kit/src/main/java/blade/kit/PathKit.java b/blade-kit/src/main/java/blade/kit/PathKit.java deleted file mode 100644 index b0513dc00..000000000 --- a/blade-kit/src/main/java/blade/kit/PathKit.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - -/** - * 路径工具类,处理request上的路径 - * - * @author biezhi - * @since 1.0 - */ -public final class PathKit { - - public static final String ALL_PATHS = "/*"; - private static final String SLASH = "/"; - - private PathKit() { - } - - public static String getRelativePath(HttpServletRequest request) { - - String path = request.getRequestURI(); - String contextPath = request.getContextPath(); - - path = path.substring(contextPath.length()); - - if (path.length() > 0) { - path = path.substring(1); - } - - if (!path.startsWith(SLASH)) { - path = SLASH + path; - } - - try { - path = URLDecoder.decode(path, "UTF-8"); - } catch (UnsupportedEncodingException ex) { - } - return path; - } - - public static List convertRouteToList(String route) { - String[] pathArray = StringKit.split(route, "/"); - if(null != pathArray && pathArray.length > 0){ - List path = CollectionKit.newArrayList(); - for (String p : pathArray) { - if (p.length() > 0) { - path.add(p); - } - } - return path; - } - return CollectionKit.newArrayList(0); - } - - public static boolean isParam(String routePart) { - return routePart.startsWith(":"); - } - - public static boolean isSplat(String routePart) { - return routePart.equals("*"); - } - -} From 822b2165e54541023e6988cc4c5c3f69dfe2d876 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 17:38:55 +0800 Subject: [PATCH 207/545] remove pathkit --- .../com/blade/route/SampleRouteMatcher.java | 187 +----------------- 1 file changed, 3 insertions(+), 184 deletions(-) diff --git a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java index 0c89c07bd..e55cb3220 100644 --- a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java @@ -10,8 +10,6 @@ import com.blade.http.HttpMethod; import com.blade.http.Path; -import blade.kit.PathKit; - public class SampleRouteMatcher { // private static final Logger LOGGER = Logger.getLogger(SampleRouteMatcher.class); @@ -99,7 +97,7 @@ public boolean matches(Route route, HttpMethod httpMethod, String path) { // 如果是拦截器的全部匹配模式则跳过,返回true if ((httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER) && (route.getHttpMethod() == httpMethod) - && route.getPath().equals(PathKit.ALL_PATHS)) { + && route.getPath().equals(Path.ALL_PATHS)) { return true; } @@ -130,8 +128,8 @@ private boolean matchPath(String path, String uri) { } // 检查参数 - List thisPathList = PathKit.convertRouteToList(path); - List uriList = PathKit.convertRouteToList(uri); + List thisPathList = Path.convertRouteToList(path); + List uriList = Path.convertRouteToList(uri); int thisPathSize = thisPathList.size(); int uriSize = uriList.size(); @@ -182,183 +180,4 @@ private boolean matchPath(String path, String uri) { } } - /** - * 查询是否有路由 - * - * @param httpMethod http请求方法,GET/POST - * @param uri 请求路径 - * @return 返回一个路由匹配对象 - *//* - public Route findRoute(HttpMethod httpMethod, String uri) { - - uri = (uri.length() > 1 && uri.endsWith("/")) ? uri.substring(0, uri.length() - 1) : uri; - - List routeEntries = this.findRouteMatcher(httpMethod, uri); - - // 优先匹配原则 - giveMatch(uri, routeEntries); - - RouteMatcher entry = routeEntries.size() > 0 ? routeEntries.get(0) : null; - - return entry != null ? new RouteMatcher(entry.getRouterHandler(), entry.getTarget(), entry.getExecMethod(), entry.getHttpMethod(), entry.getPath(), uri) : null; - } - - private void giveMatch(final String uri, List routeEntries) { - Collections.sort(routeEntries, new Comparator() { - @Override - public int compare(RouteMatcher o1, RouteMatcher o2) { - if(o2.getPath().equals(uri)){ - return o2.getPath().indexOf(uri); - } - return -1; - } - }); - } - - *//** - * 查询一个路由集合 - * - * @param httpMethod http请求方法,GET/POST - * @param path 请求路径 - * @return 返回一个路由匹配对象集合 - *//* - public List findInterceptor(HttpMethod httpMethod, String uri) { - if(uri.length() > 1){ - uri = uri.endsWith("/") ? uri.substring(0, uri.length() - 1) : uri; - } - List matchSet = CollectionKit.newArrayList(); - List routeEntries = this.searchInterceptor(httpMethod, uri); - - for (RouteMatcher routeEntry : routeEntries) { - matchSet.add(routeEntry); - } - - return matchSet; - } - - *//** - * 清空路由集合 - *//* - public void clearRoutes() { - routes.clear(); - } - - *//** - * 添加一个路由对象 - * - * @param target 路由目标执行的class - * @param execMethod 路由执行方法 - * @param url 路由url - * @param method 路由http方法 - *//* - public void addRoute(Class target, Method execMethod, String url, HttpMethod httpMethod) { - RouteMatcher routeMatcher = new RouteMatcher(); - routeMatcher.setTarget(target); - routeMatcher.setExecMethod(execMethod); - routeMatcher.setHttpMethod(httpMethod); - routeMatcher.setPath(url); - - LOGGER.debug("Add Route:" + routeMatcher); - - // 添加到路由集合 - routes.add(routeMatcher); - } - - *//** - * 添加一个拦截器对象 - * - * @param target 路由目标执行的class - * @param execMethod 路由执行方法 - * @param url 路由url - * @param method 路由http方法 - *//* - public void addInterceptor(Class target, Method execMethod, String url, HttpMethod httpMethod) { - RouteMatcher routeMatcher = new RouteMatcher(); - routeMatcher.setTarget(target); - routeMatcher.setExecMethod(execMethod); - routeMatcher.setHttpMethod(httpMethod); - routeMatcher.setPath(url); - - LOGGER.debug("Add Interceptor:" + routeMatcher); - - // 添加到路由集合 - interceptors.add(routeMatcher); - } - - *//** - * 添加一个路由对象 - * - * @param router 执行的匿名类 - * @param url 路由url - * @param method 路由http方法 - *//* - public void addRoute(RouteHandler routerHandler, String url, HttpMethod httpMethod) { - - RouteMatcher routeMatcher = new RouteMatcher(); - routeMatcher.setRouterHandler(routerHandler); - routeMatcher.setHttpMethod(httpMethod); - routeMatcher.setPath(url); - - LOGGER.debug("Add Route:" + routeMatcher); - - // 添加到路由集合 - routes.add(routeMatcher); - } - - *//** - * 添加一个拦截器对象 - * - * @param router 执行的匿名类 - * @param url 路由url - * @param method 路由http方法 - *//* - public void addInterceptor(RouteHandler routerHandler, String url, HttpMethod httpMethod) { - - RouteMatcher routeMatcher = new RouteMatcher(); - routeMatcher.setRouterHandler(routerHandler); - routeMatcher.setHttpMethod(httpMethod); - routeMatcher.setPath(url); - - LOGGER.debug("Add Interceptor:" + routeMatcher); - - // 添加到路由集合 - interceptors.add(routeMatcher); - } - - *//** - * 查找所有匹配HttpMethod和path的路由 - * - * @param httpMethod http方法 - * @param path 路由路径 - * @return 返回匹配的所有路由集合 - *//* - private List findRouteMatcher(HttpMethod httpMethod, String path) { - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - - List matchSet = CollectionKit.newArrayList(); - for (RouteMatcher entry : routes) { - if (entry.matches(httpMethod, path)) { - matchSet.add(entry); - } - } - return matchSet; - } - - *//** - * 查找所有匹配HttpMethod和path的路由 - * - * @param httpMethod http方法 - * @param path 路由路径 - * @return 返回匹配的所有路由集合 - *//* - private List searchInterceptor(HttpMethod httpMethod, String path) { - List matchSet = CollectionKit.newArrayList(); - for (RouteMatcher entry : interceptors) { - if (entry.matches(httpMethod, path)) { - matchSet.add(entry); - } - } - return matchSet; - } - */ } From 94d105e88cddae2ec56c2b170de82c279973b3d8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 17:50:33 +0800 Subject: [PATCH 208/545] add RenderException --- .../main/java/com/blade/render/Render.java | 4 +- blade-jetbrick/pom.xml | 76 ++--- .../java/blade/render/JetbrickRender.java | 322 ++++++++---------- 3 files changed, 173 insertions(+), 229 deletions(-) diff --git a/blade-core/src/main/java/com/blade/render/Render.java b/blade-core/src/main/java/com/blade/render/Render.java index 6b880e206..92516174b 100644 --- a/blade-core/src/main/java/com/blade/render/Render.java +++ b/blade-core/src/main/java/com/blade/render/Render.java @@ -8,7 +8,7 @@ * */ public interface Render { - - public void render(ModelAndView modelAndView, Writer writer); + + public void render(ModelAndView modelAndView, Writer writer) throws RenderException; } diff --git a/blade-jetbrick/pom.xml b/blade-jetbrick/pom.xml index 3be6989fb..5eeb1f4be 100644 --- a/blade-jetbrick/pom.xml +++ b/blade-jetbrick/pom.xml @@ -1,38 +1,38 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-jetbrick - jar - 1.2.6 - blade-jetbrick - https://github.com/biezhi/blade/tree/master/blade-jetbrick - - - - com.bladejava - blade-core - ${blade.version} - provided - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - com.github.subchen - jetbrick-template - 2.0.12 - - - - + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + + blade-jetbrick + jar + 1.2.7 + blade-jetbrick + https://github.com/biezhi/blade/tree/master/blade-jetbrick + + + + com.bladejava + blade-core + ${blade.version} + provided + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + com.github.subchen + jetbrick-template + 2.0.12 + + + + diff --git a/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java b/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java index 020b5bce6..073147d04 100644 --- a/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java +++ b/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java @@ -1,189 +1,133 @@ -package blade.render; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import com.blade.BladeWebContext; -import com.blade.render.ModelAndView; -import com.blade.render.Render; -import com.blade.servlet.Request; -import com.blade.servlet.Response; -import com.blade.servlet.Session; - -import blade.exception.BladeException; -import blade.kit.log.Logger; -import jetbrick.io.resource.ResourceNotFoundException; -import jetbrick.template.JetEngine; -import jetbrick.template.JetTemplate; - -/** - * Velocity渲染引擎 - * @author biezhi - * - */ -public class JetbrickRender extends Render { - - private static final Logger LOGGER = Logger.getLogger(JetbrickRender.class); - - private JetEngine jetEngine; - - private Properties config; - - /** - * 默认构造函数 - */ - public JetbrickRender() { - config = new Properties(); - config.put("jetx.input.encoding", blade.encoding()); - config.put("jetx.output.encoding", blade.encoding()); - config.put("jetx.template.suffix", ".html"); - config.put("jetx.template.loaders", "jetbrick.template.loader.FileSystemResourceLoader"); - - jetEngine = JetEngine.create(config); - } - - /** - * @return 返回JetEngine引擎 - */ - public JetEngine getJetEngine(){ - return jetEngine; - } - - /** - * 清空配置 - */ - public void clean(){ - if(null != config){ - config.clear(); - } - } - - /** - * 添加一个配置 - * @param key 配置键 - * @param value 配置值 - */ - public void put(String key, Object value){ - if(null == config){ - config = new Properties(); - } - config.put(key, value); - } - - /** - * 根据配置文件构造一个JetEngine引擎 - * @param configLocation - * @throws IOException - */ - public JetbrickRender(String configLocation) throws IOException { - jetEngine = JetEngine.create(configLocation); - } - - /** - * 根据构造一个JetEngine引擎 - * @param config Properties配置 - */ - public JetbrickRender(Properties config) { - this.config = config; - jetEngine = JetEngine.create(this.config); - } - - /** - * 手动构造JetEngine引擎 - * @param jetEngine jetEngine引擎 - */ - public JetbrickRender(JetEngine jetEngine) { - this.jetEngine = jetEngine; - } - - /** - * 渲染视图 - */ - @Override - public Object render(String view) { - - Response response = BladeWebContext.response(); - try { - Request request = BladeWebContext.request(); - Session session = BladeWebContext.session(); - - String realView = blade.webRoot() + disposeView(view); - - JetTemplate template = jetEngine.getTemplate(realView); - - Map context = new HashMap(); - - Set attrs = request.attributes(); - if(null != attrs && attrs.size() > 0){ - for(String attr : attrs){ - context.put(attr, request.attribute(attr)); - } - } - - Set session_attrs = session.attributes(); - if(null != session_attrs && session_attrs.size() > 0){ - for(String attr : session_attrs){ - context.put(attr, session.attribute(attr)); - } - } - - template.render(context, response.outputStream()); - } catch (ResourceNotFoundException e) { - render404(response, disposeView(view)); - } catch (IOException e) { - LOGGER.error(e); - } - return null; - } - - - /** - * 渲染视图 - */ - @Override - public Object render(ModelAndView modelAndView) { - - Response response = BladeWebContext.response(); - - try { - Request request = BladeWebContext.request(); - Session session = BladeWebContext.session(); - - if(null == modelAndView){ - throw new BladeException("modelAndView is null"); - } - - String view = blade.webRoot() + disposeView(modelAndView.getView()); - - JetTemplate template = jetEngine.getTemplate(view); - - Map context = modelAndView.getModel(); - - Set attrs = request.attributes(); - if(null != attrs && attrs.size() > 0){ - for(String attr : attrs){ - context.put(attr, request.attribute(attr)); - } - } - - Set session_attrs = session.attributes(); - if(null != session_attrs && session_attrs.size() > 0){ - for(String attr : session_attrs){ - context.put(attr, session.attribute(attr)); - } - } - - template.render(context, response.outputStream()); - - } catch (ResourceNotFoundException e) { - render404(response, modelAndView.getView()); - } catch (IOException e) { - LOGGER.error(e); - } - return null; - } - -} +package blade.render; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import com.blade.Blade; +import com.blade.context.BladeWebContext; +import com.blade.http.Request; +import com.blade.render.ModelAndView; +import com.blade.render.Render; +import com.blade.servlet.Session; + +import blade.kit.log.Logger; +import jetbrick.template.JetEngine; +import jetbrick.template.JetTemplate; + +/** + * Velocity渲染引擎 + * @author biezhi + * + */ +public class JetbrickRender implements Render { + + private static final Logger LOGGER = Logger.getLogger(JetbrickRender.class); + + private JetEngine jetEngine; + + private Properties config; + + private Blade blade; + /** + * 默认构造函数 + */ + public JetbrickRender() { + blade = Blade.me(); + config = new Properties(); + config.put("jetx.input.encoding", blade.encoding()); + config.put("jetx.output.encoding", blade.encoding()); + config.put("jetx.template.suffix", ".html"); + config.put("jetx.template.loaders", "jetbrick.template.loader.FileSystemResourceLoader"); + jetEngine = JetEngine.create(config); + } + + /** + * @return 返回JetEngine引擎 + */ + public JetEngine getJetEngine(){ + return jetEngine; + } + + /** + * 清空配置 + */ + public void clean(){ + if(null != config){ + config.clear(); + } + } + + /** + * 添加一个配置 + * @param key 配置键 + * @param value 配置值 + */ + public void put(String key, Object value){ + if(null == config){ + config = new Properties(); + } + config.put(key, value); + } + + /** + * 根据配置文件构造一个JetEngine引擎 + * @param configLocation + * @throws IOException + */ + public JetbrickRender(String configLocation) throws IOException { + jetEngine = JetEngine.create(configLocation); + } + + /** + * 根据构造一个JetEngine引擎 + * @param config Properties配置 + */ + public JetbrickRender(Properties config) { + this.config = config; + jetEngine = JetEngine.create(this.config); + } + + /** + * 手动构造JetEngine引擎 + * @param jetEngine jetEngine引擎 + */ + public JetbrickRender(JetEngine jetEngine) { + this.jetEngine = jetEngine; + } + + + @Override + public void render(ModelAndView modelAndView, Writer writer) { + Request request = BladeWebContext.request(); + Session session = request.session(); + + JetTemplate template = jetEngine.getTemplate(modelAndView.getView()); + + Map context = modelAndView.getModel(); + + Set attrs = request.attributes(); + if(null != attrs && attrs.size() > 0){ + for(String attr : attrs){ + context.put(attr, request.attribute(attr)); + } + } + + Set session_attrs = session.attributes(); + if(null != session_attrs && session_attrs.size() > 0){ + for(String attr : session_attrs){ + context.put(attr, session.attribute(attr)); + } + } + + try { + template.render(context, writer); + } catch (Exception e) { + e.printStackTrace(); + LOGGER.error(e); + } + } + +} From 1720f77aff715001de03acee5e492d35d43853d9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 18:00:14 +0800 Subject: [PATCH 209/545] merge render engin --- LAST_VERSION.md | 27 --- blade-beetl/README.md | 44 ---- blade-beetl/pom.xml | 37 ---- .../main/java/blade/render/BeetlRender.java | 170 --------------- blade-core/pom.xml | 51 +++-- blade-jetbrick/README.md | 45 ---- blade-jetbrick/pom.xml | 38 ---- .../java/blade/render/JetbrickRender.java | 133 ------------ blade-velocity/README.md | 46 ----- blade-velocity/pom.xml | 37 ---- .../java/blade/render/VelocityRender.java | 193 ------------------ 11 files changed, 36 insertions(+), 785 deletions(-) delete mode 100644 blade-beetl/README.md delete mode 100644 blade-beetl/pom.xml delete mode 100644 blade-beetl/src/main/java/blade/render/BeetlRender.java delete mode 100644 blade-jetbrick/README.md delete mode 100644 blade-jetbrick/pom.xml delete mode 100644 blade-jetbrick/src/main/java/blade/render/JetbrickRender.java delete mode 100644 blade-velocity/README.md delete mode 100644 blade-velocity/pom.xml delete mode 100644 blade-velocity/src/main/java/blade/render/VelocityRender.java diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 9206fbe7f..fb7a40fc8 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -44,33 +44,6 @@ ``` -## [blade-jetbrick](http://search.maven.org/#search%7Cga%7C1%7Cblade-jetbrick) -```xml - -    com.bladejava -    blade-jetbrick -    1.2.6 - -``` - -## [blade-beetl](http://search.maven.org/#search%7Cga%7C1%7Cblade-beetl) -```xml - -    com.bladejava -    blade-beetl -    1.2.4 - -``` - -## [blade-velocity](http://search.maven.org/#search%7Cga%7C1%7Cblade-velocity) -```xml - -    com.bladejava -    blade-velocity -    1.2.3 - -``` - ## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache) ```xml diff --git a/blade-beetl/README.md b/blade-beetl/README.md deleted file mode 100644 index d8121d3dd..000000000 --- a/blade-beetl/README.md +++ /dev/null @@ -1,44 +0,0 @@ -#blade-beetl - -```java -public class App extends BladeApplication{ - - Logger logger = Logger.getLogger(App.class); - @Override - public void init() { - - // 设置路由、拦截器包所在包 - Blade.defaultRoute("blade.sample"); - - // 设置BeetlRender引擎 - Blade.viewEngin(new BeetlRender()); - } - -} -``` - -Route Code - -```java -@Route("/you/:username") -public String you(Request request) { - ModelAndView modelAndView = new ModelAndView(""); - modelAndView.add("username", request.pathParam(":username")); - return R.render(modelAndView); -} -``` - -View Code - -```html - - - - -Blade Beetl Demo - - -

hello ${username}

- - -``` \ No newline at end of file diff --git a/blade-beetl/pom.xml b/blade-beetl/pom.xml deleted file mode 100644 index 1f0ac6c2a..000000000 --- a/blade-beetl/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-beetl - jar - 1.2.4 - blade-beetl - https://github.com/biezhi/blade/tree/master/blade-beetl - - - - com.bladejava - blade-core - ${blade.version} - provided - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - org.beetl - beetl-core - 2.2.3 - - - diff --git a/blade-beetl/src/main/java/blade/render/BeetlRender.java b/blade-beetl/src/main/java/blade/render/BeetlRender.java deleted file mode 100644 index 3a30f91fb..000000000 --- a/blade-beetl/src/main/java/blade/render/BeetlRender.java +++ /dev/null @@ -1,170 +0,0 @@ -package blade.render; - -import java.io.IOException; -import java.util.Map; -import java.util.Set; - -import org.beetl.core.Configuration; -import org.beetl.core.GroupTemplate; -import org.beetl.core.Template; -import org.beetl.core.exception.BeetlException; -import org.beetl.core.resource.WebAppResourceLoader; - -import com.blade.BladeWebContext; -import com.blade.render.ModelAndView; -import com.blade.render.Render; -import com.blade.servlet.Request; -import com.blade.servlet.Response; -import com.blade.servlet.Session; - -import blade.exception.BladeException; -import blade.kit.log.Logger; - -/** - * Beetl渲染引擎 - * @author biezhi - * - */ -public class BeetlRender extends Render { - - private static final Logger LOGGER = Logger.getLogger(BeetlRender.class); - - private GroupTemplate groupTemplate = null; - - /** - * 默认构造函数 - */ - public BeetlRender() { - try { - String root = blade.webRoot() + blade.viewPrefix(); - WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); - resourceLoader.setAutoCheck(true); - resourceLoader.setRoot(root); - Configuration cfg = Configuration.defaultConfiguration(); - groupTemplate = new GroupTemplate(resourceLoader, cfg); - } catch (IOException e) { - LOGGER.error(e); - } - } - - public BeetlRender(Configuration configuration) { - try { - String root = blade.webRoot() + blade.viewPrefix(); - WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); - resourceLoader.setAutoCheck(true); - resourceLoader.setRoot(root); - Configuration cfg = Configuration.defaultConfiguration(); - groupTemplate = new GroupTemplate(resourceLoader, cfg); - groupTemplate.setConf(configuration); - } catch (IOException e) { - LOGGER.error(e); - } - } - - /** - * 渲染视图 - */ - @Override - public Object render(String view) { - - Response response = BladeWebContext.response(); - try { - Request request = BladeWebContext.request(); - Session session = BladeWebContext.session(); - - view = disposeView(view); - - Template template = groupTemplate.getTemplate(view); - - Set attrs = request.attributes(); - if(null != attrs && attrs.size() > 0){ - for(String attr : attrs){ - template.binding(attr, request.attribute(attr)); - } - } - - Set session_attrs = session.attributes(); - if(null != session_attrs && session_attrs.size() > 0){ - for(String attr : session_attrs){ - template.binding(attr, session.attribute(attr)); - } - } - - template.renderTo(response.outputStream()); - } catch (BeetlException e) { - LOGGER.error(e); - } catch (IOException e) { - LOGGER.error(e); - } - return null; - } - - - /** - * 渲染视图 - */ - @Override - public Object render(ModelAndView modelAndView) { - - Response response = BladeWebContext.response(); - try { - - Request request = BladeWebContext.request(); - Session session = BladeWebContext.session(); - - if(null == modelAndView){ - throw new BladeException("modelAndView is null"); - } - - String view = disposeView(modelAndView.getView()); - - Template template = groupTemplate.getTemplate(view); - - Map context = modelAndView.getModel(); - if(null != context && context.size() > 0){ - Set keys = context.keySet(); - for(String key : keys){ - template.binding(key, context.get(key)); - } - } - - Set attrs = request.attributes(); - if(null != attrs && attrs.size() > 0){ - for(String attr : attrs){ - template.binding(attr, request.attribute(attr)); - } - } - - Set session_attrs = session.attributes(); - if(null != session_attrs && session_attrs.size() > 0){ - for(String attr : session_attrs){ - template.binding(attr, session.attribute(attr)); - } - } - - template.renderTo(response.outputStream()); - } catch (BeetlException e) { - LOGGER.error(e); - } catch (IOException e) { - LOGGER.error(e); - } - - return null; - } - - /** - * 处理视图 - * @param view 视图名称 - * @return 返回取出多余"/"的全路径 - */ - @Override - protected String disposeView(String view){ - if(null != view){ - view = view.replaceAll("[/]+", "/"); - if(!view.endsWith(blade.viewSuffix())){ - view = view + blade.viewSuffix(); - } - } - return view; - } -} diff --git a/blade-core/pom.xml b/blade-core/pom.xml index bbd95b214..6e567b6b6 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -8,17 +8,20 @@ blade-root 1.0 - + blade-core jar ${blade.version} blade-core https://github.com/biezhi/blade/blade-core - + 9.3.4.v20151007 + 2.0.12 + 2.2.3 + 1.7 - + com.bladejava @@ -32,17 +35,35 @@ provided - org.eclipse.jetty - jetty-server - ${jetty.version} - provided - - - org.eclipse.jetty - jetty-webapp - ${jetty.version} - provided - - + com.github.subchen + jetbrick-template + ${jetbrick.version} + provided +
+ + org.beetl + beetl-core + ${beetl.version} + provided + + + org.apache.velocity + velocity + ${velocity.version} + provided + + + org.eclipse.jetty + jetty-server + ${jetty.version} + provided + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + provided + +
diff --git a/blade-jetbrick/README.md b/blade-jetbrick/README.md deleted file mode 100644 index 6bcbb8d7a..000000000 --- a/blade-jetbrick/README.md +++ /dev/null @@ -1,45 +0,0 @@ -#blade-jetbrick - -```java -public class App extends BladeApplication{ - - Logger logger = Logger.getLogger(App.class); - - @Override - public void init() { - - // 设置路由、拦截器包所在包 - Blade.defaultRoute("blade.sample"); - - // 设置JetbrickRender引擎 - Blade.viewEngin(new JetbrickRender()); - } - -} -``` - -Route Code - -```java -@Route("/you/:username") -public String you(Request request) { - ModelAndView modelAndView = new ModelAndView(""); - modelAndView.add("username", request.pathParam(":username")); - return R.render(modelAndView); -} -``` - -View Code - -```html - - - - -Blade Jetbrick Demo - - -

hello ${username}

- - -``` \ No newline at end of file diff --git a/blade-jetbrick/pom.xml b/blade-jetbrick/pom.xml deleted file mode 100644 index 5eeb1f4be..000000000 --- a/blade-jetbrick/pom.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-jetbrick - jar - 1.2.7 - blade-jetbrick - https://github.com/biezhi/blade/tree/master/blade-jetbrick - - - - com.bladejava - blade-core - ${blade.version} - provided - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - com.github.subchen - jetbrick-template - 2.0.12 - - - - diff --git a/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java b/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java deleted file mode 100644 index 073147d04..000000000 --- a/blade-jetbrick/src/main/java/blade/render/JetbrickRender.java +++ /dev/null @@ -1,133 +0,0 @@ -package blade.render; - -import java.io.IOException; -import java.io.Writer; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import com.blade.Blade; -import com.blade.context.BladeWebContext; -import com.blade.http.Request; -import com.blade.render.ModelAndView; -import com.blade.render.Render; -import com.blade.servlet.Session; - -import blade.kit.log.Logger; -import jetbrick.template.JetEngine; -import jetbrick.template.JetTemplate; - -/** - * Velocity渲染引擎 - * @author biezhi - * - */ -public class JetbrickRender implements Render { - - private static final Logger LOGGER = Logger.getLogger(JetbrickRender.class); - - private JetEngine jetEngine; - - private Properties config; - - private Blade blade; - /** - * 默认构造函数 - */ - public JetbrickRender() { - blade = Blade.me(); - config = new Properties(); - config.put("jetx.input.encoding", blade.encoding()); - config.put("jetx.output.encoding", blade.encoding()); - config.put("jetx.template.suffix", ".html"); - config.put("jetx.template.loaders", "jetbrick.template.loader.FileSystemResourceLoader"); - jetEngine = JetEngine.create(config); - } - - /** - * @return 返回JetEngine引擎 - */ - public JetEngine getJetEngine(){ - return jetEngine; - } - - /** - * 清空配置 - */ - public void clean(){ - if(null != config){ - config.clear(); - } - } - - /** - * 添加一个配置 - * @param key 配置键 - * @param value 配置值 - */ - public void put(String key, Object value){ - if(null == config){ - config = new Properties(); - } - config.put(key, value); - } - - /** - * 根据配置文件构造一个JetEngine引擎 - * @param configLocation - * @throws IOException - */ - public JetbrickRender(String configLocation) throws IOException { - jetEngine = JetEngine.create(configLocation); - } - - /** - * 根据构造一个JetEngine引擎 - * @param config Properties配置 - */ - public JetbrickRender(Properties config) { - this.config = config; - jetEngine = JetEngine.create(this.config); - } - - /** - * 手动构造JetEngine引擎 - * @param jetEngine jetEngine引擎 - */ - public JetbrickRender(JetEngine jetEngine) { - this.jetEngine = jetEngine; - } - - - @Override - public void render(ModelAndView modelAndView, Writer writer) { - Request request = BladeWebContext.request(); - Session session = request.session(); - - JetTemplate template = jetEngine.getTemplate(modelAndView.getView()); - - Map context = modelAndView.getModel(); - - Set attrs = request.attributes(); - if(null != attrs && attrs.size() > 0){ - for(String attr : attrs){ - context.put(attr, request.attribute(attr)); - } - } - - Set session_attrs = session.attributes(); - if(null != session_attrs && session_attrs.size() > 0){ - for(String attr : session_attrs){ - context.put(attr, session.attribute(attr)); - } - } - - try { - template.render(context, writer); - } catch (Exception e) { - e.printStackTrace(); - LOGGER.error(e); - } - } - -} diff --git a/blade-velocity/README.md b/blade-velocity/README.md deleted file mode 100644 index 22592c2ce..000000000 --- a/blade-velocity/README.md +++ /dev/null @@ -1,46 +0,0 @@ -#blade-velocity - -```java -public class App implements BladeApplication{ - - Logger logger = Logger.getLogger(App.class); - - @Override - public void init() { - - // 设置路由、拦截器包所在包 - Blade.defaultRoute("blade.sample"); - - // 设置VelocityRender引擎 - final Render render = new VelocityRender(); - Blade.viewEngin(render); - } - -} -``` - -Route Code - -```java -@Route("/you/:username") -public String you(Request request) { - ModelAndView modelAndView = new ModelAndView(""); - modelAndView.add("username", request.pathParam(":username")); - return R.render(modelAndView); -} -``` - -View Code - -```html - - - - -Blade Velocity Demo - - -

hello $username

- - -``` \ No newline at end of file diff --git a/blade-velocity/pom.xml b/blade-velocity/pom.xml deleted file mode 100644 index 734c28e10..000000000 --- a/blade-velocity/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-velocity - jar - 1.2.3 - blade-velocity - https://github.com/biezhi/blade/tree/master/blade-velocity - - - - com.bladejava - blade-core - ${blade.version} - provided - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - org.apache.velocity - velocity - 1.7 - - - diff --git a/blade-velocity/src/main/java/blade/render/VelocityRender.java b/blade-velocity/src/main/java/blade/render/VelocityRender.java deleted file mode 100644 index 27ed48e07..000000000 --- a/blade-velocity/src/main/java/blade/render/VelocityRender.java +++ /dev/null @@ -1,193 +0,0 @@ -package blade.render; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.util.Properties; -import java.util.Set; - -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.Velocity; -import org.apache.velocity.app.VelocityEngine; -import org.apache.velocity.exception.MethodInvocationException; -import org.apache.velocity.exception.ParseErrorException; -import org.apache.velocity.exception.ResourceNotFoundException; - -import com.blade.BladeWebContext; -import com.blade.render.ModelAndView; -import com.blade.render.Render; -import com.blade.servlet.Request; -import com.blade.servlet.Response; -import com.blade.servlet.Session; - -import blade.exception.BladeException; -import blade.kit.log.Logger; - -/** - * Velocity渲染引擎 - * @author biezhi - * - */ -public class VelocityRender extends Render { - - private static final Logger LOGGER = Logger.getLogger(VelocityRender.class); - - private final VelocityEngine velocityEngine; - - /** - * 默认构造函数 - */ - public VelocityRender() { - Properties properties = new Properties(); - - properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, blade.webRoot()); - properties.setProperty(Velocity.ENCODING_DEFAULT, blade.encoding()); - properties.setProperty(Velocity.INPUT_ENCODING, blade.encoding()); - properties.setProperty(Velocity.OUTPUT_ENCODING, blade.encoding()); - velocityEngine = new VelocityEngine(properties); - } - - /** - * 根据配置文件构造一个Velocity引擎 - * @param propertiesFile - * @throws IOException - */ - public VelocityRender(String propertiesFile) throws IOException { - String loadPath = VelocityRender.class.getClassLoader().getResource("/").getPath(); - String fileName = loadPath + propertiesFile; - - Properties properties = new Properties(); - InputStream inStream = new FileInputStream(new File(fileName)); - properties.load(inStream); - - // 默认查询路径 - if(!properties.contains(Velocity.FILE_RESOURCE_LOADER_PATH)){ - properties.put(Velocity.FILE_RESOURCE_LOADER_PATH, blade.webRoot()); - } - velocityEngine = new VelocityEngine(properties); - } - - /** - * 根据构造一个Velocity引擎 - * @param properties - */ - public VelocityRender(Properties properties) { - velocityEngine = new VelocityEngine(properties); - } - - /** - * 手动构造Velocity引擎 - * @param velocityEngine_ - */ - public VelocityRender(VelocityEngine velocityEngine) { - this.velocityEngine = velocityEngine; - } - - /** - * 渲染视图 - */ - @Override - public Object render(String view) { - - Response response = BladeWebContext.response(); - try { - Request request = BladeWebContext.request(); - Session session = BladeWebContext.session(); - - view = disposeView(view); - - VelocityContext context = new VelocityContext(); - - Template template = velocityEngine.getTemplate(view); - - Set attrs = request.attributes(); - if(null != attrs && attrs.size() > 0){ - for(String attr : attrs){ - context.put(attr, request.attribute(attr)); - } - } - - Set session_attrs = session.attributes(); - if(null != session_attrs && session_attrs.size() > 0){ - for(String attr : session_attrs){ - context.put(attr, session.attribute(attr)); - } - } - - PrintWriter writer = response.writer(); - - template.merge(context, writer); - - writer.flush(); - writer.close(); - - } catch (ResourceNotFoundException e) { - render404(response, view); - } catch (ParseErrorException e) { - LOGGER.error(e); - } catch (MethodInvocationException e) { - LOGGER.error(e); - } catch (IOException e) { - LOGGER.error(e); - } - return null; - } - - - /** - * 渲染视图 - */ - @Override - public Object render(ModelAndView modelAndView) { - Response response = BladeWebContext.response(); - try { - Request request = BladeWebContext.request(); - Session session = BladeWebContext.session(); - - if(null == modelAndView){ - throw new BladeException("modelAndView is null"); - } - - String view = disposeView(modelAndView.getView()); - - VelocityContext context = new VelocityContext(modelAndView.getModel()); - - Set attrs = request.attributes(); - if(null != attrs && attrs.size() > 0){ - for(String attr : attrs){ - context.put(attr, request.attribute(attr)); - } - } - - Set session_attrs = session.attributes(); - if(null != session_attrs && session_attrs.size() > 0){ - for(String attr : session_attrs){ - context.put(attr, session.attribute(attr)); - } - } - - Template template = velocityEngine.getTemplate(view); - - PrintWriter writer = response.writer(); - - template.merge(context, writer); - - writer.flush(); - writer.close(); - - } catch (ResourceNotFoundException e) { - render404(response, modelAndView.getView()); - } catch (ParseErrorException e) { - LOGGER.error(e); - } catch (MethodInvocationException e) { - LOGGER.error(e); - } catch (IOException e) { - LOGGER.error(e); - } - return null; - } - -} From 81141991aa15b199966b0b092888488d27f2c9e2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 18:11:46 +0800 Subject: [PATCH 210/545] update models --- pom.xml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index dae248cbd..341cbe68d 100644 --- a/pom.xml +++ b/pom.xml @@ -23,13 +23,10 @@ blade-kit blade-core blade-cache - blade-jetbrick blade-sql2o - blade-velocity - blade-beetl blade-redis - blade-startup - + blade-startup + From a34a5d5f57f1e3e51acb3ca094591ace07637052 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 18:14:46 +0800 Subject: [PATCH 211/545] add render --- .../java/com/blade/render/BeetlRender.java | 100 +++++++++++++ .../java/com/blade/render/JetbrickRender.java | 136 ++++++++++++++++++ .../com/blade/render/RenderException.java | 22 +++ .../java/com/blade/render/VelocityRender.java | 121 ++++++++++++++++ 4 files changed, 379 insertions(+) create mode 100644 blade-core/src/main/java/com/blade/render/BeetlRender.java create mode 100644 blade-core/src/main/java/com/blade/render/JetbrickRender.java create mode 100644 blade-core/src/main/java/com/blade/render/RenderException.java create mode 100644 blade-core/src/main/java/com/blade/render/VelocityRender.java diff --git a/blade-core/src/main/java/com/blade/render/BeetlRender.java b/blade-core/src/main/java/com/blade/render/BeetlRender.java new file mode 100644 index 000000000..56054beba --- /dev/null +++ b/blade-core/src/main/java/com/blade/render/BeetlRender.java @@ -0,0 +1,100 @@ +package com.blade.render; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; +import java.util.Set; + +import org.beetl.core.Configuration; +import org.beetl.core.GroupTemplate; +import org.beetl.core.Template; +import org.beetl.core.exception.BeetlException; +import org.beetl.core.resource.WebAppResourceLoader; + +import com.blade.Blade; +import com.blade.context.BladeWebContext; +import com.blade.http.Request; +import com.blade.servlet.Session; + +import blade.kit.log.Logger; + +/** + * Beetl渲染引擎 + * @author biezhi + * + */ +public class BeetlRender implements Render { + + private static final Logger LOGGER = Logger.getLogger(BeetlRender.class); + + private GroupTemplate groupTemplate = null; + + private Blade blade; + /** + * 默认构造函数 + */ + public BeetlRender() { + try { + blade = Blade.me(); + String root = blade.webRoot() + blade.viewPrefix(); + WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); + resourceLoader.setAutoCheck(true); + resourceLoader.setRoot(root); + Configuration cfg = Configuration.defaultConfiguration(); + groupTemplate = new GroupTemplate(resourceLoader, cfg); + } catch (IOException e) { + LOGGER.error(e); + } + } + + public BeetlRender(Configuration configuration) { + try { + blade = Blade.me(); + String root = blade.webRoot() + blade.viewPrefix(); + WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); + resourceLoader.setAutoCheck(true); + resourceLoader.setRoot(root); + Configuration cfg = Configuration.defaultConfiguration(); + groupTemplate = new GroupTemplate(resourceLoader, cfg); + groupTemplate.setConf(configuration); + } catch (IOException e) { + LOGGER.error(e); + } + } + + @Override + public void render(ModelAndView modelAndView, Writer writer) throws RenderException { + Request request = BladeWebContext.request(); + Session session = request.session(); + + Template template = groupTemplate.getTemplate(modelAndView.getView()); + + Map context = modelAndView.getModel(); + if(null != context && context.size() > 0){ + Set keys = context.keySet(); + for(String key : keys){ + template.binding(key, context.get(key)); + } + } + + Set attrs = request.attributes(); + if(null != attrs && attrs.size() > 0){ + for(String attr : attrs){ + template.binding(attr, request.attribute(attr)); + } + } + + Set session_attrs = session.attributes(); + if(null != session_attrs && session_attrs.size() > 0){ + for(String attr : session_attrs){ + template.binding(attr, session.attribute(attr)); + } + } + try { + template.renderTo(writer); + } catch (BeetlException e) { + e.printStackTrace(); + LOGGER.error(e); + } + } +} diff --git a/blade-core/src/main/java/com/blade/render/JetbrickRender.java b/blade-core/src/main/java/com/blade/render/JetbrickRender.java new file mode 100644 index 000000000..2c3e06350 --- /dev/null +++ b/blade-core/src/main/java/com/blade/render/JetbrickRender.java @@ -0,0 +1,136 @@ +package com.blade.render; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import com.blade.Blade; +import com.blade.context.BladeWebContext; +import com.blade.http.Request; +import com.blade.render.ModelAndView; +import com.blade.render.Render; +import com.blade.servlet.Session; + +import blade.kit.log.Logger; +import jetbrick.template.JetEngine; +import jetbrick.template.JetTemplate; + +/** + * Velocity渲染引擎 + * @author biezhi + * + */ +public class JetbrickRender implements Render { + + private static final Logger LOGGER = Logger.getLogger(JetbrickRender.class); + + private JetEngine jetEngine; + + private Properties config; + + private Blade blade; + /** + * 默认构造函数 + */ + public JetbrickRender() { + this.blade = Blade.me(); + config = new Properties(); + config.put("jetx.input.encoding", blade.encoding()); + config.put("jetx.output.encoding", blade.encoding()); + config.put("jetx.template.suffix", ".html"); + config.put("jetx.template.loaders", "jetbrick.template.loader.FileSystemResourceLoader"); + jetEngine = JetEngine.create(config); + } + + /** + * @return 返回JetEngine引擎 + */ + public JetEngine getJetEngine(){ + return jetEngine; + } + + /** + * 清空配置 + */ + public void clean(){ + if(null != config){ + config.clear(); + } + } + + /** + * 添加一个配置 + * @param key 配置键 + * @param value 配置值 + */ + public void put(String key, Object value){ + if(null == config){ + config = new Properties(); + } + config.put(key, value); + } + + /** + * 根据配置文件构造一个JetEngine引擎 + * @param configLocation + * @throws IOException + */ + public JetbrickRender(String configLocation) throws IOException { + this.blade = Blade.me(); + jetEngine = JetEngine.create(configLocation); + } + + /** + * 根据构造一个JetEngine引擎 + * @param config Properties配置 + */ + public JetbrickRender(Properties config) { + this.blade = Blade.me(); + this.config = config; + jetEngine = JetEngine.create(this.config); + } + + /** + * 手动构造JetEngine引擎 + * @param jetEngine jetEngine引擎 + */ + public JetbrickRender(JetEngine jetEngine) { + this.blade = Blade.me(); + this.jetEngine = jetEngine; + } + + + @Override + public void render(ModelAndView modelAndView, Writer writer) { + Request request = BladeWebContext.request(); + Session session = request.session(); + + JetTemplate template = jetEngine.getTemplate(modelAndView.getView()); + + Map context = modelAndView.getModel(); + + Set attrs = request.attributes(); + if(null != attrs && attrs.size() > 0){ + for(String attr : attrs){ + context.put(attr, request.attribute(attr)); + } + } + + Set session_attrs = session.attributes(); + if(null != session_attrs && session_attrs.size() > 0){ + for(String attr : session_attrs){ + context.put(attr, session.attribute(attr)); + } + } + + try { + template.render(context, writer); + } catch (Exception e) { + e.printStackTrace(); + LOGGER.error(e); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/render/RenderException.java b/blade-core/src/main/java/com/blade/render/RenderException.java new file mode 100644 index 000000000..51cb98551 --- /dev/null +++ b/blade-core/src/main/java/com/blade/render/RenderException.java @@ -0,0 +1,22 @@ +package com.blade.render; +public class RenderException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public RenderException() { + super(); + } + + public RenderException(String message, Throwable cause) { + super(message, cause); + } + + public RenderException(String message) { + super(message); + } + + public RenderException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/render/VelocityRender.java b/blade-core/src/main/java/com/blade/render/VelocityRender.java new file mode 100644 index 000000000..2d3b9e5ed --- /dev/null +++ b/blade-core/src/main/java/com/blade/render/VelocityRender.java @@ -0,0 +1,121 @@ +package com.blade.render; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.util.Properties; +import java.util.Set; + +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.app.VelocityEngine; + +import com.blade.Blade; +import com.blade.context.BladeWebContext; +import com.blade.http.Request; +import com.blade.servlet.Session; + +import blade.kit.log.Logger; + +/** + * Velocity渲染引擎 + * @author biezhi + * + */ +public class VelocityRender implements Render { + + private static final Logger LOGGER = Logger.getLogger(VelocityRender.class); + + private final VelocityEngine velocityEngine; + + private Blade blade; + /** + * 默认构造函数 + */ + public VelocityRender() { + blade = Blade.me(); + Properties properties = new Properties(); + + properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, blade.webRoot()); + properties.setProperty(Velocity.ENCODING_DEFAULT, blade.encoding()); + properties.setProperty(Velocity.INPUT_ENCODING, blade.encoding()); + properties.setProperty(Velocity.OUTPUT_ENCODING, blade.encoding()); + velocityEngine = new VelocityEngine(properties); + } + + /** + * 根据配置文件构造一个Velocity引擎 + * @param propertiesFile + * @throws IOException + */ + public VelocityRender(String propertiesFile) throws IOException { + blade = Blade.me(); + String loadPath = VelocityRender.class.getClassLoader().getResource("/").getPath(); + String fileName = loadPath + propertiesFile; + + Properties properties = new Properties(); + InputStream inStream = new FileInputStream(new File(fileName)); + properties.load(inStream); + + // 默认查询路径 + if(!properties.contains(Velocity.FILE_RESOURCE_LOADER_PATH)){ + properties.put(Velocity.FILE_RESOURCE_LOADER_PATH, blade.webRoot()); + } + velocityEngine = new VelocityEngine(properties); + } + + /** + * 根据构造一个Velocity引擎 + * @param properties + */ + public VelocityRender(Properties properties) { + blade = Blade.me(); + velocityEngine = new VelocityEngine(properties); + } + + /** + * 手动构造Velocity引擎 + * @param velocityEngine_ + */ + public VelocityRender(VelocityEngine velocityEngine) { + blade = Blade.me(); + this.velocityEngine = velocityEngine; + } + + @Override + public void render(ModelAndView modelAndView, Writer writer) throws RenderException { + Request request = BladeWebContext.request(); + Session session = request.session(); + + VelocityContext context = new VelocityContext(modelAndView.getModel()); + + Set attrs = request.attributes(); + if(null != attrs && attrs.size() > 0){ + for(String attr : attrs){ + context.put(attr, request.attribute(attr)); + } + } + + Set session_attrs = session.attributes(); + if(null != session_attrs && session_attrs.size() > 0){ + for(String attr : session_attrs){ + context.put(attr, session.attribute(attr)); + } + } + + try { + Template template = velocityEngine.getTemplate(modelAndView.getView()); + template.merge(context, writer); + writer.flush(); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + LOGGER.error(e); + } + + } + +} From 834c4a1f325ba793eab4954774938ffe4defb0a9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 28 Oct 2015 18:21:59 +0800 Subject: [PATCH 212/545] add package-info --- blade-core/src/main/java/com/blade/annotation/package-info.java | 2 +- blade-core/src/main/java/com/blade/ioc/package-info.java | 2 +- blade-core/src/main/java/com/blade/package-info.java | 2 +- blade-core/src/main/java/com/blade/plugin/package-info.java | 2 +- blade-core/src/main/java/com/blade/render/package-info.java | 2 +- blade-core/src/main/java/com/blade/route/package-info.java | 2 +- blade-core/src/main/java/com/blade/servlet/package-info.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/blade-core/src/main/java/com/blade/annotation/package-info.java b/blade-core/src/main/java/com/blade/annotation/package-info.java index 2c47704f1..537ca5e3a 100644 --- a/blade-core/src/main/java/com/blade/annotation/package-info.java +++ b/blade-core/src/main/java/com/blade/annotation/package-info.java @@ -1,4 +1,4 @@ /** - * blade注解所在包 + * Blade注解包 */ package com.blade.annotation; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/package-info.java b/blade-core/src/main/java/com/blade/ioc/package-info.java index 7e196796a..3573a46d3 100644 --- a/blade-core/src/main/java/com/blade/ioc/package-info.java +++ b/blade-core/src/main/java/com/blade/ioc/package-info.java @@ -1,4 +1,4 @@ /** - * blade依赖注入包 + * Blade依赖注入包 */ package com.blade.ioc; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/package-info.java b/blade-core/src/main/java/com/blade/package-info.java index 262b7b19a..a81c553be 100644 --- a/blade-core/src/main/java/com/blade/package-info.java +++ b/blade-core/src/main/java/com/blade/package-info.java @@ -1,4 +1,4 @@ /** - * blade + * Blade */ package com.blade; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/plugin/package-info.java b/blade-core/src/main/java/com/blade/plugin/package-info.java index 974e945e6..39b8ea2e0 100644 --- a/blade-core/src/main/java/com/blade/plugin/package-info.java +++ b/blade-core/src/main/java/com/blade/plugin/package-info.java @@ -1,4 +1,4 @@ /** - * blade插件包 + * 插件包 */ package com.blade.plugin; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/render/package-info.java b/blade-core/src/main/java/com/blade/render/package-info.java index 82911835d..41a8203db 100644 --- a/blade-core/src/main/java/com/blade/render/package-info.java +++ b/blade-core/src/main/java/com/blade/render/package-info.java @@ -1,4 +1,4 @@ /** - * blade视图渲染 + * 视图渲染包,包含JSP、JetbrickTemplate、Beetl等 */ package com.blade.render; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/package-info.java b/blade-core/src/main/java/com/blade/route/package-info.java index 8c19d51f1..90a5f2e61 100644 --- a/blade-core/src/main/java/com/blade/route/package-info.java +++ b/blade-core/src/main/java/com/blade/route/package-info.java @@ -1,4 +1,4 @@ /** - * blade路由实现 + * 路由以及实现 */ package com.blade.route; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/servlet/package-info.java b/blade-core/src/main/java/com/blade/servlet/package-info.java index b92f99871..7c6887306 100644 --- a/blade-core/src/main/java/com/blade/servlet/package-info.java +++ b/blade-core/src/main/java/com/blade/servlet/package-info.java @@ -1,4 +1,4 @@ /** - * blade处理请求和响应 + * Servlet封装 */ package com.blade.servlet; \ No newline at end of file From de4f46b3f4c7aa62db7709fdd13c81228bdb25f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5?= Date: Wed, 28 Oct 2015 22:33:38 +0800 Subject: [PATCH 213/545] Update README.md --- README.md | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a416b8625..4666a728e 100644 --- a/README.md +++ b/README.md @@ -64,12 +64,26 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex [update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) -## licenses - -Blade Framework based on the [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) - ## Contact - Blog:[https://biezhi.me](https://biezhi.me) - Mail: biezhi.me#gmail.com - QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) + +## licenses + +``` +Copyright 2015 biezhi + +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. +``` From 0b08c9aad415daebf77c58b2292163c1d712503a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5?= Date: Wed, 28 Oct 2015 22:34:14 +0800 Subject: [PATCH 214/545] Update README_CN.md --- README_CN.md | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/README_CN.md b/README_CN.md index 2d38f137c..d6d45d862 100644 --- a/README_CN.md +++ b/README_CN.md @@ -64,12 +64,26 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 [更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) -## 开源协议 - -Blade框架基于 [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) - ## 联系我 - Blog:[https://biezhi.me](https://biezhi.me) - Mail: biezhi.me#gmail.com - Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) + +## 开源协议 + +``` +Copyright 2015 biezhi + +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. +``` From 7686941572cc18f21da2030aa982b30bb7c745a5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 09:48:21 +0800 Subject: [PATCH 215/545] update readme --- README.md | 2 +- README_CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4666a728e..5d6f9c0bd 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ public class App { blade.get("/", (request, response) -> { response.html("

Hello blade!

"); }); - blade.app(App.class).listen(9001).start(); + blade.listen(9001).start(); } } ``` diff --git a/README_CN.md b/README_CN.md index d6d45d862..7cf7ecc32 100644 --- a/README_CN.md +++ b/README_CN.md @@ -39,7 +39,7 @@ public class App { blade.get("/", (request, response) -> { response.html("

Hello blade!

"); }); - blade.app(App.class).listen(9001).start(); + blade.listen(9001).start(); } } ``` From 3a749985d1aaabe9c3f8c943b8af689db276dc28 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 11:21:17 +0800 Subject: [PATCH 216/545] add controller loader cache --- ...ader.java => AbstractFileRouteLoader.java} | 78 ++++++++++++------- .../loader/ClassPathControllerLoader.java | 24 +++++- ...sLoader.java => ClassPathRouteLoader.java} | 19 +++-- .../com/blade/loader/ControllerLoader.java | 9 +++ ...Loader.java => FileSystemRouteLoader.java} | 17 +++- .../{RoutesLoader.java => RouteLoader.java} | 11 ++- 6 files changed, 116 insertions(+), 42 deletions(-) rename blade-core/src/main/java/com/blade/loader/{AbstractFileRoutesLoader.java => AbstractFileRouteLoader.java} (78%) rename blade-core/src/main/java/com/blade/loader/{ClassPathRoutesLoader.java => ClassPathRouteLoader.java} (62%) rename blade-core/src/main/java/com/blade/loader/{FileSystemRoutesLoader.java => FileSystemRouteLoader.java} (55%) rename blade-core/src/main/java/com/blade/loader/{RoutesLoader.java => RouteLoader.java} (56%) diff --git a/blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java similarity index 78% rename from blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java rename to blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java index 2e243d750..835d5ce12 100644 --- a/blade-core/src/main/java/com/blade/loader/AbstractFileRoutesLoader.java +++ b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.Reader; import java.lang.reflect.Method; import java.text.ParseException; import java.util.ArrayList; @@ -17,51 +16,65 @@ import com.blade.route.Route; import com.blade.route.RoutesException; -public abstract class AbstractFileRoutesLoader implements RoutesLoader { +import blade.kit.IOKit; + +/** + *

+ * 抽象加载器实现 + *

+ * + * @author biezhi + * @since 1.0 + */ +public abstract class AbstractFileRouteLoader implements RouteLoader { private ControllerLoader controllerLoader = new ClassPathControllerLoader(); + protected abstract InputStream getInputStream() throws Exception; + @Override public List load() throws ParseException, RoutesException { InputStream inputStream = null; try { inputStream = getInputStream(); } catch (Exception e) { - throw new RoutesException("Problem loading the routes.config file: " + e.getMessage(), e); + throw new RoutesException("Loading the route config file error: " + e.getMessage(), e); } - try { return load(inputStream); } catch (IOException e) { - throw new RoutesException("Problem loading the routes.config file: " + e.getMessage(), e); + throw new RoutesException("Loading the route config file error: " + e.getMessage(), e); } } + /** + * 加载路由 + * + * @param inputStream 路由文件流 + * @return 返回路由列表 + * @throws ParseException 解析异常 + * @throws IOException IO异常 + */ private List load(InputStream inputStream) throws ParseException, IOException { - int line = 0; // reset line positioning - List routes = new ArrayList(); // this is what we will fill and return - + int line = 0; + List routes = new ArrayList(); BufferedReader in = null; try { in = new BufferedReader(new InputStreamReader(inputStream)); - String input; while ( (input = in.readLine()) != null ) { line++; input = input.trim(); - // only parse line if it is not empty and not a comment if (!input.equals("") && !input.startsWith("#")) { Route route = parse(input, line); routes.add(route); } } - } finally { - closeResource(in); + IOKit.closeQuietly(in); } - return routes; } @@ -71,16 +84,16 @@ private Route parse(String input, int line) throws ParseException { throw new ParseException("Unrecognized format", line); } - // retrieve and validate the three arguments + // 验证HTTP请求方 String httpMethod = validateHttpMethod( st.nextToken().trim(), line ); + String path = validatePath( st.nextToken().trim(), line ); String controllerAndMethod = validateControllerAndMethod( st.nextToken().trim(), line ); - // retrieve controller name int hashPos = controllerAndMethod.indexOf('#'); String controllerName = controllerAndMethod.substring(0, hashPos); - // retrieve controller method + // 获取控制器方法 String controllerMethod = controllerAndMethod.substring(hashPos + 1); return buildRoute(httpMethod, path, controllerName, controllerMethod); @@ -91,10 +104,8 @@ private String validateHttpMethod(String httpMethod, int line) throws ParseExcep !httpMethod.equalsIgnoreCase("POST") && !httpMethod.equalsIgnoreCase("PUT") && !httpMethod.equalsIgnoreCase("DELETE")) { - throw new ParseException("Unrecognized HTTP method: " + httpMethod, line); } - return httpMethod; } @@ -102,7 +113,7 @@ private String validatePath(String path, int line) throws ParseException { if (!path.startsWith("/")) { throw new ParseException("Path must start with '/'", line); } - + boolean openedKey = false; for (int i=0; i < path.length(); i++) { @@ -144,6 +155,14 @@ private boolean isValidCharForPath(char c, boolean openedKey) { return true; } + /** + * 验证控制器方法 + * + * @param beanAndMethod 控制器和方法,使用#隔开 + * @param line 所在行数 + * @return 返回验证后的字符串,异常则抛出 + * @throws ParseException + */ private String validateControllerAndMethod(String beanAndMethod, int line) throws ParseException { int hashPos = beanAndMethod.indexOf('#'); if (hashPos == -1) { @@ -153,6 +172,16 @@ private String validateControllerAndMethod(String beanAndMethod, int line) throw return beanAndMethod; } + /** + * 构建一个路由对象 + * + * @param httpMethod 请求方法 + * @param path 路由路径 + * @param controllerName 控制器名称 + * @param methodName 执行的方法名称 + * @return 返回路由对象 + * @throws RoutesException + */ private Route buildRoute(String httpMethod, String path, String controllerName, String methodName) throws RoutesException { Object controller = controllerLoader.load(controllerName); Method method = getMethod(controller, methodName); @@ -168,17 +197,6 @@ private Method getMethod(Object controller, String methodName) throws RoutesExce } } - private void closeResource(Reader reader) { - if (reader != null) { - try { - reader.close(); - } catch (Exception e) { - } - } - } - - protected abstract InputStream getInputStream() throws Exception; - public void setBasePackage(String basePackage) { this.controllerLoader = new ClassPathControllerLoader(basePackage); } diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java index 725dc4ca9..9c78b0e8f 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java @@ -1,13 +1,27 @@ package com.blade.loader; +import com.blade.ioc.Container; +import com.blade.ioc.SampleContainer; +import com.blade.ioc.Scope; import com.blade.route.RoutesException; +/** + * + *

+ * ClassPath控制器加载器 + *

+ * + * @author biezhi + * @since 1.0 + */ public class ClassPathControllerLoader implements ControllerLoader { private String basePackage; private ClassLoader classLoader = ClassPathControllerLoader.class.getClassLoader(); + private Container container = SampleContainer.single(); + public ClassPathControllerLoader() { this(""); } @@ -27,9 +41,15 @@ public Object load(String controllerName) throws RoutesException { String className = basePackage + controllerName; try { - // load the controller class and instantiate it + // 加载控制器实例 Class controllerClass = classLoader.loadClass(className); - return controllerClass.newInstance(); + + Object controller = container.getBean(controllerClass, Scope.SINGLE); + if(null == controller){ + controller = controllerClass.newInstance(); + container.registBean(controller); + } + return controller; } catch (Exception e) { throw new RoutesException(e); } diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathRoutesLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathRouteLoader.java similarity index 62% rename from blade-core/src/main/java/com/blade/loader/ClassPathRoutesLoader.java rename to blade-core/src/main/java/com/blade/loader/ClassPathRouteLoader.java index f5393533a..5cf2c9d48 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathRoutesLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ClassPathRouteLoader.java @@ -4,24 +4,33 @@ import java.io.FileInputStream; import java.io.InputStream; -public class ClassPathRoutesLoader extends AbstractFileRoutesLoader { +/** + * + *

+ * 基于ClassPath实现的路由加载器 + *

+ * + * @author biezhi + * @since 1.0 + */ +public class ClassPathRouteLoader extends AbstractFileRouteLoader { private File file; private InputStream inputStream; - public ClassPathRoutesLoader() { + public ClassPathRouteLoader() { } - public ClassPathRoutesLoader(String filePath) { + public ClassPathRouteLoader(String filePath) { this(new File(filePath)); } - public ClassPathRoutesLoader(File file) { + public ClassPathRouteLoader(File file) { this.file = file; } - public ClassPathRoutesLoader(InputStream inputStream) { + public ClassPathRouteLoader(InputStream inputStream) { this.inputStream = inputStream; } diff --git a/blade-core/src/main/java/com/blade/loader/ControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ControllerLoader.java index 31e9bc106..07a3014a7 100644 --- a/blade-core/src/main/java/com/blade/loader/ControllerLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ControllerLoader.java @@ -2,6 +2,15 @@ import com.blade.route.RoutesException; +/** + * + *

+ * 控制器加载接口 + *

+ * + * @author biezhi + * @since 1.0 + */ public interface ControllerLoader { Object load(String controllerName) throws RoutesException; diff --git a/blade-core/src/main/java/com/blade/loader/FileSystemRoutesLoader.java b/blade-core/src/main/java/com/blade/loader/FileSystemRouteLoader.java similarity index 55% rename from blade-core/src/main/java/com/blade/loader/FileSystemRoutesLoader.java rename to blade-core/src/main/java/com/blade/loader/FileSystemRouteLoader.java index f1a459787..152447b87 100644 --- a/blade-core/src/main/java/com/blade/loader/FileSystemRoutesLoader.java +++ b/blade-core/src/main/java/com/blade/loader/FileSystemRouteLoader.java @@ -4,18 +4,27 @@ import java.io.FileInputStream; import java.io.InputStream; -public class FileSystemRoutesLoader extends AbstractFileRoutesLoader { +/** + * + *

+ * 基于文件系统实现的路由加载器 + *

+ * + * @author biezhi + * @since 1.0 + */ +public class FileSystemRouteLoader extends AbstractFileRouteLoader { private File file; - public FileSystemRoutesLoader() { + public FileSystemRouteLoader() { } - public FileSystemRoutesLoader(String filePath) { + public FileSystemRouteLoader(String filePath) { this(new File(filePath)); } - public FileSystemRoutesLoader(File file) { + public FileSystemRouteLoader(File file) { this.file = file; } diff --git a/blade-core/src/main/java/com/blade/loader/RoutesLoader.java b/blade-core/src/main/java/com/blade/loader/RouteLoader.java similarity index 56% rename from blade-core/src/main/java/com/blade/loader/RoutesLoader.java rename to blade-core/src/main/java/com/blade/loader/RouteLoader.java index a9269ee70..285f95977 100644 --- a/blade-core/src/main/java/com/blade/loader/RoutesLoader.java +++ b/blade-core/src/main/java/com/blade/loader/RouteLoader.java @@ -6,7 +6,16 @@ import com.blade.route.Route; import com.blade.route.RoutesException; -public interface RoutesLoader { +/** + * + *

+ * 路由加载器 + *

+ * + * @author biezhi + * @since 1.0 + */ +public interface RouteLoader { List load() throws ParseException, RoutesException; From 63bf80a2ce77fffc3d837d9baaa9eb0839f14df2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 11:21:28 +0800 Subject: [PATCH 217/545] add comment --- .../main/java/com/blade/ActionHandler.java | 41 +-- blade-core/src/main/java/com/blade/Blade.java | 236 +++++++++++------- .../src/main/java/com/blade/Bootstrap.java | 3 + .../src/main/java/com/blade/CoreFilter.java | 8 + .../main/java/com/blade/IocApplication.java | 15 +- .../com/blade/context/BladeWebContext.java | 8 + .../java/com/blade/http/HttpException.java | 70 ++++-- .../main/java/com/blade/http/HttpMethod.java | 2 + .../main/java/com/blade/http/HttpStatus.java | 3 + .../src/main/java/com/blade/http/Path.java | 5 +- .../src/main/java/com/blade/http/Request.java | 24 ++ .../main/java/com/blade/http/Response.java | 24 ++ 12 files changed, 305 insertions(+), 134 deletions(-) diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java index cbfee00d2..d96d14045 100644 --- a/blade-core/src/main/java/com/blade/ActionHandler.java +++ b/blade-core/src/main/java/com/blade/ActionHandler.java @@ -15,7 +15,6 @@ */ package com.blade; -import java.io.IOException; import java.lang.reflect.Method; import java.util.List; @@ -55,10 +54,19 @@ public class ActionHandler { private static final Logger LOGGER = Logger.getLogger(ActionHandler.class); + /** + * blade对象 + */ private Blade blade; + /** + * 路由管理器 + */ private Router router; + /** + * 路由匹配器 + */ private SampleRouteMatcher sampleRouteMatcher; /** @@ -87,9 +95,10 @@ public ActionHandler(ServletContext context, Blade blade){ /** * 处理请求 - * @param httpRequest - * @param httpResponse - * @return + * + * @param httpRequest HttpServletRequest对象 + * @param httpResponse HttpServletResponse对象 + * @return 返回true,处理完毕;返回false,由filter继续处理 */ public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ @@ -175,11 +184,11 @@ public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpRe /** * 404视图渲染 - * @param response - * @param uri - * @throws IOException + * + * @param response 响应对象 + * @param uri 404的URI */ - private void render404(Response response, String uri) throws IOException{ + private void render404(Response response, String uri) { String view404 = blade.view404(); if(StringKit.isNotBlank(view404)){ ModelAndView modelAndView = new ModelAndView(view404); @@ -192,10 +201,11 @@ private void render404(Response response, String uri) throws IOException{ } /** - * 执行拦截器方法 - * @param request - * @param response - * @param interceptors + * 执行拦截器的方法 + * + * @param request 请求对象 + * @param response 响应对象 + * @param interceptors 要执行的拦截器列表 */ private void invokeInterceptor(Request request, Response response, List interceptors) { for(Route route : interceptors){ @@ -205,6 +215,7 @@ private void invokeInterceptor(Request request, Response response, List i /** * 实际的路由方法执行 + * * @param request 请求对象 * @param response 响应对象 * @param route 路由对象 @@ -254,6 +265,7 @@ private Object[] getArgs(Request request, Response response, Class[] params){ /** * 执行路由方法 + * * @param object 方法的实例,即该方法所在类的对象 * @param method 要执行的method * @param request Request对象,作为参数注入 @@ -273,8 +285,9 @@ private Object executeMethod(Object object, Method method, Request request, Resp /** * 要过滤掉的目录 - * @param uri - * @return + * + * @param uri URI表示当前路径,在静态目录中进行过滤 + * @return 返回false,过滤成功;返回true,不过滤 */ private boolean filterStaticFolder(String uri){ int len = blade.staticFolder().length; diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 9bd8e5091..846606a37 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -24,7 +24,7 @@ import com.blade.http.HttpMethod; import com.blade.ioc.Container; import com.blade.ioc.SampleContainer; -import com.blade.loader.ClassPathRoutesLoader; +import com.blade.loader.ClassPathRouteLoader; import com.blade.loader.Config; import com.blade.loader.Configurator; import com.blade.plugin.Plugin; @@ -98,23 +98,41 @@ public void init() { */ private static final int DEFAULT_PORT = 9000; + /** + * blade启动端口,jetty服务 + */ private int port = DEFAULT_PORT; private Blade() { } + /** + * @return 单例方式返回Blade对象 + */ public static Blade me(){ return ME; } + /** + * 设置App是否已经初始化 + * @param isInit 是否初始化 + */ public void setInit(boolean isInit) { this.isInit = isInit; } + /** + * 创建一个Jetty服务 + * @param port 服务端口 + * @return 返回Blade封装的Server + */ public Server createServer(int port){ return new Server(port); } + /** + * @return 返回路由管理对象 + */ public Router router() { return router; } @@ -237,27 +255,68 @@ public Blade ioc(String...packages){ return this; } + /** + * 添加一个路由 + * + * @param path 路由路径 + * @param target 路由执行的目标对象 + * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) + * @return 返回Blade单例实例 + */ public Blade route(String path, Object target, String method){ router.route(path, target, method); return this; } + /** + * 添加一个路由 + * + * @param path 路由路径 + * @param target 路由执行的目标对象 + * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) + * @return 返回Blade单例实例 + */ + @Deprecated public Blade addRoute(String path, Object target, String method){ return route(path, target, method); } + /** + * 添加一个路由 + * + * @param path 路由路径 + * @param target 路由执行的目标对象 + * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) + * @param httpMethod + * @return 返回Blade单例实例 + */ + @Deprecated public Blade addRoute(String path, Object target, String method, HttpMethod httpMethod){ return route(path, target, method, httpMethod); } /** - * 注册一个函数式的路由
- *

- * 方法上指定请求类型,如:post:signin - *

+ * 添加一个路由 + * + * @param path 路由路径 + * @param target 路由执行的目标对象 + * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) + * @param httpMethod + * @return 返回Blade单例实例 + */ + public Blade route(String path, Object target, String method, HttpMethod httpMethod){ + router.route(path, target, method, httpMethod); + return this; + } + + /** + * 注册一个函数式的路由 + * 方法上指定请求类型(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) + * * @param path 路由url * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 + * @param method 路由处理方法名称 + * @return Blade 返回Blade单例实例 */ public Blade route(String path, Class clazz, String method){ router.route(path, clazz, method); @@ -266,57 +325,60 @@ public Blade route(String path, Class clazz, String method){ /** * 注册一个函数式的路由 + * * @param path 路由url * @param clazz 路由处理类 * @param methodName 路由处理方法名称 * @param httpMethod 请求类型,GET/POST + * @return Blade 返回Blade单例实例 */ public Blade route(String path, Class clazz, String method, HttpMethod httpMethod){ router.route(path, clazz, method, httpMethod); return this; } - public Blade route(String path, Object target, String method, HttpMethod httpMethod){ - router.route(path, target, method, httpMethod); - return this; - } - /** - * get请求 - * @param path - * @param handler + * 注册一个GET请求的路由 + * + * @param path 路由路径 + * @param handler 执行路由的Handle + * @return 返回Blade单例实例 */ public Blade get(String path, RouteHandler handler){ router.route(path, handler, HttpMethod.GET); return this; } - /** - * post请求 - * @param path - * @param handler + * 注册一个POST请求的路由 + * + * @param path 路由路径 + * @param handler 执行路由的Handle + * @return 返回Blade单例实例 */ public Blade post(String path, RouteHandler handler){ router.route(path, handler, HttpMethod.POST); return this; } - /** - * delete请求 - * @param path - * @param handler + * 注册一个DELETE请求的路由 + * + * @param path 路由路径 + * @param handler 执行路由的Handle + * @return 返回Blade单例实例 */ public Blade delete(String path, RouteHandler handler){ router.route(path, handler, HttpMethod.DELETE); return this; } - /** - * put请求 - * @param paths + * 注册一个PUT请求的路由 + * + * @param path 路由路径 + * @param handler 执行路由的Handle + * @return 返回Blade单例实例 */ public Blade put(String path, RouteHandler handler){ router.route(path, handler, HttpMethod.PUT); @@ -324,69 +386,35 @@ public Blade put(String path, RouteHandler handler){ } /** - * patch请求 - * @param path - * @param handler - */ - public Blade patch(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.PATCH); - return this; - } - - /** - * head请求 - * @param path - * @param handler - */ - public Blade head(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.HEAD); - return this; - } - - /** - * trace请求 - * @param path - * @param handler - */ - public Blade trace(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.TRACE); - return this; - } - - /** - * options请求 - * @param path - * @param handler - */ - public Blade options(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.OPTIONS); - return this; - } - - /** - * connect请求 - * @param path - * @param handler + * 注册一个任意请求的路由 + * + * @param path 路由路径 + * @param handler 执行路由的Handle + * @return 返回Blade单例实例 */ - public Blade connect(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.CONNECT); + public Blade all(String path, RouteHandler handler){ + router.route(path, handler, HttpMethod.ALL); return this; } /** - * 任意请求 - * @param path - * @param handler + * 注册一个任意请求的路由 + * + * @param path 路由路径 + * @param handler 执行路由的Handle + * @return 返回Blade单例实例 */ - public Blade all(String path, RouteHandler handler){ + public Blade any(String path, RouteHandler handler){ router.route(path, handler, HttpMethod.ALL); return this; } /** - * 拦截器before请求 - * @param path - * @param routeHandler + * 注册一个前置拦截器请求的路由 + * + * @param path 路由路径 + * @param handler 执行路由的Handle + * @return 返回Blade单例实例 */ public Blade before(String path, RouteHandler handler){ router.route(path, handler, HttpMethod.BEFORE); @@ -394,9 +422,11 @@ public Blade before(String path, RouteHandler handler){ } /** - * 拦截器after请求 - * @param path - * @param routeHandler + * 注册一个后置拦截器请求的路由 + * + * @param path 路由路径 + * @param handler 执行路由的Handle + * @return 返回Blade单例实例 */ public Blade after(String path, RouteHandler handler){ router.route(path, handler, HttpMethod.AFTER); @@ -407,6 +437,7 @@ public Blade after(String path, RouteHandler handler){ * 设置渲染引擎,默认是JSP引擎 * * @param render 渲染引擎对象 + * @return 返回Blade单例实例 */ public Blade viewEngin(Render render) { this.render = render; @@ -417,6 +448,7 @@ public Blade viewEngin(Render render) { * 设置默认视图前缀,默认为WEB_ROOT/WEB-INF目录 * * @param prefix 视图路径,如:/WEB-INF/views + * @return 返回Blade单例实例 */ public Blade viewPrefix(final String prefix) { if(null != prefix && prefix.startsWith("/")){ @@ -429,6 +461,7 @@ public Blade viewPrefix(final String prefix) { * 设置视图默认后缀名,默认为.jsp * * @param viewExt 视图后缀,如:.html .vm + * @return 返回Blade单例实例 */ public Blade viewSuffix(final String suffix) { if(null != suffix && suffix.startsWith(".")){ @@ -442,6 +475,7 @@ public Blade viewSuffix(final String suffix) { * * @param viewPath 视图路径,如:/WEB-INF/views * @param viewExt 视图后缀,如:.html .vm + * @return 返回Blade单例实例 */ public Blade view(final String viewPath, final String viewExt) { viewPrefix(viewPath); @@ -452,7 +486,8 @@ public Blade view(final String viewPath, final String viewExt) { /** * 设置框架静态文件所在文件夹 * - * @param folders + * @param folders 要过滤的目录数组,如:"/public,/static,/images" + * @return 返回Blade单例实例 */ public Blade staticFolder(final String ... folders) { config.setStaticFolders(folders); @@ -461,8 +496,9 @@ public Blade staticFolder(final String ... folders) { /** * 设置是否启用XSS防御 - * @param enableXSS - * @return + * + * @param enableXSS 是否启用XSS防御,默认不启用 + * @return 返回Blade单例实例 */ public Blade enableXSS(boolean enableXSS){ config.setEnableXSS(enableXSS); @@ -473,6 +509,7 @@ public Blade enableXSS(boolean enableXSS){ * 动态设置全局初始化类 * * @param bootstrap 全局初始化bladeApplication + * @return 返回Blade单例实例 */ public Blade app(Bootstrap bootstrap){ this.bootstrap = bootstrap; @@ -483,6 +520,7 @@ public Blade app(Bootstrap bootstrap){ * 动态设置全局初始化类 * * @param bootstrap 全局初始化bladeApplication + * @return 返回Blade单例实例 */ public Blade app(Class bootstrap){ this.bootstrap = (Bootstrap) ReflectKit.newInstance(bootstrap); @@ -493,6 +531,7 @@ public Blade app(Class bootstrap){ * 设置404视图页面 * * @param view404 404视图页面 + * @return 返回Blade单例实例 */ public Blade setView404(final String view404){ config.setView404(view404); @@ -503,6 +542,7 @@ public Blade setView404(final String view404){ * 设置500视图页面 * * @param view500 500视图页面 + * @return 返回Blade单例实例 */ public Blade setView500(final String view500){ config.setView500(view500); @@ -513,6 +553,7 @@ public Blade setView500(final String view500){ * 设置web根目录 * * @param webRoot web根目录物理路径 + * @return 返回Blade单例实例 */ public Blade webRoot(final String webRoot){ config.setWebRoot(webRoot); @@ -521,7 +562,9 @@ public Blade webRoot(final String webRoot){ /** * 设置系统是否以debug方式运行 + * * @param isdebug true:是,默认true;false:否 + * @return 返回Blade单例实例 */ public Blade debug(boolean isdebug){ config.setDebug(isdebug); @@ -529,9 +572,10 @@ public Blade debug(boolean isdebug){ } /** - * 设置监听端口 - * @param port - * @return + * 设置Jetty服务监听端口 + * + * @param port 端口,默认9000 + * @return 返回Blade单例实例 */ public Blade listen(int port){ this.port = port; @@ -539,8 +583,10 @@ public Blade listen(int port){ } /** - * 设置启动上下文 - * @param contextPath + * 设置jetty启动上下文 + * + * @param contextPath 设置上下文contextPath,默认/ + * @return 返回Blade单例实例 */ public void start(String contextPath) { try { @@ -552,15 +598,14 @@ public void start(String contextPath) { } /** - * 启动服务 + * 启动Jetty服务 */ public void start() { this.start("/"); } /** - * 返回系统配制 - * @return + * @return 返回系统配置对象 */ public Config config(){ return config; @@ -683,10 +728,17 @@ public T plugin(Class pluginClazz){ return (T) object; } + /** + * 注册一个配置文件的路由 + * + * @param basePackage 控制器包名 + * @param conf 配置文件路径,配置文件必须在classpath下 + * @return 返回Blade单例实例 + */ public Blade routeConf(String basePackage, String conf) { try { InputStream ins = Blade.class.getResourceAsStream("/" + conf); - ClassPathRoutesLoader routesLoader = new ClassPathRoutesLoader(ins); + ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); routesLoader.setBasePackage(basePackage); List routes = routesLoader.load(); router.addRoutes(routes); diff --git a/blade-core/src/main/java/com/blade/Bootstrap.java b/blade-core/src/main/java/com/blade/Bootstrap.java index a23dd96d9..7db9008b9 100644 --- a/blade-core/src/main/java/com/blade/Bootstrap.java +++ b/blade-core/src/main/java/com/blade/Bootstrap.java @@ -28,6 +28,9 @@ public abstract class Bootstrap { */ public abstract void init(); + /** + * 初始化配置后执行 + */ public void contextInitialized(){ // } diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 531e3e9d7..6658c3f18 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -49,8 +49,14 @@ public class CoreFilter implements Filter { */ private static final String BOOSTRAP_CLASS = "bootstrapClass"; + /** + * Blade单例对象 + */ private Blade blade; + /** + * 执行所有请求的处理器 + */ private ActionHandler actionHandler; @Override @@ -73,6 +79,7 @@ public void init(FilterConfig filterConfig) throws ServletException { // 构建路由 new RouteBuilder(blade).building(); + // 初始化IOC IocApplication.init(blade); bootstrap.contextInitialized(); @@ -80,6 +87,7 @@ public void init(FilterConfig filterConfig) throws ServletException { blade.setInit(true); actionHandler = new ActionHandler(filterConfig.getServletContext(), blade); + LOGGER.info("blade init complete!"); } } catch (Exception e) { diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index 3372b0cf0..954f2317b 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -45,16 +45,23 @@ public final class IocApplication { /** * IOC容器,单例获取默认的容器实现 */ - static final Container container = SampleContainer.single(); + private static final Container container = SampleContainer.single(); /** * 类读取对象,加载class */ - static final ClassReader classReader = new ClassPathClassReader(); - - static final List PLUGINS = CollectionKit.newArrayList(); + private static final ClassReader classReader = new ClassPathClassReader(); + /** + * 插件列表 + */ + private static final List PLUGINS = CollectionKit.newArrayList(); + /** + * 初始化IOC + * + * @param blade Blade实例 + */ public static void init(Blade blade){ // 初始化全局配置类 diff --git a/blade-core/src/main/java/com/blade/context/BladeWebContext.java b/blade-core/src/main/java/com/blade/context/BladeWebContext.java index cab37e482..b238e52b9 100644 --- a/blade-core/src/main/java/com/blade/context/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/context/BladeWebContext.java @@ -38,7 +38,15 @@ public final class BladeWebContext { * ServletContext对象,在应用初始化时创建 */ private ServletContext context; + + /** + * Request对象 + */ private Request request; + + /** + * Response对象 + */ private Response response; private BladeWebContext(){} diff --git a/blade-core/src/main/java/com/blade/http/HttpException.java b/blade-core/src/main/java/com/blade/http/HttpException.java index 74f0c04aa..300efe9af 100644 --- a/blade-core/src/main/java/com/blade/http/HttpException.java +++ b/blade-core/src/main/java/com/blade/http/HttpException.java @@ -1,23 +1,47 @@ -package com.blade.http; - -public class HttpException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - public HttpException() { - super(); - } - - public HttpException(String message, Throwable throwable) { - super(message, throwable); - } - - public HttpException(String message) { - super(message); - } - - public HttpException(Throwable throwable) { - super(throwable); - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.http; + +/** + * + *

+ * Http异常 + *

+ * + * @author biezhi + * @since 1.0 + */ +public class HttpException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public HttpException() { + super(); + } + + public HttpException(String message, Throwable throwable) { + super(message, throwable); + } + + public HttpException(String message) { + super(message); + } + + public HttpException(Throwable throwable) { + super(throwable); + } + +} diff --git a/blade-core/src/main/java/com/blade/http/HttpMethod.java b/blade-core/src/main/java/com/blade/http/HttpMethod.java index 7d2d6596a..9cdca8dbf 100644 --- a/blade-core/src/main/java/com/blade/http/HttpMethod.java +++ b/blade-core/src/main/java/com/blade/http/HttpMethod.java @@ -16,7 +16,9 @@ package com.blade.http; /** + *

* HTTP请求方法 + *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/http/HttpStatus.java b/blade-core/src/main/java/com/blade/http/HttpStatus.java index 8f3b0b8d3..e0507ea7a 100644 --- a/blade-core/src/main/java/com/blade/http/HttpStatus.java +++ b/blade-core/src/main/java/com/blade/http/HttpStatus.java @@ -16,7 +16,10 @@ package com.blade.http; /** + * + *

* HTTP状态码 + *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/http/Path.java b/blade-core/src/main/java/com/blade/http/Path.java index 25b73ff27..d60c984b9 100644 --- a/blade-core/src/main/java/com/blade/http/Path.java +++ b/blade-core/src/main/java/com/blade/http/Path.java @@ -25,7 +25,10 @@ import blade.kit.StringKit; /** - * PATH处理 + * + *

+ * 路径、URL处理 + *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/http/Request.java b/blade-core/src/main/java/com/blade/http/Request.java index 2e00c01c7..76118cdf9 100644 --- a/blade-core/src/main/java/com/blade/http/Request.java +++ b/blade-core/src/main/java/com/blade/http/Request.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.http; import java.io.InputStream; @@ -12,6 +27,15 @@ import com.blade.servlet.Session; import com.blade.servlet.multipart.FileItem; +/** + * + *

+ * HTTP请求对象 + *

+ * + * @author biezhi + * @since 1.0 + */ public interface Request { HttpServletRequest raw(); diff --git a/blade-core/src/main/java/com/blade/http/Response.java b/blade-core/src/main/java/com/blade/http/Response.java index fd07675dd..5edd40256 100644 --- a/blade-core/src/main/java/com/blade/http/Response.java +++ b/blade-core/src/main/java/com/blade/http/Response.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.http; import java.io.IOException; @@ -9,6 +24,15 @@ import com.blade.render.ModelAndView; +/** + * + *

+ * HTTP响应对象 + *

+ * + * @author biezhi + * @since 1.0 + */ public interface Response { HttpServletResponse raw(); From d8ab1f940add69fe0b42267973ba85eca0600d20 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 11:21:55 +0800 Subject: [PATCH 218/545] add package-info --- blade-core/src/main/java/com/blade/context/package-info.java | 4 ++++ blade-core/src/main/java/com/blade/http/package-info.java | 4 ++++ blade-core/src/main/java/com/blade/loader/package-info.java | 4 ++++ blade-core/src/main/java/com/blade/server/package-info.java | 4 ++++ .../main/java/com/blade/servlet/multipart/package-info.java | 4 ++++ blade-core/src/main/java/com/blade/verify/package-info.java | 4 ++++ 6 files changed, 24 insertions(+) create mode 100644 blade-core/src/main/java/com/blade/context/package-info.java create mode 100644 blade-core/src/main/java/com/blade/http/package-info.java create mode 100644 blade-core/src/main/java/com/blade/loader/package-info.java create mode 100644 blade-core/src/main/java/com/blade/server/package-info.java create mode 100644 blade-core/src/main/java/com/blade/servlet/multipart/package-info.java create mode 100644 blade-core/src/main/java/com/blade/verify/package-info.java diff --git a/blade-core/src/main/java/com/blade/context/package-info.java b/blade-core/src/main/java/com/blade/context/package-info.java new file mode 100644 index 000000000..e5f2d1b68 --- /dev/null +++ b/blade-core/src/main/java/com/blade/context/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade上下文 + */ +package com.blade.context; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/http/package-info.java b/blade-core/src/main/java/com/blade/http/package-info.java new file mode 100644 index 000000000..3ebeb38eb --- /dev/null +++ b/blade-core/src/main/java/com/blade/http/package-info.java @@ -0,0 +1,4 @@ +/** + * Request、Response接口 + */ +package com.blade.http; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/loader/package-info.java b/blade-core/src/main/java/com/blade/loader/package-info.java new file mode 100644 index 000000000..98165b833 --- /dev/null +++ b/blade-core/src/main/java/com/blade/loader/package-info.java @@ -0,0 +1,4 @@ +/** + * 配置加载包 + */ +package com.blade.loader; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/server/package-info.java b/blade-core/src/main/java/com/blade/server/package-info.java new file mode 100644 index 000000000..0e8ea64f8 --- /dev/null +++ b/blade-core/src/main/java/com/blade/server/package-info.java @@ -0,0 +1,4 @@ +/** + * Jetty服务包 + */ +package com.blade.server; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/package-info.java b/blade-core/src/main/java/com/blade/servlet/multipart/package-info.java new file mode 100644 index 000000000..127a4c5bb --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/multipart/package-info.java @@ -0,0 +1,4 @@ +/** + * Multipart处理 + */ +package com.blade.servlet.multipart; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/verify/package-info.java b/blade-core/src/main/java/com/blade/verify/package-info.java new file mode 100644 index 000000000..669c278ce --- /dev/null +++ b/blade-core/src/main/java/com/blade/verify/package-info.java @@ -0,0 +1,4 @@ +/** + * 认证、安全包 + */ +package com.blade.verify; \ No newline at end of file From 9f411cbd474be44e6c9d95c1685c1d59c49b86f8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 11:31:19 +0800 Subject: [PATCH 219/545] add and update comment --- blade-core/src/main/java/com/blade/Blade.java | 4 +- .../blade/loader/AbstractFileRouteLoader.java | 16 +++---- .../loader/ClassPathControllerLoader.java | 6 +-- .../com/blade/loader/ControllerLoader.java | 4 +- .../java/com/blade/loader/RouteLoader.java | 4 +- .../java/com/blade/render/BeetlRender.java | 28 +++++++++++- .../java/com/blade/render/JetbrickRender.java | 25 ++++++++++- .../main/java/com/blade/render/JspRender.java | 3 ++ .../java/com/blade/render/ModelAndView.java | 3 ++ .../main/java/com/blade/render/Render.java | 21 ++++++++- .../com/blade/render/RenderException.java | 25 +++++++++++ .../java/com/blade/render/VelocityRender.java | 26 ++++++++++- .../src/main/java/com/blade/route/Route.java | 36 ++++++++++++++++ .../java/com/blade/route/RouteBuilder.java | 5 +++ .../java/com/blade/route/RouteException.java | 43 +++++++++++++++++++ .../java/com/blade/route/RouteHandler.java | 21 ++++++++- .../src/main/java/com/blade/route/Router.java | 18 ++++++++ .../java/com/blade/route/RoutesException.java | 24 ----------- .../com/blade/route/SampleRouteMatcher.java | 24 +++++++++++ .../main/java/com/blade/server/Server.java | 18 ++++++++ .../com/blade/servlet/ServletRequest.java | 18 ++++++++ .../com/blade/servlet/ServletResponse.java | 18 ++++++++ .../main/java/com/blade/servlet/Session.java | 3 ++ .../com/blade/servlet/multipart/FileItem.java | 21 ++++++++- .../blade/servlet/multipart/Multipart.java | 24 +++++++++++ .../servlet/multipart/MultipartException.java | 24 +++++++++++ .../servlet/multipart/MultipartHandler.java | 24 +++++++++++ .../java/com/blade/verify/CSRFConfig.java | 21 ++++++++- .../com/blade/verify/CSRFTokenManager.java | 21 ++++++++- 29 files changed, 478 insertions(+), 50 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/route/RouteException.java delete mode 100644 blade-core/src/main/java/com/blade/route/RoutesException.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 846606a37..79109a764 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -33,7 +33,7 @@ import com.blade.route.Route; import com.blade.route.RouteHandler; import com.blade.route.Router; -import com.blade.route.RoutesException; +import com.blade.route.RouteException; import com.blade.server.Server; import blade.kit.IOKit; @@ -742,7 +742,7 @@ public Blade routeConf(String basePackage, String conf) { routesLoader.setBasePackage(basePackage); List routes = routesLoader.load(); router.addRoutes(routes); - } catch (RoutesException e) { + } catch (RouteException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); diff --git a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java index 835d5ce12..49244d88b 100644 --- a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java @@ -14,7 +14,7 @@ import com.blade.http.Request; import com.blade.http.Response; import com.blade.route.Route; -import com.blade.route.RoutesException; +import com.blade.route.RouteException; import blade.kit.IOKit; @@ -33,17 +33,17 @@ public abstract class AbstractFileRouteLoader implements RouteLoader { protected abstract InputStream getInputStream() throws Exception; @Override - public List load() throws ParseException, RoutesException { + public List load() throws ParseException, RouteException { InputStream inputStream = null; try { inputStream = getInputStream(); } catch (Exception e) { - throw new RoutesException("Loading the route config file error: " + e.getMessage(), e); + throw new RouteException("Loading the route config file error: " + e.getMessage(), e); } try { return load(inputStream); } catch (IOException e) { - throw new RoutesException("Loading the route config file error: " + e.getMessage(), e); + throw new RouteException("Loading the route config file error: " + e.getMessage(), e); } } @@ -180,20 +180,20 @@ private String validateControllerAndMethod(String beanAndMethod, int line) throw * @param controllerName 控制器名称 * @param methodName 执行的方法名称 * @return 返回路由对象 - * @throws RoutesException + * @throws RouteException */ - private Route buildRoute(String httpMethod, String path, String controllerName, String methodName) throws RoutesException { + private Route buildRoute(String httpMethod, String path, String controllerName, String methodName) throws RouteException { Object controller = controllerLoader.load(controllerName); Method method = getMethod(controller, methodName); return new Route(HttpMethod.valueOf(httpMethod.toUpperCase()), path, controller, method); } - private Method getMethod(Object controller, String methodName) throws RoutesException { + private Method getMethod(Object controller, String methodName) throws RouteException { try { return controller.getClass().getMethod(methodName, Request.class, Response.class); } catch (Exception e) { - throw new RoutesException(e); + throw new RouteException(e); } } diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java index 9c78b0e8f..48a598f6c 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java @@ -3,7 +3,7 @@ import com.blade.ioc.Container; import com.blade.ioc.SampleContainer; import com.blade.ioc.Scope; -import com.blade.route.RoutesException; +import com.blade.route.RouteException; /** * @@ -37,7 +37,7 @@ public ClassPathControllerLoader(String basePackage) { } @Override - public Object load(String controllerName) throws RoutesException { + public Object load(String controllerName) throws RouteException { String className = basePackage + controllerName; try { @@ -51,7 +51,7 @@ public Object load(String controllerName) throws RoutesException { } return controller; } catch (Exception e) { - throw new RoutesException(e); + throw new RouteException(e); } } diff --git a/blade-core/src/main/java/com/blade/loader/ControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ControllerLoader.java index 07a3014a7..6c92ed277 100644 --- a/blade-core/src/main/java/com/blade/loader/ControllerLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ControllerLoader.java @@ -1,6 +1,6 @@ package com.blade.loader; -import com.blade.route.RoutesException; +import com.blade.route.RouteException; /** * @@ -13,6 +13,6 @@ */ public interface ControllerLoader { - Object load(String controllerName) throws RoutesException; + Object load(String controllerName) throws RouteException; } diff --git a/blade-core/src/main/java/com/blade/loader/RouteLoader.java b/blade-core/src/main/java/com/blade/loader/RouteLoader.java index 285f95977..79b62ba8f 100644 --- a/blade-core/src/main/java/com/blade/loader/RouteLoader.java +++ b/blade-core/src/main/java/com/blade/loader/RouteLoader.java @@ -4,7 +4,7 @@ import java.util.List; import com.blade.route.Route; -import com.blade.route.RoutesException; +import com.blade.route.RouteException; /** * @@ -17,6 +17,6 @@ */ public interface RouteLoader { - List load() throws ParseException, RoutesException; + List load() throws ParseException, RouteException; } diff --git a/blade-core/src/main/java/com/blade/render/BeetlRender.java b/blade-core/src/main/java/com/blade/render/BeetlRender.java index 56054beba..5443d4284 100644 --- a/blade-core/src/main/java/com/blade/render/BeetlRender.java +++ b/blade-core/src/main/java/com/blade/render/BeetlRender.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.render; import java.io.IOException; @@ -19,17 +34,28 @@ import blade.kit.log.Logger; /** + * + *

* Beetl渲染引擎 - * @author biezhi + *

* + * @author biezhi + * @since 1.0 */ public class BeetlRender implements Render { private static final Logger LOGGER = Logger.getLogger(BeetlRender.class); + /** + * Beetl获取模板对象 + */ private GroupTemplate groupTemplate = null; + /** + * Blade对象 + */ private Blade blade; + /** * 默认构造函数 */ diff --git a/blade-core/src/main/java/com/blade/render/JetbrickRender.java b/blade-core/src/main/java/com/blade/render/JetbrickRender.java index 2c3e06350..02258211b 100644 --- a/blade-core/src/main/java/com/blade/render/JetbrickRender.java +++ b/blade-core/src/main/java/com/blade/render/JetbrickRender.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.render; import java.io.IOException; @@ -18,9 +33,13 @@ import jetbrick.template.JetTemplate; /** + * + *

* Velocity渲染引擎 - * @author biezhi + *

* + * @author biezhi + * @since 1.0 */ public class JetbrickRender implements Render { @@ -62,6 +81,7 @@ public void clean(){ /** * 添加一个配置 + * * @param key 配置键 * @param value 配置值 */ @@ -74,6 +94,7 @@ public void put(String key, Object value){ /** * 根据配置文件构造一个JetEngine引擎 + * * @param configLocation * @throws IOException */ @@ -84,6 +105,7 @@ public JetbrickRender(String configLocation) throws IOException { /** * 根据构造一个JetEngine引擎 + * * @param config Properties配置 */ public JetbrickRender(Properties config) { @@ -94,6 +116,7 @@ public JetbrickRender(Properties config) { /** * 手动构造JetEngine引擎 + * * @param jetEngine jetEngine引擎 */ public JetbrickRender(JetEngine jetEngine) { diff --git a/blade-core/src/main/java/com/blade/render/JspRender.java b/blade-core/src/main/java/com/blade/render/JspRender.java index 9ec74af25..9e2ecc767 100644 --- a/blade-core/src/main/java/com/blade/render/JspRender.java +++ b/blade-core/src/main/java/com/blade/render/JspRender.java @@ -29,7 +29,10 @@ import blade.kit.log.Logger; /** + * + *

* JSP渲染引擎,默认的渲染器 + *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/render/ModelAndView.java b/blade-core/src/main/java/com/blade/render/ModelAndView.java index 082940354..2ac98b581 100644 --- a/blade-core/src/main/java/com/blade/render/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/render/ModelAndView.java @@ -20,7 +20,10 @@ import blade.kit.CollectionKit; /** + * + *

* ModelAndView使用模型和视图来渲染 + *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/render/Render.java b/blade-core/src/main/java/com/blade/render/Render.java index 92516174b..c68d0b0fc 100644 --- a/blade-core/src/main/java/com/blade/render/Render.java +++ b/blade-core/src/main/java/com/blade/render/Render.java @@ -1,11 +1,30 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.render; import java.io.Writer; /** + * + *

* 渲染器接口 - * @author biezhi + *

* + * @author biezhi + * @since 1.0 */ public interface Render { diff --git a/blade-core/src/main/java/com/blade/render/RenderException.java b/blade-core/src/main/java/com/blade/render/RenderException.java index 51cb98551..9ff6a4ebf 100644 --- a/blade-core/src/main/java/com/blade/render/RenderException.java +++ b/blade-core/src/main/java/com/blade/render/RenderException.java @@ -1,4 +1,29 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.render; + +/** + * + *

+ * 渲染器异常 + *

+ * + * @author biezhi + * @since 1.0 + */ public class RenderException extends RuntimeException { private static final long serialVersionUID = 1L; diff --git a/blade-core/src/main/java/com/blade/render/VelocityRender.java b/blade-core/src/main/java/com/blade/render/VelocityRender.java index 2d3b9e5ed..71b3652b8 100644 --- a/blade-core/src/main/java/com/blade/render/VelocityRender.java +++ b/blade-core/src/main/java/com/blade/render/VelocityRender.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.render; import java.io.File; @@ -21,9 +36,13 @@ import blade.kit.log.Logger; /** + * + *

* Velocity渲染引擎 - * @author biezhi + *

* + * @author biezhi + * @since 1.0 */ public class VelocityRender implements Render { @@ -48,6 +67,7 @@ public VelocityRender() { /** * 根据配置文件构造一个Velocity引擎 + * * @param propertiesFile * @throws IOException */ @@ -69,6 +89,7 @@ public VelocityRender(String propertiesFile) throws IOException { /** * 根据构造一个Velocity引擎 + * * @param properties */ public VelocityRender(Properties properties) { @@ -78,7 +99,8 @@ public VelocityRender(Properties properties) { /** * 手动构造Velocity引擎 - * @param velocityEngine_ + * + * @param velocityEngine */ public VelocityRender(VelocityEngine velocityEngine) { blade = Blade.me(); diff --git a/blade-core/src/main/java/com/blade/route/Route.java b/blade-core/src/main/java/com/blade/route/Route.java index 14b1f309c..7418addd0 100644 --- a/blade-core/src/main/java/com/blade/route/Route.java +++ b/blade-core/src/main/java/com/blade/route/Route.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; import java.lang.reflect.Method; @@ -5,14 +20,35 @@ import com.blade.http.HttpMethod; import com.blade.http.Path; +/** + * + *

+ * 路由对象 + *

+ * + * @author biezhi + * @since 1.0 + */ public class Route { + /** + * HTTP请求方法 + */ private HttpMethod httpMethod; + /** + * 路由路径 + */ private String path; + /** + * 执行逻辑的目标对象 + */ private Object target; + /** + * 执行逻辑的目标方法 + */ private Method action; public Route() { diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index a95d8b72a..e7350b1cc 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -33,7 +33,10 @@ import blade.kit.resource.ClassReader; /** + * + *

* 路由构造器 + *

* * @author biezhi * @since 1.0 @@ -110,8 +113,10 @@ public void building() { * @param interceptorPackages 要添加的拦截器包 */ private void buildInterceptor(String... interceptorPackages){ + // 扫描所有的Interceptor Set> classes = null; + // 拦截器 for(String packageName : interceptorPackages){ diff --git a/blade-core/src/main/java/com/blade/route/RouteException.java b/blade-core/src/main/java/com/blade/route/RouteException.java new file mode 100644 index 000000000..d027ac396 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/RouteException.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +/** + * + *

+ * 路由异常类 + *

+ * + * @author biezhi + * @since 1.0 + */ +public class RouteException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public RouteException(String message) { + super(message); + } + + public RouteException(String message, Throwable cause) { + super(message, cause); + } + + public RouteException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/route/RouteHandler.java b/blade-core/src/main/java/com/blade/route/RouteHandler.java index 069bff8e5..0d404519f 100644 --- a/blade-core/src/main/java/com/blade/route/RouteHandler.java +++ b/blade-core/src/main/java/com/blade/route/RouteHandler.java @@ -1,12 +1,31 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; import com.blade.http.Request; import com.blade.http.Response; /** + * + *

* 路由执行器 - * @author biezhi + *

* + * @author biezhi + * @since 1.0 */ public interface RouteHandler { diff --git a/blade-core/src/main/java/com/blade/route/Router.java b/blade-core/src/main/java/com/blade/route/Router.java index 9e82d44cf..ce4151745 100644 --- a/blade-core/src/main/java/com/blade/route/Router.java +++ b/blade-core/src/main/java/com/blade/route/Router.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; import java.lang.reflect.InvocationTargetException; @@ -17,7 +32,10 @@ import blade.kit.log.Logger; /** + * + *

* 注册、管理路由 + *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/route/RoutesException.java b/blade-core/src/main/java/com/blade/route/RoutesException.java deleted file mode 100644 index 76846acc5..000000000 --- a/blade-core/src/main/java/com/blade/route/RoutesException.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.blade.route; - -/** - * Generally thrown when a problem occurs loading the routes (different from a parsing error) - * - * @author German Escobar - */ -public class RoutesException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - public RoutesException(String message) { - super(message); - } - - public RoutesException(String message, Throwable cause) { - super(message, cause); - } - - public RoutesException(Throwable cause) { - super(cause); - } - -} diff --git a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java index e55cb3220..531eb414e 100644 --- a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; import java.net.URI; @@ -10,6 +25,15 @@ import com.blade.http.HttpMethod; import com.blade.http.Path; +/** + * + *

+ * 路由匹配器默认实现 + *

+ * + * @author biezhi + * @since 1.0 + */ public class SampleRouteMatcher { // private static final Logger LOGGER = Logger.getLogger(SampleRouteMatcher.class); diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java index 8db23149c..348f80c7d 100644 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.server; import java.util.EnumSet; @@ -11,7 +26,10 @@ import blade.kit.log.Logger; /** + * + *

* Jetty服务 + *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java index 696bf3a83..951e4c23a 100644 --- a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet; import java.io.BufferedReader; @@ -36,7 +51,10 @@ import blade.kit.text.HTMLFilter; /** + * + *

* ServletRequest + *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/servlet/ServletResponse.java b/blade-core/src/main/java/com/blade/servlet/ServletResponse.java index 039e4dbfb..3c40e7aae 100644 --- a/blade-core/src/main/java/com/blade/servlet/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/servlet/ServletResponse.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet; import java.io.IOException; @@ -23,7 +38,10 @@ import blade.kit.Assert; /** + * + *

* ServletResponse + *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/servlet/Session.java b/blade-core/src/main/java/com/blade/servlet/Session.java index 6b7985049..ae17c417f 100644 --- a/blade-core/src/main/java/com/blade/servlet/Session.java +++ b/blade-core/src/main/java/com/blade/servlet/Session.java @@ -22,7 +22,10 @@ import javax.servlet.http.HttpSession; /** + * + *

* HttpSession包装 + *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java b/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java index 8fa409c0e..effbb6b01 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java +++ b/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet.multipart; import java.io.File; @@ -5,9 +20,13 @@ import java.util.Map; /** + * + *

* HTTP multipart/form-data 请求 - * @author biezhi + *

* + * @author biezhi + * @since 1.0 */ public class FileItem { diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java b/blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java index d34026b4c..36497c56c 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java +++ b/blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet.multipart; import java.io.File; @@ -13,6 +28,15 @@ import blade.kit.IOKit; +/** + * + *

+ * Multipart对象 + *

+ * + * @author biezhi + * @since 1.0 + */ public class Multipart { public static final String CONTENT_TYPE = "Content-Type"; diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java index 940fab864..931ac1c20 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java +++ b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java @@ -1,5 +1,29 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet.multipart; +/** + * + *

+ * Multipart异常类 + *

+ * + * @author biezhi + * @since 1.0 + */ public class MultipartException extends Exception { private static final long serialVersionUID = 1L; diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java index 0a18e4400..caebf48b4 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java +++ b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java @@ -1,5 +1,29 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet.multipart; +/** + * + *

+ * MultipartHandler + *

+ * + * @author biezhi + * @since 1.0 + */ public interface MultipartHandler { void handleFormItem(String name, String value); diff --git a/blade-core/src/main/java/com/blade/verify/CSRFConfig.java b/blade-core/src/main/java/com/blade/verify/CSRFConfig.java index ea2953f14..aa5caf950 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFConfig.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFConfig.java @@ -1,9 +1,28 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.verify; /** + * + *

* CSRF配置 - * @author biezhi + *

* + * @author biezhi + * @since 1.0 */ public class CSRFConfig { diff --git a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java index f68a9286d..7cea37015 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.verify; import com.blade.http.Request; @@ -9,9 +24,13 @@ import blade.kit.log.Logger; /** + * + *

* CSRF token管理器 - * @author biezhi + *

* + * @author biezhi + * @since 1.0 */ public class CSRFTokenManager { From 6542349b6e3b0866b18643bdb32725254abb9ab7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 11:38:54 +0800 Subject: [PATCH 220/545] update log --- UPDATE_LOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index bfff127e4..7cca661f4 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,4 +1,9 @@ -#Blade 更新日志 +# Blade 更新日志 + +### v1.4.1 + 1. 去除过度设计 + 2. 添加多种路由配置 + 3. 统一渲染引擎,不在分离 ### v1.4.0 1. 添加CSRF防御 From b22382696aacdfcd1db33bb980d9730429701750 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 17:06:51 +0800 Subject: [PATCH 221/545] add testcase --- blade-core/pom.xml | 36 +++++++++++++++++-- blade-core/src/main/java/com/blade/Blade.java | 29 +++++++++++++-- .../src/main/java/com/blade/http/Request.java | 2 +- .../main/java/com/blade/server/Server.java | 30 ++++++++++++---- .../com/blade/servlet/ServletRequest.java | 21 ++++++++--- .../com/blade/servlet/ServletResponse.java | 1 + .../main/java/com/blade/servlet/Session.java | 2 +- pom.xml | 14 +------- 8 files changed, 104 insertions(+), 31 deletions(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 6e567b6b6..1ab4d331b 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -11,7 +11,7 @@ blade-core jar - ${blade.version} + 1.4.1-alpha blade-core https://github.com/biezhi/blade/blade-core @@ -20,6 +20,8 @@ 2.0.12 2.2.3 1.7 + 4.3.5 + 1.7.7 @@ -31,7 +33,7 @@ javax.servlet javax.servlet-api - ${servlet.version} + 3.1.0 provided @@ -64,6 +66,36 @@ ${jetty.version} provided + + org.testng + testng + 6.8.8 + provided + + + org.mockito + mockito-all + 1.9.5 + test + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + test + + + org.apache.httpcomponents + fluent-hc + ${httpclient.version} + test + + + org.slf4j + slf4j-api + ${slf4j.version} + test + diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 79109a764..f69b95f41 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -103,6 +103,11 @@ public void init() { */ private int port = DEFAULT_PORT; + /** + * jetty服务 + */ + private Server bladeServer; + private Blade() { } @@ -590,8 +595,8 @@ public Blade listen(int port){ */ public void start(String contextPath) { try { - Server bladeServer = new Server(this.port); - bladeServer.run(contextPath); + bladeServer = new Server(this.port); + bladeServer.start(contextPath); } catch (Exception e) { throw new RuntimeException(e); } @@ -604,6 +609,26 @@ public void start() { this.start("/"); } + /** + * 停止jetty服务 + */ + public void stop() { + try { + bladeServer.stop(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * join in server + * @throws InterruptedException + * @throws Exception + */ + public void join() throws InterruptedException { + bladeServer.join(); + } + /** * @return 返回系统配置对象 */ diff --git a/blade-core/src/main/java/com/blade/http/Request.java b/blade-core/src/main/java/com/blade/http/Request.java index 76118cdf9..09f9d7f03 100644 --- a/blade-core/src/main/java/com/blade/http/Request.java +++ b/blade-core/src/main/java/com/blade/http/Request.java @@ -118,7 +118,7 @@ public interface Request { void attribute(String name, Object value); - Object attribute(String name); + T attribute(String name); Set attributes(); diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java index 348f80c7d..16ea95e1a 100644 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -40,22 +40,38 @@ public class Server { private int port = 9000; + private org.eclipse.jetty.server.Server server; + + private ServletContextHandler context; + public Server(int port) { this.port = port; } - public void run(String contextPath) throws Exception{ + public void setPort(int port){ + this.port = port; + } + + public void start(String contextPath) throws Exception{ - org.eclipse.jetty.server.Server server = new org.eclipse.jetty.server.Server(port); + server = new org.eclipse.jetty.server.Server(this.port); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath(contextPath); context.setResourceBase(System.getProperty("java.io.tmpdir")); context.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); - server.setHandler(context); - + + server.setHandler(this.context); server.start(); - LOGGER.info("Blade Server Listen on 0.0.0.0:" + port); - server.join(); + LOGGER.info("Blade Server Listen on 0.0.0.0:" + this.port); + } + + public void join() throws InterruptedException { + server.join(); + } + + public void stop() throws Exception{ + context.stop(); + server.stop(); } } diff --git a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java index 951e4c23a..5b374f042 100644 --- a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java @@ -319,7 +319,7 @@ public String method() { @Override public HttpMethod httpMethod() { - return HttpMethod.valueOf(request.getMethod()); + return HttpMethod.valueOf(request.getMethod().toUpperCase()); } @Override @@ -351,9 +351,14 @@ public void attribute(String name, Object value) { request.setAttribute(name, value); } + @SuppressWarnings("unchecked") @Override - public Object attribute(String name) { - return request.getAttribute(name); + public T attribute(String name) { + Object object = request.getAttribute(name); + if(null != object){ + return (T) object; + } + return null; } @Override @@ -405,8 +410,14 @@ private Cookie map(Cookie servletCookie) { Cookie cookie = new Cookie(servletCookie.getName(), servletCookie.getValue()); cookie.setMaxAge(servletCookie.getMaxAge()); cookie.setHttpOnly(servletCookie.isHttpOnly()); - cookie.setPath(servletCookie.getPath()); - cookie.setDomain(servletCookie.getDomain()); + String path = servletCookie.getPath(); + if(null != path){ + cookie.setPath(path); + } + String domain = servletCookie.getDomain(); + if(null != domain){ + cookie.setDomain(domain); + } cookie.setSecure(servletCookie.getSecure()); return cookie; } diff --git a/blade-core/src/main/java/com/blade/servlet/ServletResponse.java b/blade-core/src/main/java/com/blade/servlet/ServletResponse.java index 3c40e7aae..016420bc7 100644 --- a/blade-core/src/main/java/com/blade/servlet/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/servlet/ServletResponse.java @@ -294,6 +294,7 @@ public Response render(String view) { } viewPath = Path.cleanPath(viewPath); ModelAndView modelAndView = new ModelAndView(viewPath); + render.render(modelAndView, response.getWriter()); return this; } catch (IOException e) { diff --git a/blade-core/src/main/java/com/blade/servlet/Session.java b/blade-core/src/main/java/com/blade/servlet/Session.java index ae17c417f..ebc717ddd 100644 --- a/blade-core/src/main/java/com/blade/servlet/Session.java +++ b/blade-core/src/main/java/com/blade/servlet/Session.java @@ -34,7 +34,7 @@ public class Session { private HttpSession session; - Session(HttpSession session) { + public Session(HttpSession session) { if (session == null) { throw new IllegalArgumentException("session cannot be null"); } diff --git a/pom.xml b/pom.xml index 341cbe68d..f5473070d 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,6 @@ 1.6 1.6 UTF-8 - 4.11 3.0.1 1.4.1-alpha @@ -28,17 +27,6 @@ blade-startup - - - - junit - junit - ${junit.version} - test - - - - oss-snapshots @@ -67,7 +55,7 @@ maven-surefire-plugin 2.5 - true + false
From 918d82d0654edb44aafcec593e5a12547029c30e Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 17:07:44 +0800 Subject: [PATCH 222/545] add test --- .../test/java/com/blade/BladeTestCase.java | 45 +++ .../test/java/com/blade/MockAnnotation.java | 12 + .../test/java/com/blade/MockController.java | 12 + .../com/blade/servlet/ServletRequestTest.java | 312 ++++++++++++++++++ .../multipart/multiple-files-fixed.txt | 21 ++ .../resources/multipart/multiple-files.txt | 21 ++ .../resources/multipart/single-file-fixed.txt | 11 + .../test/resources/multipart/single-file.txt | 11 + 8 files changed, 445 insertions(+) create mode 100644 blade-core/src/test/java/com/blade/BladeTestCase.java create mode 100644 blade-core/src/test/java/com/blade/MockAnnotation.java create mode 100644 blade-core/src/test/java/com/blade/MockController.java create mode 100644 blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java create mode 100644 blade-core/src/test/resources/multipart/multiple-files-fixed.txt create mode 100644 blade-core/src/test/resources/multipart/multiple-files.txt create mode 100644 blade-core/src/test/resources/multipart/single-file-fixed.txt create mode 100644 blade-core/src/test/resources/multipart/single-file.txt diff --git a/blade-core/src/test/java/com/blade/BladeTestCase.java b/blade-core/src/test/java/com/blade/BladeTestCase.java new file mode 100644 index 000000000..92a00893d --- /dev/null +++ b/blade-core/src/test/java/com/blade/BladeTestCase.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +import java.net.ConnectException; +import java.net.Socket; + +import org.apache.http.HttpResponse; +import org.apache.http.client.fluent.Request; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class BladeTestCase { + + @SuppressWarnings("resource") + @Test + public void testStartStopServer() throws Exception { + Blade blade = Blade.me(); + blade.listen(10241).start(); + try { + HttpResponse response = Request.Get("http://localhost:10241/").execute().returnResponse(); + Assert.assertEquals(response.getStatusLine().getStatusCode(), 404); + } finally { + blade.stop(); + try { + new Socket("localhost", 10241); + Assert.fail("Server is still running"); + } catch (ConnectException e) {} + } + } + +} diff --git a/blade-core/src/test/java/com/blade/MockAnnotation.java b/blade-core/src/test/java/com/blade/MockAnnotation.java new file mode 100644 index 000000000..a3c780fc6 --- /dev/null +++ b/blade-core/src/test/java/com/blade/MockAnnotation.java @@ -0,0 +1,12 @@ +package com.blade; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface MockAnnotation { + +} diff --git a/blade-core/src/test/java/com/blade/MockController.java b/blade-core/src/test/java/com/blade/MockController.java new file mode 100644 index 000000000..2ecf408e2 --- /dev/null +++ b/blade-core/src/test/java/com/blade/MockController.java @@ -0,0 +1,12 @@ +package com.blade; + +import com.blade.http.Request; +import com.blade.http.Response; + +public class MockController { + + public void init(Request request, Response response) {} + + public void show(Request request, Response response) {} + +} \ No newline at end of file diff --git a/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java b/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java new file mode 100644 index 000000000..534747a0c --- /dev/null +++ b/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java @@ -0,0 +1,312 @@ +package com.blade.servlet; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.blade.MockController; +import com.blade.http.HttpMethod; +import com.blade.http.Request; +import com.blade.http.Response; +import com.blade.route.Route; + +public class ServletRequestTest { + + @Test + public void testRetrieveHost() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getServerName()).thenReturn("localhost"); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.host(), "localhost"); + } + + @Test + public void testRetrievePath() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getContextPath()).thenReturn("/context"); + when(servletRequest.getRequestURI()).thenReturn("/users/edit/1"); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.path(), "/users/edit/1"); + } + + @Test + public void testRetrievePathVariables() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getContextPath()).thenReturn(""); + when(servletRequest.getRequestURI()).thenReturn("/users/1/edit/th1s1s4hAsh/"); + + Route route = new Route(HttpMethod.GET, "/users/:userId/edit/:hash", new MockController(), + MockController.class.getMethod("init", Request.class, Response.class)); + Request request = new ServletRequest(servletRequest); + request.setRoute(route); + + Map pathVariables = request.pathParams(); + Assert.assertNotNull(pathVariables); + Assert.assertEquals(pathVariables.size(), 2); + Assert.assertEquals(pathVariables.get("userId"), "1"); + Assert.assertEquals(pathVariables.get("hash"), "th1s1s4hAsh"); + } + + @Test + public void testNotRetrieveNonExistingPathVariable() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getContextPath()).thenReturn(""); + when(servletRequest.getRequestURI()).thenReturn("/users/1/edit/th1s1s4hAsh"); + + Route route = new Route(HttpMethod.GET, "/users/1/edit/th1s1s4hAsh", new MockController(), + MockController.class.getMethod("init", Request.class, Response.class)); + Request request = new ServletRequest(servletRequest); + request.setRoute(route); + + Map pathVariables = request.pathParams(); + Assert.assertNotNull(pathVariables); + Assert.assertEquals(pathVariables.size(), 0); + } + + @Test + public void testRetrieveQueryString() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getQueryString()).thenReturn("method=test&action=success"); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.queryString(), "method=test&action=success"); + } + + @Test + public void testRetrieveParams() throws Exception { + Map mockParams = new HashMap(); + mockParams.put("param1", new String[]{"value1"}); + mockParams.put("param2", new String[]{"val1", "val2"}); + + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getParameterMap()).thenReturn(mockParams); + + Request request = new ServletRequest(servletRequest); + + Map params = request.querys(); + Assert.assertNotNull(params); + Assert.assertEquals(params.size(), 2); + + String param1 = params.get("param1"); + Assert.assertNotNull(param1); + Assert.assertEquals(param1, "value1"); + + String param2 = params.get("param2"); + Assert.assertNotNull(param2); + Assert.assertEquals(param2, "val1,val2"); + + Assert.assertNull(params.get("notexistnet")); + } + + @Test + public void testRetrieveStringParam() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getParameterValues("param1")).thenReturn(new String[]{"value1"}); + + Request request = new ServletRequest(servletRequest); + + Assert.assertNotNull(request.query("param1")); + Assert.assertEquals(request.query("param1"), "value1"); + } + + @Test + public void testNotRetrieveNonExistingParam() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + Request request = new ServletRequest(servletRequest); + Assert.assertNull(request.query("nonexisting")); + } + + @Test + public void testRetrieveLongParam() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getParameterValues("param1")).thenReturn(new String[]{"1"}); + + Request request = new ServletRequest(servletRequest); + + Assert.assertNotNull(request.query("param1")); + Assert.assertEquals(request.query("param1"), "1"); + } + + @Test + public void testRetrieveUrl() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getRequestURL()).thenReturn(new StringBuffer("http://www.google.com:81/test")); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.url(), "http://www.google.com:81/test"); + } + + @Test + public void testRetrieveMethod() throws Exception { + HttpServletRequest servletRequest = mockServletRequest("GET"); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.method(), "GET"); + } + + @Test + public void testRetrieveRemoteAddress() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getRemoteAddr()).thenReturn("localhost"); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.address(), "localhost"); + } + + @Test + public void testRetrieveContentType() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getContentType()).thenReturn("application/json"); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.contentType(), "application/json"); + } + + @Test + public void testRetrievePort() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getServerPort()).thenReturn(1); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.port(), 1); + } + + @Test + public void testRetrieveIsSecure() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.isSecure()).thenReturn(true); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.isSecure(), true); + } + + @Test + public void testRetrieveIsAjax() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getHeader("x-requested-with")).thenReturn("XMLHttpRequest"); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.isAjax(), true); + + when(servletRequest.getHeader("x-requested-with")).thenReturn(null); + Assert.assertEquals(request.isAjax(), false); + + when(servletRequest.getHeader("x-requested-with")).thenReturn("Another"); + Assert.assertEquals(request.isAjax(), false); + } + + @Test + public void testRetrieveCookie() throws Exception { + javax.servlet.http.Cookie[] servletCookies = {new javax.servlet.http.Cookie("test-1", "1")}; + + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getCookies()).thenReturn(servletCookies); + + Request request = new ServletRequest(servletRequest); + Map cookies = request.cookies(); + + Assert.assertEquals(cookies.size(), 1); + + Cookie cookie = cookies.get("test-1"); + Assert.assertNotNull(cookie); + Assert.assertEquals(cookie.getValue(), "1"); + Assert.assertEquals(cookie.getMaxAge(), -1); + Assert.assertNull(cookie.getDomain()); + Assert.assertNull(cookie.getPath()); + + Assert.assertNotNull(request.cookie("test-1")); + Assert.assertNull(request.cookie("not-existent")); + } + + @Test + public void testRetrieveEmptyCookies() throws Exception { + javax.servlet.http.Cookie[] servletCookies = {}; + + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getCookies()).thenReturn(servletCookies); + + Request request = new ServletRequest(servletRequest); + Map cookies = request.cookies(); + + Assert.assertEquals(cookies.size(), 0); + } + + @Test + public void shoudlRetrieveHeader() throws Exception { + HttpServletRequest servletRequest = mockServletRequest(); + when(servletRequest.getHeader("Authorization")).thenReturn("Basic ..."); + + Request request = new ServletRequest(servletRequest); + Assert.assertEquals(request.header("Authorization"), "Basic ..."); + } + + + private HttpServletRequest mockServletRequest() { + return mockServletRequest("GET"); + } + + private HttpServletRequest mockServletRequest(String methodName) { + HttpServletRequest servletRequest = mock(HttpServletRequest.class); + when(servletRequest.getMethod()).thenReturn(methodName); + + return servletRequest; + } + + private static void fixMultipartLineSeparators(String fileName) throws IOException { + File file = new File("src/test/resources/multipart/" + fileName + "-fixed.txt"); + if (!file.exists()) { + file.createNewFile(); + } + + BufferedReader reader = null; + BufferedWriter writer = null; + try { + reader = new BufferedReader(new InputStreamReader(ServletRequestTest.class.getResourceAsStream("/multipart/" + fileName + ".txt"))); + writer = new BufferedWriter(new FileWriter(file.getAbsoluteFile())); + String line; + while ((line = reader.readLine()) != null) { + writer.write(line + "\r\n"); + } + } finally { + if (reader != null) { + try { + reader.close(); + } catch (Exception e) { + } + } + if (writer != null) { + try { + writer.close(); + } catch (Exception e) { + } + } + } + } + + public static void main(String... args) throws IOException { + //Warning + //Be carefull if shouldRetrieveSingleFile or shouldRetrieveMultipleFiles fail is probably because + //your system change the line endings in the associated txt files.HTTP Multipart use CRLF as line ending + //while Unix like systems use only LF. + //If that is the problem runnign this main will fix it ;) + fixMultipartLineSeparators("single-file"); + fixMultipartLineSeparators("multiple-files"); + } + +} diff --git a/blade-core/src/test/resources/multipart/multiple-files-fixed.txt b/blade-core/src/test/resources/multipart/multiple-files-fixed.txt new file mode 100644 index 000000000..624f61028 --- /dev/null +++ b/blade-core/src/test/resources/multipart/multiple-files-fixed.txt @@ -0,0 +1,21 @@ +--AaB03x +Content-Disposition: form-data; name="submit-name" + +Larry +--AaB03x +Content-Disposition: form-data; name="files" +Content-Type: multipart/mixed; boundary=BbC04y + +--BbC04y +Content-Disposition: form-data; filename="file1.txt" +Content-Type: text/plain + +this is a text file +--BbC04y +Content-Disposition: form-data; filename="file2.gif" +Content-Type: image/gif +Content-Transfer-Encoding: binary + +sdfsdf38owefhoe8yr +--BbC04y-- +--AaB03x-- diff --git a/blade-core/src/test/resources/multipart/multiple-files.txt b/blade-core/src/test/resources/multipart/multiple-files.txt new file mode 100644 index 000000000..71980dde4 --- /dev/null +++ b/blade-core/src/test/resources/multipart/multiple-files.txt @@ -0,0 +1,21 @@ +--AaB03x +Content-Disposition: form-data; name="submit-name" + +Larry +--AaB03x +Content-Disposition: form-data; name="files" +Content-Type: multipart/mixed; boundary=BbC04y + +--BbC04y +Content-Disposition: form-data; filename="file1.txt" +Content-Type: text/plain + +this is a text file +--BbC04y +Content-Disposition: form-data; filename="file2.gif" +Content-Type: image/gif +Content-Transfer-Encoding: binary + +sdfsdf38owefhoe8yr +--BbC04y-- +--AaB03x-- diff --git a/blade-core/src/test/resources/multipart/single-file-fixed.txt b/blade-core/src/test/resources/multipart/single-file-fixed.txt new file mode 100644 index 000000000..4aa31e205 --- /dev/null +++ b/blade-core/src/test/resources/multipart/single-file-fixed.txt @@ -0,0 +1,11 @@ +--AaB03x +Content-Disposition: form-data; name="submit-name" + +Larry +--AaB03x +Content-Disposition: form-data; name="files"; filename="file1.txt" +Content-Type: text/plain +Content-Length: 8 + +this is a plain file +--AaB03x-- diff --git a/blade-core/src/test/resources/multipart/single-file.txt b/blade-core/src/test/resources/multipart/single-file.txt new file mode 100644 index 000000000..13efcb837 --- /dev/null +++ b/blade-core/src/test/resources/multipart/single-file.txt @@ -0,0 +1,11 @@ +--AaB03x +Content-Disposition: form-data; name="submit-name" + +Larry +--AaB03x +Content-Disposition: form-data; name="files"; filename="file1.txt" +Content-Type: text/plain +Content-Length: 8 + +this is a plain file +--AaB03x-- From 132037179d507d6c6868c45e9917f8642200c874 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 17:16:06 +0800 Subject: [PATCH 223/545] add junit --- .../src/test/java/blade/test/HttpTest.java | 36 ----------- .../src/test/java/blade/test/JSONTest.java | 59 ------------------- .../src/test/java/blade/test/LogTest.java | 19 ------ .../src/test/java/blade/test/MailTest.java | 36 ----------- .../src/test/java/blade/test/StringTest.java | 36 ----------- .../src/test/java/blade/test/TaskTest.java | 35 ----------- blade-kit/src/test/java/blade/test/User.java | 32 ---------- pom.xml | 43 +++++++++----- 8 files changed, 28 insertions(+), 268 deletions(-) delete mode 100644 blade-kit/src/test/java/blade/test/HttpTest.java delete mode 100644 blade-kit/src/test/java/blade/test/JSONTest.java delete mode 100644 blade-kit/src/test/java/blade/test/LogTest.java delete mode 100644 blade-kit/src/test/java/blade/test/MailTest.java delete mode 100644 blade-kit/src/test/java/blade/test/StringTest.java delete mode 100644 blade-kit/src/test/java/blade/test/TaskTest.java delete mode 100644 blade-kit/src/test/java/blade/test/User.java diff --git a/blade-kit/src/test/java/blade/test/HttpTest.java b/blade-kit/src/test/java/blade/test/HttpTest.java deleted file mode 100644 index d533abc7d..000000000 --- a/blade-kit/src/test/java/blade/test/HttpTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package blade.test; - -import java.io.File; - -import blade.kit.http.HttpRequest; - - - -public class HttpTest { - - public static void main(String[] args) { - - // 发送一个GET请求并获取内容 - String body = HttpRequest.get("http://bladejava.com").body(); - System.out.println(body); - - // 发送一个带heder的请求 - String res = HttpRequest.get("http://bladejava.com").accept("application/json") - .userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0").body(); - System.out.println(res); - - // 发送一个POST请求 - HttpRequest.post("http://www.example.com").part("id", 20).part("name", "jack").body(); - - // 带认证的请求 - int response = HttpRequest.get("http://google.com").basic("username", "p4ssw0rd").code(); - System.out.println(response); - - // 下载一个图片 - File file = new File("F:/a.png"); - HttpRequest.get("http://img.blog.csdn.net/20150601232126808").receive(file); - - - } - -} diff --git a/blade-kit/src/test/java/blade/test/JSONTest.java b/blade-kit/src/test/java/blade/test/JSONTest.java deleted file mode 100644 index 25074fc93..000000000 --- a/blade-kit/src/test/java/blade/test/JSONTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package blade.test; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import blade.kit.json.JSONKit; -import blade.kit.json.Json; -import blade.kit.json.JsonArray; -import blade.kit.json.JsonObject; -import blade.kit.json.JsonValue; - -public class JSONTest { - - public static void main(String[] args) { - //[{"text": "首页","href": "/"},{"text": "博客","href": "blog"},{"text": "关于","href": "about"},{"text": "联系","href": "contact"}] - String json = "[{\"text\": \"博客\",\"href\": \"blog\"}]"; - - // 下面构造两个map、一个list和一个Employee对象 - Map map1 = new HashMap(); - map1.put("name", "Alexia"); - map1.put("sex", "female"); - map1.put("age", "23"); - - List> list = new ArrayList>(); - Map map = new HashMap(); - - map.put("abc", "123456"); - map.put("def", "hmm"); - list.add(map); - - String string = JSONKit.toJSONString(list); - System.out.println(string); - - List list2 = Json.parse(json).asArray().values(); - System.out.println(list2); - - JsonObject obj1 = new JsonObject(); - obj1.add("name", "jack"); - - System.out.println(obj1); - - JsonArray obj2 = new JsonArray(); - obj2.add("123"); - - System.out.println(obj2); - - User u1 = new User(); - u1.setAge(22); - u1.setName("rose"); - - System.out.println(JSONKit.toJSONString(u1)); - -// User u = JSONKit.parse("{\"name\":\"jack\",\"age\":20}", User.class); -// System.out.println(u); - } - -} diff --git a/blade-kit/src/test/java/blade/test/LogTest.java b/blade-kit/src/test/java/blade/test/LogTest.java deleted file mode 100644 index cbfeaf514..000000000 --- a/blade-kit/src/test/java/blade/test/LogTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package blade.test; -import blade.kit.log.Logger; - - -public class LogTest { - - private static final Logger LOGGER = Logger.getLogger(LogTest.class); - - public static void main(String[] args) { -// LOGGER.setLevel(Level.INFO); - LOGGER.debug("debug hello"); - LOGGER.info("info hello %s", "aaa"); - LOGGER.warn("warn hello"); - - System.out.println(LOGGER.isDebugEnabled()); - System.out.println(LOGGER.isInfoEnabled()); - System.out.println(LOGGER.isErrorEnabled()); - } -} diff --git a/blade-kit/src/test/java/blade/test/MailTest.java b/blade-kit/src/test/java/blade/test/MailTest.java deleted file mode 100644 index 068919b6f..000000000 --- a/blade-kit/src/test/java/blade/test/MailTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package blade.test; - -import java.io.IOException; - -import blade.kit.MailKit; -import blade.kit.mail.MailTemplate; - -public class MailTest { - - public static void main(String[] args) { - // 发送方配置,邮箱帐号和密码 - MailKit.config(MailKit.SMTP_QQ, "921293209@qq.com", "helloworld"); - - // 测试给【xxx@qq.com】发送邮件 - MailKit.send("xxx@qq.com", "测试发送邮件", "hello"); - - // 测试异步发送邮件 - MailKit.asynSend("xxx", "测试异步发送邮件", "hello"); - - // 测试给【xxx@qq.com】发送邮件并抄送给xoxo@qq.com - MailKit.sendAndCc("xxx@qq.com", "xoxo@qq.com", "测试发送邮件", "hello"); - - // 测试给【xxx@qq.com】发送邮件并带一个附件 - MailKit.send("xxx@qq.com", "测试发送邮件", "hello", "F:/aa.txt"); - - // 使用模板给【xxx@qq.com】发送邮件并带一个附件 - try { - MailTemplate template = new MailTemplate("F:/a.html", "xxx@qq.com", null); - MailKit.send(template, "新主题"); - } catch (IOException e) { - e.printStackTrace(); - } - - } - -} diff --git a/blade-kit/src/test/java/blade/test/StringTest.java b/blade-kit/src/test/java/blade/test/StringTest.java deleted file mode 100644 index b27d3b1f2..000000000 --- a/blade-kit/src/test/java/blade/test/StringTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package blade.test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import blade.kit.StringKit; - - -public class StringTest { - - public static void main(String[] args) { - - //判断是否为空 - String str = "hello"; - System.out.println(StringKit.isNotEmpty(str)); - - //分割字符串 - String[] arr = StringKit.split("1,2,3", ","); - System.out.println(Arrays.toString(arr)); - - //生成5个随机字符串 - System.out.println(StringKit.random(5)); - - //将字符串20转换为long类型,如果为null或者空则给一个默认值10 - System.out.println(StringKit.toLong("20", 10)); - - List list = new ArrayList(); - list.add(22); - list.add(30); - //将集合用指定字符分隔 - String listString = StringKit.join(list, "|"); - System.out.println(listString); - } - -} diff --git a/blade-kit/src/test/java/blade/test/TaskTest.java b/blade-kit/src/test/java/blade/test/TaskTest.java deleted file mode 100644 index f20499806..000000000 --- a/blade-kit/src/test/java/blade/test/TaskTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package blade.test; - -import java.util.Date; -import java.util.concurrent.TimeUnit; - -import blade.kit.TaskKit; - - -public class TaskTest { - - public static void main(String[] args) { - TaskKit.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - System.out.println("每隔两秒执行一次"); - } - }, 2); - - TaskKit.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - System.out.println("在指定的延时之后开始以固定的频率来运行任务。后续任务的启动时间不受前次任务延时影响。"); - } - }, 10, 3, TimeUnit.SECONDS); - - TaskKit.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - System.out.println("在指定的时间点启动,两次任务间保持固定的时间间隔"); - } - }, new Date(), 3, TimeUnit.SECONDS); - - } - -} diff --git a/blade-kit/src/test/java/blade/test/User.java b/blade-kit/src/test/java/blade/test/User.java deleted file mode 100644 index 03bdee871..000000000 --- a/blade-kit/src/test/java/blade/test/User.java +++ /dev/null @@ -1,32 +0,0 @@ -package blade.test; - -public class User { - - private String name; - private long age; - - public User() { - // TODO Auto-generated constructor stub - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public long getAge() { - return age; - } - - public void setAge(long age) { - this.age = age; - } - - @Override - public String toString() { - return "User [name=" + name + ", age=" + age + "]"; - } -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index f5473070d..40b22d097 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 com.bladejava @@ -16,6 +17,7 @@ UTF-8 3.0.1 1.4.1-alpha + 4.12 @@ -24,22 +26,33 @@ blade-cache blade-sql2o blade-redis - blade-startup - - + blade-startup + + - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + - + + + + + junit + junit + ${junit.version} + test + + + + From ae97b7125a540d57edbcd4ff6aec73b6b794b794 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 17:22:26 +0800 Subject: [PATCH 224/545] add blade-cache testCase --- .../main/java/blade/cache/AbstractCache.java | 20 ++++++++++++++-- .../src/main/java/blade/cache/Cache.java | 21 +++++++++++++--- .../main/java/blade/cache/CacheCleaner.java | 22 +++++++++++++++-- .../main/java/blade/cache/CacheException.java | 18 ++++++++++++++ .../main/java/blade/cache/CacheManager.java | 20 +++++++++++++++- .../main/java/blade/cache/CacheObject.java | 23 ++++++++++++++---- .../main/java/blade/cache/impl/FIFOCache.java | 23 ++++++++++++++---- .../main/java/blade/cache/impl/LFUCache.java | 24 +++++++++++++++---- .../main/java/blade/cache/impl/LRUCache.java | 20 ++++++++++++++-- .../src/test/java/blade/test/CacheTest.java | 18 +++++++------- 10 files changed, 178 insertions(+), 31 deletions(-) diff --git a/blade-cache/src/main/java/blade/cache/AbstractCache.java b/blade-cache/src/main/java/blade/cache/AbstractCache.java index 3b292ed6e..1c03dd01b 100644 --- a/blade-cache/src/main/java/blade/cache/AbstractCache.java +++ b/blade-cache/src/main/java/blade/cache/AbstractCache.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; import java.util.Collections; @@ -8,12 +23,13 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; /** + * + *

* 抽象缓存基础实现 + *

* * @author biezhi * @since 1.0 - * @param - * @param */ @SuppressWarnings("unchecked") public abstract class AbstractCache implements Cache { diff --git a/blade-cache/src/main/java/blade/cache/Cache.java b/blade-cache/src/main/java/blade/cache/Cache.java index 557f86ef3..ab4238e77 100644 --- a/blade-cache/src/main/java/blade/cache/Cache.java +++ b/blade-cache/src/main/java/blade/cache/Cache.java @@ -1,16 +1,31 @@ - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; import java.util.Set; /** + * + *

* 缓存顶级接口 + *

* * @author biezhi * @since 1.0 - * @param - * @param */ public interface Cache { diff --git a/blade-cache/src/main/java/blade/cache/CacheCleaner.java b/blade-cache/src/main/java/blade/cache/CacheCleaner.java index 2f68766f1..7dc8767b3 100644 --- a/blade-cache/src/main/java/blade/cache/CacheCleaner.java +++ b/blade-cache/src/main/java/blade/cache/CacheCleaner.java @@ -1,12 +1,30 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; import java.util.Set; /** + * + *

* 定时清理缓存线程 + *

* - * @author biezhi - * @since 1.0 + * @author biezhi + * @since 1.0 */ public class CacheCleaner extends Thread { diff --git a/blade-cache/src/main/java/blade/cache/CacheException.java b/blade-cache/src/main/java/blade/cache/CacheException.java index 16e8a3c97..cb145f691 100644 --- a/blade-cache/src/main/java/blade/cache/CacheException.java +++ b/blade-cache/src/main/java/blade/cache/CacheException.java @@ -1,7 +1,25 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; /** + * + *

* 缓存异常封装 + *

* * @author biezhi * @since 1.0 diff --git a/blade-cache/src/main/java/blade/cache/CacheManager.java b/blade-cache/src/main/java/blade/cache/CacheManager.java index 81479ff10..495165bf2 100644 --- a/blade-cache/src/main/java/blade/cache/CacheManager.java +++ b/blade-cache/src/main/java/blade/cache/CacheManager.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; import java.util.HashMap; @@ -9,7 +24,10 @@ import blade.cache.impl.LRUCache; /** + * + *

* 缓存管理对象 + *

* * @author biezhi * @since 1.0 @@ -32,7 +50,7 @@ public class CacheManager { private static Object _mlock = new Object(); - public CacheManager() { + private CacheManager() { _cacheMap = new HashMap(); _cleaner = new CacheCleaner(DEFAULT_CLEAN_TIME); //默认30秒自动清空缓存 _cleaner.start(); diff --git a/blade-cache/src/main/java/blade/cache/CacheObject.java b/blade-cache/src/main/java/blade/cache/CacheObject.java index fa3010967..4af5cb1f9 100644 --- a/blade-cache/src/main/java/blade/cache/CacheObject.java +++ b/blade-cache/src/main/java/blade/cache/CacheObject.java @@ -1,12 +1,27 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; /** + *

* 缓存实体对象 + *

* - * @author biezhi - * @since 1.0 - * @param - * @param + * @author biezhi + * @since 1.0 */ public class CacheObject { diff --git a/blade-cache/src/main/java/blade/cache/impl/FIFOCache.java b/blade-cache/src/main/java/blade/cache/impl/FIFOCache.java index 20399c474..fec064c0a 100644 --- a/blade-cache/src/main/java/blade/cache/impl/FIFOCache.java +++ b/blade-cache/src/main/java/blade/cache/impl/FIFOCache.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache.impl; import java.util.Iterator; @@ -5,14 +20,14 @@ import blade.cache.AbstractCache; import blade.cache.CacheObject; - /** - * FIFO实现 * + *

+ * FIFO实现 + *

+ * * @author biezhi * @since 1.0 - * @param - * @param */ public class FIFOCache extends AbstractCache { diff --git a/blade-cache/src/main/java/blade/cache/impl/LFUCache.java b/blade-cache/src/main/java/blade/cache/impl/LFUCache.java index 9a82ccaeb..db31021de 100644 --- a/blade-cache/src/main/java/blade/cache/impl/LFUCache.java +++ b/blade-cache/src/main/java/blade/cache/impl/LFUCache.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache.impl; import java.util.Iterator; @@ -6,12 +21,13 @@ import blade.cache.CacheObject; /** + * + *

* LFU实现 + *

* - * @author biezhi - * @since 1.0 - * @param - * @param + * @author biezhi + * @since 1.0 */ public class LFUCache extends AbstractCache { diff --git a/blade-cache/src/main/java/blade/cache/impl/LRUCache.java b/blade-cache/src/main/java/blade/cache/impl/LRUCache.java index 939c82f7a..658dd89dd 100644 --- a/blade-cache/src/main/java/blade/cache/impl/LRUCache.java +++ b/blade-cache/src/main/java/blade/cache/impl/LRUCache.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache.impl; import java.util.Iterator; import java.util.LinkedHashMap; @@ -7,12 +22,13 @@ import blade.cache.CacheObject; /** + * + *

* LRU 实现 + *

* * @author biezhi * @since 1.0 - * @param - * @param */ public class LRUCache extends AbstractCache { diff --git a/blade-cache/src/test/java/blade/test/CacheTest.java b/blade-cache/src/test/java/blade/test/CacheTest.java index c414640fa..e4ab65144 100644 --- a/blade-cache/src/test/java/blade/test/CacheTest.java +++ b/blade-cache/src/test/java/blade/test/CacheTest.java @@ -1,12 +1,13 @@ package blade.test; +import org.junit.Assert; import org.junit.Test; import blade.cache.Cache; import blade.cache.CacheManager; public class CacheTest { - + @Test public void testLRU2(){ CacheManager cm = CacheManager.getInstance(); @@ -15,8 +16,8 @@ public void testLRU2(){ cache.set("name:1", "jack"); cache.set("name:2", "jack2"); - System.out.println(cache.get("name:2")); - + Assert.assertEquals("jack", cache.get("name:1")); + Assert.assertEquals("jack2", cache.get("name:2")); } @Test @@ -28,14 +29,14 @@ public void testAutoClean(){ cache.set("name:1", "jack"); cache.set("name:2", "jack2"); - System.out.println(cache.get("name:2")); + Assert.assertEquals("jack2", cache.get("name:2")); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } - System.out.println(cache.get("name:2")); + Assert.assertEquals(null, cache.get("name:2")); } @Test @@ -47,10 +48,9 @@ public void testHashCache(){ cache.hset("user:list", "a2", "456"); cache.hset("user:list", "a3", "789"); - System.out.println(cache.hget("user:list", "a1")); - System.out.println(cache.hget("user:list", "a2")); - System.out.println(cache.hget("user:list", "a3")); - + Assert.assertEquals("123", cache.hget("user:list", "a1")); + Assert.assertEquals("456", cache.hget("user:list", "a2")); + Assert.assertEquals("789", cache.hget("user:list", "a3")); } } From 363d2ddf2b5ffe902b1117d346602fbfe142cf85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5?= Date: Thu, 29 Oct 2015 17:24:45 +0800 Subject: [PATCH 225/545] Update .travis.yml --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 45f3cd645..d67d8f63b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,4 @@ language: java jdk: - oraclejdk8 - oraclejdk7 - - openjdk7 -script: - mvn test -Dmaven.test.skip=false -fae \ No newline at end of file + - openjdk6 From 4ca27429d0192eba4c1be250fbc07fee4cec4bf5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 17:34:16 +0800 Subject: [PATCH 226/545] update maven compoler plugin --- pom.xml | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/pom.xml b/pom.xml index 40b22d097..795ebc21a 100644 --- a/pom.xml +++ b/pom.xml @@ -55,23 +55,22 @@ - - org.apache.maven.plugin - maven-compiler-plugin - 2.1 - - true - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.5 - - false - - - + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + true + + 1.6 + 1.6 + false + true + true + 1.6 + true + + +
\ No newline at end of file From bc948a78bcae0fb69821985e630d790844e95b10 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 17:37:16 +0800 Subject: [PATCH 227/545] update pom build --- pom.xml | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 135 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 795ebc21a..2a97e966b 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,80 @@ blade-root https://github.com/biezhi/blade - + + + + release + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + package + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + package + + jar + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + verify + + sign + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6 + true + + sonatype-nexus-staging + https://oss.sonatype.org/ + true + + + + + + + sonatype-nexus-snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + + sonatype-nexus-staging + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + 1.6 1.6 @@ -55,21 +128,75 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + pertest + -Xms1024m -Xmx1024m -Xss1m + + org.apache.maven.plugins maven-compiler-plugin - 2.3.2 - true + 3.1 1.6 1.6 - false - true - true - 1.6 - true + UTF-8 + + + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + + UTF-8 + + org.apache.maven.plugins + maven-jar-plugin + + + log4j.xml + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + UTF-8 + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.4.1 + From e867768ad3553ecfc89deb6e9c512be8d03492f7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 17:58:48 +0800 Subject: [PATCH 228/545] update testng socpe -> test --- blade-core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 1ab4d331b..292737f53 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -70,7 +70,7 @@ org.testng testng 6.8.8 - provided + test org.mockito From 03b619d658570853ebd4acbfc2cc05ac64dc90ab Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 18:00:30 +0800 Subject: [PATCH 229/545] update --- .travis.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index d67d8f63b..9d60e2338 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ -language: java -jdk: - - oraclejdk8 - - oraclejdk7 - - openjdk6 +language: java +jdk: + - oraclejdk8 + - oraclejdk7 + - openjdk6 +script: + mvn install -Dmaven.test.skip=false -fae \ No newline at end of file From d8d85ec5d9767171cfa0cc095a4e8bc2e14c7b06 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 18:05:04 +0800 Subject: [PATCH 230/545] update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9d60e2338..35538f60f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,4 @@ jdk: - oraclejdk7 - openjdk6 script: - mvn install -Dmaven.test.skip=false -fae \ No newline at end of file + mvn compile -DskipTests=true \ No newline at end of file From 4d7a09fb1777987809b22d8fcde2752090dd4a0e Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 29 Oct 2015 18:13:34 +0800 Subject: [PATCH 231/545] - --- .travis.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 35538f60f..e7969656e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,3 @@ language: java jdk: - - oraclejdk8 - - oraclejdk7 - - openjdk6 -script: - mvn compile -DskipTests=true \ No newline at end of file + - oraclejdk8 \ No newline at end of file From 8fb64cf52046f1ee7c63d62b5292ecabb6412303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5?= Date: Thu, 29 Oct 2015 20:48:21 +0800 Subject: [PATCH 232/545] Update pom.xml --- pom.xml | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2a97e966b..831b10d52 100644 --- a/pom.xml +++ b/pom.xml @@ -197,7 +197,35 @@ maven-release-plugin 2.4.1
+ + org.eluder.coveralls + coveralls-maven-plugin + 3.1.0 + + 8lXc2riIWKCpWIzRBxTitoZN667hYNdT3 + + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.6 + + UTF-8 + true + + xml + html + + + + **/*Test.class + + + + + - \ No newline at end of file + From 5a4a032ef8ee1bd8151ef6f8ed9b55661bc4a6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5?= Date: Thu, 29 Oct 2015 20:48:56 +0800 Subject: [PATCH 233/545] Update .travis.yml --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e7969656e..ae902f488 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ language: java jdk: - - oraclejdk8 \ No newline at end of file + - oraclejdk8 +after_success: + - mvn clean cobertura:cobertura coveralls:report From e917e7ca9f7a1c99993e66176c6b1a96218e9759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5?= Date: Thu, 29 Oct 2015 20:59:25 +0800 Subject: [PATCH 234/545] Update pom.xml --- pom.xml | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/pom.xml b/pom.xml index 831b10d52..5759fa271 100644 --- a/pom.xml +++ b/pom.xml @@ -197,34 +197,28 @@ maven-release-plugin 2.4.1 - - org.eluder.coveralls - coveralls-maven-plugin - 3.1.0 - - 8lXc2riIWKCpWIzRBxTitoZN667hYNdT3 - - - + org.codehaus.mojo cobertura-maven-plugin - 2.6 + 2.7 - UTF-8 + xml + 256m + true - - xml - html - - - - **/*Test.class - - - + + + + org.eluder.coveralls + coveralls-maven-plugin + 3.2.0 + + 8lXc2riIWKCpWIzRBxTitoZN667hYNdT3 + + From 921ccf21cfb9ea898ae5f37cbfec7ba26b7965f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5?= Date: Thu, 29 Oct 2015 20:59:56 +0800 Subject: [PATCH 235/545] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ae902f488..370795289 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,4 +2,4 @@ language: java jdk: - oraclejdk8 after_success: - - mvn clean cobertura:cobertura coveralls:report + - mvn cobertura:cobertura coveralls:report From ba98b2169a1872e0e8622b42c2466fcde23c96ba Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 10:06:57 +0800 Subject: [PATCH 236/545] add comment --- blade-core/src/main/java/com/blade/Blade.java | 27 ++++++++++------- .../main/java/com/blade/annotation/After.java | 10 +++---- .../java/com/blade/annotation/Before.java | 10 +++---- .../java/com/blade/annotation/Component.java | 5 +++- .../java/com/blade/annotation/Inject.java | 8 +++-- .../com/blade/annotation/Interceptor.java | 2 +- .../main/java/com/blade/annotation/Path.java | 11 +++---- .../main/java/com/blade/ioc/Container.java | 8 +++-- .../java/com/blade/render/BeetlRender.java | 5 ++++ .../java/com/blade/render/JetbrickRender.java | 4 +-- .../java/com/blade/render/ModelAndView.java | 5 ++-- .../java/com/blade/render/VelocityRender.java | 8 ++--- .../java/com/blade/route/RouteBuilder.java | 2 -- .../servlet/multipart/MultipartReader.java | 2 +- .../com/blade/verify/CSRFTokenManager.java | 29 ++++++++++--------- 15 files changed, 77 insertions(+), 59 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index f69b95f41..326fdb6dc 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -215,6 +215,7 @@ private void configuration(Map configMap){ * 可传入多个包,所有的路由类都在该包下 * * @param packages 路由包路径 + * @return 返回Blade单例实例 */ public Blade routes(String...packages){ if(null != packages && packages.length >0){ @@ -228,6 +229,7 @@ public Blade routes(String...packages){ * 如上规则,会超找com.bladejava.route、com.bladejava.interceptor下的路由和拦截器 * * @param basePackage 默认包路径 + * @return 返回Blade单例实例 */ public Blade defaultRoute(String basePackage){ if(null != basePackage){ @@ -240,6 +242,7 @@ public Blade defaultRoute(String basePackage){ * 设置拦截器所在的包路径,如:com.bladejava.interceptor * * @param packageName 拦截器所在的包 + * @return 返回Blade单例实例 */ public Blade interceptor(String packageName) { if(null != packageName && packageName.length() >0){ @@ -252,6 +255,7 @@ public Blade interceptor(String packageName) { * 设置依赖注入包,如:com.bladejava.service * * @param packages 所有需要做注入的包,可传入多个 + * @return 返回Blade单例实例 */ public Blade ioc(String...packages){ if(null != packages && packages.length >0){ @@ -292,7 +296,7 @@ public Blade addRoute(String path, Object target, String method){ * @param path 路由路径 * @param target 路由执行的目标对象 * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) - * @param httpMethod + * @param httpMethod HTTP请求方法 * @return 返回Blade单例实例 */ @Deprecated @@ -306,7 +310,7 @@ public Blade addRoute(String path, Object target, String method, HttpMethod http * @param path 路由路径 * @param target 路由执行的目标对象 * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) - * @param httpMethod + * @param httpMethod HTTP方法 * @return 返回Blade单例实例 */ public Blade route(String path, Object target, String method, HttpMethod httpMethod){ @@ -333,7 +337,7 @@ public Blade route(String path, Class clazz, String method){ * * @param path 路由url * @param clazz 路由处理类 - * @param methodName 路由处理方法名称 + * @param method 路由处理方法名称 * @param httpMethod 请求类型,GET/POST * @return Blade 返回Blade单例实例 */ @@ -465,7 +469,7 @@ public Blade viewPrefix(final String prefix) { /** * 设置视图默认后缀名,默认为.jsp * - * @param viewExt 视图后缀,如:.html .vm + * @param suffix 视图后缀,如:.html .vm * @return 返回Blade单例实例 */ public Blade viewSuffix(final String suffix) { @@ -510,13 +514,13 @@ public Blade enableXSS(boolean enableXSS){ return this; } - /** + /** * 动态设置全局初始化类 * * @param bootstrap 全局初始化bladeApplication * @return 返回Blade单例实例 */ - public Blade app(Bootstrap bootstrap){ + public Blade app(Bootstrap bootstrap){ this.bootstrap = bootstrap; return this; } @@ -527,7 +531,7 @@ public Blade app(Bootstrap bootstrap){ * @param bootstrap 全局初始化bladeApplication * @return 返回Blade单例实例 */ - public Blade app(Class bootstrap){ + public Blade app(Class bootstrap){ this.bootstrap = (Bootstrap) ReflectKit.newInstance(bootstrap); return this; } @@ -591,7 +595,6 @@ public Blade listen(int port){ * 设置jetty启动上下文 * * @param contextPath 设置上下文contextPath,默认/ - * @return 返回Blade单例实例 */ public void start(String contextPath) { try { @@ -622,8 +625,8 @@ public void stop() { /** * join in server - * @throws InterruptedException - * @throws Exception + * + * @throws InterruptedException join异常 */ public void join() throws InterruptedException { bladeServer.join(); @@ -741,8 +744,10 @@ public boolean enableXSS(){ /** * 返回插件对象 + * * @param pluginClazz 插件class - * @return + * @param 泛型 + * @return 返回插件对象 */ @SuppressWarnings("unchecked") public T plugin(Class pluginClazz){ diff --git a/blade-core/src/main/java/com/blade/annotation/After.java b/blade-core/src/main/java/com/blade/annotation/After.java index 5da81bbd0..d2f5a4bd0 100644 --- a/blade-core/src/main/java/com/blade/annotation/After.java +++ b/blade-core/src/main/java/com/blade/annotation/After.java @@ -24,7 +24,7 @@ * 拦截器后置事件注解,写在方法上 * 如: *
- *  @After("")
+ *  {@link After}
  *	public void after(Request request){...}
  * 
* @@ -36,19 +36,17 @@ public @interface After { /** - * 后置事件要拦截的URL + * @return 后置事件要拦截的URL */ String value() default ""; /** - * 路由后缀 - * @return String + * @return 路由后缀 */ String suffix() default ""; /** - * 多个前置拦截 - * @return + * @return 多个前置拦截 */ String[] values() default {}; } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/Before.java b/blade-core/src/main/java/com/blade/annotation/Before.java index e74f64f57..6b497f435 100644 --- a/blade-core/src/main/java/com/blade/annotation/Before.java +++ b/blade-core/src/main/java/com/blade/annotation/Before.java @@ -24,7 +24,7 @@ * 拦截器前置事件注解,写在方法上 * 如: *
- *  @Before("")
+ *  {@link Before}
  *	public void before(Request request){...}
  *
* @@ -36,19 +36,17 @@ public @interface Before { /** - * 前置事件要拦截的URL + * @return 前置事件要拦截的URL */ String value() default ""; /** - * 路由后缀 - * @return String + * @return 路由后缀 */ String suffix() default ""; /** - * 多个后置拦截 - * @return + * @return 多个前置拦截 */ String[] values() default {}; } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/Component.java b/blade-core/src/main/java/com/blade/annotation/Component.java index c2bdffdea..560f1322b 100644 --- a/blade-core/src/main/java/com/blade/annotation/Component.java +++ b/blade-core/src/main/java/com/blade/annotation/Component.java @@ -21,8 +21,11 @@ import java.lang.annotation.Target; /** - * 可以被注入的bean注解 * + *

+ * 可以被注入的bean注解 + *

+ * * @author biezhi * @since 1.0 */ diff --git a/blade-core/src/main/java/com/blade/annotation/Inject.java b/blade-core/src/main/java/com/blade/annotation/Inject.java index 48805477b..d0b8afcad 100644 --- a/blade-core/src/main/java/com/blade/annotation/Inject.java +++ b/blade-core/src/main/java/com/blade/annotation/Inject.java @@ -21,8 +21,11 @@ import java.lang.annotation.Target; /** - * 自动注入接口 * + *

+ * 自动注入 + *

+ * * @author biezhi * @since 1.0 */ @@ -31,8 +34,7 @@ public @interface Inject { /** - * 要注入的类类型 - * @return class + * @return 要注入的类类型 */ Class value() default Class.class; diff --git a/blade-core/src/main/java/com/blade/annotation/Interceptor.java b/blade-core/src/main/java/com/blade/annotation/Interceptor.java index f54fa1929..ac92f7c17 100644 --- a/blade-core/src/main/java/com/blade/annotation/Interceptor.java +++ b/blade-core/src/main/java/com/blade/annotation/Interceptor.java @@ -24,7 +24,7 @@ * 拦截器注解,写在类上 * 如: *
- * @Interceptor
+ * {@link Interceptor}
  * public class BaseInterceptor {...}
  * 
* @author biezhi diff --git a/blade-core/src/main/java/com/blade/annotation/Path.java b/blade-core/src/main/java/com/blade/annotation/Path.java index 6ffa13dbe..23b7ad3e7 100644 --- a/blade-core/src/main/java/com/blade/annotation/Path.java +++ b/blade-core/src/main/java/com/blade/annotation/Path.java @@ -21,8 +21,11 @@ import java.lang.annotation.Target; /** - * 路由类注解,标识一个类是否是路由 * + *

+ * 路由类注解,标识一个类是否是路由 + *

+ * * @author biezhi * @since 1.0 */ @@ -32,14 +35,12 @@ public @interface Path{ /** - * 命名空间 - * @return String + * @return 命名空间 */ String value() default "/"; /** - * 路由后缀 - * @return String + * @return 路由后缀 */ String suffix() default ""; diff --git a/blade-core/src/main/java/com/blade/ioc/Container.java b/blade-core/src/main/java/com/blade/ioc/Container.java index 61f85176e..3c2164269 100644 --- a/blade-core/src/main/java/com/blade/ioc/Container.java +++ b/blade-core/src/main/java/com/blade/ioc/Container.java @@ -34,6 +34,7 @@ public interface Container { * * @param name bean名称,可以是类名 * @param scope 对象作用域,单例或者每次都创建 + * @param 泛型 * @return 一个bean对象 */ T getBean(String name, Scope scope); @@ -43,6 +44,7 @@ public interface Container { * * @param type class类型 * @param scope 对象作用域,单例或者每次都创建 + * @param 泛型 * @return 一个bean对象 */ T getBean(Class type, Scope scope); @@ -53,6 +55,7 @@ public interface Container { Set getBeanNames(); /** + * @param 泛型 * @return 返回所有bean的集合 */ Collection getBeans(); @@ -69,6 +72,7 @@ public interface Container { * 根据注解获取ioc容器中匹配的bean对象集合 * * @param annotation annotation class类型 + * @param 泛型 * @return 返回符合annotation class类型的所有bean */ List getBeansByAnnotation(Class annotation); @@ -147,8 +151,8 @@ public interface Container { void initWired(); /** - * 注入一个类 - * @param object + * 注入一个object + * @param object 要注入的object */ void injection(Object object); diff --git a/blade-core/src/main/java/com/blade/render/BeetlRender.java b/blade-core/src/main/java/com/blade/render/BeetlRender.java index 5443d4284..a914dcb72 100644 --- a/blade-core/src/main/java/com/blade/render/BeetlRender.java +++ b/blade-core/src/main/java/com/blade/render/BeetlRender.java @@ -73,6 +73,11 @@ public BeetlRender() { } } + public BeetlRender(GroupTemplate groupTemplate) { + blade = Blade.me(); + this.groupTemplate = groupTemplate; + } + public BeetlRender(Configuration configuration) { try { blade = Blade.me(); diff --git a/blade-core/src/main/java/com/blade/render/JetbrickRender.java b/blade-core/src/main/java/com/blade/render/JetbrickRender.java index 02258211b..122943ff2 100644 --- a/blade-core/src/main/java/com/blade/render/JetbrickRender.java +++ b/blade-core/src/main/java/com/blade/render/JetbrickRender.java @@ -95,8 +95,8 @@ public void put(String key, Object value){ /** * 根据配置文件构造一个JetEngine引擎 * - * @param configLocation - * @throws IOException + * @param configLocation 配置文件路径 + * @throws IOException 抛出IO异常 */ public JetbrickRender(String configLocation) throws IOException { this.blade = Blade.me(); diff --git a/blade-core/src/main/java/com/blade/render/ModelAndView.java b/blade-core/src/main/java/com/blade/render/ModelAndView.java index 2ac98b581..0c8c39581 100644 --- a/blade-core/src/main/java/com/blade/render/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/render/ModelAndView.java @@ -92,7 +92,7 @@ public String getView() { /** * 设置视图 - * @param view + * @param view 视图文件名称 */ public void setView(String view) { this.view = view; @@ -107,7 +107,8 @@ public Map getModel() { /** * 设置model - * @param model + * + * @param model 存放数据的map */ public void setModel(Map model) { this.model = model; diff --git a/blade-core/src/main/java/com/blade/render/VelocityRender.java b/blade-core/src/main/java/com/blade/render/VelocityRender.java index 71b3652b8..c7ce21fc5 100644 --- a/blade-core/src/main/java/com/blade/render/VelocityRender.java +++ b/blade-core/src/main/java/com/blade/render/VelocityRender.java @@ -68,8 +68,8 @@ public VelocityRender() { /** * 根据配置文件构造一个Velocity引擎 * - * @param propertiesFile - * @throws IOException + * @param propertiesFile properties文件路径 + * @throws IOException 抛出IO异常 */ public VelocityRender(String propertiesFile) throws IOException { blade = Blade.me(); @@ -90,7 +90,7 @@ public VelocityRender(String propertiesFile) throws IOException { /** * 根据构造一个Velocity引擎 * - * @param properties + * @param properties Properties配置文件 */ public VelocityRender(Properties properties) { blade = Blade.me(); @@ -100,7 +100,7 @@ public VelocityRender(Properties properties) { /** * 手动构造Velocity引擎 * - * @param velocityEngine + * @param velocityEngine velocity引擎对象 */ public VelocityRender(VelocityEngine velocityEngine) { blade = Blade.me(); diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index e7350b1cc..bfbf79611 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -74,8 +74,6 @@ public RouteBuilder(Blade blade) { /** * 开始构建路由 - * - * @return 返回构建路由后的构造器 */ public void building() { String basePackage = blade.basePackage(); diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java index 3d6994bed..47ad9c953 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java +++ b/blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java @@ -42,7 +42,7 @@ * header-part := 1*header CRLF
* header := header-name ":" header-value
* header-name := <printable ascii characters except ":">
- * header-value := <any ascii characters except CR & LF>
+ * header-value := <any ascii characters except CR & LF>
* body-data := <arbitrary data>
* * diff --git a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java index 7cea37015..d9cc619f2 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java @@ -50,9 +50,10 @@ public static void config(CSRFConfig config){ /** * 创建一个token - * @param request - * @param response - * @return + * + * @param request 请求对象 + * @param response 响应对象 + * @return 返回token令牌 */ public static String createToken(Request request, Response response) { String token = null; @@ -78,9 +79,10 @@ public static String createToken(Request request, Response response) { /** * 根据表单参数验证 - * @param request - * @param response - * @return + * + * @param request 请求对象 + * @param response 响应对象 + * @return 返回是否验证成功 */ public static boolean verifyAsForm(Request request, Response response) { // 从 session 中得到 csrftoken 属性 @@ -101,9 +103,10 @@ public static boolean verifyAsForm(Request request, Response response) { /** * 根据头信息验证 - * @param request - * @param response - * @return + * + * @param request 请求对象 + * @param response 响应对象 + * @return 返回是否验证成功 */ public static boolean verifyAsHeader(Request request, Response response) { // 从 session 中得到 csrftoken 属性 @@ -124,9 +127,10 @@ public static boolean verifyAsHeader(Request request, Response response) { /** * 根据cookie验证 - * @param request - * @param response - * @return + * + * @param request 请求对象 + * @param response 响应对象 + * @return 返回是否验证成功 */ public static boolean verifyAsCookie(Request request, Response response) { // 从 session 中得到 csrftoken 属性 @@ -141,7 +145,6 @@ public static boolean verifyAsCookie(Request request, Response response) { return true; } } - return false; } From c993665a7e663c47a2adf87e9bce1dfeb87f2009 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 10:31:39 +0800 Subject: [PATCH 237/545] test for junit --- blade-core/pom.xml | 6 +- .../test/java/com/blade/BladeTestCase.java | 4 +- .../com/blade/servlet/ServletRequestTest.java | 4 +- .../main/java/blade/kit/CollectionKit.java | 26 +- .../src/main/java/blade/kit/DateKit.java | 16 +- pom.xml | 305 ++++++++---------- 6 files changed, 170 insertions(+), 191 deletions(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 292737f53..93bf84621 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -67,10 +67,8 @@ provided - org.testng - testng - 6.8.8 - test + junit + junit org.mockito diff --git a/blade-core/src/test/java/com/blade/BladeTestCase.java b/blade-core/src/test/java/com/blade/BladeTestCase.java index 92a00893d..b7e965b08 100644 --- a/blade-core/src/test/java/com/blade/BladeTestCase.java +++ b/blade-core/src/test/java/com/blade/BladeTestCase.java @@ -20,8 +20,8 @@ import org.apache.http.HttpResponse; import org.apache.http.client.fluent.Request; -import org.testng.Assert; -import org.testng.annotations.Test; +import org.junit.Assert; +import org.junit.Test; public class BladeTestCase { diff --git a/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java b/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java index 534747a0c..ddc2772aa 100644 --- a/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java +++ b/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java @@ -15,8 +15,8 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; -import org.testng.Assert; -import org.testng.annotations.Test; +import org.junit.Assert; +import org.junit.Test; import com.blade.MockController; import com.blade.http.HttpMethod; diff --git a/blade-kit/src/main/java/blade/kit/CollectionKit.java b/blade-kit/src/main/java/blade/kit/CollectionKit.java index cf539946d..7af5afa44 100644 --- a/blade-kit/src/main/java/blade/kit/CollectionKit.java +++ b/blade-kit/src/main/java/blade/kit/CollectionKit.java @@ -1123,8 +1123,7 @@ public static ConcurrentSkipListMap createConcurrentSkipListMap(Sor /** * 创建ConcurrentSkipListSet实例 * - * @param - * @param + * @param 泛型 * @return ConcurrentSkipListSet实例 */ public static ConcurrentSkipListSet createConcurrentSkipListSet() { @@ -1134,8 +1133,7 @@ public static ConcurrentSkipListSet createConcurrentSkipListSet() { /** * 创建ConcurrentSkipListSet实例 * - * @param - * @param + * @param 泛型 * @param collection 集合 @see Collection * @return ConcurrentSkipListSet实例 */ @@ -1150,8 +1148,7 @@ public static ConcurrentSkipListSet createConcurrentSkipListSet(Collectio /** * 创建ConcurrentSkipListSet实例 * - * @param - * @param + * @param 泛型 * @param comparator 比较器 @see Comparator * @return ConcurrentSkipListSet实例 */ @@ -1166,8 +1163,7 @@ public static ConcurrentSkipListSet createConcurrentSkipListSet(Comparato /** * 创建ConcurrentSkipListSet实例 * - * @param - * @param + * @param 泛型 * @param set 可排序的散列 @see SortedSet * @return ConcurrentSkipListSet实例 */ @@ -1182,7 +1178,7 @@ public static ConcurrentSkipListSet createConcurrentSkipListSet(SortedSet /** * 创建ConcurrentLinkedQueue实例 * - * @param + * @param 泛型 * @return ConcurrentLinkedQueue实例 */ public static Queue createConcurrentLinkedQueue() { @@ -1192,7 +1188,7 @@ public static Queue createConcurrentLinkedQueue() { /** * 创建ConcurrentLinkedQueue实例 * - * @param + * @param 泛型 * @param collection 集合 @see Collection * @return ConcurrentLinkedQueue实例 */ @@ -1207,7 +1203,7 @@ public static Queue createConcurrentLinkedQueue(Collection c /** * 创建CopyOnWriteArrayList实例 * - * @param + * @param 泛型 * @return CopyOnWriteArrayList实例 */ public static CopyOnWriteArrayList createCopyOnWriteArrayList() { @@ -1217,7 +1213,7 @@ public static CopyOnWriteArrayList createCopyOnWriteArrayList() { /** * 创建CopyOnWriteArrayList实例 * - * @param + * @param 泛型 * @param collection 集合 @see Collection * * @return CopyOnWriteArrayList实例 @@ -1233,7 +1229,7 @@ public static CopyOnWriteArrayList createCopyOnWriteArrayList(Collection< /** * 创建CopyOnWriteArrayList实例 * - * @param + * @param 泛型 * @param toCopyIn 创建一个保存给定数组的副本的数组 * * @return CopyOnWriteArrayList实例 @@ -1249,7 +1245,7 @@ public static CopyOnWriteArrayList createCopyOnWriteArrayList(E[] toCopyI /** * 创建CopyOnWriteArraySet实例 * - * @param + * @param 泛型 * @return CopyOnWriteArraySet实例 */ public static CopyOnWriteArraySet createCopyOnWriteArraySet() { @@ -1259,7 +1255,7 @@ public static CopyOnWriteArraySet createCopyOnWriteArraySet() { /** * 创建CopyOnWriteArraySet实例 * - * @param + * @param 泛型 * @param collection 集合 @see Collection * * @return CopyOnWriteArraySet实例 diff --git a/blade-kit/src/main/java/blade/kit/DateKit.java b/blade-kit/src/main/java/blade/kit/DateKit.java index a3c7f78d0..437cb7179 100644 --- a/blade-kit/src/main/java/blade/kit/DateKit.java +++ b/blade-kit/src/main/java/blade/kit/DateKit.java @@ -24,7 +24,10 @@ import java.util.List; /** + * + *

* 日期处理类 + *

* * @author biezhi * @since 1.0 @@ -35,31 +38,37 @@ public class DateKit { * 日 */ public final static int INTERVAL_DAY = 1; + /** * 周 */ public final static int INTERVAL_WEEK = 2; + /** * 月 */ public final static int INTERVAL_MONTH = 3; + /** * 年 */ public final static int INTERVAL_YEAR = 4; + /** * 小时 */ public final static int INTERVAL_HOUR = 5; + /** * 分钟 */ public final static int INTERVAL_MINUTE = 6; + /** * 秒 */ public final static int INTERVAL_SECOND = 7; - + /** * date = 1901-01-01 */ @@ -68,9 +77,8 @@ public class DateKit { /** * 测试是否是当天 * - * @param date - * - 某一日期 - * @return true-今天, false-不是 + * @param date 某一日期 + * @return true 今天, false-不是 */ @SuppressWarnings("deprecation") public static boolean isToday(Date date) { diff --git a/pom.xml b/pom.xml index 5759fa271..e86bd9461 100644 --- a/pom.xml +++ b/pom.xml @@ -12,78 +12,64 @@ https://github.com/biezhi/blade - - release - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - package - - jar-no-fork - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - package - - jar - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - verify - - sign - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6 - true - - sonatype-nexus-staging - https://oss.sonatype.org/ - true - - - - - - - sonatype-nexus-snapshots - https://oss.sonatype.org/content/repositories/snapshots/ - - - sonatype-nexus-staging - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - + + release + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + package + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + verify + + sign + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6 + true + + sonatype-nexus-staging + https://oss.sonatype.org/ + true + + + + + + + sonatype-nexus-snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + + sonatype-nexus-staging + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + 1.6 1.6 @@ -128,98 +114,89 @@ - - org.apache.maven.plugins - maven-surefire-plugin - - pertest - -Xms1024m -Xmx1024m -Xss1m - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.6 - 1.6 - UTF-8 - - - - org.apache.maven.plugins - maven-resources-plugin - 2.6 - - UTF-8 - - - - org.apache.maven.plugins - maven-jar-plugin - - - log4j.xml - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - UTF-8 - - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-release-plugin - 2.4.1 - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - xml - 256m - - true - - - - - - org.eluder.coveralls - coveralls-maven-plugin - 3.2.0 - - 8lXc2riIWKCpWIzRBxTitoZN667hYNdT3 - - - + + + org.apache.maven.plugins + maven-surefire-plugin + + pertest + -Xms1024m -Xmx1024m -Xss1m + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + UTF-8 + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + + UTF-8 + + + + + org.apache.maven.plugins + maven-jar-plugin + + + log4j.xml + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar + + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.4.1 + + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + xml + 256m + + true + + + + + + org.eluder.coveralls + coveralls-maven-plugin + 3.2.0 + + 8lXc2riIWKCpWIzRBxTitoZN667hYNdT3 + + + From b8d02cabf6e5b52100ffc4ecf59d0fc38ac892b2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 10:32:28 +0800 Subject: [PATCH 238/545] add compile jdk7,jdk6 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 370795289..2c5d974bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: java jdk: - oraclejdk8 + - oraclejdk7 + - oraclejdk6 after_success: - mvn cobertura:cobertura coveralls:report From 599ae0e5b9ae28a7e4588c3ccca776ca0e985fae Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 10:34:54 +0800 Subject: [PATCH 239/545] update jetty version --- blade-core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 93bf84621..c0bdc2fd8 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -16,7 +16,7 @@ https://github.com/biezhi/blade/blade-core - 9.3.4.v20151007 + 8.1.15.v20140411 2.0.12 2.2.3 1.7 From 01d165bb4bf4056b1199881188335620a823c5b7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 10:42:09 +0800 Subject: [PATCH 240/545] update oraclejdk6 to openjdk6 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2c5d974bf..407ba9d05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,6 @@ language: java jdk: - oraclejdk8 - oraclejdk7 - - oraclejdk6 + - openjdk6 after_success: - mvn cobertura:cobertura coveralls:report From 30c91b50f17867a66d4bae9635276dd5ae5237df Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 10:46:01 +0800 Subject: [PATCH 241/545] update pom.xml --- pom.xml | 109 -------------------------------------------------------- 1 file changed, 109 deletions(-) diff --git a/pom.xml b/pom.xml index e86bd9461..a80308885 100644 --- a/pom.xml +++ b/pom.xml @@ -11,65 +11,6 @@ blade-root https://github.com/biezhi/blade - - - release - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - package - - jar-no-fork - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - verify - - sign - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6 - true - - sonatype-nexus-staging - https://oss.sonatype.org/ - true - - - - - - - sonatype-nexus-snapshots - https://oss.sonatype.org/content/repositories/snapshots/ - - - sonatype-nexus-staging - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - 1.6 1.6 @@ -114,16 +55,6 @@ - - - org.apache.maven.plugins - maven-surefire-plugin - - pertest - -Xms1024m -Xmx1024m -Xss1m - - - org.apache.maven.plugins maven-compiler-plugin @@ -134,46 +65,6 @@ UTF-8 - - - org.apache.maven.plugins - maven-resources-plugin - 2.6 - - UTF-8 - - - - - org.apache.maven.plugins - maven-jar-plugin - - - log4j.xml - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar - - - - - - - org.apache.maven.plugins - maven-release-plugin - 2.4.1 - - org.codehaus.mojo From 822bcebb198fa4ad8e15ebf52d6b30e1b1688dee Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 10:50:55 +0800 Subject: [PATCH 242/545] update pom.xml --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index a80308885..5e05fe955 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,11 @@ UTF-8 + + org.apache.maven.plugins + maven-surefire-plugin + 2.14.1 + org.codehaus.mojo From d481a15956a26335a9f969668b198f7dafafe662 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 10:57:56 +0800 Subject: [PATCH 243/545] - --- .travis.yml | 1 - pom.xml | 5 ----- 2 files changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 407ba9d05..abf532887 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,5 @@ language: java jdk: - oraclejdk8 - oraclejdk7 - - openjdk6 after_success: - mvn cobertura:cobertura coveralls:report diff --git a/pom.xml b/pom.xml index 5e05fe955..a80308885 100644 --- a/pom.xml +++ b/pom.xml @@ -65,11 +65,6 @@ UTF-8 - - org.apache.maven.plugins - maven-surefire-plugin - 2.14.1 - org.codehaus.mojo From 8a32676f822dceec0773d4e23209f91649eca330 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 11:20:42 +0800 Subject: [PATCH 244/545] add testcase --- .../test/java/com/blade/servlet/ServletRequestTest.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java b/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java index ddc2772aa..fab1b8ea0 100644 --- a/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java +++ b/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java @@ -248,7 +248,7 @@ public void testRetrieveEmptyCookies() throws Exception { } @Test - public void shoudlRetrieveHeader() throws Exception { + public void testRetrieveHeader() throws Exception { HttpServletRequest servletRequest = mockServletRequest(); when(servletRequest.getHeader("Authorization")).thenReturn("Basic ..."); @@ -299,12 +299,7 @@ private static void fixMultipartLineSeparators(String fileName) throws IOExcepti } } - public static void main(String... args) throws IOException { - //Warning - //Be carefull if shouldRetrieveSingleFile or shouldRetrieveMultipleFiles fail is probably because - //your system change the line endings in the associated txt files.HTTP Multipart use CRLF as line ending - //while Unix like systems use only LF. - //If that is the problem runnign this main will fix it ;) + public static void main(String[] args) throws IOException { fixMultipartLineSeparators("single-file"); fixMultipartLineSeparators("multiple-files"); } From a07b81e3a99d079dd9b81f73dd110faf4501c77d Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 11:21:04 +0800 Subject: [PATCH 245/545] add servletResponse testcase --- .../blade/servlet/ServletResponseTest.java | 193 ++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 blade-core/src/test/java/com/blade/servlet/ServletResponseTest.java diff --git a/blade-core/src/test/java/com/blade/servlet/ServletResponseTest.java b/blade-core/src/test/java/com/blade/servlet/ServletResponseTest.java new file mode 100644 index 000000000..b8c9ea44e --- /dev/null +++ b/blade-core/src/test/java/com/blade/servlet/ServletResponseTest.java @@ -0,0 +1,193 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Map; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.junit.Assert; +import org.junit.Test; + +import com.blade.http.HttpStatus; +import com.blade.http.Response; +import com.blade.render.ModelAndView; +import com.blade.render.Render; + +public class ServletResponseTest { + + @Test + public void testRetrieveStatus() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletResponse.getStatus()).thenReturn(400); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + Assert.assertEquals(response.status(), 400); + } + + @Test + public void testSetStatus() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + response.status(400); + + verify(servletResponse).setStatus(400); + } + + @Test + public void testSetBadRequest() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + response.badRequest(); + + verify(servletResponse).setStatus(HttpStatus.BAD_REQUEST); + } + + @Test + public void testSetUnauthorized() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + response.unauthorized(); + + verify(servletResponse).setStatus(HttpStatus.UNAUTHORIZED); + } + + @Test + public void testRetrieveContentType() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletResponse.getContentType()).thenReturn("application/json"); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + Assert.assertEquals(response.contentType(), "application/json"); + } + + @Test + public void testSetContentType() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + response.contentType("application/json"); + + verify(servletResponse).setContentType("application/json"); + } + + @Test + public void testRetrieveHeader() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletResponse.getHeader("Authorization")).thenReturn("Basic"); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + Assert.assertEquals(response.header("Authorization"), "Basic"); + } + + @Test + public void testSetHeader() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + response.header("Authorization", "Basic"); + + verify(servletResponse).setHeader("Authorization", "Basic"); + } + + @Test + public void testSetCookie() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + response.cookie(new Cookie("test-1", "1")); + + verify(servletResponse).addCookie(any(javax.servlet.http.Cookie.class)); + } + + @Test + public void testRemoveCookie() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + response.removeCookie(new Cookie("test-1", "1")); + + verify(servletResponse).addCookie(any(javax.servlet.http.Cookie.class)); + } + + @Test + public void testSetAndGetAttributes() throws Exception { + Response response = new ServletResponse(mock(HttpServletResponse.class), mock(Render.class)); + response.attribute("test-1", "1"); + + Map atts = response.attributes(); + + Assert.assertNotNull(atts); + Assert.assertEquals(atts.size(), 1); + Assert.assertEquals(atts.get("test-1"), "1"); + } + + @Test + public void testFailWhenTryingToSetNullAttributeName() throws Exception { + Response response = new ServletResponse(mock(HttpServletResponse.class), mock(Render.class)); + response.attribute(null, "1"); + } + + @Test + public void testFailWhenTryingToSetNullAttributeValue() throws Exception { + Response response = new ServletResponse(mock(HttpServletResponse.class), mock(Render.class)); + response.attribute("test-1", null); + + } + + @Test + public void testWriteOutput() throws Exception { + PrintWriter writer = mock(PrintWriter.class); + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + when(servletResponse.getWriter()).thenReturn(writer); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + response.text("test"); + + verify(writer).print("test"); + } + + @Test + public void testRenderTemplate() throws Exception { + Render render = mock(Render.class); + + Response response = new ServletResponse(mock(HttpServletResponse.class), render); + response.render("template"); + + verify(render).render( any(ModelAndView.class), any(Writer.class)); + } + + @Test + public void testRedirect() throws Exception { + HttpServletResponse servletResponse = mock(HttpServletResponse.class); + + Response response = new ServletResponse(servletResponse, mock(Render.class)); + response.redirect("/"); + + verify(servletResponse).sendRedirect("/"); + } +} \ No newline at end of file From e985696be851e4dab4bd825a6c8957e0ea126033 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 11:29:34 +0800 Subject: [PATCH 246/545] add blade-kit test code --- .../java/com/blade/kit/HttpRequestTest.java | 33 +++++++++++ .../src/test/java/com/blade/kit/JSONTest.java | 59 +++++++++++++++++++ .../src/test/java/com/blade/kit/LogTest.java | 19 ++++++ .../src/test/java/com/blade/kit/MailTest.java | 36 +++++++++++ .../test/java/com/blade/kit/StringTest.java | 36 +++++++++++ .../src/test/java/com/blade/kit/TaskTest.java | 35 +++++++++++ .../src/test/java/com/blade/kit/User.java | 32 ++++++++++ 7 files changed, 250 insertions(+) create mode 100644 blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java create mode 100644 blade-kit/src/test/java/com/blade/kit/JSONTest.java create mode 100644 blade-kit/src/test/java/com/blade/kit/LogTest.java create mode 100644 blade-kit/src/test/java/com/blade/kit/MailTest.java create mode 100644 blade-kit/src/test/java/com/blade/kit/StringTest.java create mode 100644 blade-kit/src/test/java/com/blade/kit/TaskTest.java create mode 100644 blade-kit/src/test/java/com/blade/kit/User.java diff --git a/blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java b/blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java new file mode 100644 index 000000000..d9a3dc03e --- /dev/null +++ b/blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java @@ -0,0 +1,33 @@ +package com.blade.kit; + +import java.io.File; + +import blade.kit.http.HttpRequest; + +public class HttpRequestTest { + + public static void main(String[] args) { + + // 发送一个GET请求并获取内容 + String body = HttpRequest.get("http://bladejava.com").body(); + System.out.println(body); + + // 发送一个带heder的请求 + String res = HttpRequest.get("http://bladejava.com").accept("application/json") + .userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0").body(); + System.out.println(res); + + // 发送一个POST请求 + HttpRequest.post("http://www.example.com").part("id", 20).part("name", "jack").body(); + + // 带认证的请求 + int response = HttpRequest.get("http://google.com").basic("username", "p4ssw0rd").code(); + System.out.println(response); + + // 下载一个图片 + File file = new File("F:/a.png"); + HttpRequest.get("http://img.blog.csdn.net/20150601232126808").receive(file); + + } + +} diff --git a/blade-kit/src/test/java/com/blade/kit/JSONTest.java b/blade-kit/src/test/java/com/blade/kit/JSONTest.java new file mode 100644 index 000000000..b66e5fccc --- /dev/null +++ b/blade-kit/src/test/java/com/blade/kit/JSONTest.java @@ -0,0 +1,59 @@ +package com.blade.kit; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import blade.kit.json.JSONKit; +import blade.kit.json.Json; +import blade.kit.json.JsonArray; +import blade.kit.json.JsonObject; +import blade.kit.json.JsonValue; + +public class JSONTest { + + public static void main(String[] args) { + //[{"text": "首页","href": "/"},{"text": "博客","href": "blog"},{"text": "关于","href": "about"},{"text": "联系","href": "contact"}] + String json = "[{\"text\": \"博客\",\"href\": \"blog\"}]"; + + // 下面构造两个map、一个list和一个Employee对象 + Map map1 = new HashMap(); + map1.put("name", "Alexia"); + map1.put("sex", "female"); + map1.put("age", "23"); + + List> list = new ArrayList>(); + Map map = new HashMap(); + + map.put("abc", "123456"); + map.put("def", "hmm"); + list.add(map); + + String string = JSONKit.toJSONString(list); + System.out.println(string); + + List list2 = Json.parse(json).asArray().values(); + System.out.println(list2); + + JsonObject obj1 = new JsonObject(); + obj1.add("name", "jack"); + + System.out.println(obj1); + + JsonArray obj2 = new JsonArray(); + obj2.add("123"); + + System.out.println(obj2); + + User u1 = new User(); + u1.setAge(22); + u1.setName("rose"); + + System.out.println(JSONKit.toJSONString(u1)); + +// User u = JSONKit.parse("{\"name\":\"jack\",\"age\":20}", User.class); +// System.out.println(u); + } + +} diff --git a/blade-kit/src/test/java/com/blade/kit/LogTest.java b/blade-kit/src/test/java/com/blade/kit/LogTest.java new file mode 100644 index 000000000..904e6d109 --- /dev/null +++ b/blade-kit/src/test/java/com/blade/kit/LogTest.java @@ -0,0 +1,19 @@ +package com.blade.kit; +import blade.kit.log.Logger; + + +public class LogTest { + + private static final Logger LOGGER = Logger.getLogger(LogTest.class); + + public static void main(String[] args) { +// LOGGER.setLevel(Level.INFO); + LOGGER.debug("debug hello"); + LOGGER.info("info hello %s", "aaa"); + LOGGER.warn("warn hello"); + + System.out.println(LOGGER.isDebugEnabled()); + System.out.println(LOGGER.isInfoEnabled()); + System.out.println(LOGGER.isErrorEnabled()); + } +} diff --git a/blade-kit/src/test/java/com/blade/kit/MailTest.java b/blade-kit/src/test/java/com/blade/kit/MailTest.java new file mode 100644 index 000000000..3edd7ff7f --- /dev/null +++ b/blade-kit/src/test/java/com/blade/kit/MailTest.java @@ -0,0 +1,36 @@ +package com.blade.kit; + +import java.io.IOException; + +import blade.kit.MailKit; +import blade.kit.mail.MailTemplate; + +public class MailTest { + + public static void main(String[] args) { + // 发送方配置,邮箱帐号和密码 + MailKit.config(MailKit.SMTP_QQ, "921293209@qq.com", "helloworld"); + + // 测试给【xxx@qq.com】发送邮件 + MailKit.send("xxx@qq.com", "测试发送邮件", "hello"); + + // 测试异步发送邮件 + MailKit.asynSend("xxx", "测试异步发送邮件", "hello"); + + // 测试给【xxx@qq.com】发送邮件并抄送给xoxo@qq.com + MailKit.sendAndCc("xxx@qq.com", "xoxo@qq.com", "测试发送邮件", "hello"); + + // 测试给【xxx@qq.com】发送邮件并带一个附件 + MailKit.send("xxx@qq.com", "测试发送邮件", "hello", "F:/aa.txt"); + + // 使用模板给【xxx@qq.com】发送邮件并带一个附件 + try { + MailTemplate template = new MailTemplate("F:/a.html", "xxx@qq.com", null); + MailKit.send(template, "新主题"); + } catch (IOException e) { + e.printStackTrace(); + } + + } + +} diff --git a/blade-kit/src/test/java/com/blade/kit/StringTest.java b/blade-kit/src/test/java/com/blade/kit/StringTest.java new file mode 100644 index 000000000..3b08574f5 --- /dev/null +++ b/blade-kit/src/test/java/com/blade/kit/StringTest.java @@ -0,0 +1,36 @@ +package com.blade.kit; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import blade.kit.StringKit; + + +public class StringTest { + + public static void main(String[] args) { + + //判断是否为空 + String str = "hello"; + System.out.println(StringKit.isNotEmpty(str)); + + //分割字符串 + String[] arr = StringKit.split("1,2,3", ","); + System.out.println(Arrays.toString(arr)); + + //生成5个随机字符串 + System.out.println(StringKit.random(5)); + + //将字符串20转换为long类型,如果为null或者空则给一个默认值10 + System.out.println(StringKit.toLong("20", 10)); + + List list = new ArrayList(); + list.add(22); + list.add(30); + //将集合用指定字符分隔 + String listString = StringKit.join(list, "|"); + System.out.println(listString); + } + +} diff --git a/blade-kit/src/test/java/com/blade/kit/TaskTest.java b/blade-kit/src/test/java/com/blade/kit/TaskTest.java new file mode 100644 index 000000000..5fd0f02b0 --- /dev/null +++ b/blade-kit/src/test/java/com/blade/kit/TaskTest.java @@ -0,0 +1,35 @@ +package com.blade.kit; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +import blade.kit.TaskKit; + + +public class TaskTest { + + public static void main(String[] args) { + TaskKit.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + System.out.println("每隔两秒执行一次"); + } + }, 2); + + TaskKit.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + System.out.println("在指定的延时之后开始以固定的频率来运行任务。后续任务的启动时间不受前次任务延时影响。"); + } + }, 10, 3, TimeUnit.SECONDS); + + TaskKit.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + System.out.println("在指定的时间点启动,两次任务间保持固定的时间间隔"); + } + }, new Date(), 3, TimeUnit.SECONDS); + + } + +} diff --git a/blade-kit/src/test/java/com/blade/kit/User.java b/blade-kit/src/test/java/com/blade/kit/User.java new file mode 100644 index 000000000..d2ce61c2b --- /dev/null +++ b/blade-kit/src/test/java/com/blade/kit/User.java @@ -0,0 +1,32 @@ +package com.blade.kit; + +public class User { + + private String name; + private long age; + + public User() { + // TODO Auto-generated constructor stub + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getAge() { + return age; + } + + public void setAge(long age) { + this.age = age; + } + + @Override + public String toString() { + return "User [name=" + name + ", age=" + age + "]"; + } +} \ No newline at end of file From 68ce361645ba1651318a05a6a968441932bfa8e9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 11:47:34 +0800 Subject: [PATCH 247/545] update LAST_VERSION --- LAST_VERSION.md | 4 +- README.md | 3 +- README_CN.md | 3 +- blade-core/pom.xml | 4 +- blade-kit/pom.xml | 94 +++++++++++++++++++++++----------------------- pom.xml | 2 +- 6 files changed, 56 insertions(+), 54 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index fb7a40fc8..d58a972ea 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -23,7 +23,7 @@     com.bladejava     blade-kit -    1.2.7 +    1.2.8-alpha ``` @@ -32,7 +32,7 @@     com.bladejava     blade-core -    1.4.1-alpha +    1.4.1-beta ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/README.md b/README.md index 5d6f9c0bd..0c3836ba6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ [![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) -[![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![maven-central](https://maven-badges.herokuapp.com/maven-central/com.bladejava/blade-core/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [中文](https://github.com/biezhi/blade/blob/master/README_CN.md) diff --git a/README_CN.md b/README_CN.md index 7cf7ecc32..981855f2d 100644 --- a/README_CN.md +++ b/README_CN.md @@ -2,7 +2,8 @@ [![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) [![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) -[![release](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![maven-central](https://maven-badges.herokuapp.com/maven-central/com.bladejava/blade-core/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) [English](https://github.com/biezhi/blade/blob/master/README.md) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index c0bdc2fd8..8dd0e57df 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -11,7 +11,7 @@ blade-core jar - 1.4.1-alpha + ${blade.version} blade-core https://github.com/biezhi/blade/blade-core @@ -28,7 +28,7 @@ com.bladejava blade-kit - 1.2.7 + 1.2.8-alpha javax.servlet diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index dbd1cfbf9..8c7b8ba90 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -1,47 +1,47 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-kit - jar - 1.2.7 - blade-kit - https://github.com/biezhi/blade/tree/master/blade-kit - - - 3.0.1 - - - - - junit - junit - - - javax.mail - mail - 1.5.0-b01 - provided - - - log4j - log4j - 1.2.17 - provided - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - - + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + + blade-kit + jar + 1.2.8-alpha + blade-kit + https://github.com/biezhi/blade/tree/master/blade-kit + + + 3.0.1 + + + + + junit + junit + + + javax.mail + mail + 1.5.0-b01 + provided + + + log4j + log4j + 1.2.17 + provided + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + + diff --git a/pom.xml b/pom.xml index a80308885..1e8011d4e 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ 1.6 UTF-8 3.0.1 - 1.4.1-alpha + 1.4.1-beta 4.12 From fbbdac5b58b8a7b405feccf96a9df592fd1e6fe3 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 17:32:53 +0800 Subject: [PATCH 248/545] bootstrap.contextInitialized add Blade param --- blade-core/src/main/java/com/blade/Blade.java | 29 ++++++++++++++----- .../src/main/java/com/blade/Bootstrap.java | 2 +- .../src/main/java/com/blade/CoreFilter.java | 2 +- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 326fdb6dc..f91143ea1 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -154,27 +154,39 @@ public void regObject(Object object){ } /** - *
 	 * Properties配置文件方式
 	 * 文件的路径基于classpath
-	 * 
* * @param confName 配置文件路径 + * @return 返回Blade单例实例 */ - public void setAppConf(String confName){ + public Blade config(String confName){ Map configMap = PropertyKit.getPropertyMap(confName); configuration(configMap); + return this; + } + + /** + * Properties配置文件方式 + * 文件的路径基于classpath + * + * @param confName 配置文件路径 + * @return 返回Blade单例实例 + */ + public Blade setAppConf(String confName){ + Map configMap = PropertyKit.getPropertyMap(confName); + configuration(configMap); + return this; } /** - *
 	 * JSON文件的配置
 	 * 文件的路径基于classpath
-	 * 
* * @param jsonPath json文件路径 + * @return 返回Blade单例实例 */ - public void setJsonConf(String jsonPath){ + public Blade setJsonConf(String jsonPath){ InputStream inputStream = Blade.class.getResourceAsStream(jsonPath); if(null != inputStream){ try { @@ -185,6 +197,7 @@ public void setJsonConf(String jsonPath){ e.printStackTrace(); } } + return this; } /** @@ -193,10 +206,12 @@ public void setJsonConf(String jsonPath){ *
* * @param json json配置 + * @return 返回Blade单例实例 */ - public void setAppJson(String json){ + public Blade setAppJson(String json){ Map configMap = JSONKit.toMap(json); configuration(configMap); + return this; } /** diff --git a/blade-core/src/main/java/com/blade/Bootstrap.java b/blade-core/src/main/java/com/blade/Bootstrap.java index 7db9008b9..1fd3102e9 100644 --- a/blade-core/src/main/java/com/blade/Bootstrap.java +++ b/blade-core/src/main/java/com/blade/Bootstrap.java @@ -31,7 +31,7 @@ public abstract class Bootstrap { /** * 初始化配置后执行 */ - public void contextInitialized(){ + public void contextInitialized(Blade blade){ // } } diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 6658c3f18..68b0d0df1 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -82,7 +82,7 @@ public void init(FilterConfig filterConfig) throws ServletException { // 初始化IOC IocApplication.init(blade); - bootstrap.contextInitialized(); + bootstrap.contextInitialized(blade); blade.setInit(true); From 82912fcdb8dfb01bc9ce42e7f560c25a8079bcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5?= Date: Fri, 30 Oct 2015 17:49:56 +0800 Subject: [PATCH 249/545] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0c3836ba6..e8947ab18 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ [![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) -[![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://maven-badges.herokuapp.com/maven-central/com.bladejava/blade-core/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) [中文](https://github.com/biezhi/blade/blob/master/README_CN.md) From 79e7ba7ec3d85626d0afaa23440ce909e8d6736b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5?= Date: Fri, 30 Oct 2015 17:50:21 +0800 Subject: [PATCH 250/545] Update README_CN.md --- README_CN.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README_CN.md b/README_CN.md index 981855f2d..c740c42bd 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,10 +1,10 @@ [![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) -[![Build Status](https://api.travis-ci.org/biezhi/blade.svg?branch=master)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://maven-badges.herokuapp.com/maven-central/com.bladejava/blade-core/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg)](http://weibo.com/u/5238733773) +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) [English](https://github.com/biezhi/blade/blob/master/README.md) From 76bcd84ec08f4b0c6500c8cc8a796d54786b14ba Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 30 Oct 2015 17:56:02 +0800 Subject: [PATCH 251/545] update pom --- pom.xml | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/pom.xml b/pom.xml index 1e8011d4e..d252af758 100644 --- a/pom.xml +++ b/pom.xml @@ -65,28 +65,6 @@ UTF-8 - - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - xml - 256m - - true - - - - - - org.eluder.coveralls - coveralls-maven-plugin - 3.2.0 - - 8lXc2riIWKCpWIzRBxTitoZN667hYNdT3 - - From 1ca06137acce91165592c64a2883125c054f8c12 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 3 Nov 2015 10:03:06 +0800 Subject: [PATCH 252/545] update readme --- README.md | 15 ++++++++++++++- README_CN.md | 15 ++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e8947ab18..bf10bd360 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,19 @@ If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! ## Getting started -To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) and then create a class with a main method like this: +To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : + +`Maven` config: + +```sh + + com.bladejava + blade-core + last_version + +``` + +create `Main` method like this: ```java public class App { @@ -53,6 +65,7 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex + [API DOCS](http://bladejava.com/apidocs/) + [USE GUIDE](https://github.com/biezhi/blade/wiki) + [EXAMPLES](https://github.com/bladejava) ++ [VERSION](LAST_VERSION.md) ## Plan diff --git a/README_CN.md b/README_CN.md index c740c42bd..89fb0cecb 100644 --- a/README_CN.md +++ b/README_CN.md @@ -30,7 +30,19 @@ ## 快速入门 -开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) ,然后创建一个类 ,编写 `Main` 函数: +开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : + +`Maven` 配置: + +```sh + + com.bladejava + blade-core + 最终版本 + +``` + +编写 `Main`函数: ```java public class App { @@ -53,6 +65,7 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 + [API文档](http://bladejava.com/apidocs/) + [使用指南](https://github.com/biezhi/blade/wiki) + [相关案例](https://github.com/bladejava) ++ [版本查询](LAST_VERSION.md) ### 计划 From e404d13db8b0f61b2739e5bc20d3e982c4d69bf0 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 9 Nov 2015 14:23:23 +0800 Subject: [PATCH 253/545] fix jetty for jdk7 --- blade-startup/pom.xml | 114 +++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/blade-startup/pom.xml b/blade-startup/pom.xml index 63a824e71..bf54bc750 100644 --- a/blade-startup/pom.xml +++ b/blade-startup/pom.xml @@ -1,57 +1,57 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-startup - 1.0.0 - blade-startup - - https://github.com/biezhi/blade/blade-startup - - - UTF-8 - 9.3.4.v20151007 - 3.1.0 - - - - - com.bladejava - blade-core - ${blade.version} - - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - - org.eclipse.jetty - jetty-server - ${jetty.version} - - - org.eclipse.jetty - jetty-webapp - ${jetty.version} - - - - org.eclipse.jetty - jetty-servlet - 9.3.4.v20151007 - - - - - + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + + blade-startup + 1.0.1 + blade-startup + + https://github.com/biezhi/blade/blade-startup + + + UTF-8 + 9.2.12.v20150709 + 3.1.0 + + + + + com.bladejava + blade-core + ${blade.version} + + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + + + + + + + From b1258c040a2ed050de608fb54b59d9d2cb951a3e Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 9 Nov 2015 14:24:07 +0800 Subject: [PATCH 254/545] optimize the Blade singleton --- blade-core/src/main/java/com/blade/Blade.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index f91143ea1..73e1136c2 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -52,12 +52,7 @@ public class Blade { /** * 当前最新版本 */ - public static final String VERSION = "1.4.1-alpha"; - - /** - * Blade单例 - */ - private static final Blade ME = new Blade(); + public static final String VERSION = "1.4.1"; /** * 框架是否已经初始化 @@ -111,11 +106,15 @@ public void init() { private Blade() { } + private static class BladeHolder { + private static Blade ME = new Blade(); + } + /** * @return 单例方式返回Blade对象 */ public static Blade me(){ - return ME; + return BladeHolder.ME; } /** From 8312ac5d9719226ce952262430fc53b16b9edd54 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 9 Nov 2015 14:24:38 +0800 Subject: [PATCH 255/545] rename SampleRouteMatcher to RouteMatcher --- .../main/java/com/blade/ActionHandler.java | 12 +- .../java/com/blade/route/RouteMatcher.java | 151 +++++++++++++ .../com/blade/route/SampleRouteMatcher.java | 207 ------------------ 3 files changed, 157 insertions(+), 213 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/route/RouteMatcher.java delete mode 100644 blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java index d96d14045..2ffa61779 100644 --- a/blade-core/src/main/java/com/blade/ActionHandler.java +++ b/blade-core/src/main/java/com/blade/ActionHandler.java @@ -31,7 +31,7 @@ import com.blade.route.Route; import com.blade.route.RouteHandler; import com.blade.route.Router; -import com.blade.route.SampleRouteMatcher; +import com.blade.route.RouteMatcher; import com.blade.servlet.ServletRequest; import com.blade.servlet.ServletResponse; @@ -67,7 +67,7 @@ public class ActionHandler { /** * 路由匹配器 */ - private SampleRouteMatcher sampleRouteMatcher; + private RouteMatcher routeMatcher; /** * 服务器500错误时返回的HTML @@ -90,7 +90,7 @@ public ActionHandler(ServletContext context, Blade blade){ this.blade = blade; this.router = blade.router(); this.context = context; - this.sampleRouteMatcher = new SampleRouteMatcher(router); + this.routeMatcher = new RouteMatcher(router); } /** @@ -131,19 +131,19 @@ public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpRe // 初始化context BladeWebContext.setContext(context, request, response); - Route route = sampleRouteMatcher.getRoute(method, uri); + Route route = routeMatcher.getRoute(method, uri); // 如果找到 if (route != null) { // 执行before拦截 - List befores = sampleRouteMatcher.getBefore(uri); + List befores = routeMatcher.getBefore(uri); invokeInterceptor(request, response, befores); // 实际执行方法 handle(request, response, route); // 执行after拦截 - List afters = sampleRouteMatcher.getAfter(uri); + List afters = routeMatcher.getAfter(uri); invokeInterceptor(request, response, afters); return true; } diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java new file mode 100644 index 000000000..b6f249c14 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/RouteMatcher.java @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import com.blade.http.HttpMethod; +import com.blade.http.Path; + +/** + * + *

+ * 路由匹配器默认实现 + *

+ * + * @author biezhi + * @since 1.0 + */ +public class RouteMatcher { + +// private static final Logger LOGGER = Logger.getLogger(SampleRouteMatcher.class); + + // 存储所有路由 + private List routes; + + private List interceptors; + + public RouteMatcher(Router router) { + this.routes = router.getRoutes(); + this.interceptors = router.getInterceptors(); + } + + /** + * 查找一个路由 + * @param httpMethod http请求方法 + * @param path 请求路径 + * @return 返回路由对象 + */ + public Route getRoute(String httpMethod, String path) { + String cleanPath = parsePath(path); + List matchRoutes = new ArrayList(); + for (Route route : this.routes) { + if (matchesPath(route.getPath(), cleanPath)) { + if (route.getHttpMethod() == HttpMethod.ALL + || HttpMethod.valueOf(httpMethod) == route.getHttpMethod()) { + matchRoutes.add(route); + } + } + } + // 优先匹配原则 + giveMatch(path, matchRoutes); + + return matchRoutes.size() > 0 ? matchRoutes.get(0) : null; + } + + /** + * 查找所有前置拦截器 + * @param path 请求路径 + * @return 返回前置拦截器列表 + */ + public List getBefore(String path) { + List befores = new ArrayList(); + String cleanPath = parsePath(path); + for (Route route : this.interceptors) { + if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.BEFORE){ + befores.add(route); + } + } + giveMatch(path, befores); + return befores; + } + + /** + * 查找所有后置拦截器 + * @param path 请求路径 + * @return 返回后置拦截器列表 + */ + public List getAfter(String path) { + List afters = new ArrayList(); + String cleanPath = parsePath(path); + for (Route route : interceptors) { + if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.AFTER){ + afters.add(route); + } + } + giveMatch(path, afters); + return afters; + } + + /** + * 对path进行排序 + * @param uri 请求uri + * @param routes 路由列表 + */ + private void giveMatch(final String uri, List routes) { + Collections.sort(routes, new Comparator() { + @Override + public int compare(Route o1, Route o2) { + if(o2.getPath().equals(uri)){ + return o2.getPath().indexOf(uri); + } + return -1; + } + }); + } + + /** + * 匹配路径 + * @param routePath 路由路径 + * @param pathToMatch 要匹配的路径 + * @return 返回是否匹配成功 + */ + private boolean matchesPath(String routePath, String pathToMatch) { + routePath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); + return pathToMatch.matches("(?i)" + routePath); + } + + /** + * 解析路径 + * @param path 路径地址 + * @return 返回解析后的路径 + */ + private String parsePath(String path) { + path = Path.fixPath(path); + try { + URI uri = new URI(path); + return uri.getPath(); + } catch (URISyntaxException e) { + return null; + } + } + +} diff --git a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java b/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java deleted file mode 100644 index 531eb414e..000000000 --- a/blade-core/src/main/java/com/blade/route/SampleRouteMatcher.java +++ /dev/null @@ -1,207 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import com.blade.http.HttpMethod; -import com.blade.http.Path; - -/** - * - *

- * 路由匹配器默认实现 - *

- * - * @author biezhi - * @since 1.0 - */ -public class SampleRouteMatcher { - -// private static final Logger LOGGER = Logger.getLogger(SampleRouteMatcher.class); - - // 存储所有路由 - private List routes; - - private List interceptors; - - public SampleRouteMatcher(Router router) { - this.routes = router.getRoutes(); - this.interceptors = router.getInterceptors(); - } - - public Route getRoute(String httpMethod, String path) { - String cleanPath = parsePath(path); - List matchRoutes = new ArrayList(); - for (Route route : this.routes) { - if (matchesPath(route.getPath(), cleanPath)) { - if (route.getHttpMethod() == HttpMethod.ALL - || HttpMethod.valueOf(httpMethod) == route.getHttpMethod()) { - matchRoutes.add(route); - } - } - } - // 优先匹配原则 - giveMatch(path, matchRoutes); - - return matchRoutes.size() > 0 ? matchRoutes.get(0) : null; - } - - private void giveMatch(final String uri, List routes) { - Collections.sort(routes, new Comparator() { - @Override - public int compare(Route o1, Route o2) { - if(o2.getPath().equals(uri)){ - return o2.getPath().indexOf(uri); - } - return -1; - } - }); - } - - private boolean matchesPath(String routePath, String pathToMatch) { - routePath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); - return pathToMatch.matches("(?i)" + routePath); - } - - private String parsePath(String path) { - path = Path.fixPath(path); - try { - URI uri = new URI(path); - return uri.getPath(); - } catch (URISyntaxException e) { - return null; - } - } - - public List getBefore(String path) { - List befores = new ArrayList(); - String cleanPath = parsePath(path); - for (Route route : this.interceptors) { - if (matches(route, HttpMethod.BEFORE, cleanPath)) { - befores.add(route); - } - } - giveMatch(path, befores); - return befores; - } - - public List getAfter(String path) { - List afters = new ArrayList(); - String cleanPath = parsePath(path); - for (Route route : interceptors) { - if (matches(route, HttpMethod.AFTER, cleanPath)) { - afters.add(route); - } - } - giveMatch(path, afters); - return afters; - } - - public boolean matches(Route route, HttpMethod httpMethod, String path) { - - // 如果是拦截器的全部匹配模式则跳过,返回true - if ((httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER) - && (route.getHttpMethod() == httpMethod) - && route.getPath().equals(Path.ALL_PATHS)) { - return true; - } - - boolean match = false; - if (route.getHttpMethod() == HttpMethod.ALL || route.getHttpMethod() == httpMethod) { - match = matchPath(route.getPath(), path); - } - - return match; - } - - /** - * 继续匹配 - * - * @param uri - * @return - */ - private boolean matchPath(String path, String uri) { - - // /hello - if (!path.endsWith("*") && ((uri.endsWith("/") && !path.endsWith("/")) - || (path.endsWith("/") && !uri.endsWith("/")))) { - return false; - } - - if (path.equals(uri)) { - return true; - } - - // 检查参数 - List thisPathList = Path.convertRouteToList(path); - List uriList = Path.convertRouteToList(uri); - - int thisPathSize = thisPathList.size(); - int uriSize = uriList.size(); - - if (thisPathSize == uriSize) { - for (int i = 0; i < thisPathSize; i++) { - String thisPathPart = thisPathList.get(i); - String pathPart = uriList.get(i); - - if ((i == thisPathSize - 1) && (thisPathPart.equals("*") && path.endsWith("*"))) { - // 通配符匹配 - return true; - } - - if ((!thisPathPart.startsWith(":")) - && !thisPathPart.equals(pathPart) - && !thisPathPart.equals("*")) { - return false; - } - } - // 全部匹配 - return true; - } else { - if (path.endsWith("*")) { - if (uriSize == (thisPathSize - 1) && (path.endsWith("/"))) { - uriList.add(""); - uriList.add(""); - uriSize += 2; - } - - if (thisPathSize < uriSize) { - for (int i = 0; i < thisPathSize; i++) { - String thisPathPart = thisPathList.get(i); - String pathPart = uriList.get(i); - if (thisPathPart.equals("*") && (i == thisPathSize - 1) && path.endsWith("*")) { - return true; - } - if (!thisPathPart.startsWith(":") - && !thisPathPart.equals(pathPart) - && !thisPathPart.equals("*")) { - return false; - } - } - return true; - } - } - return false; - } - } - -} From 9b5711497fe42977f53c1c4be352f1a1d6a06ec8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 9 Nov 2015 14:27:54 +0800 Subject: [PATCH 256/545] update blade version to 1.4.1 --- UPDATE_LOG.md | 1 + pom.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 7cca661f4..b1b6b194b 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -4,6 +4,7 @@ 1. 去除过度设计 2. 添加多种路由配置 3. 统一渲染引擎,不在分离 + 4. 优化字符串分割 ### v1.4.0 1. 添加CSRF防御 diff --git a/pom.xml b/pom.xml index d252af758..86ab4cb91 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ 1.6 UTF-8 3.0.1 - 1.4.1-beta + 1.4.1 4.12 From 0f47b372ddddffce8868d5ffc13c002f395c7b20 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 9 Nov 2015 14:43:34 +0800 Subject: [PATCH 257/545] add blade-sample --- LAST_VERSION.md | 11 +- blade-sample/pom.xml | 67 +++++++++ blade-sample/src/main/java/com/xxx/App.java | 12 ++ blade-sample/src/main/webapp/WEB-INF/web.xml | 21 +++ pom.xml | 142 +++++++++---------- 5 files changed, 181 insertions(+), 72 deletions(-) create mode 100644 blade-sample/pom.xml create mode 100644 blade-sample/src/main/java/com/xxx/App.java create mode 100644 blade-sample/src/main/webapp/WEB-INF/web.xml diff --git a/LAST_VERSION.md b/LAST_VERSION.md index d58a972ea..4b933ea69 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -32,7 +32,7 @@     com.bladejava     blade-core -    1.4.1-beta +    1.4.1 ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -67,6 +67,15 @@     com.bladejava     blade-startup +    1.0.1 + +``` + +## [blade-sample](http://search.maven.org/#search%7Cga%7C1%7Cblade-sample) +```xml + +    com.bladejava +    blade-sample     1.0.0 ``` \ No newline at end of file diff --git a/blade-sample/pom.xml b/blade-sample/pom.xml new file mode 100644 index 000000000..1c9ef7099 --- /dev/null +++ b/blade-sample/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + blade-sample + 1.0.0 + war + blade-sample Maven Webapp + http://maven.apache.org + + + 1.6 + 1.6 + UTF-8 + + + + + com.bladejava + blade-core + ${blade.version} + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + + blade-sample + + + org.apache.maven.plugins + maven-compiler-plugin + 3.2 + + 1.6 + 1.6 + UTF8 + + + + org.mortbay.jetty + maven-jetty-plugin + 6.1.7 + + src/main/webapp + 1 + / + + + 9000 + 30000 + + + + + + + diff --git a/blade-sample/src/main/java/com/xxx/App.java b/blade-sample/src/main/java/com/xxx/App.java new file mode 100644 index 000000000..a04d43893 --- /dev/null +++ b/blade-sample/src/main/java/com/xxx/App.java @@ -0,0 +1,12 @@ +package com.xxx; + +import com.blade.Bootstrap; + +public class App extends Bootstrap { + + @Override + public void init() { + + } + +} diff --git a/blade-sample/src/main/webapp/WEB-INF/web.xml b/blade-sample/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..dc47db24e --- /dev/null +++ b/blade-sample/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,21 @@ + + + + Archetype Created Web Application + + + CoreFilter + com.blade.CoreFilter + + bootstrapClass + com.xxx.App + + + + CoreFilter + /* + + + diff --git a/pom.xml b/pom.xml index 86ab4cb91..d5108eaa3 100644 --- a/pom.xml +++ b/pom.xml @@ -1,71 +1,71 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - pom - - blade-root - https://github.com/biezhi/blade - - - 1.6 - 1.6 - UTF-8 - 3.0.1 - 1.4.1 - 4.12 - - - - blade-kit - blade-core - blade-cache - blade-sql2o - blade-redis - blade-startup - - - - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - - - - junit - junit - ${junit.version} - test - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.6 - 1.6 - UTF-8 - - - - - - + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + pom + + blade-root + https://github.com/biezhi/blade + + + 1.6 + 1.6 + UTF-8 + 3.0.1 + 1.4.1 + 4.12 + + + + blade-kit + blade-core + blade-cache + blade-sql2o + blade-redis + blade-startup + blade-sample + + + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + + junit + junit + ${junit.version} + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + UTF-8 + + + + + + \ No newline at end of file From b9a8051133ebeb56265c22f45fa4bf41a016e955 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 9 Nov 2015 14:49:54 +0800 Subject: [PATCH 258/545] init base config --- blade-sample/src/main/java/com/xxx/App.java | 7 +++++-- .../src/main/java/com/xxx/route/IndexRoute.java | 12 ++++++++++++ blade-sample/src/main/resources/blade.conf | 6 ++++++ blade-sample/src/main/resources/route.conf | 1 + .../src/main/webapp/WEB-INF/views/index.jsp | 13 +++++++++++++ 5 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 blade-sample/src/main/java/com/xxx/route/IndexRoute.java create mode 100644 blade-sample/src/main/resources/blade.conf create mode 100644 blade-sample/src/main/resources/route.conf create mode 100644 blade-sample/src/main/webapp/WEB-INF/views/index.jsp diff --git a/blade-sample/src/main/java/com/xxx/App.java b/blade-sample/src/main/java/com/xxx/App.java index a04d43893..cd3dcf155 100644 --- a/blade-sample/src/main/java/com/xxx/App.java +++ b/blade-sample/src/main/java/com/xxx/App.java @@ -1,12 +1,15 @@ package com.xxx; +import com.blade.Blade; import com.blade.Bootstrap; public class App extends Bootstrap { @Override public void init() { - + Blade blade = Blade.me(); + blade.routeConf("com.xxx.route", "route.conf"); + blade.config("blade.conf"); } - + } diff --git a/blade-sample/src/main/java/com/xxx/route/IndexRoute.java b/blade-sample/src/main/java/com/xxx/route/IndexRoute.java new file mode 100644 index 000000000..f06d30ee0 --- /dev/null +++ b/blade-sample/src/main/java/com/xxx/route/IndexRoute.java @@ -0,0 +1,12 @@ +package com.xxx.route; + +import com.blade.http.Request; +import com.blade.http.Response; + +public class IndexRoute { + + public void index(Request request, Response response){ + response.render("index"); + } + +} diff --git a/blade-sample/src/main/resources/blade.conf b/blade-sample/src/main/resources/blade.conf new file mode 100644 index 000000000..f5872f4af --- /dev/null +++ b/blade-sample/src/main/resources/blade.conf @@ -0,0 +1,6 @@ +#\u89c6\u56fe\u6587\u4ef6\u76ee\u5f55 +blade.prefix=/WEB-INF/views/ +#\u89c6\u56fe\u6587\u4ef6\u540e\u7f00 +blade.suffix=.jsp +#\u9759\u6001\u6587\u4ef6\u76ee\u5f55 +blade.filter_folder=/static/ \ No newline at end of file diff --git a/blade-sample/src/main/resources/route.conf b/blade-sample/src/main/resources/route.conf new file mode 100644 index 000000000..e1f4f0a9a --- /dev/null +++ b/blade-sample/src/main/resources/route.conf @@ -0,0 +1 @@ +GET / IndexRoute#index \ No newline at end of file diff --git a/blade-sample/src/main/webapp/WEB-INF/views/index.jsp b/blade-sample/src/main/webapp/WEB-INF/views/index.jsp new file mode 100644 index 000000000..d2c29326b --- /dev/null +++ b/blade-sample/src/main/webapp/WEB-INF/views/index.jsp @@ -0,0 +1,13 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%> + + + + +Welcome To Blade + + +
+

Hi gays!

+
+ + \ No newline at end of file From 74bded79d3a5b7ea979c838f3a2008d87c3be7b2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 9 Nov 2015 14:52:25 +0800 Subject: [PATCH 259/545] update jetty version --- blade-core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 8dd0e57df..ebb80cdc1 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -16,7 +16,7 @@ https://github.com/biezhi/blade/blade-core - 8.1.15.v20140411 + 9.2.12.v20150709 2.0.12 2.2.3 1.7 From bcd7aa235b7be86cf4161ef160d57e190be4b055 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 9 Nov 2015 14:54:28 +0800 Subject: [PATCH 260/545] rename --- .travis.yml | 1 + blade-sample/pom.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index abf532887..407ba9d05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,5 +2,6 @@ language: java jdk: - oraclejdk8 - oraclejdk7 + - openjdk6 after_success: - mvn cobertura:cobertura coveralls:report diff --git a/blade-sample/pom.xml b/blade-sample/pom.xml index 1c9ef7099..594766aaf 100644 --- a/blade-sample/pom.xml +++ b/blade-sample/pom.xml @@ -11,7 +11,7 @@ blade-sample 1.0.0 war - blade-sample Maven Webapp + blade-sample http://maven.apache.org From 55605a37141970d9cff561e3c0d891118aef65d0 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 9 Nov 2015 15:15:14 +0800 Subject: [PATCH 261/545] reset route separator --- .../java/com/blade/loader/AbstractFileRouteLoader.java | 10 +++++----- blade-sample/src/main/resources/route.conf | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java index 49244d88b..c16297c79 100644 --- a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java @@ -67,7 +67,7 @@ private List load(InputStream inputStream) throws ParseException, IOExcep input = input.trim(); - if (!input.equals("") && !input.startsWith("#")) { + if (!input.equals("") && !input.startsWith(".")) { Route route = parse(input, line); routes.add(route); } @@ -90,7 +90,7 @@ private Route parse(String input, int line) throws ParseException { String path = validatePath( st.nextToken().trim(), line ); String controllerAndMethod = validateControllerAndMethod( st.nextToken().trim(), line ); - int hashPos = controllerAndMethod.indexOf('#'); + int hashPos = controllerAndMethod.indexOf("."); String controllerName = controllerAndMethod.substring(0, hashPos); // 获取控制器方法 @@ -136,7 +136,7 @@ private String validatePath(String path, int line) throws ParseException { } private boolean isValidCharForPath(char c, boolean openedKey) { - char[] invalidChars = { '?', '#', ' ' }; + char[] invalidChars = { '?', '.', ' ' }; for (char invalidChar : invalidChars) { if (c == invalidChar) { return false; @@ -158,13 +158,13 @@ private boolean isValidCharForPath(char c, boolean openedKey) { /** * 验证控制器方法 * - * @param beanAndMethod 控制器和方法,使用#隔开 + * @param beanAndMethod 控制器和方法,使用.隔开 * @param line 所在行数 * @return 返回验证后的字符串,异常则抛出 * @throws ParseException */ private String validateControllerAndMethod(String beanAndMethod, int line) throws ParseException { - int hashPos = beanAndMethod.indexOf('#'); + int hashPos = beanAndMethod.indexOf("."); if (hashPos == -1) { throw new ParseException("Unrecognized format for '" + beanAndMethod + "'", line); } diff --git a/blade-sample/src/main/resources/route.conf b/blade-sample/src/main/resources/route.conf index e1f4f0a9a..b470081c6 100644 --- a/blade-sample/src/main/resources/route.conf +++ b/blade-sample/src/main/resources/route.conf @@ -1 +1 @@ -GET / IndexRoute#index \ No newline at end of file +GET / IndexRoute.index \ No newline at end of file From 7170e8da155e537d31458c6bac0b519e5ee35844 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 9 Nov 2015 15:24:50 +0800 Subject: [PATCH 262/545] remove openjdk6 --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 407ba9d05..abf532887 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,5 @@ language: java jdk: - oraclejdk8 - oraclejdk7 - - openjdk6 after_success: - mvn cobertura:cobertura coveralls:report From 4f69a6c0313beb256a84d4ae7ee7d9aa58ba82ac Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 10 Nov 2015 16:11:36 +0800 Subject: [PATCH 263/545] update readme --- README.md | 8 ++++---- README_CN.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index bf10bd360..6542e4498 100644 --- a/README.md +++ b/README.md @@ -69,10 +69,10 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ## Plan -1. Improve the document -2. Add the routing configuration way -3. To develop personalized social applications -4. Maintain and optimize the code +- 1. The development of social application platform +- 2. Add the test code +- 3. Optimize the code base +- 4. Optimization of concurrent ability ## Update diff --git a/README_CN.md b/README_CN.md index 89fb0cecb..4d652f00b 100644 --- a/README_CN.md +++ b/README_CN.md @@ -69,10 +69,10 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ### 计划 -- 1. 完善文档 -- 2. 添加配置方式路由 -- 3. 开发个性化社交应用 -- 4. 维护和优化代码 +- 1. 开发社交应用平台 +- 2. 添加测试代码 +- 3. 优化基础代码 +- 4. 优化并发能力 ## 更新日志 From 1728c72ed50310619db1bd909e3608c3bb4aeb6f Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 27 Nov 2015 18:49:01 +0800 Subject: [PATCH 264/545] add blade proxy --- blade-proxy/src/main/java/com/blade/proxy/Proxy.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 blade-proxy/src/main/java/com/blade/proxy/Proxy.java diff --git a/blade-proxy/src/main/java/com/blade/proxy/Proxy.java b/blade-proxy/src/main/java/com/blade/proxy/Proxy.java new file mode 100644 index 000000000..c909d3786 --- /dev/null +++ b/blade-proxy/src/main/java/com/blade/proxy/Proxy.java @@ -0,0 +1,5 @@ +package com.blade.proxy; + +public interface Proxy { + +} From dc8de34623a176c45db0de73a30affef2e8eb82b Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 30 Nov 2015 10:20:45 +0800 Subject: [PATCH 265/545] optimize the code, modify the name --- .../src/main/java/com/blade/ActionHandler.java | 4 ++-- blade-core/src/main/java/com/blade/Blade.java | 12 ++++++------ .../src/main/java/com/blade/IocApplication.java | 14 +++++++------- .../java/com/blade/context/BladeWebContext.java | 10 +++++----- .../src/main/java/com/blade/plugin/Plugin.java | 1 + .../main/java/com/blade/route/RouteBuilder.java | 2 +- .../main/java/com/blade/route/RouteMatcher.java | 2 +- .../com/blade/route/{Router.java => Routers.java} | 4 ++-- 8 files changed, 25 insertions(+), 24 deletions(-) rename blade-core/src/main/java/com/blade/route/{Router.java => Routers.java} (95%) diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java index 2ffa61779..187e11e98 100644 --- a/blade-core/src/main/java/com/blade/ActionHandler.java +++ b/blade-core/src/main/java/com/blade/ActionHandler.java @@ -30,7 +30,7 @@ import com.blade.render.ModelAndView; import com.blade.route.Route; import com.blade.route.RouteHandler; -import com.blade.route.Router; +import com.blade.route.Routers; import com.blade.route.RouteMatcher; import com.blade.servlet.ServletRequest; import com.blade.servlet.ServletResponse; @@ -62,7 +62,7 @@ public class ActionHandler { /** * 路由管理器 */ - private Router router; + private Routers router; /** * 路由匹配器 diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 73e1136c2..e36806a6b 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -32,7 +32,7 @@ import com.blade.render.Render; import com.blade.route.Route; import com.blade.route.RouteHandler; -import com.blade.route.Router; +import com.blade.route.Routers; import com.blade.route.RouteException; import com.blade.server.Server; @@ -86,7 +86,7 @@ public void init() { /** * 路由管理对象 */ - private Router router = new Router(); + private Routers router = new Routers(); /** * 默认启动端口 @@ -137,7 +137,7 @@ public Server createServer(int port){ /** * @return 返回路由管理对象 */ - public Router router() { + public Routers router() { return router; } @@ -764,10 +764,10 @@ public boolean enableXSS(){ * @return 返回插件对象 */ @SuppressWarnings("unchecked") - public T plugin(Class pluginClazz){ - Object object = IocApplication.getPlugin(pluginClazz); + public T plugin(Class plugin){ + Object object = IocApplication.getPlugin(plugin); if(null == object){ - object = IocApplication.registerPlugin(pluginClazz); + object = IocApplication.registerPlugin(plugin); } return (T) object; } diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index 954f2317b..79534921d 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -96,15 +96,15 @@ private static void initIOC(String[] iocPackages) { } @SuppressWarnings("unchecked") - public static T registerPlugin(Class pluginClazz){ - Object object = container.registBean(pluginClazz); - T plugin = (T) object; - PLUGINS.add(plugin); - return plugin; + public static T registerPlugin(Class plugin){ + Object object = container.registBean(plugin); + T t = (T) object; + PLUGINS.add(t); + return t; } - public static T getPlugin(Class pluginClazz){ - return container.getBean(pluginClazz, Scope.SINGLE); + public static T getPlugin(Class plugin){ + return container.getBean(plugin, Scope.SINGLE); } /** diff --git a/blade-core/src/main/java/com/blade/context/BladeWebContext.java b/blade-core/src/main/java/com/blade/context/BladeWebContext.java index b238e52b9..3f5ca27c6 100644 --- a/blade-core/src/main/java/com/blade/context/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/context/BladeWebContext.java @@ -27,12 +27,12 @@ * @author biezhi * @since 1.0 */ -public final class BladeWebContext { +public class BladeWebContext { /** * 当前线程的Request对象 */ - private static final ThreadLocal BLADE_WEB_CONTEXT = new ThreadLocal(); + private static ThreadLocal ctx = new ThreadLocal(); /** * ServletContext对象,在应用初始化时创建 @@ -52,7 +52,7 @@ public final class BladeWebContext { private BladeWebContext(){} public static BladeWebContext me(){ - return BLADE_WEB_CONTEXT.get(); + return ctx.get(); } public static void setContext(ServletContext context, Request request, Response response) { @@ -60,14 +60,14 @@ public static void setContext(ServletContext context, Request request, Response bladeWebContext.context = context; bladeWebContext.request = request; bladeWebContext.response = response; - BLADE_WEB_CONTEXT.set(bladeWebContext); + ctx.set(bladeWebContext); } /** * 移除当前线程的Request、Response对象 */ public static void remove(){ - BLADE_WEB_CONTEXT.remove(); + ctx.remove(); } public static Request request() { diff --git a/blade-core/src/main/java/com/blade/plugin/Plugin.java b/blade-core/src/main/java/com/blade/plugin/Plugin.java index 9785f5477..e692d875d 100644 --- a/blade-core/src/main/java/com/blade/plugin/Plugin.java +++ b/blade-core/src/main/java/com/blade/plugin/Plugin.java @@ -15,6 +15,7 @@ */ package com.blade.plugin; + /** * 插件顶层接口 * diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index bfbf79611..d4eb990c1 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -65,7 +65,7 @@ public class RouteBuilder { private Blade blade; - private Router router; + private Routers router; public RouteBuilder(Blade blade) { this.blade = blade; diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java index b6f249c14..8b6d81e14 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcher.java @@ -43,7 +43,7 @@ public class RouteMatcher { private List interceptors; - public RouteMatcher(Router router) { + public RouteMatcher(Routers router) { this.routes = router.getRoutes(); this.interceptors = router.getInterceptors(); } diff --git a/blade-core/src/main/java/com/blade/route/Router.java b/blade-core/src/main/java/com/blade/route/Routers.java similarity index 95% rename from blade-core/src/main/java/com/blade/route/Router.java rename to blade-core/src/main/java/com/blade/route/Routers.java index ce4151745..11dc34d37 100644 --- a/blade-core/src/main/java/com/blade/route/Router.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -40,9 +40,9 @@ * @author biezhi * @since 1.0 */ -public class Router { +public class Routers { - private Logger LOGGER = Logger.getLogger(Router.class); + private Logger LOGGER = Logger.getLogger(Routers.class); private final static Container container = SampleContainer.single(); From d4f2b7d9c52191cdd778dfbf6e9ebddeb6b3c6ff Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 30 Nov 2015 10:26:13 +0800 Subject: [PATCH 266/545] remove register object method, add get ioc container method --- blade-core/src/main/java/com/blade/Blade.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index e36806a6b..8e706c359 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -76,7 +76,7 @@ public void init() { /** * IOC容器,存储路由到ioc中 */ - private Container container = SampleContainer.single(); + private Container container = new SampleContainer(); /** * 默认JSP渲染 @@ -142,14 +142,10 @@ public Routers router() { } /** - *
-	 * 手动注册一个对象到ioc容器中
-	 * 
- * - * @param object 要注册的object + * @return 返回Blade IOC容器 */ - public void regObject(Object object){ - container.registBean(object); + public Container container(){ + return container; } /** From 02e9ba809a93ba593dc202b0ece9645df1f2ac4d Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 30 Nov 2015 10:43:56 +0800 Subject: [PATCH 267/545] Optimize the code, modify the name --- blade-core/src/main/java/com/blade/Blade.java | 59 +++++++---------- .../src/main/java/com/blade/CoreFilter.java | 7 +- .../main/java/com/blade/IocApplication.java | 41 +++++++----- .../com/blade/ioc/AbstractBeanFactory.java | 66 ------------------- .../java/com/blade/ioc/PrototypeBean.java | 36 ---------- .../java/com/blade/ioc/SampleContainer.java | 24 +++---- .../main/java/com/blade/ioc/SingleBean.java | 36 ---------- .../loader/ClassPathControllerLoader.java | 4 +- .../java/com/blade/route/RouteBuilder.java | 20 +++--- .../main/java/com/blade/route/Routers.java | 13 ++-- 10 files changed, 77 insertions(+), 229 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java delete mode 100644 blade-core/src/main/java/com/blade/ioc/PrototypeBean.java delete mode 100644 blade-core/src/main/java/com/blade/ioc/SingleBean.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 8e706c359..64ddbe94d 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -39,6 +39,7 @@ import blade.kit.IOKit; import blade.kit.PropertyKit; import blade.kit.ReflectKit; +import blade.kit.StringKit; import blade.kit.json.JSONKit; /** @@ -68,6 +69,11 @@ public void init() { } }; + /** + * ioc全局对象 + */ + private IocApplication iocApplication = new IocApplication(); + /** * 全局配置对象 */ @@ -86,7 +92,7 @@ public void init() { /** * 路由管理对象 */ - private Routers router = new Routers(); + private Routers router = new Routers(container); /** * 默认启动端口 @@ -293,33 +299,6 @@ public Blade route(String path, Object target, String method){ * @param path 路由路径 * @param target 路由执行的目标对象 * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) - * @return 返回Blade单例实例 - */ - @Deprecated - public Blade addRoute(String path, Object target, String method){ - return route(path, target, method); - } - - /** - * 添加一个路由 - * - * @param path 路由路径 - * @param target 路由执行的目标对象 - * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) - * @param httpMethod HTTP请求方法 - * @return 返回Blade单例实例 - */ - @Deprecated - public Blade addRoute(String path, Object target, String method, HttpMethod httpMethod){ - return route(path, target, method, httpMethod); - } - - /** - * 添加一个路由 - * - * @param path 路由路径 - * @param target 路由执行的目标对象 - * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) * @param httpMethod HTTP方法 * @return 返回Blade单例实例 */ @@ -464,13 +443,13 @@ public Blade viewEngin(Render render) { } /** - * 设置默认视图前缀,默认为WEB_ROOT/WEB-INF目录 + * 设置默认视图前缀,默认为WEBROOT/WEB-INF/目录 * - * @param prefix 视图路径,如:/WEB-INF/views + * @param prefix 视图路径,如:/WEB-INF/views/ * @return 返回Blade单例实例 */ public Blade viewPrefix(final String prefix) { - if(null != prefix && prefix.startsWith("/")){ + if(StringKit.isNotBlank(prefix) && prefix.startsWith("/")){ config.setViewPrefix(prefix); } return this; @@ -483,7 +462,7 @@ public Blade viewPrefix(final String prefix) { * @return 返回Blade单例实例 */ public Blade viewSuffix(final String suffix) { - if(null != suffix && suffix.startsWith(".")){ + if(StringKit.isNotBlank(suffix) && suffix.startsWith(".")){ config.setViewSuffix(suffix); } return this; @@ -525,7 +504,7 @@ public Blade enableXSS(boolean enableXSS){ } /** - * 动态设置全局初始化类 + * 动态设置全局初始化类, 内嵌式Jetty启动用 * * @param bootstrap 全局初始化bladeApplication * @return 返回Blade单例实例 @@ -761,15 +740,15 @@ public boolean enableXSS(){ */ @SuppressWarnings("unchecked") public T plugin(Class plugin){ - Object object = IocApplication.getPlugin(plugin); + Object object = iocApplication.getPlugin(plugin); if(null == object){ - object = IocApplication.registerPlugin(plugin); + object = iocApplication.registerPlugin(plugin); } return (T) object; } /** - * 注册一个配置文件的路由 + * 注册一个配置文件的路由,如:"com.xxx.route","route.conf" * * @param basePackage 控制器包名 * @param conf 配置文件路径,配置文件必须在classpath下 @@ -789,4 +768,12 @@ public Blade routeConf(String basePackage, String conf) { } return this; } + + void iocInit(){ + iocApplication.init(this); + } + + IocApplication iocApplication(){ + return iocApplication; + } } diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 68b0d0df1..810055ccf 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -80,10 +80,9 @@ public void init(FilterConfig filterConfig) throws ServletException { new RouteBuilder(blade).building(); // 初始化IOC - IocApplication.init(blade); - + blade.iocInit(); + bootstrap.contextInitialized(blade); - blade.setInit(true); actionHandler = new ActionHandler(filterConfig.getServletContext(), blade); @@ -143,7 +142,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha public void destroy() { LOGGER.info("blade destroy!"); BladeWebContext.remove(); - IocApplication.destroy(); + blade.iocApplication().destroy(); TaskKit.depose(); } diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index 79534921d..a6052aa1f 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -15,20 +15,19 @@ */ package com.blade; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; -import com.blade.ioc.Container; -import com.blade.ioc.SampleContainer; -import com.blade.ioc.Scope; -import com.blade.plugin.Plugin; - -import blade.kit.CollectionKit; import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; +import com.blade.ioc.Container; +import com.blade.ioc.Scope; +import com.blade.plugin.Plugin; + /** * IOC容器初始化类 *

@@ -38,31 +37,37 @@ * @author biezhi * @since 1.0 */ -public final class IocApplication { +public class IocApplication { private static final Logger LOGGER = Logger.getLogger(IocApplication.class); /** * IOC容器,单例获取默认的容器实现 */ - private static final Container container = SampleContainer.single(); + private Container container = null; /** * 类读取对象,加载class */ - private static final ClassReader classReader = new ClassPathClassReader(); + private ClassReader classReader = null; /** * 插件列表 */ - private static final List PLUGINS = CollectionKit.newArrayList(); + private List plugins = null; + + public IocApplication() { + this.classReader = new ClassPathClassReader(); + this.plugins = new ArrayList(); + } /** * 初始化IOC * * @param blade Blade实例 */ - public static void init(Blade blade){ + public void init(Blade blade){ + this.container = blade.container(); // 初始化全局配置类 if(null == container.getBean(Bootstrap.class, Scope.SINGLE)){ @@ -87,7 +92,7 @@ public static void init(Blade blade){ * 要配置符合ioc的注解的类才会被加载 * */ - private static void initIOC(String[] iocPackages) { + private void initIOC(String[] iocPackages) { if(null != iocPackages && iocPackages.length > 0){ for(String packageName : iocPackages){ registerBean(packageName); @@ -96,14 +101,14 @@ private static void initIOC(String[] iocPackages) { } @SuppressWarnings("unchecked") - public static T registerPlugin(Class plugin){ + public T registerPlugin(Class plugin){ Object object = container.registBean(plugin); T t = (T) object; - PLUGINS.add(t); + plugins.add(t); return t; } - public static T getPlugin(Class plugin){ + public T getPlugin(Class plugin){ return container.getBean(plugin, Scope.SINGLE); } @@ -112,7 +117,7 @@ public static T getPlugin(Class plugin){ * * @param packageName 包名称 */ - private static void registerBean(String packageName) { + private void registerBean(String packageName) { // 是否递归扫描 boolean recursive = false; @@ -134,10 +139,10 @@ private static void registerBean(String packageName) { /** * 销毁 */ - public static void destroy() { + public void destroy() { // 清空ioc容器 container.removeAll(); - for(Plugin plugin : PLUGINS){ + for(Plugin plugin : plugins){ plugin.destroy(); } } diff --git a/blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java b/blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java deleted file mode 100644 index 483d75568..000000000 --- a/blade-core/src/main/java/com/blade/ioc/AbstractBeanFactory.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.annotation.Annotation; -import java.util.Collection; -import java.util.List; -import java.util.Set; - -import blade.kit.log.Logger; - -/** - * 抽象bean工厂,用于注册和获取bean对象 - * - * @author biezhi - * @since 1.0 - */ -public abstract class AbstractBeanFactory { - - private static final Logger LOGGER = Logger.getLogger(AbstractBeanFactory.class); - - protected Container container = SampleContainer.single(); - - public abstract Object getBean(String className); - - public abstract Object getBean(Class clazz); - - public boolean resetBean(Class clazz, Object object){ - LOGGER.info("resetBean object=" + object); - if(null != clazz.getInterfaces() && null != object){ - container.removeBean(clazz); - container.getBeanMap().put(clazz.getName(), object); - } - return true; - } - - public Set getBeanNames(){ - return container.getBeanNames(); - } - - public Collection getBeans(){ - return container.getBeans(); - } - - public List getBeansByAnnotation(Class annotation){ - return container.getBeansByAnnotation(annotation); - } - - public List> getClassesByAnnotation(Class annotation){ - return container.getClassesByAnnotation(annotation); - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/PrototypeBean.java b/blade-core/src/main/java/com/blade/ioc/PrototypeBean.java deleted file mode 100644 index 9821e4ee5..000000000 --- a/blade-core/src/main/java/com/blade/ioc/PrototypeBean.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -/** - * 原生bean对象 - * - * @author biezhi - * @since 1.0 - */ -public class PrototypeBean extends AbstractBeanFactory { - - @Override - public Object getBean(String className) { - return container.getBean(className, Scope.PROTOTYPE); - } - - @Override - public Object getBean(Class clazz) { - return container.getBean(clazz, Scope.PROTOTYPE); - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java index 30bdb0712..832f9f594 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -56,17 +56,9 @@ public class SampleContainer implements Container { */ private static final Map, List> ANNOTATION_CONTAINER = CollectionKit.newConcurrentHashMap(); - private SampleContainer() { + public SampleContainer() { } - public static SampleContainer single() { - return DefaultContainerHoder.single; - } - - private static class DefaultContainerHoder { - private static final SampleContainer single = new SampleContainer(); - } - public Map getBeanMap() { return BEAN_CONTAINER; } @@ -116,7 +108,7 @@ public Collection getBeans() { @Override public boolean hasBean(Class clz) { - if (null != single().getBean(clz, Scope.SINGLE)) { + if (null != this.getBean(clz, Scope.SINGLE)) { return true; } return false; @@ -124,7 +116,7 @@ public boolean hasBean(Class clz) { @Override public boolean hasBean(String name) { - if (null != single().getBean(name, Scope.SINGLE)) { + if (null != this.getBean(name, Scope.SINGLE)) { return true; } return false; @@ -202,7 +194,7 @@ private void putAnnotationMap(Class clazz, Object object){ listObject = CollectionKit.newArrayList(); } listObject.add(object); - single().put(annotation.annotationType(), listObject); + this.put(annotation.annotationType(), listObject); } } } @@ -241,7 +233,7 @@ private Object recursiveAssembly(Class clazz){ String implClassName = clazz.getPackage().getName() + ".impl." + clazz.getSimpleName() + "Impl"; return ReflectKit.newInstance(implClassName); } else { - field = single().registBean(clazz); + field = this.registBean(clazz); } } return field; @@ -289,7 +281,7 @@ public List getBeansByAnnotation(Class annotation) public void registBean(Set> classes) { if(!CollectionKit.isEmpty(classes)){ for(Class clazz : classes){ - single().registBean(clazz); + this.registBean(clazz); } } } @@ -319,11 +311,11 @@ public void injection(Object object) { if (null != inject ) { // 要注入的字段 - Object injectField = single().getBean(field.getType(), Scope.SINGLE); + Object injectField = this.getBean(field.getType(), Scope.SINGLE); // 指定装配到哪个class if(inject.value() != Class.class){ // 指定装配的类 - injectField = single().getBean(inject.value(), Scope.SINGLE); + injectField = this.getBean(inject.value(), Scope.SINGLE); if (null == injectField) { injectField = recursiveAssembly(inject.value()); diff --git a/blade-core/src/main/java/com/blade/ioc/SingleBean.java b/blade-core/src/main/java/com/blade/ioc/SingleBean.java deleted file mode 100644 index be60db8b1..000000000 --- a/blade-core/src/main/java/com/blade/ioc/SingleBean.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -/** - * 单例bean对象,容器中只存在一个bean实例 - * - * @author biezhi - * @since 1.0 - */ -public class SingleBean extends AbstractBeanFactory { - - @Override - public Object getBean(String className) { - return container.getBean(className, Scope.SINGLE); - } - - @Override - public Object getBean(Class clazz) { - return container.getBean(clazz, Scope.SINGLE); - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java index 48a598f6c..c0f6abeeb 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java @@ -1,7 +1,7 @@ package com.blade.loader; +import com.blade.Blade; import com.blade.ioc.Container; -import com.blade.ioc.SampleContainer; import com.blade.ioc.Scope; import com.blade.route.RouteException; @@ -20,7 +20,7 @@ public class ClassPathControllerLoader implements ControllerLoader { private ClassLoader classLoader = ClassPathControllerLoader.class.getClassLoader(); - private Container container = SampleContainer.single(); + private Container container = Blade.me().container(); public ClassPathControllerLoader() { this(""); diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index d4eb990c1..2234c8ed9 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -18,6 +18,10 @@ import java.lang.reflect.Method; import java.util.Set; +import blade.kit.StringKit; +import blade.kit.resource.ClassPathClassReader; +import blade.kit.resource.ClassReader; + import com.blade.Blade; import com.blade.annotation.After; import com.blade.annotation.Before; @@ -26,11 +30,6 @@ import com.blade.annotation.Route; import com.blade.http.HttpMethod; import com.blade.ioc.Container; -import com.blade.ioc.SampleContainer; - -import blade.kit.StringKit; -import blade.kit.resource.ClassPathClassReader; -import blade.kit.resource.ClassReader; /** * @@ -46,12 +45,12 @@ public class RouteBuilder { /** * 默认路由后缀包,用户扫描路由所在位置,默认为route,用户可自定义 */ - private String PACKAGE_ROUTE = "route"; + private String pkgRoute = "route"; /** * 默认拦截器后缀包,用户扫描拦截器所在位置,默认为interceptor,用户可自定义 */ - private String PACKAGE_INTERCEPTOR = "interceptor"; + private String pkgInterceptor = "interceptor"; /** * 类读取器,用于在指定规则中扫描类 @@ -61,7 +60,7 @@ public class RouteBuilder { /** * IOC容器,存储路由到ioc中 */ - private Container container = SampleContainer.single(); + private Container container = null; private Blade blade; @@ -70,6 +69,7 @@ public class RouteBuilder { public RouteBuilder(Blade blade) { this.blade = blade; this.router = blade.router(); + this.container = blade.container(); } /** @@ -84,8 +84,8 @@ public void building() { String suffix = basePackage.endsWith(".*") ? ".*" : ""; basePackage = basePackage.endsWith(".*") ? basePackage.substring(0, basePackage.length() - 2) : basePackage; - String routePackage = basePackage + "." + PACKAGE_ROUTE + suffix; - String interceptorPackage = basePackage + "." + PACKAGE_INTERCEPTOR + suffix; + String routePackage = basePackage + "." + pkgRoute + suffix; + String interceptorPackage = basePackage + "." + pkgInterceptor + suffix; buildRoute(routePackage); buildInterceptor(interceptorPackage); diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 11dc34d37..3a2c37b81 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -20,17 +20,16 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import blade.kit.ReflectKit; +import blade.kit.log.Logger; + import com.blade.http.HttpMethod; import com.blade.http.HttpStatus; import com.blade.http.Request; import com.blade.http.Response; import com.blade.ioc.Container; -import com.blade.ioc.SampleContainer; import com.blade.ioc.Scope; -import blade.kit.ReflectKit; -import blade.kit.log.Logger; - /** * *

@@ -44,7 +43,7 @@ public class Routers { private Logger LOGGER = Logger.getLogger(Routers.class); - private final static Container container = SampleContainer.single(); + private Container container = null; private List routes = new CopyOnWriteArrayList(); @@ -52,6 +51,10 @@ public class Routers { private static final String METHOD_NAME = "handle"; + public Routers(Container container) { + this.container = container; + } + public void handle(Request request, Response response, Route route) throws Exception { request.setRoute(route); response.status(HttpStatus.NOT_FOUND); From b44c2ec7627ad1adf3f09832cc3335ae49c1b5a5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 30 Nov 2015 15:04:57 +0800 Subject: [PATCH 268/545] add aop support --- blade-aop/pom.xml | 33 +++ .../blade/aop/AbstractMethodInterceptor.java | 46 ++++ .../blade/aop/AbstractRouteInterceptor.java | 51 ++++ .../java/com/blade/aop/AdviceMatcher.java | 229 ++++++++++++++++++ .../blade/aop/DefaultMethodInvocation.java | 99 ++++++++ .../main/java/com/blade/aop/DefaultProxy.java | 93 +++++++ .../java/com/blade/aop/ProxyBeanFactory.java | 103 ++++++++ .../java/com/blade/aop/annotation/After.java | 33 +++ .../java/com/blade/aop/annotation/Before.java | 33 +++ .../aop/exception/AdviceMatcherException.java | 39 +++ .../intercept/AbstractMethodInterceptor.java | 46 ++++ .../AbstractMethodInterceptorFactory.java | 57 +++++ .../com/blade/aop/intercept/Interceptor.java | 24 ++ .../com/blade/aop/intercept/Invocation.java | 27 +++ .../com/blade/aop/intercept/Joinpoint.java | 27 +++ .../aop/intercept/MethodInterceptor.java | 33 +++ .../blade/aop/intercept/MethodInvocation.java | 33 +++ 17 files changed, 1006 insertions(+) create mode 100644 blade-aop/pom.xml create mode 100644 blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java create mode 100644 blade-aop/src/main/java/com/blade/aop/AbstractRouteInterceptor.java create mode 100644 blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java create mode 100644 blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java create mode 100644 blade-aop/src/main/java/com/blade/aop/DefaultProxy.java create mode 100644 blade-aop/src/main/java/com/blade/aop/ProxyBeanFactory.java create mode 100644 blade-aop/src/main/java/com/blade/aop/annotation/After.java create mode 100644 blade-aop/src/main/java/com/blade/aop/annotation/Before.java create mode 100644 blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java create mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptor.java create mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java create mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/Interceptor.java create mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/Invocation.java create mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/Joinpoint.java create mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/MethodInterceptor.java create mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/MethodInvocation.java diff --git a/blade-aop/pom.xml b/blade-aop/pom.xml new file mode 100644 index 000000000..5d0124938 --- /dev/null +++ b/blade-aop/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + blade-proxy + 1.0 + blade-proxy + http://maven.apache.org + + + UTF-8 + + + + + com.bladejava + blade-core + ${blade.version} + + + + cglib + cglib-nodep + 3.1 + + + diff --git a/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java b/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java new file mode 100644 index 000000000..839ccc9e9 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; + +import com.blade.aop.intercept.MethodInterceptor; +import com.blade.aop.intercept.MethodInvocation; + +/** + * 抽象方法拦截器 + * @author biezhi + * @since 1.0 + */ +public abstract class AbstractMethodInterceptor implements MethodInterceptor { + + /** + * 执行方法 + */ + public Object invoke(MethodInvocation invocation) throws Throwable { + Object result = invocation.proceed(); + return result; + } + + /** + * 前置执行 + */ + protected abstract void beforeAdvice(); + + /** + * 后置执行 + */ + protected abstract void afterAdvice(); + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/AbstractRouteInterceptor.java b/blade-aop/src/main/java/com/blade/aop/AbstractRouteInterceptor.java new file mode 100644 index 000000000..0a2ef716d --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/AbstractRouteInterceptor.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; +/** + * + * 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. + */ + +import com.blade.aop.intercept.MethodInvocation; + +/** + * 抽象路由拦截器 + * @author biezhi + * @since 1.0 + */ +public abstract class AbstractRouteInterceptor extends AbstractMethodInterceptor { + + @Override + public void beforeAdvice() { + } + + @Override + public void afterAdvice() { + } + + @Override + public abstract Object invoke(MethodInvocation invocation) throws Throwable; +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java b/blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java new file mode 100644 index 000000000..949e7e342 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import com.blade.aop.annotation.After; +import com.blade.aop.annotation.Before; +import com.blade.aop.exception.AdviceMatcherException; +import com.blade.aop.intercept.MethodInvocation; + +import blade.kit.log.Logger; + +/** + * 方法和切点的匹配器 + * @author biezhi + * @since 1.0 + */ +public class AdviceMatcher { + + private Logger logger = Logger.getLogger(AdviceMatcher.class); + + private AbstractMethodInterceptor interceptor; + private MethodInvocation invocation; + + public AdviceMatcher(AbstractMethodInterceptor interceptor, MethodInvocation invocation) { + this.interceptor = interceptor; + this.invocation = invocation; + } + + public boolean match(Class adviceAnnotationType, String joinPoint) { + // 要执行的方法 + try { + Method adviceMethod = interceptor.getClass().getDeclaredMethod(joinPoint, new Class[] {}); + if (adviceAnnotationType == Before.class) { + Before before = adviceMethod.getAnnotation(Before.class); + if (before == null) + return false; + String pointcut = before.expression(); + return beforeOrAfterMatch(pointcut, invocation.getMethod()); + } else if (adviceAnnotationType == After.class) { + After after = adviceMethod.getAnnotation(After.class); + if (after == null) + return false; + String pointcut = after.expression(); + return beforeOrAfterMatch(pointcut, invocation.getMethod()); + } + } catch (SecurityException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + logger.warn(joinPoint + ":" + e.getMessage()); + return false; + } + return true; + } + + /** + * 支持的方法名表达式有: + * 1)*xxx, 以*开头 + * 2)xxx*, 以*结尾 + * 3)* 所有 + * 4)没有*,指定方法名 + * 5)指定的annotation + * + * @param pointcut + * @param methodName + * @return + */ + private boolean beforeOrAfterMatch(String pointcut, Method method) { + + if(null == pointcut){ + return false; + } + // 注解/方法 + String[] pointcuts = pointcut.split(":"); + if(pointcuts.length == 1){ + // 注解 + return isMethod(pointcut, method); + } else{ + if(pointcuts.length == 2){ + String point1 = pointcuts[0]; + String point2 = pointcuts[1]; + // 第一个是注解,(expression = "注解:方法") + if(point1.startsWith("@")){ + return isAnnotationAndMatchMehtod(point1, point2, method); + } else{ + //(expression = "类:方法") + //(expression = "类:注解") + //(expression = "包:方法") + //(expression = "包:注解") + + // 类或者包级别 + if(isClass(point1, method) || isPackage(point1, method)){ + return isClassOrPackageMethod(point1, point2, method); + } + return false; + } + } + if(pointcuts.length == 3){ + //类:注解:方法 + String point1 = pointcuts[0]; + String point2 = pointcuts[1]; + String point3 = pointcuts[2]; + if(isClass(point1, method)){ + return isAnnotationAndMatchMehtod(point2, point3, method); + } + } + return false; + } + } + + private boolean isClassOrPackageMethod(String classPoint, String methodPoint, Method method){ + if(methodPoint.startsWith("@")){ + return isAnnotationMehtod(methodPoint, method); + } else{ + return isMatchMethod(methodPoint, method.getName()); + } + } + + private boolean isMethod(String pointcut, Method method){ + // 注解 + if(pointcut.startsWith("@")){ + return isAnnotationMehtod(pointcut, method); + } else{ + return isMatchMethod(pointcut, method.getName()); + } + } + + /** + * 是否匹配一个带注解的方法 + * @param pointcut + * @param method + * @return + */ + @SuppressWarnings("unchecked") + private boolean isAnnotationMehtod(String pointcut, Method method){ + try { + Class annotationClass = (Class) Class.forName(pointcut.substring(1)); + if(null != method.getAnnotation(annotationClass)){ + return true; + } + } catch (ClassNotFoundException e) { + throw new AdviceMatcherException("错误的注解类型"); + } + return false; + } + + /** + * 是否匹配一个表达式中的方法 + * @param pointcut + * @param methodName + * @return + */ + private boolean isMatchMethod(String pointcut, String methodName){ + int indexOfStar = pointcut.indexOf("*"); + if (indexOfStar != -1) {// 方法名中有*号 + if (indexOfStar == 0) {// 以*开头 + if ("*".equals(pointcut)) {// 只有* + return true; + } else { + return methodName.endsWith(pointcut.substring(1)); + } + } else {// 以*结尾,中间有*也算以*结尾 + return methodName.startsWith(pointcut.substring(0, indexOfStar)); + } + } else { + if(pointcut.indexOf(".") != -1){ + throw new AdviceMatcherException("错误的方法表达式"); + } + return methodName.equals(pointcut); + } + } + + /** + * 是否同时匹配annotation和method + * @param annotationPointcut + * @param methodPointcut + * @param method + * @return + */ + private boolean isAnnotationAndMatchMehtod(String annotationPointcut, String methodPointcut, Method method){ + boolean isMatch = isMatchMethod(methodPointcut, method.getName()); + boolean isAnnotation = isAnnotationMehtod(annotationPointcut, method); + return isMatch && isAnnotation; + } + + /** + * 判断给出的包名是否是方法所属包 + * @param packageName + * @param method + * @return + */ + private boolean isPackage(String packageName, Method method){ + if(null != packageName){ + String packName = method.getDeclaringClass().getPackage().getName(); + return packName.equals(packageName); + } + return false; + } + + /** + * 判断给出的类名是否是方法所属类 + * @param className + * @param method + * @return + */ + private boolean isClass(String className, Method method){ + if(null != className){ + String CanonicalName = method.getDeclaringClass().getCanonicalName(); + return CanonicalName.equals(className); + } + return false; + } + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java b/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java new file mode 100644 index 000000000..616564626 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Method; +import java.util.List; + +import com.blade.aop.annotation.After; +import com.blade.aop.annotation.Before; +import com.blade.aop.intercept.MethodInvocation; + +import blade.kit.log.Logger; + +/** + * 默认的方法执行器实现 + * @author biezhi + * @since 1.0 + */ +public class DefaultMethodInvocation implements MethodInvocation { + + private static final Logger LOGGER = Logger.getLogger(DefaultMethodInvocation.class); + + List interceptors; + private DefaultProxy proxy; + private Method method; + private Object target; + private Object[] args; + int index = 0; + private boolean executed = false; + + public DefaultMethodInvocation(DefaultProxy proxy, Method method, Object target, Object[] args, List interceptorChain) { + this.interceptors = interceptorChain; + this.method = method; + this.target = target; + this.args = args; + this.proxy = proxy; + } + + public Object proceed() throws Exception { + AbstractMethodInterceptor interceptor = null; + Object result = null; + if (interceptors.size() > 0 && index < interceptors.size()) { + interceptor = interceptors.get(index++); + if (new AdviceMatcher(interceptor, this).match(Before.class, "beforeAdvice")) { + interceptor.beforeAdvice(); // 执行前置建议 + } + proceed(); // 执行下一个拦截器 + } + // 执行真正的方法调用 + if (!executed) { + executed = true; + try { + result = method.invoke(target, args); + } catch (RuntimeException e) { + LOGGER.error(e.getMessage()); + } + } + if (index > 0) { + interceptor = interceptors.get(--index); + if (new AdviceMatcher(interceptor, this).match(After.class, "afterAdvice")) { + interceptor.afterAdvice(); // 执行后置建议 + } + } + return result; + } + + public Object getThis() { + return target; + } + + public AccessibleObject getStaticPart() { + return null; + } + + public Method getMethod() { + return method; + } + + public DefaultProxy getProxy() { + return proxy; + } + + public Object[] getArguments() { + return args; + } +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/DefaultProxy.java b/blade-aop/src/main/java/com/blade/aop/DefaultProxy.java new file mode 100644 index 000000000..96fd8caea --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/DefaultProxy.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; +/** + * + * 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. + */ + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +/** + * 默认代理获取类 + * @author biezhi + * @since 1.0 + */ +public class DefaultProxy implements MethodInterceptor { + + private Object target; + private List interceptorChain = new ArrayList(); + + public DefaultProxy(Object target, List interceptorChain) { + this.target = target; + if (interceptorChain != null && interceptorChain.size() > 0) { + this.interceptorChain.addAll(interceptorChain); + } + } + + public void addInterceptor(AbstractMethodInterceptor abstractMethodInterceptor){ + interceptorChain.add(abstractMethodInterceptor); + } + + public Object getProxy(Object target) { + this.target = target; + // cglib 中加强器,用来创建动态代理 + Enhancer enhancer = new Enhancer(); + // 设置要创建动态代理的类 + enhancer.setSuperclass(target.getClass()); + // 设置回调,这里相当于是对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实行intercept()方法进行拦截 + enhancer.setCallback(this); + Object proxy = enhancer.create(); + return proxy; + } + + public Object getProxy() { + // cglib 中加强器,用来创建动态代理 + Enhancer enhancer = new Enhancer(); + // 设置要创建动态代理的类 + enhancer.setSuperclass(target.getClass()); + // 设置回调,这里相当于是对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实行intercept()方法进行拦截 + enhancer.setCallback(this); + Object proxy = enhancer.create(); + return proxy; + } + + @Override + public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { + DefaultMethodInvocation methodInvocation = new DefaultMethodInvocation(this, method, target, args, interceptorChain); + return methodInvocation.proceed(); + } + + public Object getTarget() { + return target; + } +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/ProxyBeanFactory.java b/blade-aop/src/main/java/com/blade/aop/ProxyBeanFactory.java new file mode 100644 index 000000000..b8d3d6a14 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/ProxyBeanFactory.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; +/** + * + * 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. + */ + +import java.util.Arrays; +import java.util.List; + +/** + * 单例的代理工厂 + * @author biezhi + * @since 1.0 + */ +public class ProxyBeanFactory { + + private ProxyBeanFactory() { + } + + public static ProxyBeanFactory single() { + return SingleHoder.single; + } + + private static class SingleHoder { + + private static final ProxyBeanFactory single = new ProxyBeanFactory(); + } + + /** + * + * @param targetClazz 创建指定类target实例 + * @param chain 系统的拦截器链 + * @return + */ + public Object newProxy(Class targetClazz, List chain) { + Object proxyBean = null; + try { + Object target = targetClazz.newInstance(); + proxyBean = new DefaultProxy(target, chain).getProxy(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return proxyBean; + } + + public Object newProxy(Class targetClazz, AbstractMethodInterceptor ... chain) { + Object proxyBean = null; + try { + Object target = targetClazz.newInstance(); + List chainList = null; + if(null != chain && chain.length > 0){ + chainList = Arrays.asList(chain); + } + proxyBean = new DefaultProxy(target, chainList).getProxy(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return proxyBean; + } + + public Object newProxy(Object target, AbstractMethodInterceptor ... chain) { + List chainList = null; + if(null != chain && chain.length > 0){ + chainList = Arrays.asList(chain); + } + Object proxyBean = new DefaultProxy(target, chainList).getProxy(); + return proxyBean; + } + + public Object newProxy(Object target, List chain) { + Object proxyBean = new DefaultProxy(target, chain).getProxy(); + return proxyBean; + } +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/annotation/After.java b/blade-aop/src/main/java/com/blade/aop/annotation/After.java new file mode 100644 index 000000000..7335711f3 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/annotation/After.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 后置执行注解 + * @author biezhi + * @since 1.0 + */ +@Target(value={ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface After{ + + String expression() default ""; +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/annotation/Before.java b/blade-aop/src/main/java/com/blade/aop/annotation/Before.java new file mode 100644 index 000000000..881d428e5 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/annotation/Before.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 前置执行注解 + * @author biezhi + * @since 1.0 + */ +@Target(value={ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Before { + + String expression() default ""; + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java b/blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java new file mode 100644 index 000000000..33c699711 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.exception; + +/** + * 切入点匹配异常 + * @author biezhi + * @since 1.0 + */ +public class AdviceMatcherException extends RuntimeException { + + private static final long serialVersionUID = -5143613620732802399L; + + public AdviceMatcherException() { + super(); + } + + public AdviceMatcherException(Exception e) { + super(e); + } + + public AdviceMatcherException(String msg) { + super(msg); + } + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptor.java b/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptor.java new file mode 100644 index 000000000..e17ba6116 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptor.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; + +import com.blade.aop.intercept.MethodInterceptor; +import com.blade.aop.intercept.MethodInvocation; + +/** + * 抽象方法拦截器 + * @author biezhi + * @since 1.0 + */ +public abstract class AbstractMethodInterceptor implements MethodInterceptor { + + /** + * 执行方法 + */ + public Object invoke(MethodInvocation invocation) throws Throwable { + Object result = invocation.proceed(); + return result; + } + + /** + * 前置执行 + */ + protected abstract void beforeAdvice(); + + /** + * 后置执行 + */ + protected abstract void afterAdvice(); + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java b/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java new file mode 100644 index 000000000..4f2df75d0 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; + +import java.util.ArrayList; +import java.util.List; + +/** + * 拦截器方法工厂 + * @author biezhi + * @since 1.0 + */ +public final class AbstractMethodInterceptorFactory { + + /** + * 普通拦截器列表 + */ + private static final List interceptorList = new ArrayList(); + + /** + * 获取所有普通拦截器 + * @return + */ + public static List getAbstractInterceptors() { + return interceptorList; + } + + /** + * 添加一个拦截器 + * @param routeInterceptors + */ + public static void addInterceptor(List routeInterceptors) { + interceptorList.addAll(routeInterceptors); + } + + /** + * 添加一组拦截器 + * @param routeInterceptor + */ + public static void addInterceptor(AbstractMethodInterceptor routeInterceptor) { + interceptorList.add(routeInterceptor); + } + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/Interceptor.java b/blade-aop/src/main/java/com/blade/aop/intercept/Interceptor.java new file mode 100644 index 000000000..0e39ed7b5 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/intercept/Interceptor.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; + +/** + * 拦截器顶层接口 + * @author biezhi + * @since 1.0 + */ +public interface Interceptor { +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/Invocation.java b/blade-aop/src/main/java/com/blade/aop/intercept/Invocation.java new file mode 100644 index 000000000..4894cf547 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/intercept/Invocation.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; + +/** + * 执行器接口 + * @author biezhi + * @since 1.0 + */ +public interface Invocation extends Joinpoint { + + Object[] getArguments(); + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/Joinpoint.java b/blade-aop/src/main/java/com/blade/aop/intercept/Joinpoint.java new file mode 100644 index 000000000..ed162d02d --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/intercept/Joinpoint.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; + +/** + * 切入点 + * @author biezhi + * @since 1.0 + */ +public interface Joinpoint { + + Object proceed() throws Throwable; + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/MethodInterceptor.java b/blade-aop/src/main/java/com/blade/aop/intercept/MethodInterceptor.java new file mode 100644 index 000000000..68c33c9ab --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/intercept/MethodInterceptor.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; + +/** + * 方法拦截器 + * @author biezhi + * @since 1.0 + */ +public interface MethodInterceptor extends Interceptor{ + + /** + * 执行方法 + * @param invocation + * @return + * @throws Throwable + */ + public Object invoke(MethodInvocation invocation) throws Throwable; + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/MethodInvocation.java b/blade-aop/src/main/java/com/blade/aop/intercept/MethodInvocation.java new file mode 100644 index 000000000..400e3a76d --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/intercept/MethodInvocation.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; + +import java.lang.reflect.Method; + +/** + * 方法执行器 + * @author biezhi + * @since 1.0 + */ +public interface MethodInvocation extends Invocation { + + /** + * 获取方法 + * @return + */ + Method getMethod(); + +} \ No newline at end of file From 641ec9135db9feac0d64fdfe6bbf90f6f18d6031 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 30 Nov 2015 15:05:12 +0800 Subject: [PATCH 269/545] add aop support --- blade-proxy/src/main/java/com/blade/proxy/Proxy.java | 5 ----- pom.xml | 5 +++-- 2 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 blade-proxy/src/main/java/com/blade/proxy/Proxy.java diff --git a/blade-proxy/src/main/java/com/blade/proxy/Proxy.java b/blade-proxy/src/main/java/com/blade/proxy/Proxy.java deleted file mode 100644 index c909d3786..000000000 --- a/blade-proxy/src/main/java/com/blade/proxy/Proxy.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.blade.proxy; - -public interface Proxy { - -} diff --git a/pom.xml b/pom.xml index d5108eaa3..bab5e895f 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.4.1 + 1.4.2-alpha 4.12 @@ -26,7 +26,8 @@ blade-sql2o blade-redis blade-startup - blade-sample + blade-sample + blade-aop From f0a1ae28961421f41d3a51a330e2041b6ed47448 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 2 Dec 2015 18:24:33 +0800 Subject: [PATCH 270/545] add blade oauth2 --- .../main/java/com/blade/http/HttpStatus.java | 2 +- .../src/main/java/com/blade/oauth2/OAuth.java | 67 +++ .../java/com/blade/oauth2/OAuthError.java | 131 ++++++ .../java/com/blade/oauth2/OAuthRequest.java | 51 +++ .../java/com/blade/oauth2/OAuthResponse.java | 183 ++++++++ .../oauth2/base/request/OAuthBaseRequest.java | 90 ++++ .../base/request/OAuthTokenBaseRequest.java | 68 +++ .../base/validator/OAuthBaseValidator.java | 135 ++++++ .../oauth2/base/validator/OAuthValidator.java | 30 ++ .../exception/OAuthProblemException.java | 97 +++++ .../com/blade/oauth2/issuer/MD5Generator.java | 15 + .../com/blade/oauth2/issuer/OAuthIssuer.java | 19 + .../blade/oauth2/issuer/OAuthIssuerKit.java | 31 ++ .../oauth2/issuer/UUIDValueGenerator.java | 20 + .../blade/oauth2/issuer/ValueGenerator.java | 21 + .../java/com/blade/oauth2/kit/OAuthKit.java | 408 ++++++++++++++++++ .../blade/oauth2/message/OAuthMessage.java | 31 ++ .../blade/oauth2/message/types/GrantType.java | 29 ++ .../oauth2/message/types/ParameterStyle.java | 27 ++ .../oauth2/message/types/ResponseType.java | 26 ++ .../blade/oauth2/message/types/TokenType.java | 26 ++ .../parameters/JSONBodyParametersApplier.java | 21 + .../oauth2/request/OAuthGrantRequest.java | 48 +++ .../com/blade/oauth2/request/RequestType.java | 27 ++ .../oauth2/response/OAuthASResponse.java | 137 ++++++ .../validator/AuthorizationCodeValidator.java | 28 ++ .../validator/AuthorizationValidator.java | 158 +++++++ .../validator/ClientCredentialValidator.java | 51 +++ .../validator/ImplicitCodeValidator.java | 188 ++++++++ .../PasswordCredentialValidator.java | 124 ++++++ .../validator/RefreshTokenValidator.java | 90 ++++ 31 files changed, 2378 insertions(+), 1 deletion(-) create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/OAuth.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/OAuthError.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/exception/OAuthProblemException.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/issuer/MD5Generator.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuer.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuerKit.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/issuer/UUIDValueGenerator.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/issuer/ValueGenerator.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/message/OAuthMessage.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/message/types/GrantType.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/message/types/ParameterStyle.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/message/types/ResponseType.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/message/types/TokenType.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/request/RequestType.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java create mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java diff --git a/blade-core/src/main/java/com/blade/http/HttpStatus.java b/blade-core/src/main/java/com/blade/http/HttpStatus.java index e0507ea7a..85f18b158 100644 --- a/blade-core/src/main/java/com/blade/http/HttpStatus.java +++ b/blade-core/src/main/java/com/blade/http/HttpStatus.java @@ -45,5 +45,5 @@ public final class HttpStatus { public static final int NOT_IMPLEMENTED = 501; public static final int OVERLOADED = 502; public static final int GATEWAY_TIMEOUT = 503; - + } diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuth.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuth.java new file mode 100644 index 000000000..863bd282d --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/OAuth.java @@ -0,0 +1,67 @@ +package com.blade.oauth2; + +import com.blade.oauth2.message.types.ParameterStyle; +import com.blade.oauth2.message.types.TokenType; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public final class OAuth { + + public static final class HttpMethod { + public static final String POST = "POST"; + public static final String GET = "GET"; + public static final String DELETE = "DELETE"; + public static final String PUT = "PUT"; + } + + public static final class HeaderType { + public static final String CONTENT_TYPE = "Content-Type"; + public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; + public static final String AUTHORIZATION = "Authorization"; + } + + public static final class WWWAuthHeader { + public static final String REALM = "realm"; + } + + public static final class ContentType { + public static final String URL_ENCODED = "application/x-www-form-urlencoded"; + public static final String JSON = "application/json"; + } + + public static final String OAUTH_RESPONSE_TYPE = "response_type"; + public static final String OAUTH_CLIENT_ID = "client_id"; + public static final String OAUTH_CLIENT_SECRET = "client_secret"; + public static final String OAUTH_REDIRECT_URI = "redirect_uri"; + public static final String OAUTH_USERNAME = "username"; + public static final String OAUTH_PASSWORD = "password"; + public static final String OAUTH_ASSERTION_TYPE = "assertion_type"; + public static final String OAUTH_ASSERTION = "assertion"; + public static final String OAUTH_SCOPE = "scope"; + public static final String OAUTH_STATE = "state"; + public static final String OAUTH_GRANT_TYPE = "grant_type"; + + public static final String OAUTH_HEADER_NAME = "Bearer"; + + //Authorization response params + public static final String OAUTH_CODE = "code"; + public static final String OAUTH_ACCESS_TOKEN = "access_token"; + public static final String OAUTH_EXPIRES_IN = "expires_in"; + public static final String OAUTH_REFRESH_TOKEN = "refresh_token"; + public static final String OAUTH_EXAMPLE_PARAMETER = "example_parameter"; + + public static final String OAUTH_TOKEN_TYPE = "token_type"; + + public static final String OAUTH_TOKEN = "oauth_token"; + + public static final String OAUTH_TOKEN_DRAFT_0 = "access_token"; + public static final String OAUTH_BEARER_TOKEN = "access_token"; + + public static final ParameterStyle DEFAULT_PARAMETER_STYLE = ParameterStyle.HEADER; + public static final TokenType DEFAULT_TOKEN_TYPE = TokenType.BEARER; + + public static final String OAUTH_VERSION_DIFFER = "oauth_signature_method"; +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthError.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthError.java new file mode 100644 index 000000000..d385da27e --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthError.java @@ -0,0 +1,131 @@ +package com.blade.oauth2; + +public abstract class OAuthError { + + //error response params + public static final String OAUTH_ERROR = "error"; + public static final String OAUTH_ERROR_DESCRIPTION = "error_description"; + public static final String OAUTH_ERROR_URI = "error_uri"; + + public static final class CodeResponse { + /** + * The request is missing a required parameter, includes an + unsupported parameter value, or is otherwise malformed. + */ + public static final String INVALID_REQUEST = "invalid_request"; + + /** + * The client is not authorized to request an authorization + code using this method. + */ + public static final String UNAUTHORIZED_CLIENT = "unauthorized_client"; + + /** + * The resource owner or authorization server denied the + request. + */ + public static final String ACCESS_DENIED = "access_denied"; + + /** + * The authorization server does not support obtaining an + authorization code using this method. + */ + public static final String UNSUPPORTED_RESPONSE_TYPE = "unsupported_response_type"; + + /** + * The requested scope is invalid, unknown, or malformed. + */ + public static final String INVALID_SCOPE = "invalid_scope"; + + /** + * The authorization server encountered an unexpected + condition which prevented it from fulfilling the request. + */ + public static final String SERVER_ERROR = "server_error"; + + /** + * The authorization server is currently unable to handle + the request due to a temporary overloading or maintenance + of the server. + */ + public static final String TEMPORARILY_UNAVAILABLE = "temporarily_unavailable"; + + } + + public static final class TokenResponse { + /** + The request is missing a required parameter, includes an + unsupported parameter value, repeats a parameter, + includes multiple credentials, utilizes more than one + mechanism for authenticating the client, or is otherwise + malformed. + */ + public static final String INVALID_REQUEST = "invalid_request"; + /** + Client authentication failed (e.g. unknown client, no + client authentication included, or unsupported + authentication method). The authorization server MAY + return an HTTP 401 (Unauthorized) status code to indicate + which HTTP authentication schemes are supported. If the + client attempted to authenticate via the "Authorization" + request header field, the authorization server MUST + respond with an HTTP 401 (Unauthorized) status code, and + include the "WWW-Authenticate" response header field + matching the authentication scheme used by the client. + */ + public static final String INVALID_CLIENT = "invalid_client"; + + /** + The provided authorization grant (e.g. authorization + code, resource owner credentials, client credentials) is + invalid, expired, revoked, does not match the redirection + URI used in the authorization request, or was issued to + another client. + */ + public static final String INVALID_GRANT = "invalid_grant"; + + /** + The authenticated client is not authorized to use this + authorization grant type. + */ + public static final String UNAUTHORIZED_CLIENT = "unauthorized_client"; + + /** + The authorization grant type is not supported by the + authorization server. + */ + public static final String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type"; + + /** + * The requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner. + */ + public static final String INVALID_SCOPE = "invalid_scope"; + } + + public static final class ResourceResponse { + /** + The request is missing a required parameter, includes an + unsupported parameter value, repeats a parameter, + includes multiple credentials, utilizes more than one + mechanism for authenticating the client, or is otherwise + malformed. + */ + public static final String INVALID_REQUEST = "invalid_request"; + + + public static final String EXPIRED_TOKEN = "expired_token"; + + /** + * The request requires higher privileges than provided by the + * access token. + */ + public static final String INSUFFICIENT_SCOPE = "insufficient_scope"; + + /** + * The access token provided is expired, revoked, malformed, or + * invalid for other reasons. + */ + public static final String INVALID_TOKEN = "invalid_token"; + } + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java new file mode 100644 index 000000000..48e58927a --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java @@ -0,0 +1,51 @@ +/** + * + */ +package com.blade.oauth2; + +import blade.kit.ReflectKit; +import blade.kit.StringKit; + +import com.blade.http.Request; +import com.blade.oauth2.base.request.OAuthBaseRequest; +import com.blade.oauth2.base.validator.OAuthValidator; +import com.blade.oauth2.exception.OAuthProblemException; +import com.blade.oauth2.kit.OAuthKit; +import com.blade.oauth2.message.types.ResponseType; +import com.blade.oauth2.validator.AuthorizationValidator; +import com.blade.oauth2.validator.ImplicitCodeValidator; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class OAuthRequest extends OAuthBaseRequest { + + public OAuthRequest(Request request) + throws OAuthProblemException { + super(request); + } + + @Override + protected OAuthValidator initValidator() throws OAuthProblemException { + // end user authorization validators + validators.put(ResponseType.CODE.toString(), AuthorizationValidator.class); + validators.put(ResponseType.TOKEN.toString(), ImplicitCodeValidator.class); + final String requestTypeValue = getParam(OAuth.OAUTH_RESPONSE_TYPE); + if (StringKit.isBlank(requestTypeValue)) { + throw OAuthKit.handleOAuthProblemException("Missing response_type parameter value"); + } + final Class> clazz = validators + .get(requestTypeValue); + if (clazz == null) { + throw OAuthKit.handleOAuthProblemException("Invalid response_type parameter value"); + } + return (OAuthValidator) ReflectKit.newInstance(clazz); + } + + public String getResponseType() { + return getParam(OAuth.OAUTH_RESPONSE_TYPE); + } + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java new file mode 100644 index 000000000..91be98322 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java @@ -0,0 +1,183 @@ +package com.blade.oauth2; + +import java.util.HashMap; +import java.util.Map; + +import blade.kit.StringKit; + +import com.blade.http.HttpStatus; +import com.blade.http.Request; +import com.blade.oauth2.exception.OAuthProblemException; +import com.blade.oauth2.message.OAuthMessage; +import com.blade.oauth2.parameters.JSONBodyParametersApplier; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class OAuthResponse implements OAuthMessage { + + protected int responseStatus; + protected String uri; + protected String body; + + protected Map headers = new HashMap(); + + protected OAuthResponse(String uri, int responseStatus) { + this.uri = uri; + this.responseStatus = responseStatus; + } + + public static OAuthResponseBuilder status(int code) { + return new OAuthResponseBuilder(code); + } + + public static OAuthErrorResponseBuilder errorResponse(int code, Request request) { + return new OAuthErrorResponseBuilder(code, request); + } + + public static OAuthErrorResponseBuilder errorUnAuthResponse(Request request) { + OAuthErrorResponseBuilder errorRep = new OAuthErrorResponseBuilder(HttpStatus.UNAUTHORIZED, request); + errorRep.setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT); + return errorRep; + } + + public static OAuthErrorResponseBuilder errorBadReqResponse(Request request) { + return new OAuthErrorResponseBuilder(HttpStatus.BAD_REQUEST, request); + } + + @Override + public String getLocationUri() { + return uri; + } + + @Override + public void setLocationUri(String uri) { + this.uri = uri; + } + + @Override + public String getBody() { + return body; + } + + @Override + public void setBody(String body) { + this.body = body; + } + + @Override + public String getHeader(String name) { + return headers.get(name); + } + + @Override + public Map getHeaders() { + return headers; + } + + @Override + public void setHeaders(Map headers) { + this.headers = headers; + } + + public int getResponseStatus() { + return responseStatus; + } + + @Override + public void addHeader(String name, String header) { + headers.put(name, header); + } + + public static class OAuthResponseBuilder { + + protected JSONBodyParametersApplier applier; + protected Map parameters = new HashMap(); + protected int responseCode; + protected String location; + + public OAuthResponseBuilder(int responseCode) { + this.responseCode = responseCode; + } + + public OAuthResponseBuilder location(String location) { + this.location = location; + return this; + } + + public OAuthResponseBuilder setScope(String value) { + this.parameters.put(OAuth.OAUTH_SCOPE, value); + return this; + } + + public OAuthResponseBuilder setParam(String key, String value) { + this.parameters.put(key, value); + return this; + } + + public OAuthResponse buildJSONMessage() { + OAuthResponse msg = new OAuthResponse(location, responseCode); + this.applier = new JSONBodyParametersApplier(); + return (OAuthResponse)applier.applyOAuthParameters(msg, parameters); + } + + } + + public static class OAuthErrorResponseBuilder extends OAuthResponseBuilder { + + public OAuthErrorResponseBuilder(int responseCode, Request request) { + super(responseCode); + + String state = request.query(OAuth.OAUTH_STATE); + if (StringKit.isNotBlank(state)){ + this.setState(state); + }else{ + this.setState(null); + } + + String errorUri = request.query(OAuthError.OAUTH_ERROR_URI); + if (StringKit.isNotBlank(errorUri)) { + this.setErrorUri(errorUri); + } + } + + public OAuthErrorResponseBuilder error(OAuthProblemException ex) { + this.parameters.put(OAuthError.OAUTH_ERROR, ex.getError()); + this.parameters.put(OAuthError.OAUTH_ERROR_DESCRIPTION, ex.getDescription()); + return this; + } + + public OAuthErrorResponseBuilder setError(String error) { + this.parameters.put(OAuthError.OAUTH_ERROR, error); + return this; + } + + public OAuthErrorResponseBuilder setErrorDescription(String desc) { + this.parameters.put(OAuthError.OAUTH_ERROR_DESCRIPTION, desc); + return this; + } + + public OAuthErrorResponseBuilder setErrorUri(String state) { + this.parameters.put(OAuthError.OAUTH_ERROR_URI, state); + return this; + } + + public OAuthErrorResponseBuilder setState(String state) { + this.parameters.put(OAuth.OAUTH_STATE, state); + return this; + } + + public OAuthErrorResponseBuilder setRealm(String realm) { + this.parameters.put(OAuth.WWWAuthHeader.REALM, realm); + return this; + } + + public OAuthErrorResponseBuilder location(String location) { + this.location = location; + return this; + } + } + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java new file mode 100644 index 000000000..299b0d066 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java @@ -0,0 +1,90 @@ +/** + * + */ + +package com.blade.oauth2.base.request; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.base.validator.OAuthValidator; +import com.blade.oauth2.exception.OAuthProblemException; +import com.blade.oauth2.kit.OAuthKit; + +/** + * The Abstract OAuth request for the Authorization server. + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public abstract class OAuthBaseRequest { + + protected Request request; + protected OAuthValidator validator; + + protected Map>> validators = + new HashMap>>(); + + public OAuthBaseRequest(Request request) throws OAuthProblemException { + this.request = request; + validate(); + } + + public OAuthBaseRequest() { + } + + protected void validate() throws OAuthProblemException { + validator = initValidator(); + validator.validateMethod(request); + validator.validateContentType(request); + validator.validateRequiredParameters(request); + validator.validateClientAuthenticationCredentials(request); + } + + protected abstract OAuthValidator initValidator() throws OAuthProblemException; + + public String getParam(String name) { + return request.query(name); + } + + public String getClientId() { + String[] creds = OAuthKit.decodeClientAuthenticationHeader(request.header(OAuth.HeaderType.AUTHORIZATION)); + if (creds != null) { + return creds[0]; + } + return getParam(OAuth.OAUTH_CLIENT_ID); + } + + public String getRedirectURI() { + return getParam(OAuth.OAUTH_REDIRECT_URI); + } + + public String getClientSecret() { + String[] creds = OAuthKit.decodeClientAuthenticationHeader(request.header(OAuth.HeaderType.AUTHORIZATION)); + if (creds != null) { + return creds[1]; + } + return getParam(OAuth.OAUTH_CLIENT_SECRET); + } + + /** + * + * @return + */ + public boolean isClientAuthHeaderUsed() { + return OAuthKit.decodeClientAuthenticationHeader(request.header(OAuth.HeaderType.AUTHORIZATION)) != null; + } + + public String getState() { + return getParam(OAuth.OAUTH_STATE); + } + + public Set getScopes() { + String scopes = getParam(OAuth.OAUTH_SCOPE); + return OAuthKit.decodeScopes(scopes); + } + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java new file mode 100644 index 000000000..7d7423a1b --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java @@ -0,0 +1,68 @@ +/** + * + */ + +package com.blade.oauth2.base.request; + +import blade.kit.ReflectKit; +import blade.kit.StringKit; + +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.base.validator.OAuthValidator; +import com.blade.oauth2.exception.OAuthProblemException; +import com.blade.oauth2.kit.OAuthKit; + +/** + * Abstract OAuth Token request class + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public abstract class OAuthTokenBaseRequest extends OAuthBaseRequest { + + protected OAuthTokenBaseRequest(Request request) + throws OAuthProblemException { + super(request); + } + + protected OAuthValidator initValidator() + throws OAuthProblemException { + final String requestTypeValue = getParam(OAuth.OAUTH_GRANT_TYPE); + if (StringKit.isBlank(requestTypeValue)) { + throw OAuthKit + .handleOAuthProblemException("Missing grant_type parameter value"); + } + final Class> clazz = validators + .get(requestTypeValue); + if (clazz == null) { + throw OAuthKit + .handleOAuthProblemException("Invalid grant_type parameter value"); + } + return (OAuthValidator) ReflectKit.newInstance(clazz); + } + + public String getPassword() { + return getParam(OAuth.OAUTH_PASSWORD); + } + + public String getUsername() { + return getParam(OAuth.OAUTH_USERNAME); + } + + public String getRefreshToken() { + return getParam(OAuth.OAUTH_REFRESH_TOKEN); + } + + /** + * response_type : code, 中获得的code + * @return + */ + public String getCode() { + return getParam(OAuth.OAUTH_CODE); + } + + public String getGrantType() { + return getParam(OAuth.OAUTH_GRANT_TYPE); + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java new file mode 100644 index 000000000..f9d8fdc3c --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java @@ -0,0 +1,135 @@ +/** + * + */ +package com.blade.oauth2.base.validator; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import blade.kit.StringKit; + +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.exception.OAuthProblemException; +import com.blade.oauth2.kit.OAuthKit; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + * @param + */ +public abstract class OAuthBaseValidator implements OAuthValidator { + + protected List requiredParams = new ArrayList(); + protected Map optionalParams = new HashMap(); + protected List notAllowedParams = new ArrayList(); + protected boolean enforceClientAuthentication = false; + + @Override + public void validateMethod(T request) throws OAuthProblemException { + if (!request.method().equals(OAuth.HttpMethod.POST)) { + throw OAuthKit.handleOAuthProblemException("Method not set to POST."); + } + } + + @Override + public void validateContentType(T request) throws OAuthProblemException { + String contentType = request.contentType(); + final String expectedContentType = OAuth.ContentType.URL_ENCODED; + if (!OAuthKit.hasContentType(contentType, expectedContentType)) { + throw OAuthKit.handleBadContentTypeException(expectedContentType); + } + } + + @Override + public void validateRequiredParameters(T request) throws OAuthProblemException { + final Set missingParameters = new HashSet(); + for (String requiredParam : requiredParams) { + String val = request.query(requiredParam); + if (StringKit.isNotBlank(val)) { + missingParameters.add(requiredParam); + } + } + if (!missingParameters.isEmpty()) { + throw OAuthKit.handleMissingParameters(missingParameters); + } + } + + @Override + public void validateOptionalParameters(T request) throws OAuthProblemException { + final Set missingParameters = new HashSet(); + + for (Map.Entry requiredParam : optionalParams.entrySet()) { + final String paramName = requiredParam.getKey(); + String val = request.query(paramName); + if (StringKit.isNotBlank(val)) { + String[] dependentParams = requiredParam.getValue(); + if (null!=dependentParams&&dependentParams.length > 0) { + for (String dependentParam : dependentParams) { + val = request.query(dependentParam); + if (StringKit.isBlank(val)) { + missingParameters.add(dependentParam); + } + } + } + } + } + + if (!missingParameters.isEmpty()) { + throw OAuthKit.handleMissingParameters(missingParameters); + } + } + + @Override + public void validateNotAllowedParameters(T request) throws OAuthProblemException { + List notAllowedParameters = new ArrayList(); + for (String requiredParam : notAllowedParams) { + String val = request.query(requiredParam); + if (StringKit.isNotBlank(val)) { + notAllowedParameters.add(requiredParam); + } + } + if (!notAllowedParameters.isEmpty()) { + throw OAuthKit.handleNotAllowedParametersOAuthException(notAllowedParameters); + } + } + + @Override + public void validateClientAuthenticationCredentials(T request) throws OAuthProblemException { + if (enforceClientAuthentication) { + Set missingParameters = new HashSet(); + String clientAuthHeader = request.header(OAuth.HeaderType.AUTHORIZATION); + String[] clientCreds = OAuthKit.decodeClientAuthenticationHeader(clientAuthHeader); + + // Only fallback to params if the auth header is not correct. Don't allow a mix of auth header vs params + if (clientCreds == null || StringKit.isBlank(clientCreds[0]) || StringKit.isBlank(clientCreds[1])) { + + if (StringKit.isBlank(request.query(OAuth.OAUTH_CLIENT_ID))) { + missingParameters.add(OAuth.OAUTH_CLIENT_ID); + } + if (StringKit.isBlank(request.query(OAuth.OAUTH_CLIENT_SECRET))) { + missingParameters.add(OAuth.OAUTH_CLIENT_SECRET); + } + } + + if (!missingParameters.isEmpty()) { + throw OAuthKit.handleMissingParameters(missingParameters); + } + } + } + + @Override + public void performAllValidations(T request) throws OAuthProblemException { + this.validateContentType(request); + this.validateMethod(request); + this.validateRequiredParameters(request); + this.validateOptionalParameters(request); + this.validateNotAllowedParameters(request); + this.validateClientAuthenticationCredentials(request); + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java new file mode 100644 index 000000000..469f467ac --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java @@ -0,0 +1,30 @@ +/** + */ +package com.blade.oauth2.base.validator; + +import com.blade.http.Request; +import com.blade.oauth2.exception.OAuthProblemException; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + * @param + */ +public interface OAuthValidator { + + public void validateMethod(T request) throws OAuthProblemException; + + public void validateContentType(T request) throws OAuthProblemException; + + public void validateRequiredParameters(T request) throws OAuthProblemException; + + public void validateOptionalParameters(T request) throws OAuthProblemException; + + public void validateNotAllowedParameters(T request) throws OAuthProblemException; + + public void validateClientAuthenticationCredentials(T request) throws OAuthProblemException; + + public void performAllValidations(T request) throws OAuthProblemException; + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/exception/OAuthProblemException.java b/blade-oauth2/src/main/java/com/blade/oauth2/exception/OAuthProblemException.java new file mode 100644 index 000000000..e80d72146 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/exception/OAuthProblemException.java @@ -0,0 +1,97 @@ + +package com.blade.oauth2.exception; + +import java.util.HashMap; +import java.util.Map; + +import blade.kit.StringKit; + +public class OAuthProblemException extends IllegalArgumentException { + + /** + * + */ + private static final long serialVersionUID = 1536483571040822380L; + private String error; + private String description; + + private int responseStatus; + + private Map parameters = new HashMap(); + + protected OAuthProblemException(String error) { + this(error, ""); + } + + protected OAuthProblemException(String error, String description) { + super(error + " " + description); + this.description = description; + this.error = error; + } + + public static OAuthProblemException error(String error) { + return new OAuthProblemException(error); + } + + public static OAuthProblemException error(String error, String description) { + return new OAuthProblemException(error, description); + } + + public OAuthProblemException description(String description) { + this.description = description; + return this; + } + + public OAuthProblemException responseStatus(int responseStatus) { + this.responseStatus = responseStatus; + return this; + } + + public OAuthProblemException setParameter(String name, String value) { + parameters.put(name, value); + return this; + } + + public String getError() { + return error; + } + + public String getDescription() { + return description; + } + + public int getResponseStatus() { + return responseStatus == 0 ? 400 : responseStatus; + } + + public String get(String name) { + return parameters.get(name); + } + + public Map getParameters() { + return parameters; + } + + @Override + public String getMessage() { + StringBuilder b = new StringBuilder(); + if (StringKit.isNotBlank(error)) { + b.append(error); + } + + if (StringKit.isNotBlank(description)) { + b.append(", ").append(description); + } + return b.toString(); + } + + @Override + public String toString() { + return "OAuthProblemException{" + + "error='" + error + '\'' + + ", description='" + description + '\'' + + ", responseStatus=" + responseStatus + + ", parameters=" + parameters + + '}'; + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/MD5Generator.java b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/MD5Generator.java new file mode 100644 index 000000000..b777c67ed --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/MD5Generator.java @@ -0,0 +1,15 @@ +/** + * + */ +package com.blade.oauth2.issuer; + +import blade.kit.EncrypKit; + +public class MD5Generator extends ValueGenerator { + + @Override + public String generateValue(String param) { + return EncrypKit.md5(param); + } + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuer.java b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuer.java new file mode 100644 index 000000000..62fac8e4f --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuer.java @@ -0,0 +1,19 @@ +/** + * + */ + +package com.blade.oauth2.issuer; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public interface OAuthIssuer { + + public String accessToken(); + + public String authorizationCode(); + + public String refreshToken(); +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuerKit.java b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuerKit.java new file mode 100644 index 000000000..ee3284352 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuerKit.java @@ -0,0 +1,31 @@ +/** + * + */ + +package com.blade.oauth2.issuer; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class OAuthIssuerKit implements OAuthIssuer { + + private ValueGenerator vg; + + public OAuthIssuerKit(ValueGenerator vg) { + this.vg = vg; + } + + public String accessToken() { + return vg.generateValue(); + } + + public String refreshToken() { + return vg.generateValue(); + } + + public String authorizationCode() { + return vg.generateValue(); + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/UUIDValueGenerator.java b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/UUIDValueGenerator.java new file mode 100644 index 000000000..f66fdc1cd --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/UUIDValueGenerator.java @@ -0,0 +1,20 @@ +/** + * + */ + +package com.blade.oauth2.issuer; + +import java.util.UUID; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class UUIDValueGenerator extends ValueGenerator { + + @Override + public String generateValue(String param) { + return UUID.fromString(UUID.nameUUIDFromBytes(param.getBytes()).toString()).toString(); + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/ValueGenerator.java b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/ValueGenerator.java new file mode 100644 index 000000000..29be7c77c --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/ValueGenerator.java @@ -0,0 +1,21 @@ +/** + * + */ +package com.blade.oauth2.issuer; + +import java.util.UUID; + + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public abstract class ValueGenerator { + + public String generateValue() { + return generateValue(UUID.randomUUID().toString()); + } + + public abstract String generateValue(String param); +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java b/blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java new file mode 100644 index 000000000..ebb651b57 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java @@ -0,0 +1,408 @@ +/** + * + */ + +package com.blade.oauth2.kit; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import blade.kit.Base64; +import blade.kit.StringKit; + +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.OAuthError; +import com.blade.oauth2.exception.OAuthProblemException; + +/** + * Common OAuth Utils class. + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public final class OAuthKit { + + private static final String ENCODING = "UTF-8"; + private static final String PARAMETER_SEPARATOR = "&"; + private static final String NAME_VALUE_SEPARATOR = "="; + + public static final String AUTH_SCHEME = OAuth.OAUTH_HEADER_NAME; + + private static final Pattern OAUTH_HEADER = Pattern.compile("\\s*(\\w*)\\s+(.*)"); + private static final Pattern NVP = Pattern.compile("(\\S*)\\s*\\=\\s*\"([^\"]*)\""); + + public static final String MULTIPART = "multipart/"; + + private static final String DEFAULT_CONTENT_CHARSET = ENCODING; + + /** + * Translates parameters into application/x-www-form-urlencoded String + * + * @param parameters parameters to encode + * @param encoding The name of a supported + * character + * encoding. + * @return Translated string + */ + public static String format( + final Collection> parameters, + final String encoding) { + final StringBuilder result = new StringBuilder(); + for (final Map.Entry parameter : parameters) { + String value = parameter.getValue() == null? null : String.valueOf(parameter.getValue()); + if (StringKit.isNotBlank(parameter.getKey()) + && StringKit.isNotBlank(value)) { + final String encodedName = encode(parameter.getKey(), encoding); + final String encodedValue = value != null ? encode(value, encoding) : ""; + if (result.length() > 0) { + result.append(PARAMETER_SEPARATOR); + } + result.append(encodedName); + result.append(NAME_VALUE_SEPARATOR); + result.append(encodedValue); + } + } + return result.toString(); + } + + private static String encode(final String content, final String encoding) { + try { + return URLEncoder.encode(content, + encoding != null ? encoding : "UTF-8"); + } catch (UnsupportedEncodingException problem) { + throw new IllegalArgumentException(problem); + } + } + + /** + * Read data from Input Stream and save it as a String. + * + * @param is InputStream to be read + * @return String that was read from the stream + */ + public static String saveStreamAsString(InputStream is) throws IOException { + return toString(is, ENCODING); + } + + /** + * Get the entity content as a String, using the provided default character set + * if none is found in the entity. + * If defaultCharset is null, the default "UTF-8" is used. + * + * @param is input stream to be saved as string + * @param defaultCharset character set to be applied if none found in the entity + * @return the entity content as a String + * @throws IllegalArgumentException if entity is null or if content length > Integer.MAX_VALUE + * @throws IOException if an error occurs reading the input stream + */ + public static String toString( + final InputStream is, final String defaultCharset) throws IOException { + if (is == null) { + throw new IllegalArgumentException("InputStream may not be null"); + } + + String charset = defaultCharset; + if (charset == null) { + charset = DEFAULT_CONTENT_CHARSET; + } + Reader reader = new InputStreamReader(is, charset); + StringBuilder sb = new StringBuilder(); + int l; + try { + char[] tmp = new char[4096]; + while ((l = reader.read(tmp)) != -1) { + sb.append(tmp, 0, l); + } + } finally { + reader.close(); + } + return sb.toString(); + } + + /** + * Creates invalid_request exception with given message + * + * @param message error message + * @return OAuthException + */ + public static OAuthProblemException handleOAuthProblemException(String message) { + return OAuthProblemException.error(OAuthError.TokenResponse.INVALID_REQUEST) + .description(message); + } + + /** + * Creates OAuthProblemException that contains set of missing oauth parameters + * + * @param missingParams missing oauth parameters + * @return OAuthProblemException with user friendly message about missing oauth parameters + */ + public static OAuthProblemException handleMissingParameters(Set missingParams) { + StringBuffer sb = new StringBuffer("Missing parameters: "); + if (!OAuthKit.isEmpty(missingParams)) { + for (String missingParam : missingParams) { + sb.append(missingParam).append(" "); + } + } + return handleOAuthProblemException(sb.toString().trim()); + } + + public static OAuthProblemException handleBadContentTypeException(String expectedContentType) { + StringBuilder errorMsg = new StringBuilder("Bad request content type. Expecting: ").append( + expectedContentType); + return handleOAuthProblemException(errorMsg.toString()); + } + + public static OAuthProblemException handleNotAllowedParametersOAuthException( + List notAllowedParams) { + StringBuffer sb = new StringBuffer("Not allowed parameters: "); + if (notAllowedParams != null) { + for (String notAllowed : notAllowedParams) { + sb.append(notAllowed).append(" "); + } + } + return handleOAuthProblemException(sb.toString().trim()); + } + + /** + * Parse a form-urlencoded document. + */ + public static Map decodeForm(String form) { + Map params = new HashMap(); + if (StringKit.isNotBlank(form)) { + for (String nvp : form.split("\\&")) { + int equals = nvp.indexOf('='); + String name; + String value; + if (equals < 0) { + name = decodePercent(nvp); + value = null; + } else { + name = decodePercent(nvp.substring(0, equals)); + value = decodePercent(nvp.substring(equals + 1)); + } + params.put(name, value); + } + } + return params; + } + + /** + * Return true if the given Content-Type header means FORM_ENCODED. + */ + public static boolean isFormEncoded(String contentType) { + if (contentType == null) { + return false; + } + int semi = contentType.indexOf(";"); + if (semi >= 0) { + contentType = contentType.substring(0, semi); + } + return OAuth.ContentType.URL_ENCODED.equalsIgnoreCase(contentType.trim()); + } + + public static String decodePercent(String s) { + try { + return URLDecoder.decode(s, ENCODING); + // This implements http://oauth.pbwiki.com/FlexibleDecoding + } catch (java.io.UnsupportedEncodingException wow) { + throw new RuntimeException(wow.getMessage(), wow); + } + } + + private static boolean isEmpty(Set missingParams) { + if (missingParams == null || missingParams.size() == 0) { + return true; + } + return false; + } + + public static String getAuthHeaderField(String authHeader) { + + if (authHeader != null) { + Matcher m = OAUTH_HEADER.matcher(authHeader); + if (m.matches()) { + if (AUTH_SCHEME.equalsIgnoreCase(m.group(1))) { + return m.group(2); + } + } + } + return null; + } + + public static Map decodeOAuthHeader(String header) { + Map headerValues = new HashMap(); + if (header != null) { + Matcher m = OAUTH_HEADER.matcher(header); + if (m.matches()) { + if (AUTH_SCHEME.equalsIgnoreCase(m.group(1))) { + for (String nvp : m.group(2).split("\\s*,\\s*")) { + m = NVP.matcher(nvp); + if (m.matches()) { + String name = decodePercent(m.group(1)); + String value = decodePercent(m.group(2)); + headerValues.put(name, value); + } + } + } + } + } + return headerValues; + } + + // todo: implement method to decode header form (with no challenge) + + /** + * Decodes the Basic Authentication header into a username and password + * + * @param authenticationHeader {@link String} containing the encoded header value. + * e.g. "Basic dXNlcm5hbWU6cGFzc3dvcmQ=" + * @return a {@link String[]} if the header could be decoded into a non null username and password or null. + * @throws UnsupportedEncodingException + */ + public static String[] decodeClientAuthenticationHeader(String authenticationHeader) { + if (authenticationHeader == null || "".equals(authenticationHeader)) { + return null; + } + String[] tokens = authenticationHeader.split(" "); + if (tokens == null) { + return null; + } + if (tokens[0] != null && !"".equals(tokens[0])) { + String authType = tokens[0]; + if (!authType.equalsIgnoreCase("basic")) { + return null; + } + } + try { + if (tokens[1] != null && !"".equals(tokens[1])) { + String encodedCreds = tokens[1]; + String decodedCreds = new String(Base64.decoder(encodedCreds)); + if (decodedCreds.contains(":") && decodedCreds.split(":").length == 2) { + String[] creds = decodedCreds.split(":"); + if (StringKit.isNotBlank(creds[0]) && StringKit.isNotBlank(creds[1])) { + return decodedCreds.split(":"); + } + } + } + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Construct a WWW-Authenticate header + */ + public static String encodeOAuthHeader(Map entries) { + StringBuffer sb = new StringBuffer(); + sb.append(OAuth.OAUTH_HEADER_NAME).append(" "); + for (Map.Entry entry : entries.entrySet()) { + String value = entry.getValue() == null? null: String.valueOf(entry.getValue()); + if (StringKit.isNotBlank(entry.getKey()) && StringKit.isNotBlank(value)) { + sb.append(entry.getKey()); + sb.append("=\""); + sb.append(value); + sb.append("\","); + } + } + + return sb.substring(0, sb.length() - 1); + } + + /** + * Construct an Authorization Bearer header + */ + public static String encodeAuthorizationBearerHeader(Map entries) { + StringBuffer sb = new StringBuffer(); + sb.append(OAuth.OAUTH_HEADER_NAME).append(" "); + for (Map.Entry entry : entries.entrySet()) { + String value = entry.getValue() == null? null: String.valueOf(entry.getValue()); + if (StringKit.isNotBlank(entry.getKey()) && StringKit.isNotBlank(value)) { + sb.append(value); + } + } + + return sb.toString(); + } + + public static String getAuthzMethod(String header) { + if (header != null) { + Matcher m = OAUTH_HEADER.matcher(header); + if (m.matches()) { + return m.group(1); + + } + } + return null; + } + + public static Set decodeScopes(String s) { + Set scopes = new HashSet(); + if (StringKit.isNotBlank(s)) { + StringTokenizer tokenizer = new StringTokenizer(s, " "); + + while (tokenizer.hasMoreElements()) { + scopes.add(tokenizer.nextToken()); + } + } + return scopes; + + } + + public static String encodeScopes(Set s) { + StringBuffer scopes = new StringBuffer(); + for (String scope : s) { + scopes.append(scope).append(" "); + } + return scopes.toString().trim(); + + } + + public static boolean isMultipart(Request request) { + + if (!"post".equals(request.method().toLowerCase())) { + return false; + } + String contentType = request.contentType(); + if (contentType == null) { + return false; + } + if (contentType.toLowerCase().startsWith(MULTIPART)) { + return true; + } + return false; + } + + + public static boolean hasContentType(String requestContentType, String requiredContentType) { + if (StringKit.isNotBlank(requiredContentType) || StringKit.isNotBlank(requestContentType)) { + return false; + } + StringTokenizer tokenizer = new StringTokenizer(requestContentType, ";"); + while (tokenizer.hasMoreTokens()) { + if (requiredContentType.equals(tokenizer.nextToken())) { + return true; + } + } + + return false; + } + +} + + diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/message/OAuthMessage.java b/blade-oauth2/src/main/java/com/blade/oauth2/message/OAuthMessage.java new file mode 100644 index 000000000..21b9097ed --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/message/OAuthMessage.java @@ -0,0 +1,31 @@ +/** + * + */ +package com.blade.oauth2.message; + +import java.util.Map; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public interface OAuthMessage { + + String getLocationUri(); + + void setLocationUri(String uri); + + String getBody(); + + void setBody(String body); + + String getHeader(String name); + + void addHeader(String name, String header); + + Map getHeaders(); + + void setHeaders(Map headers); + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/GrantType.java b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/GrantType.java new file mode 100644 index 000000000..961041f0d --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/GrantType.java @@ -0,0 +1,29 @@ +/** + * + */ +package com.blade.oauth2.message.types; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public enum GrantType { + + // NONE("none"), + AUTHORIZATION_CODE("authorization_code"), + PASSWORD("password"), + REFRESH_TOKEN("refresh_token"), + CLIENT_CREDENTIALS("client_credentials"); + + private String grantType; + + GrantType(String grantType) { + this.grantType = grantType; + } + + @Override + public String toString() { + return grantType; + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ParameterStyle.java b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ParameterStyle.java new file mode 100644 index 000000000..368b89065 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ParameterStyle.java @@ -0,0 +1,27 @@ +/** + * + */ +package com.blade.oauth2.message.types; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public enum ParameterStyle { + + BODY("body"), + QUERY("query"), + HEADER("header"); + + private String parameterStyle; + + ParameterStyle(String parameterStyle) { + this.parameterStyle = parameterStyle; + } + + @Override + public String toString() { + return parameterStyle; + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ResponseType.java b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ResponseType.java new file mode 100644 index 000000000..fc119ec60 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ResponseType.java @@ -0,0 +1,26 @@ +/* + * + */ +package com.blade.oauth2.message.types; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public enum ResponseType { + + CODE("code"), + TOKEN("token"); + + private String code; + + ResponseType(String code) { + this.code = code; + } + + @Override + public String toString() { + return code; + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/TokenType.java b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/TokenType.java new file mode 100644 index 000000000..5c3d1937c --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/TokenType.java @@ -0,0 +1,26 @@ +/** + * + */ +package com.blade.oauth2.message.types; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public enum TokenType { + + BEARER("Bearer"), + MAC("MAC"); + + private String tokenType; + + TokenType(String grantType) { + this.tokenType = grantType; + } + + @Override + public String toString() { + return tokenType; + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java b/blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java new file mode 100644 index 000000000..b7f038a34 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java @@ -0,0 +1,21 @@ +/** + * + */ + +package com.blade.oauth2.parameters; + +import java.util.Map; + +import blade.kit.json.Json; + +import com.blade.oauth2.message.OAuthMessage; + +public class JSONBodyParametersApplier { + + public OAuthMessage applyOAuthParameters(OAuthMessage message, Map params) { + String json = Json.parse(params).toString(); + message.setBody(json); + return message; + } + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java new file mode 100644 index 000000000..b46259220 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java @@ -0,0 +1,48 @@ +/** + * + */ + +package com.blade.oauth2.request; + +import com.blade.http.Request; +import com.blade.oauth2.base.request.OAuthTokenBaseRequest; +import com.blade.oauth2.base.validator.OAuthValidator; +import com.blade.oauth2.exception.OAuthProblemException; +import com.blade.oauth2.message.types.GrantType; +import com.blade.oauth2.validator.AuthorizationCodeValidator; +import com.blade.oauth2.validator.ClientCredentialValidator; +import com.blade.oauth2.validator.PasswordCredentialValidator; +import com.blade.oauth2.validator.RefreshTokenValidator; + + +/** + * The Default OAuth Authorization Server class that validates whether a given HttpServletRequest is a valid + * OAuth Token request. + *

+ * IMPORTANT: This OAuthTokenRequest assumes that a token request requires client authentication. + * Please see section 3.2.1 of the OAuth Specification: http://tools.ietf.org/html/rfc6749#section-3.2.1 + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class OAuthGrantRequest extends OAuthTokenBaseRequest { + + /** + * Create an OAuth Token request from a given HttpSerlvetRequest + * + * @param request the HttpServletRequest that is validated and transformed into the OAuth Token Request + * @throws OAuthProblemException if the request was not a valid Token request this exception is thrown. + */ + public OAuthGrantRequest(Request request) throws OAuthProblemException { + super(request); + } + + @Override + protected OAuthValidator initValidator() throws OAuthProblemException { + validators.put(GrantType.PASSWORD.toString(), PasswordCredentialValidator.class); + validators.put(GrantType.CLIENT_CREDENTIALS.toString(), ClientCredentialValidator.class); + validators.put(GrantType.AUTHORIZATION_CODE.toString(), AuthorizationCodeValidator.class); + validators.put(GrantType.REFRESH_TOKEN.toString(), RefreshTokenValidator.class); + return super.initValidator(); + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/request/RequestType.java b/blade-oauth2/src/main/java/com/blade/oauth2/request/RequestType.java new file mode 100644 index 000000000..5b582ea55 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/request/RequestType.java @@ -0,0 +1,27 @@ +/** + * + */ +package com.blade.oauth2.request; + +/** + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public enum RequestType { + + // link OAuthGrantRequst + GRANT_REQUEST("grant_request"), + // link OAuthRequest + CODE_TOKEN_REQUEST("code_token_request"); + + private String parameterStyle; + + RequestType(String parameterStyle) { + this.parameterStyle = parameterStyle; + } + + @Override + public String toString() { + return parameterStyle; + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java b/blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java new file mode 100644 index 000000000..7550abff8 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java @@ -0,0 +1,137 @@ +/** + * + */ + +package com.blade.oauth2.response; + + +import com.blade.http.HttpStatus; +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.OAuthResponse; +import com.blade.oauth2.OAuthResponse.OAuthResponseBuilder; +import com.blade.oauth2.message.types.TokenType; + +/** + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class OAuthASResponse extends OAuthResponse { + + protected OAuthASResponse(String uri, int responseStatus) { + super(uri, responseStatus); + } + + public static OAuthAuthorizationResponseBuilder authorizationResponse(Request request) { + return new OAuthAuthorizationResponseBuilder(request, HttpStatus.OK); + } + + public static OAuthAuthorizationResponseBuilder authorizationResponse(Request request,int code) { + return new OAuthAuthorizationResponseBuilder(request,code); + } + + public static OAuthTokenResponseBuilder tokenResponse() { + return new OAuthTokenResponseBuilder(HttpStatus.OK); + } + + public static OAuthTokenResponseBuilder tokenResponse(int code) { + return new OAuthTokenResponseBuilder(code); + } + + public static class OAuthAuthorizationResponseBuilder extends OAuthResponseBuilder { + + public OAuthAuthorizationResponseBuilder(Request request,int responseCode) { + super(responseCode); + //AMBER-45 + String state = request.query(OAuth.OAUTH_STATE); + if (state!=null){ + this.setState(state); + } + } + + OAuthAuthorizationResponseBuilder setState(String state) { + this.parameters.put(OAuth.OAUTH_STATE, state); + return this; + } + + public OAuthAuthorizationResponseBuilder setCode(String code) { + this.parameters.put(OAuth.OAUTH_CODE, code); + return this; + } + + public OAuthAuthorizationResponseBuilder setAccessToken(String token) { + this.parameters.put(OAuth.OAUTH_ACCESS_TOKEN, token); + return this; + } + + public OAuthAuthorizationResponseBuilder setExpiresIn(String expiresIn) { + this.parameters.put(OAuth.OAUTH_EXPIRES_IN, expiresIn == null ? null : Long.valueOf(expiresIn)); + return this; + } + + public OAuthAuthorizationResponseBuilder setExpiresIn(Long expiresIn) { + this.parameters.put(OAuth.OAUTH_EXPIRES_IN, expiresIn); + return this; + } + + public OAuthAuthorizationResponseBuilder location(String location) { + this.location = location; + return this; + } + + public OAuthAuthorizationResponseBuilder setParam(String key, String value) { + this.parameters.put(key, value); + return this; + } + } + + + public static class OAuthTokenResponseBuilder extends OAuthResponseBuilder { + + public OAuthTokenResponseBuilder(int responseCode) { + super(responseCode); + this.setTokenType(TokenType.BEARER); + } + + public OAuthTokenResponseBuilder setAccessToken(String token) { + this.parameters.put(OAuth.OAUTH_ACCESS_TOKEN, token); + return this; + } + + public OAuthTokenResponseBuilder setExpiresIn(String expiresIn) { + this.parameters.put(OAuth.OAUTH_EXPIRES_IN, expiresIn == null ? null : Long.valueOf(expiresIn)); + return this; + } + + public OAuthTokenResponseBuilder setRefreshToken(String refreshToken) { + this.parameters.put(OAuth.OAUTH_REFRESH_TOKEN, refreshToken); + return this; + } + + public OAuthTokenResponseBuilder setTokenType(String tokenType) { + this.parameters.put(OAuth.OAUTH_TOKEN_TYPE, tokenType); + return this; + } + + public OAuthTokenResponseBuilder setTokenType(TokenType tokenType) { + return this.setTokenType(String.valueOf(tokenType)); + } + + public OAuthTokenResponseBuilder setExampleParamter(String exampleParamter) { + this.parameters.put(OAuth.OAUTH_EXAMPLE_PARAMETER, exampleParamter); + return this; + } + + public OAuthTokenResponseBuilder setParam(String key, String value) { + this.parameters.put(key, value); + return this; + } + + public OAuthTokenResponseBuilder location(String location) { + this.location = location; + return this; + } + } + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java new file mode 100644 index 000000000..eed723647 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java @@ -0,0 +1,28 @@ +/** + * + */ +package com.blade.oauth2.validator; + +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.base.validator.OAuthBaseValidator; + +/** + * Validator that checks for the required fields in an OAuth Token request with the Authorization Code grant type. + * This validator enforces client authentication either through basic authentication or body parameters. + * + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class AuthorizationCodeValidator extends OAuthBaseValidator { + + public AuthorizationCodeValidator() { + //Value MUST be set to "authorization_code". + requiredParams.add(OAuth.OAUTH_GRANT_TYPE); + requiredParams.add(OAuth.OAUTH_CODE); + requiredParams.add(OAuth.OAUTH_REDIRECT_URI); + requiredParams.add(OAuth.OAUTH_CLIENT_ID); + enforceClientAuthentication = true; + } + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java new file mode 100644 index 000000000..238c1f4e8 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java @@ -0,0 +1,158 @@ +/** + * http://www.rfcreader.com/#rfc6749_line1027 + * The authorization code grant type is used to obtain both access + tokens and refresh tokens and is optimized for confidential clients. + Since this is a redirection-based flow, the client must be capable of + interacting with the resource owner's user-agent (typically a web + browser) and capable of receiving incoming requests (via redirection) + from the authorization server. + + +----------+ + | Resource | + | Owner | + | | + +----------+ + ^ + | + (B) + +----|-----+ Client Identifier +---------------+ + | -+----(A)-- & Redirection URI ---->| | + | User- | | Authorization | + | Agent -+----(B)-- User authenticates --->| Server | + | | | | + | -+----(C)-- Authorization Code ---<| | + +-|----|---+ +---------------+ + | | ^ v + (A) (C) | | + | | | | + ^ v | | + +---------+ | | + | |>---(D)-- Authorization Code ---------' | + | Client | & Redirection URI | + | | | + | |<---(E)----- Access Token -------------------' + +---------+ (w/ Optional Refresh Token) + + Note: The lines illustrating steps (A), (B), and (C) are broken into + two parts as they pass through the user-agent. + + Figure 3: Authorization Code Flow + + The flow illustrated in Figure 3 includes the following steps: + + (A) The client initiates the flow by directing the resource owner's + user-agent to the authorization endpoint. The client includes + its client identifier, requested scope, local state, and a + redirection URI to which the authorization server will send the + user-agent back once access is granted (or denied). + + (B) The authorization server authenticates the resource owner (via + the user-agent) and establishes whether the resource owner + grants or denies the client's access request. + + (C) Assuming the resource owner grants access, the authorization + server redirects the user-agent back to the client using the + redirection URI provided earlier (in the request or during + client registration). The redirection URI includes an + authorization code and any local state provided by the client + earlier. + + (D) The client requests an access token from the authorization + server's token endpoint by including the authorization code + received in the previous step. When making the request, the + client authenticates with the authorization server. The client + includes the redirection URI used to obtain the authorization + code for verification. + + (E) The authorization server authenticates the client, validates the + authorization code, and ensures that the redirection URI + received matches the URI used to redirect the client in + step (C). If valid, the authorization server responds back with + an access token and, optionally, a refresh token. + +4.1.1. Authorization Request + + + The client constructs the request URI by adding the following + parameters to the query component of the authorization endpoint URI + using the "application/x-www-form-urlencoded" format, per Appendix B: + + response_type + REQUIRED. Value MUST be set to "code". + + client_id + REQUIRED. The client identifier as described in Section 2.2. + + redirect_uri + OPTIONAL. As described in Section 3.1.2. + + scope + OPTIONAL. The scope of the access request as described by + Section 3.3. + + state + RECOMMENDED. An opaque value used by the client to maintain + state between the request and callback. The authorization + server includes this value when redirecting the user-agent back + to the client. The parameter SHOULD be used for preventing + cross-site request forgery as described in Section 10.12. + + The client directs the resource owner to the constructed URI using an + HTTP redirection response, or by other means available to it via the + user-agent. + + For example, the client directs the user-agent to make the following + HTTP request using TLS (with extra line breaks for display purposes + only): + + GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz + &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 + Host: server.example.com + + The authorization server validates the request to ensure that all + required parameters are present and valid. If the request is valid, + the authorization server authenticates the resource owner and obtains + an authorization decision (by asking the resource owner or by + establishing approval via other means). + + When a decision is established, the authorization server directs the + user-agent to the provided client redirection URI using an HTTP + redirection response, or by other means available to it via the + user-agent. + */ +package com.blade.oauth2.validator; + +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.OAuthError; +import com.blade.oauth2.base.validator.OAuthBaseValidator; +import com.blade.oauth2.exception.OAuthProblemException; + +/** + * Authorization Code Grant + * Authorization Request + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class AuthorizationValidator extends OAuthBaseValidator { + + public AuthorizationValidator() { + //Value MUST be set to "code". + requiredParams.add(OAuth.OAUTH_RESPONSE_TYPE); + requiredParams.add(OAuth.OAUTH_CLIENT_ID); + } + + @Override + public void validateMethod(Request request) throws OAuthProblemException { + String method = request.method(); + if (!method.equals(OAuth.HttpMethod.GET) && !method.equals(OAuth.HttpMethod.POST)) { + throw OAuthProblemException.error(OAuthError.CodeResponse.INVALID_REQUEST) + .description("Method not correct."); + } + } + + @Override + public void validateContentType(Request request) throws OAuthProblemException { + } +} + diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java new file mode 100644 index 000000000..378e6faf7 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java @@ -0,0 +1,51 @@ +/** + * http://www.rfcreader.com/#rfc6749 + * 4.4.2. Access Token Request + * + * The client can request an access token using only its client + credentials (or other supported means of authentication) when the + client is requesting access to the protected resources under its + control, or those of another resource owner that have been previously + arranged with the authorization server (the method of which is beyond + the scope of this specification). + + The client credentials grant type MUST only be used by confidential + clients. + + +---------+ +---------------+ + | | | | + | |>--(A)- Client Authentication --->| Authorization | + | Client | | Server | + | |<--(B)---- Access Token ---------<| | + | | | | + +---------+ +---------------+ + + Figure 6: Client Credentials Flow + + The flow illustrated in Figure 6 includes the following steps: + + (A) The client authenticates with the authorization server and + requests an access token from the token endpoint. + + (B) The authorization server authenticates the client, and if valid, + issues an access token. + */ +package com.blade.oauth2.validator; + +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.base.validator.OAuthBaseValidator; + +/** + * Client Credentials Grant + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class ClientCredentialValidator extends OAuthBaseValidator { + + public ClientCredentialValidator() { + //Value MUST be set to "client_credentials". + requiredParams.add(OAuth.OAUTH_GRANT_TYPE); + enforceClientAuthentication = true; + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java new file mode 100644 index 000000000..6578f93b9 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java @@ -0,0 +1,188 @@ +/** + * http://www.rfcreader.com/#rfc6749_line1439 + * 4.2. Implicit Grant + * + * The implicit grant type is used to obtain access tokens (it does not + support the issuance of refresh tokens) and is optimized for public + clients known to operate a particular redirection URI. These clients + are typically implemented in a browser using a scripting language + such as JavaScript. + + Since this is a redirection-based flow, the client must be capable of + interacting with the resource owner's user-agent (typically a web + browser) and capable of receiving incoming requests (via redirection) + from the authorization server. + + Unlike the authorization code grant type, in which the client makes + separate requests for authorization and for an access token, the + client receives the access token as the result of the authorization + request. + + The implicit grant type does not include client authentication, and + relies on the presence of the resource owner and the registration of + the redirection URI. Because the access token is encoded into the + redirection URI, it may be exposed to the resource owner and other + applications residing on the same device. + + +----------+ + | Resource | + | Owner | + | | + +----------+ + ^ + | + (B) + +----|-----+ Client Identifier +---------------+ + | -+----(A)-- & Redirection URI --->| | + | User- | | Authorization | + | Agent -|----(B)-- User authenticates -->| Server | + | | | | + | |<---(C)--- Redirection URI ----<| | + | | with Access Token +---------------+ + | | in Fragment + | | +---------------+ + | |----(D)--- Redirection URI ---->| Web-Hosted | + | | without Fragment | Client | + | | | Resource | + | (F) |<---(E)------- Script ---------<| | + | | +---------------+ + +-|--------+ + | | + (A) (G) Access Token + | | + ^ v + +---------+ + | | + | Client | + | | + +---------+ + + Note: The lines illustrating steps (A) and (B) are broken into two + parts as they pass through the user-agent. + + Figure 4: Implicit Grant Flow + + The flow illustrated in Figure 4 includes the following steps: + + (A) The client initiates the flow by directing the resource owner's + user-agent to the authorization endpoint. The client includes + its client identifier, requested scope, local state, and a + redirection URI to which the authorization server will send the + user-agent back once access is granted (or denied). + + (B) The authorization server authenticates the resource owner (via + the user-agent) and establishes whether the resource owner + grants or denies the client's access request. + + (C) Assuming the resource owner grants access, the authorization + server redirects the user-agent back to the client using the + redirection URI provided earlier. The redirection URI includes + the access token in the URI fragment. + + (D) The user-agent follows the redirection instructions by making a + request to the web-hosted client resource (which does not + include the fragment per [RFC2616]). The user-agent retains the + fragment information locally. + + (E) The web-hosted client resource returns a web page (typically an + HTML document with an embedded script) capable of accessing the + full redirection URI including the fragment retained by the + user-agent, and extracting the access token (and other + parameters) contained in the fragment. + + (F) The user-agent executes the script provided by the web-hosted + client resource locally, which extracts the access token. + + (G) The user-agent passes the access token to the client. + + See Sections 1.3.2 and 9 for background on using the implicit grant. + See Sections 10.3 and 10.16 for important security considerations + when using the implicit grant. + + The client constructs the request URI by adding the following + parameters to the query component of the authorization endpoint URI + using the "application/x-www-form-urlencoded" format, per Appendix B: + + response_type + REQUIRED. Value MUST be set to "token". + + client_id + REQUIRED. The client identifier as described in Section 2.2. + + redirect_uri + OPTIONAL. As described in Section 3.1.2. + + scope + OPTIONAL. The scope of the access request as described by + Section 3.3. + + state + RECOMMENDED. An opaque value used by the client to maintain + state between the request and callback. The authorization + server includes this value when redirecting the user-agent back + to the client. The parameter SHOULD be used for preventing + cross-site request forgery as described in Section 10.12. + + The client directs the resource owner to the constructed URI using an + HTTP redirection response, or by other means available to it via the + user-agent. + + For example, the client directs the user-agent to make the following + HTTP request using TLS (with extra line breaks for display purposes + only): + + GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz + &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 + Host: server.example.com + + The authorization server validates the request to ensure that all + required parameters are present and valid. The authorization server + MUST verify that the redirection URI to which it will redirect the + access token matches a redirection URI registered by the client as + described in Section 3.1.2. + + If the request is valid, the authorization server authenticates the + resource owner and obtains an authorization decision (by asking the + resource owner or by establishing approval via other means). + + When a decision is established, the authorization server directs the + user-agent to the provided client redirection URI using an HTTP + redirection response, or by other means available to it via the + user-agent. + */ + +package com.blade.oauth2.validator; + +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.OAuthError; +import com.blade.oauth2.base.validator.OAuthBaseValidator; +import com.blade.oauth2.exception.OAuthProblemException; + + +/** + * Implicit Grant + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class ImplicitCodeValidator extends OAuthBaseValidator { + + public ImplicitCodeValidator() { + //Value MUST be set to "token". + requiredParams.add(OAuth.OAUTH_RESPONSE_TYPE); + requiredParams.add(OAuth.OAUTH_CLIENT_ID); + } + + @Override + public void validateMethod(Request request) throws OAuthProblemException { + String method = request.method(); + if (!OAuth.HttpMethod.GET.equals(method) && !OAuth.HttpMethod.POST.equals(method)) { + throw OAuthProblemException.error(OAuthError.CodeResponse.INVALID_REQUEST) + .description("Method not correct."); + } + } + + @Override + public void validateContentType(Request request) throws OAuthProblemException { + } +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java new file mode 100644 index 000000000..cab2c17f4 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java @@ -0,0 +1,124 @@ +/** + * http://www.rfcreader.com/#rfc6749 + * 4.3. Resource Owner Password Credentials Grant + * The resource owner password credentials grant type is suitable in + cases where the resource owner has a trust relationship with the + client, such as the device operating system or a highly privileged + + application. The authorization server should take special care when + enabling this grant type and only allow it when other flows are not + viable. + + This grant type is suitable for clients capable of obtaining the + resource owner's credentials (username and password, typically using + an interactive form). It is also used to migrate existing clients + using direct authentication schemes such as HTTP Basic or Digest + authentication to OAuth by converting the stored credentials to an + access token. + + +----------+ + | Resource | + | Owner | + | | + +----------+ + v + | Resource Owner + (A) Password Credentials + | + v + +---------+ +---------------+ + | |>--(B)---- Resource Owner ------->| | + | | Password Credentials | Authorization | + | Client | | Server | + | |<--(C)---- Access Token ---------<| | + | | (w/ Optional Refresh Token) | | + +---------+ +---------------+ + + Figure 5: Resource Owner Password Credentials Flow + + The flow illustrated in Figure 5 includes the following steps: + + (A) The resource owner provides the client with its username and + password. + + (B) The client requests an access token from the authorization + server's token endpoint by including the credentials received + from the resource owner. When making the request, the client + authenticates with the authorization server. + + (C) The authorization server authenticates the client and validates + the resource owner credentials, and if valid, issues an access + token. + + The client makes a request to the token endpoint by adding the + following parameters using the "application/x-www-form-urlencoded" + format per Appendix B with a character encoding of UTF-8 in the HTTP + request entity-body: + + grant_type + REQUIRED. Value MUST be set to "password". + + username + REQUIRED. The resource owner username. + + password + REQUIRED. The resource owner password. + + scope + OPTIONAL. The scope of the access request as described by + Section 3.3. + + If the client type is confidential or the client was issued client + credentials (or assigned other authentication requirements), the + client MUST authenticate with the authorization server as described + in Section 3.2.1. + + For example, the client makes the following HTTP request using + transport-layer security (with extra line breaks for display purposes + only): + + POST /token HTTP/1.1 + Host: server.example.com + Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW + Content-Type: application/x-www-form-urlencoded + + grant_type=password&username=johndoe&password=A3ddj3w + + The authorization server MUST: + + o require client authentication for confidential clients or for any + client that was issued client credentials (or with other + authentication requirements), + + o authenticate the client if client authentication is included, and + + o validate the resource owner password credentials using its + existing password validation algorithm. + + Since this access token request utilizes the resource owner's + password, the authorization server MUST protect the endpoint against + brute force attacks (e.g., using rate-limitation or generating + alerts) + */ +package com.blade.oauth2.validator; + +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.base.validator.OAuthBaseValidator; + +/** + * Resource Owner Password Credentials Grant + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class PasswordCredentialValidator extends OAuthBaseValidator { + + public PasswordCredentialValidator() { + // Value MUST be set to "password" + requiredParams.add(OAuth.OAUTH_GRANT_TYPE); + requiredParams.add(OAuth.OAUTH_USERNAME); + requiredParams.add(OAuth.OAUTH_PASSWORD); + enforceClientAuthentication = true; + } + +} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java new file mode 100644 index 000000000..89cee6e64 --- /dev/null +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java @@ -0,0 +1,90 @@ +/** + * http://www.rfcreader.com/#rfc6749 + * 6. Refreshing an Access Token + * If the authorization server issued a refresh token to the client, the + client makes a refresh request to the token endpoint by adding the + following parameters using the "application/x-www-form-urlencoded" + format per Appendix B with a character encoding of UTF-8 in the HTTP + request entity-body: + + grant_type + REQUIRED. Value MUST be set to "refresh_token". + + refresh_token + REQUIRED. The refresh token issued to the client. + + scope + OPTIONAL. The scope of the access request as described by + Section 3.3. The requested scope MUST NOT include any scope + not originally granted by the resource owner, and if omitted is + treated as equal to the scope originally granted by the + resource owner. + + Because refresh tokens are typically long-lasting credentials used to + request additional access tokens, the refresh token is bound to the + client to which it was issued. If the client type is confidential or + the client was issued client credentials (or assigned other + authentication requirements), the client MUST authenticate with the + authorization server as described in Section 3.2.1. + + For example, the client makes the following HTTP request using + transport-layer security (with extra line breaks for display purposes + only): + + POST /token HTTP/1.1 + Host: server.example.com + Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW + Content-Type: application/x-www-form-urlencoded + + grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA + + The authorization server MUST: + + o require client authentication for confidential clients or for any + client that was issued client credentials (or with other + authentication requirements), + + o authenticate the client if client authentication is included and + ensure that the refresh token was issued to the authenticated + client, and + + o validate the refresh token. + + If valid and authorized, the authorization server issues an access + token as described in Section 5.1. If the request failed + verification or is invalid, the authorization server returns an error + response as described in Section 5.2. + + The authorization server MAY issue a new refresh token, in which case + the client MUST discard the old refresh token and replace it with the + new refresh token. The authorization server MAY revoke the old + refresh token after issuing a new refresh token to the client. If a + new refresh token is issued, the refresh token scope MUST be + identical to that of the refresh token included by the client in the + request. + */ +package com.blade.oauth2.validator; + +import com.blade.http.Request; +import com.blade.oauth2.OAuth; +import com.blade.oauth2.base.validator.OAuthBaseValidator; + +/** + * Validator that checks for the required fields in an OAuth Token request with the Refresh token grant type. + * This validator enforces client authentication either through basic authentication or body parameters. + * + * http://www.rfcreader.com/#rfc6749 + * 6. Refreshing an Access Token + * @author BruceZCQ [zcq@zhucongqi.cn] + * @version + */ +public class RefreshTokenValidator extends OAuthBaseValidator { + + public RefreshTokenValidator() { + //Value MUST be set to "refresh_token". + requiredParams.add(OAuth.OAUTH_GRANT_TYPE); + requiredParams.add(OAuth.OAUTH_REFRESH_TOKEN); + enforceClientAuthentication = true; + } + +} From 6967723a7552d12347bf5a1b0aa938132106c34a Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 2 Dec 2015 18:25:03 +0800 Subject: [PATCH 271/545] add blade oauth2 pom.xml --- blade-oauth2/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 blade-oauth2/README.md diff --git a/blade-oauth2/README.md b/blade-oauth2/README.md new file mode 100644 index 000000000..abf626eac --- /dev/null +++ b/blade-oauth2/README.md @@ -0,0 +1,12 @@ +# blade-oauth2 + +修改自[jfinal-oauth2.0-server](http://git.oschina.net/brucezcq/jfinal-oauth2.0-server) + +参考[RFC6749](http://www.rfcreader.com/#rfc6749) + +实现了OAuth 2.0定义了四种授权方式 + +* 授权码模式(authorization code): 先获取下次请求token的code,然后在带着code去请求token +* 简化模式(implicit):直接请求token +* 密码模式(resource owner password credentials): 先完成授权,然后再获取token +* 客户端模式(client credentials): 类似密码保护模式 From 3fa5ce6e4494f9e9258f815bdf9dd614a2cd04b5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 3 Dec 2015 16:11:05 +0800 Subject: [PATCH 272/545] simplify ioc code --- .../main/java/com/blade/ioc/Container.java | 7 + .../java/com/blade/ioc/SampleContainer.java | 164 ++++++++++-------- 2 files changed, 98 insertions(+), 73 deletions(-) diff --git a/blade-core/src/main/java/com/blade/ioc/Container.java b/blade-core/src/main/java/com/blade/ioc/Container.java index 3c2164269..3d0ad6a8e 100644 --- a/blade-core/src/main/java/com/blade/ioc/Container.java +++ b/blade-core/src/main/java/com/blade/ioc/Container.java @@ -130,6 +130,13 @@ public interface Container { */ Object registBean(Class clazz); + /** + * 注册一个代名称的Bean + * @param clazz + * @return + */ + Object registBean(String name, Object value); + /** * 注册一个对象到bean容器中 * diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java index 832f9f594..f19c29a37 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -25,16 +25,17 @@ import java.util.Map.Entry; import java.util.Set; -import com.blade.annotation.Component; -import com.blade.annotation.Inject; -import com.blade.annotation.Path; - import blade.exception.BladeException; import blade.kit.CloneKit; import blade.kit.CollectionKit; import blade.kit.ReflectKit; +import blade.kit.StringKit; import blade.kit.log.Logger; +import com.blade.annotation.Component; +import com.blade.annotation.Inject; +import com.blade.annotation.Path; + /** * 默认的IOC容器实现 * @@ -47,26 +48,42 @@ public class SampleContainer implements Container { private static final Logger LOGGER = Logger.getLogger(SampleContainer.class); /** - * 保存所有bean对象 + * 保存所有bean对象 如:com.xxxx.User @Userx7asc + */ + private Map beans = CollectionKit.newConcurrentHashMap(); + + /** + * 存储所有的对象名和对于的类名关系 */ - private static final Map BEAN_CONTAINER = CollectionKit.newConcurrentHashMap(); + private Map beanKeys = CollectionKit.newConcurrentHashMap(); /** * 保存所有注解的class */ - private static final Map, List> ANNOTATION_CONTAINER = CollectionKit.newConcurrentHashMap(); + private Map, List> annotaionBeans = CollectionKit.newConcurrentHashMap(); + public SampleContainer() { } public Map getBeanMap() { - return BEAN_CONTAINER; + return beans; } @Override public T getBean(String name, Scope scope) { - Object obj = BEAN_CONTAINER.get(name); - if(null != scope && scope == Scope.PROTOTYPE){ + + String className = beanKeys.get(name); + if(StringKit.isBlank(className)){ + if(null == beans.get(name)){ + return null; + } else { + className = name; + } + } + + Object obj = beans.get(className); + if(null != scope && null != Scope.SINGLE){ try { return (T) CloneKit.deepClone(obj); } catch (Exception e) { @@ -78,60 +95,45 @@ public T getBean(String name, Scope scope) { @Override public T getBean(Class type, Scope scope) { - Set keys = BEAN_CONTAINER.keySet(); - for(String key : keys){ - Object obj = BEAN_CONTAINER.get(key); - if (type.isAssignableFrom(obj.getClass())) { - if(null != scope && scope == Scope.PROTOTYPE){ - try { - return (T) CloneKit.deepClone(obj); - } catch (Exception e) { - LOGGER.error("克隆对象失败," + e.getMessage()); - } - } else { - return (T) obj; - } - } - } - return null; + return this.getBean(type.getCanonicalName(), scope); } @Override public Set getBeanNames() { - return BEAN_CONTAINER.keySet(); + return beanKeys.keySet(); } @Override public Collection getBeans() { - return BEAN_CONTAINER.values(); + return beans.values(); } @Override - public boolean hasBean(Class clz) { - if (null != this.getBean(clz, Scope.SINGLE)) { - return true; - } - return false; + public boolean hasBean(Class clazz) { + String className = clazz.getCanonicalName(); + return beanKeys.containsValue(className); } @Override public boolean hasBean(String name) { - if (null != this.getBean(name, Scope.SINGLE)) { - return true; - } - return false; + return null != beanKeys.get(name); } @Override public boolean removeBean(String name) { - Object object = BEAN_CONTAINER.remove(name); - return (null != object); + String className = beanKeys.get(name); + if(StringKit.isNotBlank(className)){ + beanKeys.remove(name); + beans.remove(className); + return true; + } + return false; } @Override public boolean removeBean(Class clazz) { - Object object = BEAN_CONTAINER.remove(clazz.getName()); - return (null != object); + beans.remove(clazz.getCanonicalName()); + return true; } /** @@ -144,39 +146,50 @@ public boolean removeBean(Class clazz) { public Object registBean(Class clazz) { String name = clazz.getCanonicalName(); - Object object = null; //非抽象类、接口 - if (!Modifier.isAbstract(clazz.getModifiers()) && !clazz.isInterface()) { + if (isNormalClass(clazz)) { + object = ReflectKit.newInstance(clazz); + return registBean(name, object); + } + return object; + } + + @Override + public Object registBean(String name, Object value) { + Class clazz = value.getClass(); + //非抽象类、接口 + if (isNormalClass(clazz)) { - object = ReflectKit.newInstance(clazz); + // 如果容器已经存在该名称对于的对象,直接返回 + String className = beanKeys.get(name); + if (StringKit.isNotBlank(className)) { + return beans.get(className); + } + + className = clazz.getCanonicalName(); + beanKeys.put(name, className); + beans.put(name, value); - put(name, object); //实现的接口对应存储 if(clazz.getInterfaces().length > 0){ - put(clazz.getInterfaces()[0].getCanonicalName(), object); + beans.put(clazz.getInterfaces()[0].getCanonicalName(), value); } //带有annotation if(null != clazz.getDeclaredAnnotations()){ - putAnnotationMap(clazz, object); + putAnnotationMap(clazz, value); } } - return object; + return value; } - /** - * bean容器存储 - * - * @param name 要进入IOC容器的bean名称 - * @param object 要进入IOC容器的bean对象 - */ - private void put(String name, Object object){ - if(!BEAN_CONTAINER.containsValue(object)){ - BEAN_CONTAINER.put(name, object); - } - } + @Override + public Object registBean(Object object) { + String className = object.getClass().getCanonicalName(); + return registBean(className, object); + } /** * 给annotationMap添加元素 @@ -189,7 +202,7 @@ private void putAnnotationMap(Class clazz, Object object){ List listObject = null; for(Annotation annotation : annotations){ if(null != annotation){ - listObject = ANNOTATION_CONTAINER.get(annotation.annotationType()); + listObject = annotaionBeans.get(annotation.annotationType()); if(CollectionKit.isEmpty(listObject)){ listObject = CollectionKit.newArrayList(); } @@ -206,8 +219,8 @@ private void putAnnotationMap(Class clazz, Object object){ * @param listObject 要注入的对象列表 */ private void put(Class clazz, List listObject){ - if(null == ANNOTATION_CONTAINER.get(clazz)){ - ANNOTATION_CONTAINER.put(clazz, listObject); + if(null == annotaionBeans.get(clazz)){ + annotaionBeans.put(clazz, listObject); } } @@ -216,7 +229,7 @@ private void put(Class clazz, List listObject){ */ @Override public void initWired() throws RuntimeException { - Iterator> it = BEAN_CONTAINER.entrySet().iterator(); + Iterator> it = beans.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); Object object = entry.getValue(); @@ -258,6 +271,18 @@ public boolean isRegister(Annotation[] annotations) { } return false; } + + /** + * 是否是一个非接口和抽象类的Class + * @param clazz + * @return + */ + private boolean isNormalClass(Class clazz){ + if(!Modifier.isAbstract(clazz.getModifiers()) && !clazz.isInterface()){ + return true; + } + return false; + } @Override public List> getClassesByAnnotation(Class annotation) { @@ -274,7 +299,7 @@ public List> getClassesByAnnotation(Class annotat @Override public List getBeansByAnnotation(Class annotation) { - return (List) ANNOTATION_CONTAINER.get(annotation); + return (List) annotaionBeans.get(annotation); } @Override @@ -286,17 +311,10 @@ public void registBean(Set> classes) { } } - @Override - public Object registBean(Object object) { - String name = object.getClass().getName(); - put(name, object); - return object; - } - @Override public boolean removeAll() { - BEAN_CONTAINER.clear(); - ANNOTATION_CONTAINER.clear(); + beans.clear(); + annotaionBeans.clear(); return true; } From bdb08169322b45a3bdfd7b1e155c76ed2a4eed3d Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 3 Dec 2015 16:50:25 +0800 Subject: [PATCH 273/545] update default Container Impl --- .../java/com/blade/annotation/Inject.java | 6 +- .../java/com/blade/ioc/SampleContainer.java | 66 +++++++++++-------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/blade-core/src/main/java/com/blade/annotation/Inject.java b/blade-core/src/main/java/com/blade/annotation/Inject.java index d0b8afcad..4a370fc12 100644 --- a/blade-core/src/main/java/com/blade/annotation/Inject.java +++ b/blade-core/src/main/java/com/blade/annotation/Inject.java @@ -34,8 +34,12 @@ public @interface Inject { /** - * @return 要注入的类类型 + * @return 要注入的Class的对象 */ Class value() default Class.class; + /** + * @return 要注入某个名称的对象 + */ + String name() default ""; } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java index f19c29a37..f4f7100b1 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -122,18 +122,18 @@ public boolean hasBean(String name) { @Override public boolean removeBean(String name) { String className = beanKeys.get(name); - if(StringKit.isNotBlank(className)){ + if(StringKit.isBlank(className)){ + className = name; + } else { beanKeys.remove(name); - beans.remove(className); - return true; - } - return false; + } + beans.remove(className); + return true; } @Override public boolean removeBean(Class clazz) { - beans.remove(clazz.getCanonicalName()); - return true; + return this.removeBean(clazz.getCanonicalName()); } /** @@ -170,11 +170,17 @@ public Object registBean(String name, Object value) { className = clazz.getCanonicalName(); beanKeys.put(name, className); - beans.put(name, value); + if(null == beans.get(className)){ + beans.put(className, value); + } //实现的接口对应存储 - if(clazz.getInterfaces().length > 0){ - beans.put(clazz.getInterfaces()[0].getCanonicalName(), value); + Class[] interfaces = clazz.getInterfaces(); + if(interfaces.length > 0){ + for(Class interfaceClazz : interfaces){ + System.out.println(interfaceClazz.getCanonicalName()); + this.registBean(interfaceClazz.getCanonicalName(), value); + } } //带有annotation @@ -313,6 +319,7 @@ public void registBean(Set> classes) { @Override public boolean removeAll() { + beanKeys.clear(); beans.clear(); annotaionBeans.clear(); return true; @@ -329,25 +336,32 @@ public void injection(Object object) { if (null != inject ) { // 要注入的字段 - Object injectField = this.getBean(field.getType(), Scope.SINGLE); - // 指定装配到哪个class - if(inject.value() != Class.class){ - // 指定装配的类 - injectField = this.getBean(inject.value(), Scope.SINGLE); - - if (null == injectField) { - injectField = recursiveAssembly(inject.value()); - } - - } else { - if (null == injectField) { - injectField = recursiveAssembly(field.getType()); - } + Object injectField = null; + String name = inject.name(); + if(!name.equals("")){ + String className = beanKeys.get(name); + if(null != className && !className.equals("")){ + injectField = beans.get(className); + } + if (null == injectField) { + throw new RuntimeException("Unable to load " + name); + } + } else { + if(inject.value() == Class.class){ + injectField = recursiveAssembly(field.getType()); + } else { + // 指定装配的类 + injectField = this.getBean(inject.value(), null); + if (null == injectField) { + injectField = recursiveAssembly(inject.value()); + } + } } - + if (null == injectField) { throw new BladeException("Unable to load " + field.getType().getCanonicalName() + "!"); } + boolean accessible = field.isAccessible(); field.setAccessible(true); field.set(object, injectField); @@ -362,5 +376,5 @@ public void injection(Object object) { LOGGER.error(e); } } - + } \ No newline at end of file From 1731e50fae8d09a045f463e8d5b499966646c80b Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 4 Dec 2015 18:32:50 +0800 Subject: [PATCH 274/545] add blade patchca --- .../main/java/com/blade/IocApplication.java | 7 +- .../main/java/com/blade/http/Response.java | 4 +- .../java/com/blade/ioc/SampleContainer.java | 1 - .../com/blade/patchca/PatchcaService.java | 126 +++++++++++++ .../patchca/background/BackgroundFactory.java | 27 +++ .../SingleColorBackgroundFactory.java | 51 ++++++ .../java/org/patchca/color/ColorFactory.java | 26 +++ .../patchca/color/GradientColorFactory.java | 48 +++++ .../org/patchca/color/RandomColorFactory.java | 54 ++++++ .../org/patchca/color/SingleColorFactory.java | 44 +++++ .../patchca/filter/AbstractFilterFactory.java | 41 +++++ .../filter/ConfigurableFilterFactory.java | 37 ++++ .../org/patchca/filter/FilterFactory.java | 27 +++ .../library/AbstractConvolveImageOp.java | 65 +++++++ .../filter/library/AbstractImageOp.java | 172 ++++++++++++++++++ .../library/AbstractTransformImageOp.java | 55 ++++++ .../patchca/filter/library/BlurImageOp.java | 30 +++ .../patchca/filter/library/CurvesImageOp.java | 115 ++++++++++++ .../filter/library/DiffuseImageOp.java | 60 ++++++ .../filter/library/DoubleRippleImageOp.java | 31 ++++ .../patchca/filter/library/MarbleImageOp.java | 91 +++++++++ .../patchca/filter/library/PerlinNoise.java | 95 ++++++++++ .../patchca/filter/library/RippleImageOp.java | 80 ++++++++ .../patchca/filter/library/SoftenImageOp.java | 30 +++ .../patchca/filter/library/WobbleImageOp.java | 101 ++++++++++ .../predefined/CurvesRippleFilterFactory.java | 58 ++++++ .../DiffuseRippleFilterFactory.java | 38 ++++ .../predefined/DoubleRippleFilterFactory.java | 47 +++++ .../predefined/MarbleRippleFilterFactory.java | 40 ++++ .../predefined/RippleFilterFactory.java | 59 ++++++ .../predefined/WobbleRippleFilterFactory.java | 42 +++++ .../java/org/patchca/font/FontFactory.java | 25 +++ .../org/patchca/font/RandomFontFactory.java | 90 +++++++++ .../service/AbstractCaptchaService.java | 115 ++++++++++++ .../java/org/patchca/service/Captcha.java | 49 +++++ .../org/patchca/service/CaptchaService.java | 24 +++ .../service/ConfigurableCaptchaService.java | 43 +++++ .../patchca/service/SimpleCaptchaService.java | 59 ++++++ .../text/renderer/AbstractTextRenderer.java | 103 +++++++++++ .../text/renderer/BestFitTextRenderer.java | 36 ++++ .../renderer/RandomYBestFitTextRenderer.java | 41 +++++ .../text/renderer/SimpleTextRenderer.java | 34 ++++ .../patchca/text/renderer/TextCharacter.java | 117 ++++++++++++ .../patchca/text/renderer/TextRenderer.java | 38 ++++ .../org/patchca/text/renderer/TextString.java | 83 +++++++++ .../patchca/utils/encoder/EncoderHelper.java | 37 ++++ .../word/AdaptiveRandomWordFactory.java | 58 ++++++ .../org/patchca/word/RandomWordFactory.java | 60 ++++++ .../java/org/patchca/word/WordFactory.java | 24 +++ .../test/java/org/blade/patchca/AppTest.java | 15 ++ pom.xml | 2 + 51 files changed, 2748 insertions(+), 7 deletions(-) create mode 100644 blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java create mode 100644 blade-patchca/src/main/java/org/patchca/background/BackgroundFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/background/SingleColorBackgroundFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/color/ColorFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/color/GradientColorFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/color/RandomColorFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/color/SingleColorFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/AbstractFilterFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/ConfigurableFilterFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/FilterFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/AbstractConvolveImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/AbstractImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/AbstractTransformImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/BlurImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/CurvesImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/DiffuseImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/DoubleRippleImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/MarbleImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/PerlinNoise.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/RippleImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/SoftenImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/WobbleImageOp.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/CurvesRippleFilterFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/DiffuseRippleFilterFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/DoubleRippleFilterFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/MarbleRippleFilterFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/RippleFilterFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/WobbleRippleFilterFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/font/FontFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/font/RandomFontFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/service/AbstractCaptchaService.java create mode 100644 blade-patchca/src/main/java/org/patchca/service/Captcha.java create mode 100644 blade-patchca/src/main/java/org/patchca/service/CaptchaService.java create mode 100644 blade-patchca/src/main/java/org/patchca/service/ConfigurableCaptchaService.java create mode 100644 blade-patchca/src/main/java/org/patchca/service/SimpleCaptchaService.java create mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/AbstractTextRenderer.java create mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/BestFitTextRenderer.java create mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/RandomYBestFitTextRenderer.java create mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/SimpleTextRenderer.java create mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/TextCharacter.java create mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/TextRenderer.java create mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/TextString.java create mode 100644 blade-patchca/src/main/java/org/patchca/utils/encoder/EncoderHelper.java create mode 100644 blade-patchca/src/main/java/org/patchca/word/AdaptiveRandomWordFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/word/RandomWordFactory.java create mode 100644 blade-patchca/src/main/java/org/patchca/word/WordFactory.java create mode 100644 blade-patchca/src/test/java/org/blade/patchca/AppTest.java diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index a6052aa1f..0af03d999 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -16,7 +16,6 @@ package com.blade; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Set; @@ -80,9 +79,9 @@ public void init(Blade blade){ // 初始化注入 container.initWired(); - Collection beans = container.getBeans(); - for(Object object : beans){ - LOGGER.info("Add Object:" + object.getClass() + "=" + object); + Set names = container.getBeanNames(); + for(String name : names){ + LOGGER.info("Add Object:" + name + "=" + container.getBean(name, null)); } } diff --git a/blade-core/src/main/java/com/blade/http/Response.java b/blade-core/src/main/java/com/blade/http/Response.java index 5edd40256..a808d496d 100644 --- a/blade-core/src/main/java/com/blade/http/Response.java +++ b/blade-core/src/main/java/com/blade/http/Response.java @@ -16,9 +16,9 @@ package com.blade.http; import java.io.IOException; +import java.io.OutputStream; import java.util.Map; -import javax.servlet.ServletOutputStream; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; @@ -83,7 +83,7 @@ public interface Response { Response xml(String output); - ServletOutputStream outputStream() throws IOException; + OutputStream outputStream() throws IOException; Response render(String view) ; diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java index f4f7100b1..fe87435db 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -178,7 +178,6 @@ public Object registBean(String name, Object value) { Class[] interfaces = clazz.getInterfaces(); if(interfaces.length > 0){ for(Class interfaceClazz : interfaces){ - System.out.println(interfaceClazz.getCanonicalName()); this.registBean(interfaceClazz.getCanonicalName(), value); } } diff --git a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java new file mode 100644 index 000000000..6f6df152f --- /dev/null +++ b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java @@ -0,0 +1,126 @@ +package com.blade.patchca; + +import java.awt.Color; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Random; + +import org.patchca.color.ColorFactory; +import org.patchca.filter.FilterFactory; +import org.patchca.filter.predefined.DiffuseRippleFilterFactory; +import org.patchca.service.ConfigurableCaptchaService; +import org.patchca.utils.encoder.EncoderHelper; +import org.patchca.word.RandomWordFactory; +import org.patchca.word.WordFactory; + +import blade.kit.log.Logger; + +import com.blade.http.Response; +import com.blade.servlet.Session; + +/** + * PatchcaService + */ +public class PatchcaService { + + private static final Logger LOGGER = Logger.getLogger(PatchcaService.class); + + private ConfigurableCaptchaService cs = null; + private static Random random = new Random(); + public String CHARS = "23456789abcdefghigkmnpqrstuvwxyzABCDEFGHIGKLMNPQRSTUVWXYZ"; + public Integer maxLen = 4; + public Integer minLen = 4; + + private PatchcaService() { + cs = new ConfigurableCaptchaService(); + // cs.setColorFactory(new SingleColorFactory(new Color(25, 60, 170))); + cs.setColorFactory(new ColorFactory() { + @Override + public Color getColor(int x) { + int[] c = new int[3]; + int i = random.nextInt(c.length); + for (int fi = 0; fi < c.length; fi++) { + if (fi == i) { + c[fi] = random.nextInt(71); + } else { + c[fi] = random.nextInt(256); + } + } + return new Color(c[0], c[1], c[2]); + } + }); + RandomWordFactory wf = new RandomWordFactory(); + wf.setCharacters(CHARS); + wf.setMaxLength(maxLen); + wf.setMinLength(minLen); + cs.setWordFactory(wf); + cs.setFilterFactory(new DiffuseRippleFilterFactory()); + } + + public static PatchcaService get(){ + return new PatchcaService(); + } + + public PatchcaService color(ColorFactory colorFactory){ + cs.setColorFactory(colorFactory); + return this; + } + + public PatchcaService word(WordFactory wordFactory){ + cs.setWordFactory(wordFactory); + return this; + } + + public PatchcaService filter(FilterFactory filterFactory){ + cs.setFilterFactory(filterFactory); + return this; + } + + public void session(Session session, Response response, String patchca){ + try { + setResponseHeaders(response); + String token = EncoderHelper.getChallangeAndWriteImage(cs, "png", response.outputStream()); + session.attribute(patchca, token); + LOGGER.info("当前sessionid = " + session.id() + ", 验证码 = " + token); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void setResponseHeaders(Response response) { + response.contentType("image/png"); + response.header("Cache-Control", "no-cache, no-store"); + response.header("Pragma", "no-cache"); + long time = System.currentTimeMillis(); + response.header("Last-Modified", time + ""); + response.header("Date", time + ""); + response.header("Expires", time + ""); + } + + public String getToken(String imgType, OutputStream outputStream){ + try { + String token = EncoderHelper.getChallangeAndWriteImage(cs, imgType, outputStream); + return token; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + public File create(String imgPath, String imgType) { + try { + FileOutputStream fos = new FileOutputStream(imgPath); + EncoderHelper.getChallangeAndWriteImage(cs, imgType, fos); + fos.close(); + return new File(imgPath); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/blade-patchca/src/main/java/org/patchca/background/BackgroundFactory.java b/blade-patchca/src/main/java/org/patchca/background/BackgroundFactory.java new file mode 100644 index 000000000..646aaf6cb --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/background/BackgroundFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ + +package org.patchca.background; + +import java.awt.image.BufferedImage; + +public interface BackgroundFactory { + + void fillBackground(BufferedImage dest); +} diff --git a/blade-patchca/src/main/java/org/patchca/background/SingleColorBackgroundFactory.java b/blade-patchca/src/main/java/org/patchca/background/SingleColorBackgroundFactory.java new file mode 100644 index 000000000..869af0a7d --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/background/SingleColorBackgroundFactory.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.background; + +import org.patchca.color.ColorFactory; +import org.patchca.color.SingleColorFactory; + +import java.awt.*; +import java.awt.image.BufferedImage; + + +public class SingleColorBackgroundFactory implements BackgroundFactory { + + private ColorFactory colorFactory; + + public SingleColorBackgroundFactory() { + colorFactory = new SingleColorFactory(Color.WHITE); + } + + public SingleColorBackgroundFactory(Color color) { + colorFactory = new SingleColorFactory(color); + } + + public void setColorFactory(ColorFactory colorFactory) { + this.colorFactory = colorFactory; + } + + @Override + public void fillBackground(BufferedImage dest) { + Graphics g = dest.getGraphics(); + g.setColor(colorFactory.getColor(0)); + g.fillRect(0, 0, dest.getWidth(), dest.getHeight()); + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/color/ColorFactory.java b/blade-patchca/src/main/java/org/patchca/color/ColorFactory.java new file mode 100644 index 000000000..4a48ec393 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/color/ColorFactory.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.color; + +import java.awt.*; + +public interface ColorFactory { + + Color getColor(int index); +} diff --git a/blade-patchca/src/main/java/org/patchca/color/GradientColorFactory.java b/blade-patchca/src/main/java/org/patchca/color/GradientColorFactory.java new file mode 100644 index 000000000..badecd70f --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/color/GradientColorFactory.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.color; + +import java.awt.*; + +public class GradientColorFactory implements ColorFactory { + + private Color start; + private Color step; + + public GradientColorFactory() { + start = new Color(192, 192, 0); + step = new Color(192, 128, 128); + } + + @Override + public Color getColor(int index) { + return new Color((start.getRed() + step.getRed() * index) % 256, + (start.getGreen() + step.getGreen() * index) % 256, + (start.getBlue() + step.getBlue() * index) % 256); + } + + public void setStart(Color start) { + this.start = start; + } + + public void setStep(Color step) { + this.step = step; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/color/RandomColorFactory.java b/blade-patchca/src/main/java/org/patchca/color/RandomColorFactory.java new file mode 100644 index 000000000..035a41434 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/color/RandomColorFactory.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.color; + +import java.awt.*; +import java.util.Random; + +public class RandomColorFactory implements ColorFactory { + + private Color min; + private Color max; + private Color color; + + public RandomColorFactory() { + min = new Color(20,40,80); + max = new Color(21,50,140); + } + + public void setMin(Color min) { + this.min = min; + } + + public void setMax(Color max) { + this.max = max; + } + + @Override + public Color getColor(int index) { + if (color == null) { + Random r = new Random(); + color = new Color( min.getRed() + r.nextInt((max.getRed() - min.getRed())), + min.getGreen() + r.nextInt((max.getGreen() - min.getGreen())), + min.getBlue() + r.nextInt((max.getBlue() - min.getBlue()))); + } + return color; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/color/SingleColorFactory.java b/blade-patchca/src/main/java/org/patchca/color/SingleColorFactory.java new file mode 100644 index 000000000..06ce3be3e --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/color/SingleColorFactory.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.color; + +import java.awt.*; + +public class SingleColorFactory implements ColorFactory { + + private Color color; + + public SingleColorFactory() { + color = Color.BLACK; + } + + public SingleColorFactory(Color color) { + this.color = color; + } + + @Override + public Color getColor(int index) { + return color; + } + + public void setColor(Color color) { + this.color = color; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/AbstractFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/AbstractFilterFactory.java new file mode 100644 index 000000000..665b8e178 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/AbstractFilterFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter; + +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.util.List; + +public abstract class AbstractFilterFactory implements FilterFactory { + + protected abstract List getFilters(); + + public BufferedImage applyFilters(BufferedImage source) { + BufferedImage dest = source; + for (BufferedImageOp filter : getFilters()) { + dest = filter.filter(dest, null); + } + int x = (source.getWidth() - dest.getWidth()) / 2; + int y = (source.getHeight() - dest.getHeight()) / 2; + source = new BufferedImage(source.getWidth(), source.getHeight(), source.getType()); + source.getGraphics().drawImage(dest, x, y, null); + return source; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/ConfigurableFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/ConfigurableFilterFactory.java new file mode 100644 index 000000000..9c34991a0 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/ConfigurableFilterFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter; + +import java.awt.image.BufferedImageOp; +import java.util.List; + +public class ConfigurableFilterFactory extends AbstractFilterFactory { + + private List filters; + + @Override + public List getFilters() { + return filters; + } + + public void setFilters(List filters) { + this.filters = filters; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/FilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/FilterFactory.java new file mode 100644 index 000000000..67ed89309 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/FilterFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter; + +import java.awt.image.BufferedImage; + +public interface FilterFactory { + + BufferedImage applyFilters(BufferedImage source); + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/AbstractConvolveImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/AbstractConvolveImageOp.java new file mode 100644 index 000000000..d89063eee --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/AbstractConvolveImageOp.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + + +public abstract class AbstractConvolveImageOp extends AbstractImageOp { + + private float[][] matrix; + + protected AbstractConvolveImageOp(float[][] matrix) { + this.matrix = matrix; + } + + @Override + protected void filter(int[] inPixels, int[] outPixels, int width, int height) { + long time1 = System.currentTimeMillis(); + int matrixWidth = matrix[0].length; + int matrixHeight = matrix.length; + int mattrixLeft = - matrixWidth / 2; + int matrixTop = - matrixHeight / 2; + for (int y = 0; y < height; y++) { + int ytop = y + matrixTop; + int ybottom = y + matrixTop + matrixHeight; + for (int x = 0; x < width; x++) { + float[] sum = {0.5f, 0.5f, 0.5f, 0.5f}; + int xleft = x + mattrixLeft; + int xright = x + mattrixLeft + matrixWidth; + int matrixY = 0; + for (int my = ytop; my < ybottom; my ++, matrixY++) { + int matrixX = 0; + for (int mx = xleft; mx < xright; mx ++, matrixX ++) { + int pixel = getPixel(inPixels, mx, my, width, height, EDGE_ZERO); + float m = matrix[matrixY][matrixX]; + sum[0] += m * ((pixel >> 24) & 0xff); + sum[1] += m * ((pixel >> 16) & 0xff); + sum[2] += m * ((pixel >> 8) & 0xff); + sum[3] += m * (pixel & 0xff); + } + } + outPixels[x + y * width] = (limitByte((int)sum[0]) << 24) | (limitByte((int)sum[1]) << 16) | (limitByte((int)sum[2]) << 8) | (limitByte((int)sum[3])); + } + } + long time2 = System.currentTimeMillis() - time1; + //System.out.println("AbstractConvolveImageOp " + time2); + + } + + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/AbstractImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/AbstractImageOp.java new file mode 100644 index 000000000..1f6b70e43 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/AbstractImageOp.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + +import java.awt.*; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ColorModel; +import java.awt.image.IndexColorModel; + +public abstract class AbstractImageOp implements BufferedImageOp { + + public static final int EDGE_ZERO = 0; + public static final int EDGE_MIRROR = 1; + public static final int EDGE_CLAMP = 2; + + protected int edgeMode; + protected RenderingHints hints; + + public int getEdgeMode() { + return edgeMode; + } + + public void setEdgeMode(int edgeMode) { + this.edgeMode = edgeMode; + } + + protected int getPixel(int pixels[], int x, int y, int width, int height, int edgeMode) { + if (x >= 0 && x < width && y >= 0 && y < height) { + return pixels[x + y * width]; + } else if (edgeMode == EDGE_ZERO) { + return 0; + } else if (edgeMode == EDGE_CLAMP) { + if (x < 0) { + x = 0; + } else if (x >= width) { + x = width - 1; + } + if (y < 0) { + y = 0; + } else if (y >= height) { + y = height - 1; + } + return pixels[x + y * width]; + } else { + if (x < 0) { + x = -x; + } else if (x >= width) { + x = width + width - x - 1; + } + if (y < 0) { + y = -y; + } else if (y > height) { + y = height = height - y - 1; + } + try { + return pixels[x + y * width]; + } catch (Exception e) { + return 0; + } + } + } + + private int linear(int from, int to, int shift, double d) { + return ((int) Math.floor(((from >> shift) & 0xff) + d * (((to >> shift) & 0xff) - ((from >> shift) & 0xff)))) << shift; + } + + private int linear(int from, int to, double d) { + int c = 0; + for (int i = 0; i < 4; i++) { + c += linear(from, to, i * 8, d); + } + return c; + } + + protected int bilinear(int nw, int ne, int sw, int se, double xd, double yd) { + return linear(linear(nw, ne, xd), linear(sw, se, xd), yd); + } + + protected int getPixelBilinear(int pixels[], double x, double y, int width, int height, int edgeMode) { + int xi = (int) Math.floor(x); + int yi = (int) Math.floor(y); + double xd = x - xi; + double yd = y - yi; + int nw = getPixel(pixels, xi, yi, width, height, edgeMode); + int ne = getPixel(pixels, xi + 1, yi, width, height, edgeMode); + int sw = getPixel(pixels, xi, yi + 1, width, height, edgeMode); + int se = getPixel(pixels, xi + 1, yi + 1, width, height, edgeMode); + return bilinear(nw, ne, sw, se, xd, yd); + } + + protected int limit(int v, int min, int max) { + if (v < min) { + v = min; + } else if (v > max) { + v = max; + } + return v; + } + + protected int limitByte(int v) { + return limit(v, 0, 255); + } + + protected void filter(int[] inPixels, int[] outPixels, int width, int height) { + + } + + @Override + public BufferedImage filter(BufferedImage src, BufferedImage dest) { + if (dest == null) { + dest = createCompatibleDestImage(src, null); + } + int width = src.getWidth(); + int height = src.getHeight(); + int[] inPixels = new int[width * height]; + int[] outPixels = new int[width * height]; + src.getRaster().getDataElements(0, 0, width, height, inPixels); + filter(inPixels, outPixels, width, height); + dest.getRaster().setDataElements(0, 0, width, height, outPixels); + return dest; + } + + @Override + public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) { + if (destCM == null) { + destCM = src.getColorModel(); + if (destCM instanceof IndexColorModel) { + destCM = ColorModel.getRGBdefault(); + } + } + return new BufferedImage(destCM, destCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), destCM.isAlphaPremultiplied(), null); + } + + @Override + public Rectangle2D getBounds2D(BufferedImage src) { + return src.getRaster().getBounds(); + } + + @Override + public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) { + if (dstPt == null) { + dstPt = new Point2D.Float(); + } + dstPt.setLocation(srcPt.getX(), srcPt.getY()); + return dstPt; + } + + @Override + public RenderingHints getRenderingHints() { + return hints; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/AbstractTransformImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/AbstractTransformImageOp.java new file mode 100644 index 000000000..be2174942 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/AbstractTransformImageOp.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + + +public abstract class AbstractTransformImageOp extends AbstractImageOp { + + protected abstract void transform(int x, int y, double[] t); + + protected void init() { + } + + private boolean initialized; + + public AbstractTransformImageOp() { + setEdgeMode(EDGE_CLAMP); + } + + @Override + protected void filter(int[] inPixels, int[] outPixels, int width, int height) { + if (!initialized) { + init(); + initialized = true; + } + long time1 = System.currentTimeMillis(); + double[]t = new double[2]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + transform(x, y, t); + int pixel = getPixelBilinear(inPixels, t[0], t[1], width, height, getEdgeMode()); + outPixels[x + y * width] = pixel; + } + } + long time2 = System.currentTimeMillis() - time1; + //System.out.println("AbstractTransformImageOp " + time2); + } + +} + diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/BlurImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/BlurImageOp.java new file mode 100644 index 000000000..950e9379d --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/BlurImageOp.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + +public class BlurImageOp extends AbstractConvolveImageOp { + + private static final float[][] matrix = { { 1 / 16f, 2 / 16f, 1 / 16f }, + { 2 / 16f, 4 / 16f, 2 / 16f }, { 1 / 16f, 2 / 16f, 1 / 16f } }; + + public BlurImageOp() { + super(matrix); + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/CurvesImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/CurvesImageOp.java new file mode 100644 index 000000000..3a66d20f7 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/CurvesImageOp.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + +import org.patchca.color.ColorFactory; +import org.patchca.color.SingleColorFactory; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.Random; + + +public class CurvesImageOp extends AbstractImageOp { + + private float strokeMin; + private float strokeMax; + private ColorFactory colorFactory = new SingleColorFactory(); + + public float getStrokeMin() { + return strokeMin; + } + + public void setStrokeMin(float strokeMin) { + this.strokeMin = strokeMin; + } + + public float getStrokeMax() { + return strokeMax; + } + + + public void setStrokeMax(float strokeMax) { + this.strokeMax = strokeMax; + } + public ColorFactory getColorFactory() { + return colorFactory; + } + + public void setColorFactory(ColorFactory colorFactory) { + this.colorFactory = colorFactory; + } + + private double hermiteSpline(double x1, double a1, double x2, double a2, double t) { + double t2=t*t; + double t3=t2*t; + double b=-a2-2.0*a1-3.0*x1+3.0*x2; + double a=a2+a1+2.0*x1-2.0*x2; + return a*t3+b*t2+a1*t+x1; + } + + private double catmullRomSpline(double x0, double x1, double x2, double x3, double t) { + double a1 = (x2 - x0) / 2; + double a2 = (x3 - x1) / 2; + return hermiteSpline(x1, a1, x2, a2, t); + } + + @Override + public BufferedImage filter(BufferedImage src, BufferedImage dest) { + if (dest == null) { + dest = createCompatibleDestImage(src, null); + } + double width = dest.getWidth(); + double height = dest.getHeight(); + Graphics2D g2 = (Graphics2D) src.getGraphics(); + g2.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); + Random r = new Random(); + int cp = 4 + r.nextInt(3); + int[] xPoints = new int[cp]; + int[] yPoints = new int[cp]; + width -= 10; + for (int i = 0; i < cp; i++) { + xPoints[i] = (int) ((int) 5 + (i * width) / (cp - 1)); + yPoints[i] = (int) (height * (r.nextDouble() * 0.5 + 0.2)); + } + int subsections = 6; + int[] xPointsSpline = new int[(cp - 1)*subsections]; + int[] yPointsSpline = new int[(cp - 1)*subsections]; + for (int i = 0; i < cp - 1; i++) { + double x0 = i > 0 ? xPoints[i - 1] : 2 * xPoints[i] - xPoints[i + 1]; + double x1 = xPoints[i]; + double x2 = xPoints[i + 1]; + double x3 = (i + 2 < cp) ? xPoints[i + 2] : 2 * xPoints[i + 1] - xPoints[i]; + double y0 = i > 0 ? yPoints[i - 1] : 2 * yPoints[i] - yPoints[i + 1]; + double y1 = yPoints[i]; + double y2 = yPoints[i + 1]; + double y3 = (i + 2 < cp) ? yPoints[i + 2] : 2 * yPoints[i + 1] - yPoints[i]; + for (int j = 0; j < subsections; j++) { + xPointsSpline[i * subsections + j] = (int) catmullRomSpline(x0, x1, x2, x3, 1.0 / subsections * j); + yPointsSpline[i * subsections + j] = (int) catmullRomSpline(y0, y1, y2, y3, 1.0 / subsections * j); + } + } + for (int i = 0; i < xPointsSpline.length - 1; i++) { + g2.setColor(colorFactory.getColor(i)); + g2.setStroke(new BasicStroke(2 + 2 * r.nextFloat())); + g2.drawLine(xPointsSpline[i], yPointsSpline[i], xPointsSpline[i + 1], yPointsSpline[i + 1]); + } + return src; + } +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/DiffuseImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/DiffuseImageOp.java new file mode 100644 index 000000000..42a0f0166 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/DiffuseImageOp.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + +import java.util.Random; + +public class DiffuseImageOp extends AbstractTransformImageOp { + + double[] tx; + double[] ty; + double amount; + + public DiffuseImageOp() { + amount = 1.6; + } + + public double getAmount() { + return amount; + } + + public void setAmount(double amount) { + this.amount = amount; + } + + @Override + protected synchronized void init() { + tx = new double[256]; + ty = new double[256]; + for (int i = 0; i < 256; i++) { + double angle = 2 * Math.PI * i / 256; + tx[i] = amount * Math.sin(angle); + ty[i] = amount * Math.cos(angle); + } + } + + @Override + protected void transform(int x, int y, double[] t) { + Random r = new Random(); + int angle = (int) (r.nextFloat() * 255); + t[0] = x + tx[angle]; + t[1] = y + ty[angle]; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/DoubleRippleImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/DoubleRippleImageOp.java new file mode 100644 index 000000000..73fb17c63 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/DoubleRippleImageOp.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + +public class DoubleRippleImageOp extends RippleImageOp { + + @Override + protected void transform(int x, int y, double[] t) { + double tx = Math.sin((double) y / yWavelength + yRandom) + 1.3 * Math.sin((double) 0.6 * y / yWavelength + yRandom); + double ty = Math.cos((double) x / xWavelength + xRandom) + 1.3 * Math.cos((double) 0.6 * x / xWavelength + xRandom); + t[0] = x + xAmplitude * tx; + t[1] = y + yAmplitude * ty; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/MarbleImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/MarbleImageOp.java new file mode 100644 index 000000000..5e47eb2ae --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/MarbleImageOp.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + +public class MarbleImageOp extends AbstractTransformImageOp { + + double scale; + double amount; + double turbulence; + double[] tx; + double[] ty; + double randomX; + double randomY; + + public MarbleImageOp() { + scale = 15; + amount = 1.1; + turbulence = 6.2; + randomX = 256 * Math.random(); + randomY = 256 * Math.random(); + } + + public double getScale() { + return scale; + } + + public void setScale(double scale) { + this.scale = scale; + } + + public double getAmount() { + return amount; + } + + public void setAmount(double amount) { + this.amount = amount; + } + + public double getTurbulence() { + return turbulence; + } + + public void setTurbulence(double turbulence) { + this.turbulence = turbulence; + } + + @Override + protected synchronized void init() { + tx = new double[256]; + ty = new double[256]; + for (int i = 0; i < 256; i++) { + double angle = 2 * Math.PI * i * turbulence / 256; + tx[i] = amount * Math.sin(angle); + ty[i] = amount * Math.cos(angle); + } + } + + @Override + protected void transform(int x, int y, double[] t) { + int d = limitByte((int) (127 * (1 + PerlinNoise.noise2D(((double)x) / scale + randomX, ((double)y) / scale + randomY)))); + t[0] = x + tx[d]; + t[1] = y + ty[d]; + } + + protected void filter2(int[] inPixels, int[] outPixels, int width, int height) { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int pixel = limitByte((int) (127 * (1 + PerlinNoise.noise2D(((double)x) / scale + randomX, ((double)y) / scale + randomY)))); + outPixels[x + y * width] = (limitByte((int)255) << 24) | (limitByte((int)pixel) << 16) | (limitByte((int)pixel) << 8) | (limitByte((int)pixel)); + } + } + } + + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/PerlinNoise.java b/blade-patchca/src/main/java/org/patchca/filter/library/PerlinNoise.java new file mode 100644 index 000000000..8a0e80bf8 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/PerlinNoise.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + +public class PerlinNoise { + + static int p[] = { 151, 160, 137, 91, 90, 15, + 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, + 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, + 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, + 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, + 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, + 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, + 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, + 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, + 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, + 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, + 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, + 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, + 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, + 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, + 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, + 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, + 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, + 61, 156, 180, 151, 160, 137, 91, 90, 15, + 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, + 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, + 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, + 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, + 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, + 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, + 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, + 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, + 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, + 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, + 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, + 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, + 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, + 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, + 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, + 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, + 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, + 61, 156, 180 }; + + public static double noise2D(double x, double y) { + double fx = Math.floor(x); + double fy = Math.floor(y); + double u, v; + int ix = ((int) fx) & 0xFF; + int iy = ((int) fy) & 0xFF; + x -= fx; + y -= fy; + int i = p[ix]; + int j = p[ix + 1]; + u = fade(x); + v = fade(y); + double grad1 = grad(p[i + iy], x, y); + double grad2 = grad(p[j + iy], x - 1, y); + double grad3 = grad(p[i + iy + 1], x, y - 1); + double grad4 = grad(p[j + iy + 1], x - 1, y - 1); + return lerp(v, lerp(u, grad1, grad2), lerp(u, grad3, grad4)); + } + + static double fade(double t) { + return t * t * t * (t * (t * 6 - 15) + 10); + } + + static double grad(int hash, double x, double y) { + int h = hash & 3; + double u = (h & 1) == 0 ? x : -x; + double v = (h & 2) == 0 ? y : -y; + return u + v; + } + + public static double lerp(double t, double a, double b) { + return a + t * (b - a); + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/RippleImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/RippleImageOp.java new file mode 100644 index 000000000..3d014fb25 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/RippleImageOp.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + + +public class RippleImageOp extends AbstractTransformImageOp { + + protected double xWavelength; + protected double yWavelength; + protected double xAmplitude; + protected double yAmplitude; + protected double xRandom; + protected double yRandom; + + public RippleImageOp() { + xWavelength = 20; + yWavelength = 10; + xAmplitude = 5; + yAmplitude = 5; + xRandom = 5 * Math.random(); + yRandom = 5 * Math.random(); + } + + public double getxWavelength() { + return xWavelength; + } + + public void setxWavelength(double xWavelength) { + this.xWavelength = xWavelength; + } + + public double getyWavelength() { + return yWavelength; + } + + public void setyWavelength(double yWavelength) { + this.yWavelength = yWavelength; + } + + public double getxAmplitude() { + return xAmplitude; + } + + public void setxAmplitude(double xAmplitude) { + this.xAmplitude = xAmplitude; + } + + public double getyAmplitude() { + return yAmplitude; + } + + public void setyAmplitude(double yAmplitude) { + this.yAmplitude = yAmplitude; + } + + @Override + protected void transform(int x, int y, double[] t) { + double tx = Math.sin((double) y / yWavelength + yRandom); + double ty = Math.cos((double) x / xWavelength + xRandom); + t[0] = x + xAmplitude * tx; + t[1] = y + yAmplitude * ty; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/SoftenImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/SoftenImageOp.java new file mode 100644 index 000000000..1eb39b0a2 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/SoftenImageOp.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + +public class SoftenImageOp extends AbstractConvolveImageOp { + + private static final float[][] matrix = { { 0 / 16f, 1 / 16f, 0 / 16f }, + { 1 / 16f, 12 / 16f, 1 / 16f }, { 0 / 16f, 1 / 16f, 0 / 16f } }; + + public SoftenImageOp() { + super(matrix); + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/WobbleImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/WobbleImageOp.java new file mode 100644 index 000000000..590b4e81c --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/library/WobbleImageOp.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.library; + + +public class WobbleImageOp extends AbstractTransformImageOp { + + private double xWavelength; + private double yWavelength; + private double xAmplitude; + private double yAmplitude; + private double xRandom; + private double yRandom; + private double xScale; + private double yScale; + + public WobbleImageOp() { + xWavelength = 15; + yWavelength = 15; + xAmplitude = 4.0; + yAmplitude = 3.0; + xScale = 1.0; + yScale = 1.0; + xRandom = 3 * Math.random(); + yRandom = 10 * Math.random(); + } + + public double getxWavelength() { + return xWavelength; + } + + public void setxWavelength(double xWavelength) { + this.xWavelength = xWavelength; + } + + public double getyWavelength() { + return yWavelength; + } + + public void setyWavelength(double yWavelength) { + this.yWavelength = yWavelength; + } + + public double getxAmplitude() { + return xAmplitude; + } + + public void setxAmplitude(double xAmplitude) { + this.xAmplitude = xAmplitude; + } + + public double getyAmplitude() { + return yAmplitude; + } + + public void setyAmplitude(double yAmplitude) { + this.yAmplitude = yAmplitude; + } + + public double getxScale() { + return xScale; + } + + public void setxScale(double xScale) { + this.xScale = xScale; + } + + public double getyScale() { + return yScale; + } + + public void setyScale(double yScale) { + this.yScale = yScale; + } + + @Override + protected void transform(int x, int y, double[] t) { + double tx = Math.cos((double) (xScale * x + y) / xWavelength + xRandom); + double ty = Math.sin((double) (yScale * y + x) / yWavelength + yRandom); + t[0] = x + xAmplitude * tx; + t[1] = y + yAmplitude * ty; + + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/CurvesRippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/CurvesRippleFilterFactory.java new file mode 100644 index 000000000..996181fa6 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/predefined/CurvesRippleFilterFactory.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.predefined; + +import org.patchca.color.ColorFactory; +import org.patchca.filter.library.CurvesImageOp; + +import java.awt.image.BufferedImageOp; +import java.util.ArrayList; +import java.util.List; + +public class CurvesRippleFilterFactory extends RippleFilterFactory { + + protected CurvesImageOp curves = new CurvesImageOp(); + + public CurvesRippleFilterFactory() { + } + + public CurvesRippleFilterFactory(ColorFactory colorFactory) { + setColorFactory(colorFactory); + } + + @Override + protected List getPreRippleFilters() { + List list = new ArrayList(); + list.add(curves); + return list; + } + + public void setStrokeMin(float strokeMin) { + curves.setStrokeMin(strokeMin); + } + + public void setStrokeMax(float strokeMax) { + curves.setStrokeMax(strokeMax); + } + + public void setColorFactory(ColorFactory colorFactory) { + curves.setColorFactory(colorFactory); + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/DiffuseRippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/DiffuseRippleFilterFactory.java new file mode 100644 index 000000000..e668e745c --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/predefined/DiffuseRippleFilterFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.predefined; + +import org.patchca.filter.library.DiffuseImageOp; + +import java.awt.image.BufferedImageOp; +import java.util.ArrayList; +import java.util.List; + + +public class DiffuseRippleFilterFactory extends RippleFilterFactory { + + protected DiffuseImageOp diffuse = new DiffuseImageOp(); + + @Override + protected List getPreRippleFilters() { + List list = new ArrayList(); + list.add(diffuse); + return list; + } +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/DoubleRippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/DoubleRippleFilterFactory.java new file mode 100644 index 000000000..52ddaf52e --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/predefined/DoubleRippleFilterFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.predefined; + +import org.patchca.filter.AbstractFilterFactory; +import org.patchca.filter.library.DoubleRippleImageOp; + +import java.awt.image.BufferedImageOp; +import java.util.ArrayList; +import java.util.List; + + +public class DoubleRippleFilterFactory extends AbstractFilterFactory { + + protected List filters; + protected DoubleRippleImageOp ripple; + + public DoubleRippleFilterFactory() { + ripple = new DoubleRippleImageOp(); + } + + @Override + public List getFilters() { + if (filters == null) { + filters = new ArrayList(); + filters.add(ripple); + } + return filters; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/MarbleRippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/MarbleRippleFilterFactory.java new file mode 100644 index 000000000..99f7f1177 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/predefined/MarbleRippleFilterFactory.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.predefined; + +import org.patchca.filter.library.MarbleImageOp; + +import java.awt.image.BufferedImageOp; +import java.util.ArrayList; +import java.util.List; + + +public class MarbleRippleFilterFactory extends RippleFilterFactory { + + protected MarbleImageOp marble = new MarbleImageOp(); + + @Override + protected List getPreRippleFilters() { + List list = new ArrayList(); + list.add(marble); + return list; + } + +} + diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/RippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/RippleFilterFactory.java new file mode 100644 index 000000000..3bf2c2334 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/predefined/RippleFilterFactory.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.predefined; + +import org.patchca.filter.AbstractFilterFactory; +import org.patchca.filter.library.RippleImageOp; + +import java.awt.image.BufferedImageOp; +import java.util.ArrayList; +import java.util.List; + + +public class RippleFilterFactory extends AbstractFilterFactory { + + protected List filters; + protected RippleImageOp ripple; + + public RippleFilterFactory() { + ripple = new RippleImageOp(); + } + + protected List getPreRippleFilters() { + return new ArrayList(); + } + + protected List getPostRippleFilters() { + return new ArrayList(); + + } + + @Override + public List getFilters() { + if (filters == null) { + filters = new ArrayList(); + filters.addAll(getPreRippleFilters()); + filters.add(ripple); + filters.addAll(getPostRippleFilters()); + } + return filters; + } + + +} diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/WobbleRippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/WobbleRippleFilterFactory.java new file mode 100644 index 000000000..3b5094e32 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/filter/predefined/WobbleRippleFilterFactory.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.filter.predefined; + +import org.patchca.filter.library.WobbleImageOp; + +import java.awt.image.BufferedImageOp; +import java.util.ArrayList; +import java.util.List; + + +public class WobbleRippleFilterFactory extends RippleFilterFactory { + + protected WobbleImageOp wobble; + + public WobbleRippleFilterFactory() { + wobble = new WobbleImageOp(); + } + @Override + protected List getPreRippleFilters() { + List list = new ArrayList(); + list.add(wobble); + return list; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/font/FontFactory.java b/blade-patchca/src/main/java/org/patchca/font/FontFactory.java new file mode 100644 index 000000000..6438406c8 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/font/FontFactory.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.font; + +import java.awt.*; + +public interface FontFactory { + Font getFont(int index); +} diff --git a/blade-patchca/src/main/java/org/patchca/font/RandomFontFactory.java b/blade-patchca/src/main/java/org/patchca/font/RandomFontFactory.java new file mode 100644 index 000000000..80547d856 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/font/RandomFontFactory.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.font; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +public class RandomFontFactory implements FontFactory { + + protected List families; + protected int minSize; + protected int maxSize; + protected boolean randomStyle; + + public RandomFontFactory() { + families = new ArrayList(); + families.add("Verdana"); + families.add("Tahoma"); + minSize = 45; + maxSize = 45; + } + + public RandomFontFactory(List families) { + this(); + this.families = families; + } + + public RandomFontFactory(String[] families) { + this(); + this.families = Arrays.asList(families); + } + + public RandomFontFactory(int size, List families) { + this(families); + minSize = maxSize = size; + } + + public RandomFontFactory(int size, String[] families) { + this(families); + minSize = maxSize = size; + } + + public void setFamilies(List families) { + this.families = families; + } + + public void setMinSize(int minSize) { + this.minSize = minSize; + } + + public void setMaxSize(int maxSize) { + this.maxSize = maxSize; + } + + public void setRandomStyle(boolean randomStyle) { + this.randomStyle = randomStyle; + } + + @Override + public Font getFont(int index) { + Random r = new Random(); + String family = families.get(r.nextInt(families.size())); + boolean bold = r.nextBoolean() && randomStyle; + int size = minSize; + if (maxSize - minSize > 0) { + size += r.nextInt(maxSize - minSize); + } + return new Font(family, bold ? Font.BOLD : Font.PLAIN, size); + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/service/AbstractCaptchaService.java b/blade-patchca/src/main/java/org/patchca/service/AbstractCaptchaService.java new file mode 100644 index 000000000..d7a723fe6 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/service/AbstractCaptchaService.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.service; + +import org.patchca.background.BackgroundFactory; +import org.patchca.color.ColorFactory; +import org.patchca.filter.FilterFactory; +import org.patchca.font.FontFactory; +import org.patchca.text.renderer.TextRenderer; +import org.patchca.word.WordFactory; + +import java.awt.image.BufferedImage; + +public abstract class AbstractCaptchaService implements CaptchaService { + + protected FontFactory fontFactory; + protected WordFactory wordFactory; + protected ColorFactory colorFactory; + protected BackgroundFactory backgroundFactory; + protected TextRenderer textRenderer; + protected FilterFactory filterFactory; + protected int width; + protected int height; + + public void setFontFactory(FontFactory fontFactory) { + this.fontFactory = fontFactory; + } + + public void setWordFactory(WordFactory wordFactory) { + this.wordFactory = wordFactory; + } + + public void setColorFactory(ColorFactory colorFactory) { + this.colorFactory = colorFactory; + } + + public void setBackgroundFactory(BackgroundFactory backgroundFactory) { + this.backgroundFactory = backgroundFactory; + } + + public void setTextRenderer(TextRenderer textRenderer) { + this.textRenderer = textRenderer; + } + + public void setFilterFactory(FilterFactory filterFactory) { + this.filterFactory = filterFactory; + } + + public FontFactory getFontFactory() { + return fontFactory; + } + + public WordFactory getWordFactory() { + return wordFactory; + } + + public ColorFactory getColorFactory() { + return colorFactory; + } + + public BackgroundFactory getBackgroundFactory() { + return backgroundFactory; + } + + public TextRenderer getTextRenderer() { + return textRenderer; + } + + public FilterFactory getFilterFactory() { + return filterFactory; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + @Override + public Captcha getCaptcha() { + BufferedImage bufImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + backgroundFactory.fillBackground(bufImage); + String word = wordFactory.getNextWord(); + textRenderer.draw(word, bufImage, fontFactory, colorFactory); + bufImage = filterFactory.applyFilters(bufImage); + return new Captcha(word, bufImage); + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/service/Captcha.java b/blade-patchca/src/main/java/org/patchca/service/Captcha.java new file mode 100644 index 000000000..c80ccad9b --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/service/Captcha.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.service; + +import java.awt.image.BufferedImage; + +public class Captcha { + + private String challenge; + private BufferedImage image; + + public Captcha(String challenge, BufferedImage image) { + this.challenge = challenge; + this.image = image; + } + + public String getChallenge() { + return challenge; + } + + public void setChallenge(String challenge) { + this.challenge = challenge; + } + + public BufferedImage getImage() { + return image; + } + + public void setImage(BufferedImage image) { + this.image = image; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/service/CaptchaService.java b/blade-patchca/src/main/java/org/patchca/service/CaptchaService.java new file mode 100644 index 000000000..b26f6d6da --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/service/CaptchaService.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.service; + +public interface CaptchaService { + + Captcha getCaptcha(); +} diff --git a/blade-patchca/src/main/java/org/patchca/service/ConfigurableCaptchaService.java b/blade-patchca/src/main/java/org/patchca/service/ConfigurableCaptchaService.java new file mode 100644 index 000000000..eeb9500f7 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/service/ConfigurableCaptchaService.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.service; + +import org.patchca.background.SingleColorBackgroundFactory; +import org.patchca.color.SingleColorFactory; +import org.patchca.filter.predefined.CurvesRippleFilterFactory; +import org.patchca.font.RandomFontFactory; +import org.patchca.text.renderer.BestFitTextRenderer; +import org.patchca.word.AdaptiveRandomWordFactory; + +public class ConfigurableCaptchaService extends AbstractCaptchaService { + + public ConfigurableCaptchaService() { + backgroundFactory = new SingleColorBackgroundFactory(); + wordFactory = new AdaptiveRandomWordFactory(); + fontFactory = new RandomFontFactory(); + textRenderer = new BestFitTextRenderer(); + colorFactory = new SingleColorFactory(); + filterFactory = new CurvesRippleFilterFactory(colorFactory); + textRenderer.setLeftMargin(10); + textRenderer.setRightMargin(10); + width = 160; + height = 70; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/service/SimpleCaptchaService.java b/blade-patchca/src/main/java/org/patchca/service/SimpleCaptchaService.java new file mode 100644 index 000000000..55311a6c5 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/service/SimpleCaptchaService.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.service; + +import org.patchca.background.SingleColorBackgroundFactory; +import org.patchca.color.SingleColorFactory; +import org.patchca.filter.FilterFactory; +import org.patchca.font.RandomFontFactory; +import org.patchca.text.renderer.BestFitTextRenderer; +import org.patchca.word.AdaptiveRandomWordFactory; + +import java.awt.*; + +public class SimpleCaptchaService extends AbstractCaptchaService { + + public SimpleCaptchaService(int width, int height, Color textColor, Color backgroundColor, int fontSize, FilterFactory ff) { + backgroundFactory = new SingleColorBackgroundFactory(backgroundColor); + wordFactory = new AdaptiveRandomWordFactory(); + fontFactory = new RandomFontFactory(); + textRenderer = new BestFitTextRenderer(); + colorFactory = new SingleColorFactory(textColor); + filterFactory = ff; + this.width = width; + this.height = height; + } + + public SimpleCaptchaService(int width, int height, Color textColor, Color backgroundColor, int fontSize, String[]fontNames, FilterFactory ff) { + backgroundFactory = new SingleColorBackgroundFactory(backgroundColor); + wordFactory = new AdaptiveRandomWordFactory(); + fontFactory = new RandomFontFactory(fontNames); + textRenderer = new BestFitTextRenderer(); + colorFactory = new SingleColorFactory(textColor); + filterFactory = ff; + this.width = width; + this.height = height; + } + + @Override + public Captcha getCaptcha() { + return null; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/AbstractTextRenderer.java b/blade-patchca/src/main/java/org/patchca/text/renderer/AbstractTextRenderer.java new file mode 100644 index 000000000..95044db75 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/text/renderer/AbstractTextRenderer.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.text.renderer; + +import org.patchca.color.ColorFactory; +import org.patchca.font.FontFactory; + +import java.awt.*; +import java.awt.font.FontRenderContext; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; + +public abstract class AbstractTextRenderer implements TextRenderer { + + protected int leftMargin; + protected int rightMargin; + protected int topMargin; + protected int bottomMargin; + + protected abstract void arrangeCharacters(int width, int height, TextString ts); + + public AbstractTextRenderer() { + leftMargin = rightMargin = 5; + topMargin = bottomMargin = 5; + } + + @Override + public void setLeftMargin(int leftMargin) { + this.leftMargin = leftMargin; + } + + @Override + public void setRightMargin(int rightMargin) { + this.rightMargin = rightMargin; + } + + @Override + public void setTopMargin(int topMargin) { + this.topMargin = topMargin; + } + + @Override + public void setBottomMargin(int bottomMargin) { + this.bottomMargin = bottomMargin; + } + + @Override + public void draw(String text, BufferedImage canvas, FontFactory fontFactory, ColorFactory colorFactory) { + Graphics2D g = (Graphics2D) canvas.getGraphics(); + TextString ts = convertToCharacters(text, g, fontFactory, colorFactory); + arrangeCharacters(canvas.getWidth(), canvas.getHeight(), ts); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + for (TextCharacter tc : ts.getCharacters()) { + g.setColor(tc.getColor()); + g.drawString(tc.iterator(), (float) tc.getX(), (float) tc.getY()); + } + } + + protected TextString convertToCharacters(String text, Graphics2D g, FontFactory fontFactory, ColorFactory colorFactory) { + TextString characters = new TextString(); + FontRenderContext frc = g.getFontRenderContext(); + double lastx = 0; + for (int i = 0; i < text.length(); i++) { + Font font = fontFactory.getFont(i); + char c = text.charAt(i); + FontMetrics fm = g.getFontMetrics(font); + Rectangle2D bounds = font.getStringBounds(String.valueOf(c), frc); + TextCharacter tc = new TextCharacter(); + tc.setCharacter(c); + tc.setFont(font); + tc.setWidth(fm.charWidth(c)); + tc.setHeight(fm.getAscent() + fm.getDescent()); + tc.setAscent(fm.getAscent()); + tc.setDescent(fm.getDescent()); + tc.setX(lastx); + tc.setY(0); + tc.setFont(font); + tc.setColor(colorFactory.getColor(i)); + lastx += bounds.getWidth(); + characters.addCharacter(tc); + } + return characters; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/BestFitTextRenderer.java b/blade-patchca/src/main/java/org/patchca/text/renderer/BestFitTextRenderer.java new file mode 100644 index 000000000..60762edcd --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/text/renderer/BestFitTextRenderer.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.text.renderer; + +public class BestFitTextRenderer extends AbstractTextRenderer { + + @Override + protected void arrangeCharacters(int width, int height, TextString ts) { + double widthRemaining = (width - ts.getWidth() - leftMargin - rightMargin) / ts.getCharacters().size(); + double x = leftMargin + widthRemaining / 2; + height -= topMargin + bottomMargin; + for (TextCharacter tc : ts.getCharacters()) { + double y = topMargin + (height + tc.getAscent() * 0.7) / 2; + tc.setX(x); + tc.setY(y); + x += tc.getWidth() + widthRemaining; + } + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/RandomYBestFitTextRenderer.java b/blade-patchca/src/main/java/org/patchca/text/renderer/RandomYBestFitTextRenderer.java new file mode 100644 index 000000000..b6a4250a4 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/text/renderer/RandomYBestFitTextRenderer.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.text.renderer; + +import java.util.Random; + +public class RandomYBestFitTextRenderer extends AbstractTextRenderer { + + @Override + protected void arrangeCharacters(int width, int height, TextString ts) { + double widthRemaining = (width - ts.getWidth() - leftMargin - rightMargin) / ts.getCharacters().size(); + double vmiddle = height / 2; + double x = leftMargin + widthRemaining / 2; + Random r = new Random(); + height -= topMargin + bottomMargin; + for (TextCharacter tc : ts.getCharacters()) { + double heightRemaining = height - tc.getHeight(); + double y = vmiddle + 0.35 * tc.getAscent() + (1 - 2 * r.nextDouble()) * heightRemaining; + tc.setX(x); + tc.setY(y); + x += tc.getWidth() + widthRemaining; + } + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/SimpleTextRenderer.java b/blade-patchca/src/main/java/org/patchca/text/renderer/SimpleTextRenderer.java new file mode 100644 index 000000000..dc68afc35 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/text/renderer/SimpleTextRenderer.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.text.renderer; + +public class SimpleTextRenderer extends AbstractTextRenderer { + + @Override + protected void arrangeCharacters(int width, int height, TextString ts) { + double x = leftMargin; + for (TextCharacter tc : ts.getCharacters()) { + double y = topMargin + (height + tc.getAscent() * 0.7) / 2; + tc.setX(x); + tc.setY(y); + x += tc.getWidth(); + } + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/TextCharacter.java b/blade-patchca/src/main/java/org/patchca/text/renderer/TextCharacter.java new file mode 100644 index 000000000..4e0e025f2 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/text/renderer/TextCharacter.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.text.renderer; + +import java.awt.*; +import java.awt.font.TextAttribute; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; + +public class TextCharacter { + + private double x; + private double y; + private double width; + private double height; + private double ascent; + private double descent; + private char character; + private Font font; + private Color color; + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public double getWidth() { + return width; + } + + public void setWidth(double width) { + this.width = width; + } + + public double getHeight() { + return height; + } + + public void setHeight(double height) { + this.height = height; + } + + public char getCharacter() { + return character; + } + + public void setCharacter(char character) { + this.character = character; + } + + public Font getFont() { + return font; + } + + public void setFont(Font font) { + this.font = font; + } + + public Color getColor() { + return color; + } + + public void setColor(Color color) { + this.color = color; + } + + public double getAscent() { + return ascent; + } + + public void setAscent(double ascent) { + this.ascent = ascent; + } + + public double getDescent() { + return descent; + } + + public void setDescent(double descent) { + this.descent = descent; + } + + public AttributedCharacterIterator iterator() { + AttributedString aString = new AttributedString(String + .valueOf(character)); + aString.addAttribute(TextAttribute.FONT, font, 0, 1); + return aString.getIterator(); + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/TextRenderer.java b/blade-patchca/src/main/java/org/patchca/text/renderer/TextRenderer.java new file mode 100644 index 000000000..24caf7e37 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/text/renderer/TextRenderer.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.text.renderer; + +import org.patchca.color.ColorFactory; +import org.patchca.font.FontFactory; + +import java.awt.image.BufferedImage; + +public interface TextRenderer { + + void setLeftMargin(int leftMargin); + + void setRightMargin(int rightMargin); + + void setTopMargin(int topMargin); + + void setBottomMargin(int bottomMargin); + + void draw(String text, BufferedImage canvas, FontFactory fontFactory, ColorFactory colorFactory); + +} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/TextString.java b/blade-patchca/src/main/java/org/patchca/text/renderer/TextString.java new file mode 100644 index 000000000..903324fcd --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/text/renderer/TextString.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.text.renderer; + +import java.util.ArrayList; + +public class TextString { + + private ArrayList characters = new ArrayList(); + + public void clear() { + characters.clear(); + } + + public void addCharacter(TextCharacter tc) { + characters.add(tc); + } + + public ArrayList getCharacters() { + return characters; + } + + public double getWidth() { + double minx = 0; + double maxx = 0; + boolean first = true; + for (TextCharacter tc : characters) { + if (first) { + minx = tc.getX(); + maxx = tc.getX() + tc.getWidth(); + first = false; + } else { + if (minx > tc.getX()) { + minx = tc.getX(); + } + if (maxx < tc.getX() + tc.getWidth()) { + maxx = tc.getX() + tc.getWidth(); + } + } + + } + return maxx - minx; + } + + public double getHeight() { + double miny = 0; + double maxy = 0; + boolean first = true; + for (TextCharacter tc : characters) { + if (first) { + miny = tc.getY(); + maxy = tc.getY() + tc.getHeight(); + first = false; + } else { + if (miny > tc.getY()) { + miny = tc.getY(); + } + if (maxy < tc.getY() + tc.getHeight()) { + maxy = tc.getY() + tc.getHeight(); + } + } + + } + return maxy - miny; + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/utils/encoder/EncoderHelper.java b/blade-patchca/src/main/java/org/patchca/utils/encoder/EncoderHelper.java new file mode 100644 index 000000000..d34af1e7a --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/utils/encoder/EncoderHelper.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.utils.encoder; + +import org.patchca.service.Captcha; +import org.patchca.service.CaptchaService; + +import javax.imageio.ImageIO; +import java.io.IOException; +import java.io.OutputStream; + +public class EncoderHelper { + + public static String getChallangeAndWriteImage(CaptchaService service, String format, OutputStream os) throws IOException { + Captcha captcha = service.getCaptcha(); + ImageIO.write(captcha.getImage(), format, os); + return captcha.getChallenge(); + } + +} + diff --git a/blade-patchca/src/main/java/org/patchca/word/AdaptiveRandomWordFactory.java b/blade-patchca/src/main/java/org/patchca/word/AdaptiveRandomWordFactory.java new file mode 100644 index 000000000..c0de231a4 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/word/AdaptiveRandomWordFactory.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.word; + +import java.util.Random; + +public class AdaptiveRandomWordFactory extends RandomWordFactory { + + protected String wideCharacters; + + public void setWideCharacters(String wideCharacters) { + this.wideCharacters = wideCharacters; + } + + public AdaptiveRandomWordFactory() { + characters = "absdegkmnopwx23456789"; + wideCharacters = "mw"; + } + + @Override + public String getNextWord() { + Random rnd = new Random(); + StringBuffer sb = new StringBuffer(); + StringBuffer chars = new StringBuffer(characters); + int l = minLength + (maxLength > minLength ? rnd.nextInt(maxLength - minLength) : 0); + for (int i = 0; i < l; i++) { + int j = rnd.nextInt(chars.length()); + char c = chars.charAt(j); + if (wideCharacters.indexOf(c) != -1) { + for (int k = 0; k < wideCharacters.length(); k++) { + int idx = chars.indexOf(String.valueOf(wideCharacters.charAt(k))); + if (idx != -1) { + chars.deleteCharAt(idx); + } + } + } + sb.append(c); + } + return sb.toString(); + } + +} diff --git a/blade-patchca/src/main/java/org/patchca/word/RandomWordFactory.java b/blade-patchca/src/main/java/org/patchca/word/RandomWordFactory.java new file mode 100644 index 000000000..f1848fbf8 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/word/RandomWordFactory.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.word; + +import java.util.Random; + +public class RandomWordFactory implements WordFactory { + + protected String characters; + protected int minLength; + protected int maxLength; + + public void setCharacters(String characters) { + this.characters = characters; + } + + public void setMinLength(int minLength) { + this.minLength = minLength; + } + + public void setMaxLength(int maxLength) { + this.maxLength = maxLength; + } + + public RandomWordFactory() { + characters = "absdegkmnopwx23456789"; + minLength = 6; + maxLength = 6; + } + + @Override + public String getNextWord() { + Random rnd = new Random(); + StringBuffer sb = new StringBuffer(); + int l = minLength + (maxLength > minLength ? rnd.nextInt(maxLength - minLength) : 0); + for (int i = 0; i < l; i++) { + int j = rnd.nextInt(characters.length()); + sb.append(characters.charAt(j)); + } + return sb.toString(); + } + + +} diff --git a/blade-patchca/src/main/java/org/patchca/word/WordFactory.java b/blade-patchca/src/main/java/org/patchca/word/WordFactory.java new file mode 100644 index 000000000..d410bfc60 --- /dev/null +++ b/blade-patchca/src/main/java/org/patchca/word/WordFactory.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2009 Piotr Piastucki + * + * This file is part of Patchca CAPTCHA library. + * + * Patchca is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Patchca is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Patchca. If not, see . + */ +package org.patchca.word; + +public interface WordFactory { + + String getNextWord(); +} diff --git a/blade-patchca/src/test/java/org/blade/patchca/AppTest.java b/blade-patchca/src/test/java/org/blade/patchca/AppTest.java new file mode 100644 index 000000000..011975764 --- /dev/null +++ b/blade-patchca/src/test/java/org/blade/patchca/AppTest.java @@ -0,0 +1,15 @@ +package org.blade.patchca; + +import java.io.IOException; + +import com.blade.patchca.PatchcaService; + +public class AppTest { + + public static void main(String[] args) throws IOException { + + PatchcaService service = PatchcaService.get(); + // 生成一个验证码到本地 + service.create("F:/aaa.png", "png"); + } +} diff --git a/pom.xml b/pom.xml index bab5e895f..10d9746cf 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,8 @@ blade-startup blade-sample blade-aop + blade-oauth2 + blade-patchca From 91f5692f4df1fdbf4596a519175eec5c6f1f533b Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 4 Dec 2015 18:36:19 +0800 Subject: [PATCH 275/545] update token method --- .../com/blade/patchca/PatchcaService.java | 26 ++++++++++++------- pom.xml | 2 +- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java index 6f6df152f..39393fc55 100644 --- a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java +++ b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java @@ -5,7 +5,6 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.util.Random; import org.patchca.color.ColorFactory; @@ -27,12 +26,9 @@ public class PatchcaService { private static final Logger LOGGER = Logger.getLogger(PatchcaService.class); - + private ConfigurableCaptchaService cs = null; private static Random random = new Random(); - public String CHARS = "23456789abcdefghigkmnpqrstuvwxyzABCDEFGHIGKLMNPQRSTUVWXYZ"; - public Integer maxLen = 4; - public Integer minLen = 4; private PatchcaService() { cs = new ConfigurableCaptchaService(); @@ -53,9 +49,9 @@ public Color getColor(int x) { } }); RandomWordFactory wf = new RandomWordFactory(); - wf.setCharacters(CHARS); - wf.setMaxLength(maxLen); - wf.setMinLength(minLen); + wf.setCharacters("23456789abcdefghigkmnpqrstuvwxyzABCDEFGHIGKLMNPQRSTUVWXYZ"); + wf.setMaxLength(4); + wf.setMinLength(4); cs.setWordFactory(wf); cs.setFilterFactory(new DiffuseRippleFilterFactory()); } @@ -100,9 +96,19 @@ private void setResponseHeaders(Response response) { response.header("Expires", time + ""); } - public String getToken(String imgType, OutputStream outputStream){ + public String token(String imgType, Response response){ try { - String token = EncoderHelper.getChallangeAndWriteImage(cs, imgType, outputStream); + String token = EncoderHelper.getChallangeAndWriteImage(cs, imgType, response.outputStream()); + return token; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + public String token(Response response){ + try { + String token = EncoderHelper.getChallangeAndWriteImage(cs, "png", response.outputStream()); return token; } catch (IOException e) { e.printStackTrace(); diff --git a/pom.xml b/pom.xml index 10d9746cf..8c88707d2 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ blade-sample blade-aop blade-oauth2 - blade-patchca + blade-patchca From 8f86f94cedd99f7632bfba2159a9c8062ff06970 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 4 Dec 2015 18:37:55 +0800 Subject: [PATCH 276/545] add patchca pom.xml and readme --- blade-patchca/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 blade-patchca/README.md diff --git a/blade-patchca/README.md b/blade-patchca/README.md new file mode 100644 index 000000000..4d706a7e7 --- /dev/null +++ b/blade-patchca/README.md @@ -0,0 +1,4 @@ +# blade-patchca + +基于blade框架 + patchca 的验证码工具包。 + From 9c84135773de7902b3fa43af0f4aa31a79ec33bb Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 4 Dec 2015 18:45:37 +0800 Subject: [PATCH 277/545] update blade-core version to 1.4.2-alpha --- LAST_VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 4b933ea69..8ee8ad485 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -32,7 +32,7 @@     com.bladejava     blade-core -    1.4.1 +    1.4.2-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) From 9d4783390048bb084c81a1cc97155ac814fa9ef0 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 7 Dec 2015 16:46:45 +0800 Subject: [PATCH 278/545] add pom.xml --- blade-oauth2/pom.xml | 24 ++++++++++++++++++++++++ blade-patchca/pom.xml | 23 +++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 blade-oauth2/pom.xml create mode 100644 blade-patchca/pom.xml diff --git a/blade-oauth2/pom.xml b/blade-oauth2/pom.xml new file mode 100644 index 000000000..ba01fe9da --- /dev/null +++ b/blade-oauth2/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + blade-oauth2 + 1.0 + blade-oauth2 + http://maven.apache.org + + + + com.bladejava + blade-core + ${blade.version} + + + + diff --git a/blade-patchca/pom.xml b/blade-patchca/pom.xml new file mode 100644 index 000000000..dd4243c09 --- /dev/null +++ b/blade-patchca/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + blade-patchca + 1.0.0 + blade-patchca + http://maven.apache.org + + + + com.bladejava + blade-core + ${blade.version} + + + From d0fc55ec1d3b1f04e277495720ea0d943492201e Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 10:18:29 +0800 Subject: [PATCH 279/545] add comments --- blade-core/src/main/java/com/blade/Blade.java | 10 + .../src/main/java/com/blade/http/Request.java | 201 +++++++++++++++++- .../com/blade/servlet/ServletRequest.java | 43 +++- 3 files changed, 243 insertions(+), 11 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 64ddbe94d..bada03197 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -154,6 +154,16 @@ public Container container(){ return container; } + /** + * 设置一个IOC容器 + * @param container ioc容器对象 + * @return 返回blade + */ + public Blade container(Container container){ + this.container = container; + return this; + } + /** * Properties配置文件方式 * 文件的路径基于classpath diff --git a/blade-core/src/main/java/com/blade/http/Request.java b/blade-core/src/main/java/com/blade/http/Request.java index 09f9d7f03..8e82ec1cb 100644 --- a/blade-core/src/main/java/com/blade/http/Request.java +++ b/blade-core/src/main/java/com/blade/http/Request.java @@ -38,96 +38,287 @@ */ public interface Request { + /** + * @return 返回HttpServletRequest原生对象 + */ HttpServletRequest raw(); + /** + * 初始化路由上的URL参数,如:/user/23 + * @param routePath 路由URL + */ void initPathParams(String routePath); + /** + * @return 返回客户端请求主机 + */ String host(); + /** + * @return 返回请求URL + */ String url(); + /** + * @return 返回请求uri + */ String path(); + /** + * @return 返回UA + */ String userAgent(); + /** + * @return 返回PathInfo + */ String pathInfo(); + /** + * @return 返回协议 + */ String protocol(); + /** + * @return 返回servletPath + */ String servletPath(); + /** + * @return 返回contextPath + */ String contextPath(); + /** + * @return 返回上下文对象 + */ ServletContext context(); + /** + * @return 路径上的参数Map + */ Map pathParams(); + /** + * 获取一个URL上的参数 + * @param name 参数名 + * @return 返回参数值 + */ String param(String name); + /** + * 获取一个URL上的参数,如果为NULL则返回defaultValue + * @param name 参数名 + * @param defaultValue 默认值 + * @return 返回参数值 + */ + String param(String name, String defaultValue); + + /** + * 返回一个Int类型的URL参数 + * @param name 参数名 + * @return 返回Int参数值 + */ Integer paramAsInt(String name); + /** + * 返回一个Long类型的URL参数 + * @param name 参数名 + * @return 返回Long参数值 + */ Long paramAsLong(String name); - Boolean paramAsBoolean(String name); + /** + * 返回一个Boolean类型的URL参数 + * @param name 参数名 + * @return 返回Boolean参数值 + */ + Boolean paramAsBool(String name); + /** + * @return 返回请求字符串 + */ String queryString(); + /** + * @return 返回请求参数Map + */ Map querys(); + /** + * 获取一个请求参数 + * @param name 参数名 + * @return 返回请求参数值 + */ String query(String name); + /** + * 获取一个请求参数,如果为NULL则返回defaultValue + * @param name 参数名 + * @param defaultValue 默认返回值 + * @return 返回请求参数值 + */ + String query(String name, String defaultValue); + + /** + * 返回一个Int类型的请求参数 + * @param name 参数名 + * @return 返回Int参数值 + */ Integer queryAsInt(String name); + /** + * 返回一个Long类型的请求参数 + * @param name 参数名 + * @return 返回Long参数值 + */ Long queryAsLong(String name); - Boolean queryAsBoolean(String name); - + /** + * 返回一个Boolean类型的请求参数 + * @param name 参数名 + * @return 返回Boolean参数值 + */ + Boolean queryAsBool(String name); + + /** + * 返回一个Float类型的请求参数 + * @param name 参数名 + * @return 返回Float参数值 + */ Float queryAsFloat(String name); + /** + * 返回一个Double类型的请求参数 + * @param name 参数名 + * @return 返回Double参数值 + */ Double queryAsDouble(String name); + /** + * @return 返回请求方法 + */ String method(); + /** + * @return 返回枚举类型的HttpMethod + */ HttpMethod httpMethod(); + /** + * @return 返回服务器远程地址 + */ String address(); + /** + * @return 返回当前会话 + */ Session session(); + /** + * 返回当前或创建一个会话 + * @param create 是否创建会话 + * @return 返回会话对象 + */ Session session(boolean create); + /** + * @return 返回contentType + */ String contentType(); + /** + * @return 返回服务器端口 + */ int port(); + /** + * @return 返回是否使用SSL连接 + */ boolean isSecure(); + /** + * @return 放回当前请求是否是AJAX请求 + */ boolean isAjax(); + /** + * @return 返回Cookie Map + */ Map cookies(); + /** + * 获取String类型Cookie + * @param name cookie name + * @return 返回cookie值 + */ String cookie(String name); + /** + * 获取Cookie + * @param name cookie name + * @return 返回cookie值 + */ Cookie cookieRaw(String name); + /** + * @return 返回头信息Map + */ Map headers(); + /** + * 获取头信息 + * @param name 参数名 + * @return 返回头信息 + */ String header(String name); - + + /** + * 设置请求编码 + * @param encoding 编码字符串 + */ void encoding(String encoding); + /** + * 设置一个RequestAttribute + * @param name 参数名 + * @param value 参数值 + */ void attribute(String name, Object value); + /** + * 获取一个RequestAttribute + * @param name 参数名 + * @return 返回参数值 + */ T attribute(String name); + /** + * @return 返回Request中所有Attribute + */ Set attributes(); + /** + * @return 返回请求中文件列表 + */ FileItem[] files(); - + + /** + * @return 返回请求体 + */ BodyParser body(); + /** + * 设置路由,执行请求用 + * @param route 路由对象 + */ void setRoute(Route route); + /** + * 请求体接口 + * @author biezhi + * + */ interface BodyParser { String asString(); InputStream asInputStream(); diff --git a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java index 5b374f042..ba5f194d0 100644 --- a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/servlet/ServletRequest.java @@ -203,7 +203,19 @@ public Map pathParams() { @Override public String param(String name) { String val = pathParams.get(name); - if(blade.enableXSS()){ + if(null != val && blade.enableXSS()){ + return HTMLFilter.htmlSpecialChars(val); + } + return val; + } + + @Override + public String param(String name, String defaultValue) { + String val = pathParams.get(name); + if(null == val){ + val = defaultValue; + } + if (null != val && blade.enableXSS()) { return HTMLFilter.htmlSpecialChars(val); } return val; @@ -228,7 +240,7 @@ public Long paramAsLong(String name) { } @Override - public Boolean paramAsBoolean(String name) { + public Boolean paramAsBool(String name) { String value = param(name); if (null != value) { return Boolean.valueOf(value); @@ -256,11 +268,30 @@ public Map querys() { @Override public String query(String name) { String[] param = request.getParameterValues(name); + String val = null; if (param != null) { - return join(param); + val = join(param); + } else { + val = multipartParams.get(name); + } + if(null != val && blade.enableXSS()){ + return HTMLFilter.htmlSpecialChars(val); + } + return val; + } + + @Override + public String query(String name, String defaultValue) { + String[] param = request.getParameterValues(name); + String val = null; + if (param != null) { + val = join(param); + } else { + val = multipartParams.get(name); + } + if(null == val){ + val = defaultValue; } - - String val = multipartParams.get(name); if(blade.enableXSS()){ return HTMLFilter.htmlSpecialChars(val); } @@ -286,7 +317,7 @@ public Long queryAsLong(String name) { } @Override - public Boolean queryAsBoolean(String name) { + public Boolean queryAsBool(String name) { String value = query(name); if (null != value) { return Boolean.valueOf(value); From 04078a35afb54cbd8e693d39f0da0ec8dd1acd07 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 13:59:54 +0800 Subject: [PATCH 280/545] remove test code --- blade-core/pom.xml | 28 -- .../test/java/com/blade/BladeTestCase.java | 45 --- .../test/java/com/blade/MockAnnotation.java | 12 - .../test/java/com/blade/MockController.java | 12 - .../com/blade/servlet/ServletRequestTest.java | 307 ------------------ .../blade/servlet/ServletResponseTest.java | 193 ----------- pom.xml | 2 +- 7 files changed, 1 insertion(+), 598 deletions(-) delete mode 100644 blade-core/src/test/java/com/blade/BladeTestCase.java delete mode 100644 blade-core/src/test/java/com/blade/MockAnnotation.java delete mode 100644 blade-core/src/test/java/com/blade/MockController.java delete mode 100644 blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java delete mode 100644 blade-core/src/test/java/com/blade/servlet/ServletResponseTest.java diff --git a/blade-core/pom.xml b/blade-core/pom.xml index ebb80cdc1..e12fca680 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -66,34 +66,6 @@ ${jetty.version} provided - - junit - junit - - - org.mockito - mockito-all - 1.9.5 - test - - - org.apache.httpcomponents - httpclient - ${httpclient.version} - test - - - org.apache.httpcomponents - fluent-hc - ${httpclient.version} - test - - - org.slf4j - slf4j-api - ${slf4j.version} - test - diff --git a/blade-core/src/test/java/com/blade/BladeTestCase.java b/blade-core/src/test/java/com/blade/BladeTestCase.java deleted file mode 100644 index b7e965b08..000000000 --- a/blade-core/src/test/java/com/blade/BladeTestCase.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.net.ConnectException; -import java.net.Socket; - -import org.apache.http.HttpResponse; -import org.apache.http.client.fluent.Request; -import org.junit.Assert; -import org.junit.Test; - -public class BladeTestCase { - - @SuppressWarnings("resource") - @Test - public void testStartStopServer() throws Exception { - Blade blade = Blade.me(); - blade.listen(10241).start(); - try { - HttpResponse response = Request.Get("http://localhost:10241/").execute().returnResponse(); - Assert.assertEquals(response.getStatusLine().getStatusCode(), 404); - } finally { - blade.stop(); - try { - new Socket("localhost", 10241); - Assert.fail("Server is still running"); - } catch (ConnectException e) {} - } - } - -} diff --git a/blade-core/src/test/java/com/blade/MockAnnotation.java b/blade-core/src/test/java/com/blade/MockAnnotation.java deleted file mode 100644 index a3c780fc6..000000000 --- a/blade-core/src/test/java/com/blade/MockAnnotation.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.blade; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ ElementType.TYPE, ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -public @interface MockAnnotation { - -} diff --git a/blade-core/src/test/java/com/blade/MockController.java b/blade-core/src/test/java/com/blade/MockController.java deleted file mode 100644 index 2ecf408e2..000000000 --- a/blade-core/src/test/java/com/blade/MockController.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.blade; - -import com.blade.http.Request; -import com.blade.http.Response; - -public class MockController { - - public void init(Request request, Response response) {} - - public void show(Request request, Response response) {} - -} \ No newline at end of file diff --git a/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java b/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java deleted file mode 100644 index fab1b8ea0..000000000 --- a/blade-core/src/test/java/com/blade/servlet/ServletRequestTest.java +++ /dev/null @@ -1,307 +0,0 @@ -package com.blade.servlet; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; - -import org.junit.Assert; -import org.junit.Test; - -import com.blade.MockController; -import com.blade.http.HttpMethod; -import com.blade.http.Request; -import com.blade.http.Response; -import com.blade.route.Route; - -public class ServletRequestTest { - - @Test - public void testRetrieveHost() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getServerName()).thenReturn("localhost"); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.host(), "localhost"); - } - - @Test - public void testRetrievePath() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getContextPath()).thenReturn("/context"); - when(servletRequest.getRequestURI()).thenReturn("/users/edit/1"); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.path(), "/users/edit/1"); - } - - @Test - public void testRetrievePathVariables() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getContextPath()).thenReturn(""); - when(servletRequest.getRequestURI()).thenReturn("/users/1/edit/th1s1s4hAsh/"); - - Route route = new Route(HttpMethod.GET, "/users/:userId/edit/:hash", new MockController(), - MockController.class.getMethod("init", Request.class, Response.class)); - Request request = new ServletRequest(servletRequest); - request.setRoute(route); - - Map pathVariables = request.pathParams(); - Assert.assertNotNull(pathVariables); - Assert.assertEquals(pathVariables.size(), 2); - Assert.assertEquals(pathVariables.get("userId"), "1"); - Assert.assertEquals(pathVariables.get("hash"), "th1s1s4hAsh"); - } - - @Test - public void testNotRetrieveNonExistingPathVariable() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getContextPath()).thenReturn(""); - when(servletRequest.getRequestURI()).thenReturn("/users/1/edit/th1s1s4hAsh"); - - Route route = new Route(HttpMethod.GET, "/users/1/edit/th1s1s4hAsh", new MockController(), - MockController.class.getMethod("init", Request.class, Response.class)); - Request request = new ServletRequest(servletRequest); - request.setRoute(route); - - Map pathVariables = request.pathParams(); - Assert.assertNotNull(pathVariables); - Assert.assertEquals(pathVariables.size(), 0); - } - - @Test - public void testRetrieveQueryString() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getQueryString()).thenReturn("method=test&action=success"); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.queryString(), "method=test&action=success"); - } - - @Test - public void testRetrieveParams() throws Exception { - Map mockParams = new HashMap(); - mockParams.put("param1", new String[]{"value1"}); - mockParams.put("param2", new String[]{"val1", "val2"}); - - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getParameterMap()).thenReturn(mockParams); - - Request request = new ServletRequest(servletRequest); - - Map params = request.querys(); - Assert.assertNotNull(params); - Assert.assertEquals(params.size(), 2); - - String param1 = params.get("param1"); - Assert.assertNotNull(param1); - Assert.assertEquals(param1, "value1"); - - String param2 = params.get("param2"); - Assert.assertNotNull(param2); - Assert.assertEquals(param2, "val1,val2"); - - Assert.assertNull(params.get("notexistnet")); - } - - @Test - public void testRetrieveStringParam() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getParameterValues("param1")).thenReturn(new String[]{"value1"}); - - Request request = new ServletRequest(servletRequest); - - Assert.assertNotNull(request.query("param1")); - Assert.assertEquals(request.query("param1"), "value1"); - } - - @Test - public void testNotRetrieveNonExistingParam() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - Request request = new ServletRequest(servletRequest); - Assert.assertNull(request.query("nonexisting")); - } - - @Test - public void testRetrieveLongParam() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getParameterValues("param1")).thenReturn(new String[]{"1"}); - - Request request = new ServletRequest(servletRequest); - - Assert.assertNotNull(request.query("param1")); - Assert.assertEquals(request.query("param1"), "1"); - } - - @Test - public void testRetrieveUrl() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getRequestURL()).thenReturn(new StringBuffer("http://www.google.com:81/test")); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.url(), "http://www.google.com:81/test"); - } - - @Test - public void testRetrieveMethod() throws Exception { - HttpServletRequest servletRequest = mockServletRequest("GET"); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.method(), "GET"); - } - - @Test - public void testRetrieveRemoteAddress() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getRemoteAddr()).thenReturn("localhost"); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.address(), "localhost"); - } - - @Test - public void testRetrieveContentType() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getContentType()).thenReturn("application/json"); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.contentType(), "application/json"); - } - - @Test - public void testRetrievePort() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getServerPort()).thenReturn(1); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.port(), 1); - } - - @Test - public void testRetrieveIsSecure() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.isSecure()).thenReturn(true); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.isSecure(), true); - } - - @Test - public void testRetrieveIsAjax() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getHeader("x-requested-with")).thenReturn("XMLHttpRequest"); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.isAjax(), true); - - when(servletRequest.getHeader("x-requested-with")).thenReturn(null); - Assert.assertEquals(request.isAjax(), false); - - when(servletRequest.getHeader("x-requested-with")).thenReturn("Another"); - Assert.assertEquals(request.isAjax(), false); - } - - @Test - public void testRetrieveCookie() throws Exception { - javax.servlet.http.Cookie[] servletCookies = {new javax.servlet.http.Cookie("test-1", "1")}; - - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getCookies()).thenReturn(servletCookies); - - Request request = new ServletRequest(servletRequest); - Map cookies = request.cookies(); - - Assert.assertEquals(cookies.size(), 1); - - Cookie cookie = cookies.get("test-1"); - Assert.assertNotNull(cookie); - Assert.assertEquals(cookie.getValue(), "1"); - Assert.assertEquals(cookie.getMaxAge(), -1); - Assert.assertNull(cookie.getDomain()); - Assert.assertNull(cookie.getPath()); - - Assert.assertNotNull(request.cookie("test-1")); - Assert.assertNull(request.cookie("not-existent")); - } - - @Test - public void testRetrieveEmptyCookies() throws Exception { - javax.servlet.http.Cookie[] servletCookies = {}; - - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getCookies()).thenReturn(servletCookies); - - Request request = new ServletRequest(servletRequest); - Map cookies = request.cookies(); - - Assert.assertEquals(cookies.size(), 0); - } - - @Test - public void testRetrieveHeader() throws Exception { - HttpServletRequest servletRequest = mockServletRequest(); - when(servletRequest.getHeader("Authorization")).thenReturn("Basic ..."); - - Request request = new ServletRequest(servletRequest); - Assert.assertEquals(request.header("Authorization"), "Basic ..."); - } - - - private HttpServletRequest mockServletRequest() { - return mockServletRequest("GET"); - } - - private HttpServletRequest mockServletRequest(String methodName) { - HttpServletRequest servletRequest = mock(HttpServletRequest.class); - when(servletRequest.getMethod()).thenReturn(methodName); - - return servletRequest; - } - - private static void fixMultipartLineSeparators(String fileName) throws IOException { - File file = new File("src/test/resources/multipart/" + fileName + "-fixed.txt"); - if (!file.exists()) { - file.createNewFile(); - } - - BufferedReader reader = null; - BufferedWriter writer = null; - try { - reader = new BufferedReader(new InputStreamReader(ServletRequestTest.class.getResourceAsStream("/multipart/" + fileName + ".txt"))); - writer = new BufferedWriter(new FileWriter(file.getAbsoluteFile())); - String line; - while ((line = reader.readLine()) != null) { - writer.write(line + "\r\n"); - } - } finally { - if (reader != null) { - try { - reader.close(); - } catch (Exception e) { - } - } - if (writer != null) { - try { - writer.close(); - } catch (Exception e) { - } - } - } - } - - public static void main(String[] args) throws IOException { - fixMultipartLineSeparators("single-file"); - fixMultipartLineSeparators("multiple-files"); - } - -} diff --git a/blade-core/src/test/java/com/blade/servlet/ServletResponseTest.java b/blade-core/src/test/java/com/blade/servlet/ServletResponseTest.java deleted file mode 100644 index b8c9ea44e..000000000 --- a/blade-core/src/test/java/com/blade/servlet/ServletResponseTest.java +++ /dev/null @@ -1,193 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.servlet; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.PrintWriter; -import java.io.Writer; -import java.util.Map; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import org.junit.Assert; -import org.junit.Test; - -import com.blade.http.HttpStatus; -import com.blade.http.Response; -import com.blade.render.ModelAndView; -import com.blade.render.Render; - -public class ServletResponseTest { - - @Test - public void testRetrieveStatus() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - when(servletResponse.getStatus()).thenReturn(400); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - Assert.assertEquals(response.status(), 400); - } - - @Test - public void testSetStatus() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - response.status(400); - - verify(servletResponse).setStatus(400); - } - - @Test - public void testSetBadRequest() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - response.badRequest(); - - verify(servletResponse).setStatus(HttpStatus.BAD_REQUEST); - } - - @Test - public void testSetUnauthorized() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - response.unauthorized(); - - verify(servletResponse).setStatus(HttpStatus.UNAUTHORIZED); - } - - @Test - public void testRetrieveContentType() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - when(servletResponse.getContentType()).thenReturn("application/json"); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - Assert.assertEquals(response.contentType(), "application/json"); - } - - @Test - public void testSetContentType() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - response.contentType("application/json"); - - verify(servletResponse).setContentType("application/json"); - } - - @Test - public void testRetrieveHeader() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - when(servletResponse.getHeader("Authorization")).thenReturn("Basic"); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - Assert.assertEquals(response.header("Authorization"), "Basic"); - } - - @Test - public void testSetHeader() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - response.header("Authorization", "Basic"); - - verify(servletResponse).setHeader("Authorization", "Basic"); - } - - @Test - public void testSetCookie() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - response.cookie(new Cookie("test-1", "1")); - - verify(servletResponse).addCookie(any(javax.servlet.http.Cookie.class)); - } - - @Test - public void testRemoveCookie() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - response.removeCookie(new Cookie("test-1", "1")); - - verify(servletResponse).addCookie(any(javax.servlet.http.Cookie.class)); - } - - @Test - public void testSetAndGetAttributes() throws Exception { - Response response = new ServletResponse(mock(HttpServletResponse.class), mock(Render.class)); - response.attribute("test-1", "1"); - - Map atts = response.attributes(); - - Assert.assertNotNull(atts); - Assert.assertEquals(atts.size(), 1); - Assert.assertEquals(atts.get("test-1"), "1"); - } - - @Test - public void testFailWhenTryingToSetNullAttributeName() throws Exception { - Response response = new ServletResponse(mock(HttpServletResponse.class), mock(Render.class)); - response.attribute(null, "1"); - } - - @Test - public void testFailWhenTryingToSetNullAttributeValue() throws Exception { - Response response = new ServletResponse(mock(HttpServletResponse.class), mock(Render.class)); - response.attribute("test-1", null); - - } - - @Test - public void testWriteOutput() throws Exception { - PrintWriter writer = mock(PrintWriter.class); - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - when(servletResponse.getWriter()).thenReturn(writer); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - response.text("test"); - - verify(writer).print("test"); - } - - @Test - public void testRenderTemplate() throws Exception { - Render render = mock(Render.class); - - Response response = new ServletResponse(mock(HttpServletResponse.class), render); - response.render("template"); - - verify(render).render( any(ModelAndView.class), any(Writer.class)); - } - - @Test - public void testRedirect() throws Exception { - HttpServletResponse servletResponse = mock(HttpServletResponse.class); - - Response response = new ServletResponse(servletResponse, mock(Render.class)); - response.redirect("/"); - - verify(servletResponse).sendRedirect("/"); - } -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8c88707d2..f246e36ff 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.4.2-alpha + 1.4.2-beta 4.12 From 7076195e0b24c056545f53ef45086e2ba727923e Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 14:05:18 +0800 Subject: [PATCH 281/545] rename container register bean method name --- .../main/java/com/blade/IocApplication.java | 6 +++--- .../src/main/java/com/blade/ioc/Container.java | 13 +++++++------ .../java/com/blade/ioc/SampleContainer.java | 18 +++++++++--------- .../loader/ClassPathControllerLoader.java | 2 +- .../java/com/blade/route/RouteBuilder.java | 4 ++-- .../src/main/java/com/blade/route/Routers.java | 8 ++++---- 6 files changed, 26 insertions(+), 25 deletions(-) diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index 0af03d999..e2e76a52e 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -70,7 +70,7 @@ public void init(Blade blade){ // 初始化全局配置类 if(null == container.getBean(Bootstrap.class, Scope.SINGLE)){ - container.registBean(blade.bootstrap()); + container.registerBean(blade.bootstrap()); } // 初始化ioc容器 @@ -101,7 +101,7 @@ private void initIOC(String[] iocPackages) { @SuppressWarnings("unchecked") public T registerPlugin(Class plugin){ - Object object = container.registBean(plugin); + Object object = container.registerBean(plugin); T t = (T) object; plugins.add(t); return t; @@ -130,7 +130,7 @@ private void registerBean(String packageName) { for (Class clazz : classes) { // 注册带有Component和Service注解的类 if (container.isRegister(clazz.getAnnotations())) { - container.registBean(clazz); + container.registerBean(clazz); } } } diff --git a/blade-core/src/main/java/com/blade/ioc/Container.java b/blade-core/src/main/java/com/blade/ioc/Container.java index 3d0ad6a8e..002fb5839 100644 --- a/blade-core/src/main/java/com/blade/ioc/Container.java +++ b/blade-core/src/main/java/com/blade/ioc/Container.java @@ -128,14 +128,15 @@ public interface Container { * @param clazz 要注册的class类型 * @return 返回注册后的bean对象 */ - Object registBean(Class clazz); + Object registerBean(Class clazz); /** * 注册一个代名称的Bean - * @param clazz - * @return + * @param name bean名称 + * @param value bean对象 + * @return 返回注册的Bean */ - Object registBean(String name, Object value); + Object registerBean(String name, Object value); /** * 注册一个对象到bean容器中 @@ -143,14 +144,14 @@ public interface Container { * @param object 要注册的object * @return 返回注册后的Bean实例 */ - Object registBean(Object object); + Object registerBean(Object object); /** * 注册一个class集合进入ioc容器 * * @param classes 要注册的class集合 */ - void registBean(Set> classes); + void registerBean(Set> classes); /** * 初始化IOC diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java index fe87435db..d2041bffa 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -143,7 +143,7 @@ public boolean removeBean(Class clazz) { * @return 返回注册后的bean对象 */ @Override - public Object registBean(Class clazz) { + public Object registerBean(Class clazz) { String name = clazz.getCanonicalName(); Object object = null; @@ -151,13 +151,13 @@ public Object registBean(Class clazz) { //非抽象类、接口 if (isNormalClass(clazz)) { object = ReflectKit.newInstance(clazz); - return registBean(name, object); + return registerBean(name, object); } return object; } @Override - public Object registBean(String name, Object value) { + public Object registerBean(String name, Object value) { Class clazz = value.getClass(); //非抽象类、接口 if (isNormalClass(clazz)) { @@ -178,7 +178,7 @@ public Object registBean(String name, Object value) { Class[] interfaces = clazz.getInterfaces(); if(interfaces.length > 0){ for(Class interfaceClazz : interfaces){ - this.registBean(interfaceClazz.getCanonicalName(), value); + this.registerBean(interfaceClazz.getCanonicalName(), value); } } @@ -191,9 +191,9 @@ public Object registBean(String name, Object value) { } @Override - public Object registBean(Object object) { + public Object registerBean(Object object) { String className = object.getClass().getCanonicalName(); - return registBean(className, object); + return registerBean(className, object); } /** @@ -251,7 +251,7 @@ private Object recursiveAssembly(Class clazz){ String implClassName = clazz.getPackage().getName() + ".impl." + clazz.getSimpleName() + "Impl"; return ReflectKit.newInstance(implClassName); } else { - field = this.registBean(clazz); + field = this.registerBean(clazz); } } return field; @@ -308,10 +308,10 @@ public List getBeansByAnnotation(Class annotation) } @Override - public void registBean(Set> classes) { + public void registerBean(Set> classes) { if(!CollectionKit.isEmpty(classes)){ for(Class clazz : classes){ - this.registBean(clazz); + this.registerBean(clazz); } } } diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java index c0f6abeeb..e6ddd54f4 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java @@ -47,7 +47,7 @@ public Object load(String controllerName) throws RouteException { Object controller = container.getBean(controllerClass, Scope.SINGLE); if(null == controller){ controller = controllerClass.newInstance(); - container.registBean(controller); + container.registerBean(controller); } return controller; } catch (Exception e) { diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index 2234c8ed9..434a8450f 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -177,7 +177,7 @@ private void parseInterceptor(final Class interceptor){ return; } - container.registBean(interceptor); + container.registerBean(interceptor); for (Method method : methods) { @@ -232,7 +232,7 @@ private void parseRouter(final Class router){ return; } - container.registBean(router); + container.registerBean(router); final String nameSpace = router.getAnnotation(Path.class).value(); diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 3a2c37b81..3299558d9 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -157,7 +157,7 @@ public void route(String path, Class clazz, String methodName) { Object controller = container.getBean(clazz, Scope.SINGLE); if(null == controller){ controller = ReflectKit.newInstance(clazz); - container.registBean(controller); + container.registerBean(controller); } Method method = clazz.getMethod(methodName, Request.class, Response.class); @@ -175,7 +175,7 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt Object controller = container.getBean(clazz, Scope.SINGLE); if(null == controller){ controller = ReflectKit.newInstance(clazz); - container.registBean(controller); + container.registerBean(controller); } Method method = clazz.getMethod(methodName, Request.class, Response.class); addRoute(httpMethod, path, controller, method); @@ -191,7 +191,7 @@ public void route(String path, Class clazz, Method method, HttpMethod httpMet Object controller = container.getBean(clazz, Scope.SINGLE); if(null == controller){ controller = ReflectKit.newInstance(clazz); - container.registBean(controller); + container.registerBean(controller); } addRoute(httpMethod, path, controller, method); } catch (SecurityException e) { @@ -202,7 +202,7 @@ public void route(String path, Class clazz, Method method, HttpMethod httpMet public void route(String path, Object target, String methodName, HttpMethod httpMethod) { try { Class clazz = target.getClass(); - container.registBean(target); + container.registerBean(target); Method method = clazz.getMethod(methodName, Request.class, Response.class); addRoute(httpMethod, path, target, method); } catch (NoSuchMethodException e) { From 40f0d41a6367275af812ffd0f4c6aa5f701da001 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 14:13:49 +0800 Subject: [PATCH 282/545] update Blade.plugin() comment --- blade-core/src/main/java/com/blade/Blade.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index bada03197..72ab96069 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -744,7 +744,7 @@ public boolean enableXSS(){ /** * 返回插件对象 * - * @param pluginClazz 插件class + * @param plugin 插件class * @param 泛型 * @return 返回插件对象 */ From 95df936ea2d0ac576ecd42c9dc88dec867391c8e Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 14:16:58 +0800 Subject: [PATCH 283/545] modify package name --- blade-core/src/main/java/com/blade/ActionHandler.java | 4 ++-- blade-core/src/main/java/com/blade/Blade.java | 2 +- .../src/main/java/com/blade/context/BladeWebContext.java | 2 +- blade-core/src/main/java/com/blade/http/Request.java | 2 +- blade-core/src/main/java/com/blade/render/BeetlRender.java | 2 +- blade-core/src/main/java/com/blade/render/JetbrickRender.java | 2 +- blade-core/src/main/java/com/blade/render/VelocityRender.java | 2 +- blade-core/src/main/java/com/blade/servlet/package-info.java | 4 ---- .../java/com/blade/servlet/{ => wrapper}/ServletRequest.java | 2 +- .../java/com/blade/servlet/{ => wrapper}/ServletResponse.java | 2 +- .../main/java/com/blade/servlet/{ => wrapper}/Session.java | 2 +- .../src/main/java/com/blade/servlet/wrapper/package-info.java | 4 ++++ .../src/main/java/com/blade/verify/CSRFTokenManager.java | 2 +- .../src/main/java/com/blade/patchca/PatchcaService.java | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/servlet/package-info.java rename blade-core/src/main/java/com/blade/servlet/{ => wrapper}/ServletRequest.java (95%) rename blade-core/src/main/java/com/blade/servlet/{ => wrapper}/ServletResponse.java (95%) rename blade-core/src/main/java/com/blade/servlet/{ => wrapper}/Session.java (98%) create mode 100644 blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java index 187e11e98..5e2bd7f17 100644 --- a/blade-core/src/main/java/com/blade/ActionHandler.java +++ b/blade-core/src/main/java/com/blade/ActionHandler.java @@ -32,8 +32,8 @@ import com.blade.route.RouteHandler; import com.blade.route.Routers; import com.blade.route.RouteMatcher; -import com.blade.servlet.ServletRequest; -import com.blade.servlet.ServletResponse; +import com.blade.servlet.wrapper.ServletRequest; +import com.blade.servlet.wrapper.ServletResponse; import blade.exception.BladeException; import blade.kit.ReflectKit; diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 72ab96069..c80af40d8 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -53,7 +53,7 @@ public class Blade { /** * 当前最新版本 */ - public static final String VERSION = "1.4.1"; + public static final String VERSION = "1.4.2-beta"; /** * 框架是否已经初始化 diff --git a/blade-core/src/main/java/com/blade/context/BladeWebContext.java b/blade-core/src/main/java/com/blade/context/BladeWebContext.java index 3f5ca27c6..dd0f1ec26 100644 --- a/blade-core/src/main/java/com/blade/context/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/context/BladeWebContext.java @@ -19,7 +19,7 @@ import com.blade.http.Request; import com.blade.http.Response; -import com.blade.servlet.Session; +import com.blade.servlet.wrapper.Session; /** * 全局的WeContext diff --git a/blade-core/src/main/java/com/blade/http/Request.java b/blade-core/src/main/java/com/blade/http/Request.java index 8e82ec1cb..82f321c89 100644 --- a/blade-core/src/main/java/com/blade/http/Request.java +++ b/blade-core/src/main/java/com/blade/http/Request.java @@ -24,8 +24,8 @@ import javax.servlet.http.HttpServletRequest; import com.blade.route.Route; -import com.blade.servlet.Session; import com.blade.servlet.multipart.FileItem; +import com.blade.servlet.wrapper.Session; /** * diff --git a/blade-core/src/main/java/com/blade/render/BeetlRender.java b/blade-core/src/main/java/com/blade/render/BeetlRender.java index a914dcb72..ffae2d2e6 100644 --- a/blade-core/src/main/java/com/blade/render/BeetlRender.java +++ b/blade-core/src/main/java/com/blade/render/BeetlRender.java @@ -29,7 +29,7 @@ import com.blade.Blade; import com.blade.context.BladeWebContext; import com.blade.http.Request; -import com.blade.servlet.Session; +import com.blade.servlet.wrapper.Session; import blade.kit.log.Logger; diff --git a/blade-core/src/main/java/com/blade/render/JetbrickRender.java b/blade-core/src/main/java/com/blade/render/JetbrickRender.java index 122943ff2..6ded75c65 100644 --- a/blade-core/src/main/java/com/blade/render/JetbrickRender.java +++ b/blade-core/src/main/java/com/blade/render/JetbrickRender.java @@ -26,7 +26,7 @@ import com.blade.http.Request; import com.blade.render.ModelAndView; import com.blade.render.Render; -import com.blade.servlet.Session; +import com.blade.servlet.wrapper.Session; import blade.kit.log.Logger; import jetbrick.template.JetEngine; diff --git a/blade-core/src/main/java/com/blade/render/VelocityRender.java b/blade-core/src/main/java/com/blade/render/VelocityRender.java index c7ce21fc5..ff8806a68 100644 --- a/blade-core/src/main/java/com/blade/render/VelocityRender.java +++ b/blade-core/src/main/java/com/blade/render/VelocityRender.java @@ -31,7 +31,7 @@ import com.blade.Blade; import com.blade.context.BladeWebContext; import com.blade.http.Request; -import com.blade.servlet.Session; +import com.blade.servlet.wrapper.Session; import blade.kit.log.Logger; diff --git a/blade-core/src/main/java/com/blade/servlet/package-info.java b/blade-core/src/main/java/com/blade/servlet/package-info.java deleted file mode 100644 index 7c6887306..000000000 --- a/blade-core/src/main/java/com/blade/servlet/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Servlet封装 - */ -package com.blade.servlet; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java b/blade-core/src/main/java/com/blade/servlet/wrapper/ServletRequest.java similarity index 95% rename from blade-core/src/main/java/com/blade/servlet/ServletRequest.java rename to blade-core/src/main/java/com/blade/servlet/wrapper/ServletRequest.java index ba5f194d0..c07c3928b 100644 --- a/blade-core/src/main/java/com/blade/servlet/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/servlet/wrapper/ServletRequest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.servlet; +package com.blade.servlet.wrapper; import java.io.BufferedReader; import java.io.IOException; diff --git a/blade-core/src/main/java/com/blade/servlet/ServletResponse.java b/blade-core/src/main/java/com/blade/servlet/wrapper/ServletResponse.java similarity index 95% rename from blade-core/src/main/java/com/blade/servlet/ServletResponse.java rename to blade-core/src/main/java/com/blade/servlet/wrapper/ServletResponse.java index 016420bc7..d87d8c6db 100644 --- a/blade-core/src/main/java/com/blade/servlet/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/servlet/wrapper/ServletResponse.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.servlet; +package com.blade.servlet.wrapper; import java.io.IOException; import java.io.PrintWriter; diff --git a/blade-core/src/main/java/com/blade/servlet/Session.java b/blade-core/src/main/java/com/blade/servlet/wrapper/Session.java similarity index 98% rename from blade-core/src/main/java/com/blade/servlet/Session.java rename to blade-core/src/main/java/com/blade/servlet/wrapper/Session.java index ebc717ddd..2c55a0653 100644 --- a/blade-core/src/main/java/com/blade/servlet/Session.java +++ b/blade-core/src/main/java/com/blade/servlet/wrapper/Session.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.servlet; +package com.blade.servlet.wrapper; import java.util.Enumeration; import java.util.Set; diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java b/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java new file mode 100644 index 000000000..cb660a14c --- /dev/null +++ b/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java @@ -0,0 +1,4 @@ +/** + * Servlet封装 + */ +package com.blade.servlet.wrapper; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java index d9cc619f2..15134aee0 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java @@ -17,7 +17,7 @@ import com.blade.http.Request; import com.blade.http.Response; -import com.blade.servlet.Session; +import com.blade.servlet.wrapper.Session; import blade.kit.HashidKit; import blade.kit.StringKit; diff --git a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java index 39393fc55..688990304 100644 --- a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java +++ b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java @@ -18,7 +18,7 @@ import blade.kit.log.Logger; import com.blade.http.Response; -import com.blade.servlet.Session; +import com.blade.servlet.wrapper.Session; /** * PatchcaService From d854d086718baca954b27f4621f8cdd9afeaa9a9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 15:18:00 +0800 Subject: [PATCH 284/545] optimal route finder --- .../main/java/com/blade/ActionHandler.java | 2 +- blade-core/src/main/java/com/blade/Blade.java | 46 ++++++---- .../src/main/java/com/blade/Bootstrap.java | 4 +- .../src/main/java/com/blade/CoreFilter.java | 2 +- .../java/com/blade/route/RouteBuilder.java | 8 +- .../java/com/blade/route/RouteMatcher.java | 51 ++++++++--- .../main/java/com/blade/route/Routers.java | 84 +++++++++---------- pom.xml | 2 +- 8 files changed, 117 insertions(+), 82 deletions(-) diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java index 5e2bd7f17..cba3e7bce 100644 --- a/blade-core/src/main/java/com/blade/ActionHandler.java +++ b/blade-core/src/main/java/com/blade/ActionHandler.java @@ -88,7 +88,7 @@ public class ActionHandler { public ActionHandler(ServletContext context, Blade blade){ this.blade = blade; - this.router = blade.router(); + this.router = blade.routers(); this.context = context; this.routeMatcher = new RouteMatcher(router); } diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index c80af40d8..48bf9ba65 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -53,7 +53,7 @@ public class Blade { /** * 当前最新版本 */ - public static final String VERSION = "1.4.2-beta"; + public static final String VERSION = "1.4.2"; /** * 框架是否已经初始化 @@ -65,7 +65,7 @@ public class Blade { */ private Bootstrap bootstrap = new Bootstrap() { @Override - public void init() { + public void init(Blade blade) { } }; @@ -92,7 +92,7 @@ public void init() { /** * 路由管理对象 */ - private Routers router = new Routers(container); + private Routers routers = new Routers(container); /** * 默认启动端口 @@ -143,8 +143,8 @@ public Server createServer(int port){ /** * @return 返回路由管理对象 */ - public Routers router() { - return router; + public Routers routers() { + return routers; } /** @@ -299,7 +299,7 @@ public Blade ioc(String...packages){ * @return 返回Blade单例实例 */ public Blade route(String path, Object target, String method){ - router.route(path, target, method); + routers.route(path, target, method); return this; } @@ -313,7 +313,7 @@ public Blade route(String path, Object target, String method){ * @return 返回Blade单例实例 */ public Blade route(String path, Object target, String method, HttpMethod httpMethod){ - router.route(path, target, method, httpMethod); + routers.route(path, target, method, httpMethod); return this; } @@ -327,7 +327,7 @@ public Blade route(String path, Object target, String method, HttpMethod httpMet * @return Blade 返回Blade单例实例 */ public Blade route(String path, Class clazz, String method){ - router.route(path, clazz, method); + routers.route(path, clazz, method); return this; } @@ -341,7 +341,17 @@ public Blade route(String path, Class clazz, String method){ * @return Blade 返回Blade单例实例 */ public Blade route(String path, Class clazz, String method, HttpMethod httpMethod){ - router.route(path, clazz, method, httpMethod); + routers.route(path, clazz, method, httpMethod); + return this; + } + + /** + * 添加路由列表 + * @param routes 路由列表 + * @return 返回Blade单例实例 + */ + public Blade routes(List routes){ + routers.addRoutes(routes); return this; } @@ -353,7 +363,7 @@ public Blade route(String path, Class clazz, String method, HttpMethod httpMe * @return 返回Blade单例实例 */ public Blade get(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.GET); + routers.route(path, handler, HttpMethod.GET); return this; } @@ -365,7 +375,7 @@ public Blade get(String path, RouteHandler handler){ * @return 返回Blade单例实例 */ public Blade post(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.POST); + routers.route(path, handler, HttpMethod.POST); return this; } @@ -377,7 +387,7 @@ public Blade post(String path, RouteHandler handler){ * @return 返回Blade单例实例 */ public Blade delete(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.DELETE); + routers.route(path, handler, HttpMethod.DELETE); return this; } @@ -389,7 +399,7 @@ public Blade delete(String path, RouteHandler handler){ * @return 返回Blade单例实例 */ public Blade put(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.PUT); + routers.route(path, handler, HttpMethod.PUT); return this; } @@ -401,7 +411,7 @@ public Blade put(String path, RouteHandler handler){ * @return 返回Blade单例实例 */ public Blade all(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.ALL); + routers.route(path, handler, HttpMethod.ALL); return this; } @@ -413,7 +423,7 @@ public Blade all(String path, RouteHandler handler){ * @return 返回Blade单例实例 */ public Blade any(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.ALL); + routers.route(path, handler, HttpMethod.ALL); return this; } @@ -425,7 +435,7 @@ public Blade any(String path, RouteHandler handler){ * @return 返回Blade单例实例 */ public Blade before(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.BEFORE); + routers.route(path, handler, HttpMethod.BEFORE); return this; } @@ -437,7 +447,7 @@ public Blade before(String path, RouteHandler handler){ * @return 返回Blade单例实例 */ public Blade after(String path, RouteHandler handler){ - router.route(path, handler, HttpMethod.AFTER); + routers.route(path, handler, HttpMethod.AFTER); return this; } @@ -770,7 +780,7 @@ public Blade routeConf(String basePackage, String conf) { ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); routesLoader.setBasePackage(basePackage); List routes = routesLoader.load(); - router.addRoutes(routes); + routers.addRoutes(routes); } catch (RouteException e) { e.printStackTrace(); } catch (ParseException e) { diff --git a/blade-core/src/main/java/com/blade/Bootstrap.java b/blade-core/src/main/java/com/blade/Bootstrap.java index 1fd3102e9..2dd4589a7 100644 --- a/blade-core/src/main/java/com/blade/Bootstrap.java +++ b/blade-core/src/main/java/com/blade/Bootstrap.java @@ -25,11 +25,13 @@ public abstract class Bootstrap { /** * 初始化方法,在应用启动的时候做一些初始化操作 + * @param blade Blade全局对象 */ - public abstract void init(); + public abstract void init(Blade blade); /** * 初始化配置后执行 + * @param blade Blade全局对象 */ public void contextInitialized(Blade blade){ // diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 810055ccf..2d3294425 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -72,7 +72,7 @@ public void init(FilterConfig filterConfig) throws ServletException { String bootStrapClassName = filterConfig.getInitParameter(BOOSTRAP_CLASS); if(StringKit.isNotBlank(bootStrapClassName)){ bootstrap = getBootstrap(filterConfig.getInitParameter(BOOSTRAP_CLASS)); - bootstrap.init(); + bootstrap.init(blade); blade.app(bootstrap); } diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index 434a8450f..6fbc4edfd 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -64,11 +64,11 @@ public class RouteBuilder { private Blade blade; - private Routers router; + private Routers routers; public RouteBuilder(Blade blade) { this.blade = blade; - this.router = blade.router(); + this.routers = blade.routers(); this.container = blade.container(); } @@ -285,7 +285,7 @@ private String getRoutePath(String value, String nameSpace, String suffix){ * @param method 路由http方法 */ private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ - this.router.route(path, clazz, execMethod, method); + this.routers.route(path, clazz, execMethod, method); } /** @@ -297,7 +297,7 @@ private void buildRoute(Class clazz, Method execMethod, String path, HttpMeth * @param method 路由http方法 */ private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ - this.router.route(path, clazz, execMethod, method); + this.routers.route(path, clazz, execMethod, method); } } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java index 8b6d81e14..bbae44e20 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcher.java @@ -18,9 +18,12 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; +import java.util.Set; import com.blade.http.HttpMethod; import com.blade.http.Path; @@ -38,14 +41,22 @@ public class RouteMatcher { // private static final Logger LOGGER = Logger.getLogger(SampleRouteMatcher.class); - // 存储所有路由 - private List routes; - - private List interceptors; - + // 存储URL和路由关系 + private Map routes = null; + private Map interceptors = null; + + // 存储Map Key + private Set routeKeys = null; + private List interceptorRoutes = new ArrayList(); + public RouteMatcher(Routers router) { - this.routes = router.getRoutes(); - this.interceptors = router.getInterceptors(); + this.routes = router.getRoutes(); + this.interceptors = router.getInterceptors(); + this.routeKeys = routes.keySet(); + Collection inters = interceptors.values(); + if (null != inters && inters.size() > 0) { + this.interceptorRoutes.addAll(inters); + } } /** @@ -56,15 +67,28 @@ public RouteMatcher(Routers router) { */ public Route getRoute(String httpMethod, String path) { String cleanPath = parsePath(path); + + String routeKey = path + "#" + httpMethod.toLowerCase(); + Route route = routes.get(routeKey); + if(null != route){ + return route; + } + route = routes.get(path + "#ALL"); + if(null != route){ + return route; + } + List matchRoutes = new ArrayList(); - for (Route route : this.routes) { - if (matchesPath(route.getPath(), cleanPath)) { - if (route.getHttpMethod() == HttpMethod.ALL - || HttpMethod.valueOf(httpMethod) == route.getHttpMethod()) { + for(String key : routeKeys){ + String[] keyArr = key.split("#"); + HttpMethod routeMethod = HttpMethod.valueOf(keyArr[1]); + if (matchesPath(keyArr[0], cleanPath)) { + if (routeMethod == HttpMethod.ALL || HttpMethod.valueOf(httpMethod) == routeMethod) { matchRoutes.add(route); } } } + // 优先匹配原则 giveMatch(path, matchRoutes); @@ -77,9 +101,10 @@ public Route getRoute(String httpMethod, String path) { * @return 返回前置拦截器列表 */ public List getBefore(String path) { + List befores = new ArrayList(); String cleanPath = parsePath(path); - for (Route route : this.interceptors) { + for (Route route : interceptorRoutes) { if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.BEFORE){ befores.add(route); } @@ -96,7 +121,7 @@ public List getBefore(String path) { public List getAfter(String path) { List afters = new ArrayList(); String cleanPath = parsePath(path); - for (Route route : interceptors) { + for (Route route : interceptorRoutes) { if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.AFTER){ afters.add(route); } diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 3299558d9..3f888fd4b 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -15,16 +15,15 @@ */ package com.blade.route; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.HashMap; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; +import java.util.Map; import blade.kit.ReflectKit; import blade.kit.log.Logger; import com.blade.http.HttpMethod; -import com.blade.http.HttpStatus; import com.blade.http.Request; import com.blade.http.Response; import com.blade.ioc.Container; @@ -45,77 +44,76 @@ public class Routers { private Container container = null; - private List routes = new CopyOnWriteArrayList(); + private Map routes = null; - private List interceptors = new CopyOnWriteArrayList(); + private Map interceptors = null; private static final String METHOD_NAME = "handle"; public Routers(Container container) { this.container = container; + this.routes = new HashMap(); + this.interceptors = new HashMap(); } - public void handle(Request request, Response response, Route route) throws Exception { - request.setRoute(route); - response.status(HttpStatus.NOT_FOUND); - - Object controller = route.getTarget(); - Method method = route.getAction(); - try { - method.invoke(controller, request, response); - } catch (InvocationTargetException e) { - throw (Exception) e.getCause(); - } - } - - public List getRoutes() { + public Map getRoutes() { return routes; } - - public void setRoutes(List routes) { - this.routes = routes; - } - public void addRoute(Route route) { - this.routes.add(route); + public Map getInterceptors() { + return interceptors; } - public void addRoutes(List routes) { - for(Route route : routes){ - if(this.routes.contains(route)){ - LOGGER.warn("\tRoute "+ route +" has exist"); - continue; + public void addRoute(Route route) { + String path = route.getPath(); + HttpMethod httpMethod = route.getHttpMethod(); + String key = path + "#" + httpMethod.toString(); + + // 存在的 + if (null != this.routes.get(key)) { + LOGGER.warn("\tRoute "+ path + " -> " + httpMethod.toString() +" has exist"); + } + + if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ + if (null != this.interceptors.get(key)) { + LOGGER.warn("\tInterceptor "+ path + " -> " + httpMethod.toString() +" has exist"); } - this.routes.add(route); + this.interceptors.put(key, route); + LOGGER.debug("Add Interceptor:" + route); + } else { + this.routes.put(key, route); LOGGER.debug("Add Route:" + route); } } - public List getInterceptors() { - return interceptors; + public void addRoutes(List routes) { + for(Route route : routes){ + this.addRoute(route); + } } - public void addInterceptors(List interceptors) { - this.interceptors.addAll(interceptors); - } - public void addRoute(HttpMethod httpMethod, String path, Object controller, String methodName) throws NoSuchMethodException { Method method = controller.getClass().getMethod(methodName, Request.class, Response.class); addRoute(httpMethod, path, controller, method); } public void addRoute(HttpMethod httpMethod, String path, Object controller, Method method) { -// method.setAccessible(true); - Route route = new Route(httpMethod, path, controller, method); - if(this.routes.contains(route)){ - LOGGER.warn("\tRoute "+ route +" has exist"); + + String key = path + "#" + httpMethod.toString(); + // 存在的 + if (null != this.routes.get(key)) { + LOGGER.warn("\tRoute "+ path + " -> " + httpMethod.toString() +" has exist"); } + Route route = new Route(httpMethod, path, controller, method); if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ - interceptors.add(route); + if (null != this.interceptors.get(key)) { + LOGGER.warn("\tInterceptor "+ path + " -> " + httpMethod.toString() +" has exist"); + } + this.interceptors.put(key, route); LOGGER.debug("Add Interceptor:" + route); } else { - routes.add(route); + this.routes.put(key, route); LOGGER.debug("Add Route:" + route); } diff --git a/pom.xml b/pom.xml index f246e36ff..b6c496a72 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.4.2-beta + 1.4.2 4.12 From fb6372fe1ed6d30dd54bd61bd497a68b68069083 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 15:26:37 +0800 Subject: [PATCH 285/545] grammar --- UPDATE_LOG.md | 3 +++ .../main/java/com/blade/context/BladeWebContext.java | 8 ++++---- blade-core/src/main/java/com/blade/loader/Config.java | 10 +++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index b1b6b194b..f2d69dba8 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,5 +1,8 @@ # Blade 更新日志 +### v1.4.2 + 1. 优化路由寻址算法 + ### v1.4.1 1. 去除过度设计 2. 添加多种路由配置 diff --git a/blade-core/src/main/java/com/blade/context/BladeWebContext.java b/blade-core/src/main/java/com/blade/context/BladeWebContext.java index dd0f1ec26..9bd4be31b 100644 --- a/blade-core/src/main/java/com/blade/context/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/context/BladeWebContext.java @@ -71,11 +71,11 @@ public static void remove(){ } public static Request request() { - return BladeWebContext.me().request; + return me().request; } public static Response response() { - return BladeWebContext.me().response; + return me().response; } public static Session session() { @@ -83,13 +83,13 @@ public static Session session() { } public static ServletContext servletContext() { - return BladeWebContext.me().context; + return me().context; } public ServletContext getContext() { return context; } - + public Request getRequest() { return request; } diff --git a/blade-core/src/main/java/com/blade/loader/Config.java b/blade-core/src/main/java/com/blade/loader/Config.java index b1faee8a1..a04e40125 100644 --- a/blade-core/src/main/java/com/blade/loader/Config.java +++ b/blade-core/src/main/java/com/blade/loader/Config.java @@ -88,7 +88,7 @@ public String get(String key){ return configMap.get(key); } - public Integer getToInt(String key){ + public Integer getAsInt(String key){ String val = get(key); if(null != val && PatternKit.isNumber(val)){ return Integer.valueOf(val); @@ -96,7 +96,7 @@ public Integer getToInt(String key){ return null; } - public Long getToLong(String key){ + public Long getAsLong(String key){ String val = get(key); if(null != val && PatternKit.isNumber(val)){ return Long.valueOf(val); @@ -104,7 +104,7 @@ public Long getToLong(String key){ return null; } - public Boolean getToBoolean(String key){ + public Boolean getAsBoolean(String key){ String val = get(key); if(null != val){ return Boolean.valueOf(val); @@ -112,7 +112,7 @@ public Boolean getToBoolean(String key){ return null; } - public Double getToDouble(String key){ + public Double getAsDouble(String key){ String val = get(key); if(null != val){ return Double.valueOf(val); @@ -120,7 +120,7 @@ public Double getToDouble(String key){ return null; } - public Float getToFloat(String key){ + public Float getAsFloat(String key){ String val = get(key); if(null != val){ return Float.valueOf(val); From 64474b8649779fc86cdcd05c2a002b47a609d7a7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 15:42:01 +0800 Subject: [PATCH 286/545] remove blade-sample --- blade-sample/pom.xml | 67 ------------------- blade-sample/src/main/java/com/xxx/App.java | 15 ----- .../main/java/com/xxx/route/IndexRoute.java | 12 ---- blade-sample/src/main/resources/blade.conf | 6 -- blade-sample/src/main/resources/route.conf | 1 - .../src/main/webapp/WEB-INF/views/index.jsp | 13 ---- blade-sample/src/main/webapp/WEB-INF/web.xml | 21 ------ 7 files changed, 135 deletions(-) delete mode 100644 blade-sample/pom.xml delete mode 100644 blade-sample/src/main/java/com/xxx/App.java delete mode 100644 blade-sample/src/main/java/com/xxx/route/IndexRoute.java delete mode 100644 blade-sample/src/main/resources/blade.conf delete mode 100644 blade-sample/src/main/resources/route.conf delete mode 100644 blade-sample/src/main/webapp/WEB-INF/views/index.jsp delete mode 100644 blade-sample/src/main/webapp/WEB-INF/web.xml diff --git a/blade-sample/pom.xml b/blade-sample/pom.xml deleted file mode 100644 index 594766aaf..000000000 --- a/blade-sample/pom.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - blade-sample - 1.0.0 - war - blade-sample - http://maven.apache.org - - - 1.6 - 1.6 - UTF-8 - - - - - com.bladejava - blade-core - ${blade.version} - - - javax.servlet - javax.servlet-api - 3.0.1 - provided - - - - blade-sample - - - org.apache.maven.plugins - maven-compiler-plugin - 3.2 - - 1.6 - 1.6 - UTF8 - - - - org.mortbay.jetty - maven-jetty-plugin - 6.1.7 - - src/main/webapp - 1 - / - - - 9000 - 30000 - - - - - - - diff --git a/blade-sample/src/main/java/com/xxx/App.java b/blade-sample/src/main/java/com/xxx/App.java deleted file mode 100644 index cd3dcf155..000000000 --- a/blade-sample/src/main/java/com/xxx/App.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.xxx; - -import com.blade.Blade; -import com.blade.Bootstrap; - -public class App extends Bootstrap { - - @Override - public void init() { - Blade blade = Blade.me(); - blade.routeConf("com.xxx.route", "route.conf"); - blade.config("blade.conf"); - } - -} diff --git a/blade-sample/src/main/java/com/xxx/route/IndexRoute.java b/blade-sample/src/main/java/com/xxx/route/IndexRoute.java deleted file mode 100644 index f06d30ee0..000000000 --- a/blade-sample/src/main/java/com/xxx/route/IndexRoute.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.xxx.route; - -import com.blade.http.Request; -import com.blade.http.Response; - -public class IndexRoute { - - public void index(Request request, Response response){ - response.render("index"); - } - -} diff --git a/blade-sample/src/main/resources/blade.conf b/blade-sample/src/main/resources/blade.conf deleted file mode 100644 index f5872f4af..000000000 --- a/blade-sample/src/main/resources/blade.conf +++ /dev/null @@ -1,6 +0,0 @@ -#\u89c6\u56fe\u6587\u4ef6\u76ee\u5f55 -blade.prefix=/WEB-INF/views/ -#\u89c6\u56fe\u6587\u4ef6\u540e\u7f00 -blade.suffix=.jsp -#\u9759\u6001\u6587\u4ef6\u76ee\u5f55 -blade.filter_folder=/static/ \ No newline at end of file diff --git a/blade-sample/src/main/resources/route.conf b/blade-sample/src/main/resources/route.conf deleted file mode 100644 index b470081c6..000000000 --- a/blade-sample/src/main/resources/route.conf +++ /dev/null @@ -1 +0,0 @@ -GET / IndexRoute.index \ No newline at end of file diff --git a/blade-sample/src/main/webapp/WEB-INF/views/index.jsp b/blade-sample/src/main/webapp/WEB-INF/views/index.jsp deleted file mode 100644 index d2c29326b..000000000 --- a/blade-sample/src/main/webapp/WEB-INF/views/index.jsp +++ /dev/null @@ -1,13 +0,0 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%> - - - - -Welcome To Blade - - -
-

Hi gays!

-
- - \ No newline at end of file diff --git a/blade-sample/src/main/webapp/WEB-INF/web.xml b/blade-sample/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index dc47db24e..000000000 --- a/blade-sample/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - Archetype Created Web Application - - - CoreFilter - com.blade.CoreFilter - - bootstrapClass - com.xxx.App - - - - CoreFilter - /* - - - From 9afd52ac5efdf3a3b1fb3b3d61ae078372aa34d3 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 15:43:45 +0800 Subject: [PATCH 287/545] remove blade-sample --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index b6c496a72..75731d9d8 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,6 @@ blade-sql2o blade-redis blade-startup - blade-sample blade-aop blade-oauth2 blade-patchca From 184c890f86b7c8fdd685f27c4219585717937e41 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 15:45:38 +0800 Subject: [PATCH 288/545] Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index abf532887..2c5d974bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,5 +2,6 @@ language: java jdk: - oraclejdk8 - oraclejdk7 + - oraclejdk6 after_success: - mvn cobertura:cobertura coveralls:report From 4bcc0b1aa5b7abca6880200300abf74d0c869138 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 15:46:34 +0800 Subject: [PATCH 289/545] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2c5d974bf..407ba9d05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,6 @@ language: java jdk: - oraclejdk8 - oraclejdk7 - - oraclejdk6 + - openjdk6 after_success: - mvn cobertura:cobertura coveralls:report From 12ede4af5a15ecd8dcf78396cc643fbe6bda0a33 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 15:53:29 +0800 Subject: [PATCH 290/545] release blade-patchca --- LAST_VERSION.md | 7 ++++--- blade-patchca/pom.xml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 8ee8ad485..c16ae323b 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -1,6 +1,7 @@ # blade last version 如果在maven仓库中下载不到最新版本的依赖,请添加maven snapshots仓库 + ```xml @@ -71,11 +72,11 @@ ``` -## [blade-sample](http://search.maven.org/#search%7Cga%7C1%7Cblade-sample) +## [blade-patchca](http://search.maven.org/#search%7Cga%7C1%7Cblade-patchca) ```xml     com.bladejava -    blade-sample +    blade-patchca     1.0.0 -``` \ No newline at end of file +``` diff --git a/blade-patchca/pom.xml b/blade-patchca/pom.xml index dd4243c09..134d3adbe 100644 --- a/blade-patchca/pom.xml +++ b/blade-patchca/pom.xml @@ -11,7 +11,7 @@ blade-patchca 1.0.0 blade-patchca - http://maven.apache.org + https://github.com/biezhi/blade/tree/master/blade-patchca From c7a7c293f7570fd41cad8046819453579e588cf7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 15:54:17 +0800 Subject: [PATCH 291/545] Update README --- README.md | 4 ++-- README_CN.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6542e4498..ccec59f8b 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) -[中文](https://github.com/biezhi/blade/blob/master/README_CN.md) +[中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) ## What Is Blade? -`blade` is a lightweight MVC framework. It is based on the principles of simplicity and elegance. +Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! ## Features diff --git a/README_CN.md b/README_CN.md index 4d652f00b..c86b3a68f 100644 --- a/README_CN.md +++ b/README_CN.md @@ -10,7 +10,7 @@ ## Blade是什么? -`blade` 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计。 +Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计。 如果你喜欢,欢迎 [Star and Fork](https://github.com/biezhi/blade), 谢谢! ## 特性 From bfb8e0f80d449aaed81da9037d4b67df88295af0 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 16:31:07 +0800 Subject: [PATCH 292/545] aop mode create Class --- blade-core/src/main/java/com/blade/Aop.java | 38 +++++++++++++++++++ blade-core/src/main/java/com/blade/Blade.java | 15 ++++---- .../src/main/java/com/blade/CoreFilter.java | 7 ++-- .../java/com/blade/ioc/SampleContainer.java | 12 ++---- .../loader/ClassPathControllerLoader.java | 3 +- .../main/java/com/blade/route/Routers.java | 8 ++-- blade-oauth2/pom.xml | 4 +- .../java/com/blade/oauth2/OAuthRequest.java | 4 +- .../base/request/OAuthTokenBaseRequest.java | 7 ++-- 9 files changed, 66 insertions(+), 32 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/Aop.java diff --git a/blade-core/src/main/java/com/blade/Aop.java b/blade-core/src/main/java/com/blade/Aop.java new file mode 100644 index 000000000..bbebff45e --- /dev/null +++ b/blade-core/src/main/java/com/blade/Aop.java @@ -0,0 +1,38 @@ +package com.blade; + +import blade.kit.ReflectKit; + +@SuppressWarnings("unchecked") +public final class Aop { + + private static boolean isAop = false; + + public static T create(Class clazz){ + if(isAop){ + //...aop + } else { + Object object = ReflectKit.newInstance(clazz); + if(null != object){ + return (T) object; + } + } + return null; + } + + public static T create(String className){ + try { + Class clazz = Class.forName(className); + if(isAop){ + //...aop + } else { + Object object = ReflectKit.newInstance(clazz); + if(null != object){ + return (T) object; + } + } + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return null; + } +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 48bf9ba65..249143529 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -21,6 +21,11 @@ import java.util.List; import java.util.Map; +import blade.kit.IOKit; +import blade.kit.PropertyKit; +import blade.kit.StringKit; +import blade.kit.json.JSONKit; + import com.blade.http.HttpMethod; import com.blade.ioc.Container; import com.blade.ioc.SampleContainer; @@ -31,17 +36,11 @@ import com.blade.render.JspRender; import com.blade.render.Render; import com.blade.route.Route; +import com.blade.route.RouteException; import com.blade.route.RouteHandler; import com.blade.route.Routers; -import com.blade.route.RouteException; import com.blade.server.Server; -import blade.kit.IOKit; -import blade.kit.PropertyKit; -import blade.kit.ReflectKit; -import blade.kit.StringKit; -import blade.kit.json.JSONKit; - /** * Blade Core Class * @@ -541,7 +540,7 @@ public Blade app(Bootstrap bootstrap){ * @return 返回Blade单例实例 */ public Blade app(Class bootstrap){ - this.bootstrap = (Bootstrap) ReflectKit.newInstance(bootstrap); + this.bootstrap = Aop.create(bootstrap); return this; } diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java index 2d3294425..4d57e9382 100644 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ b/blade-core/src/main/java/com/blade/CoreFilter.java @@ -103,13 +103,14 @@ public void init(FilterConfig filterConfig) throws ServletException { * @return 一个全局初始化对象 * @throws ServletException */ - private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { + @SuppressWarnings("unchecked") + private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { Bootstrap bootstrapClass = null; try { if(null != botstrapClassName){ - Class applicationClass = Class.forName(botstrapClassName); + Class applicationClass = (Class) Class.forName(botstrapClassName); if(null != applicationClass){ - bootstrapClass = (Bootstrap) applicationClass.newInstance(); + bootstrapClass = Aop.create(applicationClass); } } else { throw new ServletException("bootstrapClass is null !"); diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java index d2041bffa..5c57b51bb 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -28,10 +28,10 @@ import blade.exception.BladeException; import blade.kit.CloneKit; import blade.kit.CollectionKit; -import blade.kit.ReflectKit; import blade.kit.StringKit; import blade.kit.log.Logger; +import com.blade.Aop; import com.blade.annotation.Component; import com.blade.annotation.Inject; import com.blade.annotation.Path; @@ -150,7 +150,7 @@ public Object registerBean(Class clazz) { //非抽象类、接口 if (isNormalClass(clazz)) { - object = ReflectKit.newInstance(clazz); + object = Aop.create(clazz); return registerBean(name, object); } return object; @@ -246,13 +246,9 @@ public void initWired() throws RuntimeException { private Object recursiveAssembly(Class clazz){ Object field = null; if(null != clazz){ - // 是接口或者抽象类 - if(clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())){ - String implClassName = clazz.getPackage().getName() + ".impl." + clazz.getSimpleName() + "Impl"; - return ReflectKit.newInstance(implClassName); - } else { + if(!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())){ field = this.registerBean(clazz); - } + } } return field; } diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java index e6ddd54f4..99c307e2c 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java @@ -1,5 +1,6 @@ package com.blade.loader; +import com.blade.Aop; import com.blade.Blade; import com.blade.ioc.Container; import com.blade.ioc.Scope; @@ -46,7 +47,7 @@ public Object load(String controllerName) throws RouteException { Object controller = container.getBean(controllerClass, Scope.SINGLE); if(null == controller){ - controller = controllerClass.newInstance(); + controller = Aop.create(controllerClass); container.registerBean(controller); } return controller; diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 3f888fd4b..194752381 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -20,9 +20,9 @@ import java.util.List; import java.util.Map; -import blade.kit.ReflectKit; import blade.kit.log.Logger; +import com.blade.Aop; import com.blade.http.HttpMethod; import com.blade.http.Request; import com.blade.http.Response; @@ -154,7 +154,7 @@ public void route(String path, Class clazz, String methodName) { } Object controller = container.getBean(clazz, Scope.SINGLE); if(null == controller){ - controller = ReflectKit.newInstance(clazz); + controller = Aop.create(clazz); container.registerBean(controller); } @@ -172,7 +172,7 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt try { Object controller = container.getBean(clazz, Scope.SINGLE); if(null == controller){ - controller = ReflectKit.newInstance(clazz); + controller = Aop.create(clazz); container.registerBean(controller); } Method method = clazz.getMethod(methodName, Request.class, Response.class); @@ -188,7 +188,7 @@ public void route(String path, Class clazz, Method method, HttpMethod httpMet try { Object controller = container.getBean(clazz, Scope.SINGLE); if(null == controller){ - controller = ReflectKit.newInstance(clazz); + controller = Aop.create(clazz); container.registerBean(controller); } addRoute(httpMethod, path, controller, method); diff --git a/blade-oauth2/pom.xml b/blade-oauth2/pom.xml index ba01fe9da..0775fbaf7 100644 --- a/blade-oauth2/pom.xml +++ b/blade-oauth2/pom.xml @@ -9,9 +9,9 @@ 1.0 blade-oauth2 - 1.0 + 1.0.0 blade-oauth2 - http://maven.apache.org + https://github.com/biezhi/blade/tree/master/blade-oauth2 diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java index 48e58927a..a9414e375 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java @@ -3,9 +3,9 @@ */ package com.blade.oauth2; -import blade.kit.ReflectKit; import blade.kit.StringKit; +import com.blade.Aop; import com.blade.http.Request; import com.blade.oauth2.base.request.OAuthBaseRequest; import com.blade.oauth2.base.validator.OAuthValidator; @@ -41,7 +41,7 @@ protected OAuthValidator initValidator() throws OAuthProblemException { if (clazz == null) { throw OAuthKit.handleOAuthProblemException("Invalid response_type parameter value"); } - return (OAuthValidator) ReflectKit.newInstance(clazz); + return Aop.create(clazz); } public String getResponseType() { diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java index 7d7423a1b..58689f867 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java @@ -4,9 +4,9 @@ package com.blade.oauth2.base.request; -import blade.kit.ReflectKit; import blade.kit.StringKit; +import com.blade.Aop; import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.base.validator.OAuthValidator; @@ -33,13 +33,12 @@ protected OAuthValidator initValidator() throw OAuthKit .handleOAuthProblemException("Missing grant_type parameter value"); } - final Class> clazz = validators - .get(requestTypeValue); + final Class> clazz = validators.get(requestTypeValue); if (clazz == null) { throw OAuthKit .handleOAuthProblemException("Invalid grant_type parameter value"); } - return (OAuthValidator) ReflectKit.newInstance(clazz); + return Aop.create(clazz); } public String getPassword() { From c8c543e83bee26fb0c0d453ebbb7d6df02d81557 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 16:48:56 +0800 Subject: [PATCH 293/545] add oauth2 --- LAST_VERSION.md | 2 +- blade-core/src/main/java/com/blade/Blade.java | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index c16ae323b..5ddd2c5c7 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.4.2-alpha +    1.4.3-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 249143529..f160487d5 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -52,7 +52,7 @@ public class Blade { /** * 当前最新版本 */ - public static final String VERSION = "1.4.2"; + public static final String VERSION = "1.4.3-alpha"; /** * 框架是否已经初始化 diff --git a/pom.xml b/pom.xml index 75731d9d8..c580f8c5c 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.4.2 + 1.4.3-alpha 4.12 From a4d7179ff20eb075025be48a805168db1367cea2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 18:15:15 +0800 Subject: [PATCH 294/545] use servlet as the core scheduler --- .../main/java/com/blade/ActionHandler.java | 302 ------------------ blade-core/src/main/java/com/blade/Blade.java | 25 +- .../src/main/java/com/blade/CoreFilter.java | 150 --------- .../main/java/com/blade/IocApplication.java | 8 +- .../java/com/blade/ioc/SampleContainer.java | 16 +- .../java/com/blade/route/RouteMatcher.java | 2 +- .../main/java/com/blade/server/Server.java | 13 +- 7 files changed, 25 insertions(+), 491 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/ActionHandler.java delete mode 100644 blade-core/src/main/java/com/blade/CoreFilter.java diff --git a/blade-core/src/main/java/com/blade/ActionHandler.java b/blade-core/src/main/java/com/blade/ActionHandler.java deleted file mode 100644 index cba3e7bce..000000000 --- a/blade-core/src/main/java/com/blade/ActionHandler.java +++ /dev/null @@ -1,302 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.lang.reflect.Method; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.blade.context.BladeWebContext; -import com.blade.http.HttpStatus; -import com.blade.http.Path; -import com.blade.http.Request; -import com.blade.http.Response; -import com.blade.render.ModelAndView; -import com.blade.route.Route; -import com.blade.route.RouteHandler; -import com.blade.route.Routers; -import com.blade.route.RouteMatcher; -import com.blade.servlet.wrapper.ServletRequest; -import com.blade.servlet.wrapper.ServletResponse; - -import blade.exception.BladeException; -import blade.kit.ReflectKit; -import blade.kit.StringKit; -import blade.kit.base.ThrowableKit; -import blade.kit.log.Logger; - -/** - * 请求执行的Handler - *

- * 拦截器所有blade的请求,处理route and interceptor - *

- * - * @author biezhi - * @since 1.0 - */ -public class ActionHandler { - - private static final Logger LOGGER = Logger.getLogger(ActionHandler.class); - - /** - * blade对象 - */ - private Blade blade; - - /** - * 路由管理器 - */ - private Routers router; - - /** - * 路由匹配器 - */ - private RouteMatcher routeMatcher; - - /** - * 服务器500错误时返回的HTML - */ - private static final String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " - + Blade.VERSION +"
"; - - /** - * 服务器404错误HTML - */ - private static final String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " - + Blade.VERSION +"
"; - - /** - * 全局的ServletContext对象 - */ - private ServletContext context; - - public ActionHandler(ServletContext context, Blade blade){ - this.blade = blade; - this.router = blade.routers(); - this.context = context; - this.routeMatcher = new RouteMatcher(router); - } - - /** - * 处理请求 - * - * @param httpRequest HttpServletRequest对象 - * @param httpResponse HttpServletResponse对象 - * @return 返回true,处理完毕;返回false,由filter继续处理 - */ - public boolean handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ - - Response response = null; - try { - - // http方法, GET/POST ... - String method = httpRequest.getMethod(); - - // 请求的uri - String uri = Path.getRelativePath(httpRequest); - - // 如果是静态资源则交给filter处理 - if(null != blade.staticFolder() && blade.staticFolder().length > 0){ - if(!filterStaticFolder(uri)){ - return false; - } - } - - if(blade.debug()){ - LOGGER.debug("Request : " + method + "\t" + uri); - } - - // 创建请求对象 - Request request = new ServletRequest(httpRequest); - - // 创建响应对象 - response = new ServletResponse(httpResponse, blade.render()); - - // 初始化context - BladeWebContext.setContext(context, request, response); - - Route route = routeMatcher.getRoute(method, uri); - - // 如果找到 - if (route != null) { - // 执行before拦截 - List befores = routeMatcher.getBefore(uri); - invokeInterceptor(request, response, befores); - - // 实际执行方法 - handle(request, response, route); - - // 执行after拦截 - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - return true; - } - - // 没有找到 - render404(response, uri); - return true; - } catch (BladeException bex) { - - String error = ThrowableKit.getStackTraceAsString(bex); - LOGGER.error(error); - ThrowableKit.propagate(bex); - - httpResponse.setStatus(500); - // 写入内容到浏览器 - if (!httpResponse.isCommitted()) { - response.html(INTERNAL_ERROR); - return true; - } - - } catch (Exception e) { - - String error = ThrowableKit.getStackTraceAsString(e); - LOGGER.error(error); - ThrowableKit.propagate(e); - - httpResponse.setStatus(500); - // 写入内容到浏览器 - if (!httpResponse.isCommitted()) { - response.html(INTERNAL_ERROR); - return true; - } - - } - return false; - - } - - /** - * 404视图渲染 - * - * @param response 响应对象 - * @param uri 404的URI - */ - private void render404(Response response, String uri) { - String view404 = blade.view404(); - if(StringKit.isNotBlank(view404)){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", uri); - response.render( modelAndView ); - } else { - response.status(HttpStatus.NOT_FOUND); - response.html(String.format(VIEW_NOTFOUND, uri)); - } - } - - /** - * 执行拦截器的方法 - * - * @param request 请求对象 - * @param response 响应对象 - * @param interceptors 要执行的拦截器列表 - */ - private void invokeInterceptor(Request request, Response response, List interceptors) { - for(Route route : interceptors){ - handle(request, response, route); - } - } - - /** - * 实际的路由方法执行 - * - * @param request 请求对象 - * @param response 响应对象 - * @param route 路由对象 - */ - private void handle(Request request, Response response, Route route){ - Object target = route.getTarget(); - request.initPathParams(route.getPath()); - - // 初始化context - BladeWebContext.setContext(context, request, response); - if(target instanceof RouteHandler){ - RouteHandler routeHandler = (RouteHandler)target; - routeHandler.handle(request, response); - } else { - // 要执行的路由方法 - Method actionMethod = route.getAction(); - // 执行route方法 - executeMethod(target, actionMethod, request, response); - } - } - - /** - * 获取方法内的参数 - * - * @param request Request对象,用于注入到method参数列表中 - * @param response Response对象,用于注入到method参数列表中 - * @param params params参数列表 - * @return 返回生成后的参数数组 - */ - private Object[] getArgs(Request request, Response response, Class[] params){ - - int len = params.length; - Object[] args = new Object[len]; - - for(int i=0; i paramTypeClazz = params[i]; - if(paramTypeClazz.getName().equals(Request.class.getName())){ - args[i] = request; - } - if(paramTypeClazz.getName().equals(Response.class.getName())){ - args[i] = response; - } - } - - return args; - } - - /** - * 执行路由方法 - * - * @param object 方法的实例,即该方法所在类的对象 - * @param method 要执行的method - * @param request Request对象,作为参数注入 - * @param response Response对象,作为参数注入 - * @return 返回方法执行后的返回值 - */ - private Object executeMethod(Object object, Method method, Request request, Response response){ - int len = method.getParameterTypes().length; - method.setAccessible(true); - if(len > 0){ - Object[] args = getArgs(request, response, method.getParameterTypes()); - return ReflectKit.invokeMehod(object, method, args); - } else { - return ReflectKit.invokeMehod(object, method); - } - } - - /** - * 要过滤掉的目录 - * - * @param uri URI表示当前路径,在静态目录中进行过滤 - * @return 返回false,过滤成功;返回true,不过滤 - */ - private boolean filterStaticFolder(String uri){ - int len = blade.staticFolder().length; - for(int i=0; i bootstrap){ - this.bootstrap = Aop.create(bootstrap); + Object object = container.registerBean(bootstrap); + this.bootstrap = (Bootstrap) object; return this; } @@ -789,10 +776,10 @@ public Blade routeConf(String basePackage, String conf) { } void iocInit(){ - iocApplication.init(this); + iocApplication.init(container, iocs(), bootstrap); } - IocApplication iocApplication(){ + public IocApplication iocApplication(){ return iocApplication; } } diff --git a/blade-core/src/main/java/com/blade/CoreFilter.java b/blade-core/src/main/java/com/blade/CoreFilter.java deleted file mode 100644 index 4d57e9382..000000000 --- a/blade-core/src/main/java/com/blade/CoreFilter.java +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.blade.context.BladeWebContext; -import com.blade.route.RouteBuilder; - -import blade.kit.StringKit; -import blade.kit.TaskKit; -import blade.kit.log.Logger; - -/** - * blade核心过滤器,mvc总线 - * 匹配所有请求过滤 - * - * @author biezhi - * @since 1.0 - */ -public class CoreFilter implements Filter { - - private static final Logger LOGGER = Logger.getLogger(CoreFilter.class); - - /** - * blade全局初始化类 - */ - private static final String BOOSTRAP_CLASS = "bootstrapClass"; - - /** - * Blade单例对象 - */ - private Blade blade; - - /** - * 执行所有请求的处理器 - */ - private ActionHandler actionHandler; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - - // 防止重复初始化 - try { - blade = Blade.me(); - if(!blade.isInit){ - - blade.webRoot(filterConfig.getServletContext().getRealPath("/")); - Bootstrap bootstrap = blade.bootstrap(); - String bootStrapClassName = filterConfig.getInitParameter(BOOSTRAP_CLASS); - if(StringKit.isNotBlank(bootStrapClassName)){ - bootstrap = getBootstrap(filterConfig.getInitParameter(BOOSTRAP_CLASS)); - bootstrap.init(blade); - blade.app(bootstrap); - } - - // 构建路由 - new RouteBuilder(blade).building(); - - // 初始化IOC - blade.iocInit(); - - bootstrap.contextInitialized(blade); - blade.setInit(true); - - actionHandler = new ActionHandler(filterConfig.getServletContext(), blade); - - LOGGER.info("blade init complete!"); - } - } catch (Exception e) { - e.printStackTrace(); - System.exit(0); - } - - } - - /** - * 获取全局初始化对象,初始化应用 - * - * @param botstrapClassName 全局初始化类名 - * @return 一个全局初始化对象 - * @throws ServletException - */ - @SuppressWarnings("unchecked") - private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { - Bootstrap bootstrapClass = null; - try { - if(null != botstrapClassName){ - Class applicationClass = (Class) Class.forName(botstrapClassName); - if(null != applicationClass){ - bootstrapClass = Aop.create(applicationClass); - } - } else { - throw new ServletException("bootstrapClass is null !"); - } - } catch (Exception e) { - throw new ServletException(e); - } - return bootstrapClass; - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{ - - HttpServletRequest httpRequest = (HttpServletRequest) request; - HttpServletResponse httpResponse = (HttpServletResponse) response; - - httpRequest.setCharacterEncoding(blade.encoding()); - httpResponse.setCharacterEncoding(blade.encoding()); - - /** - * 是否被RequestHandler执行 - */ - boolean isHandler = actionHandler.handle(httpRequest, httpResponse); - if(!isHandler){ - chain.doFilter(httpRequest, httpResponse); - } - } - - @Override - public void destroy() { - LOGGER.info("blade destroy!"); - BladeWebContext.remove(); - blade.iocApplication().destroy(); - TaskKit.depose(); - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index e2e76a52e..93ed4323d 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -65,16 +65,16 @@ public IocApplication() { * * @param blade Blade实例 */ - public void init(Blade blade){ - this.container = blade.container(); + public void init(Container container, String[] iocs, Bootstrap bootstrap){ + this.container = container; // 初始化全局配置类 if(null == container.getBean(Bootstrap.class, Scope.SINGLE)){ - container.registerBean(blade.bootstrap()); + container.registerBean(bootstrap); } // 初始化ioc容器 - initIOC(blade.iocs()); + initIOC(iocs); // 初始化注入 container.initWired(); diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java index 5c57b51bb..4ed4d906c 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -95,7 +95,7 @@ public T getBean(String name, Scope scope) { @Override public T getBean(Class type, Scope scope) { - return this.getBean(type.getCanonicalName(), scope); + return this.getBean(type.getName(), scope); } @Override @@ -110,7 +110,7 @@ public Collection getBeans() { @Override public boolean hasBean(Class clazz) { - String className = clazz.getCanonicalName(); + String className = clazz.getName(); return beanKeys.containsValue(className); } @@ -133,7 +133,7 @@ public boolean removeBean(String name) { @Override public boolean removeBean(Class clazz) { - return this.removeBean(clazz.getCanonicalName()); + return this.removeBean(clazz.getName()); } /** @@ -145,7 +145,7 @@ public boolean removeBean(Class clazz) { @Override public Object registerBean(Class clazz) { - String name = clazz.getCanonicalName(); + String name = clazz.getName(); Object object = null; //非抽象类、接口 @@ -168,7 +168,7 @@ public Object registerBean(String name, Object value) { return beans.get(className); } - className = clazz.getCanonicalName(); + className = clazz.getName(); beanKeys.put(name, className); if(null == beans.get(className)){ beans.put(className, value); @@ -178,7 +178,7 @@ public Object registerBean(String name, Object value) { Class[] interfaces = clazz.getInterfaces(); if(interfaces.length > 0){ for(Class interfaceClazz : interfaces){ - this.registerBean(interfaceClazz.getCanonicalName(), value); + this.registerBean(interfaceClazz.getName(), value); } } @@ -192,7 +192,7 @@ public Object registerBean(String name, Object value) { @Override public Object registerBean(Object object) { - String className = object.getClass().getCanonicalName(); + String className = object.getClass().getName(); return registerBean(className, object); } @@ -354,7 +354,7 @@ public void injection(Object object) { } if (null == injectField) { - throw new BladeException("Unable to load " + field.getType().getCanonicalName() + "!"); + throw new BladeException("Unable to load " + field.getType().getName() + "!"); } boolean accessible = field.isAccessible(); diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java index bbae44e20..77f6524d9 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcher.java @@ -68,7 +68,7 @@ public RouteMatcher(Routers router) { public Route getRoute(String httpMethod, String path) { String cleanPath = parsePath(path); - String routeKey = path + "#" + httpMethod.toLowerCase(); + String routeKey = path + "#" + httpMethod.toUpperCase(); Route route = routes.get(routeKey); if(null != route){ return route; diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java index 16ea95e1a..450e60ca0 100644 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -15,16 +15,12 @@ */ package com.blade.server; -import java.util.EnumSet; - -import javax.servlet.DispatcherType; - import org.eclipse.jetty.servlet.ServletContextHandler; -import com.blade.CoreFilter; - import blade.kit.log.Logger; +import com.blade.DispatcherServlet; + /** * *

@@ -59,10 +55,13 @@ public void start(String contextPath) throws Exception{ context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath(contextPath); context.setResourceBase(System.getProperty("java.io.tmpdir")); - context.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + context.addServlet(DispatcherServlet.class, "/"); + +// context.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); server.setHandler(this.context); server.start(); +// server.dump(System.err); LOGGER.info("Blade Server Listen on 0.0.0.0:" + this.port); } From f27c9a81eddac5ba5e654484b29e4dd8a6664c2f Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 8 Dec 2015 18:16:12 +0800 Subject: [PATCH 295/545] add DispatcherServlet --- blade-core/src/main/java/com/blade/Const.java | 26 ++ .../java/com/blade/DispatcherServlet.java | 314 ++++++++++++++++++ .../blade/context/BladeContextListener.java | 29 ++ 3 files changed, 369 insertions(+) create mode 100644 blade-core/src/main/java/com/blade/Const.java create mode 100644 blade-core/src/main/java/com/blade/DispatcherServlet.java create mode 100644 blade-core/src/main/java/com/blade/context/BladeContextListener.java diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java new file mode 100644 index 000000000..51f87460f --- /dev/null +++ b/blade-core/src/main/java/com/blade/Const.java @@ -0,0 +1,26 @@ +package com.blade; + +public interface Const { + + /** + * 当前最新版本 + */ + String BLADE_VERSION = "1.5.0-alpha"; + + /** + * 服务器500错误时返回的HTML + */ + String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + + BLADE_VERSION +"
"; + + /** + * 服务器404错误HTML + */ + String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + + BLADE_VERSION +"
"; + + /** + * jetty默认端口 + */ + int DEFAULT_PORT = 9000; +} diff --git a/blade-core/src/main/java/com/blade/DispatcherServlet.java b/blade-core/src/main/java/com/blade/DispatcherServlet.java new file mode 100644 index 000000000..40aaeb4c6 --- /dev/null +++ b/blade-core/src/main/java/com/blade/DispatcherServlet.java @@ -0,0 +1,314 @@ +package com.blade; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.List; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.blade.context.BladeWebContext; +import com.blade.http.HttpStatus; +import com.blade.http.Path; +import com.blade.http.Request; +import com.blade.http.Response; +import com.blade.render.ModelAndView; +import com.blade.route.Route; +import com.blade.route.RouteBuilder; +import com.blade.route.RouteHandler; +import com.blade.route.RouteMatcher; +import com.blade.servlet.wrapper.ServletRequest; +import com.blade.servlet.wrapper.ServletResponse; + +import blade.exception.BladeException; +import blade.kit.ReflectKit; +import blade.kit.StringKit; +import blade.kit.base.ThrowableKit; +import blade.kit.log.Logger; + +public class DispatcherServlet extends HttpServlet { + + private static final long serialVersionUID = -2607425162473178733L; + + private static final Logger LOGGER = Logger.getLogger(DispatcherServlet.class); + + private Blade blade = Blade.me(); + + private Bootstrap bootstrap; + + private ServletContext servletContext; + + private RouteMatcher routeMatcher; + + public DispatcherServlet() { + } + + public DispatcherServlet(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + blade.setInit(true); + } + + @Override + public void init(ServletConfig config) throws ServletException { + if(!blade.isInit){ + this.bootstrap = blade.bootstrap(); + if(null == bootstrap){ + String bootStrapClassName = config.getInitParameter("bootstrap"); + if(StringKit.isNotBlank(bootStrapClassName)){ + bootstrap = getBootstrap(bootStrapClassName); + } else { + bootstrap = new Bootstrap() { + @Override + public void init(Blade blade) { + } + }; + } + blade.app(bootstrap); + } + bootstrap.init(blade); + + // 构建路由 + new RouteBuilder(blade).building(); + + // 初始化IOC + blade.iocInit(); + + blade.setInit(true); + + routeMatcher = new RouteMatcher(blade.routers()); + blade.bootstrap().contextInitialized(blade); + servletContext = config.getServletContext(); + + LOGGER.info("blade init complete!"); + } + } + + @Override + protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { + httpRequest.setCharacterEncoding(blade.encoding()); + httpResponse.setCharacterEncoding(blade.encoding()); + + Response response = null; + try { + + // http方法, GET/POST ... + String method = httpRequest.getMethod(); + + // 请求的uri + String uri = Path.getRelativePath(httpRequest); + + // 如果是静态资源则交给filter处理 + if(null != blade.staticFolder() && blade.staticFolder().length > 0){ + if(!filterStaticFolder(uri)){ + return; + } + } + + if(blade.debug()){ + LOGGER.debug("Request : " + method + "\t" + uri); + } + + // 创建请求对象 + Request request = new ServletRequest(httpRequest); + + // 创建响应对象 + response = new ServletResponse(httpResponse, blade.render()); + + // 初始化context + BladeWebContext.setContext(servletContext, request, response); + + Route route = routeMatcher.getRoute(method, uri); + + // 如果找到 + if (route != null) { + // 执行before拦截 + List befores = routeMatcher.getBefore(uri); + invokeInterceptor(request, response, befores); + + // 实际执行方法 + handle(request, response, route); + + // 执行after拦截 + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + return; + } + + // 没有找到 + render404(response, uri); + return; + } catch (BladeException bex) { + + String error = ThrowableKit.getStackTraceAsString(bex); + LOGGER.error(error); + ThrowableKit.propagate(bex); + + httpResponse.setStatus(500); + // 写入内容到浏览器 + if (!httpResponse.isCommitted()) { + response.html(Const.INTERNAL_ERROR); + return; + } + + } catch (Exception e) { + + String error = ThrowableKit.getStackTraceAsString(e); + LOGGER.error(error); + ThrowableKit.propagate(e); + + httpResponse.setStatus(500); + // 写入内容到浏览器 + if (!httpResponse.isCommitted()) { + response.html(Const.INTERNAL_ERROR); + return; + } + } + return; + } + + /** + * 404视图渲染 + * + * @param response 响应对象 + * @param uri 404的URI + */ + private void render404(Response response, String uri) { + String view404 = blade.view404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(Const.VIEW_NOTFOUND, uri)); + } + } + + /** + * 执行拦截器的方法 + * + * @param request 请求对象 + * @param response 响应对象 + * @param interceptors 要执行的拦截器列表 + */ + private void invokeInterceptor(Request request, Response response, List interceptors) { + for(Route route : interceptors){ + handle(request, response, route); + } + } + + /** + * 实际的路由方法执行 + * + * @param request 请求对象 + * @param response 响应对象 + * @param route 路由对象 + */ + private void handle(Request request, Response response, Route route){ + Object target = route.getTarget(); + request.initPathParams(route.getPath()); + + // 初始化context + BladeWebContext.setContext(servletContext, request, response); + if(target instanceof RouteHandler){ + RouteHandler routeHandler = (RouteHandler)target; + routeHandler.handle(request, response); + } else { + // 要执行的路由方法 + Method actionMethod = route.getAction(); + // 执行route方法 + executeMethod(target, actionMethod, request, response); + } + } + + /** + * 获取方法内的参数 + * + * @param request Request对象,用于注入到method参数列表中 + * @param response Response对象,用于注入到method参数列表中 + * @param params params参数列表 + * @return 返回生成后的参数数组 + */ + private Object[] getArgs(Request request, Response response, Class[] params){ + + int len = params.length; + Object[] args = new Object[len]; + + for(int i=0; i paramTypeClazz = params[i]; + if(paramTypeClazz.getName().equals(Request.class.getName())){ + args[i] = request; + } + if(paramTypeClazz.getName().equals(Response.class.getName())){ + args[i] = response; + } + } + + return args; + } + + /** + * 执行路由方法 + * + * @param object 方法的实例,即该方法所在类的对象 + * @param method 要执行的method + * @param request Request对象,作为参数注入 + * @param response Response对象,作为参数注入 + * @return 返回方法执行后的返回值 + */ + private Object executeMethod(Object object, Method method, Request request, Response response){ + int len = method.getParameterTypes().length; + method.setAccessible(true); + if(len > 0){ + Object[] args = getArgs(request, response, method.getParameterTypes()); + return ReflectKit.invokeMehod(object, method, args); + } else { + return ReflectKit.invokeMehod(object, method); + } + } + + /** + * 要过滤掉的目录 + * + * @param uri URI表示当前路径,在静态目录中进行过滤 + * @return 返回false,过滤成功;返回true,不过滤 + */ + private boolean filterStaticFolder(String uri){ + int len = blade.staticFolder().length; + for(int i=0; i applicationClass = (Class) Class.forName(botstrapClassName); + if(null != applicationClass){ + bootstrapClass = Aop.create(applicationClass); + } + } else { + throw new ServletException("bootstrapClass is null !"); + } + } catch (Exception e) { + throw new ServletException(e); + } + return bootstrapClass; + } +} diff --git a/blade-core/src/main/java/com/blade/context/BladeContextListener.java b/blade-core/src/main/java/com/blade/context/BladeContextListener.java new file mode 100644 index 000000000..6ade4d668 --- /dev/null +++ b/blade-core/src/main/java/com/blade/context/BladeContextListener.java @@ -0,0 +1,29 @@ +package com.blade.context; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +import blade.kit.TaskKit; +import blade.kit.log.Logger; + +import com.blade.Blade; + +@WebListener +public class BladeContextListener implements ServletContextListener { + + private static final Logger LOGGER = Logger.getLogger(BladeContextListener.class); + + @Override + public void contextInitialized(final ServletContextEvent sce) { + LOGGER.info("blade context Initialized!"); + } + + @Override + public void contextDestroyed(final ServletContextEvent sce) { + LOGGER.info("blade destroy!"); + BladeWebContext.remove(); + Blade.me().iocApplication().destroy(); + TaskKit.depose(); + } +} \ No newline at end of file From 8454de0254b86534f161aa08d9bb07c01b455bfd Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 9 Dec 2015 13:49:59 +0800 Subject: [PATCH 296/545] add async servlet --- blade-core/src/main/java/com/blade/Aop.java | 21 ++ blade-core/src/main/java/com/blade/Blade.java | 36 +- blade-core/src/main/java/com/blade/Const.java | 26 ++ .../java/com/blade/DispatcherServlet.java | 314 ------------------ .../src/main/java/com/blade/http/Path.java | 8 +- .../main/java/com/blade/server/Server.java | 19 +- .../java/com/blade/web/DispatcherServlet.java | 146 ++++++++ 7 files changed, 240 insertions(+), 330 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/DispatcherServlet.java create mode 100644 blade-core/src/main/java/com/blade/web/DispatcherServlet.java diff --git a/blade-core/src/main/java/com/blade/Aop.java b/blade-core/src/main/java/com/blade/Aop.java index bbebff45e..d92ae606d 100644 --- a/blade-core/src/main/java/com/blade/Aop.java +++ b/blade-core/src/main/java/com/blade/Aop.java @@ -1,7 +1,28 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; import blade.kit.ReflectKit; +/** + * 作为AOP的基础,用于创建对象 + * + * @author biezhi + * @since 1.0 + */ @SuppressWarnings("unchecked") public final class Aop { diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 58c43d690..43a6d4a1d 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -52,7 +52,12 @@ public class Blade { /** * 框架是否已经初始化 */ - boolean isInit = false; + private boolean isInit = false; + + /** + * 是否异步调用 + */ + private boolean isAsyn = true; /** * blade全局初始化对象,在web.xml中配置,必须 @@ -122,7 +127,7 @@ public void setInit(boolean isInit) { * @return 返回Blade封装的Server */ public Server createServer(int port){ - return new Server(port); + return new Server(port, isAsyn); } /** @@ -586,6 +591,16 @@ public Blade listen(int port){ return this; } + /** + * 是否异步调用 + * @param isAsyn 是否异步 + * @return 返回Blade单例对象 + */ + public Blade isAsyn(boolean isAsyn){ + this.isAsyn = isAsyn; + return this; + } + /** * 设置jetty启动上下文 * @@ -593,7 +608,7 @@ public Blade listen(int port){ */ public void start(String contextPath) { try { - bladeServer = new Server(this.port); + bladeServer = new Server(this.port, this.isAsyn); bladeServer.start(contextPath); } catch (Exception e) { throw new RuntimeException(e); @@ -775,11 +790,18 @@ public Blade routeConf(String basePackage, String conf) { return this; } - void iocInit(){ - iocApplication.init(container, iocs(), bootstrap); - } - + /** + * @return 返回IocApplication对象 + */ public IocApplication iocApplication(){ return iocApplication; } + + /** + * @return 返回是否已经初始化 + */ + public boolean isInit() { + return isInit; + } + } diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 51f87460f..a98d23d59 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -1,5 +1,26 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; +/** + * 常量接口 + * + * @author biezhi + * @since 1.0 + */ public interface Const { /** @@ -23,4 +44,9 @@ public interface Const { * jetty默认端口 */ int DEFAULT_PORT = 9000; + + /** + * 请求线程池context key + */ + String BLADE_EXECUTOR = "blade-req-executor"; } diff --git a/blade-core/src/main/java/com/blade/DispatcherServlet.java b/blade-core/src/main/java/com/blade/DispatcherServlet.java deleted file mode 100644 index 40aaeb4c6..000000000 --- a/blade-core/src/main/java/com/blade/DispatcherServlet.java +++ /dev/null @@ -1,314 +0,0 @@ -package com.blade; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.List; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.blade.context.BladeWebContext; -import com.blade.http.HttpStatus; -import com.blade.http.Path; -import com.blade.http.Request; -import com.blade.http.Response; -import com.blade.render.ModelAndView; -import com.blade.route.Route; -import com.blade.route.RouteBuilder; -import com.blade.route.RouteHandler; -import com.blade.route.RouteMatcher; -import com.blade.servlet.wrapper.ServletRequest; -import com.blade.servlet.wrapper.ServletResponse; - -import blade.exception.BladeException; -import blade.kit.ReflectKit; -import blade.kit.StringKit; -import blade.kit.base.ThrowableKit; -import blade.kit.log.Logger; - -public class DispatcherServlet extends HttpServlet { - - private static final long serialVersionUID = -2607425162473178733L; - - private static final Logger LOGGER = Logger.getLogger(DispatcherServlet.class); - - private Blade blade = Blade.me(); - - private Bootstrap bootstrap; - - private ServletContext servletContext; - - private RouteMatcher routeMatcher; - - public DispatcherServlet() { - } - - public DispatcherServlet(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - blade.setInit(true); - } - - @Override - public void init(ServletConfig config) throws ServletException { - if(!blade.isInit){ - this.bootstrap = blade.bootstrap(); - if(null == bootstrap){ - String bootStrapClassName = config.getInitParameter("bootstrap"); - if(StringKit.isNotBlank(bootStrapClassName)){ - bootstrap = getBootstrap(bootStrapClassName); - } else { - bootstrap = new Bootstrap() { - @Override - public void init(Blade blade) { - } - }; - } - blade.app(bootstrap); - } - bootstrap.init(blade); - - // 构建路由 - new RouteBuilder(blade).building(); - - // 初始化IOC - blade.iocInit(); - - blade.setInit(true); - - routeMatcher = new RouteMatcher(blade.routers()); - blade.bootstrap().contextInitialized(blade); - servletContext = config.getServletContext(); - - LOGGER.info("blade init complete!"); - } - } - - @Override - protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { - httpRequest.setCharacterEncoding(blade.encoding()); - httpResponse.setCharacterEncoding(blade.encoding()); - - Response response = null; - try { - - // http方法, GET/POST ... - String method = httpRequest.getMethod(); - - // 请求的uri - String uri = Path.getRelativePath(httpRequest); - - // 如果是静态资源则交给filter处理 - if(null != blade.staticFolder() && blade.staticFolder().length > 0){ - if(!filterStaticFolder(uri)){ - return; - } - } - - if(blade.debug()){ - LOGGER.debug("Request : " + method + "\t" + uri); - } - - // 创建请求对象 - Request request = new ServletRequest(httpRequest); - - // 创建响应对象 - response = new ServletResponse(httpResponse, blade.render()); - - // 初始化context - BladeWebContext.setContext(servletContext, request, response); - - Route route = routeMatcher.getRoute(method, uri); - - // 如果找到 - if (route != null) { - // 执行before拦截 - List befores = routeMatcher.getBefore(uri); - invokeInterceptor(request, response, befores); - - // 实际执行方法 - handle(request, response, route); - - // 执行after拦截 - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - return; - } - - // 没有找到 - render404(response, uri); - return; - } catch (BladeException bex) { - - String error = ThrowableKit.getStackTraceAsString(bex); - LOGGER.error(error); - ThrowableKit.propagate(bex); - - httpResponse.setStatus(500); - // 写入内容到浏览器 - if (!httpResponse.isCommitted()) { - response.html(Const.INTERNAL_ERROR); - return; - } - - } catch (Exception e) { - - String error = ThrowableKit.getStackTraceAsString(e); - LOGGER.error(error); - ThrowableKit.propagate(e); - - httpResponse.setStatus(500); - // 写入内容到浏览器 - if (!httpResponse.isCommitted()) { - response.html(Const.INTERNAL_ERROR); - return; - } - } - return; - } - - /** - * 404视图渲染 - * - * @param response 响应对象 - * @param uri 404的URI - */ - private void render404(Response response, String uri) { - String view404 = blade.view404(); - if(StringKit.isNotBlank(view404)){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", uri); - response.render( modelAndView ); - } else { - response.status(HttpStatus.NOT_FOUND); - response.html(String.format(Const.VIEW_NOTFOUND, uri)); - } - } - - /** - * 执行拦截器的方法 - * - * @param request 请求对象 - * @param response 响应对象 - * @param interceptors 要执行的拦截器列表 - */ - private void invokeInterceptor(Request request, Response response, List interceptors) { - for(Route route : interceptors){ - handle(request, response, route); - } - } - - /** - * 实际的路由方法执行 - * - * @param request 请求对象 - * @param response 响应对象 - * @param route 路由对象 - */ - private void handle(Request request, Response response, Route route){ - Object target = route.getTarget(); - request.initPathParams(route.getPath()); - - // 初始化context - BladeWebContext.setContext(servletContext, request, response); - if(target instanceof RouteHandler){ - RouteHandler routeHandler = (RouteHandler)target; - routeHandler.handle(request, response); - } else { - // 要执行的路由方法 - Method actionMethod = route.getAction(); - // 执行route方法 - executeMethod(target, actionMethod, request, response); - } - } - - /** - * 获取方法内的参数 - * - * @param request Request对象,用于注入到method参数列表中 - * @param response Response对象,用于注入到method参数列表中 - * @param params params参数列表 - * @return 返回生成后的参数数组 - */ - private Object[] getArgs(Request request, Response response, Class[] params){ - - int len = params.length; - Object[] args = new Object[len]; - - for(int i=0; i paramTypeClazz = params[i]; - if(paramTypeClazz.getName().equals(Request.class.getName())){ - args[i] = request; - } - if(paramTypeClazz.getName().equals(Response.class.getName())){ - args[i] = response; - } - } - - return args; - } - - /** - * 执行路由方法 - * - * @param object 方法的实例,即该方法所在类的对象 - * @param method 要执行的method - * @param request Request对象,作为参数注入 - * @param response Response对象,作为参数注入 - * @return 返回方法执行后的返回值 - */ - private Object executeMethod(Object object, Method method, Request request, Response response){ - int len = method.getParameterTypes().length; - method.setAccessible(true); - if(len > 0){ - Object[] args = getArgs(request, response, method.getParameterTypes()); - return ReflectKit.invokeMehod(object, method, args); - } else { - return ReflectKit.invokeMehod(object, method); - } - } - - /** - * 要过滤掉的目录 - * - * @param uri URI表示当前路径,在静态目录中进行过滤 - * @return 返回false,过滤成功;返回true,不过滤 - */ - private boolean filterStaticFolder(String uri){ - int len = blade.staticFolder().length; - for(int i=0; i applicationClass = (Class) Class.forName(botstrapClassName); - if(null != applicationClass){ - bootstrapClass = Aop.create(applicationClass); - } - } else { - throw new ServletException("bootstrapClass is null !"); - } - } catch (Exception e) { - throw new ServletException(e); - } - return bootstrapClass; - } -} diff --git a/blade-core/src/main/java/com/blade/http/Path.java b/blade-core/src/main/java/com/blade/http/Path.java index d60c984b9..11bfb209d 100644 --- a/blade-core/src/main/java/com/blade/http/Path.java +++ b/blade-core/src/main/java/com/blade/http/Path.java @@ -19,8 +19,6 @@ import java.net.URLDecoder; import java.util.List; -import javax.servlet.http.HttpServletRequest; - import blade.kit.CollectionKit; import blade.kit.StringKit; @@ -41,10 +39,10 @@ public final class Path { public static final String ALL_PATHS = "/*"; private static final String SLASH = "/"; - public static String getRelativePath(HttpServletRequest request) { + public static String getRelativePath(String path, String contextPath) { - String path = request.getRequestURI(); - String contextPath = request.getContextPath(); +// String path = request.getRequestURI(); +// String contextPath = request.getContextPath(); path = path.substring(contextPath.length()); diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java index 450e60ca0..7ee9db3e6 100644 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -16,10 +16,12 @@ package com.blade.server; import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; import blade.kit.log.Logger; -import com.blade.DispatcherServlet; +import com.blade.web.AppContextListener; +import com.blade.web.DispatcherServlet; /** * @@ -36,18 +38,25 @@ public class Server { private int port = 9000; + private boolean async = true; + private org.eclipse.jetty.server.Server server; private ServletContextHandler context; - public Server(int port) { + public Server(int port, boolean async) { this.port = port; + this.async = async; } public void setPort(int port){ this.port = port; } + public void setAsync(boolean async) { + this.async = async; + } + public void start(String contextPath) throws Exception{ server = new org.eclipse.jetty.server.Server(this.port); @@ -55,10 +64,12 @@ public void start(String contextPath) throws Exception{ context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath(contextPath); context.setResourceBase(System.getProperty("java.io.tmpdir")); - context.addServlet(DispatcherServlet.class, "/"); + context.addEventListener(new AppContextListener()); -// context.addFilter(CoreFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); + servletHolder.setAsyncSupported(async); + context.addServlet(servletHolder, "/"); server.setHandler(this.context); server.start(); // server.dump(System.err); diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java new file mode 100644 index 000000000..ad2f6c8cf --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; + +import java.io.IOException; +import java.util.concurrent.ThreadPoolExecutor; + +import javax.servlet.AsyncContext; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import blade.kit.StringKit; +import blade.kit.log.Logger; + +import com.blade.Aop; +import com.blade.Blade; +import com.blade.Bootstrap; +import com.blade.Const; +import com.blade.route.RouteBuilder; +import com.blade.route.RouteMatcher; + +/** + * Blade核心调度器 + * + * @author biezhi + * @since 1.0 + */ +public class DispatcherServlet extends HttpServlet { + + private static final long serialVersionUID = -2607425162473178733L; + + private static final Logger LOGGER = Logger.getLogger(DispatcherServlet.class); + + private Blade blade = Blade.me(); + + private Bootstrap bootstrap; + + private ServletContext servletContext; + + public DispatcherServlet() { + } + + public DispatcherServlet(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + blade.setInit(true); + } + + @Override + public void init(ServletConfig config) throws ServletException { + if(!blade.isInit()){ + this.bootstrap = blade.bootstrap(); + if(null == bootstrap){ + String bootStrapClassName = config.getInitParameter("bootstrap"); + if(StringKit.isNotBlank(bootStrapClassName)){ + bootstrap = getBootstrap(bootStrapClassName); + } else { + bootstrap = new Bootstrap() { + @Override + public void init(Blade blade) { + } + }; + } + blade.app(bootstrap); + } + bootstrap.init(blade); + + // 构建路由 + new RouteBuilder(blade).building(); + + // 初始化IOC + blade.iocApplication().init(blade.container(), blade.iocs(), bootstrap); + + blade.bootstrap().contextInitialized(blade); + + servletContext = config.getServletContext(); + + SyncRequestHandler.routeMatcher = new RouteMatcher(blade.routers()); + AsynRequestHandler.routeMatcher = new RouteMatcher(blade.routers()); + + blade.setInit(true); + LOGGER.info("blade init complete!"); + } + } + + @Override + protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { + httpRequest.setCharacterEncoding(blade.encoding()); + httpResponse.setCharacterEncoding(blade.encoding()); + + boolean isAsync = httpRequest.isAsyncSupported(); + System.out.println("isAsync = "+isAsync); + if (isAsync) { + AsyncContext asyncCtx = httpRequest.startAsync(); + asyncCtx.addListener(new AppAsyncListener()); + asyncCtx.setTimeout(10000L); + + ThreadPoolExecutor executor = (ThreadPoolExecutor) servletContext.getAttribute(Const.BLADE_EXECUTOR); + executor.execute(new AsynRequestHandler(servletContext, asyncCtx)); +// asyncCtx.start(new AsynRequestHandler(blade, servletContext, asyncCtx)); + } else { + new SyncRequestHandler(servletContext, httpRequest, httpResponse).run(); + } + } + + /** + * 获取全局初始化对象,初始化应用 + * + * @param botstrapClassName 全局初始化类名 + * @return 一个全局初始化对象 + * @throws ServletException + */ + @SuppressWarnings("unchecked") + private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { + Bootstrap bootstrapClass = null; + try { + if(null != botstrapClassName){ + Class applicationClass = (Class) Class.forName(botstrapClassName); + if(null != applicationClass){ + bootstrapClass = Aop.create(applicationClass); + } + } else { + throw new ServletException("bootstrapClass is null !"); + } + } catch (Exception e) { + throw new ServletException(e); + } + return bootstrapClass; + } +} From a9ef7293570d87ce9cab260071b975f1cbd07a9d Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 9 Dec 2015 13:50:36 +0800 Subject: [PATCH 297/545] add async Listener And RequestHandler --- .../java/com/blade/web/AppAsyncListener.java | 38 +++ .../com/blade/web/AppContextListener.java | 27 ++ .../com/blade/web/AsynRequestHandler.java | 261 ++++++++++++++++++ .../com/blade/web/SyncRequestHandler.java | 251 +++++++++++++++++ 4 files changed, 577 insertions(+) create mode 100644 blade-core/src/main/java/com/blade/web/AppAsyncListener.java create mode 100644 blade-core/src/main/java/com/blade/web/AppContextListener.java create mode 100644 blade-core/src/main/java/com/blade/web/AsynRequestHandler.java create mode 100644 blade-core/src/main/java/com/blade/web/SyncRequestHandler.java diff --git a/blade-core/src/main/java/com/blade/web/AppAsyncListener.java b/blade-core/src/main/java/com/blade/web/AppAsyncListener.java new file mode 100644 index 000000000..c56e85988 --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/AppAsyncListener.java @@ -0,0 +1,38 @@ +package com.blade.web; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.AsyncEvent; +import javax.servlet.AsyncListener; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebListener; + +@WebListener +public class AppAsyncListener implements AsyncListener { + + @Override + public void onComplete(AsyncEvent asyncEvent) throws IOException { + System.out.println("AppAsyncListener onComplete"); + } + + @Override + public void onError(AsyncEvent asyncEvent) throws IOException { + System.out.println("AppAsyncListener onError"); + } + + @Override + public void onStartAsync(AsyncEvent asyncEvent) throws IOException { + System.out.println("AppAsyncListener onStartAsync"); + } + + @Override + public void onTimeout(AsyncEvent asyncEvent) throws IOException { + System.out.println("AppAsyncListener onTimeout"); + //we can send appropriate response to client + ServletResponse response = asyncEvent.getAsyncContext().getResponse(); + PrintWriter out = response.getWriter(); + out.write("TimeOut Error in Processing"); + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/AppContextListener.java b/blade-core/src/main/java/com/blade/web/AppContextListener.java new file mode 100644 index 000000000..49d452aba --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/AppContextListener.java @@ -0,0 +1,27 @@ +package com.blade.web; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +import com.blade.Const; + +@WebListener +public class AppContextListener implements ServletContextListener { + + public void contextInitialized(ServletContextEvent servletContextEvent) { + // create the thread pool + ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 200, 50000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(100)); + servletContextEvent.getServletContext().setAttribute(Const.BLADE_EXECUTOR, executor); + } + + public void contextDestroyed(ServletContextEvent servletContextEvent) { + ThreadPoolExecutor executor = (ThreadPoolExecutor) servletContextEvent.getServletContext().getAttribute("blade-executor"); + executor.shutdown(); + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java new file mode 100644 index 000000000..f44d7a91e --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -0,0 +1,261 @@ +package com.blade.web; + +import java.lang.reflect.Method; +import java.util.List; + +import javax.servlet.AsyncContext; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import blade.exception.BladeException; +import blade.kit.ReflectKit; +import blade.kit.StringKit; +import blade.kit.base.ThrowableKit; +import blade.kit.log.Logger; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.context.BladeWebContext; +import com.blade.http.HttpStatus; +import com.blade.http.Path; +import com.blade.http.Request; +import com.blade.http.Response; +import com.blade.render.ModelAndView; +import com.blade.route.Route; +import com.blade.route.RouteHandler; +import com.blade.route.RouteMatcher; +import com.blade.servlet.wrapper.ServletRequest; +import com.blade.servlet.wrapper.ServletResponse; + +/** + * 异步请求处理器 + * @author biezhi + */ +public class AsynRequestHandler implements Runnable { + + private static final Logger LOGGER = Logger.getLogger(AsynRequestHandler.class); + + private Blade blade = Blade.me(); + + private ServletContext servletContext; + + static RouteMatcher routeMatcher; + + private HttpServletRequest httpRequest; + + private HttpServletResponse httpResponse; + + private AsyncContext asyncContext; + + public AsynRequestHandler(ServletContext servletContext, AsyncContext asyncCtx) { + this.asyncContext = asyncCtx; + this.servletContext = servletContext; + this.httpRequest = (HttpServletRequest) asyncCtx.getRequest(); + this.httpResponse = (HttpServletResponse) asyncCtx.getResponse(); + } + + @Override + public void run(){ + + Response response = null; + try { + // http方法, GET/POST ... + String method = httpRequest.getMethod(); + + // 请求的uri + String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); + + // 如果是静态资源则交给filter处理 + if(null != blade.staticFolder() && blade.staticFolder().length > 0){ + if(!filterStaticFolder(uri)){ + asyncContext.complete(); + return; + } + } + + if(blade.debug()){ + LOGGER.debug("Request : " + method + "\t" + uri); + } + + // 创建请求对象 + Request request = new ServletRequest(httpRequest); + + // 创建响应对象 + response = new ServletResponse(httpResponse, blade.render()); + + // 初始化context + BladeWebContext.setContext(servletContext, request, response); + + Route route = routeMatcher.getRoute(method, uri); + + // 如果找到 + if (route != null) { + // 执行before拦截 + List befores = routeMatcher.getBefore(uri); + invokeInterceptor(request, response, befores); + + // 实际执行方法 + handle(request, response, route); + + // 执行after拦截 + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + asyncContext.complete(); + return; + } + + // 没有找到 + render404(response, uri); + asyncContext.complete(); + return; + } catch (BladeException bex) { + + String error = ThrowableKit.getStackTraceAsString(bex); + LOGGER.error(error); + ThrowableKit.propagate(bex); + + httpResponse.setStatus(500); + // 写入内容到浏览器 + if (!httpResponse.isCommitted()) { + response.html(Const.INTERNAL_ERROR); + asyncContext.complete(); + return; + } + + } catch (Exception e) { + + String error = ThrowableKit.getStackTraceAsString(e); + LOGGER.error(error); + ThrowableKit.propagate(e); + + httpResponse.setStatus(500); + // 写入内容到浏览器 + if (!httpResponse.isCommitted()) { + response.html(Const.INTERNAL_ERROR); + asyncContext.complete(); + return; + } + } + asyncContext.complete(); + return; + } + + /** + * 404视图渲染 + * + * @param response 响应对象 + * @param uri 404的URI + */ + private void render404(Response response, String uri) { + String view404 = blade.view404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(Const.VIEW_NOTFOUND, uri)); + } + } + + /** + * 执行拦截器的方法 + * + * @param request 请求对象 + * @param response 响应对象 + * @param interceptors 要执行的拦截器列表 + */ + private void invokeInterceptor(Request request, Response response, List interceptors) { + for(Route route : interceptors){ + handle(request, response, route); + } + } + + /** + * 实际的路由方法执行 + * + * @param request 请求对象 + * @param response 响应对象 + * @param route 路由对象 + */ + private void handle(Request request, Response response, Route route){ + Object target = route.getTarget(); + request.initPathParams(route.getPath()); + + // 初始化context + BladeWebContext.setContext(servletContext, request, response); + if(target instanceof RouteHandler){ + RouteHandler routeHandler = (RouteHandler)target; + routeHandler.handle(request, response); + } else { + // 要执行的路由方法 + Method actionMethod = route.getAction(); + // 执行route方法 + executeMethod(target, actionMethod, request, response); + } + } + + /** + * 获取方法内的参数 + * + * @param request Request对象,用于注入到method参数列表中 + * @param response Response对象,用于注入到method参数列表中 + * @param params params参数列表 + * @return 返回生成后的参数数组 + */ + private Object[] getArgs(Request request, Response response, Class[] params){ + + int len = params.length; + Object[] args = new Object[len]; + + for(int i=0; i paramTypeClazz = params[i]; + if(paramTypeClazz.getName().equals(Request.class.getName())){ + args[i] = request; + } + if(paramTypeClazz.getName().equals(Response.class.getName())){ + args[i] = response; + } + } + + return args; + } + + /** + * 执行路由方法 + * + * @param object 方法的实例,即该方法所在类的对象 + * @param method 要执行的method + * @param request Request对象,作为参数注入 + * @param response Response对象,作为参数注入 + * @return 返回方法执行后的返回值 + */ + private Object executeMethod(Object object, Method method, Request request, Response response){ + int len = method.getParameterTypes().length; + method.setAccessible(true); + if(len > 0){ + Object[] args = getArgs(request, response, method.getParameterTypes()); + return ReflectKit.invokeMehod(object, method, args); + } else { + return ReflectKit.invokeMehod(object, method); + } + } + + /** + * 要过滤掉的目录 + * + * @param uri URI表示当前路径,在静态目录中进行过滤 + * @return 返回false,过滤成功;返回true,不过滤 + */ + private boolean filterStaticFolder(String uri){ + int len = blade.staticFolder().length; + for(int i=0; i 0){ + if(!filterStaticFolder(uri)){ + return; + } + } + + if(blade.debug()){ + LOGGER.debug("Request : " + method + "\t" + uri); + } + + // 创建请求对象 + Request request = new ServletRequest(httpRequest); + + // 创建响应对象 + response = new ServletResponse(httpResponse, blade.render()); + + // 初始化context + BladeWebContext.setContext(servletContext, request, response); + + Route route = routeMatcher.getRoute(method, uri); + + // 如果找到 + if (route != null) { + // 执行before拦截 + List befores = routeMatcher.getBefore(uri); + invokeInterceptor(request, response, befores); + + // 实际执行方法 + handle(request, response, route); + + // 执行after拦截 + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + return; + } + + // 没有找到 + render404(response, uri); + return; + } catch (BladeException bex) { + + String error = ThrowableKit.getStackTraceAsString(bex); + LOGGER.error(error); + ThrowableKit.propagate(bex); + + httpResponse.setStatus(500); + // 写入内容到浏览器 + if (!httpResponse.isCommitted()) { + response.html(Const.INTERNAL_ERROR); + return; + } + + } catch (Exception e) { + + String error = ThrowableKit.getStackTraceAsString(e); + LOGGER.error(error); + ThrowableKit.propagate(e); + + httpResponse.setStatus(500); + // 写入内容到浏览器 + if (!httpResponse.isCommitted()) { + response.html(Const.INTERNAL_ERROR); + return; + } + } + return; + } + + /** + * 404视图渲染 + * + * @param response 响应对象 + * @param uri 404的URI + */ + private void render404(Response response, String uri) { + String view404 = blade.view404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(Const.VIEW_NOTFOUND, uri)); + } + } + + /** + * 执行拦截器的方法 + * + * @param request 请求对象 + * @param response 响应对象 + * @param interceptors 要执行的拦截器列表 + */ + private void invokeInterceptor(Request request, Response response, List interceptors) { + for(Route route : interceptors){ + handle(request, response, route); + } + } + + /** + * 实际的路由方法执行 + * + * @param request 请求对象 + * @param response 响应对象 + * @param route 路由对象 + */ + private void handle(Request request, Response response, Route route){ + Object target = route.getTarget(); + request.initPathParams(route.getPath()); + + // 初始化context + BladeWebContext.setContext(servletContext, request, response); + if(target instanceof RouteHandler){ + RouteHandler routeHandler = (RouteHandler)target; + routeHandler.handle(request, response); + } else { + // 要执行的路由方法 + Method actionMethod = route.getAction(); + // 执行route方法 + executeMethod(target, actionMethod, request, response); + } + } + + /** + * 获取方法内的参数 + * + * @param request Request对象,用于注入到method参数列表中 + * @param response Response对象,用于注入到method参数列表中 + * @param params params参数列表 + * @return 返回生成后的参数数组 + */ + private Object[] getArgs(Request request, Response response, Class[] params){ + + int len = params.length; + Object[] args = new Object[len]; + + for(int i=0; i paramTypeClazz = params[i]; + if(paramTypeClazz.getName().equals(Request.class.getName())){ + args[i] = request; + } + if(paramTypeClazz.getName().equals(Response.class.getName())){ + args[i] = response; + } + } + + return args; + } + + /** + * 执行路由方法 + * + * @param object 方法的实例,即该方法所在类的对象 + * @param method 要执行的method + * @param request Request对象,作为参数注入 + * @param response Response对象,作为参数注入 + * @return 返回方法执行后的返回值 + */ + private Object executeMethod(Object object, Method method, Request request, Response response){ + int len = method.getParameterTypes().length; + method.setAccessible(true); + if(len > 0){ + Object[] args = getArgs(request, response, method.getParameterTypes()); + return ReflectKit.invokeMehod(object, method, args); + } else { + return ReflectKit.invokeMehod(object, method); + } + } + + /** + * 要过滤掉的目录 + * + * @param uri URI表示当前路径,在静态目录中进行过滤 + * @return 返回false,过滤成功;返回true,不过滤 + */ + private boolean filterStaticFolder(String uri){ + int len = blade.staticFolder().length; + for(int i=0; i Date: Wed, 9 Dec 2015 13:53:22 +0800 Subject: [PATCH 298/545] rename package --- blade-core/src/main/java/com/blade/Blade.java | 2 +- .../main/java/com/blade/annotation/Route.java | 2 +- .../com/blade/context/BladeWebContext.java | 6 +++--- .../blade/loader/AbstractFileRouteLoader.java | 6 +++--- .../java/com/blade/render/BeetlRender.java | 4 ++-- .../java/com/blade/render/JetbrickRender.java | 4 ++-- .../java/com/blade/render/VelocityRender.java | 4 ++-- .../src/main/java/com/blade/route/Route.java | 4 ++-- .../java/com/blade/route/RouteBuilder.java | 2 +- .../java/com/blade/route/RouteHandler.java | 4 ++-- .../java/com/blade/route/RouteMatcher.java | 4 ++-- .../src/main/java/com/blade/route/Routers.java | 6 +++--- .../blade/servlet/multipart/package-info.java | 4 ---- .../blade/servlet/wrapper/package-info.java | 4 ---- .../com/blade/verify/CSRFTokenManager.java | 6 +++--- .../java/com/blade/web/AsynRequestHandler.java | 12 ++++++------ .../java/com/blade/web/SyncRequestHandler.java | 12 ++++++------ .../blade/{ => web}/http/HttpException.java | 2 +- .../com/blade/{ => web}/http/HttpMethod.java | 2 +- .../com/blade/{ => web}/http/HttpStatus.java | 2 +- .../java/com/blade/{ => web}/http/Path.java | 2 +- .../java/com/blade/{ => web}/http/Request.java | 6 +++--- .../com/blade/{ => web}/http/Response.java | 2 +- .../com/blade/{ => web}/http/package-info.java | 2 +- .../http}/wrapper/ServletRequest.java | 18 +++++++++--------- .../http}/wrapper/ServletResponse.java | 12 ++++++------ .../{servlet => web/http}/wrapper/Session.java | 2 +- .../blade/web/http/wrapper/package-info.java | 4 ++++ .../{servlet => web}/multipart/FileItem.java | 2 +- .../{servlet => web}/multipart/Multipart.java | 2 +- .../multipart/MultipartException.java | 2 +- .../multipart/MultipartHandler.java | 2 +- .../multipart/MultipartReader.java | 2 +- .../multipart/ParameterParser.java | 2 +- .../{servlet => web}/multipart/Streams.java | 2 +- .../com/blade/web/multipart/package-info.java | 4 ++++ 36 files changed, 79 insertions(+), 79 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/servlet/multipart/package-info.java delete mode 100644 blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java rename blade-core/src/main/java/com/blade/{ => web}/http/HttpException.java (93%) rename blade-core/src/main/java/com/blade/{ => web}/http/HttpMethod.java (96%) rename blade-core/src/main/java/com/blade/{ => web}/http/HttpStatus.java (95%) rename blade-core/src/main/java/com/blade/{ => web}/http/Path.java (95%) rename blade-core/src/main/java/com/blade/{ => web}/http/Request.java (93%) rename blade-core/src/main/java/com/blade/{ => web}/http/Response.java (98%) rename blade-core/src/main/java/com/blade/{ => web}/http/package-info.java (57%) rename blade-core/src/main/java/com/blade/{servlet => web/http}/wrapper/ServletRequest.java (93%) rename blade-core/src/main/java/com/blade/{servlet => web/http}/wrapper/ServletResponse.java (93%) rename blade-core/src/main/java/com/blade/{servlet => web/http}/wrapper/Session.java (98%) create mode 100644 blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java rename blade-core/src/main/java/com/blade/{servlet => web}/multipart/FileItem.java (93%) rename blade-core/src/main/java/com/blade/{servlet => web}/multipart/Multipart.java (96%) rename blade-core/src/main/java/com/blade/{servlet => web}/multipart/MultipartException.java (96%) rename blade-core/src/main/java/com/blade/{servlet => web}/multipart/MultipartHandler.java (96%) rename blade-core/src/main/java/com/blade/{servlet => web}/multipart/MultipartReader.java (99%) rename blade-core/src/main/java/com/blade/{servlet => web}/multipart/ParameterParser.java (99%) rename blade-core/src/main/java/com/blade/{servlet => web}/multipart/Streams.java (99%) create mode 100644 blade-core/src/main/java/com/blade/web/multipart/package-info.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 43a6d4a1d..18136af14 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -26,7 +26,6 @@ import blade.kit.StringKit; import blade.kit.json.JSONKit; -import com.blade.http.HttpMethod; import com.blade.ioc.Container; import com.blade.ioc.SampleContainer; import com.blade.loader.ClassPathRouteLoader; @@ -40,6 +39,7 @@ import com.blade.route.RouteHandler; import com.blade.route.Routers; import com.blade.server.Server; +import com.blade.web.http.HttpMethod; /** * Blade Core Class diff --git a/blade-core/src/main/java/com/blade/annotation/Route.java b/blade-core/src/main/java/com/blade/annotation/Route.java index b73c48183..56e4a580c 100644 --- a/blade-core/src/main/java/com/blade/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/annotation/Route.java @@ -20,7 +20,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import com.blade.http.HttpMethod; +import com.blade.web.http.HttpMethod; /** * 方法上定义的路由注解 diff --git a/blade-core/src/main/java/com/blade/context/BladeWebContext.java b/blade-core/src/main/java/com/blade/context/BladeWebContext.java index 9bd4be31b..7f82f1e27 100644 --- a/blade-core/src/main/java/com/blade/context/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/context/BladeWebContext.java @@ -17,9 +17,9 @@ import javax.servlet.ServletContext; -import com.blade.http.Request; -import com.blade.http.Response; -import com.blade.servlet.wrapper.Session; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.Session; /** * 全局的WeContext diff --git a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java index c16297c79..729cc0708 100644 --- a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java @@ -10,11 +10,11 @@ import java.util.List; import java.util.StringTokenizer; -import com.blade.http.HttpMethod; -import com.blade.http.Request; -import com.blade.http.Response; import com.blade.route.Route; import com.blade.route.RouteException; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Request; +import com.blade.web.http.Response; import blade.kit.IOKit; diff --git a/blade-core/src/main/java/com/blade/render/BeetlRender.java b/blade-core/src/main/java/com/blade/render/BeetlRender.java index ffae2d2e6..5cf975ecf 100644 --- a/blade-core/src/main/java/com/blade/render/BeetlRender.java +++ b/blade-core/src/main/java/com/blade/render/BeetlRender.java @@ -28,8 +28,8 @@ import com.blade.Blade; import com.blade.context.BladeWebContext; -import com.blade.http.Request; -import com.blade.servlet.wrapper.Session; +import com.blade.web.http.Request; +import com.blade.web.http.wrapper.Session; import blade.kit.log.Logger; diff --git a/blade-core/src/main/java/com/blade/render/JetbrickRender.java b/blade-core/src/main/java/com/blade/render/JetbrickRender.java index 6ded75c65..559a416a3 100644 --- a/blade-core/src/main/java/com/blade/render/JetbrickRender.java +++ b/blade-core/src/main/java/com/blade/render/JetbrickRender.java @@ -23,10 +23,10 @@ import com.blade.Blade; import com.blade.context.BladeWebContext; -import com.blade.http.Request; import com.blade.render.ModelAndView; import com.blade.render.Render; -import com.blade.servlet.wrapper.Session; +import com.blade.web.http.Request; +import com.blade.web.http.wrapper.Session; import blade.kit.log.Logger; import jetbrick.template.JetEngine; diff --git a/blade-core/src/main/java/com/blade/render/VelocityRender.java b/blade-core/src/main/java/com/blade/render/VelocityRender.java index ff8806a68..2945b306c 100644 --- a/blade-core/src/main/java/com/blade/render/VelocityRender.java +++ b/blade-core/src/main/java/com/blade/render/VelocityRender.java @@ -30,8 +30,8 @@ import com.blade.Blade; import com.blade.context.BladeWebContext; -import com.blade.http.Request; -import com.blade.servlet.wrapper.Session; +import com.blade.web.http.Request; +import com.blade.web.http.wrapper.Session; import blade.kit.log.Logger; diff --git a/blade-core/src/main/java/com/blade/route/Route.java b/blade-core/src/main/java/com/blade/route/Route.java index 7418addd0..6b9d719c4 100644 --- a/blade-core/src/main/java/com/blade/route/Route.java +++ b/blade-core/src/main/java/com/blade/route/Route.java @@ -17,8 +17,8 @@ import java.lang.reflect.Method; -import com.blade.http.HttpMethod; -import com.blade.http.Path; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Path; /** * diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index 6fbc4edfd..08770e739 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -28,8 +28,8 @@ import com.blade.annotation.Interceptor; import com.blade.annotation.Path; import com.blade.annotation.Route; -import com.blade.http.HttpMethod; import com.blade.ioc.Container; +import com.blade.web.http.HttpMethod; /** * diff --git a/blade-core/src/main/java/com/blade/route/RouteHandler.java b/blade-core/src/main/java/com/blade/route/RouteHandler.java index 0d404519f..c426066e9 100644 --- a/blade-core/src/main/java/com/blade/route/RouteHandler.java +++ b/blade-core/src/main/java/com/blade/route/RouteHandler.java @@ -15,8 +15,8 @@ */ package com.blade.route; -import com.blade.http.Request; -import com.blade.http.Response; +import com.blade.web.http.Request; +import com.blade.web.http.Response; /** * diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java index 77f6524d9..be807cc3f 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcher.java @@ -25,8 +25,8 @@ import java.util.Map; import java.util.Set; -import com.blade.http.HttpMethod; -import com.blade.http.Path; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Path; /** * diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 194752381..2b99e37d5 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -23,11 +23,11 @@ import blade.kit.log.Logger; import com.blade.Aop; -import com.blade.http.HttpMethod; -import com.blade.http.Request; -import com.blade.http.Response; import com.blade.ioc.Container; import com.blade.ioc.Scope; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Request; +import com.blade.web.http.Response; /** * diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/package-info.java b/blade-core/src/main/java/com/blade/servlet/multipart/package-info.java deleted file mode 100644 index 127a4c5bb..000000000 --- a/blade-core/src/main/java/com/blade/servlet/multipart/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Multipart处理 - */ -package com.blade.servlet.multipart; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java b/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java deleted file mode 100644 index cb660a14c..000000000 --- a/blade-core/src/main/java/com/blade/servlet/wrapper/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Servlet封装 - */ -package com.blade.servlet.wrapper; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java index 15134aee0..1fcff4526 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java @@ -15,9 +15,9 @@ */ package com.blade.verify; -import com.blade.http.Request; -import com.blade.http.Response; -import com.blade.servlet.wrapper.Session; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.Session; import blade.kit.HashidKit; import blade.kit.StringKit; diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index f44d7a91e..ee8cdd45a 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -17,16 +17,16 @@ import com.blade.Blade; import com.blade.Const; import com.blade.context.BladeWebContext; -import com.blade.http.HttpStatus; -import com.blade.http.Path; -import com.blade.http.Request; -import com.blade.http.Response; import com.blade.render.ModelAndView; import com.blade.route.Route; import com.blade.route.RouteHandler; import com.blade.route.RouteMatcher; -import com.blade.servlet.wrapper.ServletRequest; -import com.blade.servlet.wrapper.ServletResponse; +import com.blade.web.http.HttpStatus; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.ServletRequest; +import com.blade.web.http.wrapper.ServletResponse; /** * 异步请求处理器 diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index 2727ee86b..8784f67c1 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -16,16 +16,16 @@ import com.blade.Blade; import com.blade.Const; import com.blade.context.BladeWebContext; -import com.blade.http.HttpStatus; -import com.blade.http.Path; -import com.blade.http.Request; -import com.blade.http.Response; import com.blade.render.ModelAndView; import com.blade.route.Route; import com.blade.route.RouteHandler; import com.blade.route.RouteMatcher; -import com.blade.servlet.wrapper.ServletRequest; -import com.blade.servlet.wrapper.ServletResponse; +import com.blade.web.http.HttpStatus; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.ServletRequest; +import com.blade.web.http.wrapper.ServletResponse; /** * 同步请求处理器 diff --git a/blade-core/src/main/java/com/blade/http/HttpException.java b/blade-core/src/main/java/com/blade/web/http/HttpException.java similarity index 93% rename from blade-core/src/main/java/com/blade/http/HttpException.java rename to blade-core/src/main/java/com/blade/web/http/HttpException.java index 300efe9af..a3976f1e8 100644 --- a/blade-core/src/main/java/com/blade/http/HttpException.java +++ b/blade-core/src/main/java/com/blade/web/http/HttpException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.http; +package com.blade.web.http; /** * diff --git a/blade-core/src/main/java/com/blade/http/HttpMethod.java b/blade-core/src/main/java/com/blade/web/http/HttpMethod.java similarity index 96% rename from blade-core/src/main/java/com/blade/http/HttpMethod.java rename to blade-core/src/main/java/com/blade/web/http/HttpMethod.java index 9cdca8dbf..6609cead2 100644 --- a/blade-core/src/main/java/com/blade/http/HttpMethod.java +++ b/blade-core/src/main/java/com/blade/web/http/HttpMethod.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.http; +package com.blade.web.http; /** *

diff --git a/blade-core/src/main/java/com/blade/http/HttpStatus.java b/blade-core/src/main/java/com/blade/web/http/HttpStatus.java similarity index 95% rename from blade-core/src/main/java/com/blade/http/HttpStatus.java rename to blade-core/src/main/java/com/blade/web/http/HttpStatus.java index 85f18b158..150ae1c0a 100644 --- a/blade-core/src/main/java/com/blade/http/HttpStatus.java +++ b/blade-core/src/main/java/com/blade/web/http/HttpStatus.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.http; +package com.blade.web.http; /** * diff --git a/blade-core/src/main/java/com/blade/http/Path.java b/blade-core/src/main/java/com/blade/web/http/Path.java similarity index 95% rename from blade-core/src/main/java/com/blade/http/Path.java rename to blade-core/src/main/java/com/blade/web/http/Path.java index 11bfb209d..67fe203dc 100644 --- a/blade-core/src/main/java/com/blade/http/Path.java +++ b/blade-core/src/main/java/com/blade/web/http/Path.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.http; +package com.blade.web.http; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; diff --git a/blade-core/src/main/java/com/blade/http/Request.java b/blade-core/src/main/java/com/blade/web/http/Request.java similarity index 93% rename from blade-core/src/main/java/com/blade/http/Request.java rename to blade-core/src/main/java/com/blade/web/http/Request.java index 82f321c89..0466caab9 100644 --- a/blade-core/src/main/java/com/blade/http/Request.java +++ b/blade-core/src/main/java/com/blade/web/http/Request.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.http; +package com.blade.web.http; import java.io.InputStream; import java.util.Map; @@ -24,8 +24,8 @@ import javax.servlet.http.HttpServletRequest; import com.blade.route.Route; -import com.blade.servlet.multipart.FileItem; -import com.blade.servlet.wrapper.Session; +import com.blade.web.http.wrapper.Session; +import com.blade.web.multipart.FileItem; /** * diff --git a/blade-core/src/main/java/com/blade/http/Response.java b/blade-core/src/main/java/com/blade/web/http/Response.java similarity index 98% rename from blade-core/src/main/java/com/blade/http/Response.java rename to blade-core/src/main/java/com/blade/web/http/Response.java index a808d496d..0bc35e7bc 100644 --- a/blade-core/src/main/java/com/blade/http/Response.java +++ b/blade-core/src/main/java/com/blade/web/http/Response.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.http; +package com.blade.web.http; import java.io.IOException; import java.io.OutputStream; diff --git a/blade-core/src/main/java/com/blade/http/package-info.java b/blade-core/src/main/java/com/blade/web/http/package-info.java similarity index 57% rename from blade-core/src/main/java/com/blade/http/package-info.java rename to blade-core/src/main/java/com/blade/web/http/package-info.java index 3ebeb38eb..815e36c39 100644 --- a/blade-core/src/main/java/com/blade/http/package-info.java +++ b/blade-core/src/main/java/com/blade/web/http/package-info.java @@ -1,4 +1,4 @@ /** * Request、Response接口 */ -package com.blade.http; \ No newline at end of file +package com.blade.web.http; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java similarity index 93% rename from blade-core/src/main/java/com/blade/servlet/wrapper/ServletRequest.java rename to blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index c07c3928b..d20c0a428 100644 --- a/blade-core/src/main/java/com/blade/servlet/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.servlet.wrapper; +package com.blade.web.http.wrapper; import java.io.BufferedReader; import java.io.IOException; @@ -37,15 +37,15 @@ import javax.servlet.http.HttpSession; import com.blade.Blade; -import com.blade.http.HttpException; -import com.blade.http.HttpMethod; -import com.blade.http.Path; -import com.blade.http.Request; import com.blade.route.Route; -import com.blade.servlet.multipart.FileItem; -import com.blade.servlet.multipart.Multipart; -import com.blade.servlet.multipart.MultipartException; -import com.blade.servlet.multipart.MultipartHandler; +import com.blade.web.http.HttpException; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.multipart.FileItem; +import com.blade.web.multipart.Multipart; +import com.blade.web.multipart.MultipartException; +import com.blade.web.multipart.MultipartHandler; import blade.kit.IOKit; import blade.kit.text.HTMLFilter; diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java similarity index 93% rename from blade-core/src/main/java/com/blade/servlet/wrapper/ServletResponse.java rename to blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index d87d8c6db..bfade886a 100644 --- a/blade-core/src/main/java/com/blade/servlet/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.servlet.wrapper; +package com.blade.web.http.wrapper; import java.io.IOException; import java.io.PrintWriter; @@ -27,13 +27,13 @@ import com.blade.Blade; import com.blade.context.BladeWebContext; -import com.blade.http.HttpException; -import com.blade.http.HttpStatus; -import com.blade.http.Path; -import com.blade.http.Request; -import com.blade.http.Response; import com.blade.render.ModelAndView; import com.blade.render.Render; +import com.blade.web.http.HttpException; +import com.blade.web.http.HttpStatus; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.http.Response; import blade.kit.Assert; diff --git a/blade-core/src/main/java/com/blade/servlet/wrapper/Session.java b/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java similarity index 98% rename from blade-core/src/main/java/com/blade/servlet/wrapper/Session.java rename to blade-core/src/main/java/com/blade/web/http/wrapper/Session.java index 2c55a0653..1ecb62536 100644 --- a/blade-core/src/main/java/com/blade/servlet/wrapper/Session.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.servlet.wrapper; +package com.blade.web.http.wrapper; import java.util.Enumeration; import java.util.Set; diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java b/blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java new file mode 100644 index 000000000..4103de3c5 --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java @@ -0,0 +1,4 @@ +/** + * Servlet封装 + */ +package com.blade.web.http.wrapper; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java b/blade-core/src/main/java/com/blade/web/multipart/FileItem.java similarity index 93% rename from blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java rename to blade-core/src/main/java/com/blade/web/multipart/FileItem.java index effbb6b01..804c923a0 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/FileItem.java +++ b/blade-core/src/main/java/com/blade/web/multipart/FileItem.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.servlet.multipart; +package com.blade.web.multipart; import java.io.File; import java.util.HashMap; diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java b/blade-core/src/main/java/com/blade/web/multipart/Multipart.java similarity index 96% rename from blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java rename to blade-core/src/main/java/com/blade/web/multipart/Multipart.java index 36497c56c..713155867 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/Multipart.java +++ b/blade-core/src/main/java/com/blade/web/multipart/Multipart.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.servlet.multipart; +package com.blade.web.multipart; import java.io.File; import java.io.FileOutputStream; diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java b/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java similarity index 96% rename from blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java rename to blade-core/src/main/java/com/blade/web/multipart/MultipartException.java index 931ac1c20..070d76809 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartException.java +++ b/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.servlet.multipart; +package com.blade.web.multipart; /** * diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java b/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java similarity index 96% rename from blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java rename to blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java index caebf48b4..feef0012c 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartHandler.java +++ b/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.servlet.multipart; +package com.blade.web.multipart; /** * diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java b/blade-core/src/main/java/com/blade/web/multipart/MultipartReader.java similarity index 99% rename from blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java rename to blade-core/src/main/java/com/blade/web/multipart/MultipartReader.java index 47ad9c953..31fe33c59 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/MultipartReader.java +++ b/blade-core/src/main/java/com/blade/web/multipart/MultipartReader.java @@ -10,7 +10,7 @@ * 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.blade.servlet.multipart; +package com.blade.web.multipart; import java.io.ByteArrayOutputStream; import java.io.Closeable; diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/ParameterParser.java b/blade-core/src/main/java/com/blade/web/multipart/ParameterParser.java similarity index 99% rename from blade-core/src/main/java/com/blade/servlet/multipart/ParameterParser.java rename to blade-core/src/main/java/com/blade/web/multipart/ParameterParser.java index 6829d5028..a92bcab65 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/ParameterParser.java +++ b/blade-core/src/main/java/com/blade/web/multipart/ParameterParser.java @@ -10,7 +10,7 @@ * 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.blade.servlet.multipart; +package com.blade.web.multipart; import java.util.HashMap; import java.util.Map; diff --git a/blade-core/src/main/java/com/blade/servlet/multipart/Streams.java b/blade-core/src/main/java/com/blade/web/multipart/Streams.java similarity index 99% rename from blade-core/src/main/java/com/blade/servlet/multipart/Streams.java rename to blade-core/src/main/java/com/blade/web/multipart/Streams.java index 70ffb3d5b..09b3875e1 100644 --- a/blade-core/src/main/java/com/blade/servlet/multipart/Streams.java +++ b/blade-core/src/main/java/com/blade/web/multipart/Streams.java @@ -10,7 +10,7 @@ * 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.blade.servlet.multipart; +package com.blade.web.multipart; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/blade-core/src/main/java/com/blade/web/multipart/package-info.java b/blade-core/src/main/java/com/blade/web/multipart/package-info.java new file mode 100644 index 000000000..7b3ab0ee0 --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/multipart/package-info.java @@ -0,0 +1,4 @@ +/** + * Multipart处理 + */ +package com.blade.web.multipart; \ No newline at end of file From f94aaf1491b8b7f66e5c900a44b5be2ee201bf30 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 9 Dec 2015 17:49:41 +0800 Subject: [PATCH 299/545] move to 1.5.0 --- blade-core/src/main/java/com/blade/Blade.java | 10 ++- .../main/java/com/blade/IocApplication.java | 29 ++++---- .../main/java/com/blade/ioc/Container.java | 15 ----- .../java/com/blade/ioc/SampleContainer.java | 66 +++++++------------ .../java/com/blade/route/RouteBuilder.java | 5 +- .../java/com/blade/route/RouteMatcher.java | 6 +- .../java/com/blade/web/AppAsyncListener.java | 19 +++--- .../java/com/blade/web/DispatcherServlet.java | 10 +-- .../com/blade/web/SyncRequestHandler.java | 17 ++--- pom.xml | 2 +- 10 files changed, 72 insertions(+), 107 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 18136af14..cb375af85 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -531,7 +531,7 @@ public Blade app(Bootstrap bootstrap){ * @return 返回Blade单例实例 */ public Blade app(Class bootstrap){ - Object object = container.registerBean(bootstrap); + Object object = container.registerBean(Aop.create(bootstrap)); this.bootstrap = (Bootstrap) object; return this; } @@ -796,6 +796,14 @@ public Blade routeConf(String basePackage, String conf) { public IocApplication iocApplication(){ return iocApplication; } + + /** + * @return 返回IocApplication对象 + */ + public Blade iocInit(){ + iocApplication.init(container, iocs(), bootstrap); + return this; + } /** * @return 返回是否已经初始化 diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index 93ed4323d..051b15ed1 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -73,8 +73,12 @@ public void init(Container container, String[] iocs, Bootstrap bootstrap){ container.registerBean(bootstrap); } - // 初始化ioc容器 - initIOC(iocs); + // 初始化ioc容器,加载ioc包的对象 要配置符合ioc的注解的类才会被加载 + if(null != iocs && iocs.length > 0){ + for(String packageName : iocs){ + registerBean(packageName); + } + } // 初始化注入 container.initWired(); @@ -86,22 +90,9 @@ public void init(Container container, String[] iocs, Bootstrap bootstrap){ } - /** - * 初始化IOC容器,加载ioc包的对象 - * 要配置符合ioc的注解的类才会被加载 - * - */ - private void initIOC(String[] iocPackages) { - if(null != iocPackages && iocPackages.length > 0){ - for(String packageName : iocPackages){ - registerBean(packageName); - } - } - } - @SuppressWarnings("unchecked") public T registerPlugin(Class plugin){ - Object object = container.registerBean(plugin); + Object object = container.registerBean(Aop.create(plugin)); T t = (T) object; plugins.add(t); return t; @@ -130,10 +121,14 @@ private void registerBean(String packageName) { for (Class clazz : classes) { // 注册带有Component和Service注解的类 if (container.isRegister(clazz.getAnnotations())) { - container.registerBean(clazz); + container.registerBean(Aop.create(clazz)); } } } + + public List getPlugins() { + return plugins; + } /** * 销毁 diff --git a/blade-core/src/main/java/com/blade/ioc/Container.java b/blade-core/src/main/java/com/blade/ioc/Container.java index 002fb5839..8b50813f7 100644 --- a/blade-core/src/main/java/com/blade/ioc/Container.java +++ b/blade-core/src/main/java/com/blade/ioc/Container.java @@ -122,14 +122,6 @@ public interface Container { */ boolean isRegister(Annotation[] annotations); - /** - * 注册一个class类型的bean到容器中 - * - * @param clazz 要注册的class类型 - * @return 返回注册后的bean对象 - */ - Object registerBean(Class clazz); - /** * 注册一个代名称的Bean * @param name bean名称 @@ -146,13 +138,6 @@ public interface Container { */ Object registerBean(Object object); - /** - * 注册一个class集合进入ioc容器 - * - * @param classes 要注册的class集合 - */ - void registerBean(Set> classes); - /** * 初始化IOC */ diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java index 4ed4d906c..75ac7df29 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -19,10 +19,8 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Collection; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import blade.exception.BladeException; @@ -31,7 +29,6 @@ import blade.kit.StringKit; import blade.kit.log.Logger; -import com.blade.Aop; import com.blade.annotation.Component; import com.blade.annotation.Inject; import com.blade.annotation.Path; @@ -136,26 +133,6 @@ public boolean removeBean(Class clazz) { return this.removeBean(clazz.getName()); } - /** - * 注册一个bean对象到容器里 - * - * @param clazz 要注册的class - * @return 返回注册后的bean对象 - */ - @Override - public Object registerBean(Class clazz) { - - String name = clazz.getName(); - Object object = null; - - //非抽象类、接口 - if (isNormalClass(clazz)) { - object = Aop.create(clazz); - return registerBean(name, object); - } - return object; - } - @Override public Object registerBean(String name, Object value) { Class clazz = value.getClass(); @@ -178,7 +155,8 @@ public Object registerBean(String name, Object value) { Class[] interfaces = clazz.getInterfaces(); if(interfaces.length > 0){ for(Class interfaceClazz : interfaces){ - this.registerBean(interfaceClazz.getName(), value); + String clsName = interfaceClazz.getName(); + this.registerParent(clsName, value); } } @@ -190,6 +168,21 @@ public Object registerBean(String name, Object value) { return value; } + private void registerParent(String name, Object value) { + Class clazz = value.getClass(); + + // 如果容器已经存在该名称对于的对象,直接返回 + String className = beanKeys.get(name); + if (StringKit.isNotBlank(className)) { + return; + } + className = clazz.getName(); + beanKeys.put(name, className); + if(null == beans.get(className)){ + beans.put(className, value); + } + } + @Override public Object registerBean(Object object) { String className = object.getClass().getName(); @@ -234,21 +227,20 @@ private void put(Class clazz, List listObject){ */ @Override public void initWired() throws RuntimeException { - Iterator> it = beans.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - Object object = entry.getValue(); + + Set keys = beans.keySet(); + for(String className : keys){ + Object object = beans.get(className); injection(object); - } + } } // 装配 private Object recursiveAssembly(Class clazz){ Object field = null; if(null != clazz){ - if(!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())){ - field = this.registerBean(clazz); - } + String className = beanKeys.get(clazz.getName()); + field = beans.get(className); } return field; } @@ -303,15 +295,6 @@ public List getBeansByAnnotation(Class annotation) return (List) annotaionBeans.get(annotation); } - @Override - public void registerBean(Set> classes) { - if(!CollectionKit.isEmpty(classes)){ - for(Class clazz : classes){ - this.registerBean(clazz); - } - } - } - @Override public boolean removeAll() { beanKeys.clear(); @@ -329,7 +312,6 @@ public void injection(Object object) { // 需要注入的字段 Inject inject = field.getAnnotation(Inject.class); if (null != inject ) { - // 要注入的字段 Object injectField = null; String name = inject.name(); diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index 08770e739..e35a57a44 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -22,6 +22,7 @@ import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; +import com.blade.Aop; import com.blade.Blade; import com.blade.annotation.After; import com.blade.annotation.Before; @@ -177,7 +178,7 @@ private void parseInterceptor(final Class interceptor){ return; } - container.registerBean(interceptor); + container.registerBean(Aop.create(interceptor)); for (Method method : methods) { @@ -232,7 +233,7 @@ private void parseRouter(final Class router){ return; } - container.registerBean(router); + container.registerBean(Aop.create(router)); final String nameSpace = router.getAnnotation(Path.class).value(); diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java index be807cc3f..44b06beef 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcher.java @@ -49,9 +49,9 @@ public class RouteMatcher { private Set routeKeys = null; private List interceptorRoutes = new ArrayList(); - public RouteMatcher(Routers router) { - this.routes = router.getRoutes(); - this.interceptors = router.getInterceptors(); + public RouteMatcher(Routers routers) { + this.routes = routers.getRoutes(); + this.interceptors = routers.getInterceptors(); this.routeKeys = routes.keySet(); Collection inters = interceptors.values(); if (null != inters && inters.size() > 0) { diff --git a/blade-core/src/main/java/com/blade/web/AppAsyncListener.java b/blade-core/src/main/java/com/blade/web/AppAsyncListener.java index c56e85988..79bfbc69e 100644 --- a/blade-core/src/main/java/com/blade/web/AppAsyncListener.java +++ b/blade-core/src/main/java/com/blade/web/AppAsyncListener.java @@ -1,11 +1,9 @@ package com.blade.web; import java.io.IOException; -import java.io.PrintWriter; - + import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; -import javax.servlet.ServletResponse; import javax.servlet.annotation.WebListener; @WebListener @@ -13,26 +11,25 @@ public class AppAsyncListener implements AsyncListener { @Override public void onComplete(AsyncEvent asyncEvent) throws IOException { - System.out.println("AppAsyncListener onComplete"); +// System.out.println("AppAsyncListener onComplete"); } @Override public void onError(AsyncEvent asyncEvent) throws IOException { - System.out.println("AppAsyncListener onError"); +// System.out.println("AppAsyncListener onError"); } @Override public void onStartAsync(AsyncEvent asyncEvent) throws IOException { - System.out.println("AppAsyncListener onStartAsync"); +// System.out.println("AppAsyncListener onStartAsync"); } @Override public void onTimeout(AsyncEvent asyncEvent) throws IOException { - System.out.println("AppAsyncListener onTimeout"); - //we can send appropriate response to client - ServletResponse response = asyncEvent.getAsyncContext().getResponse(); - PrintWriter out = response.getWriter(); - out.write("TimeOut Error in Processing"); +// System.out.println("AppAsyncListener onTimeout"); +// ServletResponse response = asyncEvent.getAsyncContext().getResponse(); +// PrintWriter out = response.getWriter(); +// out.write("TimeOut Error in Processing"); } } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index ad2f6c8cf..bd5468a7f 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -54,6 +54,8 @@ public class DispatcherServlet extends HttpServlet { private ServletContext servletContext; + private SyncRequestHandler syncRequestHandler; + public DispatcherServlet() { } @@ -85,13 +87,14 @@ public void init(Blade blade) { new RouteBuilder(blade).building(); // 初始化IOC - blade.iocApplication().init(blade.container(), blade.iocs(), bootstrap); + blade.iocInit(); +// blade.iocApplication().init(blade.container(), blade.iocs(), bootstrap); blade.bootstrap().contextInitialized(blade); servletContext = config.getServletContext(); - SyncRequestHandler.routeMatcher = new RouteMatcher(blade.routers()); + syncRequestHandler = new SyncRequestHandler(servletContext, blade.routers()); AsynRequestHandler.routeMatcher = new RouteMatcher(blade.routers()); blade.setInit(true); @@ -105,7 +108,6 @@ protected void service(HttpServletRequest httpRequest, HttpServletResponse httpR httpResponse.setCharacterEncoding(blade.encoding()); boolean isAsync = httpRequest.isAsyncSupported(); - System.out.println("isAsync = "+isAsync); if (isAsync) { AsyncContext asyncCtx = httpRequest.startAsync(); asyncCtx.addListener(new AppAsyncListener()); @@ -115,7 +117,7 @@ protected void service(HttpServletRequest httpRequest, HttpServletResponse httpR executor.execute(new AsynRequestHandler(servletContext, asyncCtx)); // asyncCtx.start(new AsynRequestHandler(blade, servletContext, asyncCtx)); } else { - new SyncRequestHandler(servletContext, httpRequest, httpResponse).run(); + syncRequestHandler.handle(httpRequest, httpResponse); } } diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index 8784f67c1..33578a306 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -20,6 +20,7 @@ import com.blade.route.Route; import com.blade.route.RouteHandler; import com.blade.route.RouteMatcher; +import com.blade.route.Routers; import com.blade.web.http.HttpStatus; import com.blade.web.http.Path; import com.blade.web.http.Request; @@ -31,7 +32,7 @@ * 同步请求处理器 * @author biezhi */ -public class SyncRequestHandler implements Runnable { +public class SyncRequestHandler { private static final Logger LOGGER = Logger.getLogger(SyncRequestHandler.class); @@ -39,20 +40,14 @@ public class SyncRequestHandler implements Runnable { private ServletContext servletContext; - static RouteMatcher routeMatcher; + private RouteMatcher routeMatcher; - private HttpServletRequest httpRequest; - - private HttpServletResponse httpResponse; - - public SyncRequestHandler(ServletContext servletContext, HttpServletRequest httpRequest, HttpServletResponse httpResponse) { + public SyncRequestHandler(ServletContext servletContext, Routers routers) { this.servletContext = servletContext; - this.httpRequest = httpRequest; - this.httpResponse = httpResponse; + this.routeMatcher = new RouteMatcher(routers); } - @Override - public void run(){ + public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ Response response = null; try { diff --git a/pom.xml b/pom.xml index c580f8c5c..bccb56dea 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.4.3-alpha + 1.5.0-alpha 4.12 From cab66452c886ab12658dd6e5a93b7b64f57bcfc2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 9 Dec 2015 17:50:35 +0800 Subject: [PATCH 300/545] update log --- UPDATE_LOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index f2d69dba8..89e1f1f0c 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,7 +1,9 @@ # Blade 更新日志 -### v1.4.2 +### v1.5.0 1. 优化路由寻址算法 + 2. 分离同步和异步请求 + 3. 优化IOC ### v1.4.1 1. 去除过度设计 From 2b0377ab975893e6cabcee5cc13403c4217b2bf4 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 9 Dec 2015 18:04:10 +0800 Subject: [PATCH 301/545] update oauth2 to blade-1.5.0 --- .../src/main/java/com/blade/oauth2/OAuthRequest.java | 2 +- .../src/main/java/com/blade/oauth2/OAuthResponse.java | 4 ++-- .../java/com/blade/oauth2/base/request/OAuthBaseRequest.java | 2 +- .../com/blade/oauth2/base/request/OAuthTokenBaseRequest.java | 2 +- .../com/blade/oauth2/base/validator/OAuthBaseValidator.java | 2 +- .../java/com/blade/oauth2/base/validator/OAuthValidator.java | 2 +- .../src/main/java/com/blade/oauth2/kit/OAuthKit.java | 2 +- .../java/com/blade/oauth2/request/OAuthGrantRequest.java | 2 +- .../main/java/com/blade/oauth2/response/OAuthASResponse.java | 5 ++--- .../blade/oauth2/validator/AuthorizationCodeValidator.java | 2 +- .../com/blade/oauth2/validator/AuthorizationValidator.java | 2 +- .../blade/oauth2/validator/ClientCredentialValidator.java | 2 +- .../com/blade/oauth2/validator/ImplicitCodeValidator.java | 2 +- .../blade/oauth2/validator/PasswordCredentialValidator.java | 2 +- .../com/blade/oauth2/validator/RefreshTokenValidator.java | 2 +- 15 files changed, 17 insertions(+), 18 deletions(-) diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java index a9414e375..0dea01987 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java @@ -6,7 +6,6 @@ import blade.kit.StringKit; import com.blade.Aop; -import com.blade.http.Request; import com.blade.oauth2.base.request.OAuthBaseRequest; import com.blade.oauth2.base.validator.OAuthValidator; import com.blade.oauth2.exception.OAuthProblemException; @@ -14,6 +13,7 @@ import com.blade.oauth2.message.types.ResponseType; import com.blade.oauth2.validator.AuthorizationValidator; import com.blade.oauth2.validator.ImplicitCodeValidator; +import com.blade.web.http.Request; /** * diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java index 91be98322..42573497b 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java @@ -5,11 +5,11 @@ import blade.kit.StringKit; -import com.blade.http.HttpStatus; -import com.blade.http.Request; import com.blade.oauth2.exception.OAuthProblemException; import com.blade.oauth2.message.OAuthMessage; import com.blade.oauth2.parameters.JSONBodyParametersApplier; +import com.blade.web.http.HttpStatus; +import com.blade.web.http.Request; /** * diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java index 299b0d066..c8c43fce6 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java @@ -8,11 +8,11 @@ import java.util.Map; import java.util.Set; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.base.validator.OAuthValidator; import com.blade.oauth2.exception.OAuthProblemException; import com.blade.oauth2.kit.OAuthKit; +import com.blade.web.http.Request; /** * The Abstract OAuth request for the Authorization server. diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java index 58689f867..131fd9e83 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java @@ -7,11 +7,11 @@ import blade.kit.StringKit; import com.blade.Aop; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.base.validator.OAuthValidator; import com.blade.oauth2.exception.OAuthProblemException; import com.blade.oauth2.kit.OAuthKit; +import com.blade.web.http.Request; /** * Abstract OAuth Token request class diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java index f9d8fdc3c..c2b75f417 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java @@ -12,10 +12,10 @@ import blade.kit.StringKit; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.exception.OAuthProblemException; import com.blade.oauth2.kit.OAuthKit; +import com.blade.web.http.Request; /** * diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java index 469f467ac..c875ec4ce 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java @@ -2,8 +2,8 @@ */ package com.blade.oauth2.base.validator; -import com.blade.http.Request; import com.blade.oauth2.exception.OAuthProblemException; +import com.blade.web.http.Request; /** * diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java b/blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java index ebb651b57..7e5e1df56 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java @@ -24,10 +24,10 @@ import blade.kit.Base64; import blade.kit.StringKit; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.OAuthError; import com.blade.oauth2.exception.OAuthProblemException; +import com.blade.web.http.Request; /** * Common OAuth Utils class. diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java index b46259220..3a1e2a180 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java @@ -4,7 +4,6 @@ package com.blade.oauth2.request; -import com.blade.http.Request; import com.blade.oauth2.base.request.OAuthTokenBaseRequest; import com.blade.oauth2.base.validator.OAuthValidator; import com.blade.oauth2.exception.OAuthProblemException; @@ -13,6 +12,7 @@ import com.blade.oauth2.validator.ClientCredentialValidator; import com.blade.oauth2.validator.PasswordCredentialValidator; import com.blade.oauth2.validator.RefreshTokenValidator; +import com.blade.web.http.Request; /** diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java b/blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java index 7550abff8..b166502aa 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java @@ -5,12 +5,11 @@ package com.blade.oauth2.response; -import com.blade.http.HttpStatus; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.OAuthResponse; -import com.blade.oauth2.OAuthResponse.OAuthResponseBuilder; import com.blade.oauth2.message.types.TokenType; +import com.blade.web.http.HttpStatus; +import com.blade.web.http.Request; /** * diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java index eed723647..848edf48f 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java @@ -3,9 +3,9 @@ */ package com.blade.oauth2.validator; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.base.validator.OAuthBaseValidator; +import com.blade.web.http.Request; /** * Validator that checks for the required fields in an OAuth Token request with the Authorization Code grant type. diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java index 238c1f4e8..7bcb74ae6 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java @@ -122,11 +122,11 @@ an authorization decision (by asking the resource owner or by */ package com.blade.oauth2.validator; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.OAuthError; import com.blade.oauth2.base.validator.OAuthBaseValidator; import com.blade.oauth2.exception.OAuthProblemException; +import com.blade.web.http.Request; /** * Authorization Code Grant diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java index 378e6faf7..62cf8b5a5 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java @@ -32,9 +32,9 @@ arranged with the authorization server (the method of which is beyond */ package com.blade.oauth2.validator; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.base.validator.OAuthBaseValidator; +import com.blade.web.http.Request; /** * Client Credentials Grant diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java index 6578f93b9..f61596412 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java @@ -153,11 +153,11 @@ resource owner and obtains an authorization decision (by asking the package com.blade.oauth2.validator; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.OAuthError; import com.blade.oauth2.base.validator.OAuthBaseValidator; import com.blade.oauth2.exception.OAuthProblemException; +import com.blade.web.http.Request; /** diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java index cab2c17f4..c35fea1a2 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java @@ -102,9 +102,9 @@ brute force attacks (e.g., using rate-limitation or generating */ package com.blade.oauth2.validator; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.base.validator.OAuthBaseValidator; +import com.blade.web.http.Request; /** * Resource Owner Password Credentials Grant diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java index 89cee6e64..e2b403561 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java @@ -65,9 +65,9 @@ client that was issued client credentials (or with other */ package com.blade.oauth2.validator; -import com.blade.http.Request; import com.blade.oauth2.OAuth; import com.blade.oauth2.base.validator.OAuthBaseValidator; +import com.blade.web.http.Request; /** * Validator that checks for the required fields in an OAuth Token request with the Refresh token grant type. From 14b62a3f834affc61080e7e1928eba39264268c9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 9 Dec 2015 18:10:30 +0800 Subject: [PATCH 302/545] update version --- LAST_VERSION.md | 11 ++++++++++- blade-oauth2/pom.xml | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 5ddd2c5c7..a8638b3fe 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.4.3-alpha +    1.5.0-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -80,3 +80,12 @@     1.0.0 ``` + +## [blade-oauth2](http://search.maven.org/#search%7Cga%7C1%7Cblade-oauth2) +```xml + +    com.bladejava +    blade-oauth2 +    1.0.1 + +``` diff --git a/blade-oauth2/pom.xml b/blade-oauth2/pom.xml index 0775fbaf7..732c0d88f 100644 --- a/blade-oauth2/pom.xml +++ b/blade-oauth2/pom.xml @@ -9,7 +9,7 @@ 1.0 blade-oauth2 - 1.0.0 + 1.0.1 blade-oauth2 https://github.com/biezhi/blade/tree/master/blade-oauth2 From 9a1e94610e2ced57499d524278bf5c2f0a22cf8a Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 9 Dec 2015 18:17:25 +0800 Subject: [PATCH 303/545] update blade-patchca!!! --- LAST_VERSION.md | 2 +- blade-patchca/pom.xml | 2 +- .../src/main/java/com/blade/patchca/PatchcaService.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index a8638b3fe..e0aa13253 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -77,7 +77,7 @@     com.bladejava     blade-patchca -    1.0.0 +    1.0.1 ``` diff --git a/blade-patchca/pom.xml b/blade-patchca/pom.xml index 134d3adbe..4832dbeb1 100644 --- a/blade-patchca/pom.xml +++ b/blade-patchca/pom.xml @@ -9,7 +9,7 @@ 1.0 blade-patchca - 1.0.0 + 1.0.1 blade-patchca https://github.com/biezhi/blade/tree/master/blade-patchca diff --git a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java index 688990304..1b88eaf3b 100644 --- a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java +++ b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java @@ -17,8 +17,8 @@ import blade.kit.log.Logger; -import com.blade.http.Response; -import com.blade.servlet.wrapper.Session; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.Session; /** * PatchcaService From 62e72b66f9b4e4239b27514d1e629b98cbfa636d Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 9 Dec 2015 18:49:31 +0800 Subject: [PATCH 304/545] remove context listener --- .../main/java/com/blade/server/Server.java | 2 -- .../com/blade/web/AppContextListener.java | 27 ------------------- .../java/com/blade/web/DispatcherServlet.java | 8 +----- 3 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/web/AppContextListener.java diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java index 7ee9db3e6..039b880e9 100644 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -20,7 +20,6 @@ import blade.kit.log.Logger; -import com.blade.web.AppContextListener; import com.blade.web.DispatcherServlet; /** @@ -64,7 +63,6 @@ public void start(String contextPath) throws Exception{ context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath(contextPath); context.setResourceBase(System.getProperty("java.io.tmpdir")); - context.addEventListener(new AppContextListener()); ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); servletHolder.setAsyncSupported(async); diff --git a/blade-core/src/main/java/com/blade/web/AppContextListener.java b/blade-core/src/main/java/com/blade/web/AppContextListener.java deleted file mode 100644 index 49d452aba..000000000 --- a/blade-core/src/main/java/com/blade/web/AppContextListener.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.blade.web; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - - -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.annotation.WebListener; - -import com.blade.Const; - -@WebListener -public class AppContextListener implements ServletContextListener { - - public void contextInitialized(ServletContextEvent servletContextEvent) { - // create the thread pool - ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 200, 50000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(100)); - servletContextEvent.getServletContext().setAttribute(Const.BLADE_EXECUTOR, executor); - } - - public void contextDestroyed(ServletContextEvent servletContextEvent) { - ThreadPoolExecutor executor = (ThreadPoolExecutor) servletContextEvent.getServletContext().getAttribute("blade-executor"); - executor.shutdown(); - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index bd5468a7f..9405c660b 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -16,7 +16,6 @@ package com.blade.web; import java.io.IOException; -import java.util.concurrent.ThreadPoolExecutor; import javax.servlet.AsyncContext; import javax.servlet.ServletConfig; @@ -32,7 +31,6 @@ import com.blade.Aop; import com.blade.Blade; import com.blade.Bootstrap; -import com.blade.Const; import com.blade.route.RouteBuilder; import com.blade.route.RouteMatcher; @@ -88,7 +86,6 @@ public void init(Blade blade) { // 初始化IOC blade.iocInit(); -// blade.iocApplication().init(blade.container(), blade.iocs(), bootstrap); blade.bootstrap().contextInitialized(blade); @@ -112,10 +109,7 @@ protected void service(HttpServletRequest httpRequest, HttpServletResponse httpR AsyncContext asyncCtx = httpRequest.startAsync(); asyncCtx.addListener(new AppAsyncListener()); asyncCtx.setTimeout(10000L); - - ThreadPoolExecutor executor = (ThreadPoolExecutor) servletContext.getAttribute(Const.BLADE_EXECUTOR); - executor.execute(new AsynRequestHandler(servletContext, asyncCtx)); -// asyncCtx.start(new AsynRequestHandler(blade, servletContext, asyncCtx)); + asyncCtx.start(new AsynRequestHandler(servletContext, asyncCtx)); } else { syncRequestHandler.handle(httpRequest, httpResponse); } From 3a763b5192426d472d76e67fe328e5001bb5593b Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 10 Dec 2015 18:43:56 +0800 Subject: [PATCH 305/545] fix ioc init bug --- blade-core/src/main/java/com/blade/Blade.java | 12 ++++++------ .../src/main/java/com/blade/IocApplication.java | 11 +++++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index cb375af85..f24378ac0 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -64,11 +64,6 @@ public class Blade { */ private Bootstrap bootstrap = null; - /** - * ioc全局对象 - */ - private IocApplication iocApplication = new IocApplication(); - /** * 全局配置对象 */ @@ -79,6 +74,11 @@ public class Blade { */ private Container container = new SampleContainer(); + /** + * ioc全局对象 + */ + private IocApplication iocApplication = new IocApplication(container); + /** * 默认JSP渲染 */ @@ -801,7 +801,7 @@ public IocApplication iocApplication(){ * @return 返回IocApplication对象 */ public Blade iocInit(){ - iocApplication.init(container, iocs(), bootstrap); + iocApplication.init(iocs(), bootstrap); return this; } diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index 051b15ed1..e69317203 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -55,9 +55,10 @@ public class IocApplication { */ private List plugins = null; - public IocApplication() { + public IocApplication(Container container) { this.classReader = new ClassPathClassReader(); this.plugins = new ArrayList(); + this.container = container; } /** @@ -65,8 +66,7 @@ public IocApplication() { * * @param blade Blade实例 */ - public void init(Container container, String[] iocs, Bootstrap bootstrap){ - this.container = container; + public void init(String[] iocs, Bootstrap bootstrap){ // 初始化全局配置类 if(null == container.getBean(Bootstrap.class, Scope.SINGLE)){ @@ -99,7 +99,10 @@ public T registerPlugin(Class plugin){ } public T getPlugin(Class plugin){ - return container.getBean(plugin, Scope.SINGLE); + if(null != plugin && null != container){ + return container.getBean(plugin, null); + } + return null; } /** From aa1d3d133ad76e24d328962f0954408d38ef3081 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 13:21:28 +0800 Subject: [PATCH 306/545] injection route parameters extraction --- .../com/blade/web/AsynRequestHandler.java | 51 +----------- .../java/com/blade/web/RouteArgument.java | 83 +++++++++++++++++++ .../com/blade/web/SyncRequestHandler.java | 48 +---------- 3 files changed, 86 insertions(+), 96 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/web/RouteArgument.java diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index ee8cdd45a..0a89cbf6a 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -9,7 +9,6 @@ import javax.servlet.http.HttpServletResponse; import blade.exception.BladeException; -import blade.kit.ReflectKit; import blade.kit.StringKit; import blade.kit.base.ThrowableKit; import blade.kit.log.Logger; @@ -192,56 +191,10 @@ private void handle(Request request, Response response, Route route){ // 要执行的路由方法 Method actionMethod = route.getAction(); // 执行route方法 - executeMethod(target, actionMethod, request, response); + RouteArgument.executeMethod(target, actionMethod, request, response, route); } } - - /** - * 获取方法内的参数 - * - * @param request Request对象,用于注入到method参数列表中 - * @param response Response对象,用于注入到method参数列表中 - * @param params params参数列表 - * @return 返回生成后的参数数组 - */ - private Object[] getArgs(Request request, Response response, Class[] params){ - - int len = params.length; - Object[] args = new Object[len]; - - for(int i=0; i paramTypeClazz = params[i]; - if(paramTypeClazz.getName().equals(Request.class.getName())){ - args[i] = request; - } - if(paramTypeClazz.getName().equals(Response.class.getName())){ - args[i] = response; - } - } - - return args; - } - - /** - * 执行路由方法 - * - * @param object 方法的实例,即该方法所在类的对象 - * @param method 要执行的method - * @param request Request对象,作为参数注入 - * @param response Response对象,作为参数注入 - * @return 返回方法执行后的返回值 - */ - private Object executeMethod(Object object, Method method, Request request, Response response){ - int len = method.getParameterTypes().length; - method.setAccessible(true); - if(len > 0){ - Object[] args = getArgs(request, response, method.getParameterTypes()); - return ReflectKit.invokeMehod(object, method, args); - } else { - return ReflectKit.invokeMehod(object, method); - } - } - + /** * 要过滤掉的目录 * diff --git a/blade-core/src/main/java/com/blade/web/RouteArgument.java b/blade-core/src/main/java/com/blade/web/RouteArgument.java new file mode 100644 index 000000000..34f707ab6 --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/RouteArgument.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; + +import java.lang.reflect.Method; + +import blade.kit.ReflectKit; + +import com.blade.route.Route; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * 路由参数注入器 + * + * @author biezhi + * @since 1.0 + */ +public final class RouteArgument { + + /** + * 获取方法内的参数 + * + * @param request Request对象,用于注入到method参数列表中 + * @param response Response对象,用于注入到method参数列表中 + * @param route 当前操作的路由对象 + * @param params params参数列表 + * @return 返回生成后的参数数组 + */ + public static Object[] getArgs(Request request, Response response, Route route, Class[] params){ + + int len = params.length; + Object[] args = new Object[len]; + + for(int i=0; i paramTypeClazz = params[i]; + if(paramTypeClazz.getName().equals(Request.class.getName())){ + args[i] = request; + } + if(paramTypeClazz.getName().equals(Response.class.getName())){ + args[i] = response; + } + if(paramTypeClazz.getName().equals(Route.class.getName())){ + args[i] = route; + } + } + return args; + } + + /** + * 执行路由方法 + * + * @param object 方法的实例,即该方法所在类的对象 + * @param method 要执行的method + * @param request Request对象,作为参数注入 + * @param response Response对象,作为参数注入 + * @param route 当前操作的路由对象 + * @return 返回方法执行后的返回值 + */ + public static Object executeMethod(Object object, Method method, Request request, Response response, Route route){ + int len = method.getParameterTypes().length; + method.setAccessible(true); + if(len > 0){ + Object[] args = getArgs(request, response, route, method.getParameterTypes()); + return ReflectKit.invokeMehod(object, method, args); + } else { + return ReflectKit.invokeMehod(object, method); + } + } +} diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index 33578a306..3a01348e5 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -8,7 +8,6 @@ import javax.servlet.http.HttpServletResponse; import blade.exception.BladeException; -import blade.kit.ReflectKit; import blade.kit.StringKit; import blade.kit.base.ThrowableKit; import blade.kit.log.Logger; @@ -177,55 +176,10 @@ private void handle(Request request, Response response, Route route){ // 要执行的路由方法 Method actionMethod = route.getAction(); // 执行route方法 - executeMethod(target, actionMethod, request, response); + RouteArgument.executeMethod(target, actionMethod, request, response, route); } } - /** - * 获取方法内的参数 - * - * @param request Request对象,用于注入到method参数列表中 - * @param response Response对象,用于注入到method参数列表中 - * @param params params参数列表 - * @return 返回生成后的参数数组 - */ - private Object[] getArgs(Request request, Response response, Class[] params){ - - int len = params.length; - Object[] args = new Object[len]; - - for(int i=0; i paramTypeClazz = params[i]; - if(paramTypeClazz.getName().equals(Request.class.getName())){ - args[i] = request; - } - if(paramTypeClazz.getName().equals(Response.class.getName())){ - args[i] = response; - } - } - - return args; - } - - /** - * 执行路由方法 - * - * @param object 方法的实例,即该方法所在类的对象 - * @param method 要执行的method - * @param request Request对象,作为参数注入 - * @param response Response对象,作为参数注入 - * @return 返回方法执行后的返回值 - */ - private Object executeMethod(Object object, Method method, Request request, Response response){ - int len = method.getParameterTypes().length; - method.setAccessible(true); - if(len > 0){ - Object[] args = getArgs(request, response, method.getParameterTypes()); - return ReflectKit.invokeMehod(object, method, args); - } else { - return ReflectKit.invokeMehod(object, method); - } - } /** * 要过滤掉的目录 From 76ed6eec98a029c2587acb91a29e4c7020b1d0b9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 13:41:13 +0800 Subject: [PATCH 307/545] add request retuen route object --- .../main/java/com/blade/web/AsynRequestHandler.java | 5 ++++- .../src/main/java/com/blade/web/RouteArgument.java | 10 +++------- .../main/java/com/blade/web/SyncRequestHandler.java | 5 ++++- .../src/main/java/com/blade/web/http/Request.java | 5 +++++ .../com/blade/web/http/wrapper/ServletRequest.java | 10 +++++----- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index 0a89cbf6a..1edbfbeba 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -90,6 +90,7 @@ public void run(){ // 如果找到 if (route != null) { + request.setRoute(route); // 执行before拦截 List befores = routeMatcher.getBefore(uri); invokeInterceptor(request, response, befores); @@ -163,6 +164,7 @@ private void render404(Response response, String uri) { * * @param request 请求对象 * @param response 响应对象 + * @param current 当前请求的路由 * @param interceptors 要执行的拦截器列表 */ private void invokeInterceptor(Request request, Response response, List interceptors) { @@ -176,6 +178,7 @@ private void invokeInterceptor(Request request, Response response, List i * * @param request 请求对象 * @param response 响应对象 + * @param current 当前请求的路由 * @param route 路由对象 */ private void handle(Request request, Response response, Route route){ @@ -191,7 +194,7 @@ private void handle(Request request, Response response, Route route){ // 要执行的路由方法 Method actionMethod = route.getAction(); // 执行route方法 - RouteArgument.executeMethod(target, actionMethod, request, response, route); + RouteArgument.executeMethod(target, actionMethod, request, response); } } diff --git a/blade-core/src/main/java/com/blade/web/RouteArgument.java b/blade-core/src/main/java/com/blade/web/RouteArgument.java index 34f707ab6..00957aec0 100644 --- a/blade-core/src/main/java/com/blade/web/RouteArgument.java +++ b/blade-core/src/main/java/com/blade/web/RouteArgument.java @@ -19,7 +19,6 @@ import blade.kit.ReflectKit; -import com.blade.route.Route; import com.blade.web.http.Request; import com.blade.web.http.Response; @@ -40,7 +39,7 @@ public final class RouteArgument { * @param params params参数列表 * @return 返回生成后的参数数组 */ - public static Object[] getArgs(Request request, Response response, Route route, Class[] params){ + public static Object[] getArgs(Request request, Response response, Class[] params){ int len = params.length; Object[] args = new Object[len]; @@ -53,9 +52,6 @@ public static Object[] getArgs(Request request, Response response, Route route, if(paramTypeClazz.getName().equals(Response.class.getName())){ args[i] = response; } - if(paramTypeClazz.getName().equals(Route.class.getName())){ - args[i] = route; - } } return args; } @@ -70,11 +66,11 @@ public static Object[] getArgs(Request request, Response response, Route route, * @param route 当前操作的路由对象 * @return 返回方法执行后的返回值 */ - public static Object executeMethod(Object object, Method method, Request request, Response response, Route route){ + public static Object executeMethod(Object object, Method method, Request request, Response response){ int len = method.getParameterTypes().length; method.setAccessible(true); if(len > 0){ - Object[] args = getArgs(request, response, route, method.getParameterTypes()); + Object[] args = getArgs(request, response, method.getParameterTypes()); return ReflectKit.invokeMehod(object, method, args); } else { return ReflectKit.invokeMehod(object, method); diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index 3a01348e5..e49f22190 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -80,6 +80,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo // 如果找到 if (route != null) { + request.setRoute(route); // 执行before拦截 List befores = routeMatcher.getBefore(uri); invokeInterceptor(request, response, befores); @@ -148,6 +149,7 @@ private void render404(Response response, String uri) { * * @param request 请求对象 * @param response 响应对象 + * @param current 当前请求的路由 * @param interceptors 要执行的拦截器列表 */ private void invokeInterceptor(Request request, Response response, List interceptors) { @@ -161,6 +163,7 @@ private void invokeInterceptor(Request request, Response response, List i * * @param request 请求对象 * @param response 响应对象 + * @param current 当前请求的路由 * @param route 路由对象 */ private void handle(Request request, Response response, Route route){ @@ -176,7 +179,7 @@ private void handle(Request request, Response response, Route route){ // 要执行的路由方法 Method actionMethod = route.getAction(); // 执行route方法 - RouteArgument.executeMethod(target, actionMethod, request, response, route); + RouteArgument.executeMethod(target, actionMethod, request, response); } } diff --git a/blade-core/src/main/java/com/blade/web/http/Request.java b/blade-core/src/main/java/com/blade/web/http/Request.java index 0466caab9..da9e4ef38 100644 --- a/blade-core/src/main/java/com/blade/web/http/Request.java +++ b/blade-core/src/main/java/com/blade/web/http/Request.java @@ -314,6 +314,11 @@ public interface Request { */ void setRoute(Route route); + /** + * @return 返回当前请求的Route + */ + Route route(); + /** * 请求体接口 * @author biezhi diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index d20c0a428..e486fb2c4 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -108,11 +108,9 @@ private String join(String[] arr) { for (String item : arr) { ret += "," + item; } - if (ret.length() > 0) { ret = ret.substring(1); } - return ret; } @@ -135,13 +133,10 @@ public void initPathParams(String routePath) { private List getPathParam(String routePath) { List variables = new ArrayList(); - Matcher matcher = Pattern.compile(Path.VAR_REGEXP).matcher(routePath); while (matcher.find()) { - // group(0) always stands for the entire expression and we only want what is inside the {} variables.add(matcher.group(1)); } - return variables; } @@ -560,5 +555,10 @@ public void setRoute(Route route) { this.route = route; initPathParams(route.getPath()); } + + @Override + public Route route() { + return this.route; + } } From 2761841119f0dd947e7908e606681f6a21535c8d Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 13:44:53 +0800 Subject: [PATCH 308/545] update readme --- README.md | 117 ++++++++++++++++++++++++++++++++++++++++++++++ README_CN.md | 130 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 239 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ccec59f8b..fe1dc2c3a 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,123 @@ public class App { Run it and point your browser to http://localhost:9001. There you go, you've just created your first Blade app! +## API Example + +```java +public static void main(String[] args) { + Blade blade = Blade.me(); + blade.get("/user/21", getxxx); + blade.post("/save", postxxx); + blade.delete("/del/21", deletexxx); + blade.put("/put", putxxx); + blade.listen(9001).start(); +} +``` + +## REST URL Parameters + +```java +public static void main(String[] args) { + Blade blade = Blade.me(); + blade.get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + blade.get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + blade.listen(9001).start(); +} +``` + +## Form URL Parameters + +```java +public static void main(String[] args) { + Blade blade = Blade.me(); + blade.get("/user", (request, response) -> { + Integer uid = request.query("uid"); + response.text("uid : " + uid); + }); + blade.listen(9001).start(); +} +``` + +## Upload File + +```java +public void upload_img(Request request, Response response){ + + JsonObject jsonObject = new JsonObject(); + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## Route Config File + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## Route Intercept + +```java +public static void main(String[] args) { + Blade blade = Blade.me(); + blade.before("/.*", (request, response) -> { + System.out.println("before..."); + }); + blade.listen(9001).start(); +} +``` + +## DSL DB Operation + +```java +// save +public boolean save(Integer cid, Integer tid, Integer fuid, Integer tuid) { + return model.insert().param("cid", cid) + .param("tid", tid) + .param("fuid", fuid) + .param("tuid", tuid) + .param("addtime", new Date()) + .param("ntype", 0).executeAndCommit() > 0; +} + +// signin +public User signin(String username, String password) { + String pwd = EncrypKit.md5(username + password); + return model.select().eq("username", username) + .eq("password", pwd).fetchOne(); +} + +// search count +public Long getUserCount(String email){ + return model.count().eq("email", email).fetchCount(); +} +``` + OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: + [HELLO](https://github.com/bladejava/hello) diff --git a/README_CN.md b/README_CN.md index c86b3a68f..b97e96e47 100644 --- a/README_CN.md +++ b/README_CN.md @@ -45,19 +45,133 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 编写 `Main`函数: ```java -public class App { +public static void main(String[] args) { + Blade blade = Blade.me(); + blade.get("/", (request, response) -> { + response.html("

Hello blade!

"); + }); + blade.listen(9001).start(); +} +``` + +用浏览器打开 http://localhost:9001 这样就可以看到第一个Blade应用了! + +## API示例 + +```java +public static void main(String[] args) { + Blade blade = Blade.me(); + blade.get("/user/21", getxxx); + blade.post("/save", postxxx); + blade.delete("/del/21", deletexxx); + blade.put("/put", putxxx); + blade.listen(9001).start(); +} +``` + +## REST URL参数获取 + +```java +public static void main(String[] args) { + Blade blade = Blade.me(); + blade.get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + blade.get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + blade.listen(9001).start(); +} +``` + +## Form URL参数获取 + +```java +public static void main(String[] args) { + Blade blade = Blade.me(); + blade.get("/user", (request, response) -> { + Integer uid = request.query("uid"); + response.text("uid : " + uid); + }); + blade.listen(9001).start(); +} +``` + +## 上传文件 + +```java +public void upload_img(Request request, Response response){ - public static void main(String[] args) { - Blade blade = Blade.me(); - blade.get("/", (request, response) -> { - response.html("

Hello blade!

"); - }); - blade.listen(9001).start(); + JsonObject jsonObject = new JsonObject(); + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); } } ``` -用浏览器打开 http://localhost:9001 这样就可以看到第一个Blade应用了! +## 配置文件路由 + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## 路由拦截 + +```java +public static void main(String[] args) { + Blade blade = Blade.me(); + blade.before("/.*", (request, response) -> { + System.out.println("before..."); + }); + blade.listen(9001).start(); +} +``` + +## DSL数据库操作 + +```java +// 保存操作 +public boolean save(Integer cid, Integer tid, Integer fuid, Integer tuid) { + return model.insert().param("cid", cid) + .param("tid", tid) + .param("fuid", fuid) + .param("tuid", tuid) + .param("addtime", new Date()) + .param("ntype", 0).executeAndCommit() > 0; +} + +// 登录操作 +public User signin(String username, String password) { + String pwd = EncrypKit.md5(username + password); + return model.select().eq("username", username) + .eq("password", pwd).fetchOne(); +} + +// 查询条数 +public Long getUserCount(String email){ + return model.count().eq("email", email).fetchCount(); +} +``` OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: From 8617d9164b02143790eeba8749f03e42ca788dc2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 13:48:29 +0800 Subject: [PATCH 309/545] update readme --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fe1dc2c3a..6efd1c257 100644 --- a/README.md +++ b/README.md @@ -178,11 +178,11 @@ public Long getUserCount(String email){ OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: -+ [HELLO](https://github.com/bladejava/hello) -+ [API DOCS](http://bladejava.com/apidocs/) -+ [USE GUIDE](https://github.com/biezhi/blade/wiki) -+ [EXAMPLES](https://github.com/bladejava) -+ [VERSION](LAST_VERSION.md) ++ [Hello](https://github.com/bladejava/hello) ++ [Api Doc](http://bladejava.com/apidocs/) ++ [User Guide](https://github.com/biezhi/blade/wiki) ++ [Examples](https://github.com/bladejava) ++ [Version](LAST_VERSION.md) ## Plan From 72199a69577f4bdeb48be8c07b97a6f8405137de Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 14:12:48 +0800 Subject: [PATCH 310/545] update readme --- README.md | 4 ++-- README_CN.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6efd1c257..0b1fa0324 100644 --- a/README.md +++ b/README.md @@ -179,8 +179,8 @@ public Long getUserCount(String email){ OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: + [Hello](https://github.com/bladejava/hello) -+ [Api Doc](http://bladejava.com/apidocs/) -+ [User Guide](https://github.com/biezhi/blade/wiki) ++ [Api Doc](http://bladejava.com/apidocs) ++ [User Guide](http://bladejava.com/docs) + [Examples](https://github.com/bladejava) + [Version](LAST_VERSION.md) diff --git a/README_CN.md b/README_CN.md index b97e96e47..34bf686dd 100644 --- a/README_CN.md +++ b/README_CN.md @@ -176,8 +176,8 @@ public Long getUserCount(String email){ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: + [hello工程](https://github.com/bladejava/hello) -+ [API文档](http://bladejava.com/apidocs/) -+ [使用指南](https://github.com/biezhi/blade/wiki) ++ [API文档](http://bladejava.com/apidocs) ++ [使用指南](http://bladejava.com/docs) + [相关案例](https://github.com/bladejava) + [版本查询](LAST_VERSION.md) From f03218350965aa49571e08fd4df5889f4243de3a Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 15:21:28 +0800 Subject: [PATCH 311/545] aop and tx! --- blade-aop/pom.xml | 12 +- .../blade/aop/AbstractMethodInterceptor.java | 3 +- .../blade/aop/AbstractRouteInterceptor.java | 51 --------- .../java/com/blade/aop/AdviceMatcher.java | 24 ++-- .../blade/aop/DefaultMethodInvocation.java | 8 +- .../main/java/com/blade/aop/DefaultProxy.java | 30 ++--- .../java/com/blade/aop/ProxyBeanFactory.java | 103 ------------------ .../{After.java => AfterAdvice.java} | 2 +- .../{Before.java => BeforeAdvice.java} | 2 +- .../aop/exception/AdviceMatcherException.java | 2 +- .../intercept/AbstractMethodInterceptor.java | 46 -------- .../AbstractMethodInterceptorFactory.java | 2 + blade-tx/pom.xml | 29 +++++ .../plugin/tx/TransactionInterceptor.java | 37 +++++++ .../blade/plugin/tx/TransactionManage.java | 59 ++++++++++ .../java/com/blade/plugin/tx/TxPlugin.java | 40 +++++++ .../plugin/tx/annotation/Transactional.java | 16 +++ 17 files changed, 217 insertions(+), 249 deletions(-) delete mode 100644 blade-aop/src/main/java/com/blade/aop/AbstractRouteInterceptor.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/ProxyBeanFactory.java rename blade-aop/src/main/java/com/blade/aop/annotation/{After.java => AfterAdvice.java} (95%) rename blade-aop/src/main/java/com/blade/aop/annotation/{Before.java => BeforeAdvice.java} (95%) delete mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptor.java create mode 100644 blade-tx/pom.xml create mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java create mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TransactionManage.java create mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java create mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/annotation/Transactional.java diff --git a/blade-aop/pom.xml b/blade-aop/pom.xml index 5d0124938..8b58cace7 100644 --- a/blade-aop/pom.xml +++ b/blade-aop/pom.xml @@ -8,15 +8,11 @@ blade-root 1.0 - blade-proxy - 1.0 - blade-proxy + blade-aop + 1.0.0 + blade-aop http://maven.apache.org - - - UTF-8 - - + com.bladejava diff --git a/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java b/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java index 839ccc9e9..997a3465f 100644 --- a/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java +++ b/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java @@ -29,8 +29,7 @@ public abstract class AbstractMethodInterceptor implements MethodInterceptor { * 执行方法 */ public Object invoke(MethodInvocation invocation) throws Throwable { - Object result = invocation.proceed(); - return result; + return invocation.proceed(); } /** diff --git a/blade-aop/src/main/java/com/blade/aop/AbstractRouteInterceptor.java b/blade-aop/src/main/java/com/blade/aop/AbstractRouteInterceptor.java deleted file mode 100644 index 0a2ef716d..000000000 --- a/blade-aop/src/main/java/com/blade/aop/AbstractRouteInterceptor.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; -/** - * - * 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. - */ - -import com.blade.aop.intercept.MethodInvocation; - -/** - * 抽象路由拦截器 - * @author biezhi - * @since 1.0 - */ -public abstract class AbstractRouteInterceptor extends AbstractMethodInterceptor { - - @Override - public void beforeAdvice() { - } - - @Override - public void afterAdvice() { - } - - @Override - public abstract Object invoke(MethodInvocation invocation) throws Throwable; -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java b/blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java index 949e7e342..28ea4d67c 100644 --- a/blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java +++ b/blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java @@ -18,8 +18,8 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import com.blade.aop.annotation.After; -import com.blade.aop.annotation.Before; +import com.blade.aop.annotation.AfterAdvice; +import com.blade.aop.annotation.BeforeAdvice; import com.blade.aop.exception.AdviceMatcherException; import com.blade.aop.intercept.MethodInvocation; @@ -46,17 +46,23 @@ public boolean match(Class adviceAnnotationType, String joinPoint) { // 要执行的方法 try { Method adviceMethod = interceptor.getClass().getDeclaredMethod(joinPoint, new Class[] {}); - if (adviceAnnotationType == Before.class) { - Before before = adviceMethod.getAnnotation(Before.class); + if (adviceAnnotationType == BeforeAdvice.class) { + BeforeAdvice before = adviceMethod.getAnnotation(BeforeAdvice.class); if (before == null) return false; - String pointcut = before.expression(); + String pointcut = before.expression(); + if(null == pointcut || pointcut.equals("")){ + return true; + } return beforeOrAfterMatch(pointcut, invocation.getMethod()); - } else if (adviceAnnotationType == After.class) { - After after = adviceMethod.getAnnotation(After.class); + } else if (adviceAnnotationType == AfterAdvice.class) { + AfterAdvice after = adviceMethod.getAnnotation(AfterAdvice.class); if (after == null) - return false; - String pointcut = after.expression(); + return false; + String pointcut = after.expression(); + if(null == pointcut || pointcut.equals("")){ + return true; + } return beforeOrAfterMatch(pointcut, invocation.getMethod()); } } catch (SecurityException e) { diff --git a/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java b/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java index 616564626..487bec470 100644 --- a/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java +++ b/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java @@ -18,8 +18,8 @@ import java.lang.reflect.Method; import java.util.List; -import com.blade.aop.annotation.After; -import com.blade.aop.annotation.Before; +import com.blade.aop.annotation.AfterAdvice; +import com.blade.aop.annotation.BeforeAdvice; import com.blade.aop.intercept.MethodInvocation; import blade.kit.log.Logger; @@ -54,7 +54,7 @@ public Object proceed() throws Exception { Object result = null; if (interceptors.size() > 0 && index < interceptors.size()) { interceptor = interceptors.get(index++); - if (new AdviceMatcher(interceptor, this).match(Before.class, "beforeAdvice")) { + if (new AdviceMatcher(interceptor, this).match(BeforeAdvice.class, "beforeAdvice")) { interceptor.beforeAdvice(); // 执行前置建议 } proceed(); // 执行下一个拦截器 @@ -70,7 +70,7 @@ public Object proceed() throws Exception { } if (index > 0) { interceptor = interceptors.get(--index); - if (new AdviceMatcher(interceptor, this).match(After.class, "afterAdvice")) { + if (new AdviceMatcher(interceptor, this).match(AfterAdvice.class, "afterAdvice")) { interceptor.afterAdvice(); // 执行后置建议 } } diff --git a/blade-aop/src/main/java/com/blade/aop/DefaultProxy.java b/blade-aop/src/main/java/com/blade/aop/DefaultProxy.java index 96fd8caea..b00867373 100644 --- a/blade-aop/src/main/java/com/blade/aop/DefaultProxy.java +++ b/blade-aop/src/main/java/com/blade/aop/DefaultProxy.java @@ -44,15 +44,13 @@ */ public class DefaultProxy implements MethodInterceptor { - private Object target; - private List interceptorChain = new ArrayList(); + private Object target; - public DefaultProxy(Object target, List interceptorChain) { - this.target = target; - if (interceptorChain != null && interceptorChain.size() > 0) { - this.interceptorChain.addAll(interceptorChain); - } - } + private List interceptorChain = new ArrayList(); + + public DefaultProxy() { + + } public void addInterceptor(AbstractMethodInterceptor abstractMethodInterceptor){ interceptorChain.add(abstractMethodInterceptor); @@ -70,24 +68,10 @@ public Object getProxy(Object target) { return proxy; } - public Object getProxy() { - // cglib 中加强器,用来创建动态代理 - Enhancer enhancer = new Enhancer(); - // 设置要创建动态代理的类 - enhancer.setSuperclass(target.getClass()); - // 设置回调,这里相当于是对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实行intercept()方法进行拦截 - enhancer.setCallback(this); - Object proxy = enhancer.create(); - return proxy; - } - @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { DefaultMethodInvocation methodInvocation = new DefaultMethodInvocation(this, method, target, args, interceptorChain); return methodInvocation.proceed(); } - - public Object getTarget() { - return target; - } + } \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/ProxyBeanFactory.java b/blade-aop/src/main/java/com/blade/aop/ProxyBeanFactory.java deleted file mode 100644 index b8d3d6a14..000000000 --- a/blade-aop/src/main/java/com/blade/aop/ProxyBeanFactory.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; -/** - * - * 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. - */ - -import java.util.Arrays; -import java.util.List; - -/** - * 单例的代理工厂 - * @author biezhi - * @since 1.0 - */ -public class ProxyBeanFactory { - - private ProxyBeanFactory() { - } - - public static ProxyBeanFactory single() { - return SingleHoder.single; - } - - private static class SingleHoder { - - private static final ProxyBeanFactory single = new ProxyBeanFactory(); - } - - /** - * - * @param targetClazz 创建指定类target实例 - * @param chain 系统的拦截器链 - * @return - */ - public Object newProxy(Class targetClazz, List chain) { - Object proxyBean = null; - try { - Object target = targetClazz.newInstance(); - proxyBean = new DefaultProxy(target, chain).getProxy(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return proxyBean; - } - - public Object newProxy(Class targetClazz, AbstractMethodInterceptor ... chain) { - Object proxyBean = null; - try { - Object target = targetClazz.newInstance(); - List chainList = null; - if(null != chain && chain.length > 0){ - chainList = Arrays.asList(chain); - } - proxyBean = new DefaultProxy(target, chainList).getProxy(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return proxyBean; - } - - public Object newProxy(Object target, AbstractMethodInterceptor ... chain) { - List chainList = null; - if(null != chain && chain.length > 0){ - chainList = Arrays.asList(chain); - } - Object proxyBean = new DefaultProxy(target, chainList).getProxy(); - return proxyBean; - } - - public Object newProxy(Object target, List chain) { - Object proxyBean = new DefaultProxy(target, chain).getProxy(); - return proxyBean; - } -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/annotation/After.java b/blade-aop/src/main/java/com/blade/aop/annotation/AfterAdvice.java similarity index 95% rename from blade-aop/src/main/java/com/blade/aop/annotation/After.java rename to blade-aop/src/main/java/com/blade/aop/annotation/AfterAdvice.java index 7335711f3..3ac1ccb10 100644 --- a/blade-aop/src/main/java/com/blade/aop/annotation/After.java +++ b/blade-aop/src/main/java/com/blade/aop/annotation/AfterAdvice.java @@ -27,7 +27,7 @@ */ @Target(value={ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) -public @interface After{ +public @interface AfterAdvice{ String expression() default ""; } \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/annotation/Before.java b/blade-aop/src/main/java/com/blade/aop/annotation/BeforeAdvice.java similarity index 95% rename from blade-aop/src/main/java/com/blade/aop/annotation/Before.java rename to blade-aop/src/main/java/com/blade/aop/annotation/BeforeAdvice.java index 881d428e5..330c54e43 100644 --- a/blade-aop/src/main/java/com/blade/aop/annotation/Before.java +++ b/blade-aop/src/main/java/com/blade/aop/annotation/BeforeAdvice.java @@ -26,7 +26,7 @@ */ @Target(value={ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) -public @interface Before { +public @interface BeforeAdvice { String expression() default ""; diff --git a/blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java b/blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java index 33c699711..7d028cde5 100644 --- a/blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java +++ b/blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java @@ -21,7 +21,7 @@ * @since 1.0 */ public class AdviceMatcherException extends RuntimeException { - + private static final long serialVersionUID = -5143613620732802399L; public AdviceMatcherException() { diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptor.java b/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptor.java deleted file mode 100644 index e17ba6116..000000000 --- a/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptor.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; - -import com.blade.aop.intercept.MethodInterceptor; -import com.blade.aop.intercept.MethodInvocation; - -/** - * 抽象方法拦截器 - * @author biezhi - * @since 1.0 - */ -public abstract class AbstractMethodInterceptor implements MethodInterceptor { - - /** - * 执行方法 - */ - public Object invoke(MethodInvocation invocation) throws Throwable { - Object result = invocation.proceed(); - return result; - } - - /** - * 前置执行 - */ - protected abstract void beforeAdvice(); - - /** - * 后置执行 - */ - protected abstract void afterAdvice(); - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java b/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java index 4f2df75d0..c0825e9ee 100644 --- a/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java +++ b/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java @@ -17,6 +17,8 @@ import java.util.ArrayList; import java.util.List; + +import com.blade.aop.AbstractMethodInterceptor; /** * 拦截器方法工厂 diff --git a/blade-tx/pom.xml b/blade-tx/pom.xml new file mode 100644 index 000000000..c96939f64 --- /dev/null +++ b/blade-tx/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + blade-tx + 1.0.0 + blade-tx + http://maven.apache.org + + + + com.bladejava + blade-aop + 1.0.0 + + + com.bladejava + blade-sql2o + 1.2.9 + provided + + + diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java new file mode 100644 index 000000000..4e975c4b9 --- /dev/null +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java @@ -0,0 +1,37 @@ +package com.blade.plugin.tx; + +import java.sql.SQLException; + +import javax.sql.DataSource; + +import com.blade.aop.AbstractMethodInterceptor; +import com.blade.aop.annotation.AfterAdvice; +import com.blade.aop.annotation.BeforeAdvice; + +public class TransactionInterceptor extends AbstractMethodInterceptor { + + private TransactionManage transactionManager; + + public TransactionInterceptor(DataSource dataSource) { + this.transactionManager = new TransactionManage(dataSource); + } + + @BeforeAdvice(expression = "@com.blade.plugin.tx.annotation.Transactional") + public void beforeAdvice() { + try { + transactionManager.start(); + } catch (SQLException e) { + throw new RuntimeException("begin transaction failure", e); + } + } + + @AfterAdvice(expression = "@com.blade.plugin.tx.annotation.Transactional") + public void afterAdvice() { + try { + transactionManager.commit(); + } catch (SQLException e) { + throw new RuntimeException("commit transaction failure", e); + } + } + +} \ No newline at end of file diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManage.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManage.java new file mode 100644 index 000000000..7a094d1f1 --- /dev/null +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManage.java @@ -0,0 +1,59 @@ +package com.blade.plugin.tx; + +import java.sql.Connection; +import java.sql.SQLException; + +import javax.sql.DataSource; + +import blade.kit.log.Logger; + +public class TransactionManage { + + private Logger logger = Logger.getLogger(TransactionManage.class); + + private DataSource dataSource; + + public TransactionManage(DataSource dataSource) { + this.dataSource = dataSource; + } + + public void start() throws SQLException { + Connection connection = getConnection(); + connection.setAutoCommit(false); + logger.debug("begin transaction."); + } + + public final void commit() throws SQLException { + Connection connection = getConnection(); + connection.commit(); + logger.debug("commit transaction."); + } + + public final void rollback() { + Connection connection = null; + try { + connection = getConnection(); + connection.rollback(); + logger.debug("rollback transaction."); + } catch (SQLException e) { + throw new RuntimeException("Couldn't rollback on connection[" + connection + "].", e); + } + } + + public final void close() { + Connection connection = null; + try { + connection = getConnection(); + connection.setAutoCommit(true); + connection.setReadOnly(false); + connection.close(); + } catch (SQLException e) { + throw new RuntimeException("Couldn't close connection[" + connection + "].", e); + } + } + + private Connection getConnection() throws SQLException { + return dataSource.getConnection(); + } + +} \ No newline at end of file diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java b/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java new file mode 100644 index 000000000..c3dfeec04 --- /dev/null +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java @@ -0,0 +1,40 @@ +package com.blade.plugin.tx; + +import javax.sql.DataSource; + +import com.blade.aop.AopProxy; +import com.blade.plugin.Plugin; + +/** + * 事务插件 + * @author biezhi + * @since 1.0 + */ +public class TxPlugin implements Plugin { + + private TransactionInterceptor transactionInterceptor; + + public TxPlugin() { + + } + + public TxPlugin dataSource(DataSource dataSource){ + transactionInterceptor = new TransactionInterceptor(dataSource); + return this; + } + + @Override + public void run() { + if(null == transactionInterceptor){ + throw new RuntimeException("transaction plugin load error,TransactionInterceptor is NULL!"); + } else { + AopProxy.addInterceptor(transactionInterceptor); + } + } + + @Override + public void destroy() { + + } + +} diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/annotation/Transactional.java b/blade-tx/src/main/java/com/blade/plugin/tx/annotation/Transactional.java new file mode 100644 index 000000000..3c9c40b48 --- /dev/null +++ b/blade-tx/src/main/java/com/blade/plugin/tx/annotation/Transactional.java @@ -0,0 +1,16 @@ +package com.blade.plugin.tx.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +public @interface Transactional { + +} \ No newline at end of file From f18e92a4ce6c90aad6170e35fb60b72a53ab7222 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 15:40:29 +0800 Subject: [PATCH 312/545] add blade-aop --- .../src/main/java/com/blade/aop/AopProxy.java | 80 +++++++++++++++++++ .../com/blade/aop/test/AnnoInterceptor.java | 21 +++++ .../com/blade/aop/test/TestInterceptor.java | 21 +++++ .../java/com/blade/aop/test/TestMain.java | 17 ++++ .../test/java/com/blade/aop/test/Work.java | 15 ++++ blade-core/src/main/java/com/blade/Aop.java | 39 ++++++--- .../main/java/com/blade/ioc/AopCreator.java | 43 ++++++++++ .../java/com/blade/web/DispatcherServlet.java | 2 +- .../java/com/blade/plugin/tx/TxPlugin.java | 1 - 9 files changed, 224 insertions(+), 15 deletions(-) create mode 100644 blade-aop/src/main/java/com/blade/aop/AopProxy.java create mode 100644 blade-aop/src/test/java/com/blade/aop/test/AnnoInterceptor.java create mode 100644 blade-aop/src/test/java/com/blade/aop/test/TestInterceptor.java create mode 100644 blade-aop/src/test/java/com/blade/aop/test/TestMain.java create mode 100644 blade-aop/src/test/java/com/blade/aop/test/Work.java create mode 100644 blade-core/src/main/java/com/blade/ioc/AopCreator.java diff --git a/blade-aop/src/main/java/com/blade/aop/AopProxy.java b/blade-aop/src/main/java/com/blade/aop/AopProxy.java new file mode 100644 index 000000000..09c25be0f --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/AopProxy.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; + +import net.sf.cglib.core.ReflectUtils; + +/** + * AOP代理操作类,用于创建代理、添加拦截器 + * + * @author biezhi + * @since 1.0 + */ +@SuppressWarnings("unchecked") +public final class AopProxy { + + private static DefaultProxy defaultProxy = new DefaultProxy(); + + private AopProxy() { + } + + /** + * 根据Class创建一个代理 + * @param clazz Class对象 + * @return 返回代理对象 + */ + public static T create(Class clazz){ + Object target = ReflectUtils.newInstance(clazz); + Object proxy = defaultProxy.getProxy(target); + return (T) proxy; + } + + /** + * 根据Class创建一个代理 + * @param clazz Class对象 + * @return 返回代理对象 + */ + public static Object createProxy(Class clazz){ + Object target = ReflectUtils.newInstance(clazz); + Object proxy = defaultProxy.getProxy(target); + return proxy; + } + + /** + * 创建一个代理对象 + * @param target 原始java对象 + * @return 返回代理对象 + */ + public static T create(Object target){ + Object proxy = defaultProxy.getProxy(target); + return (T) proxy; + } + + /** + * 创建一个代理对象 + * @param target 原始java对象 + * @return 返回代理对象 + */ + public static Object createProxy(Object target){ + Object proxy = defaultProxy.getProxy(target); + return proxy; + } + + public static void addInterceptor(AbstractMethodInterceptor abstractMethodInterceptor){ + defaultProxy.addInterceptor(abstractMethodInterceptor); + } + +} diff --git a/blade-aop/src/test/java/com/blade/aop/test/AnnoInterceptor.java b/blade-aop/src/test/java/com/blade/aop/test/AnnoInterceptor.java new file mode 100644 index 000000000..f6db3f941 --- /dev/null +++ b/blade-aop/src/test/java/com/blade/aop/test/AnnoInterceptor.java @@ -0,0 +1,21 @@ +package com.blade.aop.test; + +import com.blade.aop.AbstractMethodInterceptor; +import com.blade.aop.annotation.AfterAdvice; +import com.blade.aop.annotation.BeforeAdvice; + +public class AnnoInterceptor extends AbstractMethodInterceptor { + + @Override + @BeforeAdvice(expression = "@javax.annotation.Resource") + protected void beforeAdvice() { + System.out.println("before Resource XXX"); + } + + @Override + @AfterAdvice(expression = "@javax.annotation.Resource") + protected void afterAdvice() { + System.out.println("after Resource XXX"); + } + +} diff --git a/blade-aop/src/test/java/com/blade/aop/test/TestInterceptor.java b/blade-aop/src/test/java/com/blade/aop/test/TestInterceptor.java new file mode 100644 index 000000000..8fed1b539 --- /dev/null +++ b/blade-aop/src/test/java/com/blade/aop/test/TestInterceptor.java @@ -0,0 +1,21 @@ +package com.blade.aop.test; + +import com.blade.aop.AbstractMethodInterceptor; +import com.blade.aop.annotation.AfterAdvice; +import com.blade.aop.annotation.BeforeAdvice; + +public class TestInterceptor extends AbstractMethodInterceptor { + + @Override + @BeforeAdvice + protected void beforeAdvice() { + System.out.println("before"); + } + + @Override + @AfterAdvice + protected void afterAdvice() { + System.out.println("after"); + } + +} diff --git a/blade-aop/src/test/java/com/blade/aop/test/TestMain.java b/blade-aop/src/test/java/com/blade/aop/test/TestMain.java new file mode 100644 index 000000000..8e4de9614 --- /dev/null +++ b/blade-aop/src/test/java/com/blade/aop/test/TestMain.java @@ -0,0 +1,17 @@ +package com.blade.aop.test; + +import com.blade.aop.AopProxy; + +public class TestMain { + + public static void main(String[] args) { + + AopProxy.addInterceptor(new TestInterceptor()); + AopProxy.addInterceptor(new AnnoInterceptor()); + Work work = AopProxy.create(Work.class); + work.run(); + + work.save(); + + } +} diff --git a/blade-aop/src/test/java/com/blade/aop/test/Work.java b/blade-aop/src/test/java/com/blade/aop/test/Work.java new file mode 100644 index 000000000..53edab3c9 --- /dev/null +++ b/blade-aop/src/test/java/com/blade/aop/test/Work.java @@ -0,0 +1,15 @@ +package com.blade.aop.test; + +import javax.annotation.Resource; + +public class Work { + + public void run(){ + System.out.println("run in work!!"); + } + + @Resource + public void save(){ + System.out.println("save ..."); + } +} diff --git a/blade-core/src/main/java/com/blade/Aop.java b/blade-core/src/main/java/com/blade/Aop.java index d92ae606d..1666720a5 100644 --- a/blade-core/src/main/java/com/blade/Aop.java +++ b/blade-core/src/main/java/com/blade/Aop.java @@ -15,6 +15,8 @@ */ package com.blade; +import com.blade.ioc.AopCreator; + import blade.kit.ReflectKit; /** @@ -26,11 +28,28 @@ @SuppressWarnings("unchecked") public final class Aop { - private static boolean isAop = false; + private static boolean AOP_OPEN = false; + + static{ + try { + Class.forName("com.blade.aop.AopProxy"); + AOP_OPEN = true; + } catch (ClassNotFoundException e) { + AOP_OPEN = false; + } + } + + public static Object create(Class clazz){ + if(AOP_OPEN){ + return AopCreator.create(clazz); + } else { + return ReflectKit.newInstance(clazz); + } + } - public static T create(Class clazz){ - if(isAop){ - //...aop + public static T createT(Class clazz){ + if(AOP_OPEN){ + return AopCreator.create(clazz); } else { Object object = ReflectKit.newInstance(clazz); if(null != object){ @@ -40,20 +59,14 @@ public static T create(Class clazz){ return null; } - public static T create(String className){ + public static Object create(String className){ try { Class clazz = Class.forName(className); - if(isAop){ - //...aop - } else { - Object object = ReflectKit.newInstance(clazz); - if(null != object){ - return (T) object; - } - } + return create(clazz); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/AopCreator.java b/blade-core/src/main/java/com/blade/ioc/AopCreator.java new file mode 100644 index 000000000..70495dd94 --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/AopCreator.java @@ -0,0 +1,43 @@ +package com.blade.ioc; + +import com.blade.aop.AopProxy; + +public final class AopCreator { + + /** + * 根据Class创建一个代理 + * @param clazz Class对象 + * @return 返回代理对象 + */ + public static T create(Class clazz){ + return AopProxy.create(clazz); + } + + /** + * 根据Class创建一个代理 + * @param clazz Class对象 + * @return 返回代理对象 + */ + public static Object createProxy(Class clazz){ + return AopProxy.create(clazz); + } + + /** + * 创建一个代理对象 + * @param target 原始java对象 + * @return 返回代理对象 + */ + public static T create(Object target){ + return AopProxy.create(target); + } + + /** + * 创建一个代理对象 + * @param target 原始java对象 + * @return 返回代理对象 + */ + public static Object createProxy(Object target){ + return AopProxy.create(target); + } + +} diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 9405c660b..fc2bc217e 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -129,7 +129,7 @@ private Bootstrap getBootstrap(String botstrapClassName) throws ServletException if(null != botstrapClassName){ Class applicationClass = (Class) Class.forName(botstrapClassName); if(null != applicationClass){ - bootstrapClass = Aop.create(applicationClass); + bootstrapClass = Aop.createT(applicationClass); } } else { throw new ServletException("bootstrapClass is null !"); diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java b/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java index c3dfeec04..4383fe4d6 100644 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java @@ -15,7 +15,6 @@ public class TxPlugin implements Plugin { private TransactionInterceptor transactionInterceptor; public TxPlugin() { - } public TxPlugin dataSource(DataSource dataSource){ From 1c27350edce542cf0cf661b20758cfcd92ea608b Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 15:55:20 +0800 Subject: [PATCH 313/545] update blade to 1.5.0-beta --- LAST_VERSION.md | 11 ++++++++++- README.md | 2 +- blade-aop/pom.xml | 6 +++--- blade-core/pom.xml | 6 ++++++ blade-tx/pom.xml | 9 ++++----- pom.xml | 3 ++- 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index e0aa13253..61110fb71 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.5.0-alpha +    1.5.0-beta ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -89,3 +89,12 @@     1.0.1 ``` + +## [blade-aop](http://search.maven.org/#search%7Cga%7C1%7Cblade-aop) +```xml + +    com.bladejava +    blade-aop +    1.0.0 + +``` diff --git a/README.md b/README.md index 0b1fa0324..dc8f0ab06 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! * Simplicity. The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. It is a goal of the project that users should be able to understand the whole framework in a single day. * Elegance. `blade` Support the REST style routing interface, provide DSL grammar to write, no invasive interceptors. -## Getting started +## Get Start To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : diff --git a/blade-aop/pom.xml b/blade-aop/pom.xml index 8b58cace7..fdf1ce56a 100644 --- a/blade-aop/pom.xml +++ b/blade-aop/pom.xml @@ -15,9 +15,9 @@ - com.bladejava - blade-core - ${blade.version} + com.bladejava + blade-kit + 1.2.8-alpha diff --git a/blade-core/pom.xml b/blade-core/pom.xml index e12fca680..bee2f9e67 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -30,6 +30,12 @@ blade-kit 1.2.8-alpha + + com.bladejava + blade-aop + 1.0.0 + provided + javax.servlet javax.servlet-api diff --git a/blade-tx/pom.xml b/blade-tx/pom.xml index c96939f64..b1a837e9d 100644 --- a/blade-tx/pom.xml +++ b/blade-tx/pom.xml @@ -16,14 +16,13 @@ com.bladejava - blade-aop - 1.0.0 + blade-core + ${blade.version} com.bladejava - blade-sql2o - 1.2.9 - provided + blade-aop + 1.0.0 diff --git a/pom.xml b/pom.xml index bccb56dea..cd4d9b7ca 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.5.0-alpha + 1.5.0-beta 4.12 @@ -27,6 +27,7 @@ blade-redis blade-startup blade-aop + blade-tx blade-oauth2 blade-patchca From 167ac8064cb0e2993ae9c2d3c62dac8f176a8392 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 16:12:22 +0800 Subject: [PATCH 314/545] update to blade-1.5.0-beta --- blade-oauth2/pom.xml | 2 +- blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java | 2 +- .../com/blade/oauth2/base/request/OAuthTokenBaseRequest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/blade-oauth2/pom.xml b/blade-oauth2/pom.xml index 732c0d88f..841adf97e 100644 --- a/blade-oauth2/pom.xml +++ b/blade-oauth2/pom.xml @@ -9,7 +9,7 @@ 1.0 blade-oauth2 - 1.0.1 + 1.0.2 blade-oauth2 https://github.com/biezhi/blade/tree/master/blade-oauth2 diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java index 0dea01987..5dae2c07d 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java @@ -41,7 +41,7 @@ protected OAuthValidator initValidator() throws OAuthProblemException { if (clazz == null) { throw OAuthKit.handleOAuthProblemException("Invalid response_type parameter value"); } - return Aop.create(clazz); + return Aop.createT(clazz); } public String getResponseType() { diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java index 131fd9e83..bcecbbecc 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java @@ -38,7 +38,7 @@ protected OAuthValidator initValidator() throw OAuthKit .handleOAuthProblemException("Invalid grant_type parameter value"); } - return Aop.create(clazz); + return Aop.createT(clazz); } public String getPassword() { From aa61d9f613ad9d4645ed6a780ea04be786aa364e Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 16:15:05 +0800 Subject: [PATCH 315/545] update blade-oauth2 to 1.0.2 --- LAST_VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 61110fb71..19c5ba0c7 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -86,7 +86,7 @@     com.bladejava     blade-oauth2 -    1.0.1 +    1.0.2 ``` From ccc0715e220f5cd01c0a52d1c0f382f0ca1d9bba Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 16:23:02 +0800 Subject: [PATCH 316/545] update const version --- blade-core/src/main/java/com/blade/Const.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index a98d23d59..a6d63a3a5 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * 当前最新版本 */ - String BLADE_VERSION = "1.5.0-alpha"; + String BLADE_VERSION = "1.5.0-beta"; /** * 服务器500错误时返回的HTML From 4215c57bf709fcc31b588eafb126590531783882 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Dec 2015 16:25:14 +0800 Subject: [PATCH 317/545] modify comment --- blade-core/src/main/java/com/blade/IocApplication.java | 4 ++-- blade-core/src/main/java/com/blade/web/RouteArgument.java | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index e69317203..b6465be87 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -63,8 +63,8 @@ public IocApplication(Container container) { /** * 初始化IOC - * - * @param blade Blade实例 + * @param iocs IOC包 + * @param bootstrap 启动对象 */ public void init(String[] iocs, Bootstrap bootstrap){ diff --git a/blade-core/src/main/java/com/blade/web/RouteArgument.java b/blade-core/src/main/java/com/blade/web/RouteArgument.java index 00957aec0..c174e77a6 100644 --- a/blade-core/src/main/java/com/blade/web/RouteArgument.java +++ b/blade-core/src/main/java/com/blade/web/RouteArgument.java @@ -35,7 +35,6 @@ public final class RouteArgument { * * @param request Request对象,用于注入到method参数列表中 * @param response Response对象,用于注入到method参数列表中 - * @param route 当前操作的路由对象 * @param params params参数列表 * @return 返回生成后的参数数组 */ @@ -63,7 +62,6 @@ public static Object[] getArgs(Request request, Response response, Class[] pa * @param method 要执行的method * @param request Request对象,作为参数注入 * @param response Response对象,作为参数注入 - * @param route 当前操作的路由对象 * @return 返回方法执行后的返回值 */ public static Object executeMethod(Object object, Method method, Request request, Response response){ From 0bc82fe09a91b997c734d58a081f16da10fb6b65 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 14 Dec 2015 17:43:04 +0800 Subject: [PATCH 318/545] add Model.create method --- blade-sql2o/pom.xml | 74 +++++++++---------- .../main/java/blade/plugin/sql2o/Model.java | 24 +++--- 2 files changed, 47 insertions(+), 51 deletions(-) diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml index a4c77732e..bd0f7ef9c 100644 --- a/blade-sql2o/pom.xml +++ b/blade-sql2o/pom.xml @@ -1,37 +1,37 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-sql2o - jar - 1.2.9 - blade-sql2o - https://github.com/biezhi/blade/tree/master/blade-sql2o - - - - com.bladejava - blade-core - ${blade.version} - provided - - - com.bladejava - blade-cache - 1.2.3 - provided - - - org.sql2o - sql2o - 1.5.4 - - - + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + + blade-sql2o + jar + 1.3.0-alpha + blade-sql2o + https://github.com/biezhi/blade/tree/master/blade-sql2o + + + + com.bladejava + blade-core + ${blade.version} + provided + + + com.bladejava + blade-cache + 1.2.3 + provided + + + org.sql2o + sql2o + 1.5.4 + + + diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java index 45a590eaa..a04d3bb91 100644 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java @@ -72,6 +72,15 @@ public class Model { private String CACHE_KEY_SQL_COUNT; private String CACHE_KEY_SQL_DETAIL; + /** + * 创建一个Model + * @param clazz model class + * @return 返回Model对象 + */ + public static Model create(Class clazz) { + return new Model(clazz); + } + public Model(Class clazz) { this.model = clazz; this.condition = new Condition(table(), pk()); @@ -270,19 +279,6 @@ public Model param(String name, Object value){ return this; } - /** - * 设置where参数列表,查询,更新,删除用到 - * - * @param name 参数键 - * @param value 参数值 - * @return 返回model对象 - */ - @Deprecated - public Model where(String name, Object value){ - condition.eq(name, value); - return this; - } - /** * 设置equals参数列表,查询,更新,删除用到 * @@ -793,7 +789,7 @@ public T fetchByPk(Serializable pk){ if(null != pk){ - this.select().where(this.pk(), pk); + this.select().eq(this.pk(), pk); String field = null; // 启用缓存 From 1344b3972e4ff1c36ffa0c2a08a19ae18ac0818a Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 15 Dec 2015 11:10:20 +0800 Subject: [PATCH 319/545] simple code add NULL judgments --- blade-core/pom.xml | 2 +- blade-core/src/main/java/com/blade/Aop.java | 20 +- blade-core/src/main/java/com/blade/Blade.java | 45 +- .../java/com/blade/ioc/SampleContainer.java | 22 +- .../main/java/com/blade/route/Routers.java | 7 + .../com/blade/web/AsynRequestHandler.java | 18 +- .../java/com/blade/web/RouteArgument.java | 14 +- .../com/blade/web/SyncRequestHandler.java | 16 +- blade-kit/pom.xml | 2 +- .../java/blade/exception/BladeException.java | 49 -- .../blade/exception/ClassReaderException.java | 47 -- .../blade/exception/ExceptionHandlerImpl.java | 43 -- .../java/blade/exception/ExceptionStack.java | 77 -- .../blade/exception/IllegalPathException.java | 35 - .../java/blade/exception/package-info.java | 4 - blade-kit/src/main/java/blade/kit/Assert.java | 730 +++++++++--------- .../src/main/java/blade/kit/FileKit.java | 12 +- .../src/main/java/blade/kit/ReflectKit.java | 135 ++-- .../blade/kit/resource/JarReaderImpl.java | 2 +- 19 files changed, 519 insertions(+), 761 deletions(-) delete mode 100644 blade-kit/src/main/java/blade/exception/BladeException.java delete mode 100644 blade-kit/src/main/java/blade/exception/ClassReaderException.java delete mode 100644 blade-kit/src/main/java/blade/exception/ExceptionHandlerImpl.java delete mode 100644 blade-kit/src/main/java/blade/exception/ExceptionStack.java delete mode 100644 blade-kit/src/main/java/blade/exception/IllegalPathException.java delete mode 100644 blade-kit/src/main/java/blade/exception/package-info.java diff --git a/blade-core/pom.xml b/blade-core/pom.xml index bee2f9e67..745d82919 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -28,7 +28,7 @@ com.bladejava blade-kit - 1.2.8-alpha + 1.2.8-beta com.bladejava diff --git a/blade-core/src/main/java/com/blade/Aop.java b/blade-core/src/main/java/com/blade/Aop.java index 1666720a5..cc3f7fc39 100644 --- a/blade-core/src/main/java/com/blade/Aop.java +++ b/blade-core/src/main/java/com/blade/Aop.java @@ -17,6 +17,7 @@ import com.blade.ioc.AopCreator; +import blade.kit.Assert; import blade.kit.ReflectKit; /** @@ -40,20 +41,31 @@ public final class Aop { } public static Object create(Class clazz){ + Assert.notNull(clazz); if(AOP_OPEN){ return AopCreator.create(clazz); } else { - return ReflectKit.newInstance(clazz); + try { + return ReflectKit.newInstance(clazz); + } catch (Exception e) { + new RuntimeException("create object error", e); + } } + return null; } public static T createT(Class clazz){ + Assert.notNull(clazz); if(AOP_OPEN){ return AopCreator.create(clazz); } else { - Object object = ReflectKit.newInstance(clazz); - if(null != object){ - return (T) object; + try { + Object object = ReflectKit.newInstance(clazz); + if(null != object){ + return (T) object; + } + } catch (Exception e) { + new RuntimeException("create object error", e); } } return null; diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index f24378ac0..501e582f5 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -21,9 +21,9 @@ import java.util.List; import java.util.Map; +import blade.kit.Assert; import blade.kit.IOKit; import blade.kit.PropertyKit; -import blade.kit.StringKit; import blade.kit.json.JSONKit; import com.blade.ioc.Container; @@ -150,6 +150,7 @@ public Container container(){ * @return 返回blade */ public Blade container(Container container){ + Assert.notNull(container); this.container = container; return this; } @@ -162,6 +163,7 @@ public Blade container(Container container){ * @return 返回Blade单例实例 */ public Blade config(String confName){ + Assert.notBlank(confName); Map configMap = PropertyKit.getPropertyMap(confName); configuration(configMap); return this; @@ -175,6 +177,7 @@ public Blade config(String confName){ * @return 返回Blade单例实例 */ public Blade setAppConf(String confName){ + Assert.notBlank(confName); Map configMap = PropertyKit.getPropertyMap(confName); configuration(configMap); return this; @@ -188,6 +191,7 @@ public Blade setAppConf(String confName){ * @return 返回Blade单例实例 */ public Blade setJsonConf(String jsonPath){ + Assert.notBlank(jsonPath); InputStream inputStream = Blade.class.getResourceAsStream(jsonPath); if(null != inputStream){ try { @@ -210,6 +214,7 @@ public Blade setJsonConf(String jsonPath){ * @return 返回Blade单例实例 */ public Blade setAppJson(String json){ + Assert.notBlank(json); Map configMap = JSONKit.toMap(json); configuration(configMap); return this; @@ -223,6 +228,7 @@ public Blade setAppJson(String json){ * @param configMap 存放配置的map */ private void configuration(Map configMap){ + Assert.notEmpty(configMap); new Configurator(config, configMap).run(); } @@ -234,9 +240,8 @@ private void configuration(Map configMap){ * @return 返回Blade单例实例 */ public Blade routes(String...packages){ - if(null != packages && packages.length >0){ - config.setRoutePackages(packages); - } + Assert.notNull(packages); + config.setRoutePackages(packages); return this; } @@ -248,9 +253,8 @@ public Blade routes(String...packages){ * @return 返回Blade单例实例 */ public Blade defaultRoute(String basePackage){ - if(null != basePackage){ - config.setBasePackage(basePackage); - } + Assert.notBlank(basePackage); + config.setBasePackage(basePackage); return this; } @@ -261,9 +265,8 @@ public Blade defaultRoute(String basePackage){ * @return 返回Blade单例实例 */ public Blade interceptor(String packageName) { - if(null != packageName && packageName.length() >0){ - config.setInterceptorPackage(packageName); - } + Assert.notBlank(packageName); + config.setInterceptorPackage(packageName); return this; } @@ -274,7 +277,8 @@ public Blade interceptor(String packageName) { * @return 返回Blade单例实例 */ public Blade ioc(String...packages){ - if(null != packages && packages.length >0){ + Assert.notNull(packages); + if(packages.length >0){ config.setIocPackages(packages); } return this; @@ -448,6 +452,7 @@ public Blade after(String path, RouteHandler handler){ * @return 返回Blade单例实例 */ public Blade viewEngin(Render render) { + Assert.notNull(render); this.render = render; return this; } @@ -459,7 +464,8 @@ public Blade viewEngin(Render render) { * @return 返回Blade单例实例 */ public Blade viewPrefix(final String prefix) { - if(StringKit.isNotBlank(prefix) && prefix.startsWith("/")){ + Assert.notBlank(prefix); + if(prefix.startsWith("/")){ config.setViewPrefix(prefix); } return this; @@ -472,7 +478,8 @@ public Blade viewPrefix(final String prefix) { * @return 返回Blade单例实例 */ public Blade viewSuffix(final String suffix) { - if(StringKit.isNotBlank(suffix) && suffix.startsWith(".")){ + Assert.notBlank(suffix); + if(suffix.startsWith(".")){ config.setViewSuffix(suffix); } return this; @@ -486,6 +493,8 @@ public Blade viewSuffix(final String suffix) { * @return 返回Blade单例实例 */ public Blade view(final String viewPath, final String viewExt) { + Assert.notBlank(viewPath); + Assert.notBlank(viewExt); viewPrefix(viewPath); viewSuffix(viewExt); return this; @@ -498,6 +507,7 @@ public Blade view(final String viewPath, final String viewExt) { * @return 返回Blade单例实例 */ public Blade staticFolder(final String ... folders) { + Assert.notNull(folders); config.setStaticFolders(folders); return this; } @@ -520,6 +530,7 @@ public Blade enableXSS(boolean enableXSS){ * @return 返回Blade单例实例 */ public Blade app(Bootstrap bootstrap){ + Assert.notNull(bootstrap); this.bootstrap = bootstrap; return this; } @@ -531,6 +542,7 @@ public Blade app(Bootstrap bootstrap){ * @return 返回Blade单例实例 */ public Blade app(Class bootstrap){ + Assert.notNull(bootstrap); Object object = container.registerBean(Aop.create(bootstrap)); this.bootstrap = (Bootstrap) object; return this; @@ -543,6 +555,7 @@ public Blade app(Class bootstrap){ * @return 返回Blade单例实例 */ public Blade setView404(final String view404){ + Assert.notBlank(view404); config.setView404(view404); return this; } @@ -554,6 +567,7 @@ public Blade setView404(final String view404){ * @return 返回Blade单例实例 */ public Blade setView500(final String view500){ + Assert.notBlank(view500); config.setView500(view500); return this; } @@ -565,6 +579,7 @@ public Blade setView500(final String view500){ * @return 返回Blade单例实例 */ public Blade webRoot(final String webRoot){ + Assert.notBlank(webRoot); config.setWebRoot(webRoot); return this; } @@ -608,6 +623,7 @@ public Blade isAsyn(boolean isAsyn){ */ public void start(String contextPath) { try { + Assert.notBlank(contextPath); bladeServer = new Server(this.port, this.isAsyn); bladeServer.start(contextPath); } catch (Exception e) { @@ -761,6 +777,7 @@ public boolean enableXSS(){ */ @SuppressWarnings("unchecked") public T plugin(Class plugin){ + Assert.notNull(plugin); Object object = iocApplication.getPlugin(plugin); if(null == object){ object = iocApplication.registerPlugin(plugin); @@ -777,6 +794,8 @@ public T plugin(Class plugin){ */ public Blade routeConf(String basePackage, String conf) { try { + Assert.notBlank(basePackage); + Assert.notBlank(conf); InputStream ins = Blade.class.getResourceAsStream("/" + conf); ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); routesLoader.setBasePackage(basePackage); diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java index 75ac7df29..7184ba32f 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -23,7 +23,7 @@ import java.util.Map; import java.util.Set; -import blade.exception.BladeException; +import blade.kit.Assert; import blade.kit.CloneKit; import blade.kit.CollectionKit; import blade.kit.StringKit; @@ -69,7 +69,7 @@ public Map getBeanMap() { @Override public T getBean(String name, Scope scope) { - + Assert.notBlank(name); String className = beanKeys.get(name); if(StringKit.isBlank(className)){ if(null == beans.get(name)){ @@ -92,6 +92,7 @@ public T getBean(String name, Scope scope) { @Override public T getBean(Class type, Scope scope) { + Assert.notNull(type); return this.getBean(type.getName(), scope); } @@ -107,17 +108,20 @@ public Collection getBeans() { @Override public boolean hasBean(Class clazz) { + Assert.notNull(clazz); String className = clazz.getName(); return beanKeys.containsValue(className); } @Override public boolean hasBean(String name) { + Assert.notBlank(name); return null != beanKeys.get(name); } @Override public boolean removeBean(String name) { + Assert.notBlank(name); String className = beanKeys.get(name); if(StringKit.isBlank(className)){ className = name; @@ -130,11 +134,15 @@ public boolean removeBean(String name) { @Override public boolean removeBean(Class clazz) { + Assert.notNull(clazz); return this.removeBean(clazz.getName()); } @Override public Object registerBean(String name, Object value) { + Assert.notBlank(name); + Assert.notNull(value); + Class clazz = value.getClass(); //非抽象类、接口 if (isNormalClass(clazz)) { @@ -169,6 +177,10 @@ public Object registerBean(String name, Object value) { } private void registerParent(String name, Object value) { + + Assert.notBlank(name); + Assert.notNull(value); + Class clazz = value.getClass(); // 如果容器已经存在该名称对于的对象,直接返回 @@ -185,6 +197,9 @@ private void registerParent(String name, Object value) { @Override public Object registerBean(Object object) { + + Assert.notNull(object); + String className = object.getClass().getName(); return registerBean(className, object); } @@ -196,6 +211,7 @@ public Object registerBean(Object object) { * @param object 注册的bean对象 */ private void putAnnotationMap(Class clazz, Object object){ + Annotation[] annotations = clazz.getAnnotations(); List listObject = null; for(Annotation annotation : annotations){ @@ -336,7 +352,7 @@ public void injection(Object object) { } if (null == injectField) { - throw new BladeException("Unable to load " + field.getType().getName() + "!"); + throw new RuntimeException("Unable to load " + field.getType().getName() + "!"); } boolean accessible = field.isAccessible(); diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 2b99e37d5..42f0970db 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; +import blade.kit.Assert; import blade.kit.log.Logger; import com.blade.Aop; @@ -87,6 +88,7 @@ public void addRoute(Route route) { } public void addRoutes(List routes) { + Assert.notNull(routes); for(Route route : routes){ this.addRoute(route); } @@ -99,6 +101,11 @@ public void addRoute(HttpMethod httpMethod, String path, Object controller, Stri public void addRoute(HttpMethod httpMethod, String path, Object controller, Method method) { + Assert.notNull(httpMethod); + Assert.notBlank(path); + Assert.notNull(controller); + Assert.notNull(method); + String key = path + "#" + httpMethod.toString(); // 存在的 if (null != this.routes.get(key)) { diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index 1edbfbeba..4e5f2738c 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -8,7 +8,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import blade.exception.BladeException; import blade.kit.StringKit; import blade.kit.base.ThrowableKit; import blade.kit.log.Logger; @@ -109,22 +108,7 @@ public void run(){ render404(response, uri); asyncContext.complete(); return; - } catch (BladeException bex) { - - String error = ThrowableKit.getStackTraceAsString(bex); - LOGGER.error(error); - ThrowableKit.propagate(bex); - - httpResponse.setStatus(500); - // 写入内容到浏览器 - if (!httpResponse.isCommitted()) { - response.html(Const.INTERNAL_ERROR); - asyncContext.complete(); - return; - } - - } catch (Exception e) { - + } catch (Exception e) { String error = ThrowableKit.getStackTraceAsString(e); LOGGER.error(error); ThrowableKit.propagate(e); diff --git a/blade-core/src/main/java/com/blade/web/RouteArgument.java b/blade-core/src/main/java/com/blade/web/RouteArgument.java index c174e77a6..a2477ee4c 100644 --- a/blade-core/src/main/java/com/blade/web/RouteArgument.java +++ b/blade-core/src/main/java/com/blade/web/RouteArgument.java @@ -67,11 +67,15 @@ public static Object[] getArgs(Request request, Response response, Class[] pa public static Object executeMethod(Object object, Method method, Request request, Response response){ int len = method.getParameterTypes().length; method.setAccessible(true); - if(len > 0){ - Object[] args = getArgs(request, response, method.getParameterTypes()); - return ReflectKit.invokeMehod(object, method, args); - } else { - return ReflectKit.invokeMehod(object, method); + try { + if(len > 0){ + Object[] args = getArgs(request, response, method.getParameterTypes()); + return ReflectKit.invokeMehod(object, method, args); + } else { + return ReflectKit.invokeMehod(object, method); + } + } catch (Exception e) { + throw new RuntimeException("invoke method error.", e); } } } diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index e49f22190..abb51d076 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -7,7 +7,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import blade.exception.BladeException; import blade.kit.StringKit; import blade.kit.base.ThrowableKit; import blade.kit.log.Logger; @@ -97,20 +96,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo // 没有找到 render404(response, uri); return; - } catch (BladeException bex) { - - String error = ThrowableKit.getStackTraceAsString(bex); - LOGGER.error(error); - ThrowableKit.propagate(bex); - - httpResponse.setStatus(500); - // 写入内容到浏览器 - if (!httpResponse.isCommitted()) { - response.html(Const.INTERNAL_ERROR); - return; - } - - } catch (Exception e) { + } catch (Exception e) { String error = ThrowableKit.getStackTraceAsString(e); LOGGER.error(error); diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index 8c7b8ba90..ad18ec14e 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - 1.2.8-alpha + 1.2.8-beta blade-kit https://github.com/biezhi/blade/tree/master/blade-kit diff --git a/blade-kit/src/main/java/blade/exception/BladeException.java b/blade-kit/src/main/java/blade/exception/BladeException.java deleted file mode 100644 index 7941c81a2..000000000 --- a/blade-kit/src/main/java/blade/exception/BladeException.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.exception; - - -/** - * blade运行时异常基类 - * - * @author biezhi - * @since 1.0 - */ -public class BladeException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - public BladeException() { - super(); - } - - public BladeException(String body) { - super(body); - } - - public BladeException(String body, Throwable cause){ - super(body, cause); - } - - public BladeException(Throwable cause){ - super(cause); - } - - public Throwable fillInStackTrace() { - return null; - } - -} diff --git a/blade-kit/src/main/java/blade/exception/ClassReaderException.java b/blade-kit/src/main/java/blade/exception/ClassReaderException.java deleted file mode 100644 index 93f49cb46..000000000 --- a/blade-kit/src/main/java/blade/exception/ClassReaderException.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.exception; - -/** - * 类读取异常 - * - * @author biezhi - * @since 1.0 - */ -public class ClassReaderException extends RuntimeException { - - private static final long serialVersionUID = -1L; - - public ClassReaderException() { - super(); - } - - public ClassReaderException(Exception e) { - super(e); - } - - public ClassReaderException(String msg) { - super(msg); - } - - public ClassReaderException(String msg, Exception e) { - super(msg, e); - } - - public Throwable fillInStackTrace() { - return null; - } -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/exception/ExceptionHandlerImpl.java b/blade-kit/src/main/java/blade/exception/ExceptionHandlerImpl.java deleted file mode 100644 index 6107b651e..000000000 --- a/blade-kit/src/main/java/blade/exception/ExceptionHandlerImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.exception; - -/** - * ExceptionHandlerImpl - * - * @author biezhi - * @since 1.0 - */ -public abstract class ExceptionHandlerImpl { - - protected Class exceptionClass; - - public ExceptionHandlerImpl(Class exceptionClass) { - this.exceptionClass = exceptionClass; - } - - public Class exceptionClass() { - return this.exceptionClass; - } - - public void exceptionClass(Class exceptionClass) { - this.exceptionClass = exceptionClass; - } - - public Throwable fillInStackTrace() { - return null; - } -} diff --git a/blade-kit/src/main/java/blade/exception/ExceptionStack.java b/blade-kit/src/main/java/blade/exception/ExceptionStack.java deleted file mode 100644 index c72b8a1ac..000000000 --- a/blade-kit/src/main/java/blade/exception/ExceptionStack.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.exception; - -import java.util.HashMap; -import java.util.Map; - -/** - * 异常栈 - * - * @author biezhi - * @since 1.0 - */ -public class ExceptionStack { - - private static ExceptionStack defaultInstance; - - - public static ExceptionStack getInstance() { - if (defaultInstance == null) { - defaultInstance = new ExceptionStack(); - } - return defaultInstance; - } - - private Map, ExceptionHandlerImpl> exceptionMap; - - public ExceptionStack() { - this.exceptionMap = new HashMap, ExceptionHandlerImpl>(); - } - - public void map(Class exceptionClass, ExceptionHandlerImpl handler) { - this.exceptionMap.put(exceptionClass, handler); - } - - public ExceptionHandlerImpl getHandler(Class exceptionClass) { - if (!this.exceptionMap.containsKey(exceptionClass)) { - - Class superclass = exceptionClass.getSuperclass(); - do { - if (this.exceptionMap.containsKey(superclass)) { - ExceptionHandlerImpl handler = this.exceptionMap.get(superclass); - this.exceptionMap.put(exceptionClass, handler); - return handler; - } - - superclass = superclass.getSuperclass(); - } while (superclass != null); - - this.exceptionMap.put(exceptionClass, null); - return null; - } - - return this.exceptionMap.get(exceptionClass); - } - - public ExceptionHandlerImpl getHandler(Exception exception) { - return this.getHandler(exception.getClass()); - } - - public Throwable fillInStackTrace() { - return null; - } -} diff --git a/blade-kit/src/main/java/blade/exception/IllegalPathException.java b/blade-kit/src/main/java/blade/exception/IllegalPathException.java deleted file mode 100644 index 3c8362144..000000000 --- a/blade-kit/src/main/java/blade/exception/IllegalPathException.java +++ /dev/null @@ -1,35 +0,0 @@ -package blade.exception; - -/** - * 代表非法的路径。 - * - * @author biezhi - * @since 1.0 - */ -public class IllegalPathException extends IllegalArgumentException { - - /** - * - */ - private static final long serialVersionUID = 1434004725746713564L; - - public IllegalPathException() { - super(); - } - - public IllegalPathException(String message, Throwable cause) { - super(message, cause); - } - - public IllegalPathException(String s) { - super(s); - } - - public IllegalPathException(Throwable cause) { - super(cause); - } - - public Throwable fillInStackTrace() { - return null; - } -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/exception/package-info.java b/blade-kit/src/main/java/blade/exception/package-info.java deleted file mode 100644 index ccd1136b2..000000000 --- a/blade-kit/src/main/java/blade/exception/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * blade异常包 - */ -package blade.exception; \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/Assert.java b/blade-kit/src/main/java/blade/kit/Assert.java index 152926146..fcacaa458 100644 --- a/blade-kit/src/main/java/blade/kit/Assert.java +++ b/blade-kit/src/main/java/blade/kit/Assert.java @@ -1,365 +1,365 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; - -import java.util.Collection; -import java.util.Map; - -/** - * 断言工具类 - * - * @author biezhi - * @since 1.0 - * - */ -public abstract class Assert { - - private static final String DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE = "The value %s is not in the specified exclusive range of %s to %s"; - private static final String DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE = "The value %s is not in the specified inclusive range of %s to %s"; - private static final String DEFAULT_IS_TRUE_EX_MESSAGE = "The validated expression is false"; - private static final String DEFAULT_IS_FALSE_EX_MESSAGE = "The validated expression is true"; - private static final String DEFAULT_NOT_BLANK_EX_MESSAGE = "The validated character sequence is blank"; - private static final String DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE = "The validated array is empty"; - private static final String DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE = "The validated character sequence is empty"; - private static final String DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE = "The validated collection is empty"; - private static final String DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE = "The validated map is empty"; - private static final String DEFAULT_IS_ASSIGNABLE_EX_MESSAGE = "Cannot assign a %s to a %s"; - private static final String DEFAULT_IS_INSTANCE_OF_EX_MESSAGE = "Expected type: %s, actual: %s"; - - public static void isTrue(boolean expression, String message) { - if (!expression) { - throw new IllegalArgumentException(message); - } - } - - public static void notNull(Object object, String message) { - if (object == null) { - throw new IllegalArgumentException(message); - } - } - - public static void notNull(Object object) { - notNull(object, "[Assertion failed] - this argument is required; it must not be null"); - } - - public static T checkNotNull(T reference) { - if (reference == null) { - throw new NullPointerException(); - } - return reference; - } - - public static void checkPositionIndexes(int start, int end, int size) { - // Carefully optimized for execution by hotspot (explanatory comment - // above) - if (start < 0 || end < start || end > size) { - throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); - } - } - - private static String badPositionIndexes(int start, int end, int size) { - if (start < 0 || start > size) { - return badPositionIndex(start, size, "start index"); - } - if (end < 0 || end > size) { - return badPositionIndex(end, size, "end index"); - } - // end < start - return format("end index (%s) must not be less than start index (%s)", end, start); - } - - private static String badPositionIndex(int index, int size, String desc) { - if (index < 0) { - return format("%s (%s) must not be negative", desc, index); - } else if (size < 0) { - throw new IllegalArgumentException("negative size: " + size); - } else { // index > size - return format("%s (%s) must not be greater than size (%s)", desc, index, size); - } - } - - /** - * Substitutes each {@code %s} in {@code template} with an argument. These are matched by - * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than - * placeholders, the unmatched arguments will be appended to the end of the formatted message in - * square braces. - * - * @param template a non-null string containing 0 or more {@code %s} placeholders. - * @param args the arguments to be substituted into the message template. Arguments are converted - * to strings using {@link String#valueOf(Object)}. Arguments can be null. - */ - // Note that this is somewhat-improperly used from Verify.java as well. - static String format(String template, Object... args) { - template = String.valueOf(template); // null -> "null" - - // start substituting the arguments into the '%s' placeholders - StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); - int templateStart = 0; - int i = 0; - while (i < args.length) { - int placeholderStart = template.indexOf("%s", templateStart); - if (placeholderStart == -1) { - break; - } - builder.append(template.substring(templateStart, placeholderStart)); - builder.append(args[i++]); - templateStart = placeholderStart + 2; - } - builder.append(template.substring(templateStart)); - - // if we run out of placeholders, append the extra args in square braces - if (i < args.length) { - builder.append(" ["); - builder.append(args[i++]); - while (i < args.length) { - builder.append(", "); - builder.append(args[i++]); - } - builder.append(']'); - } - - return builder.toString(); - } - - public static void hasLength(String text, String message) { - if (StringKit.isEmpty(text)) { - throw new IllegalArgumentException(message); - } - } - - public static void state(boolean expression, String message) { - if (!expression) { - throw new IllegalStateException(message); - } - } - - public static void isTrue(boolean expression) { - if (expression == false) { - throw new IllegalArgumentException(DEFAULT_IS_TRUE_EX_MESSAGE); - } - } - - public static void isTrue(boolean expression, String message, Object... values) { - if (expression == false) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void isFalse(boolean expression) { - if (expression) { - throw new IllegalArgumentException(DEFAULT_IS_FALSE_EX_MESSAGE); - } - } - - public static void isFalse(boolean expression, String message, Object... values) { - if (expression) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void notNull(Object object, String message, Object... values) { - if (object == null) { - throw new NullPointerException(String.format(message, values)); - } - } - - public static void notEmpty(Object[] array) { - if (array == null) { - throw new NullPointerException(DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE); - } - if (array.length == 0) { - throw new IllegalArgumentException(DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE); - } - } - - public static void notEmpty(Object[] array, String message, Object... values) { - if (array == null) { - throw new NullPointerException(String.format(message, values)); - } - if (array.length == 0) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void notEmpty(Collection collection) { - if (collection == null) { - throw new NullPointerException(DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE); - } - if (collection.size() == 0) { - throw new IllegalArgumentException(DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE); - } - } - - public static void notEmpty(Collection collection, String message, Object... values) { - if (collection == null) { - throw new NullPointerException(String.format(message, values)); - } - if (collection.size() == 0) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void notEmpty(Map map) { - if (map == null) { - throw new NullPointerException(DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE); - } - if (map.size() == 0) { - throw new IllegalArgumentException(DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE); - } - } - - public static void notEmpty(Map map, String message, Object... values) { - if (map == null) { - throw new NullPointerException(String.format(message, values)); - } - if (map.size() == 0) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void notEmpty(CharSequence str) { - if (str == null) { - throw new NullPointerException(DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE); - } - if (str.length() == 0) { - throw new IllegalArgumentException(DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE); - } - } - - public static void notEmpty(CharSequence str, String message, Object... values) { - if (str == null) { - throw new NullPointerException(String.format(message, values)); - } - if (str.length() == 0) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void notBlank(CharSequence str) { - if (str == null) { - throw new NullPointerException(DEFAULT_NOT_BLANK_EX_MESSAGE); - } - if (str.toString().trim().length() == 0) { - throw new IllegalArgumentException(DEFAULT_NOT_BLANK_EX_MESSAGE); - } - } - - public static void notBlank(CharSequence str, String message, Object... values) { - if (str == null) { - throw new NullPointerException(String.format(message, values)); - } - if (str.toString().trim().length() == 0) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void inclusiveBetween(final T start, final T end, final Comparable value) { - if (value.compareTo(start) < 0 || value.compareTo(end) > 0) { - throw new IllegalArgumentException(String.format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); - } - } - - public static void inclusiveBetween(final T start, final T end, final Comparable value, final String message, final Object... values) { - if (value.compareTo(start) < 0 || value.compareTo(end) > 0) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void inclusiveBetween(long start, long end, long value) { - if (value < start || value > end) { - throw new IllegalArgumentException(String.format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); - } - } - - public static void inclusiveBetween(long start, long end, long value, final String message, final Object... values) { - if (value < start || value > end) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void inclusiveBetween(double start, double end, double value) { - if (value < start || value > end) { - throw new IllegalArgumentException(String.format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); - } - } - - public static void inclusiveBetween(double start, double end, double value, final String message, final Object... values) { - if (value < start || value > end) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void exclusiveBetween(final T start, final T end, final Comparable value) { - if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) { - throw new IllegalArgumentException(String.format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); - } - } - - public static void exclusiveBetween(final T start, final T end, final Comparable value, final String message, final Object... values) { - if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void exclusiveBetween(long start, long end, long value) { - if (value <= start || value >= end) { - throw new IllegalArgumentException(String.format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); - } - } - - public static void exclusiveBetween(long start, long end, long value, final String message, final Object... values) { - if (value <= start || value >= end) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void exclusiveBetween(double start, double end, double value) { - if (value <= start || value >= end) { - throw new IllegalArgumentException(String.format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); - } - } - - public static void exclusiveBetween(double start, double end, double value, final String message, final Object... values) { - if (value <= start || value >= end) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void isInstanceOf(Class type, Object obj) { - if (type.isInstance(obj) == false) { - throw new IllegalArgumentException(String.format(DEFAULT_IS_INSTANCE_OF_EX_MESSAGE, type.getName(), obj == null ? "null" : obj.getClass().getName())); - } - } - - public static void isInstanceOf(Class type, Object obj, String message, Object... values) { - if (type.isInstance(obj) == false) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - - public static void isAssignableFrom(Class superType, Class type) { - if (superType.isAssignableFrom(type) == false) { - throw new IllegalArgumentException(String.format(DEFAULT_IS_ASSIGNABLE_EX_MESSAGE, type == null ? "null" : type.getName(), superType.getName())); - } - } - - public static void isAssignableFrom(Class superType, Class type, String message, Object... values) { - if (superType.isAssignableFrom(type) == false) { - throw new IllegalArgumentException(String.format(message, values)); - } - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; + +import java.util.Collection; +import java.util.Map; + +/** + * 断言工具类 + * + * @author biezhi + * @since 1.0 + * + */ +public abstract class Assert { + + private static final String DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE = "The value %s is not in the specified exclusive range of %s to %s"; + private static final String DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE = "The value %s is not in the specified inclusive range of %s to %s"; + private static final String DEFAULT_IS_TRUE_EX_MESSAGE = "The validated expression is false"; + private static final String DEFAULT_IS_FALSE_EX_MESSAGE = "The validated expression is true"; + private static final String DEFAULT_NOT_BLANK_EX_MESSAGE = "The validated character sequence is blank"; + private static final String DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE = "The validated array is empty"; + private static final String DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE = "The validated character sequence is empty"; + private static final String DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE = "The validated collection is empty"; + private static final String DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE = "The validated map is empty"; + private static final String DEFAULT_IS_ASSIGNABLE_EX_MESSAGE = "Cannot assign a %s to a %s"; + private static final String DEFAULT_IS_INSTANCE_OF_EX_MESSAGE = "Expected type: %s, actual: %s"; + + public static void isTrue(boolean expression, String message) { + if (!expression) { + throw new IllegalArgumentException(message); + } + } + + public static void notNull(Object object, String message) { + if (object == null) { + throw new NullPointerException(message); + } + } + + public static void notNull(Object object) { + notNull(object, "[Assertion failed] - this argument is required; it must not be null"); + } + + public static T checkNotNull(T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } + + public static void checkPositionIndexes(int start, int end, int size) { + // Carefully optimized for execution by hotspot (explanatory comment + // above) + if (start < 0 || end < start || end > size) { + throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); + } + } + + private static String badPositionIndexes(int start, int end, int size) { + if (start < 0 || start > size) { + return badPositionIndex(start, size, "start index"); + } + if (end < 0 || end > size) { + return badPositionIndex(end, size, "end index"); + } + // end < start + return format("end index (%s) must not be less than start index (%s)", end, start); + } + + private static String badPositionIndex(int index, int size, String desc) { + if (index < 0) { + return format("%s (%s) must not be negative", desc, index); + } else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } else { // index > size + return format("%s (%s) must not be greater than size (%s)", desc, index, size); + } + } + + /** + * Substitutes each {@code %s} in {@code template} with an argument. These are matched by + * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than + * placeholders, the unmatched arguments will be appended to the end of the formatted message in + * square braces. + * + * @param template a non-null string containing 0 or more {@code %s} placeholders. + * @param args the arguments to be substituted into the message template. Arguments are converted + * to strings using {@link String#valueOf(Object)}. Arguments can be null. + */ + // Note that this is somewhat-improperly used from Verify.java as well. + static String format(String template, Object... args) { + template = String.valueOf(template); // null -> "null" + + // start substituting the arguments into the '%s' placeholders + StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); + int templateStart = 0; + int i = 0; + while (i < args.length) { + int placeholderStart = template.indexOf("%s", templateStart); + if (placeholderStart == -1) { + break; + } + builder.append(template.substring(templateStart, placeholderStart)); + builder.append(args[i++]); + templateStart = placeholderStart + 2; + } + builder.append(template.substring(templateStart)); + + // if we run out of placeholders, append the extra args in square braces + if (i < args.length) { + builder.append(" ["); + builder.append(args[i++]); + while (i < args.length) { + builder.append(", "); + builder.append(args[i++]); + } + builder.append(']'); + } + + return builder.toString(); + } + + public static void hasLength(String text, String message) { + if (StringKit.isEmpty(text)) { + throw new IllegalArgumentException(message); + } + } + + public static void state(boolean expression, String message) { + if (!expression) { + throw new IllegalStateException(message); + } + } + + public static void isTrue(boolean expression) { + if (expression == false) { + throw new IllegalArgumentException(DEFAULT_IS_TRUE_EX_MESSAGE); + } + } + + public static void isTrue(boolean expression, String message, Object... values) { + if (expression == false) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void isFalse(boolean expression) { + if (expression) { + throw new IllegalArgumentException(DEFAULT_IS_FALSE_EX_MESSAGE); + } + } + + public static void isFalse(boolean expression, String message, Object... values) { + if (expression) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void notNull(Object object, String message, Object... values) { + if (object == null) { + throw new NullPointerException(String.format(message, values)); + } + } + + public static void notEmpty(Object[] array) { + if (array == null) { + throw new NullPointerException(DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE); + } + if (array.length == 0) { + throw new IllegalArgumentException(DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE); + } + } + + public static void notEmpty(Object[] array, String message, Object... values) { + if (array == null) { + throw new NullPointerException(String.format(message, values)); + } + if (array.length == 0) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void notEmpty(Collection collection) { + if (collection == null) { + throw new NullPointerException(DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE); + } + if (collection.size() == 0) { + throw new IllegalArgumentException(DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE); + } + } + + public static void notEmpty(Collection collection, String message, Object... values) { + if (collection == null) { + throw new NullPointerException(String.format(message, values)); + } + if (collection.size() == 0) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void notEmpty(Map map) { + if (map == null) { + throw new NullPointerException(DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE); + } + if (map.size() == 0) { + throw new IllegalArgumentException(DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE); + } + } + + public static void notEmpty(Map map, String message, Object... values) { + if (map == null) { + throw new NullPointerException(String.format(message, values)); + } + if (map.size() == 0) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void notEmpty(CharSequence str) { + if (str == null) { + throw new NullPointerException(DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE); + } + if (str.length() == 0) { + throw new IllegalArgumentException(DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE); + } + } + + public static void notEmpty(CharSequence str, String message, Object... values) { + if (str == null) { + throw new NullPointerException(String.format(message, values)); + } + if (str.length() == 0) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void notBlank(CharSequence str) { + if (str == null) { + throw new NullPointerException(DEFAULT_NOT_BLANK_EX_MESSAGE); + } + if (str.toString().trim().length() == 0) { + throw new IllegalArgumentException(DEFAULT_NOT_BLANK_EX_MESSAGE); + } + } + + public static void notBlank(CharSequence str, String message, Object... values) { + if (str == null) { + throw new NullPointerException(String.format(message, values)); + } + if (str.toString().trim().length() == 0) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void inclusiveBetween(final T start, final T end, final Comparable value) { + if (value.compareTo(start) < 0 || value.compareTo(end) > 0) { + throw new IllegalArgumentException(String.format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); + } + } + + public static void inclusiveBetween(final T start, final T end, final Comparable value, final String message, final Object... values) { + if (value.compareTo(start) < 0 || value.compareTo(end) > 0) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void inclusiveBetween(long start, long end, long value) { + if (value < start || value > end) { + throw new IllegalArgumentException(String.format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); + } + } + + public static void inclusiveBetween(long start, long end, long value, final String message, final Object... values) { + if (value < start || value > end) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void inclusiveBetween(double start, double end, double value) { + if (value < start || value > end) { + throw new IllegalArgumentException(String.format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); + } + } + + public static void inclusiveBetween(double start, double end, double value, final String message, final Object... values) { + if (value < start || value > end) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void exclusiveBetween(final T start, final T end, final Comparable value) { + if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) { + throw new IllegalArgumentException(String.format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); + } + } + + public static void exclusiveBetween(final T start, final T end, final Comparable value, final String message, final Object... values) { + if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void exclusiveBetween(long start, long end, long value) { + if (value <= start || value >= end) { + throw new IllegalArgumentException(String.format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); + } + } + + public static void exclusiveBetween(long start, long end, long value, final String message, final Object... values) { + if (value <= start || value >= end) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void exclusiveBetween(double start, double end, double value) { + if (value <= start || value >= end) { + throw new IllegalArgumentException(String.format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end)); + } + } + + public static void exclusiveBetween(double start, double end, double value, final String message, final Object... values) { + if (value <= start || value >= end) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void isInstanceOf(Class type, Object obj) { + if (type.isInstance(obj) == false) { + throw new IllegalArgumentException(String.format(DEFAULT_IS_INSTANCE_OF_EX_MESSAGE, type.getName(), obj == null ? "null" : obj.getClass().getName())); + } + } + + public static void isInstanceOf(Class type, Object obj, String message, Object... values) { + if (type.isInstance(obj) == false) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + public static void isAssignableFrom(Class superType, Class type) { + if (superType.isAssignableFrom(type) == false) { + throw new IllegalArgumentException(String.format(DEFAULT_IS_ASSIGNABLE_EX_MESSAGE, type == null ? "null" : type.getName(), superType.getName())); + } + } + + public static void isAssignableFrom(Class superType, Class type, String message, Object... values) { + if (superType.isAssignableFrom(type) == false) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + +} diff --git a/blade-kit/src/main/java/blade/kit/FileKit.java b/blade-kit/src/main/java/blade/kit/FileKit.java index 4d9511132..3f1409f4a 100644 --- a/blade-kit/src/main/java/blade/kit/FileKit.java +++ b/blade-kit/src/main/java/blade/kit/FileKit.java @@ -29,7 +29,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import blade.exception.IllegalPathException; +import blade.kit.exception.IllegalPathException; /** * 有关文件处理的工具类。 @@ -42,14 +42,6 @@ */ public abstract class FileKit { - /* - * ========================================================================== == - */ - /* 常量和singleton。 */ - /* - * ========================================================================== == - */ - private static final char COLON_CHAR = ':'; private static final String UNC_PREFIX = "//"; private static final String SLASH = "/"; @@ -111,7 +103,7 @@ public static File toFile(URL url) { public static boolean exist(String path) { return (path == null) ? false : new File(path).exists(); } - + /** * 判断文件是否存在,如果file为null,则返回false * diff --git a/blade-kit/src/main/java/blade/kit/ReflectKit.java b/blade-kit/src/main/java/blade/kit/ReflectKit.java index bab56a071..a03f82bf6 100644 --- a/blade-kit/src/main/java/blade/kit/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/ReflectKit.java @@ -18,6 +18,7 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.AccessibleObject; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -47,16 +48,15 @@ public abstract class ReflectKit { private static final Logger LOGGER = Logger.getLogger(ReflectKit.class); // ------------------------------------------------------ - /** 新建对象 */ - public static Object newInstance(String className) { + /** 新建对象 + * @throws IllegalAccessException + * @throws InstantiationException + * @throws ClassNotFoundException */ + public static Object newInstance(String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException { Object obj = null; - try { - Class clazz = Class.forName(className); - obj = clazz.newInstance(); - LOGGER.debug("new %s", className); - } catch (Exception e) { - // quiet - } + Class clazz = Class.forName(className); + obj = clazz.newInstance(); + LOGGER.debug("new %s", className); return obj; } @@ -64,26 +64,27 @@ public static Object newInstance(String className) { * 创建一个实例对象 * @param clazz class对象 * @return + * @throws IllegalAccessException + * @throws InstantiationException */ - public static Object newInstance(Class clazz){ - try { - return clazz.newInstance(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; + public static Object newInstance(Class clazz) throws InstantiationException, IllegalAccessException{ + return clazz.newInstance(); } - /** 用setter设置bean属性 */ - public static void setProperty(Object bean, String name, Object value) { + /** 用setter设置bean属性 + * @throws InvocationTargetException + * @throws IllegalArgumentException + * @throws IllegalAccessException */ + public static void setProperty(Object bean, String name, Object value) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { String methodName = "set" + StringKit.firstUpperCase(name); invokeMehodByName(bean, methodName, value); } - /** 用getter获取bean属性 */ - public static Object getProperty(Object bean, String name) { + /** 用getter获取bean属性 + * @throws InvocationTargetException + * @throws IllegalArgumentException + * @throws IllegalAccessException */ + public static Object getProperty(Object bean, String name) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { String methodName = "get" + StringKit.firstUpperCase(name); return invokeMehodByName(bean, methodName); } @@ -146,29 +147,25 @@ public static Method getMethodByName(Class clazz, String methodName) { * @param methodName 方法名称 * @param args 方法参数 * @return + * @throws InvocationTargetException + * @throws IllegalArgumentException + * @throws IllegalAccessException */ - public static Object invokeMehodByName(Object bean, String methodName, - Object... args) { - try { - Method method = getMethodByName(bean, methodName); - Class[] types = method.getParameterTypes(); - - int argCount = args == null ? 0 : args.length; + public static Object invokeMehodByName(Object bean, String methodName, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method method = getMethodByName(bean, methodName); + Class[] types = method.getParameterTypes(); - // 参数个数对不上 - ExceptionKit.makeRunTimeWhen(argCount != types.length, - "%s in %s", methodName, bean); + int argCount = args == null ? 0 : args.length; - // 转参数类型 - for (int i = 0; i < argCount; i++) { - args[i] = cast(args[i], types[i]); - } + // 参数个数对不上 + ExceptionKit.makeRunTimeWhen(argCount != types.length, + "%s in %s", methodName, bean); - return method.invoke(bean, args); - } catch (Exception e) { - ExceptionKit.makeRuntime(e); + // 转参数类型 + for (int i = 0; i < argCount; i++) { + args[i] = cast(args[i], types[i]); } - return null; + return method.invoke(bean, args); } /** @@ -177,27 +174,23 @@ public static Object invokeMehodByName(Object bean, String methodName, * @param methodName 方法名称 * @param args 方法参数 * @return + * @throws InvocationTargetException + * @throws IllegalArgumentException + * @throws IllegalAccessException */ - public static Object invokeMehod(Object bean, Method method, - Object... args) { - try { - Class[] types = method.getParameterTypes(); - - int argCount = args == null ? 0 : args.length; + public static Object invokeMehod(Object bean, Method method, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Class[] types = method.getParameterTypes(); - // 参数个数对不上 - ExceptionKit.makeRunTimeWhen(argCount != types.length, "%s in %s", method.getName(), bean); - - // 转参数类型 - for (int i = 0; i < argCount; i++) { - args[i] = cast(args[i], types[i]); - } + int argCount = args == null ? 0 : args.length; - return method.invoke(bean, args); - } catch (Exception e) { - ExceptionKit.makeRuntime(e); + // 参数个数对不上 + ExceptionKit.makeRunTimeWhen(argCount != types.length, "%s in %s", method.getName(), bean); + + // 转参数类型 + for (int i = 0; i < argCount; i++) { + args[i] = cast(args[i], types[i]); } - return null; + return method.invoke(bean, args); } // ------------------------------------------------------ @@ -215,7 +208,7 @@ public static boolean is(Object obj, Object... mybe) { public static boolean isNot(Object obj, Object... mybe) { return !is(obj, mybe); } - + // ------------------------------------------------------ /** 扫描包下面所有的类 */ @@ -291,19 +284,16 @@ private static void scanPackageClassInJar(JarFile jar, String packageDirName, Li * @param target 目标对象 * @param args 方法的参数值 * @return 调用结果 + * @throws InvocationTargetException + * @throws IllegalArgumentException + * @throws IllegalAccessException */ - public static Object invokeMethod(Method method, Object target, Object...args) { + public static Object invokeMethod(Method method, Object target, Object...args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (method == null) { return null; } - method.setAccessible(true); - try { - return method.invoke(target, args); - } catch (Exception ex) { - throw ExceptionKit.toRuntimeException(ex); - } - + return method.invoke(target, args); } /** @@ -317,9 +307,12 @@ public static Object invokeMethod(Method method, Object target, Object...args) { * @param args 参数值 * @param parameterTypes 参数类型 * @return 调用的方法的返回值 + * @throws InvocationTargetException + * @throws IllegalArgumentException + * @throws IllegalAccessException * */ - public static Object invokeMethod(Object object, String methodName, Object[] args, Class...parameterTypes) { + public static Object invokeMethod(Object object, String methodName, Object[] args, Class...parameterTypes) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (object == null || StringKit.isEmpty(methodName)) { return null; } @@ -339,9 +332,7 @@ public static Object invokeMethod(Object object, String methodName, Object[] arg if (method == null) { return null; } - return invokeMethod(method, object, args); - } /** @@ -355,9 +346,12 @@ public static Object invokeMethod(Object object, String methodName, Object[] arg * @param args 参数值 * @param parameterTypes 参数类型 * @return 调用的方法的返回值 + * @throws InvocationTargetException + * @throws IllegalArgumentException + * @throws IllegalAccessException * */ - public static Object invokeStaticMethod(Class clazz, String methodName, Object[] args, Class...parameterTypes) { + public static Object invokeStaticMethod(Class clazz, String methodName, Object[] args, Class...parameterTypes) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (parameterTypes == null) { parameterTypes = Emptys.EMPTY_CLASS_ARRAY; } @@ -373,7 +367,6 @@ public static Object invokeStaticMethod(Class clazz, String methodName, Objec if (method == null) { return null; } - return invokeMethod(method, null, args); } diff --git a/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java b/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java index 884c96f75..6b5e10847 100644 --- a/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java +++ b/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java @@ -24,9 +24,9 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; -import blade.exception.ClassReaderException; import blade.kit.Assert; import blade.kit.CollectionKit; +import blade.kit.exception.ClassReaderException; import blade.kit.log.Logger; /** From 87b02e7d2bcaddb489f5d3336a1ca0f2c556c4a1 Mon Sep 17 00:00:00 2001 From: Awakens Date: Sat, 19 Dec 2015 19:24:57 -0500 Subject: [PATCH 320/545] Edit English sentences to make the README easier to read and understand --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index dc8f0ab06..8d2d7156b 100644 --- a/README.md +++ b/README.md @@ -11,22 +11,22 @@ ## What Is Blade? Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. -If you like it, can be [Star and Fork](https://github.com/biezhi/blade), thanks! +If you like it, please [star and fork it](https://github.com/biezhi/blade). Thank you! ## Features -* [x] Lightweight. The code is simple and structure is clear +* [x] Lightweight: the code is simple and the structure is clear * [x] Modular (you can choose which components to use) -* [x] Support plug-in extension mechanism +* [x] Supports plug-in extension mechanism * [x] Restful style routing interface -* [x] Multiple configuration files support (currently properties, json and coding) -* [x] Eembed jetty server and template engine support -* [x] Support jdk1.6 or higher version +* [x] Supports multiple configuration files (currently properties, json and coding) +* [x] Embedded jetty server and template engine support +* [x] Supports jdk 1.6 and up ## Overview -* Simplicity. The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. It is a goal of the project that users should be able to understand the whole framework in a single day. -* Elegance. `blade` Support the REST style routing interface, provide DSL grammar to write, no invasive interceptors. +* Simplicity: the design is simple, easy to understand and doesn't introduce many layers between you and the standard library. It is a goal of the project that users should be able to understand the whole framework in a single day. +* Elegance: `blade` supports the REST style routing interface, has no invasive interceptors and provides the writing of DSL grammar. ## Get Start @@ -176,7 +176,7 @@ public Long getUserCount(String email){ } ``` -OK, all this may seem simple, refer to the guidelines for use more ready-made examples for your reference: +You may refer to these examples for additional guidance: + [Hello](https://github.com/bladejava/hello) + [Api Doc](http://bladejava.com/apidocs) @@ -186,7 +186,7 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ## Plan -- 1. The development of social application platform +- 1. The development of the social application platform - 2. Add the test code - 3. Optimize the code base - 4. Optimization of concurrent ability @@ -198,7 +198,7 @@ OK, all this may seem simple, refer to the guidelines for use more ready-made ex ## Contact - Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me#gmail.com +- Mail: biezhi.me@gmail.com - QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) ## licenses From 07f35d6425a059804ab195335ddc592fd56dce79 Mon Sep 17 00:00:00 2001 From: SyedWasiHaider Date: Sun, 20 Dec 2015 11:46:05 -0800 Subject: [PATCH 321/545] Added startup dependency as well. Without this dependency it throws: java.lang.ClassNotFoundException: javax.servlet.ServletException --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 8d2d7156b..289315b73 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,11 @@ To get started, first [include the Blade library](http://bladejava.com/docs/intr blade-core last_version + + com.bladejava + blade-startup + 1.0.0 + ``` create `Main` method like this: From e23fb2a00d7c54be7030a365e45eb07afdda5aa9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 09:25:19 +0800 Subject: [PATCH 322/545] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 289315b73..b2019c159 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ To get started, first [include the Blade library](http://bladejava.com/docs/intr com.bladejava blade-startup - 1.0.0 + 1.0.1 ``` From f4a0f746bfe16ff409ab3bf5ea979a2e601a6771 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 09:26:08 +0800 Subject: [PATCH 323/545] Update README_CN.md --- README_CN.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README_CN.md b/README_CN.md index 34bf686dd..4a3d24133 100644 --- a/README_CN.md +++ b/README_CN.md @@ -40,6 +40,11 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 blade-core 最终版本 + + com.bladejava + blade-startup + 1.0.1 + ``` 编写 `Main`函数: From d85a9f068d5d954cfd16263d0f34cee44e6e16e9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 10:20:02 +0800 Subject: [PATCH 324/545] fix render view real path --- .../java/com/blade/render/BeetlRender.java | 18 +++++------ .../java/com/blade/render/JetbrickRender.java | 22 ++++++++++---- .../main/java/com/blade/render/JspRender.java | 30 +++++++++++-------- .../java/com/blade/render/VelocityRender.java | 18 +++++++---- 4 files changed, 53 insertions(+), 35 deletions(-) diff --git a/blade-core/src/main/java/com/blade/render/BeetlRender.java b/blade-core/src/main/java/com/blade/render/BeetlRender.java index 5cf975ecf..0c4c45c46 100644 --- a/blade-core/src/main/java/com/blade/render/BeetlRender.java +++ b/blade-core/src/main/java/com/blade/render/BeetlRender.java @@ -51,21 +51,18 @@ public class BeetlRender implements Render { */ private GroupTemplate groupTemplate = null; - /** - * Blade对象 - */ - private Blade blade; + private String webRoot; /** * 默认构造函数 */ public BeetlRender() { try { - blade = Blade.me(); - String root = blade.webRoot() + blade.viewPrefix(); + Blade blade = Blade.me(); + this.webRoot = blade.webRoot(); WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); resourceLoader.setAutoCheck(true); - resourceLoader.setRoot(root); + resourceLoader.setRoot(this.webRoot); Configuration cfg = Configuration.defaultConfiguration(); groupTemplate = new GroupTemplate(resourceLoader, cfg); } catch (IOException e) { @@ -74,17 +71,16 @@ public BeetlRender() { } public BeetlRender(GroupTemplate groupTemplate) { - blade = Blade.me(); this.groupTemplate = groupTemplate; } public BeetlRender(Configuration configuration) { try { - blade = Blade.me(); - String root = blade.webRoot() + blade.viewPrefix(); + Blade blade = Blade.me(); + this.webRoot = blade.webRoot(); WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); resourceLoader.setAutoCheck(true); - resourceLoader.setRoot(root); + resourceLoader.setRoot(this.webRoot); Configuration cfg = Configuration.defaultConfiguration(); groupTemplate = new GroupTemplate(resourceLoader, cfg); groupTemplate.setConf(configuration); diff --git a/blade-core/src/main/java/com/blade/render/JetbrickRender.java b/blade-core/src/main/java/com/blade/render/JetbrickRender.java index 559a416a3..3fc8ffba7 100644 --- a/blade-core/src/main/java/com/blade/render/JetbrickRender.java +++ b/blade-core/src/main/java/com/blade/render/JetbrickRender.java @@ -49,12 +49,13 @@ public class JetbrickRender implements Render { private Properties config; - private Blade blade; + private String webRoot; /** * 默认构造函数 */ public JetbrickRender() { - this.blade = Blade.me(); + Blade blade = Blade.me(); + this.webRoot = blade.webRoot(); config = new Properties(); config.put("jetx.input.encoding", blade.encoding()); config.put("jetx.output.encoding", blade.encoding()); @@ -99,7 +100,8 @@ public void put(String key, Object value){ * @throws IOException 抛出IO异常 */ public JetbrickRender(String configLocation) throws IOException { - this.blade = Blade.me(); + Blade blade = Blade.me(); + this.webRoot = blade.webRoot(); jetEngine = JetEngine.create(configLocation); } @@ -109,7 +111,8 @@ public JetbrickRender(String configLocation) throws IOException { * @param config Properties配置 */ public JetbrickRender(Properties config) { - this.blade = Blade.me(); + Blade blade = Blade.me(); + this.webRoot = blade.webRoot(); this.config = config; jetEngine = JetEngine.create(this.config); } @@ -120,17 +123,24 @@ public JetbrickRender(Properties config) { * @param jetEngine jetEngine引擎 */ public JetbrickRender(JetEngine jetEngine) { - this.blade = Blade.me(); this.jetEngine = jetEngine; } + /** + * @return return config object + */ + public Properties getConfig() { + return config; + } @Override public void render(ModelAndView modelAndView, Writer writer) { Request request = BladeWebContext.request(); Session session = request.session(); - JetTemplate template = jetEngine.getTemplate(modelAndView.getView()); + String view = webRoot + modelAndView.getView(); + + JetTemplate template = jetEngine.getTemplate(view); Map context = modelAndView.getModel(); diff --git a/blade-core/src/main/java/com/blade/render/JspRender.java b/blade-core/src/main/java/com/blade/render/JspRender.java index 9e2ecc767..b27e2c901 100644 --- a/blade-core/src/main/java/com/blade/render/JspRender.java +++ b/blade-core/src/main/java/com/blade/render/JspRender.java @@ -24,10 +24,11 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.blade.context.BladeWebContext; - import blade.kit.log.Logger; +import com.blade.Blade; +import com.blade.context.BladeWebContext; + /** * *

@@ -41,22 +42,27 @@ public final class JspRender implements Render { private static final Logger LOGGER = Logger.getLogger(JspRender.class); + private String webRoot; + + public JspRender() { + webRoot = Blade.me().webRoot(); + } + @Override public void render(ModelAndView modelAndView, Writer writer) { HttpServletRequest servletRequest = BladeWebContext.request().raw(); HttpServletResponse servletResponse = BladeWebContext.response().raw(); - Map model = modelAndView.getModel(); - - String viewPath = modelAndView.getView(); - - if (null != model && !model.isEmpty()) { - Set keys = model.keySet(); - for (String key : keys) { - servletRequest.setAttribute(key, model.get(key)); - } - } try { + Map model = modelAndView.getModel(); + String viewPath = webRoot + modelAndView.getView(); + + if (null != model && !model.isEmpty()) { + Set keys = model.keySet(); + for (String key : keys) { + servletRequest.setAttribute(key, model.get(key)); + } + } servletRequest.getRequestDispatcher(viewPath).forward(servletRequest, servletResponse); } catch (ServletException e) { e.printStackTrace(); diff --git a/blade-core/src/main/java/com/blade/render/VelocityRender.java b/blade-core/src/main/java/com/blade/render/VelocityRender.java index 2945b306c..91c3e2ec4 100644 --- a/blade-core/src/main/java/com/blade/render/VelocityRender.java +++ b/blade-core/src/main/java/com/blade/render/VelocityRender.java @@ -50,12 +50,13 @@ public class VelocityRender implements Render { private final VelocityEngine velocityEngine; - private Blade blade; + private String webRoot; /** * 默认构造函数 */ public VelocityRender() { - blade = Blade.me(); + Blade blade = Blade.me(); + this.webRoot = blade.webRoot(); Properties properties = new Properties(); properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, blade.webRoot()); @@ -72,7 +73,8 @@ public VelocityRender() { * @throws IOException 抛出IO异常 */ public VelocityRender(String propertiesFile) throws IOException { - blade = Blade.me(); + Blade blade = Blade.me(); + this.webRoot = blade.webRoot(); String loadPath = VelocityRender.class.getClassLoader().getResource("/").getPath(); String fileName = loadPath + propertiesFile; @@ -93,7 +95,8 @@ public VelocityRender(String propertiesFile) throws IOException { * @param properties Properties配置文件 */ public VelocityRender(Properties properties) { - blade = Blade.me(); + Blade blade = Blade.me(); + this.webRoot = blade.webRoot(); velocityEngine = new VelocityEngine(properties); } @@ -103,7 +106,8 @@ public VelocityRender(Properties properties) { * @param velocityEngine velocity引擎对象 */ public VelocityRender(VelocityEngine velocityEngine) { - blade = Blade.me(); + Blade blade = Blade.me(); + this.webRoot = blade.webRoot(); this.velocityEngine = velocityEngine; } @@ -112,6 +116,8 @@ public void render(ModelAndView modelAndView, Writer writer) throws RenderExcept Request request = BladeWebContext.request(); Session session = request.session(); + String viewPath = webRoot + modelAndView.getView(); + VelocityContext context = new VelocityContext(modelAndView.getModel()); Set attrs = request.attributes(); @@ -129,7 +135,7 @@ public void render(ModelAndView modelAndView, Writer writer) throws RenderExcept } try { - Template template = velocityEngine.getTemplate(modelAndView.getView()); + Template template = velocityEngine.getTemplate(viewPath); template.merge(context, writer); writer.flush(); writer.close(); From 209a8a9b9a21049a6d60daffa4a86f41f0039f4b Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 10:20:18 +0800 Subject: [PATCH 325/545] set webRoot --- blade-core/src/main/java/com/blade/web/DispatcherServlet.java | 1 + 1 file changed, 1 insertion(+) diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index fc2bc217e..ee1d8147c 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -65,6 +65,7 @@ public DispatcherServlet(Bootstrap bootstrap) { @Override public void init(ServletConfig config) throws ServletException { if(!blade.isInit()){ + blade.webRoot(config.getServletContext().getRealPath("/")); this.bootstrap = blade.bootstrap(); if(null == bootstrap){ String bootStrapClassName = config.getInitParameter("bootstrap"); From 52f00662dc8334d0ded4f55d85ac994c57ce66bf Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 10:21:14 +0800 Subject: [PATCH 326/545] add gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..1920f74af --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target/ +/.settings/ +/.project \ No newline at end of file From aa45f199845c57c22269dc14c07ea82151fce31a Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 10:51:26 +0800 Subject: [PATCH 327/545] Modify notes for English --- blade-core/src/main/java/com/blade/Aop.java | 2 +- blade-core/src/main/java/com/blade/Blade.java | 373 +++++++++--------- 2 files changed, 187 insertions(+), 188 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Aop.java b/blade-core/src/main/java/com/blade/Aop.java index cc3f7fc39..aaa194c77 100644 --- a/blade-core/src/main/java/com/blade/Aop.java +++ b/blade-core/src/main/java/com/blade/Aop.java @@ -21,7 +21,7 @@ import blade.kit.ReflectKit; /** - * 作为AOP的基础,用于创建对象 + * As the basis for AOP, used to create objects * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 501e582f5..e7712c378 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -50,52 +50,52 @@ public class Blade { /** - * 框架是否已经初始化 + * Blade initialize */ private boolean isInit = false; /** - * 是否异步调用 + * Servlet asynchronous */ private boolean isAsyn = true; /** - * blade全局初始化对象,在web.xml中配置,必须 + * Blade initialize config class */ private Bootstrap bootstrap = null; /** - * 全局配置对象 + * Global configuration Object */ private Config config = new Config(); /** - * IOC容器,存储路由到ioc中 + * IOC Container, save javabean */ private Container container = new SampleContainer(); /** - * ioc全局对象 + * ioc application object */ private IocApplication iocApplication = new IocApplication(container); /** - * 默认JSP渲染 + * default render is jspRender */ private Render render = new JspRender(); /** - * 路由管理对象 + * manage route */ private Routers routers = new Routers(container); /** - * blade启动端口,jetty服务 + * jetty start port */ private int port = Const.DEFAULT_PORT; /** - * jetty服务 + * jetty server */ private Server bladeServer; @@ -107,47 +107,47 @@ private static class BladeHolder { } /** - * @return 单例方式返回Blade对象 + * @return Single case method returns Blade object */ public static Blade me(){ return BladeHolder.ME; } /** - * 设置App是否已经初始化 - * @param isInit 是否初始化 + * Set Blade initialize + * @param isInit initialize */ public void setInit(boolean isInit) { this.isInit = isInit; } /** - * 创建一个Jetty服务 - * @param port 服务端口 - * @return 返回Blade封装的Server + * create a jetty server + * @param port server port + * @return return server object */ public Server createServer(int port){ return new Server(port, isAsyn); } /** - * @return 返回路由管理对象 + * @return return route manager */ public Routers routers() { return routers; } /** - * @return 返回Blade IOC容器 + * @return return blade ioc container */ public Container container(){ return container; } /** - * 设置一个IOC容器 - * @param container ioc容器对象 - * @return 返回blade + * Setting a ioc container + * @param container ioc object + * @return return blade */ public Blade container(Container container){ Assert.notNull(container); @@ -156,12 +156,13 @@ public Blade container(Container container){ } /** - * Properties配置文件方式 - * 文件的路径基于classpath + * Setting Properties configuration file + * File path based on classpath * - * @param confName 配置文件路径 - * @return 返回Blade单例实例 + * @param confName properties file name + * @return return blade */ + @Deprecated public Blade config(String confName){ Assert.notBlank(confName); Map configMap = PropertyKit.getPropertyMap(confName); @@ -170,11 +171,11 @@ public Blade config(String confName){ } /** - * Properties配置文件方式 - * 文件的路径基于classpath + * Setting Properties configuration file + * File path based on classpath * - * @param confName 配置文件路径 - * @return 返回Blade单例实例 + * @param confName properties file name + * @return return blade */ public Blade setAppConf(String confName){ Assert.notBlank(confName); @@ -184,15 +185,15 @@ public Blade setAppConf(String confName){ } /** - * JSON文件的配置 - * 文件的路径基于classpath + * Setting JSON file configuration + * File path based on classpath * - * @param jsonPath json文件路径 - * @return 返回Blade单例实例 + * @param fileName json file name + * @return return blade */ - public Blade setJsonConf(String jsonPath){ - Assert.notBlank(jsonPath); - InputStream inputStream = Blade.class.getResourceAsStream(jsonPath); + public Blade setJsonConf(String fileName){ + Assert.notBlank(fileName); + InputStream inputStream = Blade.class.getResourceAsStream(fileName); if(null != inputStream){ try { String json = IOKit.toString(inputStream); @@ -206,12 +207,10 @@ public Blade setJsonConf(String jsonPath){ } /** - *

-	 * JSON格式的配置
-	 * 
+ * Setting json character config, Not recommended * - * @param json json配置 - * @return 返回Blade单例实例 + * @param json json character + * @return return blade */ public Blade setAppJson(String json){ Assert.notBlank(json); @@ -221,11 +220,8 @@ public Blade setAppJson(String json){ } /** - *
-	 * 根据配置map保存配置
-	 * 
- * - * @param configMap 存放配置的map + * Setting Map config + * @param configMap set config map */ private void configuration(Map configMap){ Assert.notEmpty(configMap); @@ -233,11 +229,11 @@ private void configuration(Map configMap){ } /** - * 设置路由包,如:com.baldejava.route - * 可传入多个包,所有的路由类都在该包下 + * Setting route package,e.g:com.baldejava.route + * Can be introduced into multiple packages, all of which are in the package. * - * @param packages 路由包路径 - * @return 返回Blade单例实例 + * @param packages route package path, is your package name + * @return return blade */ public Blade routes(String...packages){ Assert.notNull(packages); @@ -246,11 +242,11 @@ public Blade routes(String...packages){ } /** - * 设置顶层包,框架自动寻找路由包和拦截器包,如:com.bladejava - * 如上规则,会超找com.bladejava.route、com.bladejava.interceptor下的路由和拦截器 + * Setting top package frame automatically for routing packets and packet interceptor, e.g:com.bladejava + * As above, it will be over:com.bladejava.route、com.bladejava.interceptor Routing and interceptor inside * - * @param basePackage 默认包路径 - * @return 返回Blade单例实例 + * @param basePackage default package path + * @return return blade */ public Blade defaultRoute(String basePackage){ Assert.notBlank(basePackage); @@ -259,10 +255,10 @@ public Blade defaultRoute(String basePackage){ } /** - * 设置拦截器所在的包路径,如:com.bladejava.interceptor + * Setting the path where the interceptor, e.g:com.bladejava.interceptor * - * @param packageName 拦截器所在的包 - * @return 返回Blade单例实例 + * @param packageName interceptor packagename + * @return return blade */ public Blade interceptor(String packageName) { Assert.notBlank(packageName); @@ -271,10 +267,10 @@ public Blade interceptor(String packageName) { } /** - * 设置依赖注入包,如:com.bladejava.service + * Setting Ioc packages, e.g:com.bladejava.service * - * @param packages 所有需要做注入的包,可传入多个 - * @return 返回Blade单例实例 + * @param packages All need to do into the package, can be introduced into a number of + * @return return blade */ public Blade ioc(String...packages){ Assert.notNull(packages); @@ -285,12 +281,12 @@ public Blade ioc(String...packages){ } /** - * 添加一个路由 + * Add a route * - * @param path 路由路径 - * @param target 路由执行的目标对象 - * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) - * @return 返回Blade单例实例 + * @param path route path + * @param target Target object for routing + * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade */ public Blade route(String path, Object target, String method){ routers.route(path, target, method); @@ -298,13 +294,13 @@ public Blade route(String path, Object target, String method){ } /** - * 添加一个路由 + * Add a route * - * @param path 路由路径 - * @param target 路由执行的目标对象 - * @param method 路由执行的方法名称(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) - * @param httpMethod HTTP方法 - * @return 返回Blade单例实例 + * @param path route path + * @param target Target object for routing + * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @param httpMethod HTTPMethod + * @return return blade */ public Blade route(String path, Object target, String method, HttpMethod httpMethod){ routers.route(path, target, method, httpMethod); @@ -326,13 +322,13 @@ public Blade route(String path, Class clazz, String method){ } /** - * 注册一个函数式的路由 + * Register a functional route * - * @param path 路由url - * @param clazz 路由处理类 - * @param method 路由处理方法名称 - * @param httpMethod 请求类型,GET/POST - * @return Blade 返回Blade单例实例 + * @param path route url + * @param clazz route processing class + * @param method route processing method name + * @param httpMethod HttpMethod Type, GET/POST/... + * @return Blade return blade */ public Blade route(String path, Class clazz, String method, HttpMethod httpMethod){ routers.route(path, clazz, method, httpMethod); @@ -340,9 +336,9 @@ public Blade route(String path, Class clazz, String method, HttpMethod httpMe } /** - * 添加路由列表 - * @param routes 路由列表 - * @return 返回Blade单例实例 + * Add a route list + * @param routes route list + * @return return blade */ public Blade routes(List routes){ routers.addRoutes(routes); @@ -350,11 +346,11 @@ public Blade routes(List routes){ } /** - * 注册一个GET请求的路由 + * Register a GET request route * - * @param path 路由路径 - * @param handler 执行路由的Handle - * @return 返回Blade单例实例 + * @param path route path, request url + * @param handler execute route Handle + * @return return blade */ public Blade get(String path, RouteHandler handler){ routers.route(path, handler, HttpMethod.GET); @@ -362,11 +358,11 @@ public Blade get(String path, RouteHandler handler){ } /** - * 注册一个POST请求的路由 + * Register a POST request route * - * @param path 路由路径 - * @param handler 执行路由的Handle - * @return 返回Blade单例实例 + * @param path route path, request url + * @param handler execute route Handle + * @return return blade */ public Blade post(String path, RouteHandler handler){ routers.route(path, handler, HttpMethod.POST); @@ -374,11 +370,11 @@ public Blade post(String path, RouteHandler handler){ } /** - * 注册一个DELETE请求的路由 + * Register a DELETE request route * - * @param path 路由路径 - * @param handler 执行路由的Handle - * @return 返回Blade单例实例 + * @param path route path, request url + * @param handler execute route Handle + * @return return blade */ public Blade delete(String path, RouteHandler handler){ routers.route(path, handler, HttpMethod.DELETE); @@ -386,11 +382,11 @@ public Blade delete(String path, RouteHandler handler){ } /** - * 注册一个PUT请求的路由 + * Register a PUT request route * - * @param path 路由路径 - * @param handler 执行路由的Handle - * @return 返回Blade单例实例 + * @param path route path, request url + * @param handler execute route Handle + * @return return blade */ public Blade put(String path, RouteHandler handler){ routers.route(path, handler, HttpMethod.PUT); @@ -398,11 +394,11 @@ public Blade put(String path, RouteHandler handler){ } /** - * 注册一个任意请求的路由 + * Register for any request routing * - * @param path 路由路径 - * @param handler 执行路由的Handle - * @return 返回Blade单例实例 + * @param path route path, request url + * @param handler execute route Handle + * @return return blade */ public Blade all(String path, RouteHandler handler){ routers.route(path, handler, HttpMethod.ALL); @@ -410,11 +406,11 @@ public Blade all(String path, RouteHandler handler){ } /** - * 注册一个任意请求的路由 + * Register for any request routing * - * @param path 路由路径 - * @param handler 执行路由的Handle - * @return 返回Blade单例实例 + * @param path route path, request url + * @param handler execute route Handle + * @return return blade */ public Blade any(String path, RouteHandler handler){ routers.route(path, handler, HttpMethod.ALL); @@ -422,11 +418,11 @@ public Blade any(String path, RouteHandler handler){ } /** - * 注册一个前置拦截器请求的路由 + * Register a pre routing request interceptor * - * @param path 路由路径 - * @param handler 执行路由的Handle - * @return 返回Blade单例实例 + * @param path route path, request url + * @param handler execute route Handle + * @return return blade */ public Blade before(String path, RouteHandler handler){ routers.route(path, handler, HttpMethod.BEFORE); @@ -434,11 +430,11 @@ public Blade before(String path, RouteHandler handler){ } /** - * 注册一个后置拦截器请求的路由 + * Register a after routing request interceptor * - * @param path 路由路径 - * @param handler 执行路由的Handle - * @return 返回Blade单例实例 + * @param path route path, request url + * @param handler execute route Handle + * @return return blade */ public Blade after(String path, RouteHandler handler){ routers.route(path, handler, HttpMethod.AFTER); @@ -446,10 +442,10 @@ public Blade after(String path, RouteHandler handler){ } /** - * 设置渲染引擎,默认是JSP引擎 + * Setting Render Engin, Default is JspRender * - * @param render 渲染引擎对象 - * @return 返回Blade单例实例 + * @param render Render engine object + * @return return blade */ public Blade viewEngin(Render render) { Assert.notNull(render); @@ -458,10 +454,10 @@ public Blade viewEngin(Render render) { } /** - * 设置默认视图前缀,默认为WEBROOT/WEB-INF/目录 + * Setting default view prefix, default is WEBROOT/WEB-INF/ * - * @param prefix 视图路径,如:/WEB-INF/views/ - * @return 返回Blade单例实例 + * @param prefix views path, e.g:/WEB-INF/views/ + * @return return blade */ public Blade viewPrefix(final String prefix) { Assert.notBlank(prefix); @@ -472,10 +468,10 @@ public Blade viewPrefix(final String prefix) { } /** - * 设置视图默认后缀名,默认为.jsp + * Setting view default suffix, default is .jsp * - * @param suffix 视图后缀,如:.html .vm - * @return 返回Blade单例实例 + * @param suffix view suffix, e.g:.html .vm + * @return return blade */ public Blade viewSuffix(final String suffix) { Assert.notBlank(suffix); @@ -486,11 +482,11 @@ public Blade viewSuffix(final String suffix) { } /** - * 同事设置视图所在目录和视图后缀名 + * Also set the view's directory and view the suffix name * - * @param viewPath 视图路径,如:/WEB-INF/views - * @param viewExt 视图后缀,如:.html .vm - * @return 返回Blade单例实例 + * @param viewPath views path, e.g:/WEB-INF/views + * @param viewExt view suffix, e.g:.html .vm + * @return return blade */ public Blade view(final String viewPath, final String viewExt) { Assert.notBlank(viewPath); @@ -501,10 +497,10 @@ public Blade view(final String viewPath, final String viewExt) { } /** - * 设置框架静态文件所在文件夹 + * Setting the frame static file folder * - * @param folders 要过滤的目录数组,如:"/public,/static,/images" - * @return 返回Blade单例实例 + * @param folders List of directories to filter, e.g: "/public,/static,/images" + * @return return blade */ public Blade staticFolder(final String ... folders) { Assert.notNull(folders); @@ -513,10 +509,10 @@ public Blade staticFolder(final String ... folders) { } /** - * 设置是否启用XSS防御 + * Setting XSS is enable * - * @param enableXSS 是否启用XSS防御,默认不启用 - * @return 返回Blade单例实例 + * @param enableXSS enable XSS, default is false + * @return return blade */ public Blade enableXSS(boolean enableXSS){ config.setEnableXSS(enableXSS); @@ -524,10 +520,10 @@ public Blade enableXSS(boolean enableXSS){ } /** - * 动态设置全局初始化类, 内嵌式Jetty启动用 + * Dynamically set the global initialization class, the embedded Jetty boot * - * @param bootstrap 全局初始化bladeApplication - * @return 返回Blade单例实例 + * @param bootstrap global initialization config class + * @return return blade */ public Blade app(Bootstrap bootstrap){ Assert.notNull(bootstrap); @@ -536,10 +532,10 @@ public Blade app(Bootstrap bootstrap){ } /** - * 动态设置全局初始化类 + * Dynamically set global initialization class * - * @param bootstrap 全局初始化bladeApplication - * @return 返回Blade单例实例 + * @param bootstrap global initialization config class + * @return return blade */ public Blade app(Class bootstrap){ Assert.notNull(bootstrap); @@ -549,10 +545,10 @@ public Blade app(Class bootstrap){ } /** - * 设置404视图页面 + * Setting 404 view page * - * @param view404 404视图页面 - * @return 返回Blade单例实例 + * @param view404 404 view page + * @return return blade */ public Blade setView404(final String view404){ Assert.notBlank(view404); @@ -561,10 +557,10 @@ public Blade setView404(final String view404){ } /** - * 设置500视图页面 + * Setting 500 view page * - * @param view500 500视图页面 - * @return 返回Blade单例实例 + * @param view500 500 view page + * @return return blade */ public Blade setView500(final String view500){ Assert.notBlank(view500); @@ -573,10 +569,10 @@ public Blade setView500(final String view500){ } /** - * 设置web根目录 + * Setting blade web root path * - * @param webRoot web根目录物理路径 - * @return 返回Blade单例实例 + * @param webRoot web root path + * @return return blade */ public Blade webRoot(final String webRoot){ Assert.notBlank(webRoot); @@ -585,10 +581,10 @@ public Blade webRoot(final String webRoot){ } /** - * 设置系统是否以debug方式运行 + * Setting blade run mode * - * @param isdebug true:是,默认true;false:否 - * @return 返回Blade单例实例 + * @param isdebug is debug mode + * @return return blade */ public Blade debug(boolean isdebug){ config.setDebug(isdebug); @@ -596,10 +592,10 @@ public Blade debug(boolean isdebug){ } /** - * 设置Jetty服务监听端口 + * Setting jetty listen port * - * @param port 端口,默认9000 - * @return 返回Blade单例实例 + * @param port port, default is 9000 + * @return return blade */ public Blade listen(int port){ this.port = port; @@ -607,9 +603,9 @@ public Blade listen(int port){ } /** - * 是否异步调用 - * @param isAsyn 是否异步 - * @return 返回Blade单例对象 + * Setting servlet asynchronous + * @param isAsyn is asynchronous + * @return return blade */ public Blade isAsyn(boolean isAsyn){ this.isAsyn = isAsyn; @@ -617,9 +613,9 @@ public Blade isAsyn(boolean isAsyn){ } /** - * 设置jetty启动上下文 + * Setting jetty context * - * @param contextPath 设置上下文contextPath,默认/ + * @param contextPath context path, default is / */ public void start(String contextPath) { try { @@ -632,14 +628,14 @@ public void start(String contextPath) { } /** - * 启动Jetty服务 + * Start jetty server */ public void start() { this.start("/"); } /** - * 停止jetty服务 + * Jetty sever shutdown */ public void stop() { try { @@ -650,44 +646,44 @@ public void stop() { } /** - * join in server + * Join in server * - * @throws InterruptedException join异常 + * @throws InterruptedException join exception */ public void join() throws InterruptedException { bladeServer.join(); } /** - * @return 返回系统配置对象 + * @return Return blade config object */ public Config config(){ return config; } /** - * @return 返回Blade要扫描的基础包 + * @return Return blade scan base package */ public String basePackage(){ return config.getBasePackage(); } /** - * @return 返回路由包数组 + * @return Return route packages */ public String[] routePackages(){ return config.getRoutePackages(); } /** - * @return 返回IOC所有包 + * @return Return ioc packages */ public String[] iocs(){ return config.getIocPackages(); } /** - * @return 返回拦截器包数组,只有一个元素 这里统一用String[] + * @return Returns the interceptor array, only one element here use String[] */ public String interceptorPackage(){ return config.getInterceptorPackage(); @@ -695,85 +691,88 @@ public String interceptorPackage(){ /** - * @return 返回视图存放路径 + * @return Return views prefix */ public String viewPrefix(){ return config.getViewPrefix(); } /** - * @return 返回系统默认字符编码 + * @return Return blade encoding, default is UTF-8 */ public String encoding(){ return config.getEncoding(); } /** - * @return 返回balde启动端口 + * @return Return view suffix */ public String viewSuffix(){ return config.getViewSuffix(); } /** - * @return 返回404视图 + * @return Return 404 view */ public String view404(){ return config.getView404(); } /** - * @return 返回500视图 + * @return Return 500 view */ public String view500(){ return config.getView500(); } /** - * @return 返回webroot路径 + * @return Return blade web root path */ public String webRoot(){ return config.getWebRoot(); } /** - * @return 返回系统是否以debug方式运行 + * @return Return is debug mode */ public boolean debug(){ return config.isDebug(); } /** - * @return 返回静态资源目录 + * @return Return static resource directory */ public String[] staticFolder(){ return config.getStaticFolders(); } /** - * @return 返回Bootstrap对象 + * @return Return bootstrap object */ public Bootstrap bootstrap(){ return bootstrap; } + /** + * @return Return current render engine + */ public Render render() { return render; } /** - * @return 返回是否启用XSS防御 + * @return Return XSS is enabled */ public boolean enableXSS(){ return config.isEnableXSS(); } /** - * 返回插件对象 + * return register plugin object * - * @param plugin 插件class - * @param 泛型 - * @return 返回插件对象 + * @param plugin plugin class + * @param generic + * @return return plugin object */ @SuppressWarnings("unchecked") public T plugin(Class plugin){ @@ -786,11 +785,11 @@ public T plugin(Class plugin){ } /** - * 注册一个配置文件的路由,如:"com.xxx.route","route.conf" + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" * - * @param basePackage 控制器包名 - * @param conf 配置文件路径,配置文件必须在classpath下 - * @return 返回Blade单例实例 + * @param basePackage controller package name + * @param conf Configuration file path, the configuration file must be in classpath + * @return return blade */ public Blade routeConf(String basePackage, String conf) { try { @@ -810,14 +809,14 @@ public Blade routeConf(String basePackage, String conf) { } /** - * @return 返回IocApplication对象 + * @return Return IocApplication object */ public IocApplication iocApplication(){ return iocApplication; } /** - * @return 返回IocApplication对象 + * @return Initialize ioc application and return blade */ public Blade iocInit(){ iocApplication.init(iocs(), bootstrap); @@ -825,7 +824,7 @@ public Blade iocInit(){ } /** - * @return 返回是否已经初始化 + * @return Return blade is initialize */ public boolean isInit() { return isInit; From 9d32932d2054af4ccc1da51a611ea51d3f832936 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 11:52:52 +0800 Subject: [PATCH 328/545] update readme and modify english comments --- README.md | 2 +- README_CN.md | 2 +- .../src/main/java/com/blade/Bootstrap.java | 10 +++--- blade-core/src/main/java/com/blade/Const.java | 12 +++---- .../main/java/com/blade/IocApplication.java | 35 +++++++++---------- 5 files changed, 29 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index b2019c159..e69b2438a 100644 --- a/README.md +++ b/README.md @@ -191,7 +191,7 @@ You may refer to these examples for additional guidance: ## Plan -- 1. The development of the social application platform +- 1. Written in English Docs - 2. Add the test code - 3. Optimize the code base - 4. Optimization of concurrent ability diff --git a/README_CN.md b/README_CN.md index 4a3d24133..851d966f0 100644 --- a/README_CN.md +++ b/README_CN.md @@ -188,7 +188,7 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ### 计划 -- 1. 开发社交应用平台 +- 1. 编写英文文档 - 2. 添加测试代码 - 3. 优化基础代码 - 4. 优化并发能力 diff --git a/blade-core/src/main/java/com/blade/Bootstrap.java b/blade-core/src/main/java/com/blade/Bootstrap.java index 2dd4589a7..fe68f7189 100644 --- a/blade-core/src/main/java/com/blade/Bootstrap.java +++ b/blade-core/src/main/java/com/blade/Bootstrap.java @@ -16,7 +16,7 @@ package com.blade; /** - * Blade全局初始化类,可以在应用启动的时候做一些操作 + * Blade global initialization class, you can do some operations at the start of the application * * @author biezhi * @since 1.0 @@ -24,14 +24,14 @@ public abstract class Bootstrap { /** - * 初始化方法,在应用启动的时候做一些初始化操作 - * @param blade Blade全局对象 + * Initialization method, do some initialization operation when the application starts + * @param blade blade global object */ public abstract void init(Blade blade); /** - * 初始化配置后执行 - * @param blade Blade全局对象 + * After initialization configuration + * @param blade blade global object */ public void contextInitialized(Blade blade){ // diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index a6d63a3a5..8595b46e0 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -16,7 +16,7 @@ package com.blade; /** - * 常量接口 + * Const Interface * * @author biezhi * @since 1.0 @@ -24,29 +24,29 @@ public interface Const { /** - * 当前最新版本 + * Current version */ String BLADE_VERSION = "1.5.0-beta"; /** - * 服务器500错误时返回的HTML + * Server 500 error HTML */ String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; /** - * 服务器404错误HTML + * Server 404 error HTML */ String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; /** - * jetty默认端口 + * Default jetty server port */ int DEFAULT_PORT = 9000; /** - * 请求线程池context key + * Request ThreadPoll context key */ String BLADE_EXECUTOR = "blade-req-executor"; } diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index b6465be87..88ea1ead3 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -28,10 +28,7 @@ import com.blade.plugin.Plugin; /** - * IOC容器初始化类 - *

- * 用于初始化ioc对象 - *

+ * IOC container, used to initialize the IOC object * * @author biezhi * @since 1.0 @@ -41,17 +38,17 @@ public class IocApplication { private static final Logger LOGGER = Logger.getLogger(IocApplication.class); /** - * IOC容器,单例获取默认的容器实现 + * Ioc Container */ private Container container = null; /** - * 类读取对象,加载class + * Class to read object, load class */ private ClassReader classReader = null; /** - * 插件列表 + * Plugin List */ private List plugins = null; @@ -62,25 +59,25 @@ public IocApplication(Container container) { } /** - * 初始化IOC - * @param iocs IOC包 - * @param bootstrap 启动对象 + * IOC initialize + * @param iocs ioc packages + * @param bootstrap bootstrap object */ public void init(String[] iocs, Bootstrap bootstrap){ - // 初始化全局配置类 + // Initialize the global configuration class if(null == container.getBean(Bootstrap.class, Scope.SINGLE)){ container.registerBean(bootstrap); } - // 初始化ioc容器,加载ioc包的对象 要配置符合ioc的注解的类才会被加载 + // The object to initialize the IOC container loads the IOC package to configure the class that conforms to the IOC if(null != iocs && iocs.length > 0){ for(String packageName : iocs){ registerBean(packageName); } } - // 初始化注入 + // Initialization injection container.initWired(); Set names = container.getBeanNames(); @@ -106,20 +103,20 @@ public T getPlugin(Class plugin){ } /** - * 注册一个包下的所有对象 + * Register all objects in a package * - * @param packageName 包名称 + * @param packageName package name */ private void registerBean(String packageName) { - // 是否递归扫描 + // Recursive scan boolean recursive = false; if (packageName.endsWith(".*")) { packageName = packageName.substring(0, packageName.length() - 2); recursive = true; } - // 扫描包下所有class + // Scan package all class Set> classes = classReader.getClass(packageName, recursive); for (Class clazz : classes) { // 注册带有Component和Service注解的类 @@ -134,10 +131,10 @@ public List getPlugins() { } /** - * 销毁 + * destroy */ public void destroy() { - // 清空ioc容器 + // clean ioc container container.removeAll(); for(Plugin plugin : plugins){ plugin.destroy(); From 7b40da80788ba3adc0cc11deb4cb69f4678668af Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 11:58:14 +0800 Subject: [PATCH 329/545] modify english comments --- .../src/main/java/com/blade/annotation/After.java | 10 +++++----- .../src/main/java/com/blade/annotation/Before.java | 10 +++++----- .../src/main/java/com/blade/annotation/Component.java | 5 +---- .../src/main/java/com/blade/annotation/Inject.java | 9 +++------ .../main/java/com/blade/annotation/Interceptor.java | 4 ++-- .../src/main/java/com/blade/annotation/Path.java | 9 +++------ .../src/main/java/com/blade/annotation/Route.java | 8 ++++---- .../main/java/com/blade/annotation/package-info.java | 2 +- 8 files changed, 24 insertions(+), 33 deletions(-) diff --git a/blade-core/src/main/java/com/blade/annotation/After.java b/blade-core/src/main/java/com/blade/annotation/After.java index d2f5a4bd0..8b3b50aac 100644 --- a/blade-core/src/main/java/com/blade/annotation/After.java +++ b/blade-core/src/main/java/com/blade/annotation/After.java @@ -21,8 +21,8 @@ import java.lang.annotation.Target; /** - * 拦截器后置事件注解,写在方法上 - * 如: + * Interceptor post event annotations, write in method + * e.g: *
  *  {@link After}
  *	public void after(Request request){...}
@@ -36,17 +36,17 @@
 public @interface After {
 	
 	/**
-	 * @return	后置事件要拦截的URL
+	 * @return	After event to intercept URL
 	 */
 	String value() default "";
 	
 	/**
-	 * @return	路由后缀
+	 * @return	Route suffix
 	 */
 	String suffix() default "";
 	
 	/**
-	 * @return	多个前置拦截
+	 * @return	Multiple after intercept
 	 */
 	String[] values() default {};
 }
\ No newline at end of file
diff --git a/blade-core/src/main/java/com/blade/annotation/Before.java b/blade-core/src/main/java/com/blade/annotation/Before.java
index 6b497f435..32f5787e7 100644
--- a/blade-core/src/main/java/com/blade/annotation/Before.java
+++ b/blade-core/src/main/java/com/blade/annotation/Before.java
@@ -21,8 +21,8 @@
 import java.lang.annotation.Target;
 
 /**
- * 拦截器前置事件注解,写在方法上  
- * 如:
+ * Interceptor pre event annotation, write in method
+ * e.g:
  * 
  *  {@link Before}
  *	public void before(Request request){...}
@@ -36,17 +36,17 @@
 public @interface Before {
 	
 	/**
-	 * @return	前置事件要拦截的URL
+	 * @return	Pre event to intercept URL
 	 */
 	String value() default "";
 	
 	/**
-	 * @return	路由后缀
+	 * @return	Route suffix
 	 */
 	String suffix() default "";
 	
 	/**
-	 * @return	多个前置拦截
+	 * @return	Multiple front intercept
 	 */
 	String[] values() default {};
 }
\ No newline at end of file
diff --git a/blade-core/src/main/java/com/blade/annotation/Component.java b/blade-core/src/main/java/com/blade/annotation/Component.java
index 560f1322b..fcf71ef4a 100644
--- a/blade-core/src/main/java/com/blade/annotation/Component.java
+++ b/blade-core/src/main/java/com/blade/annotation/Component.java
@@ -21,10 +21,7 @@
 import java.lang.annotation.Target;
 
 /**
- * 
- * 

- * 可以被注入的bean注解 - *

+ * Bean annotations can be injected * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/annotation/Inject.java b/blade-core/src/main/java/com/blade/annotation/Inject.java index 4a370fc12..02ad40d53 100644 --- a/blade-core/src/main/java/com/blade/annotation/Inject.java +++ b/blade-core/src/main/java/com/blade/annotation/Inject.java @@ -21,10 +21,7 @@ import java.lang.annotation.Target; /** - * - *

- * 自动注入 - *

+ * Automatic injection * * @author biezhi * @since 1.0 @@ -34,12 +31,12 @@ public @interface Inject { /** - * @return 要注入的Class的对象 + * @return The object to be injected into the Class */ Class value() default Class.class; /** - * @return 要注入某个名称的对象 + * @return To inject an object with a name */ String name() default ""; } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/Interceptor.java b/blade-core/src/main/java/com/blade/annotation/Interceptor.java index ac92f7c17..17053461c 100644 --- a/blade-core/src/main/java/com/blade/annotation/Interceptor.java +++ b/blade-core/src/main/java/com/blade/annotation/Interceptor.java @@ -21,8 +21,8 @@ import java.lang.annotation.Target; /** - * 拦截器注解,写在类上 - * 如: + * Interceptor notes, written in the class + * e.g: *
  * {@link Interceptor}
  * public class BaseInterceptor {...}
diff --git a/blade-core/src/main/java/com/blade/annotation/Path.java b/blade-core/src/main/java/com/blade/annotation/Path.java
index 23b7ad3e7..2f3462a75 100644
--- a/blade-core/src/main/java/com/blade/annotation/Path.java
+++ b/blade-core/src/main/java/com/blade/annotation/Path.java
@@ -21,10 +21,7 @@
 import java.lang.annotation.Target;
 
 /**
- * 
- * 

- * 路由类注解,标识一个类是否是路由 - *

+ * Route class notes, identifying whether a class is routed * * @author biezhi * @since 1.0 @@ -35,12 +32,12 @@ public @interface Path{ /** - * @return 命名空间 + * @return namespace */ String value() default "/"; /** - * @return 路由后缀 + * @return route suffix */ String suffix() default ""; diff --git a/blade-core/src/main/java/com/blade/annotation/Route.java b/blade-core/src/main/java/com/blade/annotation/Route.java index 56e4a580c..395fc3277 100644 --- a/blade-core/src/main/java/com/blade/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/annotation/Route.java @@ -23,7 +23,7 @@ import com.blade.web.http.HttpMethod; /** - * 方法上定义的路由注解 + * Methods defined on the route notes * Restful routes:
@@ -47,17 +47,17 @@
 public @interface Route {
 	
 	/**
-	 * @return 请求url
+	 * @return Request url
 	 */
 	String value() default "";
 	
 	/**
-	 * @return 请求类型 HttpMethod
+	 * @return Request HttpMethod
 	 */
 	HttpMethod method() default HttpMethod.ALL;
 	
 	/**
-	 * @return 多个请求
+	 * @return Multiple requests
 	 */
 	String[] values() default {};
 	
diff --git a/blade-core/src/main/java/com/blade/annotation/package-info.java b/blade-core/src/main/java/com/blade/annotation/package-info.java
index 537ca5e3a..01b68478b 100644
--- a/blade-core/src/main/java/com/blade/annotation/package-info.java
+++ b/blade-core/src/main/java/com/blade/annotation/package-info.java
@@ -1,4 +1,4 @@
 /**
- * Blade注解包
+ * Blade Annotation
  */
 package com.blade.annotation;
\ No newline at end of file

From 5e3a6eea90e8fb1c54dec2e890ea5dc5f2507e32 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Mon, 21 Dec 2015 13:34:41 +0800
Subject: [PATCH 330/545] modify english comments

---
 .../com/blade/context/BladeWebContext.java    | 10 +-
 .../java/com/blade/context/package-info.java  |  2 +-
 .../main/java/com/blade/ioc/AopCreator.java   | 45 ++++++---
 .../main/java/com/blade/ioc/Container.java    | 96 +++++++++----------
 .../java/com/blade/ioc/SampleContainer.java   | 58 +++++------
 .../src/main/java/com/blade/ioc/Scope.java    |  6 +-
 .../main/java/com/blade/ioc/package-info.java |  2 +-
 7 files changed, 119 insertions(+), 100 deletions(-)

diff --git a/blade-core/src/main/java/com/blade/context/BladeWebContext.java b/blade-core/src/main/java/com/blade/context/BladeWebContext.java
index 7f82f1e27..b3900e7ac 100644
--- a/blade-core/src/main/java/com/blade/context/BladeWebContext.java
+++ b/blade-core/src/main/java/com/blade/context/BladeWebContext.java
@@ -22,7 +22,7 @@
 import com.blade.web.http.wrapper.Session;
 
 /**
- * 全局的WeContext
+ * BladeWebContext
  *
  * @author	biezhi
  * @since	1.0
@@ -30,22 +30,22 @@
 public class BladeWebContext {
 	
 	/**
-	 * 当前线程的Request对象
+	 * BladeWebContext object for the current thread
 	 */
     private static ThreadLocal ctx = new ThreadLocal();
     
     /**
-     * ServletContext对象,在应用初始化时创建
+     * ServletContext Object that is created when the application is initialized
      */
     private ServletContext context; 
     
     /**
-     * Request对象
+     * Request
      */
     private Request request;
     
     /**
-     * Response对象
+     * Response
      */
     private Response response;
     
diff --git a/blade-core/src/main/java/com/blade/context/package-info.java b/blade-core/src/main/java/com/blade/context/package-info.java
index e5f2d1b68..3b06fde32 100644
--- a/blade-core/src/main/java/com/blade/context/package-info.java
+++ b/blade-core/src/main/java/com/blade/context/package-info.java
@@ -1,4 +1,4 @@
 /**
- * Blade上下文
+ * Blade Context
  */
 package com.blade.context;
\ No newline at end of file
diff --git a/blade-core/src/main/java/com/blade/ioc/AopCreator.java b/blade-core/src/main/java/com/blade/ioc/AopCreator.java
index 70495dd94..f03757055 100644
--- a/blade-core/src/main/java/com/blade/ioc/AopCreator.java
+++ b/blade-core/src/main/java/com/blade/ioc/AopCreator.java
@@ -1,40 +1,61 @@
+/**
+ * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc;
 
 import com.blade.aop.AopProxy;
 
+/**
+ * Aop Create Object
+ * 
+ * @author	biezhi
+ * @since	1.0
+ */
 public final class AopCreator {
 	
 	/**
-	 * 根据Class创建一个代理
-	 * @param clazz	Class对象
-	 * @return		返回代理对象
+	 * Create an agent based on Class
+	 * @param clazz	class Object
+	 * @return		return proxy object
 	 */
 	public static  T create(Class clazz){
 		return AopProxy.create(clazz);
 	}
 	
 	/**
-	 * 根据Class创建一个代理
-	 * @param clazz	Class对象
-	 * @return		返回代理对象
+	 * Create an agent based on Class
+	 * @param clazz	class Object
+	 * @return		return proxy object
 	 */
 	public static Object createProxy(Class clazz){
 		return AopProxy.create(clazz);
 	}
 	
 	/**
-	 * 创建一个代理对象
-	 * @param target	原始java对象
-	 * @return			返回代理对象
+	 * Create a proxy object
+	 * @param target	original java object
+	 * @return			return proxy object
 	 */
 	public static  T create(Object target){
 		return AopProxy.create(target);
 	}
 	
 	/**
-	 * 创建一个代理对象
-	 * @param target	原始java对象
-	 * @return			返回代理对象
+	 * Create a proxy object
+	 * @param target	original java object
+	 * @return			return proxy object
 	 */
 	public static Object createProxy(Object target){
 		return AopProxy.create(target);
diff --git a/blade-core/src/main/java/com/blade/ioc/Container.java b/blade-core/src/main/java/com/blade/ioc/Container.java
index 8b50813f7..505e5cda4 100644
--- a/blade-core/src/main/java/com/blade/ioc/Container.java
+++ b/blade-core/src/main/java/com/blade/ioc/Container.java
@@ -22,7 +22,7 @@
 import java.util.Set;
 
 /**
- * IOC容器顶层接口
+ * IOC container top interface
  *
  * @author	biezhi
  * @since	1.0
@@ -30,127 +30,127 @@
 public interface Container {
 
 	/**
-	 * 根据bean名称和对象作用于获取一个bean对象
+	 * According to the bean name and object function to obtain a bean object
 	 * 
-	 * @param name		bean名称,可以是类名
-	 * @param scope		对象作用域,单例或者每次都创建
-	 * @param  		泛型
-	 * @return			一个bean对象
+	 * @param name		bean name
+	 * @param scope		object scope, single case or each time it is created
+	 * @param  		generic
+	 * @return			return object
 	 */
 	 T getBean(String name, Scope scope);
 
     /**
-     * 根据class和对象作用于获取一个bean对象
+     * According to the class and the object function to obtain a bean object
      * 
-     * @param type		class类型
-     * @param scope		对象作用域,单例或者每次都创建
-     * @param  		泛型
-     * @return			一个bean对象
+     * @param type		class type
+     * @param scope		object scope, single case or each time it is created
+     * @param  		generic
+     * @return			return object
      */
      T getBean(Class type, Scope scope);
 
     /**
-     * @return 返回所有bean的名称集合
+     * @return Return the name of all bean
      */
     Set getBeanNames();
     
     /**
-     * @param  		泛型
-     * @return 返回所有bean的集合
+     * @param  		generic
+     * @return Return a collection of all bean
      */
      Collection getBeans();
     
     /**
-     * 根据注解获取ioc容器中匹配的bean class集合
+     * Class bean set in the IOC container for matching based on annotations
      * 
-     * @param annotation	annotation class类型
-     * @return				返回符合annotation class类型的所有class
+     * @param annotation	annotation class type
+     * @return				return all class by annotation
      */
     List> getClassesByAnnotation(Class annotation);
     
     /**
-     * 根据注解获取ioc容器中匹配的bean对象集合
+     * To obtain a set of bean objects that match the IOC container
      * 
-     * @param annotation	annotation class类型
-     * @param  			泛型
-     * @return				返回符合annotation class类型的所有bean
+     * @param annotation	annotation class type
+     * @param  			generic
+     * @return				return all bean by annotation
      */
      List getBeansByAnnotation(Class annotation);
     
     /**
-     * 判断是否存在一个bean,根据class类型
+     * To determine if there is a bean, according to the class type
      * 
-     * @param clazz			类的class类型
-     * @return				true:存在,false:不存在
+     * @param clazz		class type
+     * @return			return class is exist
      */
     boolean hasBean(Class clazz);
 
     /**
-     * 判断是否存在一个bean,根据bena name
+     * According to name Bena to determine whether there is
      * 
-     * @param name			bean的名称,一般是class名称
-     * @return				true:存在,false:不存在
+     * @param name		bean name, usually class name
+     * @return			return class is exist
      */
     boolean hasBean(String name);
     
     /**
-     * 根据名称从ioc容器中移除一个bean对象
+     * Remove an bean object from the IOC container by name 
      * 
-     * @param name			要移除的bean对象名称
-     * @return				true:成功,false:失败
+     * @param name			to remove the bean object name 
+     * @return				return if remove success 
      */
     boolean removeBean(String name);
     
     /**
-     * 根据名称从ioc容器中移除一个bean对象
+     * Remove an bean object from the IOC container by name
      * 
-     * @param clazz			要移除的bean class类型
-     * @return				true:成功,false:失败
+     * @param clazz			to remove the class bean type 
+     * @return				return if remove success 
      */
     boolean removeBean(Class clazz);
     
     /**
-     * @return	清空容器
+     * @return	clean container
      */
     boolean removeAll();
     
     /**
-     * 获取annotations中的注解是否可以注册进入ioc容器
+     * To determine whether the comment in the annotations can be registered into the IOC container
      * 
-     * @param annotations	annotations要检测的annotation数组
-     * @return				true:可以注册,false:不可以注册
+     * @param annotations	annotation array to detect 
+     * @return				return is register
      */
     boolean isRegister(Annotation[] annotations);
 
     /**
-     * 注册一个代名称的Bean
-     * @param name	bean名称
-     * @param value	bean对象
-     * @return		返回注册的Bean
+     * Register bean with a name 
+     * @param name		bean name
+     * @param value		bean object
+     * @return			return register bean
      */
     Object registerBean(String name, Object value);
     
     /**
-     * 注册一个对象到bean容器中
+     * Register an object to the bean container
      * 
-     * @param object		要注册的object
-     * @return				返回注册后的Bean实例
+     * @param object	bean object
+     * @return			return register bean
      */
     Object registerBean(Object object);
     
     /**
-     * 初始化IOC
+     * Initialization IOC injection 
      */
     void initWired();
     
     /**
-     * 注入一个object
-     * @param object	要注入的object
+     * Inject a object 
+     * @param object	to inject object 
      */
     void injection(Object object);
     
     /**
-     * @return 返回ioc容器中的所有bean对象的K,V
+     * @return Returns the all bean objects in the IOC container
      */
     Map getBeanMap();
     
diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java
index 7184ba32f..e4b1c6efb 100644
--- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java
+++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java
@@ -34,7 +34,7 @@
 import com.blade.annotation.Path;
 
 /**
- * 默认的IOC容器实现
+ * IOC default implement
  *
  * @author	biezhi
  * @since	1.0
@@ -45,17 +45,17 @@ public class SampleContainer implements Container {
     private static final Logger LOGGER = Logger.getLogger(SampleContainer.class);
 
     /**
-     * 保存所有bean对象 如:com.xxxx.User @Userx7asc
+     * Save all bean objects, e.g: com.xxxx.User @Userx7asc
      */
     private Map beans = CollectionKit.newConcurrentHashMap();
     
     /**
-     * 存储所有的对象名和对于的类名关系
+     * All of the object storage and for class relations 
      */
     private Map beanKeys = CollectionKit.newConcurrentHashMap();
     
     /**
-     * 保存所有注解的class
+     * Save all the notes class
      */
     private Map, List> annotaionBeans = CollectionKit.newConcurrentHashMap();
     
@@ -84,7 +84,7 @@ public  T getBean(String name, Scope scope) {
     		try {
 				return (T) CloneKit.deepClone(obj);
 			} catch (Exception e) {
-				LOGGER.error("克隆对象失败," + e.getMessage());
+				throw new IocException("clone object error", e);
 			}
     	}
         return (T) obj;
@@ -144,10 +144,10 @@ public Object registerBean(String name, Object value) {
     	Assert.notNull(value);
     	
     	Class clazz = value.getClass();
-		//非抽象类、接口
+		// Not abstract class, interface 
 		if (isNormalClass(clazz)) {
 			
-			// 如果容器已经存在该名称对于的对象,直接返回
+			// If the container already exists, the name is directly returned 
 			String className = beanKeys.get(name);
 			if (StringKit.isNotBlank(className)) {
 				return beans.get(className);
@@ -159,7 +159,7 @@ public Object registerBean(String name, Object value) {
 				beans.put(className, value);
 			}
 		    
-		    //实现的接口对应存储
+		    // Achieve the interface corresponding storage 
 		    Class[] interfaces = clazz.getInterfaces();
 		    if(interfaces.length > 0){
 		    	for(Class interfaceClazz : interfaces){
@@ -168,7 +168,7 @@ public Object registerBean(String name, Object value) {
 		    	}
 		    }
 		    
-		    //带有annotation
+		    // With annotation 
 		    if(null != clazz.getDeclaredAnnotations()){
 		    	putAnnotationMap(clazz, value);
 		    }
@@ -183,7 +183,7 @@ private void registerParent(String name, Object value) {
 		
     	Class clazz = value.getClass();
 			
-		// 如果容器已经存在该名称对于的对象,直接返回
+		// If the container already exists, the name is directly returned 
 		String className = beanKeys.get(name);
 		if (StringKit.isNotBlank(className)) {
 			return;
@@ -205,10 +205,10 @@ public Object registerBean(Object object) {
 	}
     
     /**
-     * 给annotationMap添加元素
+     * Add elements to annotationMap 
      * 
-     * @param clazz			要注入的class类型
-     * @param object		注册的bean对象
+     * @param clazz		class type to be injected 
+     * @param object	registered bean object 
      */
     private void putAnnotationMap(Class clazz, Object object){
     	
@@ -227,10 +227,10 @@ private void putAnnotationMap(Class clazz, Object object){
     }
     
     /**
-     * annotationBean容器存储
+     * AnnotationBean container storage 
      * 
-     * @param clazz			允许注册的Annotation类型
-     * @param listObject	要注入的对象列表
+     * @param clazz			allows the Annotation type to be registered 
+     * @param listObject	list of objects to be injected 
      */
     private void put(Class clazz, List listObject){
     	if(null == annotaionBeans.get(clazz)){
@@ -239,7 +239,7 @@ private void put(Class clazz, List listObject){
     }
     
     /**
-     * 初始化注入
+     * Initialization injection
      */
     @Override
     public void initWired() throws RuntimeException {
@@ -251,7 +251,7 @@ public void initWired() throws RuntimeException {
     	}
     }
     
-    // 装配
+    // Assemble
     private Object recursiveAssembly(Class clazz){
     	Object field = null;
     	if(null != clazz){
@@ -263,10 +263,10 @@ private Object recursiveAssembly(Class clazz){
     
     
     /**
-     * 判断是否是可以注册的bean
+     * To determine whether the bean can be registered 
      * 
-     * @param annotations		注解类型
-     * @return 					true:可以注册 false:不可以注册
+     * @param annotations		annotation class type arrays
+     * @return 					return is register
      */
     @Override
     public boolean isRegister(Annotation[] annotations) {
@@ -282,9 +282,9 @@ public boolean isRegister(Annotation[] annotations) {
     }
     
     /**
-     * 是否是一个非接口和抽象类的Class
-     * @param clazz
-     * @return
+     * Is not interface and abstract class Class 
+     * @param clazz 	class type
+     * @return			return is interface && abstract class
      */
     private boolean isNormalClass(Class clazz){
     	if(!Modifier.isAbstract(clazz.getModifiers()) && !clazz.isInterface()){
@@ -292,7 +292,7 @@ private boolean isNormalClass(Class clazz){
     	}
     	return false;
     }
-
+    
 	@Override
 	public List> getClassesByAnnotation(Class annotation) {
 		List objectList = getBeansByAnnotation(annotation);
@@ -321,14 +321,14 @@ public boolean removeAll() {
 
 	@Override
 	public void injection(Object object) {
-		// 所有字段
+		// Traverse all fields 
 	    try {
 			Field[] fields = object.getClass().getDeclaredFields();
 			for (Field field : fields) {
-				// 需要注入的字段
+				// Need to inject the field 
 			    Inject inject = field.getAnnotation(Inject.class);
 			    if (null != inject ) {
-			    	// 要注入的字段
+			    	// Bean to be injected 
 			        Object injectField = null;
 			        String name = inject.name();
 			        if(!name.equals("")){
@@ -343,7 +343,7 @@ public void injection(Object object) {
 	        			if(inject.value() == Class.class){
 	        				injectField = recursiveAssembly(field.getType());
 				        } else {
-				        	// 指定装配的类
+				        	// Specify an assembly
 				        	injectField = this.getBean(inject.value(), null);
 				            if (null == injectField) {
 				            	injectField = recursiveAssembly(inject.value());
diff --git a/blade-core/src/main/java/com/blade/ioc/Scope.java b/blade-core/src/main/java/com/blade/ioc/Scope.java
index dae4b4147..a59a8d3b9 100644
--- a/blade-core/src/main/java/com/blade/ioc/Scope.java
+++ b/blade-core/src/main/java/com/blade/ioc/Scope.java
@@ -16,10 +16,8 @@
 package com.blade.ioc;
 
 /**
- * Bean创建类型
- * 

- * SINGLE:单例,PROTOTYPE:原生 - *

+ * Bean create type + * SINGLE, PROTOTYPE * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/ioc/package-info.java b/blade-core/src/main/java/com/blade/ioc/package-info.java index 3573a46d3..a4173b462 100644 --- a/blade-core/src/main/java/com/blade/ioc/package-info.java +++ b/blade-core/src/main/java/com/blade/ioc/package-info.java @@ -1,4 +1,4 @@ /** - * Blade依赖注入包 + * Blade IOC */ package com.blade.ioc; \ No newline at end of file From 1c2cb71b75bf98189164cae096e3f658ace8c989 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 13:35:00 +0800 Subject: [PATCH 331/545] modify english comments --- .../main/java/com/blade/ioc/IocException.java | 22 ++++++++++++ .../kit/exception/ClassReaderException.java | 32 +++++++++++++++++ .../kit/exception/IllegalPathException.java | 35 +++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 blade-core/src/main/java/com/blade/ioc/IocException.java create mode 100644 blade-kit/src/main/java/blade/kit/exception/ClassReaderException.java create mode 100644 blade-kit/src/main/java/blade/kit/exception/IllegalPathException.java diff --git a/blade-core/src/main/java/com/blade/ioc/IocException.java b/blade-core/src/main/java/com/blade/ioc/IocException.java new file mode 100644 index 000000000..9102fc219 --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/IocException.java @@ -0,0 +1,22 @@ +package com.blade.ioc; + +public class IocException extends RuntimeException { + + private static final long serialVersionUID = -1896357479295031509L; + + public IocException() { + } + + public IocException(String msg) { + super(msg); + } + + public IocException(Throwable t) { + super(t); + } + + public IocException(String msg, Throwable t) { + super(msg, t); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/exception/ClassReaderException.java b/blade-kit/src/main/java/blade/kit/exception/ClassReaderException.java new file mode 100644 index 000000000..536861e39 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/exception/ClassReaderException.java @@ -0,0 +1,32 @@ +package blade.kit.exception; + +/** + * 类读取异常 + * + * @author biezhi + * @since 1.0 + */ +public class ClassReaderException extends RuntimeException { + + private static final long serialVersionUID = -1L; + + public ClassReaderException() { + super(); + } + + public ClassReaderException(Exception e) { + super(e); + } + + public ClassReaderException(String msg) { + super(msg); + } + + public ClassReaderException(String msg, Exception e) { + super(msg, e); + } + + public Throwable fillInStackTrace() { + return null; + } +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/exception/IllegalPathException.java b/blade-kit/src/main/java/blade/kit/exception/IllegalPathException.java new file mode 100644 index 000000000..aeb57bf78 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/exception/IllegalPathException.java @@ -0,0 +1,35 @@ +package blade.kit.exception; + +/** + * 代表非法的路径。 + * + * @author biezhi + * @since 1.0 + */ +public class IllegalPathException extends IllegalArgumentException { + + /** + * + */ + private static final long serialVersionUID = 1434004725746713564L; + + public IllegalPathException() { + super(); + } + + public IllegalPathException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalPathException(String s) { + super(s); + } + + public IllegalPathException(Throwable cause) { + super(cause); + } + + public Throwable fillInStackTrace() { + return null; + } +} \ No newline at end of file From 0ee10d9734fd686659c32dbdc517a7a909a54b2d Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 13:46:42 +0800 Subject: [PATCH 332/545] modify english comments --- .../blade/loader/AbstractFileRouteLoader.java | 57 +++++++++++-------- .../loader/ClassPathControllerLoader.java | 22 +++++-- .../blade/loader/ClassPathRouteLoader.java | 20 +++++-- .../main/java/com/blade/loader/Config.java | 30 +++++----- .../java/com/blade/loader/Configurator.java | 6 +- .../com/blade/loader/ControllerLoader.java | 20 +++++-- .../blade/loader/FileSystemRouteLoader.java | 20 +++++-- .../java/com/blade/loader/RouteLoader.java | 20 +++++-- .../java/com/blade/loader/package-info.java | 2 +- 9 files changed, 134 insertions(+), 63 deletions(-) diff --git a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java index 729cc0708..01b60e3b2 100644 --- a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.loader; import java.io.BufferedReader; @@ -19,9 +34,7 @@ import blade.kit.IOKit; /** - *

- * 抽象加载器实现 - *

+ * Abstract loader implementation * * @author biezhi * @since 1.0 @@ -48,12 +61,12 @@ public List load() throws ParseException, RouteException { } /** - * 加载路由 + * Load Route * - * @param inputStream 路由文件流 - * @return 返回路由列表 - * @throws ParseException 解析异常 - * @throws IOException IO异常 + * @param inputStream route inputstream + * @return return route list + * @throws ParseException parse exception + * @throws IOException io exception */ private List load(InputStream inputStream) throws ParseException, IOException { int line = 0; @@ -84,7 +97,7 @@ private Route parse(String input, int line) throws ParseException { throw new ParseException("Unrecognized format", line); } - // 验证HTTP请求方 + // Verify HTTP request String httpMethod = validateHttpMethod( st.nextToken().trim(), line ); String path = validatePath( st.nextToken().trim(), line ); @@ -93,7 +106,7 @@ private Route parse(String input, int line) throws ParseException { int hashPos = controllerAndMethod.indexOf("."); String controllerName = controllerAndMethod.substring(0, hashPos); - // 获取控制器方法 + // Acquisition controller method String controllerMethod = controllerAndMethod.substring(hashPos + 1); return buildRoute(httpMethod, path, controllerName, controllerMethod); @@ -129,9 +142,7 @@ private String validatePath(String path, int line) throws ParseException { if (path.charAt(i) == '}') { openedKey = false; } - } - return path; } @@ -151,16 +162,16 @@ private boolean isValidCharForPath(char c, boolean openedKey) { } } } - + return true; } /** - * 验证控制器方法 + * Verification controller method * - * @param beanAndMethod 控制器和方法,使用.隔开 - * @param line 所在行数 - * @return 返回验证后的字符串,异常则抛出 + * @param beanAndMethod controller and method, using. + * @param line line number + * @return return a string that is verified after the verification. * @throws ParseException */ private String validateControllerAndMethod(String beanAndMethod, int line) throws ParseException { @@ -173,13 +184,13 @@ private String validateControllerAndMethod(String beanAndMethod, int line) throw } /** - * 构建一个路由对象 + * Construct a routing object * - * @param httpMethod 请求方法 - * @param path 路由路径 - * @param controllerName 控制器名称 - * @param methodName 执行的方法名称 - * @return 返回路由对象 + * @param httpMethod request httpMethod + * @param path route path + * @param controllerName controller name + * @param methodName method name + * @return return route object * @throws RouteException */ private Route buildRoute(String httpMethod, String path, String controllerName, String methodName) throws RouteException { diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java index 99c307e2c..34127d5dd 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.loader; import com.blade.Aop; @@ -7,10 +22,7 @@ import com.blade.route.RouteException; /** - * - *

- * ClassPath控制器加载器 - *

+ * ClassPath controller of loader * * @author biezhi * @since 1.0 @@ -42,7 +54,7 @@ public Object load(String controllerName) throws RouteException { String className = basePackage + controllerName; try { - // 加载控制器实例 + // Load controller instance Class controllerClass = classLoader.loadClass(className); Object controller = container.getBean(controllerClass, Scope.SINGLE); diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathRouteLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathRouteLoader.java index 5cf2c9d48..301d06f39 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathRouteLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ClassPathRouteLoader.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.loader; import java.io.File; @@ -5,10 +20,7 @@ import java.io.InputStream; /** - * - *

- * 基于ClassPath实现的路由加载器 - *

+ * Route loader based on ClassPath * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/loader/Config.java b/blade-core/src/main/java/com/blade/loader/Config.java index a04e40125..37ad1f838 100644 --- a/blade-core/src/main/java/com/blade/loader/Config.java +++ b/blade-core/src/main/java/com/blade/loader/Config.java @@ -23,7 +23,7 @@ import blade.kit.PatternKit; /** - * Blade配置类 + * Blade Config Class * * @author biezhi * @since 1.0 @@ -31,46 +31,46 @@ */ public class Config { - // 存放所有变量 + // Store all variables private Map configMap = CollectionKit.newHashMap(); - // 存放所有路由的包 + // Storage of all routing packets private List routePackages = CollectionKit.newArrayList(); - // 存放所有IOC的包 + // Store all IOC packages private List iocPackages = CollectionKit.newArrayList(); - // 存放所有过滤目录 + // Store all filter directories private List staticFolders = CollectionKit.newArrayList(); - // 基础包 + // Base package private String basePackage; - // 拦截器包 + // Interceptor package private String interceptorPackage; - // 编码 + // Encoding private String encoding = "utf-8"; - // 视图前缀 + // View prefix private String viewPrefix = "/WEB-INF/"; - // 视图后缀 + // View suffix private String viewSuffix = ".jsp"; - // webroot根目录,物理路径 + // web root path private String webRoot; - // 404视图位置 + // 404 view page private String view404; - // 500视图位置 + // 500 view page private String view500; - // 是否是DEBUG模式 + // Is debug mode private boolean isDebug = true; - // 是否开启XSS防御 + // Enabled XSS private boolean enableXSS = false; public Config() { diff --git a/blade-core/src/main/java/com/blade/loader/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java index ecccffaea..3cab8a65d 100644 --- a/blade-core/src/main/java/com/blade/loader/Configurator.java +++ b/blade-core/src/main/java/com/blade/loader/Configurator.java @@ -20,17 +20,17 @@ import blade.kit.StringKit; /** - * Blade配置文件注入 + * Blade configuration * * @author biezhi * @since 1.0 */ public class Configurator { - // 配置文件对象 + // Configuration object private Config bladeConfig; - // 配置map + // Configuration Map private Map configMap; public Configurator(Config bladeConfig, diff --git a/blade-core/src/main/java/com/blade/loader/ControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ControllerLoader.java index 6c92ed277..bcff33a5a 100644 --- a/blade-core/src/main/java/com/blade/loader/ControllerLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ControllerLoader.java @@ -1,12 +1,24 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.loader; import com.blade.route.RouteException; /** - * - *

- * 控制器加载接口 - *

+ * Controller loading interface * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/loader/FileSystemRouteLoader.java b/blade-core/src/main/java/com/blade/loader/FileSystemRouteLoader.java index 152447b87..37f69ee15 100644 --- a/blade-core/src/main/java/com/blade/loader/FileSystemRouteLoader.java +++ b/blade-core/src/main/java/com/blade/loader/FileSystemRouteLoader.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.loader; import java.io.File; @@ -5,10 +20,7 @@ import java.io.InputStream; /** - * - *

- * 基于文件系统实现的路由加载器 - *

+ * The file system based on Routing * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/loader/RouteLoader.java b/blade-core/src/main/java/com/blade/loader/RouteLoader.java index 79b62ba8f..00932075d 100644 --- a/blade-core/src/main/java/com/blade/loader/RouteLoader.java +++ b/blade-core/src/main/java/com/blade/loader/RouteLoader.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.loader; import java.text.ParseException; @@ -7,10 +22,7 @@ import com.blade.route.RouteException; /** - * - *

- * 路由加载器 - *

+ * Route loader * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/loader/package-info.java b/blade-core/src/main/java/com/blade/loader/package-info.java index 98165b833..bfbefb4f8 100644 --- a/blade-core/src/main/java/com/blade/loader/package-info.java +++ b/blade-core/src/main/java/com/blade/loader/package-info.java @@ -1,4 +1,4 @@ /** - * 配置加载包 + * Blade Config And Loader */ package com.blade.loader; \ No newline at end of file From b20766c6f413e564c2ecf92fffecf4d772a433ea Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 13:54:42 +0800 Subject: [PATCH 333/545] modify english comments --- .../main/java/com/blade/plugin/Plugin.java | 7 ++-- .../java/com/blade/plugin/package-info.java | 2 +- .../java/com/blade/render/BeetlRender.java | 10 +---- .../java/com/blade/render/JetbrickRender.java | 33 +++++++-------- .../main/java/com/blade/render/JspRender.java | 6 +-- .../java/com/blade/render/ModelAndView.java | 42 +++++++++---------- .../main/java/com/blade/render/Render.java | 5 +-- .../com/blade/render/RenderException.java | 5 +-- .../java/com/blade/render/VelocityRender.java | 23 ++++------ .../java/com/blade/render/package-info.java | 2 +- 10 files changed, 53 insertions(+), 82 deletions(-) diff --git a/blade-core/src/main/java/com/blade/plugin/Plugin.java b/blade-core/src/main/java/com/blade/plugin/Plugin.java index e692d875d..1bc35d6be 100644 --- a/blade-core/src/main/java/com/blade/plugin/Plugin.java +++ b/blade-core/src/main/java/com/blade/plugin/Plugin.java @@ -15,9 +15,8 @@ */ package com.blade.plugin; - /** - * 插件顶层接口 + * Plugin Interface * * @author biezhi * @since 1.0 @@ -25,12 +24,12 @@ public interface Plugin { /** - * 要执行的方法 + * Run Plugin */ void run(); /** - * 销毁,释放资源 + * Destroy, release resources */ void destroy(); } diff --git a/blade-core/src/main/java/com/blade/plugin/package-info.java b/blade-core/src/main/java/com/blade/plugin/package-info.java index 39b8ea2e0..9ef5ba337 100644 --- a/blade-core/src/main/java/com/blade/plugin/package-info.java +++ b/blade-core/src/main/java/com/blade/plugin/package-info.java @@ -1,4 +1,4 @@ /** - * 插件包 + * Blade Plugin */ package com.blade.plugin; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/render/BeetlRender.java b/blade-core/src/main/java/com/blade/render/BeetlRender.java index 0c4c45c46..e12cdaf11 100644 --- a/blade-core/src/main/java/com/blade/render/BeetlRender.java +++ b/blade-core/src/main/java/com/blade/render/BeetlRender.java @@ -34,10 +34,7 @@ import blade.kit.log.Logger; /** - * - *

- * Beetl渲染引擎 - *

+ * Beetl Render * * @author biezhi * @since 1.0 @@ -47,15 +44,12 @@ public class BeetlRender implements Render { private static final Logger LOGGER = Logger.getLogger(BeetlRender.class); /** - * Beetl获取模板对象 + * Beetl GroupTemplate Object */ private GroupTemplate groupTemplate = null; private String webRoot; - /** - * 默认构造函数 - */ public BeetlRender() { try { Blade blade = Blade.me(); diff --git a/blade-core/src/main/java/com/blade/render/JetbrickRender.java b/blade-core/src/main/java/com/blade/render/JetbrickRender.java index 3fc8ffba7..b99a7781f 100644 --- a/blade-core/src/main/java/com/blade/render/JetbrickRender.java +++ b/blade-core/src/main/java/com/blade/render/JetbrickRender.java @@ -33,10 +33,7 @@ import jetbrick.template.JetTemplate; /** - * - *

- * Velocity渲染引擎 - *

+ * Velocity Render * * @author biezhi * @since 1.0 @@ -50,9 +47,7 @@ public class JetbrickRender implements Render { private Properties config; private String webRoot; - /** - * 默认构造函数 - */ + public JetbrickRender() { Blade blade = Blade.me(); this.webRoot = blade.webRoot(); @@ -65,14 +60,14 @@ public JetbrickRender() { } /** - * @return 返回JetEngine引擎 + * @return return JetEngine */ public JetEngine getJetEngine(){ return jetEngine; } /** - * 清空配置 + * clean config */ public void clean(){ if(null != config){ @@ -81,10 +76,10 @@ public void clean(){ } /** - * 添加一个配置 + * add config * - * @param key 配置键 - * @param value 配置值 + * @param key key + * @param value value */ public void put(String key, Object value){ if(null == config){ @@ -94,10 +89,10 @@ public void put(String key, Object value){ } /** - * 根据配置文件构造一个JetEngine引擎 + * Construct a JetEngine engine based on the configuration file * - * @param configLocation 配置文件路径 - * @throws IOException 抛出IO异常 + * @param configLocation configuration file path for ClassPath + * @throws IOException io exception */ public JetbrickRender(String configLocation) throws IOException { Blade blade = Blade.me(); @@ -106,9 +101,9 @@ public JetbrickRender(String configLocation) throws IOException { } /** - * 根据构造一个JetEngine引擎 + * According to the construction of a JetEngine engine * - * @param config Properties配置 + * @param config properties configuration */ public JetbrickRender(Properties config) { Blade blade = Blade.me(); @@ -118,9 +113,9 @@ public JetbrickRender(Properties config) { } /** - * 手动构造JetEngine引擎 + * Manually constructed JetEngine engine * - * @param jetEngine jetEngine引擎 + * @param jetEngine jetEngine engine object */ public JetbrickRender(JetEngine jetEngine) { this.jetEngine = jetEngine; diff --git a/blade-core/src/main/java/com/blade/render/JspRender.java b/blade-core/src/main/java/com/blade/render/JspRender.java index b27e2c901..c64d9114c 100644 --- a/blade-core/src/main/java/com/blade/render/JspRender.java +++ b/blade-core/src/main/java/com/blade/render/JspRender.java @@ -30,10 +30,7 @@ import com.blade.context.BladeWebContext; /** - * - *

- * JSP渲染引擎,默认的渲染器 - *

+ * JSP Render, Default Render * * @author biezhi * @since 1.0 @@ -71,7 +68,6 @@ public void render(ModelAndView modelAndView, Writer writer) { e.printStackTrace(); LOGGER.error(e); } - } } diff --git a/blade-core/src/main/java/com/blade/render/ModelAndView.java b/blade-core/src/main/java/com/blade/render/ModelAndView.java index 0c8c39581..bcb7159bf 100644 --- a/blade-core/src/main/java/com/blade/render/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/render/ModelAndView.java @@ -20,10 +20,7 @@ import blade.kit.CollectionKit; /** - * - *

- * ModelAndView使用模型和视图来渲染 - *

+ * ModelAndView, Using templates and data * * @author biezhi * @since 1.0 @@ -31,19 +28,19 @@ public class ModelAndView { /** - * 数据对象,该对象被放在httprequest的attribute中 + * Data object, the object is placed in the attribute httprequest */ private Map model; /** - * 视图 + * View Page */ private String view; /** - * 创建一个空视图 + * Create an empty view * - * @param view 视图 + * @param view view page */ public ModelAndView(String view) { super(); @@ -52,10 +49,10 @@ public ModelAndView(String view) { } /** - * 创建一个带数据的模型视图对象 + * Create a model view object with data * - * @param model 数据模型 - * @param view 视图 + * @param model model data + * @param view view page */ public ModelAndView(Map model, String view) { super(); @@ -64,19 +61,19 @@ public ModelAndView(Map model, String view) { } /** - * 添加数据 + * Add data to model * - * @param key 数据键 - * @param value 数据值 + * @param key key + * @param value value */ public void add(String key, Object value){ this.model.put(key, value); } /** - * 移除一个数据 + * Remove model data * - * @param key 模型的键 + * @param key key */ public void remove(String key){ this.model.remove(key); @@ -84,31 +81,32 @@ public void remove(String key){ /** * - * @return 获取视图 + * @return Return view page */ public String getView() { return view; } /** - * 设置视图 - * @param view 视图文件名称 + * Setting view page + * + * @param view view page */ public void setView(String view) { this.view = view; } /** - * @return 获取模型 + * @return Return model map */ public Map getModel() { return model; } /** - * 设置model + * Setting model * - * @param model 存放数据的map + * @param model Storage data map */ public void setModel(Map model) { this.model = model; diff --git a/blade-core/src/main/java/com/blade/render/Render.java b/blade-core/src/main/java/com/blade/render/Render.java index c68d0b0fc..b614228a4 100644 --- a/blade-core/src/main/java/com/blade/render/Render.java +++ b/blade-core/src/main/java/com/blade/render/Render.java @@ -18,10 +18,7 @@ import java.io.Writer; /** - * - *

- * 渲染器接口 - *

+ * Render Interface, For view layer to display data * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/render/RenderException.java b/blade-core/src/main/java/com/blade/render/RenderException.java index 9ff6a4ebf..9882b9399 100644 --- a/blade-core/src/main/java/com/blade/render/RenderException.java +++ b/blade-core/src/main/java/com/blade/render/RenderException.java @@ -16,10 +16,7 @@ package com.blade.render; /** - * - *

- * 渲染器异常 - *

+ * RenderException * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/render/VelocityRender.java b/blade-core/src/main/java/com/blade/render/VelocityRender.java index 91c3e2ec4..671868f31 100644 --- a/blade-core/src/main/java/com/blade/render/VelocityRender.java +++ b/blade-core/src/main/java/com/blade/render/VelocityRender.java @@ -36,10 +36,7 @@ import blade.kit.log.Logger; /** - * - *

- * Velocity渲染引擎 - *

+ * Velocity Render * * @author biezhi * @since 1.0 @@ -51,9 +48,7 @@ public class VelocityRender implements Render { private final VelocityEngine velocityEngine; private String webRoot; - /** - * 默认构造函数 - */ + public VelocityRender() { Blade blade = Blade.me(); this.webRoot = blade.webRoot(); @@ -67,10 +62,10 @@ public VelocityRender() { } /** - * 根据配置文件构造一个Velocity引擎 + * Construct a Velocity engine based on the configuration file * - * @param propertiesFile properties文件路径 - * @throws IOException 抛出IO异常 + * @param propertiesFile properties file path + * @throws IOException IO Exception */ public VelocityRender(String propertiesFile) throws IOException { Blade blade = Blade.me(); @@ -82,7 +77,7 @@ public VelocityRender(String propertiesFile) throws IOException { InputStream inStream = new FileInputStream(new File(fileName)); properties.load(inStream); - // 默认查询路径 + // Default query path if(!properties.contains(Velocity.FILE_RESOURCE_LOADER_PATH)){ properties.put(Velocity.FILE_RESOURCE_LOADER_PATH, blade.webRoot()); } @@ -90,7 +85,7 @@ public VelocityRender(String propertiesFile) throws IOException { } /** - * 根据构造一个Velocity引擎 + * According to the construction of a Velocity engine * * @param properties Properties配置文件 */ @@ -101,9 +96,9 @@ public VelocityRender(Properties properties) { } /** - * 手动构造Velocity引擎 + * Manually constructed Velocity engine * - * @param velocityEngine velocity引擎对象 + * @param velocityEngine velocity engine object */ public VelocityRender(VelocityEngine velocityEngine) { Blade blade = Blade.me(); diff --git a/blade-core/src/main/java/com/blade/render/package-info.java b/blade-core/src/main/java/com/blade/render/package-info.java index 41a8203db..f80838ca2 100644 --- a/blade-core/src/main/java/com/blade/render/package-info.java +++ b/blade-core/src/main/java/com/blade/render/package-info.java @@ -1,4 +1,4 @@ /** - * 视图渲染包,包含JSP、JetbrickTemplate、Beetl等 + * Blade Render */ package com.blade.render; \ No newline at end of file From 914602e26c703cabd32e81e5e5f05bf183f13346 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 16:32:56 +0800 Subject: [PATCH 334/545] modify english comments --- .../src/main/java/com/blade/route/Route.java | 13 +- .../java/com/blade/route/RouteBuilder.java | 73 ++++--- .../java/com/blade/route/RouteException.java | 5 +- .../java/com/blade/route/RouteHandler.java | 5 +- .../java/com/blade/route/RouteMatcher.java | 53 +++-- .../main/java/com/blade/route/Routers.java | 9 +- .../java/com/blade/route/package-info.java | 2 +- .../main/java/com/blade/server/Server.java | 5 +- .../java/com/blade/server/package-info.java | 2 +- .../java/com/blade/verify/CSRFConfig.java | 27 ++- .../com/blade/verify/CSRFTokenManager.java | 49 +++-- .../java/com/blade/verify/package-info.java | 2 +- .../com/blade/web/AsynRequestHandler.java | 80 ++++--- .../java/com/blade/web/DispatcherServlet.java | 12 +- .../java/com/blade/web/RouteArgument.java | 24 +-- .../com/blade/web/SyncRequestHandler.java | 83 ++++---- .../com/blade/web/http/HttpException.java | 5 +- .../java/com/blade/web/http/HttpMethod.java | 4 +- .../java/com/blade/web/http/HttpStatus.java | 5 +- .../main/java/com/blade/web/http/Path.java | 8 +- .../main/java/com/blade/web/http/Request.java | 195 +++++++++--------- .../java/com/blade/web/http/Response.java | 163 ++++++++++++++- .../java/com/blade/web/http/package-info.java | 2 +- .../web/http/wrapper/ServletRequest.java | 3 - .../web/http/wrapper/ServletResponse.java | 21 +- .../com/blade/web/http/wrapper/Session.java | 5 +- .../blade/web/http/wrapper/package-info.java | 2 +- .../com/blade/web/multipart/FileItem.java | 5 +- .../com/blade/web/multipart/Multipart.java | 5 +- .../web/multipart/MultipartException.java | 4 +- .../blade/web/multipart/MultipartHandler.java | 3 - .../com/blade/web/multipart/package-info.java | 2 +- 32 files changed, 491 insertions(+), 385 deletions(-) diff --git a/blade-core/src/main/java/com/blade/route/Route.java b/blade-core/src/main/java/com/blade/route/Route.java index 6b9d719c4..fc81f9ae8 100644 --- a/blade-core/src/main/java/com/blade/route/Route.java +++ b/blade-core/src/main/java/com/blade/route/Route.java @@ -21,10 +21,7 @@ import com.blade.web.http.Path; /** - * - *

- * 路由对象 - *

+ * Route Bean * * @author biezhi * @since 1.0 @@ -32,22 +29,22 @@ public class Route { /** - * HTTP请求方法 + * HTTP Request Method */ private HttpMethod httpMethod; /** - * 路由路径 + * Route path */ private String path; /** - * 执行逻辑的目标对象 + * Logical controller object */ private Object target; /** - * 执行逻辑的目标方法 + * Implementation logic controller method */ private Method action; diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index e35a57a44..727a0fa32 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -33,10 +33,7 @@ import com.blade.web.http.HttpMethod; /** - * - *

- * 路由构造器 - *

+ * Route builder * * @author biezhi * @since 1.0 @@ -44,22 +41,22 @@ public class RouteBuilder { /** - * 默认路由后缀包,用户扫描路由所在位置,默认为route,用户可自定义 + * Default route suffix package, the user scan route location, the default is route, users can customize */ private String pkgRoute = "route"; /** - * 默认拦截器后缀包,用户扫描拦截器所在位置,默认为interceptor,用户可自定义 + * Default interceptor suffix package, the user scans the interceptor location, the default is interceptor, users can customize */ private String pkgInterceptor = "interceptor"; /** - * 类读取器,用于在指定规则中扫描类 + * Class reader, used to scan the class specified in the rules */ private ClassReader classReader = new ClassPathClassReader(); /** - * IOC容器,存储路由到ioc中 + * IOC container, storage route to IOC */ private Container container = null; @@ -74,14 +71,14 @@ public RouteBuilder(Blade blade) { } /** - * 开始构建路由 + * Start building route */ public void building() { String basePackage = blade.basePackage(); if(StringKit.isNotBlank(basePackage)){ - // 处理如:com.xxx.* 表示递归扫描包 + // Processing e.g: com.xxx.* representation of recursive scanning package String suffix = basePackage.endsWith(".*") ? ".*" : ""; basePackage = basePackage.endsWith(".*") ? basePackage.substring(0, basePackage.length() - 2) : basePackage; @@ -92,13 +89,13 @@ public void building() { buildInterceptor(interceptorPackage); } else { - // 路由 + // Route String[] routePackages = blade.routePackages(); if(null != routePackages && routePackages.length > 0){ buildRoute(routePackages); } - // 拦截器 + // Inteceptor String interceptorPackage = blade.interceptorPackage(); if(StringKit.isNotBlank(interceptorPackage)){ buildInterceptor(interceptorPackage); @@ -107,16 +104,16 @@ public void building() { } /** - * 构建拦截器 + * Build interceptor * - * @param interceptorPackages 要添加的拦截器包 + * @param interceptorPackages add the interceptor package */ private void buildInterceptor(String... interceptorPackages){ - // 扫描所有的Interceptor + // Scan all Interceptor Set> classes = null; - // 拦截器 + // Traversal Interceptor for(String packageName : interceptorPackages){ boolean recursive = false; @@ -126,7 +123,7 @@ private void buildInterceptor(String... interceptorPackages){ recursive = true; } - // 扫描所有的Interceptor + // Scan all Interceptor classes = classReader.getClassByAnnotation(packageName, Interceptor.class, recursive); if(null != classes && classes.size() > 0){ @@ -138,13 +135,13 @@ private void buildInterceptor(String... interceptorPackages){ } /** - * 构建路由 + * Build Route * - * @param routePackages 要添加的路由包 + * @param routePackages route packets to add */ private void buildRoute(String... routePackages){ Set> classes = null; - // 路由 + // Traverse route for(String packageName : routePackages){ boolean recursive = false; @@ -154,7 +151,7 @@ private void buildRoute(String... routePackages){ recursive = true; } - // 扫描所有的Controoler + // Scan all Controoler classes = classReader.getClassByAnnotation(packageName, Path.class, recursive); if(null != classes && classes.size() > 0){ @@ -167,9 +164,9 @@ private void buildRoute(String... routePackages){ } /** - * 解析拦截器 + * Parse Interceptor * - * @param interceptor 要解析的拦截器class + * @param interceptor resolve the interceptor class */ private void parseInterceptor(final Class interceptor){ @@ -222,9 +219,9 @@ private void parseInterceptor(final Class interceptor){ } /** - * 解析一个控制器中的所有路由 + * Parse all routing in a controller * - * @param controller 要解析的路由class + * @param controller resolve the routing class */ private void parseRouter(final Class router){ @@ -243,17 +240,17 @@ private void parseRouter(final Class router){ Route mapping = method.getAnnotation(Route.class); - //route方法 + //route method if (null != mapping) { - ////构建路由 + // build String path = getRoutePath(mapping.value(), nameSpace, suffix); HttpMethod methodType = mapping.method(); buildRoute(router, method, path, methodType); - // 构建多个路由 + // build multiple route String[] paths = mapping.values(); if(null != paths && paths.length > 0){ for(String value : paths){ @@ -278,24 +275,24 @@ private String getRoutePath(String value, String nameSpace, String suffix){ } /** - * 构建一个路由 + * Build a route * - * @param target 路由目标执行的class - * @param execMethod 路由执行方法 - * @param path 路由url - * @param method 路由http方法 + * @param target route target execution class + * @param execMethod route execution method + * @param path route path + * @param method route httpmethod */ private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ this.routers.route(path, clazz, execMethod, method); } /** - * 构建一个路由 + * Build a route * - * @param path 路由url - * @param target 路由目标执行的class - * @param execMethod 路由执行方法 - * @param method 路由http方法 + * @param path route path + * @param target route target execution class + * @param execMethod route execution method + * @param method route httpmethod */ private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ this.routers.route(path, clazz, execMethod, method); diff --git a/blade-core/src/main/java/com/blade/route/RouteException.java b/blade-core/src/main/java/com/blade/route/RouteException.java index d027ac396..1242bebe7 100644 --- a/blade-core/src/main/java/com/blade/route/RouteException.java +++ b/blade-core/src/main/java/com/blade/route/RouteException.java @@ -16,10 +16,7 @@ package com.blade.route; /** - * - *

- * 路由异常类 - *

+ * RouteException * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/route/RouteHandler.java b/blade-core/src/main/java/com/blade/route/RouteHandler.java index c426066e9..df6449587 100644 --- a/blade-core/src/main/java/com/blade/route/RouteHandler.java +++ b/blade-core/src/main/java/com/blade/route/RouteHandler.java @@ -19,10 +19,7 @@ import com.blade.web.http.Response; /** - * - *

- * 路由执行器 - *

+ * Route Handler * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java index 44b06beef..abe271727 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcher.java @@ -29,10 +29,7 @@ import com.blade.web.http.Path; /** - * - *

- * 路由匹配器默认实现 - *

+ * Default Route Matcher * * @author biezhi * @since 1.0 @@ -41,11 +38,11 @@ public class RouteMatcher { // private static final Logger LOGGER = Logger.getLogger(SampleRouteMatcher.class); - // 存储URL和路由关系 + // Storage URL and route private Map routes = null; private Map interceptors = null; - // 存储Map Key + // Storage Map Key private Set routeKeys = null; private List interceptorRoutes = new ArrayList(); @@ -60,10 +57,10 @@ public RouteMatcher(Routers routers) { } /** - * 查找一个路由 - * @param httpMethod http请求方法 - * @param path 请求路径 - * @return 返回路由对象 + * Find a route + * @param httpMethod httpMethod + * @param path request path + * @return return route object */ public Route getRoute(String httpMethod, String path) { String cleanPath = parsePath(path); @@ -89,16 +86,16 @@ public Route getRoute(String httpMethod, String path) { } } - // 优先匹配原则 + // Priority matching principle giveMatch(path, matchRoutes); return matchRoutes.size() > 0 ? matchRoutes.get(0) : null; } /** - * 查找所有前置拦截器 - * @param path 请求路径 - * @return 返回前置拦截器列表 + * Find all in before of the interceptor + * @param path request path + * @return return interceptor list */ public List getBefore(String path) { @@ -114,9 +111,9 @@ public List getBefore(String path) { } /** - * 查找所有后置拦截器 - * @param path 请求路径 - * @return 返回后置拦截器列表 + * Find all in after of the interceptor + * @param path request path + * @return return interceptor list */ public List getAfter(String path) { List afters = new ArrayList(); @@ -131,9 +128,9 @@ public List getAfter(String path) { } /** - * 对path进行排序 - * @param uri 请求uri - * @param routes 路由列表 + * Sort of path + * @param uri request uri + * @param routes route list */ private void giveMatch(final String uri, List routes) { Collections.sort(routes, new Comparator() { @@ -148,10 +145,11 @@ public int compare(Route o1, Route o2) { } /** - * 匹配路径 - * @param routePath 路由路径 - * @param pathToMatch 要匹配的路径 - * @return 返回是否匹配成功 + * Matching path + * + * @param routePath route path + * @param pathToMatch match path + * @return return match is success */ private boolean matchesPath(String routePath, String pathToMatch) { routePath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); @@ -159,9 +157,10 @@ private boolean matchesPath(String routePath, String pathToMatch) { } /** - * 解析路径 - * @param path 路径地址 - * @return 返回解析后的路径 + * Parse Path + * + * @param path route path + * @return return parsed path */ private String parsePath(String path) { path = Path.fixPath(path); diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 42f0970db..c9b05c199 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -31,10 +31,7 @@ import com.blade.web.http.Response; /** - * - *

- * 注册、管理路由 - *

+ * Registration, management route * * @author biezhi * @since 1.0 @@ -70,7 +67,7 @@ public void addRoute(Route route) { HttpMethod httpMethod = route.getHttpMethod(); String key = path + "#" + httpMethod.toString(); - // 存在的 + // existent if (null != this.routes.get(key)) { LOGGER.warn("\tRoute "+ path + " -> " + httpMethod.toString() +" has exist"); } @@ -107,7 +104,7 @@ public void addRoute(HttpMethod httpMethod, String path, Object controller, Meth Assert.notNull(method); String key = path + "#" + httpMethod.toString(); - // 存在的 + // existent if (null != this.routes.get(key)) { LOGGER.warn("\tRoute "+ path + " -> " + httpMethod.toString() +" has exist"); } diff --git a/blade-core/src/main/java/com/blade/route/package-info.java b/blade-core/src/main/java/com/blade/route/package-info.java index 90a5f2e61..e4a44e705 100644 --- a/blade-core/src/main/java/com/blade/route/package-info.java +++ b/blade-core/src/main/java/com/blade/route/package-info.java @@ -1,4 +1,4 @@ /** - * 路由以及实现 + * Blade Route */ package com.blade.route; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java index 039b880e9..f71cf1ce6 100644 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -23,10 +23,7 @@ import com.blade.web.DispatcherServlet; /** - * - *

- * Jetty服务 - *

+ * Jetty Server * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/server/package-info.java b/blade-core/src/main/java/com/blade/server/package-info.java index 0e8ea64f8..928775bd0 100644 --- a/blade-core/src/main/java/com/blade/server/package-info.java +++ b/blade-core/src/main/java/com/blade/server/package-info.java @@ -1,4 +1,4 @@ /** - * Jetty服务包 + * Blade Jetty Ext */ package com.blade.server; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/verify/CSRFConfig.java b/blade-core/src/main/java/com/blade/verify/CSRFConfig.java index aa5caf950..cc003869c 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFConfig.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFConfig.java @@ -16,47 +16,44 @@ package com.blade.verify; /** - * - *

- * CSRF配置 - *

+ * CSRF Config * * @author biezhi * @since 1.0 */ public class CSRFConfig { - // 用于生成令牌的全局秘钥,默认为随机字符串 + // For the global key generation token, default random string String secret = "blade"; - // 用于保存用户 ID 的 session 名称,默认为 "csrf_token" + // ID to save the session name of the user, default is "csrf_token" String session = "csrf_token"; - // 用于传递令牌的 HTTP 请求头信息字段,默认为 "X-CSRFToken" + // HTTP request header information field for passing the token, default is "X-CSRFToken"" String header = "X-CSRFToken"; - // 用于传递令牌的表单字段名,默认为 "_csrf" + // Form field name for passing a token, defaukt is "_csrf" String form = "_csrf"; - // 用于传递令牌的 Cookie 名称,默认为 "_csrf" + // Cookie name for passing a token, default is "_csrf" String cookie = "_csrf"; - // Cookie 设置路径,默认为 "/" + // Cookie path, default is "/" String cookiePath = "/"; - // 生成token的长度,默认32位 + // Generate the token's length, the default 32 int length = 32; - // cookie过期时长,默认60秒 + // Cookie long, the default 60 seconds int expire = 3600; - // 用于指定是否要求只有使用 HTTPS 时才设置 Cookie,默认为 false + // Is used to specify whether the Cookie is set to HTTPS, default is false boolean secured = false; - // 用于指定是否将令牌设置到响应的头信息中,默认为 false + // Is used to specify whether the token is set to the header information in the response, default is false boolean setHeader = false; - // 用于指定是否将令牌设置到响应的 Cookie 中,默认为 false + // Is used to specify whether the token is set to the Cookie of the response, default is false boolean setCookie = false; public CSRFConfig() { diff --git a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java index 1fcff4526..f898910a4 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java @@ -24,10 +24,7 @@ import blade.kit.log.Logger; /** - * - *

- * CSRF token管理器 - *

+ * CSRF token Manager * * @author biezhi * @since 1.0 @@ -49,11 +46,11 @@ public static void config(CSRFConfig config){ } /** - * 创建一个token + * Create a token * - * @param request 请求对象 - * @param response 响应对象 - * @return 返回token令牌 + * @param request request object + * @param response response object + * @return return token */ public static String createToken(Request request, Response response) { String token = null; @@ -78,17 +75,17 @@ public static String createToken(Request request, Response response) { } /** - * 根据表单参数验证 + * According to form parameter verification * - * @param request 请求对象 - * @param response 响应对象 - * @return 返回是否验证成功 + * @param request request object + * @param response response object + * @return return verify is success */ public static boolean verifyAsForm(Request request, Response response) { - // 从 session 中得到 csrftoken 属性 + // csrftoken attribute from session String sToken = request.session().attribute(config.session); if (sToken == null) { - // 产生新的 token 放入 session 中 + // Generate new token into session sToken = CSRFTokenManager.createToken(request, response); return true; } else { @@ -102,17 +99,17 @@ public static boolean verifyAsForm(Request request, Response response) { } /** - * 根据头信息验证 + * According to header information verification * - * @param request 请求对象 - * @param response 响应对象 - * @return 返回是否验证成功 + * @param request request object + * @param response response object + * @return return verify is success */ public static boolean verifyAsHeader(Request request, Response response) { - // 从 session 中得到 csrftoken 属性 + // csrftoken attribute from session String sToken = request.session().attribute(config.session); if (sToken == null) { - // 产生新的 token 放入 session 中 + // Generate new token into session sToken = CSRFTokenManager.createToken(request, response); return true; } else { @@ -126,17 +123,17 @@ public static boolean verifyAsHeader(Request request, Response response) { } /** - * 根据cookie验证 + * According to cookie verification * - * @param request 请求对象 - * @param response 响应对象 - * @return 返回是否验证成功 + * @param request request object + * @param response response object + * @return return verify is success */ public static boolean verifyAsCookie(Request request, Response response) { - // 从 session 中得到 csrftoken 属性 + // csrftoken attribute from session String sToken = request.session().attribute(config.session); if (sToken == null) { - // 产生新的 token 放入 session 中 + // Generate new token into session sToken = CSRFTokenManager.createToken(request, response); return true; } else { diff --git a/blade-core/src/main/java/com/blade/verify/package-info.java b/blade-core/src/main/java/com/blade/verify/package-info.java index 669c278ce..fcae53082 100644 --- a/blade-core/src/main/java/com/blade/verify/package-info.java +++ b/blade-core/src/main/java/com/blade/verify/package-info.java @@ -1,4 +1,4 @@ /** - * 认证、安全包 + * Authentication And Security */ package com.blade.verify; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index 4e5f2738c..b9032a890 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; import java.lang.reflect.Method; @@ -27,8 +42,10 @@ import com.blade.web.http.wrapper.ServletResponse; /** - * 异步请求处理器 - * @author biezhi + * Asynchronous request processor + * + * @author biezhi + * @since 1.0 */ public class AsynRequestHandler implements Runnable { @@ -58,13 +75,13 @@ public void run(){ Response response = null; try { - // http方法, GET/POST ... + // http method, GET/POST ... String method = httpRequest.getMethod(); - // 请求的uri + // reuqest uri String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - // 如果是静态资源则交给filter处理 + // If it is static, the resource is handed over to the filter if(null != blade.staticFolder() && blade.staticFolder().length > 0){ if(!filterStaticFolder(uri)){ asyncContext.complete(); @@ -76,35 +93,35 @@ public void run(){ LOGGER.debug("Request : " + method + "\t" + uri); } - // 创建请求对象 + // Create Request Request request = new ServletRequest(httpRequest); - // 创建响应对象 + // Create Response response = new ServletResponse(httpResponse, blade.render()); - // 初始化context + // Init Context BladeWebContext.setContext(servletContext, request, response); Route route = routeMatcher.getRoute(method, uri); - // 如果找到 + // If find it if (route != null) { request.setRoute(route); - // 执行before拦截 + // before inteceptor List befores = routeMatcher.getBefore(uri); invokeInterceptor(request, response, befores); - // 实际执行方法 + // execute handle(request, response, route); - // 执行after拦截 + // after inteceptor List afters = routeMatcher.getAfter(uri); invokeInterceptor(request, response, afters); asyncContext.complete(); return; } - // 没有找到 + // Not found render404(response, uri); asyncContext.complete(); return; @@ -114,7 +131,7 @@ public void run(){ ThrowableKit.propagate(e); httpResponse.setStatus(500); - // 写入内容到浏览器 + // Write content to the browser if (!httpResponse.isCommitted()) { response.html(Const.INTERNAL_ERROR); asyncContext.complete(); @@ -126,10 +143,10 @@ public void run(){ } /** - * 404视图渲染 + * 404 view render * - * @param response 响应对象 - * @param uri 404的URI + * @param response response object + * @param uri 404 uri */ private void render404(Response response, String uri) { String view404 = blade.view404(); @@ -144,12 +161,11 @@ private void render404(Response response, String uri) { } /** - * 执行拦截器的方法 + * Methods to perform the interceptor * - * @param request 请求对象 - * @param response 响应对象 - * @param current 当前请求的路由 - * @param interceptors 要执行的拦截器列表 + * @param request request object + * @param response response object + * @param interceptors execute the interceptor list */ private void invokeInterceptor(Request request, Response response, List interceptors) { for(Route route : interceptors){ @@ -158,35 +174,33 @@ private void invokeInterceptor(Request request, Response response, List i } /** - * 实际的路由方法执行 + * Actual routing method execution * - * @param request 请求对象 - * @param response 响应对象 - * @param current 当前请求的路由 - * @param route 路由对象 + * @param request request object + * @param response response object + * @param route route object */ private void handle(Request request, Response response, Route route){ Object target = route.getTarget(); request.initPathParams(route.getPath()); - // 初始化context + // Init context BladeWebContext.setContext(servletContext, request, response); if(target instanceof RouteHandler){ RouteHandler routeHandler = (RouteHandler)target; routeHandler.handle(request, response); } else { - // 要执行的路由方法 Method actionMethod = route.getAction(); - // 执行route方法 + // execute RouteArgument.executeMethod(target, actionMethod, request, response); } } /** - * 要过滤掉的目录 + * Filter out the directory * - * @param uri URI表示当前路径,在静态目录中进行过滤 - * @return 返回false,过滤成功;返回true,不过滤 + * @param uri URI represents the current path, filtering in a static directory + * @return Return false, filter the success; return true, do not filter */ private boolean filterStaticFolder(String uri){ int len = blade.staticFolder().length; diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index ee1d8147c..8c3b2b5db 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -35,7 +35,7 @@ import com.blade.route.RouteMatcher; /** - * Blade核心调度器 + * Blade Core DispatcherServlet * * @author biezhi * @since 1.0 @@ -82,10 +82,10 @@ public void init(Blade blade) { } bootstrap.init(blade); - // 构建路由 + // buiding route new RouteBuilder(blade).building(); - // 初始化IOC + // initialization ioc blade.iocInit(); blade.bootstrap().contextInitialized(blade); @@ -117,10 +117,10 @@ protected void service(HttpServletRequest httpRequest, HttpServletResponse httpR } /** - * 获取全局初始化对象,初始化应用 + * Get global initialization object, the application of the initialization * - * @param botstrapClassName 全局初始化类名 - * @return 一个全局初始化对象 + * @param botstrapClassName botstrap class name + * @return return bootstrap object * @throws ServletException */ @SuppressWarnings("unchecked") diff --git a/blade-core/src/main/java/com/blade/web/RouteArgument.java b/blade-core/src/main/java/com/blade/web/RouteArgument.java index a2477ee4c..e1694655c 100644 --- a/blade-core/src/main/java/com/blade/web/RouteArgument.java +++ b/blade-core/src/main/java/com/blade/web/RouteArgument.java @@ -23,7 +23,7 @@ import com.blade.web.http.Response; /** - * 路由参数注入器 + * Route parameters of injector * * @author biezhi * @since 1.0 @@ -31,12 +31,12 @@ public final class RouteArgument { /** - * 获取方法内的参数 + * Parameters in the method * - * @param request Request对象,用于注入到method参数列表中 - * @param response Response对象,用于注入到method参数列表中 - * @param params params参数列表 - * @return 返回生成后的参数数组 + * @param request Request object for injection to the method parameter list + * @param response Response object for injection to the method parameter list + * @param params Params parameter list + * @return Return the generated array of parameters */ public static Object[] getArgs(Request request, Response response, Class[] params){ @@ -56,13 +56,13 @@ public static Object[] getArgs(Request request, Response response, Class[] pa } /** - * 执行路由方法 + * Implementation route * - * @param object 方法的实例,即该方法所在类的对象 - * @param method 要执行的method - * @param request Request对象,作为参数注入 - * @param response Response对象,作为参数注入 - * @return 返回方法执行后的返回值 + * @param object The instance of the method, that is, the object of the method's class. + * @param method Method to execute + * @param request Request object, as parameter injection + * @param response Response object, as parameter injection + * @return Return value after the method returns */ public static Object executeMethod(Object object, Method method, Request request, Response response){ int len = method.getParameterTypes().length; diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index abb51d076..c7e939475 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; import java.lang.reflect.Method; @@ -27,8 +42,10 @@ import com.blade.web.http.wrapper.ServletResponse; /** - * 同步请求处理器 - * @author biezhi + * Synchronous request processor + * + * @author biezhi + * @since 1.0 */ public class SyncRequestHandler { @@ -49,13 +66,13 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo Response response = null; try { - // http方法, GET/POST ... + // http method, GET/POST ... String method = httpRequest.getMethod(); - // 请求的uri + // reuqest uri String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - // 如果是静态资源则交给filter处理 + // If it is static, the resource is handed over to the filter if(null != blade.staticFolder() && blade.staticFolder().length > 0){ if(!filterStaticFolder(uri)){ return; @@ -66,34 +83,34 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo LOGGER.debug("Request : " + method + "\t" + uri); } - // 创建请求对象 + // Create Request Request request = new ServletRequest(httpRequest); - // 创建响应对象 + // Create Response response = new ServletResponse(httpResponse, blade.render()); - // 初始化context + // Init Context BladeWebContext.setContext(servletContext, request, response); Route route = routeMatcher.getRoute(method, uri); - // 如果找到 + // If find it if (route != null) { request.setRoute(route); - // 执行before拦截 + // before inteceptor List befores = routeMatcher.getBefore(uri); invokeInterceptor(request, response, befores); - // 实际执行方法 + // execute handle(request, response, route); - // 执行after拦截 + // after inteceptor List afters = routeMatcher.getAfter(uri); invokeInterceptor(request, response, afters); return; } - // 没有找到 + // Not found render404(response, uri); return; } catch (Exception e) { @@ -103,7 +120,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo ThrowableKit.propagate(e); httpResponse.setStatus(500); - // 写入内容到浏览器 + // Write content to the browser if (!httpResponse.isCommitted()) { response.html(Const.INTERNAL_ERROR); return; @@ -113,10 +130,10 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo } /** - * 404视图渲染 + * 404 view render * - * @param response 响应对象 - * @param uri 404的URI + * @param response response object + * @param uri 404 uri */ private void render404(Response response, String uri) { String view404 = blade.view404(); @@ -131,12 +148,11 @@ private void render404(Response response, String uri) { } /** - * 执行拦截器的方法 + * Methods to perform the interceptor * - * @param request 请求对象 - * @param response 响应对象 - * @param current 当前请求的路由 - * @param interceptors 要执行的拦截器列表 + * @param request request object + * @param response response object + * @param interceptors execute the interceptor list */ private void invokeInterceptor(Request request, Response response, List interceptors) { for(Route route : interceptors){ @@ -145,36 +161,33 @@ private void invokeInterceptor(Request request, Response response, List i } /** - * 实际的路由方法执行 + * Actual routing method execution * - * @param request 请求对象 - * @param response 响应对象 - * @param current 当前请求的路由 - * @param route 路由对象 + * @param request request object + * @param response response object + * @param route route object */ private void handle(Request request, Response response, Route route){ Object target = route.getTarget(); request.initPathParams(route.getPath()); - // 初始化context + // Init context BladeWebContext.setContext(servletContext, request, response); if(target instanceof RouteHandler){ RouteHandler routeHandler = (RouteHandler)target; routeHandler.handle(request, response); } else { - // 要执行的路由方法 Method actionMethod = route.getAction(); - // 执行route方法 + // execute RouteArgument.executeMethod(target, actionMethod, request, response); } } - - + /** - * 要过滤掉的目录 + * Filter out the directory * - * @param uri URI表示当前路径,在静态目录中进行过滤 - * @return 返回false,过滤成功;返回true,不过滤 + * @param uri URI represents the current path, filtering in a static directory + * @return Return false, filter the success; return true, do not filter */ private boolean filterStaticFolder(String uri){ int len = blade.staticFolder().length; diff --git a/blade-core/src/main/java/com/blade/web/http/HttpException.java b/blade-core/src/main/java/com/blade/web/http/HttpException.java index a3976f1e8..92dd26a7c 100644 --- a/blade-core/src/main/java/com/blade/web/http/HttpException.java +++ b/blade-core/src/main/java/com/blade/web/http/HttpException.java @@ -16,10 +16,7 @@ package com.blade.web.http; /** - * - *

- * Http异常 - *

+ * HttpException * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/web/http/HttpMethod.java b/blade-core/src/main/java/com/blade/web/http/HttpMethod.java index 6609cead2..421c2c0ce 100644 --- a/blade-core/src/main/java/com/blade/web/http/HttpMethod.java +++ b/blade-core/src/main/java/com/blade/web/http/HttpMethod.java @@ -16,9 +16,7 @@ package com.blade.web.http; /** - *

- * HTTP请求方法 - *

+ * HTTP Request Method * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/web/http/HttpStatus.java b/blade-core/src/main/java/com/blade/web/http/HttpStatus.java index 150ae1c0a..15525b457 100644 --- a/blade-core/src/main/java/com/blade/web/http/HttpStatus.java +++ b/blade-core/src/main/java/com/blade/web/http/HttpStatus.java @@ -16,11 +16,8 @@ package com.blade.web.http; /** + * HTTP Status * - *

- * HTTP状态码 - *

- * * @author biezhi * @since 1.0 */ diff --git a/blade-core/src/main/java/com/blade/web/http/Path.java b/blade-core/src/main/java/com/blade/web/http/Path.java index 67fe203dc..7f8ee06ef 100644 --- a/blade-core/src/main/java/com/blade/web/http/Path.java +++ b/blade-core/src/main/java/com/blade/web/http/Path.java @@ -23,10 +23,7 @@ import blade.kit.StringKit; /** - * - *

- * 路径、URL处理 - *

+ * Path URL * * @author biezhi * @since 1.0 @@ -41,9 +38,6 @@ public final class Path { public static String getRelativePath(String path, String contextPath) { -// String path = request.getRequestURI(); -// String contextPath = request.getContextPath(); - path = path.substring(contextPath.length()); if (path.length() > 0) { diff --git a/blade-core/src/main/java/com/blade/web/http/Request.java b/blade-core/src/main/java/com/blade/web/http/Request.java index da9e4ef38..c8051dbaf 100644 --- a/blade-core/src/main/java/com/blade/web/http/Request.java +++ b/blade-core/src/main/java/com/blade/web/http/Request.java @@ -28,10 +28,7 @@ import com.blade.web.multipart.FileItem; /** - * - *

- * HTTP请求对象 - *

+ * HTTP Request * * @author biezhi * @since 1.0 @@ -39,290 +36,302 @@ public interface Request { /** - * @return 返回HttpServletRequest原生对象 + * @return Return HttpServletRequest */ HttpServletRequest raw(); /** - * 初始化路由上的URL参数,如:/user/23 - * @param routePath 路由URL + * URL parameters on the initial route, e.g:/user/23 + * @param routePath Route URL */ void initPathParams(String routePath); /** - * @return 返回客户端请求主机 + * @return Return client request host */ String host(); /** - * @return 返回请求URL + * @return Return request URL */ String url(); /** - * @return 返回请求uri + * @return Return request URI */ String path(); /** - * @return 返回UA + * @return Return UA */ String userAgent(); /** - * @return 返回PathInfo + * @return Return PathInfo */ String pathInfo(); /** - * @return 返回协议 + * @return Return protocol */ String protocol(); /** - * @return 返回servletPath + * @return Return servletPath */ String servletPath(); /** - * @return 返回contextPath + * @return Return contextPath */ String contextPath(); /** - * @return 返回上下文对象 + * @return Return ServletContext */ ServletContext context(); /** - * @return 路径上的参数Map + * @return Return parameters on the path Map */ Map pathParams(); /** - * 获取一个URL上的参数 - * @param name 参数名 - * @return 返回参数值 + * Get a URL parameter + * @param name Parameter name + * @return Return parameter value */ String param(String name); /** - * 获取一个URL上的参数,如果为NULL则返回defaultValue - * @param name 参数名 - * @param defaultValue 默认值 - * @return 返回参数值 + * Get a URL parameter, and returns defaultValue if it is NULL + * @param name Parameter name + * @param defaultValue Default Value + * @return Return parameter value */ String param(String name, String defaultValue); /** - * 返回一个Int类型的URL参数 - * @param name 参数名 - * @return 返回Int参数值 + * Return a URL parameter for a Int type + * @param name Parameter name + * @return Return Int parameter value */ Integer paramAsInt(String name); /** - * 返回一个Long类型的URL参数 - * @param name 参数名 - * @return 返回Long参数值 + * Return a URL parameter for a Long type + * @param name Parameter name + * @return Return Long parameter value */ Long paramAsLong(String name); /** - * 返回一个Boolean类型的URL参数 - * @param name 参数名 - * @return 返回Boolean参数值 + * Return a URL parameter for a Boolean type + * @param name Parameter name + * @return Return Boolean parameter value */ Boolean paramAsBool(String name); /** - * @return 返回请求字符串 + * @return Return query string */ String queryString(); /** - * @return 返回请求参数Map + * @return Return request query Map */ Map querys(); /** - * 获取一个请求参数 - * @param name 参数名 - * @return 返回请求参数值 + * Get a request parameter + * + * @param name Parameter name + * @return Return request parameter value */ String query(String name); /** - * 获取一个请求参数,如果为NULL则返回defaultValue - * @param name 参数名 - * @param defaultValue 默认返回值 - * @return 返回请求参数值 + * Get a request parameter, if NULL is returned to defaultValue + * + * @param name Parameter name + * @param defaultValue Default value + * @return Return request parameter values */ String query(String name, String defaultValue); /** - * 返回一个Int类型的请求参数 - * @param name 参数名 - * @return 返回Int参数值 + * Returns a request parameter for a Int type + * + * @param name Parameter name + * @return Return Int parameter values */ Integer queryAsInt(String name); /** - * 返回一个Long类型的请求参数 - * @param name 参数名 - * @return 返回Long参数值 + * Returns a request parameter for a Long type + * + * @param name Parameter name + * @return Return Long parameter values */ Long queryAsLong(String name); /** - * 返回一个Boolean类型的请求参数 - * @param name 参数名 - * @return 返回Boolean参数值 + * Returns a request parameter for a Boolean type + * + * @param name Parameter name + * @return Return Boolean parameter values */ Boolean queryAsBool(String name); /** - * 返回一个Float类型的请求参数 - * @param name 参数名 - * @return 返回Float参数值 + * Returns a request parameter for a Float type + * + * @param name Parameter name + * @return Return Float parameter values */ Float queryAsFloat(String name); /** - * 返回一个Double类型的请求参数 - * @param name 参数名 - * @return 返回Double参数值 + * Returns a request parameter for a Double type + * + * @param name Parameter name + * @return Return Double parameter values */ Double queryAsDouble(String name); /** - * @return 返回请求方法 + * @return Return request method */ String method(); /** - * @return 返回枚举类型的HttpMethod + * @return Return HttpMethod */ HttpMethod httpMethod(); /** - * @return 返回服务器远程地址 + * @return Return server remote address */ String address(); /** - * @return 返回当前会话 + * @return Return current session */ Session session(); /** - * 返回当前或创建一个会话 - * @param create 是否创建会话 - * @return 返回会话对象 + * Return to the current or create a session + * @param create create session + * @return Return session */ Session session(boolean create); /** - * @return 返回contentType + * @return Return contentType */ String contentType(); /** - * @return 返回服务器端口 + * @return Return Server Port */ int port(); /** - * @return 返回是否使用SSL连接 + * @return Return whether to use the SSL connection */ boolean isSecure(); /** - * @return 放回当前请求是否是AJAX请求 + * @return Return current request is a AJAX request */ boolean isAjax(); /** - * @return 返回Cookie Map + * @return Return Cookie Map */ Map cookies(); /** - * 获取String类型Cookie + * Get String Cookie Value + * * @param name cookie name - * @return 返回cookie值 + * @return Return Cookie Value */ String cookie(String name); /** - * 获取Cookie + * Get Cookie + * * @param name cookie name - * @return 返回cookie值 + * @return Return Cookie */ Cookie cookieRaw(String name); /** - * @return 返回头信息Map + * @return Return header information Map */ Map headers(); /** - * 获取头信息 - * @param name 参数名 - * @return 返回头信息 + * Get header information + * + * @param name Parameter name + * @return Return header information */ String header(String name); /** - * 设置请求编码 - * @param encoding 编码字符串 + * Setting request encoding + * + * @param encoding coded string */ void encoding(String encoding); /** - * 设置一个RequestAttribute - * @param name 参数名 - * @param value 参数值 + * Setting Request Attribute + * + * @param name Parameter name + * @param value Parameter Value */ void attribute(String name, Object value); /** - * 获取一个RequestAttribute - * @param name 参数名 - * @return 返回参数值 + * Get a Request Attribute + * @param name Parameter name + * @return Return parameter value */ T attribute(String name); /** - * @return 返回Request中所有Attribute + * @return Return all Attribute in Request */ Set attributes(); /** - * @return 返回请求中文件列表 + * @return Return the requested file list */ FileItem[] files(); /** - * @return 返回请求体 + * @return Return request body */ BodyParser body(); /** - * 设置路由,执行请求用 - * @param route 路由对象 + * Setting route, execute request for use + * + * @param route route object */ void setRoute(Route route); /** - * @return 返回当前请求的Route + * @return Return Route of the current request */ Route route(); /** - * 请求体接口 + * Request body interface * @author biezhi - * */ interface BodyParser { String asString(); diff --git a/blade-core/src/main/java/com/blade/web/http/Response.java b/blade-core/src/main/java/com/blade/web/http/Response.java index 0bc35e7bc..46140ccb2 100644 --- a/blade-core/src/main/java/com/blade/web/http/Response.java +++ b/blade-core/src/main/java/com/blade/web/http/Response.java @@ -17,7 +17,6 @@ import java.io.IOException; import java.io.OutputStream; -import java.util.Map; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; @@ -25,74 +24,218 @@ import com.blade.render.ModelAndView; /** - * - *

- * HTTP响应对象 - *

+ * HTTP Response * * @author biezhi * @since 1.0 */ public interface Response { + /** + * @return Return HttpServletResponse + */ HttpServletResponse raw(); + /** + * @return Return HTTP Status + */ int status(); + /** + * Setting Response Status + * + * @param status status code + * @return Return Response + */ Response status(int status); + /** + * @return Setting Response Status is BadRequest and Return Response + */ Response badRequest(); + /** + * @return Setting Response Status is unauthorized and Return Response + */ Response unauthorized(); + /** + * @return Setting Response Status is notFound and Return Response + */ Response notFound(); + /** + * @return Setting Response Status is conflict and Return Response + */ Response conflict(); + /** + * @return Return Response contentType + */ String contentType(); + /** + * Setting Response ContentType + * + * @param contentType content type + * @return Return Response + */ Response contentType(String contentType); - + + /** + * Get header + * + * @param name Header Name + * @return Return Response + */ String header(String name); + /** + * Setting header + * + * @param name Header Name + * @param value Header Value + * @return Return Response + */ Response header(String name, String value); + /** + * Setting Cookie + * + * @param cookie Cookie Object + * @return Return Response + */ Response cookie(Cookie cookie); + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @return Return Response + */ Response cookie(String name, String value); + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @return Return Response + */ Response cookie(String name, String value, int maxAge); + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @param secured Is SSL + * @return Return Response + */ Response cookie(String name, String value, int maxAge, boolean secured); + /** + * Setting Cookie + * + * @param path Cookie Domain Path + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @param secured Is SSL + * @return Return Response + */ Response cookie(String path, String name, String value, int maxAge, boolean secured); + /** + * Remove Cookie + * + * @param cookie Cookie Object + * @return Return Response + */ Response removeCookie(Cookie cookie); + /** + * Rmove Cookie By Name + * + * @param name Cookie Name + * @return Return Response + */ Response removeCookie(String name); - Map attributes(); - - Response attribute(String name, Object object); - + /** + * Render by text + * + * @param output text content + * @return Return Response + */ Response text(String output); + /** + * Render by html + * + * @param output html content + * @return Return Response + */ Response html(String output); + /** + * Render by json + * + * @param output json content + * @return Return Response + */ Response json(String output); + /** + * Render by xml + * + * @param output xml content + * @return Return Response + */ Response xml(String output); + /** + * @return Return OutputStream + * @throws IOException IOException + */ OutputStream outputStream() throws IOException; + /** + * Render view + * + * @param view view page + * @return Return Response + */ Response render(String view) ; + /** + * Render view And Setting Data + * + * @param modelAndView ModelAndView object + * @return Return Response + */ Response render(ModelAndView modelAndView) ; + /** + * Redirect to Path + * + * @param path location path + */ void redirect(String path); + /** + * Go to Path, Under contextpath + * + * @param path redirect location + */ void go(String path); + /** + * @return Return Response is Write + */ boolean isWritten(); } diff --git a/blade-core/src/main/java/com/blade/web/http/package-info.java b/blade-core/src/main/java/com/blade/web/http/package-info.java index 815e36c39..2e04b8f99 100644 --- a/blade-core/src/main/java/com/blade/web/http/package-info.java +++ b/blade-core/src/main/java/com/blade/web/http/package-info.java @@ -1,4 +1,4 @@ /** - * Request、Response接口 + * Request And Response */ package com.blade.web.http; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index e486fb2c4..a1bf290e2 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -51,10 +51,7 @@ import blade.kit.text.HTMLFilter; /** - * - *

* ServletRequest - *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index bfade886a..0ceb77b6f 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -18,13 +18,13 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; -import java.util.HashMap; -import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; +import blade.kit.Assert; + import com.blade.Blade; import com.blade.context.BladeWebContext; import com.blade.render.ModelAndView; @@ -35,13 +35,8 @@ import com.blade.web.http.Request; import com.blade.web.http.Response; -import blade.kit.Assert; - /** - * - *

* ServletResponse - *

* * @author biezhi * @since 1.0 @@ -50,8 +45,6 @@ public class ServletResponse implements Response { private HttpServletResponse response; - private Map attributes = new HashMap(); - private boolean written = false; private Render render; @@ -183,16 +176,6 @@ public Response removeCookie(String name) { return this; } - @Override - public Map attributes() { - return attributes; - } - - @Override - public Response attribute(String name, Object object) { - attributes.put(name, object); - return this; - } @Override public Response text(String text) { diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java b/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java index 1ecb62536..aa51f7591 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java @@ -22,10 +22,7 @@ import javax.servlet.http.HttpSession; /** - * - *

- * HttpSession包装 - *

+ * HttpSession Wrapper * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java b/blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java index 4103de3c5..6c29f9ebd 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java @@ -1,4 +1,4 @@ /** - * Servlet封装 + * Servlet Wrapper */ package com.blade.web.http.wrapper; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/multipart/FileItem.java b/blade-core/src/main/java/com/blade/web/multipart/FileItem.java index 804c923a0..3b82b8fc7 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/FileItem.java +++ b/blade-core/src/main/java/com/blade/web/multipart/FileItem.java @@ -20,11 +20,8 @@ import java.util.Map; /** + * HTTP multipart/form-data Request * - *

- * HTTP multipart/form-data 请求 - *

- * * @author biezhi * @since 1.0 */ diff --git a/blade-core/src/main/java/com/blade/web/multipart/Multipart.java b/blade-core/src/main/java/com/blade/web/multipart/Multipart.java index 713155867..f6d56cd98 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/Multipart.java +++ b/blade-core/src/main/java/com/blade/web/multipart/Multipart.java @@ -29,10 +29,7 @@ import blade.kit.IOKit; /** - * - *

- * Multipart对象 - *

+ * Multipart * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java b/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java index 070d76809..9fdc1ebc6 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java +++ b/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java @@ -17,9 +17,7 @@ /** * - *

- * Multipart异常类 - *

+ * MultipartException * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java b/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java index feef0012c..f564ccb41 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java +++ b/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java @@ -16,10 +16,7 @@ package com.blade.web.multipart; /** - * - *

* MultipartHandler - *

* * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/web/multipart/package-info.java b/blade-core/src/main/java/com/blade/web/multipart/package-info.java index 7b3ab0ee0..c60ec9c24 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/package-info.java +++ b/blade-core/src/main/java/com/blade/web/multipart/package-info.java @@ -1,4 +1,4 @@ /** - * Multipart处理 + * Servlet Multipart */ package com.blade.web.multipart; \ No newline at end of file From 78be8331380e7e877ed5d654c6b81b8686168a48 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 16:33:07 +0800 Subject: [PATCH 335/545] modify english comments --- blade-core/src/main/java/com/blade/web/package-info.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 blade-core/src/main/java/com/blade/web/package-info.java diff --git a/blade-core/src/main/java/com/blade/web/package-info.java b/blade-core/src/main/java/com/blade/web/package-info.java new file mode 100644 index 000000000..e3539aed1 --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade Web Core + */ +package com.blade.web; \ No newline at end of file From affba39721923c3e2b313e9070de54cd6150f3f3 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 17:57:53 +0800 Subject: [PATCH 336/545] fix route not found --- blade-core/src/main/java/com/blade/Blade.java | 23 ++++++++++++------- .../java/com/blade/route/RouteMatcher.java | 1 + .../java/com/blade/web/AppAsyncListener.java | 3 +-- .../java/com/blade/web/DispatcherServlet.java | 2 +- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index e7712c378..47138b09c 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -67,27 +67,27 @@ public class Blade { /** * Global configuration Object */ - private Config config = new Config(); + private Config config = null; /** * IOC Container, save javabean */ - private Container container = new SampleContainer(); + private Container container = null; /** * ioc application object */ - private IocApplication iocApplication = new IocApplication(container); + private IocApplication iocApplication = null; /** * default render is jspRender */ - private Render render = new JspRender(); + private Render render = null; /** * manage route */ - private Routers routers = new Routers(container); + private Routers routers = null; /** * jetty start port @@ -100,16 +100,20 @@ public class Blade { private Server bladeServer; private Blade() { + this.config = new Config(); + this.container = new SampleContainer(); + this.iocApplication = new IocApplication(container); + this.routers = new Routers(container); } - private static class BladeHolder { - private static Blade ME = new Blade(); + public static final class BladeHolder { + private static final Blade ME = new Blade(); } /** * @return Single case method returns Blade object */ - public static Blade me(){ + public static final Blade me(){ return BladeHolder.ME; } @@ -757,6 +761,9 @@ public Bootstrap bootstrap(){ * @return Return current render engine */ public Render render() { + if(null == this.render){ + this.render = new JspRender(); + } return render; } diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java index abe271727..3b3888279 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcher.java @@ -81,6 +81,7 @@ public Route getRoute(String httpMethod, String path) { HttpMethod routeMethod = HttpMethod.valueOf(keyArr[1]); if (matchesPath(keyArr[0], cleanPath)) { if (routeMethod == HttpMethod.ALL || HttpMethod.valueOf(httpMethod) == routeMethod) { + route = routes.get(key); matchRoutes.add(route); } } diff --git a/blade-core/src/main/java/com/blade/web/AppAsyncListener.java b/blade-core/src/main/java/com/blade/web/AppAsyncListener.java index 79bfbc69e..559535b29 100644 --- a/blade-core/src/main/java/com/blade/web/AppAsyncListener.java +++ b/blade-core/src/main/java/com/blade/web/AppAsyncListener.java @@ -4,9 +4,8 @@ import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; -import javax.servlet.annotation.WebListener; -@WebListener +//@WebListener public class AppAsyncListener implements AsyncListener { @Override diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 8c3b2b5db..06f9ad305 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -65,7 +65,6 @@ public DispatcherServlet(Bootstrap bootstrap) { @Override public void init(ServletConfig config) throws ServletException { if(!blade.isInit()){ - blade.webRoot(config.getServletContext().getRealPath("/")); this.bootstrap = blade.bootstrap(); if(null == bootstrap){ String bootStrapClassName = config.getInitParameter("bootstrap"); @@ -92,6 +91,7 @@ public void init(Blade blade) { servletContext = config.getServletContext(); + blade.webRoot(servletContext.getRealPath("/")); syncRequestHandler = new SyncRequestHandler(servletContext, blade.routers()); AsynRequestHandler.routeMatcher = new RouteMatcher(blade.routers()); From eb1916323ea0cf9d2e662c0f4b34efdae998a3d0 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 18:24:27 +0800 Subject: [PATCH 337/545] fix jsp render path --- blade-core/src/main/java/com/blade/Blade.java | 6 ++---- blade-core/src/main/java/com/blade/render/JspRender.java | 6 +----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 47138b09c..791107db0 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -104,6 +104,7 @@ private Blade() { this.container = new SampleContainer(); this.iocApplication = new IocApplication(container); this.routers = new Routers(container); + this.render = new JspRender(); } public static final class BladeHolder { @@ -761,10 +762,7 @@ public Bootstrap bootstrap(){ * @return Return current render engine */ public Render render() { - if(null == this.render){ - this.render = new JspRender(); - } - return render; + return this.render; } /** diff --git a/blade-core/src/main/java/com/blade/render/JspRender.java b/blade-core/src/main/java/com/blade/render/JspRender.java index c64d9114c..76a80c843 100644 --- a/blade-core/src/main/java/com/blade/render/JspRender.java +++ b/blade-core/src/main/java/com/blade/render/JspRender.java @@ -26,7 +26,6 @@ import blade.kit.log.Logger; -import com.blade.Blade; import com.blade.context.BladeWebContext; /** @@ -39,10 +38,7 @@ public final class JspRender implements Render { private static final Logger LOGGER = Logger.getLogger(JspRender.class); - private String webRoot; - public JspRender() { - webRoot = Blade.me().webRoot(); } @Override @@ -52,7 +48,7 @@ public void render(ModelAndView modelAndView, Writer writer) { try { Map model = modelAndView.getModel(); - String viewPath = webRoot + modelAndView.getView(); + String viewPath = modelAndView.getView(); if (null != model && !model.isEmpty()) { Set keys = model.keySet(); From 2ed6801c4c52e0ff474eb27ebaccd64ef20e11bc Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 18:28:37 +0800 Subject: [PATCH 338/545] update blade to 1.5.0 --- LAST_VERSION.md | 4 ++-- README.md | 2 +- README_CN.md | 2 +- blade-core/src/main/java/com/blade/Const.java | 2 +- pom.xml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 19c5ba0c7..1e12acef1 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -24,7 +24,7 @@     com.bladejava     blade-kit -    1.2.8-alpha +    1.2.8-beta ``` @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.5.0-beta +    1.5.0 ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/README.md b/README.md index e69b2438a..d9af37e0c 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ To get started, first [include the Blade library](http://bladejava.com/docs/intr com.bladejava blade-core - last_version + 1.5.0 com.bladejava diff --git a/README_CN.md b/README_CN.md index 851d966f0..b250aa25a 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,7 +38,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 最终版本 + 1.5.0 com.bladejava diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 8595b46e0..5a84a5df5 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * Current version */ - String BLADE_VERSION = "1.5.0-beta"; + String BLADE_VERSION = "1.5.0"; /** * Server 500 error HTML diff --git a/pom.xml b/pom.xml index cd4d9b7ca..5b268064b 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.5.0-beta + 1.5.0 4.12 From 3bdcd4fb798fb8accce1251517b71c0a6678fc42 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 21 Dec 2015 19:00:33 +0800 Subject: [PATCH 339/545] add gitter --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d9af37e0c..3e17b56b5 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) +[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + [中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) ## What Is Blade? @@ -204,7 +206,6 @@ You may refer to these examples for additional guidance: - Blog:[https://biezhi.me](https://biezhi.me) - Mail: biezhi.me@gmail.com -- QQ Group: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) ## licenses From e087ceb35242b3aea9bc55c87b512973843262bd Mon Sep 17 00:00:00 2001 From: sumory Date: Tue, 22 Dec 2015 11:36:33 +0800 Subject: [PATCH 340/545] ignore all classpath/target/.settings etc. --- .gitignore | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 1920f74af..0ea2344df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ -/target/ -/.settings/ -/.project \ No newline at end of file +bin +target +.settings +.project +.classpath From 2c160e57cba01dc62a6bdd5864fc6ccfb33ffacd Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 22 Dec 2015 16:50:29 +0800 Subject: [PATCH 341/545] update readme --- README.md | 4 ++-- README_CN.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3e17b56b5..91c62999c 100644 --- a/README.md +++ b/README.md @@ -185,10 +185,10 @@ public Long getUserCount(String email){ You may refer to these examples for additional guidance: -+ [Hello](https://github.com/bladejava/hello) ++ [Hello](https://github.com/blade-samples/hello) + [Api Doc](http://bladejava.com/apidocs) + [User Guide](http://bladejava.com/docs) -+ [Examples](https://github.com/bladejava) ++ [Examples](https://github.com/blade-samples) + [Version](LAST_VERSION.md) ## Plan diff --git a/README_CN.md b/README_CN.md index b250aa25a..9dd8fcea7 100644 --- a/README_CN.md +++ b/README_CN.md @@ -180,10 +180,10 @@ public Long getUserCount(String email){ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: -+ [hello工程](https://github.com/bladejava/hello) ++ [hello工程](https://github.com/blade-samples/hello) + [API文档](http://bladejava.com/apidocs) + [使用指南](http://bladejava.com/docs) -+ [相关案例](https://github.com/bladejava) ++ [相关案例](https://github.com/blade-samples) + [版本查询](LAST_VERSION.md) ### 计划 From 9665937af3cfcd47cedd61fa3a6d24aa82aba7cd Mon Sep 17 00:00:00 2001 From: shellac Date: Tue, 22 Dec 2015 11:52:58 +0000 Subject: [PATCH 342/545] Minor correction to example: query -> queryAsInt --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 91c62999c..de4bc0387 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ public static void main(String[] args) { public static void main(String[] args) { Blade blade = Blade.me(); blade.get("/user", (request, response) -> { - Integer uid = request.query("uid"); + Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); }); blade.listen(9001).start(); From 10f38b1ee50938c6b4cf88431dd4b7376b3087c1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 22 Dec 2015 20:45:52 +0800 Subject: [PATCH 343/545] Minor correction to example: query -> queryAsInt --- README_CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_CN.md b/README_CN.md index 9dd8fcea7..3c512d987 100644 --- a/README_CN.md +++ b/README_CN.md @@ -101,7 +101,7 @@ public static void main(String[] args) { public static void main(String[] args) { Blade blade = Blade.me(); blade.get("/user", (request, response) -> { - Integer uid = request.query("uid"); + Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); }); blade.listen(9001).start(); From 48190286be2192a7554c0c671d7471020a1dff71 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 09:43:43 +0800 Subject: [PATCH 344/545] update readme --- README.md | 17 ++++++++--------- README_CN.md | 17 ++++++++--------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index de4bc0387..4e7ab2c34 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ create `Main` method like this: public class App { public static void main(String[] args) { - Blade blade = Blade.me(); + Blade blade = me(); blade.get("/", (request, response) -> { response.html("

Hello blade!

"); }); @@ -70,7 +70,7 @@ Run it and point your browser to http://localhost:9001. There you go, you've jus ```java public static void main(String[] args) { - Blade blade = Blade.me(); + Blade blade = me(); blade.get("/user/21", getxxx); blade.post("/save", postxxx); blade.delete("/del/21", deletexxx); @@ -83,7 +83,7 @@ public static void main(String[] args) { ```java public static void main(String[] args) { - Blade blade = Blade.me(); + Blade blade = me(); blade.get("/user/:uid", (request, response) -> { Integer uid = request.paramAsInt("uid"); response.text("uid : " + uid); @@ -104,7 +104,7 @@ public static void main(String[] args) { ```java public static void main(String[] args) { - Blade blade = Blade.me(); + Blade blade = me(); blade.get("/user", (request, response) -> { Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); @@ -149,7 +149,7 @@ POST /upload_img UploadRoute.upload_img ```java public static void main(String[] args) { - Blade blade = Blade.me(); + Blade blade = me(); blade.before("/.*", (request, response) -> { System.out.println("before..."); }); @@ -193,10 +193,9 @@ You may refer to these examples for additional guidance: ## Plan -- 1. Written in English Docs -- 2. Add the test code -- 3. Optimize the code base -- 4. Optimization of concurrent ability +- 1. Add the test code +- 2. Optimize the code base +- 3. Optimization of concurrent ability ## Update diff --git a/README_CN.md b/README_CN.md index 3c512d987..6c9dbc59f 100644 --- a/README_CN.md +++ b/README_CN.md @@ -51,7 +51,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 ```java public static void main(String[] args) { - Blade blade = Blade.me(); + Blade blade = me(); blade.get("/", (request, response) -> { response.html("

Hello blade!

"); }); @@ -65,7 +65,7 @@ public static void main(String[] args) { ```java public static void main(String[] args) { - Blade blade = Blade.me(); + Blade blade = me(); blade.get("/user/21", getxxx); blade.post("/save", postxxx); blade.delete("/del/21", deletexxx); @@ -78,7 +78,7 @@ public static void main(String[] args) { ```java public static void main(String[] args) { - Blade blade = Blade.me(); + Blade blade = me(); blade.get("/user/:uid", (request, response) -> { Integer uid = request.paramAsInt("uid"); response.text("uid : " + uid); @@ -99,7 +99,7 @@ public static void main(String[] args) { ```java public static void main(String[] args) { - Blade blade = Blade.me(); + Blade blade = me(); blade.get("/user", (request, response) -> { Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); @@ -144,7 +144,7 @@ POST /upload_img UploadRoute.upload_img ```java public static void main(String[] args) { - Blade blade = Blade.me(); + Blade blade = me(); blade.before("/.*", (request, response) -> { System.out.println("before..."); }); @@ -188,10 +188,9 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ### 计划 -- 1. 编写英文文档 -- 2. 添加测试代码 -- 3. 优化基础代码 -- 4. 优化并发能力 +- 1. 添加测试代码 +- 2. 优化基础代码 +- 3. 优化并发能力 ## 更新日志 From e2ef198cd022c850e883967fc0dd6f641006a0d4 Mon Sep 17 00:00:00 2001 From: Uday Kadaboina Date: Tue, 22 Dec 2015 21:50:37 -0500 Subject: [PATCH 345/545] Typos in doc --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4e7ab2c34..192389a2c 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,11 @@ If you like it, please [star and fork it](https://github.com/biezhi/blade). Than * [x] Restful style routing interface * [x] Supports multiple configuration files (currently properties, json and coding) * [x] Embedded jetty server and template engine support -* [x] Supports jdk 1.6 and up +* [x] Supports JDK 1.6 and up ## Overview -* Simplicity: the design is simple, easy to understand and doesn't introduce many layers between you and the standard library. It is a goal of the project that users should be able to understand the whole framework in a single day. +* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. * Elegance: `blade` supports the REST style routing interface, has no invasive interceptors and provides the writing of DSL grammar. ## Get Start @@ -49,7 +49,7 @@ To get started, first [include the Blade library](http://bladejava.com/docs/intr
``` -create `Main` method like this: +Create `Main` method like this: ```java public class App { @@ -186,7 +186,7 @@ public Long getUserCount(String email){ You may refer to these examples for additional guidance: + [Hello](https://github.com/blade-samples/hello) -+ [Api Doc](http://bladejava.com/apidocs) ++ [API Doc](http://bladejava.com/apidocs) + [User Guide](http://bladejava.com/docs) + [Examples](https://github.com/blade-samples) + [Version](LAST_VERSION.md) @@ -206,7 +206,7 @@ You may refer to these examples for additional guidance: - Blog:[https://biezhi.me](https://biezhi.me) - Mail: biezhi.me@gmail.com -## licenses +## Licenses ``` Copyright 2015 biezhi From b2cc42e65a2157911d5171eaf616ef5dc745648c Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 13:15:05 +0800 Subject: [PATCH 346/545] update readme --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 4e7ab2c34..8cb8e3616 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ [![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) [![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) - [![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) From d897e9d8c8213c3accdedf87858138b421d02542 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 13:34:46 +0800 Subject: [PATCH 347/545] fix setWebRoot opportunity --- .../src/main/java/com/blade/web/DispatcherServlet.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 06f9ad305..e1d21fe6a 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -64,7 +64,9 @@ public DispatcherServlet(Bootstrap bootstrap) { @Override public void init(ServletConfig config) throws ServletException { + servletContext = config.getServletContext(); if(!blade.isInit()){ + blade.webRoot(servletContext.getRealPath("/")); this.bootstrap = blade.bootstrap(); if(null == bootstrap){ String bootStrapClassName = config.getInitParameter("bootstrap"); @@ -89,9 +91,6 @@ public void init(Blade blade) { blade.bootstrap().contextInitialized(blade); - servletContext = config.getServletContext(); - - blade.webRoot(servletContext.getRealPath("/")); syncRequestHandler = new SyncRequestHandler(servletContext, blade.routers()); AsynRequestHandler.routeMatcher = new RouteMatcher(blade.routers()); From 8c55d53b5b890abfd0890cb5badea954b40c8b15 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 14:14:44 +0800 Subject: [PATCH 348/545] fix setting cookie recursive --- .../java/com/blade/web/http/wrapper/ServletResponse.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index 0ceb77b6f..d084fb8b2 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -129,18 +129,20 @@ public Response cookie(String name, String value) { @Override public Response cookie(String name, String value, int maxAge) { - return cookie(name, value, maxAge); + return cookie(name, value, maxAge, false); } @Override public Response cookie(String name, String value, int maxAge, boolean secured) { - return cookie(name, value, maxAge, secured); + return cookie(null, name, value, maxAge, secured); } @Override public Response cookie(String path, String name, String value, int maxAge, boolean secured) { Cookie cookie = new Cookie(name, value); - cookie.setPath(path); + if(null != path){ + cookie.setPath(path); + } cookie.setMaxAge(maxAge); cookie.setSecure(secured); response.addCookie(cookie); From 84efa7a4f704a0f646187ac69f5dbe07bb73109f Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 15:40:46 +0800 Subject: [PATCH 349/545] controller injection object is null --- .../blade/loader/AbstractFileRouteLoader.java | 446 +++++++++--------- .../java/com/blade/route/RouteBuilder.java | 4 +- .../main/java/com/blade/route/Routers.java | 11 +- .../com/blade/web/AsynRequestHandler.java | 5 + .../com/blade/web/SyncRequestHandler.java | 7 +- 5 files changed, 241 insertions(+), 232 deletions(-) diff --git a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java index 01b60e3b2..c8aa507d4 100644 --- a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java @@ -1,223 +1,223 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.loader; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.Method; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -import com.blade.route.Route; -import com.blade.route.RouteException; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -import blade.kit.IOKit; - -/** - * Abstract loader implementation - * - * @author biezhi - * @since 1.0 - */ -public abstract class AbstractFileRouteLoader implements RouteLoader { - - private ControllerLoader controllerLoader = new ClassPathControllerLoader(); - - protected abstract InputStream getInputStream() throws Exception; - - @Override - public List load() throws ParseException, RouteException { - InputStream inputStream = null; - try { - inputStream = getInputStream(); - } catch (Exception e) { - throw new RouteException("Loading the route config file error: " + e.getMessage(), e); - } - try { - return load(inputStream); - } catch (IOException e) { - throw new RouteException("Loading the route config file error: " + e.getMessage(), e); - } - } - - /** - * Load Route - * - * @param inputStream route inputstream - * @return return route list - * @throws ParseException parse exception - * @throws IOException io exception - */ - private List load(InputStream inputStream) throws ParseException, IOException { - int line = 0; - List routes = new ArrayList(); - BufferedReader in = null; - try { - in = new BufferedReader(new InputStreamReader(inputStream)); - String input; - while ( (input = in.readLine()) != null ) { - line++; - - input = input.trim(); - - if (!input.equals("") && !input.startsWith(".")) { - Route route = parse(input, line); - routes.add(route); - } - } - } finally { - IOKit.closeQuietly(in); - } - return routes; - } - - private Route parse(String input, int line) throws ParseException { - StringTokenizer st = new StringTokenizer(input, " \t"); - if (st.countTokens() != 3) { - throw new ParseException("Unrecognized format", line); - } - - // Verify HTTP request - String httpMethod = validateHttpMethod( st.nextToken().trim(), line ); - - String path = validatePath( st.nextToken().trim(), line ); - String controllerAndMethod = validateControllerAndMethod( st.nextToken().trim(), line ); - - int hashPos = controllerAndMethod.indexOf("."); - String controllerName = controllerAndMethod.substring(0, hashPos); - - // Acquisition controller method - String controllerMethod = controllerAndMethod.substring(hashPos + 1); - - return buildRoute(httpMethod, path, controllerName, controllerMethod); - } - - private String validateHttpMethod(String httpMethod, int line) throws ParseException { - if (!httpMethod.equalsIgnoreCase("GET") && - !httpMethod.equalsIgnoreCase("POST") && - !httpMethod.equalsIgnoreCase("PUT") && - !httpMethod.equalsIgnoreCase("DELETE")) { - throw new ParseException("Unrecognized HTTP method: " + httpMethod, line); - } - return httpMethod; - } - - private String validatePath(String path, int line) throws ParseException { - if (!path.startsWith("/")) { - throw new ParseException("Path must start with '/'", line); - } - - boolean openedKey = false; - for (int i=0; i < path.length(); i++) { - - boolean validChar = isValidCharForPath(path.charAt(i), openedKey); - if (!validChar) { - throw new ParseException(path, i); - } - - if (path.charAt(i) == '{') { - openedKey = true; - } - - if (path.charAt(i) == '}') { - openedKey = false; - } - } - return path; - } - - private boolean isValidCharForPath(char c, boolean openedKey) { - char[] invalidChars = { '?', '.', ' ' }; - for (char invalidChar : invalidChars) { - if (c == invalidChar) { - return false; - } - } - - if (openedKey) { - char[] moreInvalidChars = { '/', '{' }; - for (char invalidChar : moreInvalidChars) { - if (c == invalidChar) { - return false; - } - } - } - - return true; - } - - /** - * Verification controller method - * - * @param beanAndMethod controller and method, using. - * @param line line number - * @return return a string that is verified after the verification. - * @throws ParseException - */ - private String validateControllerAndMethod(String beanAndMethod, int line) throws ParseException { - int hashPos = beanAndMethod.indexOf("."); - if (hashPos == -1) { - throw new ParseException("Unrecognized format for '" + beanAndMethod + "'", line); - } - - return beanAndMethod; - } - - /** - * Construct a routing object - * - * @param httpMethod request httpMethod - * @param path route path - * @param controllerName controller name - * @param methodName method name - * @return return route object - * @throws RouteException - */ - private Route buildRoute(String httpMethod, String path, String controllerName, String methodName) throws RouteException { - Object controller = controllerLoader.load(controllerName); - Method method = getMethod(controller, methodName); - - return new Route(HttpMethod.valueOf(httpMethod.toUpperCase()), path, controller, method); - } - - private Method getMethod(Object controller, String methodName) throws RouteException { - try { - return controller.getClass().getMethod(methodName, Request.class, Response.class); - } catch (Exception e) { - throw new RouteException(e); - } - } - - public void setBasePackage(String basePackage) { - this.controllerLoader = new ClassPathControllerLoader(basePackage); - } - - public ControllerLoader getControllerLoader() { - return controllerLoader; - } - - public void setControllerLoader(ControllerLoader controllerLoader) { - this.controllerLoader = controllerLoader; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.loader; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Method; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import com.blade.route.Route; +import com.blade.route.RouteException; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +import blade.kit.IOKit; + +/** + * Abstract loader implementation + * + * @author biezhi + * @since 1.0 + */ +public abstract class AbstractFileRouteLoader implements RouteLoader { + + private ControllerLoader controllerLoader = new ClassPathControllerLoader(); + + protected abstract InputStream getInputStream() throws Exception; + + @Override + public List load() throws ParseException, RouteException { + InputStream inputStream = null; + try { + inputStream = getInputStream(); + } catch (Exception e) { + throw new RouteException("Loading the route config file error: " + e.getMessage(), e); + } + try { + return load(inputStream); + } catch (IOException e) { + throw new RouteException("Loading the route config file error: " + e.getMessage(), e); + } + } + + /** + * Load Route + * + * @param inputStream route inputstream + * @return return route list + * @throws ParseException parse exception + * @throws IOException io exception + */ + private List load(InputStream inputStream) throws ParseException, IOException { + int line = 0; + List routes = new ArrayList(); + BufferedReader in = null; + try { + in = new BufferedReader(new InputStreamReader(inputStream)); + String input; + while ( (input = in.readLine()) != null ) { + line++; + + input = input.trim(); + + if (!input.equals("") && !input.startsWith(".")) { + Route route = parse(input, line); + routes.add(route); + } + } + } finally { + IOKit.closeQuietly(in); + } + return routes; + } + + private Route parse(String input, int line) throws ParseException { + StringTokenizer st = new StringTokenizer(input, " \t"); + if (st.countTokens() != 3) { + throw new ParseException("Unrecognized format", line); + } + + // Verify HTTP request + String httpMethod = validateHttpMethod( st.nextToken().trim(), line ); + + String path = validatePath( st.nextToken().trim(), line ); + String controllerAndMethod = validateControllerAndMethod( st.nextToken().trim(), line ); + + int hashPos = controllerAndMethod.indexOf("."); + String controllerName = controllerAndMethod.substring(0, hashPos); + + // Acquisition controller method + String controllerMethod = controllerAndMethod.substring(hashPos + 1); + + return buildRoute(httpMethod, path, controllerName, controllerMethod); + } + + private String validateHttpMethod(String httpMethod, int line) throws ParseException { + if (!httpMethod.equalsIgnoreCase("GET") && + !httpMethod.equalsIgnoreCase("POST") && + !httpMethod.equalsIgnoreCase("PUT") && + !httpMethod.equalsIgnoreCase("DELETE")) { + throw new ParseException("Unrecognized HTTP method: " + httpMethod, line); + } + return httpMethod; + } + + private String validatePath(String path, int line) throws ParseException { + if (!path.startsWith("/")) { + throw new ParseException("Path must start with '/'", line); + } + + boolean openedKey = false; + for (int i=0; i < path.length(); i++) { + + boolean validChar = isValidCharForPath(path.charAt(i), openedKey); + if (!validChar) { + throw new ParseException(path, i); + } + + if (path.charAt(i) == '{') { + openedKey = true; + } + + if (path.charAt(i) == '}') { + openedKey = false; + } + } + return path; + } + + private boolean isValidCharForPath(char c, boolean openedKey) { + char[] invalidChars = { '?', '.', ' ' }; + for (char invalidChar : invalidChars) { + if (c == invalidChar) { + return false; + } + } + + if (openedKey) { + char[] moreInvalidChars = { '/', '{' }; + for (char invalidChar : moreInvalidChars) { + if (c == invalidChar) { + return false; + } + } + } + + return true; + } + + /** + * Verification controller method + * + * @param beanAndMethod controller and method, using. + * @param line line number + * @return return a string that is verified after the verification. + * @throws ParseException + */ + private String validateControllerAndMethod(String beanAndMethod, int line) throws ParseException { + int hashPos = beanAndMethod.indexOf("."); + if (hashPos == -1) { + throw new ParseException("Unrecognized format for '" + beanAndMethod + "'", line); + } + + return beanAndMethod; + } + + /** + * Construct a routing object + * + * @param httpMethod request httpMethod + * @param path route path + * @param controllerName controller name + * @param methodName method name + * @return return route object + * @throws RouteException + */ + private Route buildRoute(String httpMethod, String path, String controllerName, String methodName) throws RouteException { + Object controller = controllerLoader.load(controllerName); + Method method = getMethod(controller, methodName); + + return new Route(HttpMethod.valueOf(httpMethod.toUpperCase()), path, null, method); + } + + private Method getMethod(Object controller, String methodName) throws RouteException { + try { + return controller.getClass().getMethod(methodName, Request.class, Response.class); + } catch (Exception e) { + throw new RouteException(e); + } + } + + public void setBasePackage(String basePackage) { + this.controllerLoader = new ClassPathControllerLoader(basePackage); + } + + public ControllerLoader getControllerLoader() { + return controllerLoader; + } + + public void setControllerLoader(ControllerLoader controllerLoader) { + this.controllerLoader = controllerLoader; + } + +} diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index 727a0fa32..bdbc1b775 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -283,7 +283,7 @@ private String getRoutePath(String value, String nameSpace, String suffix){ * @param method route httpmethod */ private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ - this.routers.route(path, clazz, execMethod, method); + routers.buildRoute(path, clazz, execMethod, method); } /** @@ -295,7 +295,7 @@ private void buildRoute(Class clazz, Method execMethod, String path, HttpMeth * @param method route httpmethod */ private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ - this.routers.route(path, clazz, execMethod, method); + routers.buildRoute(path, clazz, execMethod, method); } } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index c9b05c199..d47acfba7 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -91,16 +91,15 @@ public void addRoutes(List routes) { } } - public void addRoute(HttpMethod httpMethod, String path, Object controller, String methodName) throws NoSuchMethodException { - Method method = controller.getClass().getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, controller, method); + public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, String methodName) throws NoSuchMethodException { + Method method = handler.getClass().getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, handler, method); } public void addRoute(HttpMethod httpMethod, String path, Object controller, Method method) { Assert.notNull(httpMethod); Assert.notBlank(path); - Assert.notNull(controller); Assert.notNull(method); String key = path + "#" + httpMethod.toString(); @@ -188,14 +187,14 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt } } - public void route(String path, Class clazz, Method method, HttpMethod httpMethod) { + public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { try { Object controller = container.getBean(clazz, Scope.SINGLE); if(null == controller){ controller = Aop.create(clazz); container.registerBean(controller); } - addRoute(httpMethod, path, controller, method); + addRoute(httpMethod, path, null, method); } catch (SecurityException e) { e.printStackTrace(); } diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index b9032a890..3dc137f88 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -181,7 +181,12 @@ private void invokeInterceptor(Request request, Response response, List i * @param route route object */ private void handle(Request request, Response response, Route route){ + Object target = route.getTarget(); + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = Blade.me().container().getBean(clazz, null); + } request.initPathParams(route.getPath()); // Init context diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index c7e939475..3400fffab 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -168,13 +168,18 @@ private void invokeInterceptor(Request request, Response response, List i * @param route route object */ private void handle(Request request, Response response, Route route){ + Object target = route.getTarget(); + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = Blade.me().container().getBean(clazz, null); + } request.initPathParams(route.getPath()); // Init context BladeWebContext.setContext(servletContext, request, response); if(target instanceof RouteHandler){ - RouteHandler routeHandler = (RouteHandler)target; + RouteHandler routeHandler = (RouteHandler) target; routeHandler.handle(request, response); } else { Method actionMethod = route.getAction(); From 38a62a0def7997d9425ef0ba625de46686278eaf Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 15:42:54 +0800 Subject: [PATCH 350/545] update const version to 1.5.1-alpha --- blade-core/src/main/java/com/blade/Const.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 5a84a5df5..303ed34b9 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * Current version */ - String BLADE_VERSION = "1.5.0"; + String BLADE_VERSION = "1.5.1-alpha"; /** * Server 500 error HTML From 96845a4e47802bf015177ca7631be34d8833ac52 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 15:47:08 +0800 Subject: [PATCH 351/545] update blade verion to 1.5.1-alpha --- LAST_VERSION.md | 2 +- README.md | 2 +- README_CN.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 1e12acef1..8843e2960 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.5.0 +    1.5.1-alpha ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/README.md b/README.md index aa949a015..593d3fdc6 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ To get started, first [include the Blade library](http://bladejava.com/docs/intr com.bladejava blade-core - 1.5.0 + 1.5.1-alpha com.bladejava diff --git a/README_CN.md b/README_CN.md index 6c9dbc59f..2b376ae9b 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,7 +38,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.5.0 + 1.5.1-alpha com.bladejava From 70a03af842d2db9fd0b0af03cdfdb2b679492af6 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 15:48:04 +0800 Subject: [PATCH 352/545] update blade verion to 1.5.1-alpha --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5b268064b..67dce0ed8 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.5.0 + 1.5.1-alpha 4.12 From 3ba2f19f4348118738acf6a72fd63652e85a6c2c Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 15:50:25 +0800 Subject: [PATCH 353/545] update log --- UPDATE_LOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 89e1f1f0c..13c246304 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,5 +1,10 @@ # Blade 更新日志 +### v1.5.1 + 1. 修复webRoot是null + 2. 修复模板引擎路径错误 + 3. 修复控制器注入对象失败 + ### v1.5.0 1. 优化路由寻址算法 2. 分离同步和异步请求 From a204dc8abd7d406b33c51c276adda77df811cc86 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 15:55:07 +0800 Subject: [PATCH 354/545] add 17x number segment --- blade-kit/src/main/java/blade/kit/PatternKit.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-kit/src/main/java/blade/kit/PatternKit.java b/blade-kit/src/main/java/blade/kit/PatternKit.java index 16c002391..1f307dbee 100644 --- a/blade-kit/src/main/java/blade/kit/PatternKit.java +++ b/blade-kit/src/main/java/blade/kit/PatternKit.java @@ -64,7 +64,7 @@ public static boolean isImage(String suffix) { * @return 验证成功返回true,验证失败返回false */ public static boolean isMobile(String mobile) { - String regex = "(\\+\\d+)?1[3458]\\d{9}$"; + String regex = "(\\+\\d+)?1[34578]\\d{9}$"; return Pattern.matches(regex,mobile); } From a85afdba806f4d890109751ed26bf025a95b1fa5 Mon Sep 17 00:00:00 2001 From: Jie Shen <1993sj1993@gmail.com> Date: Wed, 23 Dec 2015 15:59:27 +0800 Subject: [PATCH 355/545] Fix typo in README REST needs to be in capitals since it is an abbreviation. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 593d3fdc6..99c6a10aa 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ If you like it, please [star and fork it](https://github.com/biezhi/blade). Than * [x] Lightweight: the code is simple and the structure is clear * [x] Modular (you can choose which components to use) * [x] Supports plug-in extension mechanism -* [x] Restful style routing interface +* [x] RESTful style routing interface * [x] Supports multiple configuration files (currently properties, json and coding) * [x] Embedded jetty server and template engine support * [x] Supports JDK 1.6 and up @@ -26,7 +26,7 @@ If you like it, please [star and fork it](https://github.com/biezhi/blade). Than ## Overview * Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. -* Elegance: `blade` supports the REST style routing interface, has no invasive interceptors and provides the writing of DSL grammar. +* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. ## Get Start From 89144eefe25452136cc00aa673dc4b66ed5b3b4a Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 16:17:20 +0800 Subject: [PATCH 356/545] add contributor and update LICENSE --- LICENSE | 13 +++++++++++++ README.md | 24 +++++++++++------------- README_CN.md | 25 ++++++++++++------------- 3 files changed, 36 insertions(+), 26 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..6f1bd93ee --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright 2015 biezhi + +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. \ No newline at end of file diff --git a/README.md b/README.md index 99c6a10aa..6671f54fb 100644 --- a/README.md +++ b/README.md @@ -204,20 +204,18 @@ You may refer to these examples for additional guidance: - Blog:[https://biezhi.me](https://biezhi.me) - Mail: biezhi.me@gmail.com -## Licenses +## Contributor -``` -Copyright 2015 biezhi +Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! -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 +- [mfarid](https://github.com/mfarid) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) - http://www.apache.org/licenses/LICENSE-2.0 +## Licenses -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. -``` +Please see [Apache License](LICENSE) diff --git a/README_CN.md b/README_CN.md index 2b376ae9b..b8f29c915 100644 --- a/README_CN.md +++ b/README_CN.md @@ -202,20 +202,19 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 - Mail: biezhi.me#gmail.com - Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) -## 开源协议 +## 贡献 -``` -Copyright 2015 biezhi +非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! -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 +- [mfarid](https://github.com/mfarid) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) - http://www.apache.org/licenses/LICENSE-2.0 +## 开源协议 + +请查看 [Apache License](LICENSE) -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. -``` From 6b34c3c1cf723b5686753f6fe327e003aaa6f542 Mon Sep 17 00:00:00 2001 From: Sudar Abisheck Date: Wed, 23 Dec 2015 15:38:51 +0530 Subject: [PATCH 357/545] Gradle dependency addition --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6671f54fb..5aa21a527 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ If you like it, please [star and fork it](https://github.com/biezhi/blade). Than To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : -`Maven` config: +Grab via `Maven`: ```sh @@ -46,6 +46,11 @@ To get started, first [include the Blade library](http://bladejava.com/docs/intr 1.0.1 ``` +or `Gradle`: +``` +compile 'com.bladejava:blade-core:1.5.0' +compile 'com.bladejava:blade-startup:1.0.1' +``` Create `Main` method like this: @@ -62,7 +67,7 @@ public class App { } ``` -Run it and point your browser to http://localhost:9001. There you go, you've just created your first Blade app! +Run it and point your browser to [http://localhost:9001](http://localhost:9001). There you go, you've just created your first Blade app! ## API Example From 6ef13dad35c6a933729e21f98673bcb0df3924da Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Dec 2015 18:27:13 +0800 Subject: [PATCH 358/545] update readme --- README.md | 4 +++- README_CN.md | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5aa21a527..8c3308bbb 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ``` -compile 'com.bladejava:blade-core:1.5.0' +compile 'com.bladejava:blade-core:1.5.1-alpha' compile 'com.bladejava:blade-startup:1.0.1' ``` @@ -214,12 +214,14 @@ You may refer to these examples for additional guidance: Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! - [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) - [shenjie1993](https://github.com/shenjie1993) - [sumory](https://github.com/sumory) - [udaykadaboina](https://github.com/udaykadaboina) - [SyedWasiHaider](https://github.com/SyedWasiHaider) - [Awakens](https://github.com/Awakens) - [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) ## Licenses diff --git a/README_CN.md b/README_CN.md index b8f29c915..bf82a568a 100644 --- a/README_CN.md +++ b/README_CN.md @@ -47,6 +47,13 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 ``` +或者 `Gradle`: + +``` +compile 'com.bladejava:blade-core:1.5.1-alpha' +compile 'com.bladejava:blade-startup:1.0.1' +``` + 编写 `Main`函数: ```java @@ -207,12 +214,14 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! - [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) - [shenjie1993](https://github.com/shenjie1993) - [sumory](https://github.com/sumory) - [udaykadaboina](https://github.com/udaykadaboina) - [SyedWasiHaider](https://github.com/SyedWasiHaider) - [Awakens](https://github.com/Awakens) - [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) ## 开源协议 From 449caf83aa7a7100ac1e4726d83674c9c61914fb Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 24 Dec 2015 13:23:44 +0800 Subject: [PATCH 359/545] update blade-core to 1.5.1-beta --- LAST_VERSION.md | 6 +- README.md | 4 +- README_CN.md | 4 +- UPDATE_LOG.md | 1 + blade-core/pom.xml | 2 +- blade-core/src/main/java/com/blade/Const.java | 2 +- .../main/java/com/blade/web/http/Request.java | 10 +++ .../web/http/wrapper/ServletRequest.java | 51 ++++++++----- blade-kit/pom.xml | 2 +- .../src/main/java/blade/kit/DateKit.java | 37 ++++++++++ .../src/main/java/blade/kit/ObjectKit.java | 73 +++++++++++++++++++ .../src/main/java/blade/kit/ReflectKit.java | 5 +- .../src/main/java/blade/kit/SystemKit.java | 3 +- .../blade/kit/exception/ReflectException.java | 22 ++++++ pom.xml | 2 +- 15 files changed, 189 insertions(+), 35 deletions(-) create mode 100644 blade-kit/src/main/java/blade/kit/ObjectKit.java create mode 100644 blade-kit/src/main/java/blade/kit/exception/ReflectException.java diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 8843e2960..4e29d8d60 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -24,7 +24,7 @@     com.bladejava     blade-kit -    1.2.8-beta +    1.2.8 ``` @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.5.1-alpha +    1.5.1-beta ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) @@ -41,7 +41,7 @@     com.bladejava     blade-sql2o -    1.2.9 +    1.3.0-alpha ``` diff --git a/README.md b/README.md index 8c3308bbb..6cab9f635 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Grab via `Maven`: com.bladejava blade-core - 1.5.1-alpha + 1.5.1-beta com.bladejava @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ``` -compile 'com.bladejava:blade-core:1.5.1-alpha' +compile 'com.bladejava:blade-core:1.5.1-beta' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/README_CN.md b/README_CN.md index bf82a568a..fbbc1a9b9 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,7 +38,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.5.1-alpha + 1.5.1-beta com.bladejava @@ -50,7 +50,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 或者 `Gradle`: ``` -compile 'com.bladejava:blade-core:1.5.1-alpha' +compile 'com.bladejava:blade-core:1.5.1-beta' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 13c246304..7188f1321 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -4,6 +4,7 @@ 1. 修复webRoot是null 2. 修复模板引擎路径错误 3. 修复控制器注入对象失败 + 4. 添加request.model表单数据转JavaBean ### v1.5.0 1. 优化路由寻址算法 diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 745d82919..4b76a3cd4 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -28,7 +28,7 @@ com.bladejava blade-kit - 1.2.8-beta + 1.2.8 com.bladejava diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 303ed34b9..a98bbe16e 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * Current version */ - String BLADE_VERSION = "1.5.1-alpha"; + String BLADE_VERSION = "1.5.1-beta"; /** * Server 500 error HTML diff --git a/blade-core/src/main/java/com/blade/web/http/Request.java b/blade-core/src/main/java/com/blade/web/http/Request.java index c8051dbaf..25948d5dd 100644 --- a/blade-core/src/main/java/com/blade/web/http/Request.java +++ b/blade-core/src/main/java/com/blade/web/http/Request.java @@ -16,6 +16,7 @@ package com.blade.web.http; import java.io.InputStream; +import java.io.Serializable; import java.util.Map; import java.util.Set; @@ -317,6 +318,15 @@ public interface Request { */ BodyParser body(); + /** + * Serialized form data, converted to the javabean + * + * @param slug bean slug, e.g: , the slug is person + * @param clazz bean type + * @return Return converted Bean Object + */ + T model(String slug, Class clazz); + /** * Setting route, execute request for use * diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index a1bf290e2..5b3151e3a 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; @@ -36,6 +37,11 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import blade.kit.IOKit; +import blade.kit.ObjectKit; +import blade.kit.StringKit; +import blade.kit.text.HTMLFilter; + import com.blade.Blade; import com.blade.route.Route; import com.blade.web.http.HttpException; @@ -47,9 +53,6 @@ import com.blade.web.multipart.MultipartException; import com.blade.web.multipart.MultipartHandler; -import blade.kit.IOKit; -import blade.kit.text.HTMLFilter; - /** * ServletRequest * @@ -64,18 +67,22 @@ public class ServletRequest implements Request { private HttpServletRequest request; - protected Map pathParams = new HashMap(); + protected Map pathParams = null; - private Map multipartParams = new HashMap(); + private Map multipartParams = null; - private List files = new ArrayList(); + private List files = null; private Session session = null; - private Blade blade = Blade.me(); + private Blade blade = null; public ServletRequest(HttpServletRequest request) throws MultipartException, IOException { this.request = request; + this.pathParams = new HashMap(); + this.multipartParams = new HashMap(); + this.files = new ArrayList(); + this.blade = Blade.me(); init(); } @@ -495,6 +502,25 @@ public void encoding(String encoding) { } } + @Override + public void setRoute(Route route) { + this.route = route; + initPathParams(route.getPath()); + } + + @Override + public Route route() { + return this.route; + } + + @Override + public T model(String slug, Class clazz) { + if(StringKit.isNotBlank(slug) && null != clazz){ + return ObjectKit.model(slug, clazz, querys()); + } + return null; + } + @Override public FileItem[] files() { FileItem[] fileParts = new FileItem[files.size()]; @@ -547,15 +573,4 @@ public byte[] asByte() { }; } - @Override - public void setRoute(Route route) { - this.route = route; - initPathParams(route.getPath()); - } - - @Override - public Route route() { - return this.route; - } - } diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index ad18ec14e..cb55afd48 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - 1.2.8-beta + 1.2.8 blade-kit https://github.com/biezhi/blade/tree/master/blade-kit diff --git a/blade-kit/src/main/java/blade/kit/DateKit.java b/blade-kit/src/main/java/blade/kit/DateKit.java index 437cb7179..75374b39f 100644 --- a/blade-kit/src/main/java/blade/kit/DateKit.java +++ b/blade-kit/src/main/java/blade/kit/DateKit.java @@ -792,5 +792,42 @@ public static long getSpecifyTimeSec(long time, int range) { public static String formatDateByUnixTime(long unixTime, String dateFormat) { return dateFormat(new Date(unixTime * 1000), dateFormat); } + + private static List dateFormats = new ArrayList(12) { + private static final long serialVersionUID = 2249396579858199535L; + { + add(new SimpleDateFormat("yyyy-MM-dd")); + add(new SimpleDateFormat("yyyy/MM/dd")); + add(new SimpleDateFormat("yyyy.MM.dd")); + add(new SimpleDateFormat("yyyy-MM-dd HH:24:mm:ss")); + add(new SimpleDateFormat("yyyy/MM/dd HH:24:mm:ss")); + add(new SimpleDateFormat("yyyy.MM.dd HH:24:mm:ss")); + add(new SimpleDateFormat("M/dd/yyyy")); + add(new SimpleDateFormat("dd.M.yyyy")); + add(new SimpleDateFormat("M/dd/yyyy hh:mm:ss a")); + add(new SimpleDateFormat("dd.M.yyyy hh:mm:ss a")); + add(new SimpleDateFormat("dd.MMM.yyyy")); + add(new SimpleDateFormat("dd-MMM-yyyy")); + } + }; + + public static Date convertToDate(String input) { + Date date = null; + if(null == input) { + return null; + } + for (SimpleDateFormat format : dateFormats) { + try { + format.setLenient(false); + date = format.parse(input); + } catch (ParseException e) { + //Shhh.. try other formats + } + if (date != null) { + break; + } + } + return date; + } } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/ObjectKit.java b/blade-kit/src/main/java/blade/kit/ObjectKit.java new file mode 100644 index 000000000..851325378 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/ObjectKit.java @@ -0,0 +1,73 @@ +package blade.kit; + +import java.lang.reflect.Field; +import java.util.Date; +import java.util.Map; + +import blade.kit.exception.ReflectException; + +public final class ObjectKit { + + private ObjectKit() { + } + + @SuppressWarnings("unchecked") + public static T model(String slug, Class clazz, Map params){ + try { + Object obj = ReflectKit.newInstance(clazz); + Field[] fields = clazz.getDeclaredFields(); + if(null == fields || fields.length == 0){ + return null; + } + + for(Field field : fields){ + field.setAccessible(true); + if(field.getName().equals("serialVersionUID")){ + continue; + } + String fieldName = slug + "." + field.getName(); + String fieldValue = params.get(fieldName); + + if(null != fieldValue){ + Object value = parse(field.getType(), fieldValue); + field.set(obj, value); + } + + } + return (T) obj; + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + throw new ReflectException(e); + } catch (IllegalAccessException e) { + throw new ReflectException(e); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + return null; + } + + public static Object parse(Class type, String value){ + if (type == Integer.class) { + return Integer.parseInt(value); + } else if (type == String.class) { + return value; + } else if (type == Date.class) { + return DateKit.convertToDate(value); + } else if (type == Double.class) { + return Double.parseDouble(value); + } else if (type == Float.class) { + return Float.parseFloat(value); + } else if (type == Long.class) { + return Long.parseLong(value); + } else if (type == Boolean.class) { + return Boolean.parseBoolean(value); + } else if (type == Short.class) { + return Short.parseShort(value); + } + return value; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/ReflectKit.java b/blade-kit/src/main/java/blade/kit/ReflectKit.java index a03f82bf6..49b5b0002 100644 --- a/blade-kit/src/main/java/blade/kit/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/ReflectKit.java @@ -34,11 +34,9 @@ import blade.kit.log.Logger; /** - * 有关 Reflection 处理的工具类。 + * 有关 Reflection处理的工具类。 * - *

* 这个类中的每个方法都可以“安全”地处理 null ,而不会抛出 NullPointerException。 - *

* * @author biezhi * @since 1.0 @@ -47,7 +45,6 @@ public abstract class ReflectKit { private static final Logger LOGGER = Logger.getLogger(ReflectKit.class); - // ------------------------------------------------------ /** 新建对象 * @throws IllegalAccessException * @throws InstantiationException diff --git a/blade-kit/src/main/java/blade/kit/SystemKit.java b/blade-kit/src/main/java/blade/kit/SystemKit.java index 7707a6ada..e4b41d503 100644 --- a/blade-kit/src/main/java/blade/kit/SystemKit.java +++ b/blade-kit/src/main/java/blade/kit/SystemKit.java @@ -1513,7 +1513,7 @@ public static final void dumpSystemInfo(PrintWriter out) { * * @return 属性值或null */ - private static String getSystemProperty(String name, boolean quiet) { + public static String getSystemProperty(String name, boolean quiet) { try { return System.getProperty(name); } catch (SecurityException e) { @@ -1521,7 +1521,6 @@ private static String getSystemProperty(String name, boolean quiet) { System.err.println("Caught a SecurityException reading the system property '" + name + "'; the SystemUtil property value will default to null."); } - return null; } } diff --git a/blade-kit/src/main/java/blade/kit/exception/ReflectException.java b/blade-kit/src/main/java/blade/kit/exception/ReflectException.java new file mode 100644 index 000000000..852d72d2f --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/exception/ReflectException.java @@ -0,0 +1,22 @@ +package blade.kit.exception; + +public class ReflectException extends RuntimeException{ + + private static final long serialVersionUID = -3979699728217399193L; + + public ReflectException() { + super(); + } + + public ReflectException(String msg) { + super(msg); + } + + public ReflectException(Throwable t) { + super(t); + } + + public ReflectException(String msg, Throwable t) { + super(msg, t); + } +} diff --git a/pom.xml b/pom.xml index 67dce0ed8..ee9ee83d6 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.5.1-alpha + 1.5.1-beta 4.12 From d26e0b51948a46dff9e9eb46597e6371f415aa76 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 28 Dec 2015 10:33:01 +0800 Subject: [PATCH 360/545] add abort request method --- .../com/blade/web/AsynRequestHandler.java | 29 ++++++++++++------- .../com/blade/web/SyncRequestHandler.java | 26 +++++++++++------ .../main/java/com/blade/web/http/Request.java | 10 +++++++ .../web/http/wrapper/ServletRequest.java | 14 ++++++++- 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index 3dc137f88..87a7994f4 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -107,17 +107,21 @@ public void run(){ // If find it if (route != null) { request.setRoute(route); + + boolean result = false; // before inteceptor List befores = routeMatcher.getBefore(uri); - invokeInterceptor(request, response, befores); - - // execute - handle(request, response, route); - - // after inteceptor - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - asyncContext.complete(); + result = invokeInterceptor(request, response, befores); + if(result){ + // execute + handle(request, response, route); + + if(!request.isAbort()){ + // after inteceptor + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + } + } return; } @@ -166,11 +170,16 @@ private void render404(Response response, String uri) { * @param request request object * @param response response object * @param interceptors execute the interceptor list + * @return Return execute is ok */ - private void invokeInterceptor(Request request, Response response, List interceptors) { + private boolean invokeInterceptor(Request request, Response response, List interceptors) { for(Route route : interceptors){ handle(request, response, route); + if(request.isAbort()){ + return false; + } } + return true; } /** diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index 3400fffab..e323ecfac 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -97,16 +97,19 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo // If find it if (route != null) { request.setRoute(route); + boolean result = false; // before inteceptor List befores = routeMatcher.getBefore(uri); - invokeInterceptor(request, response, befores); - - // execute - handle(request, response, route); - - // after inteceptor - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); + result = invokeInterceptor(request, response, befores); + if(result){ + // execute + handle(request, response, route); + if(!request.isAbort()){ + // after inteceptor + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + } + } return; } @@ -153,11 +156,16 @@ private void render404(Response response, String uri) { * @param request request object * @param response response object * @param interceptors execute the interceptor list + * @return Return execute is ok */ - private void invokeInterceptor(Request request, Response response, List interceptors) { + private boolean invokeInterceptor(Request request, Response response, List interceptors) { for(Route route : interceptors){ handle(request, response, route); + if(request.isAbort()){ + return false; + } } + return true; } /** diff --git a/blade-core/src/main/java/com/blade/web/http/Request.java b/blade-core/src/main/java/com/blade/web/http/Request.java index 25948d5dd..9634738d4 100644 --- a/blade-core/src/main/java/com/blade/web/http/Request.java +++ b/blade-core/src/main/java/com/blade/web/http/Request.java @@ -339,6 +339,16 @@ public interface Request { */ Route route(); + /** + * Abort current request + */ + void abort(); + + /** + * @return Return is abort request + */ + boolean isAbort(); + /** * Request body interface * @author biezhi diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index 5b3151e3a..617c45eca 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -77,6 +77,8 @@ public class ServletRequest implements Request { private Blade blade = null; + private boolean isAbort = false; + public ServletRequest(HttpServletRequest request) throws MultipartException, IOException { this.request = request; this.pathParams = new HashMap(); @@ -513,6 +515,16 @@ public Route route() { return this.route; } + @Override + public void abort() { + this.isAbort = true; + } + + @Override + public boolean isAbort() { + return this.isAbort; + } + @Override public T model(String slug, Class clazz) { if(StringKit.isNotBlank(slug) && null != clazz){ @@ -573,4 +585,4 @@ public byte[] asByte() { }; } -} +} \ No newline at end of file From d1eb1430d73c98190c6074e0ef3240dfe279e91e Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 28 Dec 2015 10:54:36 +0800 Subject: [PATCH 361/545] fix parameter position replacement bug --- .../main/java/com/blade/route/Routers.java | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index d47acfba7..8a7cf1c55 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -148,24 +148,31 @@ public void route(String path, Object target, String methodName) { } public void route(String path, Class clazz, String methodName) { - try { - HttpMethod httpMethod = HttpMethod.ALL; - if(methodName.indexOf(":") != -1){ - String[] methodArr = methodName.split(":"); - httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); - methodName = methodArr[1]; - } - Object controller = container.getBean(clazz, Scope.SINGLE); - if(null == controller){ - controller = Aop.create(clazz); - container.registerBean(controller); - } - + + HttpMethod httpMethod = HttpMethod.ALL; + if(methodName.indexOf(":") != -1){ + String[] methodArr = methodName.split(":"); + httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); + methodName = methodArr[1]; + } + Object controller = container.getBean(clazz, Scope.SINGLE); + if(null == controller){ + controller = Aop.create(clazz); + container.registerBean(controller); + } + try { Method method = clazz.getMethod(methodName, Request.class, Response.class); addRoute(httpMethod, path, controller, method); } catch (NoSuchMethodException e) { - e.printStackTrace(); + try { + Method method = clazz.getMethod(methodName, Response.class, Request.class); + addRoute(httpMethod, path, controller, method); + } catch (NoSuchMethodException e1) { + e1.printStackTrace(); + } catch (SecurityException e1) { + e1.printStackTrace(); + } } catch (SecurityException e) { e.printStackTrace(); } From bc02ef33402a55a86bf312d23fd0835a72b836da Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 28 Dec 2015 11:07:51 +0800 Subject: [PATCH 362/545] fix Request queryAsInt is null --- .../blade/web/http/wrapper/ServletRequest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index 617c45eca..b23c0263f 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -225,7 +225,7 @@ public String param(String name, String defaultValue) { @Override public Integer paramAsInt(String name) { String value = param(name); - if (null != value) { + if (StringKit.isNotBlank(value)) { return Integer.valueOf(value); } return null; @@ -234,7 +234,7 @@ public Integer paramAsInt(String name) { @Override public Long paramAsLong(String name) { String value = param(name); - if (null != value) { + if (StringKit.isNotBlank(value)) { return Long.valueOf(value); } return null; @@ -243,7 +243,7 @@ public Long paramAsLong(String name) { @Override public Boolean paramAsBool(String name) { String value = param(name); - if (null != value) { + if (StringKit.isNotBlank(value)) { return Boolean.valueOf(value); } return null; @@ -302,7 +302,7 @@ public String query(String name, String defaultValue) { @Override public Integer queryAsInt(String name) { String value = query(name); - if (null != value) { + if (StringKit.isNotBlank(value)) { return Integer.valueOf(value); } return null; @@ -311,7 +311,7 @@ public Integer queryAsInt(String name) { @Override public Long queryAsLong(String name) { String value = query(name); - if (null != value) { + if (StringKit.isNotBlank(value)) { return Long.valueOf(value); } return null; @@ -320,7 +320,7 @@ public Long queryAsLong(String name) { @Override public Boolean queryAsBool(String name) { String value = query(name); - if (null != value) { + if (StringKit.isNotBlank(value)) { return Boolean.valueOf(value); } return null; @@ -329,7 +329,7 @@ public Boolean queryAsBool(String name) { @Override public Float queryAsFloat(String name) { String value = query(name); - if (null != value) { + if (StringKit.isNotBlank(value)) { return Float.valueOf(value); } return null; @@ -338,7 +338,7 @@ public Float queryAsFloat(String name) { @Override public Double queryAsDouble(String name) { String value = query(name); - if (null != value) { + if (StringKit.isNotBlank(value)) { return Double.valueOf(value); } return null; From 60b86d7034c0a8672c6f047cf76d3733927043a4 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 28 Dec 2015 15:46:23 +0800 Subject: [PATCH 363/545] init project --- .../blade/aop/DefaultMethodInvocation.java | 23 +++--- .../blade/plugin/tx/TransactionHolder.java | 42 ++++++++++ .../blade/plugin/tx/TransactionManage.java | 59 -------------- .../blade/plugin/tx/TransactionManager.java | 15 ++++ .../plugin/tx/TransactionManagerImpl.java | 76 +++++++++++++++++++ 5 files changed, 144 insertions(+), 71 deletions(-) create mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java delete mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TransactionManage.java create mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TransactionManager.java create mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TransactionManagerImpl.java diff --git a/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java b/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java index 487bec470..1d5eef2aa 100644 --- a/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java +++ b/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java @@ -18,11 +18,11 @@ import java.lang.reflect.Method; import java.util.List; +import net.sf.cglib.proxy.MethodInterceptor; + import com.blade.aop.annotation.AfterAdvice; import com.blade.aop.annotation.BeforeAdvice; import com.blade.aop.intercept.MethodInvocation; - -import blade.kit.log.Logger; /** * 默认的方法执行器实现 @@ -31,17 +31,15 @@ */ public class DefaultMethodInvocation implements MethodInvocation { - private static final Logger LOGGER = Logger.getLogger(DefaultMethodInvocation.class); - List interceptors; - private DefaultProxy proxy; + private MethodInterceptor proxy; private Method method; private Object target; private Object[] args; int index = 0; private boolean executed = false; - public DefaultMethodInvocation(DefaultProxy proxy, Method method, Object target, Object[] args, List interceptorChain) { + public DefaultMethodInvocation(MethodInterceptor proxy, Method method, Object target, Object[] args, List interceptorChain) { this.interceptors = interceptorChain; this.method = method; this.target = target; @@ -49,7 +47,7 @@ public DefaultMethodInvocation(DefaultProxy proxy, Method method, Object target, this.proxy = proxy; } - public Object proceed() throws Exception { + public Object proceed() throws Throwable { AbstractMethodInterceptor interceptor = null; Object result = null; if (interceptors.size() > 0 && index < interceptors.size()) { @@ -61,12 +59,13 @@ public Object proceed() throws Exception { } // 执行真正的方法调用 if (!executed) { - executed = true; - try { + executed = true; + result = method.invoke(target, args); + /*try { result = method.invoke(target, args); - } catch (RuntimeException e) { + } catch (RuntimeException e) { LOGGER.error(e.getMessage()); - } + }*/ } if (index > 0) { interceptor = interceptors.get(--index); @@ -89,7 +88,7 @@ public Method getMethod() { return method; } - public DefaultProxy getProxy() { + public MethodInterceptor getProxy() { return proxy; } diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java new file mode 100644 index 000000000..84e4363bb --- /dev/null +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java @@ -0,0 +1,42 @@ +package com.blade.plugin.tx; + +import java.sql.Connection; + +import javax.sql.DataSource; + +public class TransactionHolder implements TransactionManager { + + private static DataSource dataSource; + + public TransactionHolder(DataSource dataSource) { + TransactionHolder.dataSource = dataSource; + } + + private static final ThreadLocal tranManager = new ThreadLocal() { + protected TransactionManager initialValue() { + System.out.println(this.toString() + "--Thread Local Initialize--"); + return new TransactionManagerImpl(dataSource); + } + }; + + @Override + public void beginTransaction() { + tranManager.get().beginTransaction(); + } + + @Override + public void commit() { + tranManager.get().commit(); + } + + @Override + public void rollback() { + tranManager.get().rollback(); + } + + @Override + public Connection getConnection() { + return tranManager.get().getConnection(); + } + +} diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManage.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManage.java deleted file mode 100644 index 7a094d1f1..000000000 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManage.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.blade.plugin.tx; - -import java.sql.Connection; -import java.sql.SQLException; - -import javax.sql.DataSource; - -import blade.kit.log.Logger; - -public class TransactionManage { - - private Logger logger = Logger.getLogger(TransactionManage.class); - - private DataSource dataSource; - - public TransactionManage(DataSource dataSource) { - this.dataSource = dataSource; - } - - public void start() throws SQLException { - Connection connection = getConnection(); - connection.setAutoCommit(false); - logger.debug("begin transaction."); - } - - public final void commit() throws SQLException { - Connection connection = getConnection(); - connection.commit(); - logger.debug("commit transaction."); - } - - public final void rollback() { - Connection connection = null; - try { - connection = getConnection(); - connection.rollback(); - logger.debug("rollback transaction."); - } catch (SQLException e) { - throw new RuntimeException("Couldn't rollback on connection[" + connection + "].", e); - } - } - - public final void close() { - Connection connection = null; - try { - connection = getConnection(); - connection.setAutoCommit(true); - connection.setReadOnly(false); - connection.close(); - } catch (SQLException e) { - throw new RuntimeException("Couldn't close connection[" + connection + "].", e); - } - } - - private Connection getConnection() throws SQLException { - return dataSource.getConnection(); - } - -} \ No newline at end of file diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManager.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManager.java new file mode 100644 index 000000000..da54bd3fe --- /dev/null +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManager.java @@ -0,0 +1,15 @@ +package com.blade.plugin.tx; + +import java.sql.Connection; + +public interface TransactionManager { + + Connection getConnection(); + + void beginTransaction(); + + void commit(); + + void rollback(); + +} diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManagerImpl.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManagerImpl.java new file mode 100644 index 000000000..11f651b1a --- /dev/null +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManagerImpl.java @@ -0,0 +1,76 @@ +package com.blade.plugin.tx; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Stack; + +import javax.sql.DataSource; + +import blade.kit.log.Logger; + +public class TransactionManagerImpl implements TransactionManager { + + private static final Logger LOGGER = Logger.getLogger(TransactionManagerImpl.class); + + private Stackconnections = new Stack(); + + private DataSource dataSource; + + public TransactionManagerImpl(DataSource dataSource) { + this.dataSource = dataSource; + } + + @Override + public Connection getConnection() { + + if (connections.isEmpty()) { + this.addConn(); + } + + return connections.peek(); + } + + @Override + public void beginTransaction() { + this.addConn(); + } + + @Override + public void commit() { + try { + if (connections.peek() != null&& !connections.peek().isClosed()) { + LOGGER.info(connections.peek() + "--> commit"); + connections.peek().commit(); + connections.pop().close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + } + + @Override + public void rollback() { + try { + if (connections.peek() != null&& !connections.peek().isClosed()) { + LOGGER.info(connections.peek() + "--> rollback"); + connections.peek().rollback(); + connections.pop().close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void addConn() { + try { + Connection con = dataSource.getConnection(); + con.setAutoCommit(false); + connections.push(con); + LOGGER.info(con + "--> connection"); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} From 9f42e8285d1f5996cd3f428476a180ed10688d0e Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 28 Dec 2015 15:46:54 +0800 Subject: [PATCH 364/545] add Transaction Interceptor --- .../plugin/tx/TransactionInterceptor.java | 18 ++++-------------- .../java/com/blade/plugin/tx/TxPlugin.java | 11 +++++------ 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java index 4e975c4b9..9d5217d50 100644 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java @@ -1,7 +1,5 @@ package com.blade.plugin.tx; -import java.sql.SQLException; - import javax.sql.DataSource; import com.blade.aop.AbstractMethodInterceptor; @@ -10,28 +8,20 @@ public class TransactionInterceptor extends AbstractMethodInterceptor { - private TransactionManage transactionManager; + private TransactionHolder local = null; public TransactionInterceptor(DataSource dataSource) { - this.transactionManager = new TransactionManage(dataSource); + local = new TransactionHolder(dataSource); } @BeforeAdvice(expression = "@com.blade.plugin.tx.annotation.Transactional") public void beforeAdvice() { - try { - transactionManager.start(); - } catch (SQLException e) { - throw new RuntimeException("begin transaction failure", e); - } + local.beginTransaction(); } @AfterAdvice(expression = "@com.blade.plugin.tx.annotation.Transactional") public void afterAdvice() { - try { - transactionManager.commit(); - } catch (SQLException e) { - throw new RuntimeException("commit transaction failure", e); - } + local.commit(); } } \ No newline at end of file diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java b/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java index 4383fe4d6..4f4fff654 100644 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java @@ -2,6 +2,8 @@ import javax.sql.DataSource; +import blade.kit.Assert; + import com.blade.aop.AopProxy; import com.blade.plugin.Plugin; @@ -12,7 +14,7 @@ */ public class TxPlugin implements Plugin { - private TransactionInterceptor transactionInterceptor; + TransactionInterceptor transactionInterceptor = null; public TxPlugin() { } @@ -24,11 +26,8 @@ public TxPlugin dataSource(DataSource dataSource){ @Override public void run() { - if(null == transactionInterceptor){ - throw new RuntimeException("transaction plugin load error,TransactionInterceptor is NULL!"); - } else { - AopProxy.addInterceptor(transactionInterceptor); - } + Assert.notNull(transactionInterceptor); + AopProxy.addInterceptor(transactionInterceptor); } @Override From 0116f024e9bfb38ec4c9736bd9ee0e21132f86a1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 29 Dec 2015 14:50:29 +0800 Subject: [PATCH 365/545] add a static resource output --- .../main/java/com/blade/ioc/AopCreator.java | 19 +--- .../com/blade/web/AsynRequestHandler.java | 14 ++- .../java/com/blade/web/RouteArgument.java | 5 +- .../com/blade/web/SyncRequestHandler.java | 40 ++++---- .../com/blade/web/http/HttpException.java | 92 ++++++++++++------- .../web/http/wrapper/ServletRequest.java | 27 +++--- .../web/http/wrapper/ServletResponse.java | 8 +- 7 files changed, 112 insertions(+), 93 deletions(-) diff --git a/blade-core/src/main/java/com/blade/ioc/AopCreator.java b/blade-core/src/main/java/com/blade/ioc/AopCreator.java index f03757055..e2bd31bb5 100644 --- a/blade-core/src/main/java/com/blade/ioc/AopCreator.java +++ b/blade-core/src/main/java/com/blade/ioc/AopCreator.java @@ -17,6 +17,7 @@ import com.blade.aop.AopProxy; + /** * Aop Create Object * @@ -43,22 +44,4 @@ public static Object createProxy(Class clazz){ return AopProxy.create(clazz); } - /** - * Create a proxy object - * @param target original java object - * @return return proxy object - */ - public static T create(Object target){ - return AopProxy.create(target); - } - - /** - * Create a proxy object - * @param target original java object - * @return return proxy object - */ - public static Object createProxy(Object target){ - return AopProxy.create(target); - } - } diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index 87a7994f4..13932be30 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -38,6 +38,7 @@ import com.blade.web.http.Path; import com.blade.web.http.Request; import com.blade.web.http.Response; +import com.blade.web.http.ResponsePrint; import com.blade.web.http.wrapper.ServletRequest; import com.blade.web.http.wrapper.ServletResponse; @@ -84,14 +85,17 @@ public void run(){ // If it is static, the resource is handed over to the filter if(null != blade.staticFolder() && blade.staticFolder().length > 0){ if(!filterStaticFolder(uri)){ - asyncContext.complete(); - return; + if(blade.debug()){ + LOGGER.debug("Request : " + method + "\t" + uri); + } + String realpath = httpRequest.getServletContext().getRealPath(uri); + ResponsePrint.printStatic(uri, realpath, httpResponse); + return; } } - if(blade.debug()){ - LOGGER.debug("Request : " + method + "\t" + uri); - } + LOGGER.info("Request : " + method + "\t" + uri); + // Create Request Request request = new ServletRequest(httpRequest); diff --git a/blade-core/src/main/java/com/blade/web/RouteArgument.java b/blade-core/src/main/java/com/blade/web/RouteArgument.java index e1694655c..0b067afc2 100644 --- a/blade-core/src/main/java/com/blade/web/RouteArgument.java +++ b/blade-core/src/main/java/com/blade/web/RouteArgument.java @@ -21,6 +21,7 @@ import com.blade.web.http.Request; import com.blade.web.http.Response; +import com.blade.web.http.ResponsePrint; /** * Route parameters of injector @@ -75,7 +76,9 @@ public static Object executeMethod(Object object, Method method, Request request return ReflectKit.invokeMehod(object, method); } } catch (Exception e) { - throw new RuntimeException("invoke method error.", e); + request.abort(); + ResponsePrint.printError(e, 500, response.raw()); } + return null; } } diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index e323ecfac..2d43e7795 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -38,6 +38,7 @@ import com.blade.web.http.Path; import com.blade.web.http.Request; import com.blade.web.http.Response; +import com.blade.web.http.ResponsePrint; import com.blade.web.http.wrapper.ServletRequest; import com.blade.web.http.wrapper.ServletResponse; @@ -65,24 +66,28 @@ public SyncRequestHandler(ServletContext servletContext, Routers routers) { public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ Response response = null; + + // http method, GET/POST ... + String method = httpRequest.getMethod(); + + // reuqest uri + String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); + + // If it is static, the resource is handed over to the filter + if(null != blade.staticFolder() && blade.staticFolder().length > 0){ + if(!filterStaticFolder(uri)){ + if(blade.debug()){ + LOGGER.debug("Request : " + method + "\t" + uri); + } + String realpath = httpRequest.getServletContext().getRealPath(uri); + ResponsePrint.printStatic(uri, realpath, httpResponse); + return; + } + } + + LOGGER.info("Request : " + method + "\t" + uri); + try { - // http method, GET/POST ... - String method = httpRequest.getMethod(); - - // reuqest uri - String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - - // If it is static, the resource is handed over to the filter - if(null != blade.staticFolder() && blade.staticFolder().length > 0){ - if(!filterStaticFolder(uri)){ - return; - } - } - - if(blade.debug()){ - LOGGER.debug("Request : " + method + "\t" + uri); - } - // Create Request Request request = new ServletRequest(httpRequest); @@ -212,4 +217,5 @@ private boolean filterStaticFolder(String uri){ return true; } + } diff --git a/blade-core/src/main/java/com/blade/web/http/HttpException.java b/blade-core/src/main/java/com/blade/web/http/HttpException.java index 92dd26a7c..4790416ff 100644 --- a/blade-core/src/main/java/com/blade/web/http/HttpException.java +++ b/blade-core/src/main/java/com/blade/web/http/HttpException.java @@ -1,44 +1,66 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; -/** - * HttpException - * - * @author biezhi - * @since 1.0 - */ -public class HttpException extends RuntimeException { +import java.io.IOException; - private static final long serialVersionUID = 1L; +public class HttpException extends IOException { - public HttpException() { - super(); - } + /** + * Serialization marker. + */ + private static final long serialVersionUID = -505306086879848229L; - public HttpException(String message, Throwable throwable) { - super(message, throwable); - } + /** + * Status code. + */ + private final transient int status; - public HttpException(String message) { - super(message); - } + /** + * Ctor. + * @param code HTTP status code + */ + public HttpException(final int code) { + super(Integer.toString(code)); + this.status = code; + } + + /** + * Ctor. + * @param code HTTP status code + * @param cause Cause of the problem + */ + public HttpException(final int code, final String cause) { + super(String.format("[%03d] %s", code, cause)); + this.status = code; + } - public HttpException(Throwable throwable) { - super(throwable); - } + /** + * Ctor. + * @param cause Cause of the problem + * @param code HTTP status code + */ + public HttpException(final Throwable cause, final int code) { + super(cause); + this.status = code; + } + + /** + * Ctor. + * @param code HTTP status code + * @param msg Exception message + * @param cause Cause of the problem + */ + public HttpException(final int code, final String msg, + final Throwable cause) { + super(String.format("[%03d] %s", code, msg), cause); + this.status = code; + } + + /** + * HTTP status code. + * @return Code + */ + public final int code() { + return this.status; + } } diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index b23c0263f..0a1be2e76 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -44,7 +44,6 @@ import com.blade.Blade; import com.blade.route.Route; -import com.blade.web.http.HttpException; import com.blade.web.http.HttpMethod; import com.blade.web.http.Path; import com.blade.web.http.Request; @@ -226,7 +225,7 @@ public String param(String name, String defaultValue) { public Integer paramAsInt(String name) { String value = param(name); if (StringKit.isNotBlank(value)) { - return Integer.valueOf(value); + return Integer.parseInt(value); } return null; } @@ -235,7 +234,7 @@ public Integer paramAsInt(String name) { public Long paramAsLong(String name) { String value = param(name); if (StringKit.isNotBlank(value)) { - return Long.valueOf(value); + return Long.parseLong(value); } return null; } @@ -244,7 +243,7 @@ public Long paramAsLong(String name) { public Boolean paramAsBool(String name) { String value = param(name); if (StringKit.isNotBlank(value)) { - return Boolean.valueOf(value); + return Boolean.parseBoolean(value); } return null; } @@ -303,7 +302,7 @@ public String query(String name, String defaultValue) { public Integer queryAsInt(String name) { String value = query(name); if (StringKit.isNotBlank(value)) { - return Integer.valueOf(value); + return Integer.parseInt(value); } return null; } @@ -312,7 +311,7 @@ public Integer queryAsInt(String name) { public Long queryAsLong(String name) { String value = query(name); if (StringKit.isNotBlank(value)) { - return Long.valueOf(value); + return Long.parseLong(value); } return null; } @@ -321,7 +320,7 @@ public Long queryAsLong(String name) { public Boolean queryAsBool(String name) { String value = query(name); if (StringKit.isNotBlank(value)) { - return Boolean.valueOf(value); + return Boolean.parseBoolean(value); } return null; } @@ -330,7 +329,7 @@ public Boolean queryAsBool(String name) { public Float queryAsFloat(String name) { String value = query(name); if (StringKit.isNotBlank(value)) { - return Float.valueOf(value); + return Float.parseFloat(value); } return null; } @@ -339,7 +338,7 @@ public Float queryAsFloat(String name) { public Double queryAsDouble(String name) { String value = query(name); if (StringKit.isNotBlank(value)) { - return Double.valueOf(value); + return Double.parseDouble(value); } return null; } @@ -546,7 +545,7 @@ public FileItem[] files() { public BodyParser body() { return new BodyParser() { @Override - public String asString() throws HttpException { + public String asString() { try { BufferedReader reader = new BufferedReader( new InputStreamReader(request.getInputStream()) ); StringBuilder sb = new StringBuilder(); @@ -560,17 +559,19 @@ public String asString() throws HttpException { return data; } catch (IOException e) { - throw new HttpException(e); + e.printStackTrace(); } + return null; } @Override - public InputStream asInputStream() throws HttpException { + public InputStream asInputStream() { try { return request.getInputStream(); } catch (IOException e) { - throw new HttpException(e); + e.printStackTrace(); } + return null; } @Override diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index d084fb8b2..6aa4a4fa0 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -29,7 +29,6 @@ import com.blade.context.BladeWebContext; import com.blade.render.ModelAndView; import com.blade.render.Render; -import com.blade.web.http.HttpException; import com.blade.web.http.HttpStatus; import com.blade.web.http.Path; import com.blade.web.http.Request; @@ -188,8 +187,9 @@ public Response text(String text) { this.written = true; return this; } catch (IOException e) { - throw new HttpException(e); + e.printStackTrace(); } + return null; } @Override @@ -315,7 +315,7 @@ public void redirect(String path) { try { response.sendRedirect(path); } catch (IOException e) { - throw new HttpException(e); + e.printStackTrace(); } } @@ -326,7 +326,7 @@ public void go(String path) { String location = Path.fixPath(ctx + path); response.sendRedirect(location); } catch (IOException e) { - throw new HttpException(e); + e.printStackTrace(); } } From 975c0dd2a817361b4ac3a1470fa4d8695e4c01d3 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 29 Dec 2015 14:50:57 +0800 Subject: [PATCH 366/545] add a static resource output --- .../com/blade/web/http/ResponsePrint.java | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 blade-core/src/main/java/com/blade/web/http/ResponsePrint.java diff --git a/blade-core/src/main/java/com/blade/web/http/ResponsePrint.java b/blade-core/src/main/java/com/blade/web/http/ResponsePrint.java new file mode 100644 index 000000000..0973a8a42 --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/http/ResponsePrint.java @@ -0,0 +1,88 @@ +package com.blade.web.http; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; + +import javax.servlet.http.HttpServletResponse; + +import blade.kit.FileKit; +import blade.kit.StreamKit; + +public final class ResponsePrint { + + private ResponsePrint() { + } + + /** + * Print Error Message + * @param err + * @param code + * @param response + */ + public static void printError(Throwable err, int code, HttpServletResponse response){ + err.printStackTrace(); + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final PrintWriter writer = new PrintWriter(baos); + err.printStackTrace(writer); + writer.close(); + response.setStatus(code); + InputStream body = new ByteArrayInputStream(baos.toByteArray()); + try { + print(body, response.getOutputStream()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Print + * @param body + * @param out + * @throws IOException + */ + public static void print(InputStream body, OutputStream out) throws IOException { + StreamKit.io(body, out, true, true); + /* + try { + int size = in.available(); + byte[] content = new byte[size]; + in.read(content); + out.write(content); + } finally { + in.close(); + out.close(); + }*/ + } + + + /** + * Print static file + * @param uri + * @param realpath + * @param httpResponse + */ + public static void printStatic(String uri, String realpath, HttpServletResponse httpResponse) { + try { + File file = new File(realpath); + if(FileKit.exist(file)){ + FileInputStream in = new FileInputStream(file); + print(in, httpResponse.getOutputStream()); + } else { + HttpException httpException = new HttpException(404, uri + " not found"); + ResponsePrint.printError(httpException, 404, httpResponse); + } + } catch (FileNotFoundException e) { + ResponsePrint.printError(e, 404, httpResponse); + } catch (IOException e) { + ResponsePrint.printError(e, 500, httpResponse); + } + } + +} From 45b2bbf8662042f88fe6568c9159b769d5c5f623 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 29 Dec 2015 15:58:43 +0800 Subject: [PATCH 367/545] a friendly error message --- LICENSE | 209 +- blade-core/src/main/java/com/blade/Blade.java | 1676 ++++++++--------- blade-core/src/main/java/com/blade/Const.java | 2 +- .../main/java/com/blade/loader/Config.java | 12 +- .../java/com/blade/loader/Configurator.java | 10 +- .../com/blade/web/AsynRequestHandler.java | 2 +- .../com/blade/web/SyncRequestHandler.java | 2 +- .../com/blade/web/http/ResponsePrint.java | 39 +- .../plugin/tx/TransactionInterceptor.java | 15 + pom.xml | 2 +- 10 files changed, 1099 insertions(+), 870 deletions(-) diff --git a/LICENSE b/LICENSE index 6f1bd93ee..9b5e4019d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,13 +1,202 @@ -Copyright 2015 biezhi -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 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ - http://www.apache.org/licenses/LICENSE-2.0 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -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. \ No newline at end of file + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 791107db0..9151e905b 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -1,838 +1,838 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.io.IOException; -import java.io.InputStream; -import java.text.ParseException; -import java.util.List; -import java.util.Map; - -import blade.kit.Assert; -import blade.kit.IOKit; -import blade.kit.PropertyKit; -import blade.kit.json.JSONKit; - -import com.blade.ioc.Container; -import com.blade.ioc.SampleContainer; -import com.blade.loader.ClassPathRouteLoader; -import com.blade.loader.Config; -import com.blade.loader.Configurator; -import com.blade.plugin.Plugin; -import com.blade.render.JspRender; -import com.blade.render.Render; -import com.blade.route.Route; -import com.blade.route.RouteException; -import com.blade.route.RouteHandler; -import com.blade.route.Routers; -import com.blade.server.Server; -import com.blade.web.http.HttpMethod; - -/** - * Blade Core Class - * - * @author biezhi - * @since 1.0 - */ -public class Blade { - - /** - * Blade initialize - */ - private boolean isInit = false; - - /** - * Servlet asynchronous - */ - private boolean isAsyn = true; - - /** - * Blade initialize config class - */ - private Bootstrap bootstrap = null; - - /** - * Global configuration Object - */ - private Config config = null; - - /** - * IOC Container, save javabean - */ - private Container container = null; - - /** - * ioc application object - */ - private IocApplication iocApplication = null; - - /** - * default render is jspRender - */ - private Render render = null; - - /** - * manage route - */ - private Routers routers = null; - - /** - * jetty start port - */ - private int port = Const.DEFAULT_PORT; - - /** - * jetty server - */ - private Server bladeServer; - - private Blade() { - this.config = new Config(); - this.container = new SampleContainer(); - this.iocApplication = new IocApplication(container); - this.routers = new Routers(container); - this.render = new JspRender(); - } - - public static final class BladeHolder { - private static final Blade ME = new Blade(); - } - - /** - * @return Single case method returns Blade object - */ - public static final Blade me(){ - return BladeHolder.ME; - } - - /** - * Set Blade initialize - * @param isInit initialize - */ - public void setInit(boolean isInit) { - this.isInit = isInit; - } - - /** - * create a jetty server - * @param port server port - * @return return server object - */ - public Server createServer(int port){ - return new Server(port, isAsyn); - } - - /** - * @return return route manager - */ - public Routers routers() { - return routers; - } - - /** - * @return return blade ioc container - */ - public Container container(){ - return container; - } - - /** - * Setting a ioc container - * @param container ioc object - * @return return blade - */ - public Blade container(Container container){ - Assert.notNull(container); - this.container = container; - return this; - } - - /** - * Setting Properties configuration file - * File path based on classpath - * - * @param confName properties file name - * @return return blade - */ - @Deprecated - public Blade config(String confName){ - Assert.notBlank(confName); - Map configMap = PropertyKit.getPropertyMap(confName); - configuration(configMap); - return this; - } - - /** - * Setting Properties configuration file - * File path based on classpath - * - * @param confName properties file name - * @return return blade - */ - public Blade setAppConf(String confName){ - Assert.notBlank(confName); - Map configMap = PropertyKit.getPropertyMap(confName); - configuration(configMap); - return this; - } - - /** - * Setting JSON file configuration - * File path based on classpath - * - * @param fileName json file name - * @return return blade - */ - public Blade setJsonConf(String fileName){ - Assert.notBlank(fileName); - InputStream inputStream = Blade.class.getResourceAsStream(fileName); - if(null != inputStream){ - try { - String json = IOKit.toString(inputStream); - Map configMap = JSONKit.toMap(json); - configuration(configMap); - } catch (IOException e) { - e.printStackTrace(); - } - } - return this; - } - - /** - * Setting json character config, Not recommended - * - * @param json json character - * @return return blade - */ - public Blade setAppJson(String json){ - Assert.notBlank(json); - Map configMap = JSONKit.toMap(json); - configuration(configMap); - return this; - } - - /** - * Setting Map config - * @param configMap set config map - */ - private void configuration(Map configMap){ - Assert.notEmpty(configMap); - new Configurator(config, configMap).run(); - } - - /** - * Setting route package,e.g:com.baldejava.route - * Can be introduced into multiple packages, all of which are in the package. - * - * @param packages route package path, is your package name - * @return return blade - */ - public Blade routes(String...packages){ - Assert.notNull(packages); - config.setRoutePackages(packages); - return this; - } - - /** - * Setting top package frame automatically for routing packets and packet interceptor, e.g:com.bladejava - * As above, it will be over:com.bladejava.route、com.bladejava.interceptor Routing and interceptor inside - * - * @param basePackage default package path - * @return return blade - */ - public Blade defaultRoute(String basePackage){ - Assert.notBlank(basePackage); - config.setBasePackage(basePackage); - return this; - } - - /** - * Setting the path where the interceptor, e.g:com.bladejava.interceptor - * - * @param packageName interceptor packagename - * @return return blade - */ - public Blade interceptor(String packageName) { - Assert.notBlank(packageName); - config.setInterceptorPackage(packageName); - return this; - } - - /** - * Setting Ioc packages, e.g:com.bladejava.service - * - * @param packages All need to do into the package, can be introduced into a number of - * @return return blade - */ - public Blade ioc(String...packages){ - Assert.notNull(packages); - if(packages.length >0){ - config.setIocPackages(packages); - } - return this; - } - - /** - * Add a route - * - * @param path route path - * @param target Target object for routing - * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @return return blade - */ - public Blade route(String path, Object target, String method){ - routers.route(path, target, method); - return this; - } - - /** - * Add a route - * - * @param path route path - * @param target Target object for routing - * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @param httpMethod HTTPMethod - * @return return blade - */ - public Blade route(String path, Object target, String method, HttpMethod httpMethod){ - routers.route(path, target, method, httpMethod); - return this; - } - - /** - * 注册一个函数式的路由 - * 方法上指定请求类型(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) - * - * @param path 路由url - * @param clazz 路由处理类 - * @param method 路由处理方法名称 - * @return Blade 返回Blade单例实例 - */ - public Blade route(String path, Class clazz, String method){ - routers.route(path, clazz, method); - return this; - } - - /** - * Register a functional route - * - * @param path route url - * @param clazz route processing class - * @param method route processing method name - * @param httpMethod HttpMethod Type, GET/POST/... - * @return Blade return blade - */ - public Blade route(String path, Class clazz, String method, HttpMethod httpMethod){ - routers.route(path, clazz, method, httpMethod); - return this; - } - - /** - * Add a route list - * @param routes route list - * @return return blade - */ - public Blade routes(List routes){ - routers.addRoutes(routes); - return this; - } - - /** - * Register a GET request route - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade get(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.GET); - return this; - } - - /** - * Register a POST request route - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade post(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.POST); - return this; - } - - /** - * Register a DELETE request route - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade delete(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.DELETE); - return this; - } - - /** - * Register a PUT request route - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade put(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.PUT); - return this; - } - - /** - * Register for any request routing - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade all(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Register for any request routing - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade any(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Register a pre routing request interceptor - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade before(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.BEFORE); - return this; - } - - /** - * Register a after routing request interceptor - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade after(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.AFTER); - return this; - } - - /** - * Setting Render Engin, Default is JspRender - * - * @param render Render engine object - * @return return blade - */ - public Blade viewEngin(Render render) { - Assert.notNull(render); - this.render = render; - return this; - } - - /** - * Setting default view prefix, default is WEBROOT/WEB-INF/ - * - * @param prefix views path, e.g:/WEB-INF/views/ - * @return return blade - */ - public Blade viewPrefix(final String prefix) { - Assert.notBlank(prefix); - if(prefix.startsWith("/")){ - config.setViewPrefix(prefix); - } - return this; - } - - /** - * Setting view default suffix, default is .jsp - * - * @param suffix view suffix, e.g:.html .vm - * @return return blade - */ - public Blade viewSuffix(final String suffix) { - Assert.notBlank(suffix); - if(suffix.startsWith(".")){ - config.setViewSuffix(suffix); - } - return this; - } - - /** - * Also set the view's directory and view the suffix name - * - * @param viewPath views path, e.g:/WEB-INF/views - * @param viewExt view suffix, e.g:.html .vm - * @return return blade - */ - public Blade view(final String viewPath, final String viewExt) { - Assert.notBlank(viewPath); - Assert.notBlank(viewExt); - viewPrefix(viewPath); - viewSuffix(viewExt); - return this; - } - - /** - * Setting the frame static file folder - * - * @param folders List of directories to filter, e.g: "/public,/static,/images" - * @return return blade - */ - public Blade staticFolder(final String ... folders) { - Assert.notNull(folders); - config.setStaticFolders(folders); - return this; - } - - /** - * Setting XSS is enable - * - * @param enableXSS enable XSS, default is false - * @return return blade - */ - public Blade enableXSS(boolean enableXSS){ - config.setEnableXSS(enableXSS); - return this; - } - - /** - * Dynamically set the global initialization class, the embedded Jetty boot - * - * @param bootstrap global initialization config class - * @return return blade - */ - public Blade app(Bootstrap bootstrap){ - Assert.notNull(bootstrap); - this.bootstrap = bootstrap; - return this; - } - - /** - * Dynamically set global initialization class - * - * @param bootstrap global initialization config class - * @return return blade - */ - public Blade app(Class bootstrap){ - Assert.notNull(bootstrap); - Object object = container.registerBean(Aop.create(bootstrap)); - this.bootstrap = (Bootstrap) object; - return this; - } - - /** - * Setting 404 view page - * - * @param view404 404 view page - * @return return blade - */ - public Blade setView404(final String view404){ - Assert.notBlank(view404); - config.setView404(view404); - return this; - } - - /** - * Setting 500 view page - * - * @param view500 500 view page - * @return return blade - */ - public Blade setView500(final String view500){ - Assert.notBlank(view500); - config.setView500(view500); - return this; - } - - /** - * Setting blade web root path - * - * @param webRoot web root path - * @return return blade - */ - public Blade webRoot(final String webRoot){ - Assert.notBlank(webRoot); - config.setWebRoot(webRoot); - return this; - } - - /** - * Setting blade run mode - * - * @param isdebug is debug mode - * @return return blade - */ - public Blade debug(boolean isdebug){ - config.setDebug(isdebug); - return this; - } - - /** - * Setting jetty listen port - * - * @param port port, default is 9000 - * @return return blade - */ - public Blade listen(int port){ - this.port = port; - return this; - } - - /** - * Setting servlet asynchronous - * @param isAsyn is asynchronous - * @return return blade - */ - public Blade isAsyn(boolean isAsyn){ - this.isAsyn = isAsyn; - return this; - } - - /** - * Setting jetty context - * - * @param contextPath context path, default is / - */ - public void start(String contextPath) { - try { - Assert.notBlank(contextPath); - bladeServer = new Server(this.port, this.isAsyn); - bladeServer.start(contextPath); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Start jetty server - */ - public void start() { - this.start("/"); - } - - /** - * Jetty sever shutdown - */ - public void stop() { - try { - bladeServer.stop(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Join in server - * - * @throws InterruptedException join exception - */ - public void join() throws InterruptedException { - bladeServer.join(); - } - - /** - * @return Return blade config object - */ - public Config config(){ - return config; - } - - /** - * @return Return blade scan base package - */ - public String basePackage(){ - return config.getBasePackage(); - } - - /** - * @return Return route packages - */ - public String[] routePackages(){ - return config.getRoutePackages(); - } - - /** - * @return Return ioc packages - */ - public String[] iocs(){ - return config.getIocPackages(); - } - - /** - * @return Returns the interceptor array, only one element here use String[] - */ - public String interceptorPackage(){ - return config.getInterceptorPackage(); - } - - - /** - * @return Return views prefix - */ - public String viewPrefix(){ - return config.getViewPrefix(); - } - - /** - * @return Return blade encoding, default is UTF-8 - */ - public String encoding(){ - return config.getEncoding(); - } - - /** - * @return Return view suffix - */ - public String viewSuffix(){ - return config.getViewSuffix(); - } - - /** - * @return Return 404 view - */ - public String view404(){ - return config.getView404(); - } - - /** - * @return Return 500 view - */ - public String view500(){ - return config.getView500(); - } - - /** - * @return Return blade web root path - */ - public String webRoot(){ - return config.getWebRoot(); - } - - /** - * @return Return is debug mode - */ - public boolean debug(){ - return config.isDebug(); - } - - /** - * @return Return static resource directory - */ - public String[] staticFolder(){ - return config.getStaticFolders(); - } - - /** - * @return Return bootstrap object - */ - public Bootstrap bootstrap(){ - return bootstrap; - } - - /** - * @return Return current render engine - */ - public Render render() { - return this.render; - } - - /** - * @return Return XSS is enabled - */ - public boolean enableXSS(){ - return config.isEnableXSS(); - } - - /** - * return register plugin object - * - * @param plugin plugin class - * @param generic - * @return return plugin object - */ - @SuppressWarnings("unchecked") - public T plugin(Class plugin){ - Assert.notNull(plugin); - Object object = iocApplication.getPlugin(plugin); - if(null == object){ - object = iocApplication.registerPlugin(plugin); - } - return (T) object; - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage controller package name - * @param conf Configuration file path, the configuration file must be in classpath - * @return return blade - */ - public Blade routeConf(String basePackage, String conf) { - try { - Assert.notBlank(basePackage); - Assert.notBlank(conf); - InputStream ins = Blade.class.getResourceAsStream("/" + conf); - ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); - routesLoader.setBasePackage(basePackage); - List routes = routesLoader.load(); - routers.addRoutes(routes); - } catch (RouteException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - return this; - } - - /** - * @return Return IocApplication object - */ - public IocApplication iocApplication(){ - return iocApplication; - } - - /** - * @return Initialize ioc application and return blade - */ - public Blade iocInit(){ - iocApplication.init(iocs(), bootstrap); - return this; - } - - /** - * @return Return blade is initialize - */ - public boolean isInit() { - return isInit; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +import java.io.IOException; +import java.io.InputStream; +import java.text.ParseException; +import java.util.List; +import java.util.Map; + +import blade.kit.Assert; +import blade.kit.IOKit; +import blade.kit.PropertyKit; +import blade.kit.json.JSONKit; + +import com.blade.ioc.Container; +import com.blade.ioc.SampleContainer; +import com.blade.loader.ClassPathRouteLoader; +import com.blade.loader.Config; +import com.blade.loader.Configurator; +import com.blade.plugin.Plugin; +import com.blade.render.JspRender; +import com.blade.render.Render; +import com.blade.route.Route; +import com.blade.route.RouteException; +import com.blade.route.RouteHandler; +import com.blade.route.Routers; +import com.blade.server.Server; +import com.blade.web.http.HttpMethod; + +/** + * Blade Core Class + * + * @author biezhi + * @since 1.0 + */ +public class Blade { + + /** + * Blade initialize + */ + private boolean isInit = false; + + /** + * Servlet asynchronous + */ + private boolean isAsyn = true; + + /** + * Blade initialize config class + */ + private Bootstrap bootstrap = null; + + /** + * Global configuration Object + */ + private Config config = null; + + /** + * IOC Container, save javabean + */ + private Container container = null; + + /** + * ioc application object + */ + private IocApplication iocApplication = null; + + /** + * default render is jspRender + */ + private Render render = null; + + /** + * manage route + */ + private Routers routers = null; + + /** + * jetty start port + */ + private int port = Const.DEFAULT_PORT; + + /** + * jetty server + */ + private Server bladeServer; + + private Blade() { + this.config = new Config(); + this.container = new SampleContainer(); + this.iocApplication = new IocApplication(container); + this.routers = new Routers(container); + this.render = new JspRender(); + } + + public static final class BladeHolder { + private static final Blade ME = new Blade(); + } + + /** + * @return Single case method returns Blade object + */ + public static final Blade me(){ + return BladeHolder.ME; + } + + /** + * Set Blade initialize + * @param isInit initialize + */ + public void setInit(boolean isInit) { + this.isInit = isInit; + } + + /** + * create a jetty server + * @param port server port + * @return return server object + */ + public Server createServer(int port){ + return new Server(port, isAsyn); + } + + /** + * @return return route manager + */ + public Routers routers() { + return routers; + } + + /** + * @return return blade ioc container + */ + public Container container(){ + return container; + } + + /** + * Setting a ioc container + * @param container ioc object + * @return return blade + */ + public Blade container(Container container){ + Assert.notNull(container); + this.container = container; + return this; + } + + /** + * Setting Properties configuration file + * File path based on classpath + * + * @param confName properties file name + * @return return blade + */ + @Deprecated + public Blade config(String confName){ + Assert.notBlank(confName); + Map configMap = PropertyKit.getPropertyMap(confName); + configuration(configMap); + return this; + } + + /** + * Setting Properties configuration file + * File path based on classpath + * + * @param confName properties file name + * @return return blade + */ + public Blade setAppConf(String confName){ + Assert.notBlank(confName); + Map configMap = PropertyKit.getPropertyMap(confName); + configuration(configMap); + return this; + } + + /** + * Setting JSON file configuration + * File path based on classpath + * + * @param fileName json file name + * @return return blade + */ + public Blade setJsonConf(String fileName){ + Assert.notBlank(fileName); + InputStream inputStream = Blade.class.getResourceAsStream(fileName); + if(null != inputStream){ + try { + String json = IOKit.toString(inputStream); + Map configMap = JSONKit.toMap(json); + configuration(configMap); + } catch (IOException e) { + e.printStackTrace(); + } + } + return this; + } + + /** + * Setting json character config, Not recommended + * + * @param json json character + * @return return blade + */ + public Blade setAppJson(String json){ + Assert.notBlank(json); + Map configMap = JSONKit.toMap(json); + configuration(configMap); + return this; + } + + /** + * Setting Map config + * @param configMap set config map + */ + private void configuration(Map configMap){ + Assert.notEmpty(configMap); + new Configurator(config, configMap).run(); + } + + /** + * Setting route package,e.g:com.baldejava.route + * Can be introduced into multiple packages, all of which are in the package. + * + * @param packages route package path, is your package name + * @return return blade + */ + public Blade routes(String...packages){ + Assert.notNull(packages); + config.setRoutePackages(packages); + return this; + } + + /** + * Setting top package frame automatically for routing packets and packet interceptor, e.g:com.bladejava + * As above, it will be over:com.bladejava.route、com.bladejava.interceptor Routing and interceptor inside + * + * @param basePackage default package path + * @return return blade + */ + public Blade defaultRoute(String basePackage){ + Assert.notBlank(basePackage); + config.setBasePackage(basePackage); + return this; + } + + /** + * Setting the path where the interceptor, e.g:com.bladejava.interceptor + * + * @param packageName interceptor packagename + * @return return blade + */ + public Blade interceptor(String packageName) { + Assert.notBlank(packageName); + config.setInterceptorPackage(packageName); + return this; + } + + /** + * Setting Ioc packages, e.g:com.bladejava.service + * + * @param packages All need to do into the package, can be introduced into a number of + * @return return blade + */ + public Blade ioc(String...packages){ + Assert.notNull(packages); + if(packages.length >0){ + config.setIocPackages(packages); + } + return this; + } + + /** + * Add a route + * + * @param path route path + * @param target Target object for routing + * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade + */ + public Blade route(String path, Object target, String method){ + routers.route(path, target, method); + return this; + } + + /** + * Add a route + * + * @param path route path + * @param target Target object for routing + * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @param httpMethod HTTPMethod + * @return return blade + */ + public Blade route(String path, Object target, String method, HttpMethod httpMethod){ + routers.route(path, target, method, httpMethod); + return this; + } + + /** + * 注册一个函数式的路由 + * 方法上指定请求类型(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) + * + * @param path 路由url + * @param clazz 路由处理类 + * @param method 路由处理方法名称 + * @return Blade 返回Blade单例实例 + */ + public Blade route(String path, Class clazz, String method){ + routers.route(path, clazz, method); + return this; + } + + /** + * Register a functional route + * + * @param path route url + * @param clazz route processing class + * @param method route processing method name + * @param httpMethod HttpMethod Type, GET/POST/... + * @return Blade return blade + */ + public Blade route(String path, Class clazz, String method, HttpMethod httpMethod){ + routers.route(path, clazz, method, httpMethod); + return this; + } + + /** + * Add a route list + * @param routes route list + * @return return blade + */ + public Blade routes(List routes){ + routers.addRoutes(routes); + return this; + } + + /** + * Register a GET request route + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade get(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.GET); + return this; + } + + /** + * Register a POST request route + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade post(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.POST); + return this; + } + + /** + * Register a DELETE request route + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade delete(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.DELETE); + return this; + } + + /** + * Register a PUT request route + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade put(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.PUT); + return this; + } + + /** + * Register for any request routing + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade all(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Register for any request routing + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade any(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Register a pre routing request interceptor + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade before(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.BEFORE); + return this; + } + + /** + * Register a after routing request interceptor + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade after(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.AFTER); + return this; + } + + /** + * Setting Render Engin, Default is JspRender + * + * @param render Render engine object + * @return return blade + */ + public Blade viewEngin(Render render) { + Assert.notNull(render); + this.render = render; + return this; + } + + /** + * Setting default view prefix, default is WEBROOT/WEB-INF/ + * + * @param prefix views path, e.g:/WEB-INF/views/ + * @return return blade + */ + public Blade viewPrefix(final String prefix) { + Assert.notBlank(prefix); + if(prefix.startsWith("/")){ + config.setViewPrefix(prefix); + } + return this; + } + + /** + * Setting view default suffix, default is .jsp + * + * @param suffix view suffix, e.g:.html .vm + * @return return blade + */ + public Blade viewSuffix(final String suffix) { + Assert.notBlank(suffix); + if(suffix.startsWith(".")){ + config.setViewSuffix(suffix); + } + return this; + } + + /** + * Also set the view's directory and view the suffix name + * + * @param viewPath views path, e.g:/WEB-INF/views + * @param viewExt view suffix, e.g:.html .vm + * @return return blade + */ + public Blade view(final String viewPath, final String viewExt) { + Assert.notBlank(viewPath); + Assert.notBlank(viewExt); + viewPrefix(viewPath); + viewSuffix(viewExt); + return this; + } + + /** + * Setting the frame static file folder + * + * @param folders List of directories to filter, e.g: "/public,/static,/images" + * @return return blade + */ + public Blade staticFolder(final String ... folders) { + Assert.notNull(folders); + config.setStaticFolders(folders); + return this; + } + + /** + * Setting XSS is enable + * + * @param enableXSS enable XSS, default is false + * @return return blade + */ + public Blade enableXSS(boolean enableXSS){ + config.setEnableXSS(enableXSS); + return this; + } + + /** + * Dynamically set the global initialization class, the embedded Jetty boot + * + * @param bootstrap global initialization config class + * @return return blade + */ + public Blade app(Bootstrap bootstrap){ + Assert.notNull(bootstrap); + this.bootstrap = bootstrap; + return this; + } + + /** + * Dynamically set global initialization class + * + * @param bootstrap global initialization config class + * @return return blade + */ + public Blade app(Class bootstrap){ + Assert.notNull(bootstrap); + Object object = container.registerBean(Aop.create(bootstrap)); + this.bootstrap = (Bootstrap) object; + return this; + } + + /** + * Setting 404 view page + * + * @param view404 404 view page + * @return return blade + */ + public Blade setView404(final String view404){ + Assert.notBlank(view404); + config.setView404(view404); + return this; + } + + /** + * Setting 500 view page + * + * @param view500 500 view page + * @return return blade + */ + public Blade setView500(final String view500){ + Assert.notBlank(view500); + config.setView500(view500); + return this; + } + + /** + * Setting blade web root path + * + * @param webRoot web root path + * @return return blade + */ + public Blade webRoot(final String webRoot){ + Assert.notBlank(webRoot); + config.setWebRoot(webRoot); + return this; + } + + /** + * Setting blade run mode + * + * @param isDev is dev mode + * @return return blade + */ + public Blade isDev(boolean isDev){ + config.setDev(isDev); + return this; + } + + /** + * Setting jetty listen port + * + * @param port port, default is 9000 + * @return return blade + */ + public Blade listen(int port){ + this.port = port; + return this; + } + + /** + * Setting servlet asynchronous + * @param isAsyn is asynchronous + * @return return blade + */ + public Blade isAsyn(boolean isAsyn){ + this.isAsyn = isAsyn; + return this; + } + + /** + * Setting jetty context + * + * @param contextPath context path, default is / + */ + public void start(String contextPath) { + try { + Assert.notBlank(contextPath); + bladeServer = new Server(this.port, this.isAsyn); + bladeServer.start(contextPath); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Start jetty server + */ + public void start() { + this.start("/"); + } + + /** + * Jetty sever shutdown + */ + public void stop() { + try { + bladeServer.stop(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Join in server + * + * @throws InterruptedException join exception + */ + public void join() throws InterruptedException { + bladeServer.join(); + } + + /** + * @return Return blade config object + */ + public Config config(){ + return config; + } + + /** + * @return Return blade scan base package + */ + public String basePackage(){ + return config.getBasePackage(); + } + + /** + * @return Return route packages + */ + public String[] routePackages(){ + return config.getRoutePackages(); + } + + /** + * @return Return ioc packages + */ + public String[] iocs(){ + return config.getIocPackages(); + } + + /** + * @return Returns the interceptor array, only one element here use String[] + */ + public String interceptorPackage(){ + return config.getInterceptorPackage(); + } + + + /** + * @return Return views prefix + */ + public String viewPrefix(){ + return config.getViewPrefix(); + } + + /** + * @return Return blade encoding, default is UTF-8 + */ + public String encoding(){ + return config.getEncoding(); + } + + /** + * @return Return view suffix + */ + public String viewSuffix(){ + return config.getViewSuffix(); + } + + /** + * @return Return 404 view + */ + public String view404(){ + return config.getView404(); + } + + /** + * @return Return 500 view + */ + public String view500(){ + return config.getView500(); + } + + /** + * @return Return blade web root path + */ + public String webRoot(){ + return config.getWebRoot(); + } + + /** + * @return Return is dev mode + */ + public boolean isDev(){ + return config.isDev(); + } + + /** + * @return Return static resource directory + */ + public String[] staticFolder(){ + return config.getStaticFolders(); + } + + /** + * @return Return bootstrap object + */ + public Bootstrap bootstrap(){ + return bootstrap; + } + + /** + * @return Return current render engine + */ + public Render render() { + return this.render; + } + + /** + * @return Return XSS is enabled + */ + public boolean enableXSS(){ + return config.isEnableXSS(); + } + + /** + * return register plugin object + * + * @param plugin plugin class + * @param generic + * @return return plugin object + */ + @SuppressWarnings("unchecked") + public T plugin(Class plugin){ + Assert.notNull(plugin); + Object object = iocApplication.getPlugin(plugin); + if(null == object){ + object = iocApplication.registerPlugin(plugin); + } + return (T) object; + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage controller package name + * @param conf Configuration file path, the configuration file must be in classpath + * @return return blade + */ + public Blade routeConf(String basePackage, String conf) { + try { + Assert.notBlank(basePackage); + Assert.notBlank(conf); + InputStream ins = Blade.class.getResourceAsStream("/" + conf); + ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); + routesLoader.setBasePackage(basePackage); + List routes = routesLoader.load(); + routers.addRoutes(routes); + } catch (RouteException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return this; + } + + /** + * @return Return IocApplication object + */ + public IocApplication iocApplication(){ + return iocApplication; + } + + /** + * @return Initialize ioc application and return blade + */ + public Blade iocInit(){ + iocApplication.init(iocs(), bootstrap); + return this; + } + + /** + * @return Return blade is initialize + */ + public boolean isInit() { + return isInit; + } + +} diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index a98bbe16e..0a4267d1d 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * Current version */ - String BLADE_VERSION = "1.5.1-beta"; + String BLADE_VERSION = "1.5.1"; /** * Server 500 error HTML diff --git a/blade-core/src/main/java/com/blade/loader/Config.java b/blade-core/src/main/java/com/blade/loader/Config.java index 37ad1f838..54e147b58 100644 --- a/blade-core/src/main/java/com/blade/loader/Config.java +++ b/blade-core/src/main/java/com/blade/loader/Config.java @@ -67,8 +67,8 @@ public class Config { // 500 view page private String view500; - // Is debug mode - private boolean isDebug = true; + // Is dev mode + private boolean isDev = false; // Enabled XSS private boolean enableXSS = false; @@ -212,12 +212,12 @@ public void setWebRoot(String webRoot) { this.webRoot = webRoot; } - public boolean isDebug() { - return isDebug; + public boolean isDev() { + return isDev; } - public void setDebug(boolean isDebug) { - this.isDebug = isDebug; + public void setDev(boolean isDev) { + this.isDev = isDev; } public String getEncoding() { diff --git a/blade-core/src/main/java/com/blade/loader/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java index 3cab8a65d..3eccaed44 100644 --- a/blade-core/src/main/java/com/blade/loader/Configurator.java +++ b/blade-core/src/main/java/com/blade/loader/Configurator.java @@ -48,7 +48,7 @@ public Configurator(Config bladeConfig, private static final String BLADE_ENCODING = "blade.encoding"; private static final String BLADE_VIEW_404 = "blade.view404"; private static final String BLADE_VIEW_500 = "blade.view500"; - private static final String BLADE_DEBUG = "blade.debug"; + private static final String BLADE_DEV = "blade.dev"; private static final String BLADE_ENABLEXSS = "blade.enableXSS"; public void run() { @@ -66,7 +66,7 @@ public void run() { String encoding = configMap.get(BLADE_ENCODING); String view404 = configMap.get(BLADE_VIEW_404); String view500 = configMap.get(BLADE_VIEW_500); - String debug = configMap.get(BLADE_DEBUG); + String dev = configMap.get(BLADE_DEV); String xss = configMap.get(BLADE_ENABLEXSS); if (StringKit.isNotBlank(route)) { @@ -108,9 +108,9 @@ public void run() { bladeConfig.setView500(view500); } - if (StringKit.isNotBlank(debug)) { - Boolean debugBool = Boolean.valueOf(debug); - bladeConfig.setDebug(debugBool); + if (StringKit.isNotBlank(dev)) { + Boolean isDev = Boolean.parseBoolean(dev); + bladeConfig.setDev(isDev); } if (StringKit.isNotBlank(xss)) { diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index 13932be30..b893dba6a 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -85,7 +85,7 @@ public void run(){ // If it is static, the resource is handed over to the filter if(null != blade.staticFolder() && blade.staticFolder().length > 0){ if(!filterStaticFolder(uri)){ - if(blade.debug()){ + if(LOGGER.isDebugEnabled()){ LOGGER.debug("Request : " + method + "\t" + uri); } String realpath = httpRequest.getServletContext().getRealPath(uri); diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index 2d43e7795..3896e9bcd 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -76,7 +76,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo // If it is static, the resource is handed over to the filter if(null != blade.staticFolder() && blade.staticFolder().length > 0){ if(!filterStaticFolder(uri)){ - if(blade.debug()){ + if(LOGGER.isDebugEnabled()){ LOGGER.debug("Request : " + method + "\t" + uri); } String realpath = httpRequest.getServletContext().getRealPath(uri); diff --git a/blade-core/src/main/java/com/blade/web/http/ResponsePrint.java b/blade-core/src/main/java/com/blade/web/http/ResponsePrint.java index 0973a8a42..e55930a65 100644 --- a/blade-core/src/main/java/com/blade/web/http/ResponsePrint.java +++ b/blade-core/src/main/java/com/blade/web/http/ResponsePrint.java @@ -15,8 +15,13 @@ import blade.kit.FileKit; import blade.kit.StreamKit; +import com.blade.Blade; +import com.blade.Const; + public final class ResponsePrint { + private static boolean isDev = Blade.me().isDev(); + private ResponsePrint() { } @@ -28,13 +33,26 @@ private ResponsePrint() { */ public static void printError(Throwable err, int code, HttpServletResponse response){ err.printStackTrace(); - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final PrintWriter writer = new PrintWriter(baos); - err.printStackTrace(writer); - writer.close(); - response.setStatus(code); - InputStream body = new ByteArrayInputStream(baos.toByteArray()); - try { + try { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final PrintWriter writer = new PrintWriter(baos); + + // If the developer mode, the error output to the page + if(isDev){ + writer.println(String.format(HTML, err.getClass() + " : " + err.getMessage())); + writer.println(); + err.printStackTrace(writer); + writer.println(END); + } else { + if(code == 404){ + writer.write(err.getMessage()); + } else { + writer.write(Const.INTERNAL_ERROR); + } + } + writer.close(); + response.setStatus(code); + InputStream body = new ByteArrayInputStream(baos.toByteArray()); print(body, response.getOutputStream()); } catch (IOException e) { e.printStackTrace(); @@ -85,4 +103,11 @@ public static void printStatic(String uri, String realpath, HttpServletResponse } } + private static final String HTML = "Blade Framework Error Page" + + "" + + "

%s

";
+	
+	
+	private static final String END = "
Blade-" + Const.BLADE_VERSION + "(Blade Framework
"; + } diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java index 9d5217d50..1fc34e48a 100644 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java @@ -5,6 +5,7 @@ import com.blade.aop.AbstractMethodInterceptor; import com.blade.aop.annotation.AfterAdvice; import com.blade.aop.annotation.BeforeAdvice; +import com.blade.aop.intercept.MethodInvocation; public class TransactionInterceptor extends AbstractMethodInterceptor { @@ -19,6 +20,20 @@ public void beforeAdvice() { local.beginTransaction(); } + @Override + public Object invoke(MethodInvocation invocation) { + try { + return super.invoke(invocation); + } catch (Exception e) { + local.rollback(); + e.printStackTrace(); + } catch (Throwable e) { + local.rollback(); + e.printStackTrace(); + } + return null; + } + @AfterAdvice(expression = "@com.blade.plugin.tx.annotation.Transactional") public void afterAdvice() { local.commit(); diff --git a/pom.xml b/pom.xml index ee9ee83d6..20cb34a13 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.5.1-beta + 1.5.1 4.12 From d07efae18d31ad17a0e94d8408263cd7f866e097 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 29 Dec 2015 16:04:47 +0800 Subject: [PATCH 368/545] update blade to 1.5.1 --- LAST_VERSION.md | 2 +- README.md | 4 +- README_CN.md | 4 +- .../main/java/com/blade/proxy/AopProxy.java | 18 +++++ .../src/main/java/com/blade/proxy/Aspect.java | 10 +++ .../java/com/blade/proxy/AspectFactory.java | 44 ++++++++++++ .../java/com/blade/proxy/AspectHandler.java | 70 +++++++++++++++++++ blade-tx/pom.xml | 56 +++++++-------- .../blade/plugin/tx/TransactionHolder.java | 6 +- 9 files changed, 180 insertions(+), 34 deletions(-) create mode 100644 blade-aop/src/main/java/com/blade/proxy/AopProxy.java create mode 100644 blade-aop/src/main/java/com/blade/proxy/Aspect.java create mode 100644 blade-aop/src/main/java/com/blade/proxy/AspectFactory.java create mode 100644 blade-aop/src/main/java/com/blade/proxy/AspectHandler.java diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 4e29d8d60..07d10f28b 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.5.1-beta +    1.5.1 ``` ## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) diff --git a/README.md b/README.md index 6cab9f635..205280e03 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Grab via `Maven`: com.bladejava blade-core - 1.5.1-beta + 1.5.1 com.bladejava @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ``` -compile 'com.bladejava:blade-core:1.5.1-beta' +compile 'com.bladejava:blade-core:1.5.1' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/README_CN.md b/README_CN.md index fbbc1a9b9..ffe4fff04 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,7 +38,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.5.1-beta + 1.5.1 com.bladejava @@ -50,7 +50,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 或者 `Gradle`: ``` -compile 'com.bladejava:blade-core:1.5.1-beta' +compile 'com.bladejava:blade-core:1.5.1' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/blade-aop/src/main/java/com/blade/proxy/AopProxy.java b/blade-aop/src/main/java/com/blade/proxy/AopProxy.java new file mode 100644 index 000000000..5b1766bd4 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/proxy/AopProxy.java @@ -0,0 +1,18 @@ +package com.blade.proxy; + +import java.util.ArrayList; +import java.util.List; + +public class AopProxy { + + private static final List INTERCEPTORS = new ArrayList(); + + public static void addInterceptor(Aspect aspect){ + INTERCEPTORS.add(aspect); + } + + public static T create(Class target){ + T obj = AspectFactory.newProxy(target, INTERCEPTORS); + return obj; + } +} diff --git a/blade-aop/src/main/java/com/blade/proxy/Aspect.java b/blade-aop/src/main/java/com/blade/proxy/Aspect.java new file mode 100644 index 000000000..89ffbbe84 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/proxy/Aspect.java @@ -0,0 +1,10 @@ +package com.blade.proxy; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +public interface Aspect { + + public Object aspect(InvocationHandler ih, Object proxy, Method method, Object[] args) throws Throwable; + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/proxy/AspectFactory.java b/blade-aop/src/main/java/com/blade/proxy/AspectFactory.java new file mode 100644 index 000000000..ac88ff418 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/proxy/AspectFactory.java @@ -0,0 +1,44 @@ +package com.blade.proxy; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.List; + +import blade.kit.ReflectKit; +import blade.kit.log.Logger; + +public class AspectFactory { + + private static final Logger logger = Logger.getLogger(AspectFactory.class); + + /** + * 私有构造方法 + */ + private AspectFactory() { + } + + /** + * 工厂方法 + * + * @param target + * 代理目标对象 + * @param aspects + * 切面集合 + */ + public static Object newInstance(Object target, List aspects) { + AspectHandler hander = new AspectHandler(target, aspects); + Class clazz = target.getClass(); + if (logger.isDebugEnabled()) { + logger.debug("Instance of " + clazz + "," + clazz.getInterfaces()); + } + return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), hander); + } + + public static T newProxy(Class target, List aspects) { + Object object = ReflectKit.newInstance(target); + AspectHandler handler = new AspectHandler(object, aspects); + + object = Proxy.newProxyInstance(target.getClassLoader(), new Class[] { target }, handler); + return target.cast(object); + } +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/proxy/AspectHandler.java b/blade-aop/src/main/java/com/blade/proxy/AspectHandler.java new file mode 100644 index 000000000..ab06cb85a --- /dev/null +++ b/blade-aop/src/main/java/com/blade/proxy/AspectHandler.java @@ -0,0 +1,70 @@ +package com.blade.proxy; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.List; + +import blade.kit.log.Logger; + +public class AspectHandler implements InvocationHandler { + + private static final Logger logger = Logger.getLogger(AspectHandler.class); + + private Object target = null; + private List aspects = null; + private int index = -1; + + public AspectHandler(int index, Object target, List aspects) { + this.index = index; + this.target = target; + this.aspects = aspects; + } + + public AspectHandler(Object target, List aspects) { + this.target = target; + this.aspects = aspects; + } + + + public Object getTarget() { + return target; + } + + + public void setTarget(Object target) { + this.target = target; + } + + public List getAspects() { + return aspects; + } + + + public void setAspects(List aspects) { + this.aspects = aspects; + } + + /** + * 委托方法 + * + * @param proxy 代理对象 + * @param method 代理方法 + * @param args 方法参数 + */ + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + if (index == -1) { + logger.info("Instance an AspectHandler to invoke method %s.", method.getName()); + return new AspectHandler(0, target, aspects).invoke(proxy, method, args); + } + Object result = null; + int len = aspects.size(); + if (index < len) { + result = aspects.get(index++).aspect(this, proxy, method, args); + } else if (index++ == len) { + result = method.invoke(target, args); + } + return result; + } + +} \ No newline at end of file diff --git a/blade-tx/pom.xml b/blade-tx/pom.xml index b1a837e9d..f30dbbb7f 100644 --- a/blade-tx/pom.xml +++ b/blade-tx/pom.xml @@ -1,28 +1,28 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - blade-tx - 1.0.0 - blade-tx - http://maven.apache.org - - - - com.bladejava - blade-core - ${blade.version} - - - com.bladejava - blade-aop - 1.0.0 - - - + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + blade-tx + 1.0.0 + blade-tx + http://maven.apache.org + + + + com.bladejava + blade-core + ${blade.version} + + + com.bladejava + blade-aop + 1.0.0 + + + diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java index 84e4363bb..8bfbc8434 100644 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java +++ b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java @@ -4,8 +4,12 @@ import javax.sql.DataSource; +import blade.kit.log.Logger; + public class TransactionHolder implements TransactionManager { + private static final Logger LOGGER = Logger.getLogger(TransactionHolder.class); + private static DataSource dataSource; public TransactionHolder(DataSource dataSource) { @@ -14,7 +18,7 @@ public TransactionHolder(DataSource dataSource) { private static final ThreadLocal tranManager = new ThreadLocal() { protected TransactionManager initialValue() { - System.out.println(this.toString() + "--Thread Local Initialize--"); + LOGGER.info("TransactionHolder Initialize"); return new TransactionManagerImpl(dataSource); } }; From f92a5c276ca63da8267a0d68105e3b75f26d9849 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 29 Dec 2015 16:08:17 +0800 Subject: [PATCH 369/545] update log --- UPDATE_LOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 7188f1321..9e01d9eff 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -5,6 +5,9 @@ 2. 修复模板引擎路径错误 3. 修复控制器注入对象失败 4. 添加request.model表单数据转JavaBean + 5. 修复CSRF验证bug + 6. 更友好的错误输出 + 7. 静态资源返回 ### v1.5.0 1. 优化路由寻址算法 From a9e5df892de2e8edfc5139bb10abde96b5220ca9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 30 Dec 2015 09:53:20 +0800 Subject: [PATCH 370/545] fix AsynRequestHandler broken bug --- blade-core/src/main/java/com/blade/Blade.java | 2 +- .../java/com/blade/annotation/Inject.java | 6 +- .../main/java/com/blade/ioc/Container.java | 20 +- .../java/com/blade/ioc/SampleContainer.java | 704 +++++++++--------- .../com/blade/web/AsynRequestHandler.java | 7 +- .../java/com/blade/web/DispatcherServlet.java | 2 +- 6 files changed, 340 insertions(+), 401 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 9151e905b..ae1345b4e 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -57,7 +57,7 @@ public class Blade { /** * Servlet asynchronous */ - private boolean isAsyn = true; + private boolean isAsyn = false; /** * Blade initialize config class diff --git a/blade-core/src/main/java/com/blade/annotation/Inject.java b/blade-core/src/main/java/com/blade/annotation/Inject.java index 02ad40d53..51dc624df 100644 --- a/blade-core/src/main/java/com/blade/annotation/Inject.java +++ b/blade-core/src/main/java/com/blade/annotation/Inject.java @@ -34,9 +34,5 @@ * @return The object to be injected into the Class */ Class value() default Class.class; - - /** - * @return To inject an object with a name - */ - String name() default ""; + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/Container.java b/blade-core/src/main/java/com/blade/ioc/Container.java index 505e5cda4..29b88a47c 100644 --- a/blade-core/src/main/java/com/blade/ioc/Container.java +++ b/blade-core/src/main/java/com/blade/ioc/Container.java @@ -93,14 +93,6 @@ public interface Container { */ boolean hasBean(String name); - /** - * Remove an bean object from the IOC container by name - * - * @param name to remove the bean object name - * @return return if remove success - */ - boolean removeBean(String name); - /** * Remove an bean object from the IOC container by name * @@ -122,14 +114,6 @@ public interface Container { */ boolean isRegister(Annotation[] annotations); - /** - * Register bean with a name - * @param name bean name - * @param value bean object - * @return return register bean - */ - Object registerBean(String name, Object value); - /** * Register an object to the bean container * @@ -147,11 +131,11 @@ public interface Container { * Inject a object * @param object to inject object */ - void injection(Object object); + void injection(Class clazz, Object object); /** * @return Returns the all bean objects in the IOC container */ - Map getBeanMap(); + Map, Object> getBeanMap(); } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java index e4b1c6efb..d014559c6 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java @@ -1,373 +1,333 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import blade.kit.Assert; -import blade.kit.CloneKit; -import blade.kit.CollectionKit; -import blade.kit.StringKit; -import blade.kit.log.Logger; - -import com.blade.annotation.Component; -import com.blade.annotation.Inject; -import com.blade.annotation.Path; - -/** - * IOC default implement - * - * @author biezhi - * @since 1.0 - */ -@SuppressWarnings("unchecked") -public class SampleContainer implements Container { - - private static final Logger LOGGER = Logger.getLogger(SampleContainer.class); - - /** - * Save all bean objects, e.g: com.xxxx.User @Userx7asc - */ - private Map beans = CollectionKit.newConcurrentHashMap(); - - /** - * All of the object storage and for class relations - */ - private Map beanKeys = CollectionKit.newConcurrentHashMap(); - - /** - * Save all the notes class - */ - private Map, List> annotaionBeans = CollectionKit.newConcurrentHashMap(); - - - public SampleContainer() { - } - - public Map getBeanMap() { - return beans; - } - - @Override - public T getBean(String name, Scope scope) { - Assert.notBlank(name); - String className = beanKeys.get(name); - if(StringKit.isBlank(className)){ - if(null == beans.get(name)){ - return null; - } else { - className = name; - } - } - - Object obj = beans.get(className); - if(null != scope && null != Scope.SINGLE){ - try { - return (T) CloneKit.deepClone(obj); - } catch (Exception e) { - throw new IocException("clone object error", e); - } - } - return (T) obj; - } - - @Override - public T getBean(Class type, Scope scope) { - Assert.notNull(type); - return this.getBean(type.getName(), scope); - } - - @Override - public Set getBeanNames() { - return beanKeys.keySet(); - } - - @Override - public Collection getBeans() { - return beans.values(); - } - - @Override - public boolean hasBean(Class clazz) { - Assert.notNull(clazz); - String className = clazz.getName(); - return beanKeys.containsValue(className); - } - - @Override - public boolean hasBean(String name) { - Assert.notBlank(name); - return null != beanKeys.get(name); - } - - @Override - public boolean removeBean(String name) { - Assert.notBlank(name); - String className = beanKeys.get(name); - if(StringKit.isBlank(className)){ - className = name; - } else { - beanKeys.remove(name); - } - beans.remove(className); - return true; - } - - @Override - public boolean removeBean(Class clazz) { - Assert.notNull(clazz); - return this.removeBean(clazz.getName()); - } - - @Override - public Object registerBean(String name, Object value) { - Assert.notBlank(name); - Assert.notNull(value); - - Class clazz = value.getClass(); - // Not abstract class, interface - if (isNormalClass(clazz)) { - - // If the container already exists, the name is directly returned - String className = beanKeys.get(name); - if (StringKit.isNotBlank(className)) { - return beans.get(className); - } - - className = clazz.getName(); - beanKeys.put(name, className); - if(null == beans.get(className)){ - beans.put(className, value); - } - - // Achieve the interface corresponding storage - Class[] interfaces = clazz.getInterfaces(); - if(interfaces.length > 0){ - for(Class interfaceClazz : interfaces){ - String clsName = interfaceClazz.getName(); - this.registerParent(clsName, value); - } - } - - // With annotation - if(null != clazz.getDeclaredAnnotations()){ - putAnnotationMap(clazz, value); - } - } - return value; - } - - private void registerParent(String name, Object value) { - - Assert.notBlank(name); - Assert.notNull(value); - - Class clazz = value.getClass(); - - // If the container already exists, the name is directly returned - String className = beanKeys.get(name); - if (StringKit.isNotBlank(className)) { - return; - } - className = clazz.getName(); - beanKeys.put(name, className); - if(null == beans.get(className)){ - beans.put(className, value); - } - } - - @Override - public Object registerBean(Object object) { - - Assert.notNull(object); - - String className = object.getClass().getName(); - return registerBean(className, object); - } - - /** - * Add elements to annotationMap - * - * @param clazz class type to be injected - * @param object registered bean object - */ - private void putAnnotationMap(Class clazz, Object object){ - - Annotation[] annotations = clazz.getAnnotations(); - List listObject = null; - for(Annotation annotation : annotations){ - if(null != annotation){ - listObject = annotaionBeans.get(annotation.annotationType()); - if(CollectionKit.isEmpty(listObject)){ - listObject = CollectionKit.newArrayList(); - } - listObject.add(object); - this.put(annotation.annotationType(), listObject); - } - } - } - - /** - * AnnotationBean container storage - * - * @param clazz allows the Annotation type to be registered - * @param listObject list of objects to be injected - */ - private void put(Class clazz, List listObject){ - if(null == annotaionBeans.get(clazz)){ - annotaionBeans.put(clazz, listObject); - } - } - - /** - * Initialization injection - */ - @Override - public void initWired() throws RuntimeException { - - Set keys = beans.keySet(); - for(String className : keys){ - Object object = beans.get(className); - injection(object); - } - } - - // Assemble - private Object recursiveAssembly(Class clazz){ - Object field = null; - if(null != clazz){ - String className = beanKeys.get(clazz.getName()); - field = beans.get(className); - } - return field; - } - - - /** - * To determine whether the bean can be registered - * - * @param annotations annotation class type arrays - * @return return is register - */ - @Override - public boolean isRegister(Annotation[] annotations) { - if (null == annotations || annotations.length == 0) { - return false; - } - for (Annotation annotation : annotations) { - if (annotation instanceof Component || annotation instanceof Path) { - return true; - } - } - return false; - } - - /** - * Is not interface and abstract class Class - * @param clazz class type - * @return return is interface && abstract class - */ - private boolean isNormalClass(Class clazz){ - if(!Modifier.isAbstract(clazz.getModifiers()) && !clazz.isInterface()){ - return true; - } - return false; - } - - @Override - public List> getClassesByAnnotation(Class annotation) { - List objectList = getBeansByAnnotation(annotation); - if(!CollectionKit.isEmpty(objectList)){ - List> classList = CollectionKit.newArrayList(objectList.size()); - for(Object object : objectList){ - classList.add(object.getClass()); - } - return classList; - } - return null; - } - - @Override - public List getBeansByAnnotation(Class annotation) { - return (List) annotaionBeans.get(annotation); - } - - @Override - public boolean removeAll() { - beanKeys.clear(); - beans.clear(); - annotaionBeans.clear(); - return true; - } - - @Override - public void injection(Object object) { - // Traverse all fields - try { - Field[] fields = object.getClass().getDeclaredFields(); - for (Field field : fields) { - // Need to inject the field - Inject inject = field.getAnnotation(Inject.class); - if (null != inject ) { - // Bean to be injected - Object injectField = null; - String name = inject.name(); - if(!name.equals("")){ - String className = beanKeys.get(name); - if(null != className && !className.equals("")){ - injectField = beans.get(className); - } - if (null == injectField) { - throw new RuntimeException("Unable to load " + name); - } - } else { - if(inject.value() == Class.class){ - injectField = recursiveAssembly(field.getType()); - } else { - // Specify an assembly - injectField = this.getBean(inject.value(), null); - if (null == injectField) { - injectField = recursiveAssembly(inject.value()); - } - } - } - - if (null == injectField) { - throw new RuntimeException("Unable to load " + field.getType().getName() + "!"); - } - - boolean accessible = field.isAccessible(); - field.setAccessible(true); - field.set(object, injectField); - field.setAccessible(accessible); - } - } - } catch (SecurityException e) { - LOGGER.error(e); - } catch (IllegalArgumentException e) { - LOGGER.error(e); - } catch (IllegalAccessException e) { - LOGGER.error(e); - } - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import blade.kit.Assert; +import blade.kit.CloneKit; +import blade.kit.CollectionKit; +import blade.kit.log.Logger; + +import com.blade.annotation.Component; +import com.blade.annotation.Inject; +import com.blade.annotation.Path; + +/** + * IOC default implement + * + * @author biezhi + * @since 1.0 + */ +@SuppressWarnings("unchecked") +public class SampleContainer implements Container { + + private static final Logger LOGGER = Logger.getLogger(SampleContainer.class); + + /** + * Save all bean objects, e.g: com.xxxx.User @Userx7asc + */ + private Map, Object> beans = CollectionKit.newConcurrentHashMap(); + + /** + * Save all the notes class + */ + private Map, List> annotaionBeans = CollectionKit.newConcurrentHashMap(); + + + public SampleContainer() { + } + + public Map, Object> getBeanMap() { + return beans; + } + + @Override + public T getBean(String name, Scope scope) { + Assert.notBlank(name); + try { + Class clazz = (Class) Class.forName(name); + return getBean(clazz, scope); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public T getBean(Class type, Scope scope) { + Assert.notNull(type); + + Object obj = beans.get(type); + if(null != scope && null != Scope.SINGLE){ + try { + return (T) CloneKit.deepClone(obj); + } catch (Exception e) { + throw new IocException("clone object error", e); + } + } + return type.cast(obj); + } + + @Override + public Set getBeanNames() { + Set> classes = beans.keySet(); + if(null != classes){ + Set beanNames = new HashSet(classes.size()); + for(Class clazz : classes){ + beanNames.add(clazz.getName()); + } + return beanNames; + } + return new HashSet(0); + } + + @Override + public Collection getBeans() { + return beans.values(); + } + + @Override + public boolean hasBean(Class clazz) { + if(null != clazz){ + return beans.get(clazz) != null; + } + return false; + } + + @Override + public boolean hasBean(String name) { + try { + Class clazz = Class.forName(name); + return hasBean(clazz); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return false; + } + + @Override + public boolean removeBean(Class clazz) { + if(null != clazz && beans.containsKey(clazz)){ + beans.remove(clazz); + return true; + } + return false; + } + + private void registerParent(Class clazz, Object value) { + if(!beans.containsKey(clazz)){ + beans.put(clazz, value); + } + } + + @Override + public Object registerBean(Object value) { + if(null != value){ + Class clazz = value.getClass(); + // Not abstract class, interface + if (isNormalClass(clazz)) { + + // If the container already exists, the name is directly returned + if(beans.containsKey(clazz)){ + return beans.get(clazz); + } + + beans.put(clazz, value); + + // Achieve the interface corresponding storage + Class[] interfaces = clazz.getInterfaces(); + if(interfaces.length > 0){ + for(Class interfaceClazz : interfaces){ + this.registerParent(interfaceClazz, value); + } + } + + // With annotation + if(null != clazz.getDeclaredAnnotations()){ + putAnnotationMap(clazz, value); + } + return value; + } + } + return null; + } + + /** + * Add elements to annotationMap + * + * @param clazz class type to be injected + * @param object registered bean object + */ + private void putAnnotationMap(Class clazz, Object object){ + + Annotation[] annotations = clazz.getAnnotations(); + List listObject = null; + for(Annotation annotation : annotations){ + if(null != annotation){ + listObject = annotaionBeans.get(annotation.annotationType()); + if(CollectionKit.isEmpty(listObject)){ + listObject = CollectionKit.newArrayList(); + } + listObject.add(object); + this.put(annotation.annotationType(), listObject); + } + } + } + + /** + * AnnotationBean container storage + * + * @param clazz allows the Annotation type to be registered + * @param listObject list of objects to be injected + */ + private void put(Class clazz, List listObject){ + if(null == annotaionBeans.get(clazz)){ + annotaionBeans.put(clazz, listObject); + } + } + + /** + * Initialization injection + */ + @Override + public void initWired() throws RuntimeException { + + Set> keys = beans.keySet(); + for(Class clazz : keys){ + Object object = beans.get(clazz); + injection(clazz, object); + } + } + + // Assemble + private Object recursiveAssembly(Class clazz){ + if(null != clazz && beans.containsKey(clazz)){ + return beans.get(clazz); + } + return null; + } + + + /** + * To determine whether the bean can be registered + * + * @param annotations annotation class type arrays + * @return return is register + */ + @Override + public boolean isRegister(Annotation[] annotations) { + if (null == annotations || annotations.length == 0) { + return false; + } + for (Annotation annotation : annotations) { + if (annotation instanceof Component || annotation instanceof Path) { + return true; + } + } + return false; + } + + /** + * Is not interface and abstract class Class + * @param clazz class type + * @return return is interface && abstract class + */ + private boolean isNormalClass(Class clazz){ + if(!Modifier.isAbstract(clazz.getModifiers()) && !clazz.isInterface()){ + return true; + } + return false; + } + + @Override + public List> getClassesByAnnotation(Class annotation) { + List objectList = getBeansByAnnotation(annotation); + if(!CollectionKit.isEmpty(objectList)){ + List> classList = CollectionKit.newArrayList(objectList.size()); + for(Object object : objectList){ + classList.add(object.getClass()); + } + return classList; + } + return null; + } + + @Override + public List getBeansByAnnotation(Class annotation) { + return (List) annotaionBeans.get(annotation); + } + + @Override + public boolean removeAll() { + beans.clear(); + annotaionBeans.clear(); + return true; + } + + @Override + public void injection(Class clazz, Object object) { + + if(null == clazz || null == object){ + return; + } + + // Traverse all fields + try { + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + // Need to inject the field + Inject inject = field.getAnnotation(Inject.class); + if (null != inject ) { + // Bean to be injected + Object injectField = null; + if(inject.value() == Class.class){ + injectField = recursiveAssembly(field.getType()); + } else { + // Specify an assembly + injectField = this.getBean(inject.value(), null); + if (null == injectField) { + injectField = recursiveAssembly(inject.value()); + } + } + + if (null == injectField) { + throw new RuntimeException("Unable to load " + field.getType().getName() + "!"); + } + + boolean accessible = field.isAccessible(); + field.setAccessible(true); + field.set(object, injectField); + field.setAccessible(accessible); + } + } + } catch (SecurityException e) { + LOGGER.error(e); + } catch (IllegalArgumentException e) { + LOGGER.error(e); + } catch (IllegalAccessException e) { + LOGGER.error(e); + } + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index b893dba6a..5d27977c3 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -126,11 +126,10 @@ public void run(){ invokeInterceptor(request, response, afters); } } - return; + } else { + // Not found + render404(response, uri); } - - // Not found - render404(response, uri); asyncContext.complete(); return; } catch (Exception e) { diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index e1d21fe6a..5314188ac 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -81,7 +81,7 @@ public void init(Blade blade) { } blade.app(bootstrap); } - bootstrap.init(blade); + blade.bootstrap().init(blade); // buiding route new RouteBuilder(blade).building(); From 104af19f1f69a41622dbe42ea91046b6755e83bb Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 30 Dec 2015 11:02:24 +0800 Subject: [PATCH 371/545] update readme --- README.md | 10 +++++----- README_CN.md | 4 ++-- blade-core/src/main/java/com/blade/Const.java | 2 +- .../com/blade/web/AsynRequestHandler.java | 15 +------------- .../com/blade/web/SyncRequestHandler.java | 20 ++++--------------- 5 files changed, 13 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 205280e03..0e378d977 100644 --- a/README.md +++ b/README.md @@ -34,20 +34,20 @@ To get started, first [include the Blade library](http://bladejava.com/docs/intr Grab via `Maven`: -```sh +```xml com.bladejava blade-core 1.5.1 - com.bladejava - blade-startup - 1.0.1 + com.bladejava + blade-startup + 1.0.1 ``` or `Gradle`: -``` +```sh compile 'com.bladejava:blade-core:1.5.1' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/README_CN.md b/README_CN.md index ffe4fff04..176c0e7de 100644 --- a/README_CN.md +++ b/README_CN.md @@ -34,7 +34,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 `Maven` 配置: -```sh +```xml com.bladejava blade-core @@ -49,7 +49,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 或者 `Gradle`: -``` +```sh compile 'com.bladejava:blade-core:1.5.1' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 0a4267d1d..c468bf22d 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * Current version */ - String BLADE_VERSION = "1.5.1"; + String BLADE_VERSION = "1.5.2-alpha"; /** * Server 500 error HTML diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index 5d27977c3..622251b22 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -24,7 +24,6 @@ import javax.servlet.http.HttpServletResponse; import blade.kit.StringKit; -import blade.kit.base.ThrowableKit; import blade.kit.log.Logger; import com.blade.Blade; @@ -133,20 +132,8 @@ public void run(){ asyncContext.complete(); return; } catch (Exception e) { - String error = ThrowableKit.getStackTraceAsString(e); - LOGGER.error(error); - ThrowableKit.propagate(e); - - httpResponse.setStatus(500); - // Write content to the browser - if (!httpResponse.isCommitted()) { - response.html(Const.INTERNAL_ERROR); - asyncContext.complete(); - return; - } + ResponsePrint.printError(e, 500, httpResponse); } - asyncContext.complete(); - return; } /** diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index 3896e9bcd..9800e9922 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -23,7 +23,6 @@ import javax.servlet.http.HttpServletResponse; import blade.kit.StringKit; -import blade.kit.base.ThrowableKit; import blade.kit.log.Logger; import com.blade.Blade; @@ -115,24 +114,13 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo invokeInterceptor(request, response, afters); } } - return; + } else { + // Not found + render404(response, uri); } - - // Not found - render404(response, uri); return; } catch (Exception e) { - - String error = ThrowableKit.getStackTraceAsString(e); - LOGGER.error(error); - ThrowableKit.propagate(e); - - httpResponse.setStatus(500); - // Write content to the browser - if (!httpResponse.isCommitted()) { - response.html(Const.INTERNAL_ERROR); - return; - } + ResponsePrint.printError(e, 500, httpResponse); } return; } From d075309a4c344be780730ddff63df944f864e919 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 30 Dec 2015 11:38:26 +0800 Subject: [PATCH 372/545] modify comment --- blade-core/src/main/java/com/blade/Blade.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index ae1345b4e..8b3257398 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -313,14 +313,13 @@ public Blade route(String path, Object target, String method, HttpMethod httpMet } /** - * 注册一个函数式的路由 - * 方法上指定请求类型(同时指定HttpMethod的方式是:post:saveUser,如不指定则为HttpMethod.ALL) - * - * @param path 路由url - * @param clazz 路由处理类 - * @param method 路由处理方法名称 - * @return Blade 返回Blade单例实例 - */ + * Add a route + * + * @param path route path + * @param target Target object for routing + * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade + */ public Blade route(String path, Class clazz, String method){ routers.route(path, clazz, method); return this; From 8ae3615868e225b400523128b894379dc04193b1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 30 Dec 2015 13:08:52 +0800 Subject: [PATCH 373/545] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0e378d977..089fcb67f 100644 --- a/README.md +++ b/README.md @@ -188,11 +188,11 @@ public Long getUserCount(String email){ You may refer to these examples for additional guidance: -+ [Hello](https://github.com/blade-samples/hello) ++ [Hello Blade](https://github.com/blade-samples/hello) + [API Doc](http://bladejava.com/apidocs) + [User Guide](http://bladejava.com/docs) ++ [Version Changes](LAST_VERSION.md) + [Examples](https://github.com/blade-samples) -+ [Version](LAST_VERSION.md) ## Plan From 65a54e3f60eab3750cd99887fb5335457e2ce64c Mon Sep 17 00:00:00 2001 From: Jie Shen <1993sj1993@gmail.com> Date: Wed, 30 Dec 2015 15:20:50 +0800 Subject: [PATCH 374/545] Change missing Chinese comments in blade-core package. --- blade-core/src/main/java/com/blade/IocApplication.java | 4 ++-- blade-core/src/main/java/com/blade/render/VelocityRender.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index 88ea1ead3..ea022add0 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -119,7 +119,7 @@ private void registerBean(String packageName) { // Scan package all class Set> classes = classReader.getClass(packageName, recursive); for (Class clazz : classes) { - // 注册带有Component和Service注解的类 + // Register classes with annotation of @Component or @Service if (container.isRegister(clazz.getAnnotations())) { container.registerBean(Aop.create(clazz)); } @@ -134,7 +134,7 @@ public List getPlugins() { * destroy */ public void destroy() { - // clean ioc container + // Clean IOC container container.removeAll(); for(Plugin plugin : plugins){ plugin.destroy(); diff --git a/blade-core/src/main/java/com/blade/render/VelocityRender.java b/blade-core/src/main/java/com/blade/render/VelocityRender.java index 671868f31..9ac758ed3 100644 --- a/blade-core/src/main/java/com/blade/render/VelocityRender.java +++ b/blade-core/src/main/java/com/blade/render/VelocityRender.java @@ -87,7 +87,7 @@ public VelocityRender(String propertiesFile) throws IOException { /** * According to the construction of a Velocity engine * - * @param properties Properties配置文件 + * @param properties Properties document */ public VelocityRender(Properties properties) { Blade blade = Blade.me(); From 966eb53a6e6f1f11347b4a488c6fee3453703e2a Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 30 Dec 2015 16:23:21 +0800 Subject: [PATCH 375/545] update readme --- README.md | 6 ++---- README_CN.md | 2 -- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 089fcb67f..ec4472961 100644 --- a/README.md +++ b/README.md @@ -120,15 +120,13 @@ public static void main(String[] args) { ```java public void upload_img(Request request, Response response){ - - JsonObject jsonObject = new JsonObject(); - + FileItem[] fileItems = request.files(); if(null != fileItems && fileItems.length > 0){ FileItem fileItem = fileItems[0]; File file = fileItem.getFile(); - + String fileRealPath = "your upload file path!"; nioTransferCopy(file, fileRealPath); diff --git a/README_CN.md b/README_CN.md index 176c0e7de..02de17f25 100644 --- a/README_CN.md +++ b/README_CN.md @@ -119,8 +119,6 @@ public static void main(String[] args) { ```java public void upload_img(Request request, Response response){ - - JsonObject jsonObject = new JsonObject(); FileItem[] fileItems = request.files(); if(null != fileItems && fileItems.length > 0){ From 1ab37d8a0b997f6ff0104c5fc62ac6630607c668 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 30 Dec 2015 16:26:14 +0800 Subject: [PATCH 376/545] update readme --- README_CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_CN.md b/README_CN.md index 02de17f25..c55841e26 100644 --- a/README_CN.md +++ b/README_CN.md @@ -102,7 +102,7 @@ public static void main(String[] args) { } ``` -## Form URL参数获取 +## 表单参数获取 ```java public static void main(String[] args) { From 7988e6e89cd8a4bf7c03d3c49c93f52217324df1 Mon Sep 17 00:00:00 2001 From: "Fan, Wen(wfan1)" Date: Tue, 5 Jan 2016 22:53:20 +0800 Subject: [PATCH 377/545] fix the bug of listToHeavy --- blade-kit/src/main/java/blade/kit/CollectionKit.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-kit/src/main/java/blade/kit/CollectionKit.java b/blade-kit/src/main/java/blade/kit/CollectionKit.java index 7af5afa44..8a6494e4b 100644 --- a/blade-kit/src/main/java/blade/kit/CollectionKit.java +++ b/blade-kit/src/main/java/blade/kit/CollectionKit.java @@ -1305,7 +1305,7 @@ public static String[] arrayToHeavy(String[] arr){ public static List listToHeavy(List list){ Set set = new HashSet(list); list.clear(); - list.removeAll(set); + list.addAll(set); return list; } From d46ff2d155bb8bb272ce40995036497a88a60909 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 18 Jan 2016 15:51:51 +0800 Subject: [PATCH 378/545] fix trim match bug --- blade-kit/src/main/java/blade/kit/StringKit.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/StringKit.java b/blade-kit/src/main/java/blade/kit/StringKit.java index 1f406731f..a63434ee9 100644 --- a/blade-kit/src/main/java/blade/kit/StringKit.java +++ b/blade-kit/src/main/java/blade/kit/StringKit.java @@ -2603,6 +2603,5 @@ public static String toString(Collection collection, String split) { builder.setLength(builder.length() - split.length()); return builder.toString(); } - - + } From da743c073254cf5a668148d6f3d3d77c5f42089c Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 18 Jan 2016 15:58:46 +0800 Subject: [PATCH 379/545] Update StringKit.java --- blade-kit/src/main/java/blade/kit/StringKit.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/StringKit.java b/blade-kit/src/main/java/blade/kit/StringKit.java index a63434ee9..91ade75ae 100644 --- a/blade-kit/src/main/java/blade/kit/StringKit.java +++ b/blade-kit/src/main/java/blade/kit/StringKit.java @@ -542,7 +542,7 @@ private static String trim(String str, String stripChars, int mode) { } else if (stripChars.length() == 0) { return str; } else { - while ((start < end) && (stripChars.indexOf(str.charAt(start)) != -1)) { + while ((start < end) && (str.startsWith(stripChars) && stripChars.indexOf(str.charAt(start)) != -1)) { start++; } } @@ -557,7 +557,7 @@ private static String trim(String str, String stripChars, int mode) { } else if (stripChars.length() == 0) { return str; } else { - while ((start < end) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) { + while ((start < end) && (str.endsWith(stripChars) && stripChars.indexOf(str.charAt(end - 1)) != -1)) { end--; } } From 709f1960387fd8d38693bdf1153cbe1835ec7070 Mon Sep 17 00:00:00 2001 From: ScienJus Date: Sun, 24 Jan 2016 19:09:31 +0800 Subject: [PATCH 380/545] fixed bug(?) --- .../java/blade/plugin/redis/RedisExecutor.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java b/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java index 272f148cc..989fbf480 100644 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java +++ b/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java @@ -1,13 +1,7 @@ package blade.plugin.redis; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPubSub; @@ -91,10 +85,10 @@ public ShardedJedis getShardedJedis(){ } /** - * 删除模糊匹配的key + * 获取模糊匹配的key * * @param likeKey 模糊匹配的key - * @return 删除成功的条数 + * @return 匹配key的集合 */ public Set getKeyLike(final String likeKey) { return new Executor>(shardedJedisPool) { @@ -103,10 +97,10 @@ public Set getKeyLike(final String likeKey) { Set execute() { Collection jedisC = jedis.getAllShards(); Iterator iter = jedisC.iterator(); - Set keys = null; + Set keys = new HashSet(); while (iter.hasNext()) { Jedis _jedis = iter.next(); - keys = _jedis.keys(likeKey + "*"); + keys.addAll(_jedis.keys(likeKey + "*")); } return keys; } From 29a28c18c021966cdc668f878b467e492fd3339b Mon Sep 17 00:00:00 2001 From: ScienJus Date: Sun, 24 Jan 2016 22:28:41 +0800 Subject: [PATCH 381/545] remove deprecated method --- .../src/main/java/blade/plugin/redis/RedisExecutor.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java b/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java index 989fbf480..b25fedfc0 100644 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java +++ b/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java @@ -58,19 +58,18 @@ public Executor(ShardedJedisPool shardedJedisPool) { * * @return 执行结果 */ - @SuppressWarnings("deprecation") public T getResult() { T result = null; try { result = execute(); } catch (Throwable e) { if (null != jedis) { - shardedJedisPool.returnResourceObject(jedis); + jedis.close(); } throw new RuntimeException("Redis execute exception", e); } finally { if (null != jedis) { - shardedJedisPool.returnResourceObject(jedis); + jedis.close(); } } return result; From 26e6f4b73561e355d8687e23020df809f7ae8144 Mon Sep 17 00:00:00 2001 From: ScienJus Date: Sun, 24 Jan 2016 23:00:10 +0800 Subject: [PATCH 382/545] use SCAN instead of KEYS --- .../blade/plugin/redis/RedisExecutor.java | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java b/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java index b25fedfc0..fc4d89cfc 100644 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java +++ b/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java @@ -3,14 +3,7 @@ import java.io.Serializable; import java.util.*; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPubSub; -import redis.clients.jedis.Pipeline; -import redis.clients.jedis.Response; -import redis.clients.jedis.ShardedJedis; -import redis.clients.jedis.ShardedJedisPipeline; -import redis.clients.jedis.ShardedJedisPool; -import redis.clients.jedis.Transaction; +import redis.clients.jedis.*; import redis.clients.util.SafeEncoder; import blade.kit.SerializeKit; @@ -91,6 +84,7 @@ public ShardedJedis getShardedJedis(){ */ public Set getKeyLike(final String likeKey) { return new Executor>(shardedJedisPool) { + final String pattern = likeKey + "*"; @Override Set execute() { @@ -99,7 +93,15 @@ Set execute() { Set keys = new HashSet(); while (iter.hasNext()) { Jedis _jedis = iter.next(); - keys.addAll(_jedis.keys(likeKey + "*")); + String cursor = "0"; + while (true) { + ScanResult result = _jedis.scan(cursor, new ScanParams().match(pattern)); + keys.addAll(result.getResult()); + cursor = result.getStringCursor(); + if ("0".equals(cursor)) { + break; + } + } } return keys; } @@ -113,6 +115,8 @@ Set execute() { * @return 删除成功的条数 */ public long delKeysLike(final String likeKey) { + final String pattern = likeKey + "*"; + return new Executor(shardedJedisPool) { @Override @@ -122,7 +126,16 @@ Long execute() { long count = 0; while (iter.hasNext()) { Jedis _jedis = iter.next(); - Set keys = _jedis.keys(likeKey + "*"); + Set keys = new HashSet(); + String cursor = "0"; + while (true) { + ScanResult result = _jedis.scan(cursor, new ScanParams().match(pattern)); + keys.addAll(result.getResult()); + cursor = result.getStringCursor(); + if ("0".equals(cursor)) { + break; + } + } count += _jedis.del(keys.toArray(new String[keys.size()])); } return count; @@ -879,7 +892,7 @@ Long execute() { * 将一个或多个值 value 插入到列表 key 的表头 * * @param key key - * @param value string value + * @param values string value * @return 执行 listPushHead 命令后,列表的长度。 */ public Long listPushHead(final String key, final String... values) { From ef34f8dd08ed97e520fb480aa3c648c64d3e8b62 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 18:40:13 +0800 Subject: [PATCH 383/545] reconstruction ioc --- blade-core/src/main/java/com/blade/Aop.java | 84 ----- blade-core/src/main/java/com/blade/Blade.java | 37 +- .../main/java/com/blade/IocApplication.java | 40 +-- .../com/blade/annotation/package-info.java | 4 - .../main/java/com/blade/ioc/AopCreator.java | 47 --- .../main/java/com/blade/ioc/BeanDefine.java | 67 ++++ .../main/java/com/blade/ioc/Container.java | 141 -------- .../src/main/java/com/blade/ioc/Ioc.java | 36 ++ .../main/java/com/blade/ioc/IocException.java | 15 + .../src/main/java/com/blade/ioc/IocKit.java | 69 ++++ .../java/com/blade/ioc/SampleContainer.java | 333 ------------------ .../main/java/com/blade/ioc/SampleIoc.java | 135 +++++++ .../blade/{ => ioc}/annotation/Component.java | 6 +- .../blade/{ => ioc}/annotation/Inject.java | 7 +- .../blade/ioc/loader/IocAnnotationLoader.java | 68 ++++ .../ioc/{Scope.java => loader/IocLoader.java} | 49 ++- .../loader/ClassPathControllerLoader.java | 12 +- .../java/com/blade/route/RouteBuilder.java | 27 +- .../main/java/com/blade/route/Routers.java | 36 +- .../blade/{ => route}/annotation/After.java | 2 +- .../blade/{ => route}/annotation/Before.java | 2 +- .../{ => route}/annotation/Interceptor.java | 2 +- .../blade/{ => route}/annotation/Path.java | 2 +- .../blade/{ => route}/annotation/Route.java | 2 +- .../blade/route/annotation/package-info.java | 4 + .../com/blade/web/AsynRequestHandler.java | 2 +- .../java/com/blade/web/DispatcherServlet.java | 20 +- .../com/blade/web/SyncRequestHandler.java | 2 +- 28 files changed, 512 insertions(+), 739 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/Aop.java delete mode 100644 blade-core/src/main/java/com/blade/annotation/package-info.java delete mode 100644 blade-core/src/main/java/com/blade/ioc/AopCreator.java create mode 100644 blade-core/src/main/java/com/blade/ioc/BeanDefine.java delete mode 100644 blade-core/src/main/java/com/blade/ioc/Container.java create mode 100644 blade-core/src/main/java/com/blade/ioc/Ioc.java create mode 100644 blade-core/src/main/java/com/blade/ioc/IocKit.java delete mode 100644 blade-core/src/main/java/com/blade/ioc/SampleContainer.java create mode 100644 blade-core/src/main/java/com/blade/ioc/SampleIoc.java rename blade-core/src/main/java/com/blade/{ => ioc}/annotation/Component.java (88%) rename blade-core/src/main/java/com/blade/{ => ioc}/annotation/Inject.java (88%) create mode 100644 blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java rename blade-core/src/main/java/com/blade/ioc/{Scope.java => loader/IocLoader.java} (68%) rename blade-core/src/main/java/com/blade/{ => route}/annotation/After.java (93%) rename blade-core/src/main/java/com/blade/{ => route}/annotation/Before.java (93%) rename blade-core/src/main/java/com/blade/{ => route}/annotation/Interceptor.java (94%) rename blade-core/src/main/java/com/blade/{ => route}/annotation/Path.java (93%) rename blade-core/src/main/java/com/blade/{ => route}/annotation/Route.java (95%) create mode 100644 blade-core/src/main/java/com/blade/route/annotation/package-info.java diff --git a/blade-core/src/main/java/com/blade/Aop.java b/blade-core/src/main/java/com/blade/Aop.java deleted file mode 100644 index aaa194c77..000000000 --- a/blade-core/src/main/java/com/blade/Aop.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import com.blade.ioc.AopCreator; - -import blade.kit.Assert; -import blade.kit.ReflectKit; - -/** - * As the basis for AOP, used to create objects - * - * @author biezhi - * @since 1.0 - */ -@SuppressWarnings("unchecked") -public final class Aop { - - private static boolean AOP_OPEN = false; - - static{ - try { - Class.forName("com.blade.aop.AopProxy"); - AOP_OPEN = true; - } catch (ClassNotFoundException e) { - AOP_OPEN = false; - } - } - - public static Object create(Class clazz){ - Assert.notNull(clazz); - if(AOP_OPEN){ - return AopCreator.create(clazz); - } else { - try { - return ReflectKit.newInstance(clazz); - } catch (Exception e) { - new RuntimeException("create object error", e); - } - } - return null; - } - - public static T createT(Class clazz){ - Assert.notNull(clazz); - if(AOP_OPEN){ - return AopCreator.create(clazz); - } else { - try { - Object object = ReflectKit.newInstance(clazz); - if(null != object){ - return (T) object; - } - } catch (Exception e) { - new RuntimeException("create object error", e); - } - } - return null; - } - - public static Object create(String className){ - try { - Class clazz = Class.forName(className); - return create(clazz); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - return null; - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 8b3257398..2160f2875 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -21,13 +21,8 @@ import java.util.List; import java.util.Map; -import blade.kit.Assert; -import blade.kit.IOKit; -import blade.kit.PropertyKit; -import blade.kit.json.JSONKit; - -import com.blade.ioc.Container; -import com.blade.ioc.SampleContainer; +import com.blade.ioc.Ioc; +import com.blade.ioc.SampleIoc; import com.blade.loader.ClassPathRouteLoader; import com.blade.loader.Config; import com.blade.loader.Configurator; @@ -41,6 +36,11 @@ import com.blade.server.Server; import com.blade.web.http.HttpMethod; +import blade.kit.Assert; +import blade.kit.IOKit; +import blade.kit.PropertyKit; +import blade.kit.json.JSONKit; + /** * Blade Core Class * @@ -72,7 +72,7 @@ public class Blade { /** * IOC Container, save javabean */ - private Container container = null; + private Ioc ioc = null; /** * ioc application object @@ -101,9 +101,9 @@ public class Blade { private Blade() { this.config = new Config(); - this.container = new SampleContainer(); - this.iocApplication = new IocApplication(container); - this.routers = new Routers(container); + this.ioc = new SampleIoc(); + this.iocApplication = new IocApplication(ioc); + this.routers = new Routers(ioc); this.render = new JspRender(); } @@ -145,8 +145,8 @@ public Routers routers() { /** * @return return blade ioc container */ - public Container container(){ - return container; + public Ioc ioc(){ + return ioc; } /** @@ -154,9 +154,9 @@ public Container container(){ * @param container ioc object * @return return blade */ - public Blade container(Container container){ - Assert.notNull(container); - this.container = container; + public Blade container(Ioc ioc){ + Assert.notNull(ioc); + this.ioc = ioc; return this; } @@ -543,8 +543,7 @@ public Blade app(Bootstrap bootstrap){ */ public Blade app(Class bootstrap){ Assert.notNull(bootstrap); - Object object = container.registerBean(Aop.create(bootstrap)); - this.bootstrap = (Bootstrap) object; + ioc.addBean(bootstrap); return this; } @@ -754,7 +753,7 @@ public String[] staticFolder(){ * @return Return bootstrap object */ public Bootstrap bootstrap(){ - return bootstrap; + return ioc.getBean(Bootstrap.class); } /** diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index ea022add0..8b0e56ab0 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -19,14 +19,13 @@ import java.util.List; import java.util.Set; +import com.blade.ioc.Ioc; +import com.blade.plugin.Plugin; + import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; -import com.blade.ioc.Container; -import com.blade.ioc.Scope; -import com.blade.plugin.Plugin; - /** * IOC container, used to initialize the IOC object * @@ -40,7 +39,7 @@ public class IocApplication { /** * Ioc Container */ - private Container container = null; + private Ioc ioc = null; /** * Class to read object, load class @@ -52,10 +51,10 @@ public class IocApplication { */ private List plugins = null; - public IocApplication(Container container) { + public IocApplication(Ioc ioc) { this.classReader = new ClassPathClassReader(); this.plugins = new ArrayList(); - this.container = container; + this.ioc = ioc; } /** @@ -66,8 +65,8 @@ public IocApplication(Container container) { public void init(String[] iocs, Bootstrap bootstrap){ // Initialize the global configuration class - if(null == container.getBean(Bootstrap.class, Scope.SINGLE)){ - container.registerBean(bootstrap); + if(null == ioc.getBean(Bootstrap.class)){ + ioc.addBean(bootstrap); } // The object to initialize the IOC container loads the IOC package to configure the class that conforms to the IOC @@ -78,26 +77,25 @@ public void init(String[] iocs, Bootstrap bootstrap){ } // Initialization injection - container.initWired(); +// container.initWired(); - Set names = container.getBeanNames(); + Set names = ioc.getBeanNames(); for(String name : names){ - LOGGER.info("Add Object:" + name + "=" + container.getBean(name, null)); + LOGGER.info("Add Object:" + name + "=" + ioc.getBean(name)); } } - @SuppressWarnings("unchecked") public T registerPlugin(Class plugin){ - Object object = container.registerBean(Aop.create(plugin)); - T t = (T) object; + ioc.addBean(plugin); + T t = ioc.getBean(plugin); plugins.add(t); return t; } public T getPlugin(Class plugin){ - if(null != plugin && null != container){ - return container.getBean(plugin, null); + if(null != plugin && null != ioc){ + return ioc.getBean(plugin); } return null; } @@ -119,10 +117,8 @@ private void registerBean(String packageName) { // Scan package all class Set> classes = classReader.getClass(packageName, recursive); for (Class clazz : classes) { - // Register classes with annotation of @Component or @Service - if (container.isRegister(clazz.getAnnotations())) { - container.registerBean(Aop.create(clazz)); - } + // Register classes + ioc.addBean(clazz); } } @@ -135,7 +131,7 @@ public List getPlugins() { */ public void destroy() { // Clean IOC container - container.removeAll(); + ioc.clearAll(); for(Plugin plugin : plugins){ plugin.destroy(); } diff --git a/blade-core/src/main/java/com/blade/annotation/package-info.java b/blade-core/src/main/java/com/blade/annotation/package-info.java deleted file mode 100644 index 01b68478b..000000000 --- a/blade-core/src/main/java/com/blade/annotation/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Blade Annotation - */ -package com.blade.annotation; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/AopCreator.java b/blade-core/src/main/java/com/blade/ioc/AopCreator.java deleted file mode 100644 index e2bd31bb5..000000000 --- a/blade-core/src/main/java/com/blade/ioc/AopCreator.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import com.blade.aop.AopProxy; - - -/** - * Aop Create Object - * - * @author biezhi - * @since 1.0 - */ -public final class AopCreator { - - /** - * Create an agent based on Class - * @param clazz class Object - * @return return proxy object - */ - public static T create(Class clazz){ - return AopProxy.create(clazz); - } - - /** - * Create an agent based on Class - * @param clazz class Object - * @return return proxy object - */ - public static Object createProxy(Class clazz){ - return AopProxy.create(clazz); - } - -} diff --git a/blade-core/src/main/java/com/blade/ioc/BeanDefine.java b/blade-core/src/main/java/com/blade/ioc/BeanDefine.java new file mode 100644 index 000000000..cc93584e3 --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/BeanDefine.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +public class BeanDefine { + + private Object bean; + private Class type; + private boolean isSignle; + + public BeanDefine() { + } + + public BeanDefine(Object bean) { + this(bean, bean.getClass()); + } + + public BeanDefine(Object bean, Class type) { + this.bean = bean; + this.type = type; + this.isSignle = true; + } + + public BeanDefine(Object bean, Class type, boolean isSingle) { + this.bean = bean; + this.type = type; + this.isSignle = isSingle; + } + + public Object getBean() { + return bean; + } + + public void setBean(Object bean) { + this.bean = bean; + } + + public Class getType() { + return type; + } + + public void setType(Class type) { + this.type = type; + } + + public boolean isSignle() { + return isSignle; + } + + public void setSignle(boolean isSignle) { + this.isSignle = isSignle; + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/Container.java b/blade-core/src/main/java/com/blade/ioc/Container.java deleted file mode 100644 index 29b88a47c..000000000 --- a/blade-core/src/main/java/com/blade/ioc/Container.java +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.annotation.Annotation; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * IOC container top interface - * - * @author biezhi - * @since 1.0 - */ -public interface Container { - - /** - * According to the bean name and object function to obtain a bean object - * - * @param name bean name - * @param scope object scope, single case or each time it is created - * @param generic - * @return return object - */ - T getBean(String name, Scope scope); - - /** - * According to the class and the object function to obtain a bean object - * - * @param type class type - * @param scope object scope, single case or each time it is created - * @param generic - * @return return object - */ - T getBean(Class type, Scope scope); - - /** - * @return Return the name of all bean - */ - Set getBeanNames(); - - /** - * @param generic - * @return Return a collection of all bean - */ - Collection getBeans(); - - /** - * Class bean set in the IOC container for matching based on annotations - * - * @param annotation annotation class type - * @return return all class by annotation - */ - List> getClassesByAnnotation(Class annotation); - - /** - * To obtain a set of bean objects that match the IOC container - * - * @param annotation annotation class type - * @param generic - * @return return all bean by annotation - */ - List getBeansByAnnotation(Class annotation); - - /** - * To determine if there is a bean, according to the class type - * - * @param clazz class type - * @return return class is exist - */ - boolean hasBean(Class clazz); - - /** - * According to name Bena to determine whether there is - * - * @param name bean name, usually class name - * @return return class is exist - */ - boolean hasBean(String name); - - /** - * Remove an bean object from the IOC container by name - * - * @param clazz to remove the class bean type - * @return return if remove success - */ - boolean removeBean(Class clazz); - - /** - * @return clean container - */ - boolean removeAll(); - - /** - * To determine whether the comment in the annotations can be registered into the IOC container - * - * @param annotations annotation array to detect - * @return return is register - */ - boolean isRegister(Annotation[] annotations); - - /** - * Register an object to the bean container - * - * @param object bean object - * @return return register bean - */ - Object registerBean(Object object); - - /** - * Initialization IOC injection - */ - void initWired(); - - /** - * Inject a object - * @param object to inject object - */ - void injection(Class clazz, Object object); - - /** - * @return Returns the all bean objects in the IOC container - */ - Map, Object> getBeanMap(); - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/Ioc.java b/blade-core/src/main/java/com/blade/ioc/Ioc.java new file mode 100644 index 000000000..609bb0687 --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/Ioc.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.util.List; +import java.util.Set; + +public interface Ioc { + + void addBean(Object bean); + + void addBean(Class type); + + Object getBean(String name); + + T getBean(Class type); + + List getBeans(); + + Set getBeanNames(); + + void clearAll(); +} diff --git a/blade-core/src/main/java/com/blade/ioc/IocException.java b/blade-core/src/main/java/com/blade/ioc/IocException.java index 9102fc219..e2859747d 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocException.java +++ b/blade-core/src/main/java/com/blade/ioc/IocException.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; public class IocException extends RuntimeException { diff --git a/blade-core/src/main/java/com/blade/ioc/IocKit.java b/blade-core/src/main/java/com/blade/ioc/IocKit.java new file mode 100644 index 000000000..4bd2813db --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/IocKit.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.blade.ioc.annotation.Inject; + +import blade.kit.reflect.ClassDefine; + +public class IocKit { + + // @Inject标注的字段 + public static List getInjectFields(ClassDefine classDefine) { + List injectors = new ArrayList(8); + for (Field field : classDefine.getDeclaredFields()) { + for (Annotation annotation : field.getAnnotations()) { + if (annotation.annotationType().equals(Inject.class)) { + injectors.add(field); + } + } + } + if (injectors.size() == 0) { + return Collections.emptyList(); + } + return injectors; + } + + public static Object getBean(Ioc ioc, BeanDefine beanDefine) { + ClassDefine classDefine = ClassDefine.create(beanDefine.getType()); + List fields = IocKit.getInjectFields(classDefine); + try { + Object bean = beanDefine.getBean(); + for (Field field : fields) { + String name = field.getType().getName(); + Object value = ioc.getBean(name); + if (value == null) { + throw new IllegalStateException("Can't inject bean: " + name + " for field: " + field); + } + field.setAccessible(true); + field.set(bean, value); + } + return bean; + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java b/blade-core/src/main/java/com/blade/ioc/SampleContainer.java deleted file mode 100644 index d014559c6..000000000 --- a/blade-core/src/main/java/com/blade/ioc/SampleContainer.java +++ /dev/null @@ -1,333 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import blade.kit.Assert; -import blade.kit.CloneKit; -import blade.kit.CollectionKit; -import blade.kit.log.Logger; - -import com.blade.annotation.Component; -import com.blade.annotation.Inject; -import com.blade.annotation.Path; - -/** - * IOC default implement - * - * @author biezhi - * @since 1.0 - */ -@SuppressWarnings("unchecked") -public class SampleContainer implements Container { - - private static final Logger LOGGER = Logger.getLogger(SampleContainer.class); - - /** - * Save all bean objects, e.g: com.xxxx.User @Userx7asc - */ - private Map, Object> beans = CollectionKit.newConcurrentHashMap(); - - /** - * Save all the notes class - */ - private Map, List> annotaionBeans = CollectionKit.newConcurrentHashMap(); - - - public SampleContainer() { - } - - public Map, Object> getBeanMap() { - return beans; - } - - @Override - public T getBean(String name, Scope scope) { - Assert.notBlank(name); - try { - Class clazz = (Class) Class.forName(name); - return getBean(clazz, scope); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public T getBean(Class type, Scope scope) { - Assert.notNull(type); - - Object obj = beans.get(type); - if(null != scope && null != Scope.SINGLE){ - try { - return (T) CloneKit.deepClone(obj); - } catch (Exception e) { - throw new IocException("clone object error", e); - } - } - return type.cast(obj); - } - - @Override - public Set getBeanNames() { - Set> classes = beans.keySet(); - if(null != classes){ - Set beanNames = new HashSet(classes.size()); - for(Class clazz : classes){ - beanNames.add(clazz.getName()); - } - return beanNames; - } - return new HashSet(0); - } - - @Override - public Collection getBeans() { - return beans.values(); - } - - @Override - public boolean hasBean(Class clazz) { - if(null != clazz){ - return beans.get(clazz) != null; - } - return false; - } - - @Override - public boolean hasBean(String name) { - try { - Class clazz = Class.forName(name); - return hasBean(clazz); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - return false; - } - - @Override - public boolean removeBean(Class clazz) { - if(null != clazz && beans.containsKey(clazz)){ - beans.remove(clazz); - return true; - } - return false; - } - - private void registerParent(Class clazz, Object value) { - if(!beans.containsKey(clazz)){ - beans.put(clazz, value); - } - } - - @Override - public Object registerBean(Object value) { - if(null != value){ - Class clazz = value.getClass(); - // Not abstract class, interface - if (isNormalClass(clazz)) { - - // If the container already exists, the name is directly returned - if(beans.containsKey(clazz)){ - return beans.get(clazz); - } - - beans.put(clazz, value); - - // Achieve the interface corresponding storage - Class[] interfaces = clazz.getInterfaces(); - if(interfaces.length > 0){ - for(Class interfaceClazz : interfaces){ - this.registerParent(interfaceClazz, value); - } - } - - // With annotation - if(null != clazz.getDeclaredAnnotations()){ - putAnnotationMap(clazz, value); - } - return value; - } - } - return null; - } - - /** - * Add elements to annotationMap - * - * @param clazz class type to be injected - * @param object registered bean object - */ - private void putAnnotationMap(Class clazz, Object object){ - - Annotation[] annotations = clazz.getAnnotations(); - List listObject = null; - for(Annotation annotation : annotations){ - if(null != annotation){ - listObject = annotaionBeans.get(annotation.annotationType()); - if(CollectionKit.isEmpty(listObject)){ - listObject = CollectionKit.newArrayList(); - } - listObject.add(object); - this.put(annotation.annotationType(), listObject); - } - } - } - - /** - * AnnotationBean container storage - * - * @param clazz allows the Annotation type to be registered - * @param listObject list of objects to be injected - */ - private void put(Class clazz, List listObject){ - if(null == annotaionBeans.get(clazz)){ - annotaionBeans.put(clazz, listObject); - } - } - - /** - * Initialization injection - */ - @Override - public void initWired() throws RuntimeException { - - Set> keys = beans.keySet(); - for(Class clazz : keys){ - Object object = beans.get(clazz); - injection(clazz, object); - } - } - - // Assemble - private Object recursiveAssembly(Class clazz){ - if(null != clazz && beans.containsKey(clazz)){ - return beans.get(clazz); - } - return null; - } - - - /** - * To determine whether the bean can be registered - * - * @param annotations annotation class type arrays - * @return return is register - */ - @Override - public boolean isRegister(Annotation[] annotations) { - if (null == annotations || annotations.length == 0) { - return false; - } - for (Annotation annotation : annotations) { - if (annotation instanceof Component || annotation instanceof Path) { - return true; - } - } - return false; - } - - /** - * Is not interface and abstract class Class - * @param clazz class type - * @return return is interface && abstract class - */ - private boolean isNormalClass(Class clazz){ - if(!Modifier.isAbstract(clazz.getModifiers()) && !clazz.isInterface()){ - return true; - } - return false; - } - - @Override - public List> getClassesByAnnotation(Class annotation) { - List objectList = getBeansByAnnotation(annotation); - if(!CollectionKit.isEmpty(objectList)){ - List> classList = CollectionKit.newArrayList(objectList.size()); - for(Object object : objectList){ - classList.add(object.getClass()); - } - return classList; - } - return null; - } - - @Override - public List getBeansByAnnotation(Class annotation) { - return (List) annotaionBeans.get(annotation); - } - - @Override - public boolean removeAll() { - beans.clear(); - annotaionBeans.clear(); - return true; - } - - @Override - public void injection(Class clazz, Object object) { - - if(null == clazz || null == object){ - return; - } - - // Traverse all fields - try { - Field[] fields = clazz.getDeclaredFields(); - for (Field field : fields) { - // Need to inject the field - Inject inject = field.getAnnotation(Inject.class); - if (null != inject ) { - // Bean to be injected - Object injectField = null; - if(inject.value() == Class.class){ - injectField = recursiveAssembly(field.getType()); - } else { - // Specify an assembly - injectField = this.getBean(inject.value(), null); - if (null == injectField) { - injectField = recursiveAssembly(inject.value()); - } - } - - if (null == injectField) { - throw new RuntimeException("Unable to load " + field.getType().getName() + "!"); - } - - boolean accessible = field.isAccessible(); - field.setAccessible(true); - field.set(object, injectField); - field.setAccessible(accessible); - } - } - } catch (SecurityException e) { - LOGGER.error(e); - } catch (IllegalArgumentException e) { - LOGGER.error(e); - } catch (IllegalAccessException e) { - LOGGER.error(e); - } - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java new file mode 100644 index 000000000..8f54af435 --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.blade.ioc.loader.IocLoader; + +import blade.kit.log.Logger; + +public class SampleIoc implements Ioc{ + + private static final Logger LOGGER = Logger.getLogger(Ioc.class); + + private final Map pool = new HashMap(); + + public void load(IocLoader loader) { + loader.load(this); + } + + // 添加用户自定义的对象 + @Override + public void addBean(Object beanObject) { + addBean(beanObject.getClass().getName(), beanObject); + } + + // 添加用户自定义的对象 + public void addBean(Class beanClass, Object beanObject) { + addBean(beanClass.getName(), beanObject); + } + + // 添加用户自定义的对象 + public void addBean(String name, Object beanObject) { + addBean(name, new BeanDefine(beanObject)); + } + + // 添加用户自定义的对象 + public void addBean(String name, BeanDefine beanDefine) { + + LOGGER.debug("addBean: %s", name); + + if (pool.put(name, beanDefine) != null) { + LOGGER.warn("Duplicated Bean: %s", name); + } + } + + // 注册 @Component 标注的对象 + @Override + public void addBean(Class type) { + addBean(type, true); + } + + // 注册 @Component 标注的对象 + public void addBean(Class type, boolean singleton) { + addBean(type.getName(), type, singleton); + } + + // 注册 @Component 标注的对象 + public void addBean(String name, Class beanClass, boolean singleton) { + + LOGGER.debug("addBean: %s", name, beanClass.getName()); + + BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton); + if (pool.put(name, beanDefine) != null) { + LOGGER.warn("Duplicated Bean: %s", name); + } + } + + private BeanDefine getBeanDefine(Class beanClass, boolean singleton) { + try { + Object object = beanClass.newInstance(); + return new BeanDefine(object, beanClass, singleton); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public T getBean(Class type) { + return type.cast(getBean(type.getName())); + } + + @Override + public Object getBean(String name) { + BeanDefine beanDefine = pool.get(name); + if (beanDefine == null) { + return null; + } + return IocKit.getBean(this, beanDefine); + } + + @Override + public List getBeans() { + Set beanNames = this.getBeanNames(); + List beans = new ArrayList(beanNames.size()); + for(String beanName : beanNames){ + Object bean = this.getBean(beanName); + if(null != bean){ + beans.add(bean); + } + } + return beans; + } + + @Override + public Set getBeanNames() { + return pool.keySet(); + } + + @Override + public void clearAll() { + pool.clear(); + } + +} diff --git a/blade-core/src/main/java/com/blade/annotation/Component.java b/blade-core/src/main/java/com/blade/ioc/annotation/Component.java similarity index 88% rename from blade-core/src/main/java/com/blade/annotation/Component.java rename to blade-core/src/main/java/com/blade/ioc/annotation/Component.java index fcf71ef4a..3118c2e48 100644 --- a/blade-core/src/main/java/com/blade/annotation/Component.java +++ b/blade-core/src/main/java/com/blade/ioc/annotation/Component.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.ioc.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -30,4 +30,8 @@ @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Component{ + + String value() default ""; + + boolean singleton() default true; } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/Inject.java b/blade-core/src/main/java/com/blade/ioc/annotation/Inject.java similarity index 88% rename from blade-core/src/main/java/com/blade/annotation/Inject.java rename to blade-core/src/main/java/com/blade/ioc/annotation/Inject.java index 51dc624df..6c3b42bca 100644 --- a/blade-core/src/main/java/com/blade/annotation/Inject.java +++ b/blade-core/src/main/java/com/blade/ioc/annotation/Inject.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.ioc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -30,9 +30,6 @@ @Retention(RetentionPolicy.RUNTIME) public @interface Inject { - /** - * @return The object to be injected into the Class - */ - Class value() default Class.class; + String value() default ""; } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java new file mode 100644 index 000000000..30a9ec184 --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.loader; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import com.blade.ioc.SampleIoc; +import com.blade.ioc.annotation.Component; + +import blade.kit.resource.ClassPathClassReader; +import blade.kit.resource.ClassReader; + +public final class IocAnnotationLoader implements IocLoader { + + private Collection> classes; + + private ClassReader classReader = new ClassPathClassReader(); + + public IocAnnotationLoader(String... packageNames) { + List> annotations = new ArrayList>(1); + annotations.add(Component.class); + this.classes = finder(Arrays.asList(packageNames), annotations, true); + } + + private Collection> finder(List packageNames, List> annotations, boolean recursive){ + Collection> classes = new ArrayList>(); + for(String packageName : packageNames){ + for(Class annotation : annotations){ + classes.addAll(classReader.getClassByAnnotation(packageName, annotation, recursive)); + } + } + return classes; + } + + public IocAnnotationLoader(Collection> classes) { + this.classes = classes; + } + + @Override + public void load(SampleIoc ioc) { + for (Class cls : classes) { + Component anno = cls.getAnnotation(Component.class); + if (anno != null) { + String name = anno.value().equals("") ? cls.getName() : anno.value(); + ioc.addBean(name, cls, anno.singleton()); + } + } + // free + classes = null; + } +} diff --git a/blade-core/src/main/java/com/blade/ioc/Scope.java b/blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java similarity index 68% rename from blade-core/src/main/java/com/blade/ioc/Scope.java rename to blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java index a59a8d3b9..b5f8747c2 100644 --- a/blade-core/src/main/java/com/blade/ioc/Scope.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java @@ -1,27 +1,24 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -/** - * Bean create type - * SINGLE, PROTOTYPE - * - * @author biezhi - * @since 1.0 - */ -public enum Scope { - SINGLE, PROTOTYPE +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.loader; + +import com.blade.ioc.SampleIoc; + +public interface IocLoader { + + void load(SampleIoc ioc); + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java index 34127d5dd..db773ff13 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java @@ -15,10 +15,8 @@ */ package com.blade.loader; -import com.blade.Aop; import com.blade.Blade; -import com.blade.ioc.Container; -import com.blade.ioc.Scope; +import com.blade.ioc.Ioc; import com.blade.route.RouteException; /** @@ -33,7 +31,7 @@ public class ClassPathControllerLoader implements ControllerLoader { private ClassLoader classLoader = ClassPathControllerLoader.class.getClassLoader(); - private Container container = Blade.me().container(); + private Ioc ioc = Blade.me().ioc(); public ClassPathControllerLoader() { this(""); @@ -57,10 +55,10 @@ public Object load(String controllerName) throws RouteException { // Load controller instance Class controllerClass = classLoader.loadClass(className); - Object controller = container.getBean(controllerClass, Scope.SINGLE); + Object controller = ioc.getBean(controllerClass); if(null == controller){ - controller = Aop.create(controllerClass); - container.registerBean(controller); + ioc.addBean(controllerClass); + controller = ioc.getBean(controllerClass); } return controller; } catch (Exception e) { diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index bdbc1b775..c958d7ec7 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -18,20 +18,19 @@ import java.lang.reflect.Method; import java.util.Set; +import com.blade.Blade; +import com.blade.ioc.Ioc; +import com.blade.route.annotation.After; +import com.blade.route.annotation.Before; +import com.blade.route.annotation.Interceptor; +import com.blade.route.annotation.Path; +import com.blade.route.annotation.Route; +import com.blade.web.http.HttpMethod; + import blade.kit.StringKit; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; -import com.blade.Aop; -import com.blade.Blade; -import com.blade.annotation.After; -import com.blade.annotation.Before; -import com.blade.annotation.Interceptor; -import com.blade.annotation.Path; -import com.blade.annotation.Route; -import com.blade.ioc.Container; -import com.blade.web.http.HttpMethod; - /** * Route builder * @@ -58,7 +57,7 @@ public class RouteBuilder { /** * IOC container, storage route to IOC */ - private Container container = null; + private Ioc ioc = null; private Blade blade; @@ -67,7 +66,7 @@ public class RouteBuilder { public RouteBuilder(Blade blade) { this.blade = blade; this.routers = blade.routers(); - this.container = blade.container(); + this.ioc = blade.ioc(); } /** @@ -175,7 +174,7 @@ private void parseInterceptor(final Class interceptor){ return; } - container.registerBean(Aop.create(interceptor)); + ioc.addBean(interceptor); for (Method method : methods) { @@ -230,7 +229,7 @@ private void parseRouter(final Class router){ return; } - container.registerBean(Aop.create(router)); + ioc.addBean(router); final String nameSpace = router.getAnnotation(Path.class).value(); diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 8a7cf1c55..4bca4328b 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -20,16 +20,14 @@ import java.util.List; import java.util.Map; -import blade.kit.Assert; -import blade.kit.log.Logger; - -import com.blade.Aop; -import com.blade.ioc.Container; -import com.blade.ioc.Scope; +import com.blade.ioc.Ioc; import com.blade.web.http.HttpMethod; import com.blade.web.http.Request; import com.blade.web.http.Response; +import blade.kit.Assert; +import blade.kit.log.Logger; + /** * Registration, management route * @@ -40,7 +38,7 @@ public class Routers { private Logger LOGGER = Logger.getLogger(Routers.class); - private Container container = null; + private Ioc ioc = null; private Map routes = null; @@ -48,8 +46,8 @@ public class Routers { private static final String METHOD_NAME = "handle"; - public Routers(Container container) { - this.container = container; + public Routers(Ioc ioc) { + this.ioc = ioc; this.routes = new HashMap(); this.interceptors = new HashMap(); } @@ -155,10 +153,10 @@ public void route(String path, Class clazz, String methodName) { httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); methodName = methodArr[1]; } - Object controller = container.getBean(clazz, Scope.SINGLE); + Object controller = ioc.getBean(clazz); if(null == controller){ - controller = Aop.create(clazz); - container.registerBean(controller); + ioc.addBean(clazz); + controller = ioc.getBean(clazz); } try { Method method = clazz.getMethod(methodName, Request.class, Response.class); @@ -180,10 +178,10 @@ public void route(String path, Class clazz, String methodName) { public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) { try { - Object controller = container.getBean(clazz, Scope.SINGLE); + Object controller = ioc.getBean(clazz); if(null == controller){ - controller = Aop.create(clazz); - container.registerBean(controller); + ioc.addBean(clazz); + controller = ioc.getBean(clazz); } Method method = clazz.getMethod(methodName, Request.class, Response.class); addRoute(httpMethod, path, controller, method); @@ -196,10 +194,10 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { try { - Object controller = container.getBean(clazz, Scope.SINGLE); + Object controller = ioc.getBean(clazz); if(null == controller){ - controller = Aop.create(clazz); - container.registerBean(controller); + ioc.addBean(clazz); + controller = ioc.getBean(clazz); } addRoute(httpMethod, path, null, method); } catch (SecurityException e) { @@ -210,7 +208,7 @@ public void buildRoute(String path, Class clazz, Method method, HttpMethod ht public void route(String path, Object target, String methodName, HttpMethod httpMethod) { try { Class clazz = target.getClass(); - container.registerBean(target); + ioc.addBean(target); Method method = clazz.getMethod(methodName, Request.class, Response.class); addRoute(httpMethod, path, target, method); } catch (NoSuchMethodException e) { diff --git a/blade-core/src/main/java/com/blade/annotation/After.java b/blade-core/src/main/java/com/blade/route/annotation/After.java similarity index 93% rename from blade-core/src/main/java/com/blade/annotation/After.java rename to blade-core/src/main/java/com/blade/route/annotation/After.java index 8b3b50aac..585052e8f 100644 --- a/blade-core/src/main/java/com/blade/annotation/After.java +++ b/blade-core/src/main/java/com/blade/route/annotation/After.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.route.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/annotation/Before.java b/blade-core/src/main/java/com/blade/route/annotation/Before.java similarity index 93% rename from blade-core/src/main/java/com/blade/annotation/Before.java rename to blade-core/src/main/java/com/blade/route/annotation/Before.java index 32f5787e7..84cdb7110 100644 --- a/blade-core/src/main/java/com/blade/annotation/Before.java +++ b/blade-core/src/main/java/com/blade/route/annotation/Before.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.route.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/annotation/Interceptor.java b/blade-core/src/main/java/com/blade/route/annotation/Interceptor.java similarity index 94% rename from blade-core/src/main/java/com/blade/annotation/Interceptor.java rename to blade-core/src/main/java/com/blade/route/annotation/Interceptor.java index 17053461c..c29170808 100644 --- a/blade-core/src/main/java/com/blade/annotation/Interceptor.java +++ b/blade-core/src/main/java/com/blade/route/annotation/Interceptor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.route.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/annotation/Path.java b/blade-core/src/main/java/com/blade/route/annotation/Path.java similarity index 93% rename from blade-core/src/main/java/com/blade/annotation/Path.java rename to blade-core/src/main/java/com/blade/route/annotation/Path.java index 2f3462a75..1cd5c480d 100644 --- a/blade-core/src/main/java/com/blade/annotation/Path.java +++ b/blade-core/src/main/java/com/blade/route/annotation/Path.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.route.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/annotation/Route.java b/blade-core/src/main/java/com/blade/route/annotation/Route.java similarity index 95% rename from blade-core/src/main/java/com/blade/annotation/Route.java rename to blade-core/src/main/java/com/blade/route/annotation/Route.java index 395fc3277..cba2887cb 100644 --- a/blade-core/src/main/java/com/blade/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/route/annotation/Route.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.route.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/route/annotation/package-info.java b/blade-core/src/main/java/com/blade/route/annotation/package-info.java new file mode 100644 index 000000000..615d80887 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/annotation/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade Annotation + */ +package com.blade.route.annotation; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java index 622251b22..853b12deb 100644 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java @@ -184,7 +184,7 @@ private void handle(Request request, Response response, Route route){ Object target = route.getTarget(); if(null == target){ Class clazz = route.getAction().getDeclaringClass(); - target = Blade.me().container().getBean(clazz, null); + target = Blade.me().ioc().getBean(clazz); } request.initPathParams(route.getPath()); diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 5314188ac..d9f9e99c5 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -25,15 +25,14 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import blade.kit.StringKit; -import blade.kit.log.Logger; - -import com.blade.Aop; import com.blade.Blade; import com.blade.Bootstrap; import com.blade.route.RouteBuilder; import com.blade.route.RouteMatcher; +import blade.kit.StringKit; +import blade.kit.log.Logger; + /** * Blade Core DispatcherServlet * @@ -71,17 +70,18 @@ public void init(ServletConfig config) throws ServletException { if(null == bootstrap){ String bootStrapClassName = config.getInitParameter("bootstrap"); if(StringKit.isNotBlank(bootStrapClassName)){ - bootstrap = getBootstrap(bootStrapClassName); + this.bootstrap = getBootstrap(bootStrapClassName); } else { - bootstrap = new Bootstrap() { + this.bootstrap = new Bootstrap() { @Override public void init(Blade blade) { } }; } - blade.app(bootstrap); + blade.app(this.bootstrap); } - blade.bootstrap().init(blade); + + this.bootstrap.init(blade); // buiding route new RouteBuilder(blade).building(); @@ -89,7 +89,7 @@ public void init(Blade blade) { // initialization ioc blade.iocInit(); - blade.bootstrap().contextInitialized(blade); + this.bootstrap.contextInitialized(blade); syncRequestHandler = new SyncRequestHandler(servletContext, blade.routers()); AsynRequestHandler.routeMatcher = new RouteMatcher(blade.routers()); @@ -129,7 +129,7 @@ private Bootstrap getBootstrap(String botstrapClassName) throws ServletException if(null != botstrapClassName){ Class applicationClass = (Class) Class.forName(botstrapClassName); if(null != applicationClass){ - bootstrapClass = Aop.createT(applicationClass); + bootstrapClass = applicationClass.newInstance(); } } else { throw new ServletException("bootstrapClass is null !"); diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index 9800e9922..b34a596c9 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -173,7 +173,7 @@ private void handle(Request request, Response response, Route route){ Object target = route.getTarget(); if(null == target){ Class clazz = route.getAction().getDeclaringClass(); - target = Blade.me().container().getBean(clazz, null); + target = Blade.me().ioc().getBean(clazz); } request.initPathParams(route.getPath()); From 6d6375df07c75738ce75acb5e729d86f32d9fe30 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 18:48:10 +0800 Subject: [PATCH 384/545] add ioc test --- .../test/java/com/blade/ioc/test/Hello.java | 13 +++++++++ .../test/java/com/blade/ioc/test/IocTest.java | 29 +++++++++++++++++++ .../test/java/com/blade/ioc/test/User.java | 10 +++++++ 3 files changed, 52 insertions(+) create mode 100644 blade-core/src/test/java/com/blade/ioc/test/Hello.java create mode 100644 blade-core/src/test/java/com/blade/ioc/test/IocTest.java create mode 100644 blade-core/src/test/java/com/blade/ioc/test/User.java diff --git a/blade-core/src/test/java/com/blade/ioc/test/Hello.java b/blade-core/src/test/java/com/blade/ioc/test/Hello.java new file mode 100644 index 000000000..ed710c784 --- /dev/null +++ b/blade-core/src/test/java/com/blade/ioc/test/Hello.java @@ -0,0 +1,13 @@ +package com.blade.ioc.test; + +import com.blade.ioc.annotation.Inject; + +public class Hello { + + @Inject + private User user; + + public void says() { + System.out.println("Hello " + user.getName()); + } +} \ No newline at end of file diff --git a/blade-core/src/test/java/com/blade/ioc/test/IocTest.java b/blade-core/src/test/java/com/blade/ioc/test/IocTest.java new file mode 100644 index 000000000..e8f1847f3 --- /dev/null +++ b/blade-core/src/test/java/com/blade/ioc/test/IocTest.java @@ -0,0 +1,29 @@ +package com.blade.ioc.test; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Before; +import org.junit.Test; + +import com.blade.ioc.Ioc; +import com.blade.ioc.SampleIoc; + +public class IocTest { + + private Ioc ioc; + + @Before + public void before(){ + ioc = new SampleIoc(); + } + + @Test + public void testAddBean() { + ioc.addBean(Hello.class); + ioc.addBean(User.class); + Hello hello = ioc.getBean(Hello.class); + assertNotNull(hello); + hello.says(); + } + +} diff --git a/blade-core/src/test/java/com/blade/ioc/test/User.java b/blade-core/src/test/java/com/blade/ioc/test/User.java new file mode 100644 index 000000000..5879b1977 --- /dev/null +++ b/blade-core/src/test/java/com/blade/ioc/test/User.java @@ -0,0 +1,10 @@ +package com.blade.ioc.test; + +public class User { + + private String name = "blade"; + + public String getName() { + return name; + } +} \ No newline at end of file From 35a3d3ee5309d11634ac65594da921fbbbebffc8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 19:13:38 +0800 Subject: [PATCH 385/545] add ioc interface to obtain objects --- .../src/main/java/com/blade/ioc/Ioc.java | 4 +++ .../src/main/java/com/blade/ioc/IocKit.java | 35 +++++++----------- .../main/java/com/blade/ioc/SampleIoc.java | 10 ++++++ .../java/com/blade/ioc/annotation/Inject.java | 3 ++ .../com/blade/ioc/annotation/InjectWith.java | 21 +++++++++++ .../com/blade/ioc/injector/FieldInjector.java | 36 +++++++++++++++++++ .../java/com/blade/ioc/injector/Injector.java | 7 ++++ .../blade/ioc/service/test/UserService.java | 7 ++++ .../ioc/service/test/UserServiceImpl.java | 13 +++++++ .../test/java/com/blade/ioc/test/IocTest.java | 18 +++++++++- 10 files changed, 130 insertions(+), 24 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/ioc/annotation/InjectWith.java create mode 100644 blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java create mode 100644 blade-core/src/main/java/com/blade/ioc/injector/Injector.java create mode 100644 blade-core/src/test/java/com/blade/ioc/service/test/UserService.java create mode 100644 blade-core/src/test/java/com/blade/ioc/service/test/UserServiceImpl.java diff --git a/blade-core/src/main/java/com/blade/ioc/Ioc.java b/blade-core/src/main/java/com/blade/ioc/Ioc.java index 609bb0687..9c6f1f3c3 100644 --- a/blade-core/src/main/java/com/blade/ioc/Ioc.java +++ b/blade-core/src/main/java/com/blade/ioc/Ioc.java @@ -18,8 +18,12 @@ import java.util.List; import java.util.Set; +import com.blade.ioc.loader.IocLoader; + public interface Ioc { + void load(IocLoader iocLoader); + void addBean(Object bean); void addBean(Class type); diff --git a/blade-core/src/main/java/com/blade/ioc/IocKit.java b/blade-core/src/main/java/com/blade/ioc/IocKit.java index 4bd2813db..1fb9db983 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocKit.java +++ b/blade-core/src/main/java/com/blade/ioc/IocKit.java @@ -21,19 +21,21 @@ import java.util.Collections; import java.util.List; -import com.blade.ioc.annotation.Inject; +import com.blade.ioc.annotation.InjectWith; +import com.blade.ioc.injector.FieldInjector; import blade.kit.reflect.ClassDefine; public class IocKit { // @Inject标注的字段 - public static List getInjectFields(ClassDefine classDefine) { - List injectors = new ArrayList(8); + public static List getInjectFields(Ioc ioc, ClassDefine classDefine) { + List injectors = new ArrayList(8); for (Field field : classDefine.getDeclaredFields()) { for (Annotation annotation : field.getAnnotations()) { - if (annotation.annotationType().equals(Inject.class)) { - injectors.add(field); + InjectWith with = annotation.annotationType().getAnnotation(InjectWith.class); + if (with != null) { + injectors.add(new FieldInjector(ioc, field)); } } } @@ -45,25 +47,12 @@ public static List getInjectFields(ClassDefine classDefine) { public static Object getBean(Ioc ioc, BeanDefine beanDefine) { ClassDefine classDefine = ClassDefine.create(beanDefine.getType()); - List fields = IocKit.getInjectFields(classDefine); - try { - Object bean = beanDefine.getBean(); - for (Field field : fields) { - String name = field.getType().getName(); - Object value = ioc.getBean(name); - if (value == null) { - throw new IllegalStateException("Can't inject bean: " + name + " for field: " + field); - } - field.setAccessible(true); - field.set(bean, value); - } - return bean; - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); + List fieldInjectors = IocKit.getInjectFields(ioc, classDefine); + Object bean = beanDefine.getBean(); + for (FieldInjector fieldInjector : fieldInjectors) { + fieldInjector.injection(bean); } - return null; + return bean; } } diff --git a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java index 8f54af435..fe274ccb4 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java @@ -31,6 +31,7 @@ public class SampleIoc implements Ioc{ private final Map pool = new HashMap(); + @Override public void load(IocLoader loader) { loader.load(this); } @@ -78,9 +79,18 @@ public void addBean(String name, Class beanClass, boolean singleton) { LOGGER.debug("addBean: %s", name, beanClass.getName()); BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton); + if (pool.put(name, beanDefine) != null) { LOGGER.warn("Duplicated Bean: %s", name); } + + Class[] interfaces = beanClass.getInterfaces(); + if(interfaces.length > 0){ + for(Class interfaceClazz : interfaces){ + this.addBean(interfaceClazz.getName(), beanDefine); + } + } + } private BeanDefine getBeanDefine(Class beanClass, boolean singleton) { diff --git a/blade-core/src/main/java/com/blade/ioc/annotation/Inject.java b/blade-core/src/main/java/com/blade/ioc/annotation/Inject.java index 6c3b42bca..edb4d3eb6 100644 --- a/blade-core/src/main/java/com/blade/ioc/annotation/Inject.java +++ b/blade-core/src/main/java/com/blade/ioc/annotation/Inject.java @@ -20,6 +20,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import com.blade.ioc.injector.FieldInjector; + /** * Automatic injection * @@ -27,6 +29,7 @@ * @since 1.0 */ @Target(ElementType.FIELD) +@InjectWith(FieldInjector.class) @Retention(RetentionPolicy.RUNTIME) public @interface Inject { diff --git a/blade-core/src/main/java/com/blade/ioc/annotation/InjectWith.java b/blade-core/src/main/java/com/blade/ioc/annotation/InjectWith.java new file mode 100644 index 000000000..107d5435a --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/annotation/InjectWith.java @@ -0,0 +1,21 @@ +package com.blade.ioc.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.blade.ioc.injector.Injector; + +/**S + * 凡是标注了 InjectFieldWith 的第三方 Annotation,就被允许进行自定义注入字段 + */ +@Target(ElementType.ANNOTATION_TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface InjectWith { + + Class value(); + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java b/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java new file mode 100644 index 000000000..dcce68c64 --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java @@ -0,0 +1,36 @@ +package com.blade.ioc.injector; + +import java.lang.reflect.Field; + +import com.blade.ioc.Ioc; + +public class FieldInjector implements Injector { + + private Ioc ioc; + + private Field field; + + public FieldInjector(Ioc ioc, Field field) { + this.ioc = ioc; + this.field = field; + } + + @Override + public void injection(Object bean) { + try { + String name = field.getType().getName(); + Object value = ioc.getBean(name); + if (value == null) { + throw new IllegalStateException("Can't inject bean: " + name + " for field: " + field); + } + field.setAccessible(true); + field.set(bean, value); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/injector/Injector.java b/blade-core/src/main/java/com/blade/ioc/injector/Injector.java new file mode 100644 index 000000000..984995fcb --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/injector/Injector.java @@ -0,0 +1,7 @@ +package com.blade.ioc.injector; + +public interface Injector { + + void injection(Object bean); + +} diff --git a/blade-core/src/test/java/com/blade/ioc/service/test/UserService.java b/blade-core/src/test/java/com/blade/ioc/service/test/UserService.java new file mode 100644 index 000000000..71e07f7b8 --- /dev/null +++ b/blade-core/src/test/java/com/blade/ioc/service/test/UserService.java @@ -0,0 +1,7 @@ +package com.blade.ioc.service.test; + +public interface UserService { + + String getName(); + +} diff --git a/blade-core/src/test/java/com/blade/ioc/service/test/UserServiceImpl.java b/blade-core/src/test/java/com/blade/ioc/service/test/UserServiceImpl.java new file mode 100644 index 000000000..6dda1dab1 --- /dev/null +++ b/blade-core/src/test/java/com/blade/ioc/service/test/UserServiceImpl.java @@ -0,0 +1,13 @@ +package com.blade.ioc.service.test; + +import com.blade.ioc.annotation.Component; + +@Component +public class UserServiceImpl implements UserService { + + @Override + public String getName() { + return "blade"; + } + +} diff --git a/blade-core/src/test/java/com/blade/ioc/test/IocTest.java b/blade-core/src/test/java/com/blade/ioc/test/IocTest.java index e8f1847f3..b2c39ba48 100644 --- a/blade-core/src/test/java/com/blade/ioc/test/IocTest.java +++ b/blade-core/src/test/java/com/blade/ioc/test/IocTest.java @@ -1,12 +1,15 @@ package com.blade.ioc.test; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; import com.blade.ioc.Ioc; import com.blade.ioc.SampleIoc; +import com.blade.ioc.loader.IocAnnotationLoader; +import com.blade.ioc.service.test.UserService; +import com.blade.ioc.service.test.UserServiceImpl; public class IocTest { @@ -26,4 +29,17 @@ public void testAddBean() { hello.says(); } + @Test + public void testGetInterface() { + ioc.load(new IocAnnotationLoader("com.blade.ioc.service.test")); + + UserService userService = ioc.getBean(UserService.class); + assertNotNull(userService); + assertEquals("blade", userService.getName()); + + UserServiceImpl userServiceImpl = ioc.getBean(UserServiceImpl.class); + + assertEquals(userService, userServiceImpl); + } + } From 9b9033923c3b0a6c3f7d3c59448d7108d5ccafaf Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 19:32:15 +0800 Subject: [PATCH 386/545] add comments and testCase --- blade-core/pom.xml | 9 +- .../main/java/com/blade/ioc/BeanDefine.java | 9 +- .../src/main/java/com/blade/ioc/Ioc.java | 8 +- .../main/java/com/blade/ioc/IocException.java | 37 --------- .../src/main/java/com/blade/ioc/IocKit.java | 23 ++++- .../main/java/com/blade/ioc/SampleIoc.java | 83 +++++++++++++++---- .../blade/ioc/annotation/package-info.java | 4 + .../com/blade/ioc/injector/FieldInjector.java | 15 ++++ .../java/com/blade/ioc/injector/Injector.java | 15 ++++ .../com/blade/ioc/injector/package-info.java | 4 + .../test/java/com/blade/ioc/test/IocTest.java | 28 +++++++ 11 files changed, 172 insertions(+), 63 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/ioc/IocException.java create mode 100644 blade-core/src/main/java/com/blade/ioc/annotation/package-info.java create mode 100644 blade-core/src/main/java/com/blade/ioc/injector/package-info.java diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 4b76a3cd4..168865ba2 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -14,7 +14,7 @@ ${blade.version} blade-core https://github.com/biezhi/blade/blade-core - + 9.2.12.v20150709 2.0.12 @@ -28,7 +28,7 @@ com.bladejava blade-kit - 1.2.8 + 1.2.9-alpha com.bladejava @@ -72,6 +72,11 @@ ${jetty.version} provided + + junit + junit + test + diff --git a/blade-core/src/main/java/com/blade/ioc/BeanDefine.java b/blade-core/src/main/java/com/blade/ioc/BeanDefine.java index cc93584e3..8383d89ff 100644 --- a/blade-core/src/main/java/com/blade/ioc/BeanDefine.java +++ b/blade-core/src/main/java/com/blade/ioc/BeanDefine.java @@ -15,15 +15,18 @@ */ package com.blade.ioc; +/** + * Bean Define, IOC to define a target + * + * @author biezhi + * @since 1.0 + */ public class BeanDefine { private Object bean; private Class type; private boolean isSignle; - public BeanDefine() { - } - public BeanDefine(Object bean) { this(bean, bean.getClass()); } diff --git a/blade-core/src/main/java/com/blade/ioc/Ioc.java b/blade-core/src/main/java/com/blade/ioc/Ioc.java index 9c6f1f3c3..59a6424df 100644 --- a/blade-core/src/main/java/com/blade/ioc/Ioc.java +++ b/blade-core/src/main/java/com/blade/ioc/Ioc.java @@ -20,6 +20,12 @@ import com.blade.ioc.loader.IocLoader; +/** + * IOC container, it provides an interface for registration and bean. + * + * @author biezhi + * @since 1.0 + */ public interface Ioc { void load(IocLoader iocLoader); @@ -35,6 +41,6 @@ public interface Ioc { List getBeans(); Set getBeanNames(); - + void clearAll(); } diff --git a/blade-core/src/main/java/com/blade/ioc/IocException.java b/blade-core/src/main/java/com/blade/ioc/IocException.java deleted file mode 100644 index e2859747d..000000000 --- a/blade-core/src/main/java/com/blade/ioc/IocException.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -public class IocException extends RuntimeException { - - private static final long serialVersionUID = -1896357479295031509L; - - public IocException() { - } - - public IocException(String msg) { - super(msg); - } - - public IocException(Throwable t) { - super(t); - } - - public IocException(String msg, Throwable t) { - super(msg, t); - } - -} diff --git a/blade-core/src/main/java/com/blade/ioc/IocKit.java b/blade-core/src/main/java/com/blade/ioc/IocKit.java index 1fb9db983..7bbf54737 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocKit.java +++ b/blade-core/src/main/java/com/blade/ioc/IocKit.java @@ -26,9 +26,21 @@ import blade.kit.reflect.ClassDefine; +/** + * IocKit, get Bean + * + * @author biezhi + * @since 1.0 + */ public class IocKit { - // @Inject标注的字段 + /** + * Get @Inject Annotated field + * + * @param ioc ioc container + * @param classDefine classDefine + * @return return FieldInjector + */ public static List getInjectFields(Ioc ioc, ClassDefine classDefine) { List injectors = new ArrayList(8); for (Field field : classDefine.getDeclaredFields()) { @@ -45,6 +57,13 @@ public static List getInjectFields(Ioc ioc, ClassDefine classDefi return injectors; } + /** + * Get bean according to BeanDefine + * + * @param ioc ioc container + * @param beanDefine beandefine object + * @return bean object + */ public static Object getBean(Ioc ioc, BeanDefine beanDefine) { ClassDefine classDefine = ClassDefine.create(beanDefine.getType()); List fieldInjectors = IocKit.getInjectFields(ioc, classDefine); @@ -55,4 +74,4 @@ public static Object getBean(Ioc ioc, BeanDefine beanDefine) { return bean; } -} +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java index fe274ccb4..1a59d71f4 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java @@ -15,6 +15,7 @@ */ package com.blade.ioc; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -23,59 +24,105 @@ import com.blade.ioc.loader.IocLoader; +import blade.kit.Assert; import blade.kit.log.Logger; -public class SampleIoc implements Ioc{ +/** + * The default IOC container implementation + * + * @author biezhi + * @since 1.0 + */ +public class SampleIoc implements Ioc { private static final Logger LOGGER = Logger.getLogger(Ioc.class); private final Map pool = new HashMap(); + /** + * ioc loader + */ @Override public void load(IocLoader loader) { loader.load(this); } - // 添加用户自定义的对象 + /** + * Add user-defined objects + */ @Override - public void addBean(Object beanObject) { - addBean(beanObject.getClass().getName(), beanObject); + public void addBean(Object bean) { + Assert.notNull(bean); + addBean(bean.getClass().getName(), bean); } - // 添加用户自定义的对象 - public void addBean(Class beanClass, Object beanObject) { - addBean(beanClass.getName(), beanObject); + /** + * Add user-defined objects + */ + public void addBean(Class beanClass, Object bean) { + Assert.notNull(beanClass); + addBean(beanClass.getName(), bean); } - // 添加用户自定义的对象 - public void addBean(String name, Object beanObject) { - addBean(name, new BeanDefine(beanObject)); + /** + * Add user-defined objects + */ + public void addBean(String name, Object bean) { + Assert.notNull(bean); + BeanDefine beanDefine = new BeanDefine(bean); + addBean(name, beanDefine); + + // add interface + Class[] interfaces = beanDefine.getType().getInterfaces(); + if(interfaces.length > 0){ + for(Class interfaceClazz : interfaces){ + this.addBean(interfaceClazz.getName(), beanDefine); + } + } } - // 添加用户自定义的对象 + /** + * Add user-defined objects + */ public void addBean(String name, BeanDefine beanDefine) { + Assert.notNull(name); + Assert.notNull(beanDefine); + LOGGER.debug("addBean: %s", name); if (pool.put(name, beanDefine) != null) { LOGGER.warn("Duplicated Bean: %s", name); } + } - // 注册 @Component 标注的对象 + /** + * Register @Component marked objects + */ @Override public void addBean(Class type) { addBean(type, true); } - // 注册 @Component 标注的对象 + /** + * Register @Component marked objects + */ public void addBean(Class type, boolean singleton) { + Assert.notNull(type); addBean(type.getName(), type, singleton); } - // 注册 @Component 标注的对象 + /** + * Register @Component marked objects + */ public void addBean(String name, Class beanClass, boolean singleton) { + Assert.notNull(name); + Assert.notNull(beanClass); + Assert.isFalse(beanClass.isInterface(), "Must not be interface: %s", beanClass.getName()); + Assert.isFalse(Modifier.isAbstract(beanClass.getModifiers()), "Must not be abstract class: %s", beanClass.getName()); + LOGGER.debug("addBean: %s", name, beanClass.getName()); BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton); @@ -84,15 +131,15 @@ public void addBean(String name, Class beanClass, boolean singleton) { LOGGER.warn("Duplicated Bean: %s", name); } + // add interface Class[] interfaces = beanClass.getInterfaces(); if(interfaces.length > 0){ for(Class interfaceClazz : interfaces){ this.addBean(interfaceClazz.getName(), beanDefine); } } - } - + private BeanDefine getBeanDefine(Class beanClass, boolean singleton) { try { Object object = beanClass.newInstance(); @@ -131,7 +178,7 @@ public List getBeans() { } return beans; } - + @Override public Set getBeanNames() { return pool.keySet(); @@ -142,4 +189,4 @@ public void clearAll() { pool.clear(); } -} +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/annotation/package-info.java b/blade-core/src/main/java/com/blade/ioc/annotation/package-info.java new file mode 100644 index 000000000..93ad4b3f1 --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/annotation/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade IOC Annotation + */ +package com.blade.ioc.annotation; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java b/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java index dcce68c64..cb7153765 100644 --- a/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java +++ b/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.injector; import java.lang.reflect.Field; diff --git a/blade-core/src/main/java/com/blade/ioc/injector/Injector.java b/blade-core/src/main/java/com/blade/ioc/injector/Injector.java index 984995fcb..ff7c0db23 100644 --- a/blade-core/src/main/java/com/blade/ioc/injector/Injector.java +++ b/blade-core/src/main/java/com/blade/ioc/injector/Injector.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.injector; public interface Injector { diff --git a/blade-core/src/main/java/com/blade/ioc/injector/package-info.java b/blade-core/src/main/java/com/blade/ioc/injector/package-info.java new file mode 100644 index 000000000..3290150d5 --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/injector/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade IOC Injector + */ +package com.blade.ioc.injector; \ No newline at end of file diff --git a/blade-core/src/test/java/com/blade/ioc/test/IocTest.java b/blade-core/src/test/java/com/blade/ioc/test/IocTest.java index b2c39ba48..dbb1111fe 100644 --- a/blade-core/src/test/java/com/blade/ioc/test/IocTest.java +++ b/blade-core/src/test/java/com/blade/ioc/test/IocTest.java @@ -42,4 +42,32 @@ public void testGetInterface() { assertEquals(userService, userServiceImpl); } + @Test + public void testGetInterface2() { + + ioc.addBean(UserServiceImpl.class); + + UserService userService = ioc.getBean(UserService.class); + assertNotNull(userService); + assertEquals("blade", userService.getName()); + + UserServiceImpl userServiceImpl = ioc.getBean(UserServiceImpl.class); + + assertEquals(userService, userServiceImpl); + } + + @Test + public void testGetInterface3() { + + ioc.addBean(new UserServiceImpl()); + + UserService userService = ioc.getBean(UserService.class); + assertNotNull(userService); + assertEquals("blade", userService.getName()); + + UserServiceImpl userServiceImpl = ioc.getBean(UserServiceImpl.class); + + assertEquals(userService, userServiceImpl); + } + } From ea5a985b892e9c8c7770e7af86ba842a728887fe Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 19:48:16 +0800 Subject: [PATCH 387/545] add config kit --- .../main/java/blade/kit/ClassLoaderKit.java | 226 ++++++++++++++++++ .../src/main/java/blade/kit/ObjectKit.java | 1 + .../src/main/java/blade/kit/PropertyKit.java | 116 --------- blade-kit/src/main/java/blade/kit/XmlKit.java | 43 ++++ .../main/java/blade/kit/config/Config.java | 60 +++++ .../kit/config/adapter/ConfigAdapter.java | 104 ++++++++ .../kit/config/adapter/PropConfigAdapter.java | 74 ++++++ .../exception/ConfigAdapterException.java | 18 ++ .../kit/config/exception/LoadException.java | 18 ++ .../blade/kit/config/loader/ConfigLoader.java | 32 +++ .../java/blade/kit/reflect/ClassDefine.java | 108 +++++++++ .../blade/kit/{ => reflect}/ReflectKit.java | 25 +- .../main/java/blade/kit/reflect/TypeKit.java | 7 + 13 files changed, 715 insertions(+), 117 deletions(-) create mode 100644 blade-kit/src/main/java/blade/kit/ClassLoaderKit.java delete mode 100644 blade-kit/src/main/java/blade/kit/PropertyKit.java create mode 100644 blade-kit/src/main/java/blade/kit/XmlKit.java create mode 100644 blade-kit/src/main/java/blade/kit/config/Config.java create mode 100644 blade-kit/src/main/java/blade/kit/config/adapter/ConfigAdapter.java create mode 100644 blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java create mode 100644 blade-kit/src/main/java/blade/kit/config/exception/ConfigAdapterException.java create mode 100644 blade-kit/src/main/java/blade/kit/config/exception/LoadException.java create mode 100644 blade-kit/src/main/java/blade/kit/config/loader/ConfigLoader.java create mode 100644 blade-kit/src/main/java/blade/kit/reflect/ClassDefine.java rename blade-kit/src/main/java/blade/kit/{ => reflect}/ReflectKit.java (93%) create mode 100644 blade-kit/src/main/java/blade/kit/reflect/TypeKit.java diff --git a/blade-kit/src/main/java/blade/kit/ClassLoaderKit.java b/blade-kit/src/main/java/blade/kit/ClassLoaderKit.java new file mode 100644 index 000000000..b6127de90 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/ClassLoaderKit.java @@ -0,0 +1,226 @@ +package blade.kit; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +public class ClassLoaderKit { + private static final Map abbreviationMap; + + /** + * Returns current thread's context class loader + */ + public static ClassLoader getDefault() { + ClassLoader loader = null; + try { + loader = Thread.currentThread().getContextClassLoader(); + } catch (Exception e) { + } + if (loader == null) { + loader = ClassLoaderKit.class.getClassLoader(); + if (loader == null) { + loader = ClassLoader.getSystemClassLoader(); + } + } + return loader; + } + + /** + * 使用默认的 ClassLoader 去载入类. + * @return null if class not found + */ + public static Class loadClass(final String qualifiedClassName) { + return loadClass(qualifiedClassName, null); + } + + /** + * 使用默认的 ClassLoader 去载入类. + * @return null if class not found + */ + public static Class loadClass(final String qualifiedClassName, ClassLoader loader) { + try { + return loadClassEx(qualifiedClassName, loader); + } catch (ClassNotFoundException e) { + return null; + } + } + + /** + * 使用默认的 ClassLoader 去载入类. + * @throws ClassNotFoundException + */ + public static Class loadClassEx(final String qualifiedClassName) throws ClassNotFoundException { + return loadClassEx(qualifiedClassName, null); + } + + /** + * 使用指定的 ClassLoader 去载入类. + * @throws ClassNotFoundException + */ + public static Class loadClassEx(final String qualifiedClassName, final ClassLoader classLoader) throws ClassNotFoundException { + Assert.notNull(qualifiedClassName, "qualifiedClassName must be not null"); + + ClassLoader loader = (classLoader == null) ? getDefault() : classLoader; + + // 尝试基本类型 + if (abbreviationMap.containsKey(qualifiedClassName)) { + String className = '[' + abbreviationMap.get(qualifiedClassName); + return Class.forName(className, false, loader).getComponentType(); + } + + // 尝试用 Class.forName() + try { + String className = getCanonicalClassName(qualifiedClassName); + return Class.forName(className, false, loader); + } catch (ClassNotFoundException e) { + } + + // 尝试当做一个内部类去识别 + if (qualifiedClassName.indexOf('$') == -1) { + int ipos = qualifiedClassName.lastIndexOf('.'); + if (ipos > 0) { + try { + String className = qualifiedClassName.substring(0, ipos) + '$' + qualifiedClassName.substring(ipos + 1); + className = getCanonicalClassName(className); + return Class.forName(className, false, loader); + } catch (ClassNotFoundException e) { + } + } + } + + throw new ClassNotFoundException(qualifiedClassName); + } + + /** + * 将 Java 类名转为 {@code Class.forName()} 可以载入的类名格式. + *
+     * getCanonicalClassName("int") == "int";
+     * getCanonicalClassName("int[]") == "[I";
+     * getCanonicalClassName("java.lang.String") == "java.lang.String";
+     * getCanonicalClassName("java.lang.String[]") == "[Ljava.lang.String;";
+     * 
+ */ + public static String getCanonicalClassName(String qualifiedClassName) { + Assert.notNull(qualifiedClassName, "qualifiedClassName must be not null"); + + String name = StringKit.trimToEmpty(qualifiedClassName); + if (name.endsWith("[]")) { + StringBuilder sb = new StringBuilder(); + + while (name.endsWith("[]")) { + name = name.substring(0, name.length() - 2); + sb.append('['); + } + + String abbreviation = abbreviationMap.get(name); + if (abbreviation != null) { + sb.append(abbreviation); + } else { + sb.append('L').append(name).append(';'); + } + + name = sb.toString(); + } + return name; + } + + /** + * Finds the resource with the given name. + * @param name - The resource name + * @return A URL object for reading the resource, or null if the resource could not be found + */ + public static URL getResource(String name) { + return getResource(name, null); + } + + /** + * Finds the resource with the given name. + * @param name - The resource name + * @return A URL object for reading the resource, or null if the resource could not be found + */ + public static URL getResource(String name, ClassLoader classLoader) { + Assert.notNull(name, "resourceName must be not null"); + + if (name.startsWith("/")) { + name = name.substring(1); + } + if (classLoader != null) { + URL url = classLoader.getResource(name); + if (url != null) { + return url; + } + } + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + if (loader != null && loader != classLoader) { + URL url = loader.getResource(name); + if (url != null) { + return url; + } + } + + return ClassLoader.getSystemResource(name); + } + + /** + * Returns an input stream for reading the specified resource. + */ + public static InputStream getResourceAsStream(String name) throws IOException { + return getResourceAsStream(name, null); + } + + /** + * Returns an input stream for reading the specified resource. + */ + public static InputStream getResourceAsStream(String name, ClassLoader classLoader) throws IOException { + URL url = getResource(name, classLoader); + if (url != null) { + return url.openStream(); + } + return null; + } + + /** + * Returns an input stream for reading the specified class. + */ + public static InputStream getClassAsStream(Class clazz) throws IOException { + return getResourceAsStream(getClassFileName(clazz), clazz.getClassLoader()); + } + + /** + * Returns an input stream for reading the specified class. + */ + public static InputStream getClassAsStream(String qualifiedClassName) throws IOException { + return getResourceAsStream(getClassFileName(qualifiedClassName)); + } + + /** + * 获取一个 class 所代表的文件名 + */ + public static String getClassFileName(Class clazz) { + if (clazz.isArray()) { + clazz = clazz.getComponentType(); + } + return getClassFileName(clazz.getName()); + } + + /** + * 获取一个 class 所代表的文件名 + */ + public static String getClassFileName(String qualifiedClassName) { + return qualifiedClassName.replace('.', '/') + ".class"; + } + + static { + abbreviationMap = new HashMap(); + abbreviationMap.put("boolean", "Z"); + abbreviationMap.put("byte", "B"); + abbreviationMap.put("short", "S"); + abbreviationMap.put("char", "C"); + abbreviationMap.put("int", "I"); + abbreviationMap.put("long", "J"); + abbreviationMap.put("float", "F"); + abbreviationMap.put("double", "D"); + } +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/ObjectKit.java b/blade-kit/src/main/java/blade/kit/ObjectKit.java index 851325378..2fadab960 100644 --- a/blade-kit/src/main/java/blade/kit/ObjectKit.java +++ b/blade-kit/src/main/java/blade/kit/ObjectKit.java @@ -5,6 +5,7 @@ import java.util.Map; import blade.kit.exception.ReflectException; +import blade.kit.reflect.ReflectKit; public final class ObjectKit { diff --git a/blade-kit/src/main/java/blade/kit/PropertyKit.java b/blade-kit/src/main/java/blade/kit/PropertyKit.java deleted file mode 100644 index df197b4a3..000000000 --- a/blade-kit/src/main/java/blade/kit/PropertyKit.java +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Set; - -import blade.kit.log.Logger; - -/** - * properties文件工具类 - * - * @author biezhi - * @since 1.0 - */ -public class PropertyKit { - - private static final Logger logger = Logger.getLogger(PropertyKit.class); - - /** - * 根据文件名读取properties文件 - */ - public static Properties getProperty(String resourceName) { - InputStream in = null; - Properties props = new Properties(); - try { - in = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName); - if (in != null) { - props.load(in); - } - } catch (IOException e) { - logger.error("加载属性文件出错!", e); - } finally { - IOKit.closeQuietly(in); - } - return props; - } - - /** - * //TODO 根据文件名读取map数据 - */ - public static Map getPropertyMap(String resourceName) { - InputStream in = null; - Map map = CollectionKit.newHashMap(); - try { - in = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName); - if (null == in) { - throw new RuntimeException("没有找到资源文件 [" + resourceName + "]"); - } - Properties prop = new Properties(); - prop.load(in); - Set> set = prop.entrySet(); - Iterator> it = set.iterator(); - while (it.hasNext()) { - Entry entry = it.next(); - String key = entry.getKey().toString(); - String value = entry.getValue().toString(); - String fuKey = getWildcard(value); - if(null != fuKey && null != prop.get(fuKey)){ - String fuValue = prop.get(fuKey).toString(); - value = value.replaceAll("\\$\\{" + fuKey + "\\}", fuValue); - } - map.put(key, value); - } - logger.info("加载properties文件[" + resourceName + "]"); - } catch (IOException e) { - e.printStackTrace(); - } finally { - IOKit.closeQuietly(in); - } - return map; - } - - private static String getWildcard(String str){ - if(null != str && str.indexOf("${") != -1){ - int start = str.indexOf("${"); - int end = str.indexOf("}"); - if(start != -1 && end != -1){ - return str.substring(start + 2, end); - } - } - return null; - } - - /** - * //TODO 根据property对象获取map格式数据 - */ - public static Map getPropertyMap(Properties prop) { - Map map = CollectionKit.newHashMap(); - Set> set = prop.entrySet(); - Iterator> it = set.iterator(); - while (it.hasNext()) { - Entry entry = it.next(); - map.put(entry.getKey().toString(), entry.getValue().toString()); - } - return map; - } -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/XmlKit.java b/blade-kit/src/main/java/blade/kit/XmlKit.java new file mode 100644 index 000000000..ccb04e6f6 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/XmlKit.java @@ -0,0 +1,43 @@ +package blade.kit; + +import java.io.File; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Node; +import org.dom4j.io.SAXReader; +import org.xml.sax.SAXException; + +public class XmlKit { + + private Document document; + + public XmlKit(String filePath) { + String xmlPath = XmlKit.class.getResource(filePath).toString(); + if (xmlPath.substring(5).indexOf(":") > 0) { + // 路径中含有:分隔符,windows系统 + xmlPath = xmlPath.substring(6); + } else { + xmlPath = xmlPath.substring(5); + } + SAXReader reader = new SAXReader(); + try { + reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + this.document = reader.read(new File(xmlPath)); + } catch (SAXException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } + } + + public String attrValue(String strXPath) { + Node n = document.selectSingleNode(strXPath); + if (n != null) { + return (n.valueOf("@value")); + } else { + return null; + } + } + +} diff --git a/blade-kit/src/main/java/blade/kit/config/Config.java b/blade-kit/src/main/java/blade/kit/config/Config.java new file mode 100644 index 000000000..789ee38db --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/config/Config.java @@ -0,0 +1,60 @@ +package blade.kit.config; + +import java.util.Map; + +/** + * 配置文件顶层接口,用于获取配置文件的真实数据 + * + */ +public interface Config { + + /** + * 获取一个String类型的值 + * + * @param key 要获取的key + * @return 返回string + */ + String getString(String key); + + /** + * 获取一个Integer类型的值 + * + * @param key 要获取的key + * @return 返回int或者null + */ + Integer getInt(String key); + + /** + * 获取一个Long类型的值 + * + * @param key 要获取的key + * @return 返回long或者null + */ + Long getLong(String key); + + /** + * 获取一个Boolean类型的值 + * + * @param key 要获取的key + * @return 返回boolean或者null + */ + Boolean getBoolean(String key); + + /** + * 获取一个Double类型的值 + * + * @param key 要获取的key + * @return 返回double或者null + */ + Double getDouble(String key); + + Map getConfigMap(); + + /** + * 将获取到的配置文件转换成一个接口 + * + * @param type 接口类型 + * @return 返回接口对象 + */ + T get(Class type); +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/config/adapter/ConfigAdapter.java b/blade-kit/src/main/java/blade/kit/config/adapter/ConfigAdapter.java new file mode 100644 index 000000000..fce3e1edf --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/config/adapter/ConfigAdapter.java @@ -0,0 +1,104 @@ +package blade.kit.config.adapter; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Map; + +import blade.kit.config.Config; + +/** + * 配置适配器,用于适配各种配置文件,解析成Config接口 + * 实现类需要完成的就是向configMap内赋值 + */ +public abstract class ConfigAdapter implements Config { + + /** + * 存储配置数据 + */ + protected Map configMap = new HashMap(); + + public String getString(String key) { + Object object = configMap.get(key); + if(null != object){ + return object.toString(); + } + return null; + } + + public Integer getInt(String key) { + String value = this.getString(key); + if(null != value){ + return Integer.parseInt(value); + } + return null; + } + + public Long getLong(String key) { + String value = this.getString(key); + if(null != value){ + return Long.parseLong(value); + } + return null; + } + + public Boolean getBoolean(String key) { + String value = this.getString(key); + if(null != value){ + return Boolean.parseBoolean(value); + } + return null; + } + + public Double getDouble(String key) { + String value = this.getString(key); + if(null != value){ + return Double.parseDouble(value); + } + return null; + } + + public T get(Class t) { + try { + @SuppressWarnings("unchecked") + T tobj = (T) Proxy.newProxyInstance(t.getClassLoader(), + new Class[] { t }, new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + + String method_name = method.getName(); + Class returnClazz = method.getReturnType(); + + if(returnClazz == String.class){ + return ConfigAdapter.this.getString(method_name); + } + + if (returnClazz == Integer.class || returnClazz == int.class) { + return ConfigAdapter.this.getInt(method_name); + } + + if(returnClazz == Long.class || returnClazz == long.class){ + return ConfigAdapter.this.getLong(method_name); + } + + if(returnClazz == Double.class || returnClazz == double.class){ + return ConfigAdapter.this.getDouble(method_name); + } + + if(returnClazz == Boolean.class || returnClazz == boolean.class){ + return ConfigAdapter.this.getBoolean(method_name); + } + return null; + } + }); + return tobj; + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + return null; + } + + public abstract Config read(String conf); + +} diff --git a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java new file mode 100644 index 000000000..c880c0ce9 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java @@ -0,0 +1,74 @@ +package blade.kit.config.adapter; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; + +import blade.kit.IOKit; +import blade.kit.config.Config; +import blade.kit.config.exception.ConfigAdapterException; +import blade.kit.log.Logger; + +/** + * 解析Properties配置文件 + * + */ +public class PropConfigAdapter extends ConfigAdapter { + + private static final Logger LOGGER = Logger.getLogger(PropConfigAdapter.class); + + @Override + public Config read(String prop_file) { + + Properties props = new Properties(); + InputStream in = null; + try { + in = Thread.currentThread().getContextClassLoader().getResourceAsStream(prop_file); + if (in != null) { + props.load(in); + } + // 解析properties文件 + Set> set = props.entrySet(); + Iterator> it = set.iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + String key = entry.getKey().toString(); + String value = entry.getValue().toString(); + String fuKey = getWildcard(value); + if(null != fuKey && null != props.get(fuKey)){ + String fuValue = props.get(fuKey).toString(); + value = value.replaceAll("\\$\\{" + fuKey + "\\}", fuValue); + } + configMap.put(key, value); + } + + LOGGER.debug("加载properties文件 [" + prop_file + "]"); + return this; + } catch (IOException e) { + throw new ConfigAdapterException("load properties file error!"); + } finally { + IOKit.closeQuietly(in); + } + } + + private String getWildcard(String str){ + if(null != str && str.indexOf("${") != -1){ + int start = str.indexOf("${"); + int end = str.indexOf("}"); + if(start != -1 && end != -1){ + return str.substring(start + 2, end); + } + } + return null; + } + + @Override + public Map getConfigMap() { + return configMap; + } + +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/config/exception/ConfigAdapterException.java b/blade-kit/src/main/java/blade/kit/config/exception/ConfigAdapterException.java new file mode 100644 index 000000000..9b21b75a2 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/config/exception/ConfigAdapterException.java @@ -0,0 +1,18 @@ +package blade.kit.config.exception; + +/** + * 配置适配异常 + */ +public class ConfigAdapterException extends RuntimeException { + + private static final long serialVersionUID = 6118361499832602075L; + + public ConfigAdapterException(String msg){ + super(msg); + } + + public ConfigAdapterException(Throwable t){ + super(t); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/config/exception/LoadException.java b/blade-kit/src/main/java/blade/kit/config/exception/LoadException.java new file mode 100644 index 000000000..b082aeb8c --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/config/exception/LoadException.java @@ -0,0 +1,18 @@ +package blade.kit.config.exception; + +/** + * 配置加载异常 + */ +public class LoadException extends RuntimeException { + + private static final long serialVersionUID = 713951618562461059L; + + public LoadException(String msg){ + super(msg); + } + + public LoadException(Throwable t){ + super(t); + } + +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/config/loader/ConfigLoader.java b/blade-kit/src/main/java/blade/kit/config/loader/ConfigLoader.java new file mode 100644 index 000000000..baa7a41f0 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/config/loader/ConfigLoader.java @@ -0,0 +1,32 @@ +package blade.kit.config.loader; + +import blade.kit.config.Config; +import blade.kit.config.adapter.ConfigAdapter; +import blade.kit.config.adapter.PropConfigAdapter; +import blade.kit.config.exception.LoadException; +import blade.kit.reflect.ReflectKit; + +/** + * 配置加载器,用于加载配置文件 + */ +public class ConfigLoader { + + public static Config load(String conf){ + return load(conf, PropConfigAdapter.class); + } + + public static Config load(String conf, Class adapter){ + + if(null == conf || conf.equals("")){ + throw new LoadException("the config file name is null"); + } + + if(null == adapter){ + throw new LoadException("the config adapter class is null"); + } + + ConfigAdapter configAdapter = ReflectKit.newBean(adapter); + + return configAdapter.read(conf); + } +} diff --git a/blade-kit/src/main/java/blade/kit/reflect/ClassDefine.java b/blade-kit/src/main/java/blade/kit/reflect/ClassDefine.java new file mode 100644 index 000000000..e35ccc33c --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/reflect/ClassDefine.java @@ -0,0 +1,108 @@ +package blade.kit.reflect; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public final class ClassDefine { + + private static final ConcurrentHashMap, ClassDefine> pool = new ConcurrentHashMap, ClassDefine>(128); + + private final Class clazz; + + private ClassDefine(Class type) { + this.clazz = type; + } + + public static ClassDefine create(Class clazz){ + ClassDefine classDefine = pool.get(clazz); + if (classDefine == null) { + classDefine = new ClassDefine(clazz); + ClassDefine old = pool.putIfAbsent(clazz, classDefine); + if (old != null) { + classDefine = old; + } + } + return classDefine; + } + + @SuppressWarnings("unchecked") + public Class getType() { + return (Class) clazz; + } + + public String getName() { + return clazz.getName(); + } + + public String getSimpleName() { + return clazz.getSimpleName(); + } + + public ClassDefine getSuperKlass() { + Class superKlass = clazz.getSuperclass(); + return (superKlass == null) ? null : ClassDefine.create(superKlass); + } + + public List getInterfaces() { + Class[] interfaces = clazz.getInterfaces(); + if (interfaces.length == 0) { + return Collections.emptyList(); + } + List results = new ArrayList(interfaces.length); + for (Class intf : interfaces) { + results.add(ClassDefine.create(intf)); + } + return results; + } + + // ------------------------------------------------------------------ + public Annotation[] getAnnotations() { + return clazz.getAnnotations(); + } + + public T getAnnotation(Class annotationClass) { + return clazz.getAnnotation(annotationClass); + } + + public boolean isAnnotationPresent(Class annotationClass) { + return clazz.isAnnotationPresent(annotationClass); + } + + public Field[] getDeclaredFields() { + return clazz.getDeclaredFields(); + } + + // ------------------------------------------------------------------ + public int getModifiers() { + return clazz.getModifiers(); + } + + public boolean isInterface() { + return Modifier.isInterface(getModifiers()); + } + + public boolean isAbstract() { + return Modifier.isAbstract(getModifiers()); + } + + public boolean isStatic() { + return Modifier.isStatic(getModifiers()); + } + + public boolean isPrivate() { + return Modifier.isPrivate(getModifiers()); + } + + public boolean isProtected() { + return Modifier.isProtected(getModifiers()); + } + + public boolean isPublic() { + return Modifier.isPublic(getModifiers()); + } +} diff --git a/blade-kit/src/main/java/blade/kit/ReflectKit.java b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java similarity index 93% rename from blade-kit/src/main/java/blade/kit/ReflectKit.java rename to blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java index 49b5b0002..bdda07446 100644 --- a/blade-kit/src/main/java/blade/kit/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package blade.kit.reflect; import java.io.File; import java.io.IOException; @@ -31,6 +31,10 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; +import blade.kit.Emptys; +import blade.kit.ExceptionKit; +import blade.kit.StringKit; +import blade.kit.SystemKit; import blade.kit.log.Logger; /** @@ -67,6 +71,25 @@ public static Object newInstance(String className) throws InstantiationException public static Object newInstance(Class clazz) throws InstantiationException, IllegalAccessException{ return clazz.newInstance(); } + + /** + * 创建一个实例对象 + * @param clazz class对象 + * @return + * @throws IllegalAccessException + * @throws InstantiationException + */ + public static T newBean(Class clazz) { + try { + Object object = clazz.newInstance(); + return clazz.cast(object); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } /** 用setter设置bean属性 * @throws InvocationTargetException diff --git a/blade-kit/src/main/java/blade/kit/reflect/TypeKit.java b/blade-kit/src/main/java/blade/kit/reflect/TypeKit.java new file mode 100644 index 000000000..724a445e6 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/reflect/TypeKit.java @@ -0,0 +1,7 @@ +package blade.kit.reflect; + +public final class TypeKit { + + public static void main(String[] args) { + } +} From 9094be2ade54835f403cd719b63dfeaf8ff64ef9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 19:50:40 +0800 Subject: [PATCH 388/545] - --- blade-core/src/main/java/com/blade/Blade.java | 29 +++++-------------- .../loader/{Config.java => BladeConfig.java} | 4 +-- .../java/com/blade/loader/Configurator.java | 4 +-- .../java/com/blade/web/RouteArgument.java | 4 +-- 4 files changed, 13 insertions(+), 28 deletions(-) rename blade-core/src/main/java/com/blade/loader/{Config.java => BladeConfig.java} (98%) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 2160f2875..c7b0d5232 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -24,7 +24,7 @@ import com.blade.ioc.Ioc; import com.blade.ioc.SampleIoc; import com.blade.loader.ClassPathRouteLoader; -import com.blade.loader.Config; +import com.blade.loader.BladeConfig; import com.blade.loader.Configurator; import com.blade.plugin.Plugin; import com.blade.render.JspRender; @@ -38,7 +38,7 @@ import blade.kit.Assert; import blade.kit.IOKit; -import blade.kit.PropertyKit; +import blade.kit.config.loader.ConfigLoader; import blade.kit.json.JSONKit; /** @@ -67,7 +67,7 @@ public class Blade { /** * Global configuration Object */ - private Config config = null; + private BladeConfig config = null; /** * IOC Container, save javabean @@ -100,7 +100,7 @@ public class Blade { private Server bladeServer; private Blade() { - this.config = new Config(); + this.config = new BladeConfig(); this.ioc = new SampleIoc(); this.iocApplication = new IocApplication(ioc); this.routers = new Routers(ioc); @@ -160,21 +160,6 @@ public Blade container(Ioc ioc){ return this; } - /** - * Setting Properties configuration file - * File path based on classpath - * - * @param confName properties file name - * @return return blade - */ - @Deprecated - public Blade config(String confName){ - Assert.notBlank(confName); - Map configMap = PropertyKit.getPropertyMap(confName); - configuration(configMap); - return this; - } - /** * Setting Properties configuration file * File path based on classpath @@ -184,8 +169,8 @@ public Blade config(String confName){ */ public Blade setAppConf(String confName){ Assert.notBlank(confName); - Map configMap = PropertyKit.getPropertyMap(confName); - configuration(configMap); + blade.kit.config.Config config = ConfigLoader.load(confName); + this.configuration(config.getConfigMap()); return this; } @@ -660,7 +645,7 @@ public void join() throws InterruptedException { /** * @return Return blade config object */ - public Config config(){ + public BladeConfig config(){ return config; } diff --git a/blade-core/src/main/java/com/blade/loader/Config.java b/blade-core/src/main/java/com/blade/loader/BladeConfig.java similarity index 98% rename from blade-core/src/main/java/com/blade/loader/Config.java rename to blade-core/src/main/java/com/blade/loader/BladeConfig.java index 54e147b58..de4877704 100644 --- a/blade-core/src/main/java/com/blade/loader/Config.java +++ b/blade-core/src/main/java/com/blade/loader/BladeConfig.java @@ -29,7 +29,7 @@ * @since 1.0 * */ -public class Config { +public class BladeConfig { // Store all variables private Map configMap = CollectionKit.newHashMap(); @@ -73,7 +73,7 @@ public class Config { // Enabled XSS private boolean enableXSS = false; - public Config() { + public BladeConfig() { } public Map getConfigMap() { diff --git a/blade-core/src/main/java/com/blade/loader/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java index 3eccaed44..00e81b86b 100644 --- a/blade-core/src/main/java/com/blade/loader/Configurator.java +++ b/blade-core/src/main/java/com/blade/loader/Configurator.java @@ -28,12 +28,12 @@ public class Configurator { // Configuration object - private Config bladeConfig; + private BladeConfig bladeConfig; // Configuration Map private Map configMap; - public Configurator(Config bladeConfig, + public Configurator(BladeConfig bladeConfig, Map configMap) { this.bladeConfig = bladeConfig; this.configMap = configMap; diff --git a/blade-core/src/main/java/com/blade/web/RouteArgument.java b/blade-core/src/main/java/com/blade/web/RouteArgument.java index 0b067afc2..a81acaa39 100644 --- a/blade-core/src/main/java/com/blade/web/RouteArgument.java +++ b/blade-core/src/main/java/com/blade/web/RouteArgument.java @@ -17,12 +17,12 @@ import java.lang.reflect.Method; -import blade.kit.ReflectKit; - import com.blade.web.http.Request; import com.blade.web.http.Response; import com.blade.web.http.ResponsePrint; +import blade.kit.reflect.ReflectKit; + /** * Route parameters of injector * From f4149c84c36f088a42d03af07f94419538ec01b5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 20:55:13 +0800 Subject: [PATCH 389/545] reconstruction json kit --- blade-kit/pom.xml | 14 +- .../src/main/java/blade/kit/json/JSON.java | 333 ++++++ .../main/java/blade/kit/json/JSONArray.java | 559 +++++++++ .../main/java/blade/kit/json/JSONHelper.java | 237 ++++ .../src/main/java/blade/kit/json/JSONKit.java | 28 +- .../{JsonLiteral.java => JSONLiteral.java} | 194 ++-- .../json/{JsonNumber.java => JSONNumber.java} | 188 +-- .../main/java/blade/kit/json/JSONObject.java | 1026 +++++++++++++++++ .../json/{JsonParser.java => JSONParser.java} | 812 ++++++------- .../json/{JsonString.java => JSONString.java} | 148 +-- .../json/{JsonValue.java => JSONValue.java} | 1000 ++++++++-------- .../json/{JsonWriter.java => JSONWriter.java} | 290 ++--- .../src/main/java/blade/kit/json/Json.java | 427 ------- .../main/java/blade/kit/json/JsonArray.java | 457 -------- .../main/java/blade/kit/json/JsonObject.java | 966 ---------------- .../java/blade/kit/json/ParseException.java | 140 +-- .../main/java/blade/kit/json/PrettyPrint.java | 314 ++--- .../java/blade/kit/json/WriterConfig.java | 100 +- .../java/blade/kit/json/WritingBuffer.java | 198 ++-- .../src/test/java/com/blade/kit/JSONTest.java | 15 +- 20 files changed, 3894 insertions(+), 3552 deletions(-) create mode 100644 blade-kit/src/main/java/blade/kit/json/JSON.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONArray.java create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONHelper.java rename blade-kit/src/main/java/blade/kit/json/{JsonLiteral.java => JSONLiteral.java} (90%) rename blade-kit/src/main/java/blade/kit/json/{JsonNumber.java => JSONNumber.java} (90%) create mode 100644 blade-kit/src/main/java/blade/kit/json/JSONObject.java rename blade-kit/src/main/java/blade/kit/json/{JsonParser.java => JSONParser.java} (84%) rename blade-kit/src/main/java/blade/kit/json/{JsonString.java => JSONString.java} (89%) rename blade-kit/src/main/java/blade/kit/json/{JsonValue.java => JSONValue.java} (88%) rename blade-kit/src/main/java/blade/kit/json/{JsonWriter.java => JSONWriter.java} (96%) delete mode 100644 blade-kit/src/main/java/blade/kit/json/Json.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JsonArray.java delete mode 100644 blade-kit/src/main/java/blade/kit/json/JsonObject.java diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index cb55afd48..51e33607c 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - 1.2.8 + 1.2.9-alpha blade-kit https://github.com/biezhi/blade/tree/master/blade-kit @@ -36,6 +36,18 @@ 1.2.17 provided + + dom4j + dom4j + 1.6.1 + provided + + + jaxen + jaxen + 1.1.6 + provided + javax.servlet javax.servlet-api diff --git a/blade-kit/src/main/java/blade/kit/json/JSON.java b/blade-kit/src/main/java/blade/kit/json/JSON.java new file mode 100644 index 000000000..9b0144f5c --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSON.java @@ -0,0 +1,333 @@ +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Reader; + + +/** + * This class serves as the entry point to the minimal-json API. + *

+ * To parse a given JSON input, use the parse() methods like in this + * example: + *

+ *
+ * JsonObject object = Json.parse(string).asObject();
+ * 
+ *

+ * To create a JSON data structure to be serialized, use the methods + * value(), array(), and object(). For example, the following + * snippet will produce the JSON string {"foo": 23, "bar": true}: + *

+ *
+ * String string = Json.object().add("foo", 23).add("bar", true).toString();
+ * 
+ *

+ * To create a JSON array from a given Java array, you can use one of the array() + * methods with varargs parameters: + *

+ *
+ * String[] names = ...
+ * JsonArray array = Json.array(names);
+ * 
+ */ +public final class JSON { + + private JSON() { + // not meant to be instantiated + } + + /** + * Represents the JSON literal null. + */ + public static final JSONValue NULL = new JSONLiteral("null"); + + /** + * Represents the JSON literal true. + */ + public static final JSONValue TRUE = new JSONLiteral("true"); + + /** + * Represents the JSON literal false. + */ + public static final JSONValue FALSE = new JSONLiteral("false"); + + /** + * Returns a JsonValue instance that represents the given int value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JSONValue value(int value) { + return new JSONNumber(Integer.toString(value, 10)); + } + + /** + * Returns a JsonValue instance that represents the given long value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JSONValue value(long value) { + return new JSONNumber(Long.toString(value, 10)); + } + + /** + * Returns a JsonValue instance that represents the given float value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JSONValue value(float value) { + if (Float.isInfinite(value) || Float.isNaN(value)) { + throw new IllegalArgumentException("Infinite and NaN values not permitted in JSON"); + } + return new JSONNumber(cutOffPointZero(Float.toString(value))); + } + + /** + * Returns a JsonValue instance that represents the given double value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JSONValue value(double value) { + if (Double.isInfinite(value) || Double.isNaN(value)) { + throw new IllegalArgumentException("Infinite and NaN values not permitted in JSON"); + } + return new JSONNumber(cutOffPointZero(Double.toString(value))); + } + + /** + * Returns a JsonValue instance that represents the given string. + * + * @param string + * the string to get a JSON representation for + * @return a JSON value that represents the given string + */ + public static JSONValue value(String string) { + return string == null ? NULL : new JSONString(string); + } + + /** + * Returns a JsonValue instance that represents the given boolean value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JSONValue value(boolean value) { + return value ? TRUE : FALSE; + } + + /** + * Creates a new empty JsonArray. This is equivalent to creating a new JsonArray using the + * constructor. + * + * @return a new empty JSON array + */ + public static JSONValue array() { + return new JSONArray(); + } + + /** + * Creates a new JsonArray that contains the JSON representations of the given int + * values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JSONArray array(int... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (int value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the given long + * values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JSONArray array(long... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (long value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the given float + * values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JSONArray array(float... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (float value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the given double + * values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JSONArray array(double... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (double value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the given + * boolean values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JSONArray array(boolean... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (boolean value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the given strings. + * + * @param strings + * the strings to be included in the new JSON array + * @return a new JSON array that contains the given strings + */ + public static JSONArray array(String... strings) { + if (strings == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (String value : strings) { + array.add(value); + } + return array; + } + + /** + * Creates a new empty JsonObject. This is equivalent to creating a new JsonObject using the + * constructor. + * + * @return a new empty JSON object + */ + public static JSONObject object() { + return new JSONObject(); + } + + /** + * Parses the given input string as JSON. The input must contain a valid JSON value, optionally + * padded with whitespace. + * + * @param string + * the input string, must be valid JSON + * @return a value that represents the parsed JSON + * @throws ParseException + * if the input is not valid JSON + */ + public static JSONValue parse(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + try { + return new JSONParser(string).parse(); + } catch (IOException exception) { + // JsonParser does not throw IOException for String + throw new RuntimeException(exception); + } + } + + /** + * Reads the entire input stream from the given reader and parses it as JSON. The input must + * contain a valid JSON value, optionally padded with whitespace. + *

+ * Characters are read in chunks and buffered internally, therefore wrapping an existing reader in + * an additional BufferedReader does not improve reading + * performance. + *

+ * + * @param reader + * the reader to read the JSON value from + * @return a value that represents the parsed JSON + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + */ + public static JSONValue parse(Reader reader) throws IOException { + if (reader == null) { + throw new NullPointerException("reader is null"); + } + return new JSONParser( reader ).parse(); + } + + private static String cutOffPointZero(String string) { + if (string.endsWith(".0")) { + return string.substring(0, string.length() - 2); + } + return string; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONArray.java b/blade-kit/src/main/java/blade/kit/json/JSONArray.java new file mode 100644 index 000000000..b26bd8bae --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONArray.java @@ -0,0 +1,559 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Represents a JSON array, an ordered collection of JSON values. + *

+ * Elements can be added using the add(...) methods which accept + * instances of {@link JSONValue}, strings, primitive numbers, and boolean + * values. To replace an element of an array, use the set(int, ...) + * methods. + *

+ *

+ * Elements can be accessed by their index using {@link #get(int)}. This class + * also supports iterating over the elements in document order using an + * {@link #iterator()} or an enhanced for loop: + *

+ * + *
+ * for (JsonValue value : jsonArray) {
+ *   ...
+ * }
+ * 
+ *

+ * An equivalent {@link List} can be obtained from the method {@link #values()}. + *

+ *

+ * Note that this class is not thread-safe. If multiple threads + * access a JsonArray instance concurrently, while at least one of + * these threads modifies the contents of this array, access to the instance + * must be synchronized externally. Failure to do so may lead to an inconsistent + * state. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public class JSONArray extends JSONValue implements Iterable { + + private final List values; + + /** + * Creates a new empty JsonArray. + */ + public JSONArray() { + values = new ArrayList(); + } + + /** + * Creates a new JsonArray with the contents of the specified JSON array. + * + * @param array + * the JsonArray to get the initial contents from, must not be + * null + */ + public JSONArray(JSONArray array) { + this(array, false); + } + + private JSONArray(JSONArray array, boolean unmodifiable) { + if (array == null) { + throw new NullPointerException("array is null"); + } + if (unmodifiable) { + values = Collections.unmodifiableList(array.values); + } else { + values = new ArrayList(array.values); + } + } + + /** + * Reads a JSON array from the given reader. + *

+ * Characters are read in chunks and buffered internally, therefore wrapping + * an existing reader in an additional BufferedReader does + * not improve reading performance. + *

+ * + * @param reader + * the reader to read the JSON array from + * @return the JSON array that has been read + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + * @throws UnsupportedOperationException + * if the input does not contain a JSON array + * @deprecated Use {@link JSON#parse(Reader)}{@link JSONValue#asArray() + * .asArray()} instead + */ + @Deprecated + public static JSONArray readFrom(Reader reader) throws IOException { + return JSONValue.readFrom(reader).asArray(); + } + + /** + * Reads a JSON array from the given string. + * + * @param string + * the string that contains the JSON array + * @return the JSON array that has been read + * @throws ParseException + * if the input is not valid JSON + * @throws UnsupportedOperationException + * if the input does not contain a JSON array + * @deprecated Use {@link JSON#parse(String)}{@link JSONValue#asArray() + * .asArray()} instead + */ + @Deprecated + public static JSONArray readFrom(String string) { + return JSONValue.readFrom(string).asArray(); + } + + /** + * Returns an unmodifiable wrapper for the specified JsonArray. This method + * allows to provide read-only access to a JsonArray. + *

+ * The returned JsonArray is backed by the given array and reflects + * subsequent changes. Attempts to modify the returned JsonArray result in + * an UnsupportedOperationException. + *

+ * + * @param array + * the JsonArray for which an unmodifiable JsonArray is to be + * returned + * @return an unmodifiable view of the specified JsonArray + */ + public static JSONArray unmodifiableArray(JSONArray array) { + return new JSONArray(array, true); + } + + /** + * Appends the JSON representation of the specified int value + * to the end of this array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(int value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified long value + * to the end of this array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(long value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified float value + * to the end of this array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(float value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified double + * value to the end of this array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(double value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified boolean + * value to the end of this array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(boolean value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified string to the end of + * this array. + * + * @param value + * the string to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(String value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the specified JSON value to the end of this array. + * + * @param value + * the JsonValue to add to the array, must not be + * null + * @return the array itself, to enable method chaining + */ + public JSONArray add(JSONValue value) { + if (value == null) { + throw new NullPointerException("value is null"); + } + values.add(value); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified int value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, int value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified long value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, long value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified float value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, float value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified double value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, double value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified boolean value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, boolean value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified string. + * + * @param index + * the index of the array element to replace + * @param value + * the string to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, String value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * specified JSON value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position, must + * not be null + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, JSONValue value) { + if (value == null) { + throw new NullPointerException("value is null"); + } + values.set(index, value); + return this; + } + + /** + * Removes the element at the specified index from this array. + * + * @param index + * the index of the element to remove + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray remove(int index) { + values.remove(index); + return this; + } + + /** + * Returns the number of elements in this array. + * + * @return the number of elements in this array + */ + public int size() { + return values.size(); + } + + /** + * Returns true if this array contains no elements. + * + * @return true if this array contains no elements + */ + public boolean isEmpty() { + return values.isEmpty(); + } + + /** + * Returns the value of the element at the specified position in this array. + * + * @param index + * the index of the array element to return + * @return the value of the element at the specified position + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONValue get(int index) { + return values.get(index); + } + + public JSONObject getJSONObject(int index) { + JSONValue jsonValue = values.get(index); + if (null != jsonValue) { + return jsonValue.asObject(); + } + return null; + } + + public String getString(int index) { + JSONValue jsonValue = values.get(index); + if (null != jsonValue) { + return jsonValue.asString(); + } + return null; + } + + public Integer getInt(int index) { + JSONValue jsonValue = values.get(index); + if (null != jsonValue) { + return jsonValue.asInt(); + } + return null; + } + + public Long getLong(int index) { + JSONValue jsonValue = values.get(index); + if (null != jsonValue) { + return jsonValue.asLong(); + } + return null; + } + + public Double getDouble(int index) { + JSONValue jsonValue = values.get(index); + if (null != jsonValue) { + return jsonValue.asDouble(); + } + return null; + } + + public Boolean getBoolean(int index) { + JSONValue jsonValue = values.get(index); + if (null != jsonValue) { + return jsonValue.asBoolean(); + } + return null; + } + + /** + * Returns a list of the values in this array in document order. The + * returned list is backed by this array and will reflect subsequent + * changes. It cannot be used to modify this array. Attempts to modify the + * returned list will result in an exception. + * + * @return a list of the values in this array + */ + public List values() { + return Collections.unmodifiableList(values); + } + + /** + * Returns an iterator over the values of this array in document order. The + * returned iterator cannot be used to modify this array. + * + * @return an iterator over the values of this array + */ + public Iterator iterator() { + final Iterator iterator = values.iterator(); + return new Iterator() { + + public boolean hasNext() { + return iterator.hasNext(); + } + + public JSONValue next() { + return iterator.next(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeArrayOpen(); + Iterator iterator = iterator(); + boolean first = true; + while (iterator.hasNext()) { + if (!first) { + writer.writeArraySeparator(); + } + iterator.next().write(writer); + first = false; + } + writer.writeArrayClose(); + } + + @Override + public boolean isArray() { + return true; + } + + @Override + public JSONArray asArray() { + return this; + } + + @Override + public int hashCode() { + return values.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONArray other = (JSONArray) object; + return values.equals(other.values); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONHelper.java b/blade-kit/src/main/java/blade/kit/json/JSONHelper.java new file mode 100644 index 000000000..2154b2a10 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONHelper.java @@ -0,0 +1,237 @@ +package blade.kit.json; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +public class JSONHelper { + + public static Object jsonValueAsObject(JSONValue value) { + if (value.isBoolean()) + return value.asBoolean(); + else if (value.isNumber()) + return value.asInt(); + else if (value.isString()) + return value.asString(); + else if (value.isArray()) + return jsonArrayAsList(value.asArray()); + else if (value.isObject()) + return parseToMap(value.asObject()); + else + return null; + } + + public static Set jsonArrayAsSet(JSONArray array) { + Set set = new HashSet(); + for (JSONValue value : array) + set.add(jsonValueAsObject(value)); + return set; + } + + public static List jsonArrayAsList(JSONArray array) { + List list = new ArrayList(array.size()); + for (JSONValue element : array) + list.add(jsonValueAsObject(element)); + return list; + } + + @SuppressWarnings("unchecked") + public static Map parseToMap(JSONObject object) { + Map map = new HashMap(object.size(), 1.f); + for (JSONObject.Member member : object) { + V v = (V) jsonValueAsObject(member.getValue()); + map.put(member.getName(), v); + } + return map; + } + + public static Map parseToMap(String json) { + try { + JSONObject jsonObject = JSON.parse(json).asObject(); + return parseToMap(jsonObject); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static JSONValue objectAsJsonValue(Object object) { + if (object == null) + return JSON.NULL; + else if (object instanceof Boolean) + return JSON.value((Boolean) object); + else if (object instanceof Integer) + return JSON.value((Integer) object); + else if (object instanceof Long) + return JSON.value((Long) object); + else if (object instanceof Float) + return JSON.value((Float) object); + else if (object instanceof Double) + return JSON.value((Double) object); + else if (object instanceof String) + return JSON.value((String) object); + else if (object instanceof Collection) + return collectionAsJsonArray((Collection) object); + else if (object instanceof Map) + return mapAsJsonObject((Map) object); + else + return null; + } + + public static JSONObject parseJSONObject(Object object) { + Map map = bean2map(object); + if (null != map) { + return mapAsJsonObject(map); + } + return null; + } + + public static JSONArray parseJSONArray(Object object) { + JSONValue jsonValue = objectAsJsonValue(object); + if (null != jsonValue) { + return jsonValue.asArray(); + } + return null; + } + + public static JSONArray collectionAsJsonArray(Collection collection) { + JSONArray array = new JSONArray(); + for (Object element : collection) + array.add(objectAsJsonValue(element)); + return array; + } + + public static JSONObject mapAsJsonObject(Map map) { + JSONObject object = new JSONObject(); + for (Entry entry : map.entrySet()) + object.put(String.valueOf(entry.getKey()), objectAsJsonValue(entry.getValue())); + return object; + } + + // Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map + private static Map bean2map(Object obj) { + if (obj == null) { + return null; + } + Map map = new HashMap(); + try { + BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()); + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + for (PropertyDescriptor property : propertyDescriptors) { + String key = property.getName(); + // 过滤class属性 + if (!key.equals("class")) { + // 得到property对应的getter方法 + Method getter = property.getReadMethod(); + Object value = getter.invoke(obj); + map.put(key, value); + } + } + } catch (Exception e) { + System.out.println("transBean2Map Error " + e); + } + return map; + } + + // Map --> Bean 1: 利用Introspector,PropertyDescriptor实现 Map --> Bean + private static T map2bean(Map map, Class type) { + T obj = null; + try { + obj = type.getConstructor().newInstance(); + BeanInfo beanInfo = Introspector.getBeanInfo(type); + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + for (PropertyDescriptor property : propertyDescriptors) { + String key = property.getName(); + if (map.containsKey(key)) { + Object value = map.get(key); + // 得到property对应的setter方法 + Method setter = property.getWriteMethod(); + setter.invoke(obj, value); + } + } + } catch (Exception e) { + System.out.println("transMap2Bean Error " + e); + } + return obj; + } + + public static T parse(JSONObject jsonObject, Class type) { + Map map = parseToMap(jsonObject); + return map2bean(map, type); + } + + /** + * 对象转换为JsonValue对象 + * + * @param bean + * @return + */ + public static JSONObject parse(Object bean) { + JSONObject json = new JSONObject(); + Class klass = bean.getClass(); + boolean includeSuperClass = klass.getClassLoader() != null; + + Method[] methods = includeSuperClass ? klass.getMethods() : klass.getDeclaredMethods(); + for (int i = 0; i < methods.length; i += 1) { + try { + Method method = methods[i]; + if (Modifier.isPublic(method.getModifiers())) { + String name = method.getName(); + String key = ""; + if (name.startsWith("get")) { + if ("getClass".equals(name) || "getDeclaringClass".equals(name)) { + key = ""; + } else { + key = name.substring(3); + } + } else if (name.startsWith("is")) { + key = name.substring(2); + } + if (key.length() > 0 && Character.isUpperCase(key.charAt(0)) + && method.getParameterTypes().length == 0) { + if (key.length() == 1) { + key = key.toLowerCase(); + } else if (!Character.isUpperCase(key.charAt(1))) { + key = key.substring(0, 1).toLowerCase() + key.substring(1); + } + + Object result = method.invoke(bean, (Object[]) null); + if (result != null) { + json.put(name, result); + } + } + } + } catch (Exception ignore) { + } + } + return json; + } + + @SuppressWarnings("unchecked") + public static JSONObject parse(Map map) { + if (map != null && !map.isEmpty()) { + JSONObject jsonObject = new JSONObject(); + Iterator iterator = map.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry) iterator.next(); + String key = entry.getKey(); + Object val = entry.getValue(); + jsonObject.put(key, val); + } + return jsonObject; + } + return null; + } + +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/JSONKit.java b/blade-kit/src/main/java/blade/kit/json/JSONKit.java index 41d2a4f4b..49c3b8d79 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONKit.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONKit.java @@ -1,35 +1,49 @@ package blade.kit.json; +import java.io.IOException; import java.util.List; import java.util.Map; public class JSONKit { public static Map toMap(String json){ - return Json.parseToMap(json); + return JSONHelper.parseToMap(json); } - public static Map toMap(JsonObject jsonObject){ - return Json.parseToMap(jsonObject); + public static Map toMap(JSONObject jsonObject){ + return JSONHelper.parseToMap(jsonObject); + } + + public static T parse(JSONObject jsonObject, Class type){ + return JSONHelper.parse(jsonObject, type); } public static String toJSONString(Object bean){ - return Json.parse(bean).toString(); + return JSONHelper.parse(bean).toString(); } public static String toJSONString(Map map){ - return Json.parse(map).toString(); + return JSONHelper.mapAsJsonObject(map).toString(); } public static String toJSONString(List list){ if(null != list && list.size() > 0){ - JsonArray jsonArray = new JsonArray(); + JSONArray jsonArray = new JSONArray(); for(T oT : list){ - jsonArray.add(Json.parse(oT)); + jsonArray.add(JSONHelper.parse(oT)); } return jsonArray.toString(); } return null; } + + public static JSONValue parse(String json) { + try { + return new JSONParser(json).parse(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } } diff --git a/blade-kit/src/main/java/blade/kit/json/JsonLiteral.java b/blade-kit/src/main/java/blade/kit/json/JSONLiteral.java similarity index 90% rename from blade-kit/src/main/java/blade/kit/json/JsonLiteral.java rename to blade-kit/src/main/java/blade/kit/json/JSONLiteral.java index ea32b91bc..6267fe81e 100644 --- a/blade-kit/src/main/java/blade/kit/json/JsonLiteral.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONLiteral.java @@ -1,97 +1,97 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; - - -@SuppressWarnings("serial") // use default serial UID -class JsonLiteral extends JsonValue { - - private final String value; - private final boolean isNull; - private final boolean isTrue; - private final boolean isFalse; - - JsonLiteral(String value) { - this.value = value; - isNull = "null".equals(value); - isTrue = "true".equals(value); - isFalse = "false".equals(value); - } - - @Override - void write(JsonWriter writer) throws IOException { - writer.writeLiteral(value); - } - - @Override - public String toString() { - return value; - } - - @Override - public int hashCode() { - return value.hashCode(); - } - - @Override - public boolean isNull() { - return isNull; - } - - @Override - public boolean isTrue() { - return isTrue; - } - - @Override - public boolean isFalse() { - return isFalse; - } - - @Override - public boolean isBoolean() { - return isTrue || isFalse; - } - - @Override - public boolean asBoolean() { - return isNull ? super.asBoolean() : isTrue; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JsonLiteral other = (JsonLiteral)object; - return value.equals(other.value); - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; + + +@SuppressWarnings("serial") // use default serial UID +class JSONLiteral extends JSONValue { + + private final String value; + private final boolean isNull; + private final boolean isTrue; + private final boolean isFalse; + + JSONLiteral(String value) { + this.value = value; + isNull = "null".equals(value); + isTrue = "true".equals(value); + isFalse = "false".equals(value); + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeLiteral(value); + } + + @Override + public String toString() { + return value; + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public boolean isNull() { + return isNull; + } + + @Override + public boolean isTrue() { + return isTrue; + } + + @Override + public boolean isFalse() { + return isFalse; + } + + @Override + public boolean isBoolean() { + return isTrue || isFalse; + } + + @Override + public boolean asBoolean() { + return isNull ? super.asBoolean() : isTrue; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONLiteral other = (JSONLiteral)object; + return value.equals(other.value); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonNumber.java b/blade-kit/src/main/java/blade/kit/json/JSONNumber.java similarity index 90% rename from blade-kit/src/main/java/blade/kit/json/JsonNumber.java rename to blade-kit/src/main/java/blade/kit/json/JSONNumber.java index 4ff0c4b8a..feca2639f 100644 --- a/blade-kit/src/main/java/blade/kit/json/JsonNumber.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONNumber.java @@ -1,94 +1,94 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; - - -@SuppressWarnings("serial") // use default serial UID -class JsonNumber extends JsonValue { - - private final String string; - - JsonNumber(String string) { - if (string == null) { - throw new NullPointerException("string is null"); - } - this.string = string; - } - - @Override - public String toString() { - return string; - } - - @Override - void write(JsonWriter writer) throws IOException { - writer.writeNumber(string); - } - - @Override - public boolean isNumber() { - return true; - } - - @Override - public int asInt() { - return Integer.parseInt(string, 10); - } - - @Override - public long asLong() { - return Long.parseLong(string, 10); - } - - @Override - public float asFloat() { - return Float.parseFloat(string); - } - - @Override - public double asDouble() { - return Double.parseDouble(string); - } - - @Override - public int hashCode() { - return string.hashCode(); - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JsonNumber other = (JsonNumber)object; - return string.equals(other.string); - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; + + +@SuppressWarnings("serial") // use default serial UID +class JSONNumber extends JSONValue { + + private final String string; + + JSONNumber(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + this.string = string; + } + + @Override + public String toString() { + return string; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeNumber(string); + } + + @Override + public boolean isNumber() { + return true; + } + + @Override + public int asInt() { + return Integer.parseInt(string, 10); + } + + @Override + public long asLong() { + return Long.parseLong(string, 10); + } + + @Override + public float asFloat() { + return Float.parseFloat(string); + } + + @Override + public double asDouble() { + return Double.parseDouble(string); + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONNumber other = (JSONNumber)object; + return string.equals(other.string); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONObject.java b/blade-kit/src/main/java/blade/kit/json/JSONObject.java new file mode 100644 index 000000000..310614b1b --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/JSONObject.java @@ -0,0 +1,1026 @@ +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import blade.kit.json.JSONObject.Member; + +/** + * Represents a JSON object, a set of name/value pairs, where the names are + * strings and the values are JSON values. + *

+ * Members can be added using the add(String, ...) methods which + * accept instances of {@link JSONValue}, strings, primitive numbers, and + * boolean values. To modify certain values of an object, use the + * set(String, ...) methods. Please note that the add + * methods are faster than set as they do not search for existing + * members. On the other hand, the add methods do not prevent + * adding multiple members with the same name. Duplicate names are discouraged + * but not prohibited by JSON. + *

+ *

+ * Members can be accessed by their name using {@link #get(String)}. A list of + * all names can be obtained from the method {@link #names()}. This class also + * supports iterating over the members in document order using an + * {@link #iterator()} or an enhanced for loop: + *

+ * + *
+ * for (Member member : jsonObject) {
+ *   String name = member.getName();
+ *   JsonValue value = member.getValue();
+ *   ...
+ * }
+ * 
+ *

+ * Even though JSON objects are unordered by definition, instances of this class + * preserve the order of members to allow processing in document order and to + * guarantee a predictable output. + *

+ *

+ * Note that this class is not thread-safe. If multiple threads + * access a JsonObject instance concurrently, while at least one of + * these threads modifies the contents of this object, access to the instance + * must be synchronized externally. Failure to do so may lead to an inconsistent + * state. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public class JSONObject extends JSONValue implements Iterable { + + private final List names; + private final List values; + private transient HashIndexTable table; + + /** + * Creates a new empty JsonObject. + */ + public JSONObject() { + names = new ArrayList(); + values = new ArrayList(); + table = new HashIndexTable(); + } + + /** + * Creates a new JsonObject, initialized with the contents of the specified + * JSON object. + * + * @param object + * the JSON object to get the initial contents from, must not be + * null + */ + public JSONObject(JSONObject object) { + this(object, false); + } + + private JSONObject(JSONObject object, boolean unmodifiable) { + if (object == null) { + throw new NullPointerException("object is null"); + } + if (unmodifiable) { + names = Collections.unmodifiableList(object.names); + values = Collections.unmodifiableList(object.values); + } else { + names = new ArrayList(object.names); + values = new ArrayList(object.values); + } + table = new HashIndexTable(); + updateHashIndex(); + } + + /** + * Reads a JSON object from the given reader. + *

+ * Characters are read in chunks and buffered internally, therefore wrapping + * an existing reader in an additional BufferedReader does + * not improve reading performance. + *

+ * + * @param reader + * the reader to read the JSON object from + * @return the JSON object that has been read + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + * @throws UnsupportedOperationException + * if the input does not contain a JSON object + * @deprecated Use {@link JSON#parse(Reader)}{@link JSONValue#asObject() + * .asObject()} instead + */ + @Deprecated + public static JSONObject readFrom(Reader reader) throws IOException { + return JSONValue.readFrom(reader).asObject(); + } + + /** + * Reads a JSON object from the given string. + * + * @param string + * the string that contains the JSON object + * @return the JSON object that has been read + * @throws ParseException + * if the input is not valid JSON + * @throws UnsupportedOperationException + * if the input does not contain a JSON object + * @deprecated Use {@link JSON#parse(String)}{@link JSONValue#asObject() + * .asObject()} instead + */ + @Deprecated + public static JSONObject readFrom(String string) { + return JSONValue.readFrom(string).asObject(); + } + + /** + * Returns an unmodifiable JsonObject for the specified one. This method + * allows to provide read-only access to a JsonObject. + *

+ * The returned JsonObject is backed by the given object and reflect changes + * that happen to it. Attempts to modify the returned JsonObject result in + * an UnsupportedOperationException. + *

+ * + * @param object + * the JsonObject for which an unmodifiable JsonObject is to be + * returned + * @return an unmodifiable view of the specified JsonObject + */ + public static JSONObject unmodifiableObject(JSONObject object) { + return new JSONObject(object, true); + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified int value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, int value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified long value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, long value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified float value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, float value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified double value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, double value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified boolean value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, boolean value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified string. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, String value) { + put(name, JSON.value(value)); + return this; + } + + public JSONObject put(String name, Object value) { + if (value instanceof String) { + put(name, JSON.value((String) value)); + } + + if (value instanceof Integer) { + put(name, JSON.value((Integer) value)); + } + + if (value instanceof Long) { + put(name, JSON.value((Long) value)); + } + + if (value instanceof JSONValue) { + put(name, (JSONValue) value); + } + + if (value instanceof JSONObject) { + put(name, (JSONObject) value); + } + + if (value instanceof JSONArray) { + put(name, (JSONArray) value); + } + + if (value instanceof Boolean) { + put(name, JSON.value((Boolean) value)); + } + + if (value instanceof Byte) { + put(name, JSON.value((Byte) value)); + } + + if (value instanceof Character) { + put(name, JSON.value((Character) value)); + } + + if (value instanceof Short) { + put(name, JSON.value((Short) value)); + } + + if (value instanceof Float) { + put(name, JSON.value((Float) value)); + } + + if (value instanceof Double) { + put(name, JSON.value((Double) value)); + } + + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the specified JSON value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add, must not be null + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, JSONValue value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + table.add(name, names.size()); + names.add(name); + values.add(value); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified int value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to replace + * @param value + * the value to set to the member + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, int value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified long value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to replace + * @param value + * the value to set to the member + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, long value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified float value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, float value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified double value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, double value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified boolean value. If this + * object does not contain a member with this name, a new member is added at + * the end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, boolean value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified string. If this object does not contain a + * member with this name, a new member is added at the end of the object. If + * this object contains multiple members with this name, only the last one + * is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, String value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the specified + * JSON value. If this object does not contain a member with this name, a + * new member is added at the end of the object. If this object contains + * multiple members with this name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add, must not be null + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, JSONValue value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + int index = indexOf(name); + if (index != -1) { + values.set(index, value); + } else { + table.add(name, names.size()); + names.add(name); + values.add(value); + } + return this; + } + + /** + * Removes a member with the specified name from this object. If this object + * contains multiple members with the given name, only the last one is + * removed. If this object does not contain a member with the specified + * name, the object is not modified. + * + * @param name + * the name of the member to remove + * @return the object itself, to enable method chaining + */ + public JSONObject remove(String name) { + if (name == null) { + throw new NullPointerException("name is null"); + } + int index = indexOf(name); + if (index != -1) { + table.remove(index); + names.remove(index); + values.remove(index); + } + return this; + } + + /** + * Copies all members of the specified object into this object. When the + * specified object contains members with names that also exist in this + * object, the existing values in this object will be replaced by the + * corresponding values in the specified object. + * + * @param object + * the object to merge + * @return the object itself, to enable method chaining + */ + public JSONObject merge(JSONObject object) { + if (object == null) { + throw new NullPointerException("object is null"); + } + for (Member member : object) { + this.set(member.name, member.value); + } + return this; + } + + /** + * Returns the value of the member with the specified name in this object. + * If this object contains multiple members with the given name, this method + * will return the last one. + * + * @param name + * the name of the member whose value is to be returned + * @return the value of the last member with the specified name, or + * null if this object does not contain a member with + * that name + */ + public JSONValue get(String name) { + if (name == null) { + throw new NullPointerException("name is null"); + } + int index = indexOf(name); + return index != -1 ? values.get(index) : null; + } + + public JSONObject getJSONObject(String name) { + JSONValue jsonValue = this.get(name); + if(null != jsonValue){ + return jsonValue.asObject(); + } + return null; + } + + public JSONArray getJSONArray(String name) { + JSONValue jsonValue = this.get(name); + if(null != jsonValue){ + return jsonValue.asArray(); + } + return null; + } + + /** + * Returns the int value of the member with the specified name + * in this object. If this object does not contain a member with this name, + * the given default value is returned. If this object contains multiple + * members with the given name, the last one will be picked. If this + * member's value does not represent a JSON number or if it cannot be + * interpreted as Java int, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public int getInt(String name, int defaultValue) { + JSONValue value = get(name); + return value != null ? value.asInt() : defaultValue; + } + + /** + * Returns the long value of the member with the specified name + * in this object. If this object does not contain a member with this name, + * the given default value is returned. If this object contains multiple + * members with the given name, the last one will be picked. If this + * member's value does not represent a JSON number or if it cannot be + * interpreted as Java long, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public long getLong(String name, long defaultValue) { + JSONValue value = get(name); + return value != null ? value.asLong() : defaultValue; + } + + /** + * Returns the float value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one will be picked. If + * this member's value does not represent a JSON number or if it cannot be + * interpreted as Java float, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public float getFloat(String name, float defaultValue) { + JSONValue value = get(name); + return value != null ? value.asFloat() : defaultValue; + } + + /** + * Returns the double value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one will be picked. If + * this member's value does not represent a JSON number or if it cannot be + * interpreted as Java double, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public double getDouble(String name, double defaultValue) { + JSONValue value = get(name); + return value != null ? value.asDouble() : defaultValue; + } + + /** + * Returns the boolean value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one will be picked. If + * this member's value does not represent a JSON true or + * false value, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public boolean getBoolean(String name, boolean defaultValue) { + JSONValue value = get(name); + return value != null ? value.asBoolean() : defaultValue; + } + + /** + * Returns the String value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one is picked. If this + * member's value does not represent a JSON string, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public String getString(String name, String defaultValue) { + JSONValue value = get(name); + return value != null ? value.asString() : defaultValue; + } + + public String getString(String name) { + JSONValue value = get(name); + return value != null ? value.asString() : null; + } + + /** + * Returns the number of members (name/value pairs) in this object. + * + * @return the number of members in this object + */ + public int size() { + return names.size(); + } + + /** + * Returns true if this object contains no members. + * + * @return true if this object contains no members + */ + public boolean isEmpty() { + return names.isEmpty(); + } + + /** + * Returns a list of the names in this object in document order. The + * returned list is backed by this object and will reflect subsequent + * changes. It cannot be used to modify this object. Attempts to modify the + * returned list will result in an exception. + * + * @return a list of the names in this object + */ + public List names() { + return Collections.unmodifiableList(names); + } + + /** + * Returns an iterator over the members of this object in document order. + * The returned iterator cannot be used to modify this object. + * + * @return an iterator over the members of this object + */ + public Iterator iterator() { + final Iterator namesIterator = names.iterator(); + final Iterator valuesIterator = values.iterator(); + return new Iterator() { + + public boolean hasNext() { + return namesIterator.hasNext(); + } + + public Member next() { + String name = namesIterator.next(); + JSONValue value = valuesIterator.next(); + return new Member(name, value); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + }; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeObjectOpen(); + Iterator namesIterator = names.iterator(); + Iterator valuesIterator = values.iterator(); + boolean first = true; + while (namesIterator.hasNext()) { + if (!first) { + writer.writeObjectSeparator(); + } + writer.writeMemberName(namesIterator.next()); + writer.writeMemberSeparator(); + valuesIterator.next().write(writer); + first = false; + } + writer.writeObjectClose(); + } + + @Override + public boolean isObject() { + return true; + } + + @Override + public JSONObject asObject() { + return this; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + names.hashCode(); + result = 31 * result + values.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + JSONObject other = (JSONObject) obj; + return names.equals(other.names) && values.equals(other.values); + } + + int indexOf(String name) { + int index = table.get(name); + if (index != -1 && name.equals(names.get(index))) { + return index; + } + return names.lastIndexOf(name); + } + + private synchronized void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { + inputStream.defaultReadObject(); + table = new HashIndexTable(); + updateHashIndex(); + } + + private void updateHashIndex() { + int size = names.size(); + for (int i = 0; i < size; i++) { + table.add(names.get(i), i); + } + } + + /** + * Represents a member of a JSON object, a pair of a name and a value. + */ + public static class Member { + + private final String name; + private final JSONValue value; + + Member(String name, JSONValue value) { + this.name = name; + this.value = value; + } + + /** + * Returns the name of this member. + * + * @return the name of this member, never null + */ + public String getName() { + return name; + } + + /** + * Returns the value of this member. + * + * @return the value of this member, never null + */ + public JSONValue getValue() { + return value; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + name.hashCode(); + result = 31 * result + value.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Member other = (Member) obj; + return name.equals(other.name) && value.equals(other.value); + } + + } + + static class HashIndexTable { + + private final byte[] hashTable = new byte[32]; // must be a power of two + + public HashIndexTable() { + } + + public HashIndexTable(HashIndexTable original) { + System.arraycopy(original.hashTable, 0, hashTable, 0, hashTable.length); + } + + void add(String name, int index) { + int slot = hashSlotFor(name); + if (index < 0xff) { + // increment by 1, 0 stands for empty + hashTable[slot] = (byte) (index + 1); + } else { + hashTable[slot] = 0; + } + } + + void remove(int index) { + for (int i = 0; i < hashTable.length; i++) { + if (hashTable[i] == index + 1) { + hashTable[i] = 0; + } else if (hashTable[i] > index + 1) { + hashTable[i]--; + } + } + } + + int get(Object name) { + int slot = hashSlotFor(name); + // subtract 1, 0 stands for empty + return (hashTable[slot] & 0xff) - 1; + } + + private int hashSlotFor(Object element) { + return element.hashCode() & hashTable.length - 1; + } + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonParser.java b/blade-kit/src/main/java/blade/kit/json/JSONParser.java similarity index 84% rename from blade-kit/src/main/java/blade/kit/json/JsonParser.java rename to blade-kit/src/main/java/blade/kit/json/JSONParser.java index c1cc3274c..fd7509083 100644 --- a/blade-kit/src/main/java/blade/kit/json/JsonParser.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONParser.java @@ -1,400 +1,412 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; - - -class JsonParser { - - private static final int MIN_BUFFER_SIZE = 10; - private static final int DEFAULT_BUFFER_SIZE = 1024; - - private final Reader reader; - private final char[] buffer; - private int bufferOffset; - private int index; - private int fill; - private int line; - private int lineOffset; - private int current; - private StringBuilder captureBuffer; - private int captureStart; - - /* - * | bufferOffset - * v - * [a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t] < input - * [l|m|n|o|p|q|r|s|t|?|?] < buffer - * ^ ^ - * | index fill - */ - - JsonParser(String string) { - this(new StringReader(string), - Math.max(MIN_BUFFER_SIZE, Math.min(DEFAULT_BUFFER_SIZE, string.length()))); - } - - JsonParser(Reader reader) { - this(reader, DEFAULT_BUFFER_SIZE); - } - - JsonParser(Reader reader, int buffersize) { - this.reader = reader; - buffer = new char[buffersize]; - line = 1; - captureStart = -1; - } - - JsonValue parse() throws IOException { - read(); - skipWhiteSpace(); - JsonValue result = readValue(); - skipWhiteSpace(); - if (!isEndOfText()) { - throw error("Unexpected character"); - } - return result; - } - - private JsonValue readValue() throws IOException { - switch (current) { - case 'n': - return readNull(); - case 't': - return readTrue(); - case 'f': - return readFalse(); - case '"': - return readString(); - case '[': - return readArray(); - case '{': - return readObject(); - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return readNumber(); - default: - throw expected("value"); - } - } - - private JsonArray readArray() throws IOException { - read(); - JsonArray array = new JsonArray(); - skipWhiteSpace(); - if (readChar(']')) { - return array; - } - do { - skipWhiteSpace(); - array.add(readValue()); - skipWhiteSpace(); - } while (readChar(',')); - if (!readChar(']')) { - throw expected("',' or ']'"); - } - return array; - } - - private JsonObject readObject() throws IOException { - read(); - JsonObject object = new JsonObject(); - skipWhiteSpace(); - if (readChar('}')) { - return object; - } - do { - skipWhiteSpace(); - String name = readName(); - skipWhiteSpace(); - if (!readChar(':')) { - throw expected("':'"); - } - skipWhiteSpace(); - object.add(name, readValue()); - skipWhiteSpace(); - } while (readChar(',')); - if (!readChar('}')) { - throw expected("',' or '}'"); - } - return object; - } - - private String readName() throws IOException { - if (current != '"') { - throw expected("name"); - } - return readStringInternal(); - } - - private JsonValue readNull() throws IOException { - read(); - readRequiredChar('u'); - readRequiredChar('l'); - readRequiredChar('l'); - return Json.NULL; - } - - private JsonValue readTrue() throws IOException { - read(); - readRequiredChar('r'); - readRequiredChar('u'); - readRequiredChar('e'); - return Json.TRUE; - } - - private JsonValue readFalse() throws IOException { - read(); - readRequiredChar('a'); - readRequiredChar('l'); - readRequiredChar('s'); - readRequiredChar('e'); - return Json.FALSE; - } - - private void readRequiredChar(char ch) throws IOException { - if (!readChar(ch)) { - throw expected("'" + ch + "'"); - } - } - - private JsonValue readString() throws IOException { - return new JsonString(readStringInternal()); - } - - private String readStringInternal() throws IOException { - read(); - startCapture(); - while (current != '"') { - if (current == '\\') { - pauseCapture(); - readEscape(); - startCapture(); - } else if (current < 0x20) { - throw expected("valid string character"); - } else { - read(); - } - } - String string = endCapture(); - read(); - return string; - } - - private void readEscape() throws IOException { - read(); - switch (current) { - case '"': - case '/': - case '\\': - captureBuffer.append((char)current); - break; - case 'b': - captureBuffer.append('\b'); - break; - case 'f': - captureBuffer.append('\f'); - break; - case 'n': - captureBuffer.append('\n'); - break; - case 'r': - captureBuffer.append('\r'); - break; - case 't': - captureBuffer.append('\t'); - break; - case 'u': - char[] hexChars = new char[4]; - for (int i = 0; i < 4; i++) { - read(); - if (!isHexDigit()) { - throw expected("hexadecimal digit"); - } - hexChars[i] = (char)current; - } - captureBuffer.append((char)Integer.parseInt(new String(hexChars), 16)); - break; - default: - throw expected("valid escape sequence"); - } - read(); - } - - private JsonValue readNumber() throws IOException { - startCapture(); - readChar('-'); - int firstDigit = current; - if (!readDigit()) { - throw expected("digit"); - } - if (firstDigit != '0') { - while (readDigit()) { - } - } - readFraction(); - readExponent(); - return new JsonNumber(endCapture()); - } - - private boolean readFraction() throws IOException { - if (!readChar('.')) { - return false; - } - if (!readDigit()) { - throw expected("digit"); - } - while (readDigit()) { - } - return true; - } - - private boolean readExponent() throws IOException { - if (!readChar('e') && !readChar('E')) { - return false; - } - if (!readChar('+')) { - readChar('-'); - } - if (!readDigit()) { - throw expected("digit"); - } - while (readDigit()) { - } - return true; - } - - private boolean readChar(char ch) throws IOException { - if (current != ch) { - return false; - } - read(); - return true; - } - - private boolean readDigit() throws IOException { - if (!isDigit()) { - return false; - } - read(); - return true; - } - - private void skipWhiteSpace() throws IOException { - while (isWhiteSpace()) { - read(); - } - } - - private void read() throws IOException { - if (index == fill) { - if (captureStart != -1) { - captureBuffer.append(buffer, captureStart, fill - captureStart); - captureStart = 0; - } - bufferOffset += fill; - fill = reader.read(buffer, 0, buffer.length); - index = 0; - if (fill == -1) { - current = -1; - return; - } - } - if (current == '\n') { - line++; - lineOffset = bufferOffset + index; - } - current = buffer[index++]; - } - - private void startCapture() { - if (captureBuffer == null) { - captureBuffer = new StringBuilder(); - } - captureStart = index - 1; - } - - private void pauseCapture() { - int end = current == -1 ? index : index - 1; - captureBuffer.append(buffer, captureStart, end - captureStart); - captureStart = -1; - } - - private String endCapture() { - int end = current == -1 ? index : index - 1; - String captured; - if (captureBuffer.length() > 0) { - captureBuffer.append(buffer, captureStart, end - captureStart); - captured = captureBuffer.toString(); - captureBuffer.setLength(0); - } else { - captured = new String(buffer, captureStart, end - captureStart); - } - captureStart = -1; - return captured; - } - - private ParseException expected(String expected) { - if (isEndOfText()) { - return error("Unexpected end of input"); - } - return error("Expected " + expected); - } - - private ParseException error(String message) { - int absIndex = bufferOffset + index; - int column = absIndex - lineOffset; - int offset = isEndOfText() ? absIndex : absIndex - 1; - return new ParseException(message, offset, line, column - 1); - } - - private boolean isWhiteSpace() { - return current == ' ' || current == '\t' || current == '\n' || current == '\r'; - } - - private boolean isDigit() { - return current >= '0' && current <= '9'; - } - - private boolean isHexDigit() { - return current >= '0' && current <= '9' - || current >= 'a' && current <= 'f' - || current >= 'A' && current <= 'F'; - } - - private boolean isEndOfText() { - return current == -1; - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + + +class JSONParser { + + private static final int MAX_NESTING_LEVEL = 1000; + private static final int MIN_BUFFER_SIZE = 10; + private static final int DEFAULT_BUFFER_SIZE = 1024; + + private final Reader reader; + private final char[] buffer; + private int bufferOffset; + private int index; + private int fill; + private int line; + private int lineOffset; + private int current; + private StringBuilder captureBuffer; + private int captureStart; + private int nestingLevel; + + /* + * | bufferOffset + * v + * [a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t] < input + * [l|m|n|o|p|q|r|s|t|?|?] < buffer + * ^ ^ + * | index fill + */ + + JSONParser(String string) { + this(new StringReader(string), + Math.max(MIN_BUFFER_SIZE, Math.min(DEFAULT_BUFFER_SIZE, string.length()))); + } + + JSONParser(Reader reader) { + this(reader, DEFAULT_BUFFER_SIZE); + } + + JSONParser(Reader reader, int buffersize) { + this.reader = reader; + buffer = new char[buffersize]; + line = 1; + captureStart = -1; + } + + JSONValue parse() throws IOException { + read(); + skipWhiteSpace(); + JSONValue result = readValue(); + skipWhiteSpace(); + if (!isEndOfText()) { + throw error("Unexpected character"); + } + return result; + } + + private JSONValue readValue() throws IOException { + switch (current) { + case 'n': + return readNull(); + case 't': + return readTrue(); + case 'f': + return readFalse(); + case '"': + return readString(); + case '[': + return readArray(); + case '{': + return readObject(); + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return readNumber(); + default: + throw expected("value"); + } + } + + private JSONArray readArray() throws IOException { + read(); + if (nestingLevel++ >= MAX_NESTING_LEVEL) { + throw error("Nesting too deep"); + } + JSONArray array = new JSONArray(); + skipWhiteSpace(); + if (readChar(']')) { + nestingLevel--; + return array; + } + do { + skipWhiteSpace(); + array.add(readValue()); + skipWhiteSpace(); + } while (readChar(',')); + if (!readChar(']')) { + throw expected("',' or ']'"); + } + nestingLevel--; + return array; + } + + private JSONObject readObject() throws IOException { + read(); + if (nestingLevel++ >= 1000) { + throw error("Nesting too deep"); + } + JSONObject object = new JSONObject(); + skipWhiteSpace(); + if (readChar('}')) { + nestingLevel--; + return object; + } + do { + skipWhiteSpace(); + String name = readName(); + skipWhiteSpace(); + if (!readChar(':')) { + throw expected("':'"); + } + skipWhiteSpace(); + object.put(name, readValue()); + skipWhiteSpace(); + } while (readChar(',')); + if (!readChar('}')) { + throw expected("',' or '}'"); + } + nestingLevel--; + return object; + } + + private String readName() throws IOException { + if (current != '"') { + throw expected("name"); + } + return readStringInternal(); + } + + private JSONValue readNull() throws IOException { + read(); + readRequiredChar('u'); + readRequiredChar('l'); + readRequiredChar('l'); + return JSON.NULL; + } + + private JSONValue readTrue() throws IOException { + read(); + readRequiredChar('r'); + readRequiredChar('u'); + readRequiredChar('e'); + return JSON.TRUE; + } + + private JSONValue readFalse() throws IOException { + read(); + readRequiredChar('a'); + readRequiredChar('l'); + readRequiredChar('s'); + readRequiredChar('e'); + return JSON.FALSE; + } + + private void readRequiredChar(char ch) throws IOException { + if (!readChar(ch)) { + throw expected("'" + ch + "'"); + } + } + + private JSONValue readString() throws IOException { + return new JSONString(readStringInternal()); + } + + private String readStringInternal() throws IOException { + read(); + startCapture(); + while (current != '"') { + if (current == '\\') { + pauseCapture(); + readEscape(); + startCapture(); + } else if (current < 0x20) { + throw expected("valid string character"); + } else { + read(); + } + } + String string = endCapture(); + read(); + return string; + } + + private void readEscape() throws IOException { + read(); + switch (current) { + case '"': + case '/': + case '\\': + captureBuffer.append((char)current); + break; + case 'b': + captureBuffer.append('\b'); + break; + case 'f': + captureBuffer.append('\f'); + break; + case 'n': + captureBuffer.append('\n'); + break; + case 'r': + captureBuffer.append('\r'); + break; + case 't': + captureBuffer.append('\t'); + break; + case 'u': + char[] hexChars = new char[4]; + for (int i = 0; i < 4; i++) { + read(); + if (!isHexDigit()) { + throw expected("hexadecimal digit"); + } + hexChars[i] = (char)current; + } + captureBuffer.append((char)Integer.parseInt(new String(hexChars), 16)); + break; + default: + throw expected("valid escape sequence"); + } + read(); + } + + private JSONValue readNumber() throws IOException { + startCapture(); + readChar('-'); + int firstDigit = current; + if (!readDigit()) { + throw expected("digit"); + } + if (firstDigit != '0') { + while (readDigit()) { + } + } + readFraction(); + readExponent(); + return new JSONNumber(endCapture()); + } + + private boolean readFraction() throws IOException { + if (!readChar('.')) { + return false; + } + if (!readDigit()) { + throw expected("digit"); + } + while (readDigit()) { + } + return true; + } + + private boolean readExponent() throws IOException { + if (!readChar('e') && !readChar('E')) { + return false; + } + if (!readChar('+')) { + readChar('-'); + } + if (!readDigit()) { + throw expected("digit"); + } + while (readDigit()) { + } + return true; + } + + private boolean readChar(char ch) throws IOException { + if (current != ch) { + return false; + } + read(); + return true; + } + + private boolean readDigit() throws IOException { + if (!isDigit()) { + return false; + } + read(); + return true; + } + + private void skipWhiteSpace() throws IOException { + while (isWhiteSpace()) { + read(); + } + } + + private void read() throws IOException { + if (index == fill) { + if (captureStart != -1) { + captureBuffer.append(buffer, captureStart, fill - captureStart); + captureStart = 0; + } + bufferOffset += fill; + fill = reader.read(buffer, 0, buffer.length); + index = 0; + if (fill == -1) { + current = -1; + return; + } + } + if (current == '\n') { + line++; + lineOffset = bufferOffset + index; + } + current = buffer[index++]; + } + + private void startCapture() { + if (captureBuffer == null) { + captureBuffer = new StringBuilder(); + } + captureStart = index - 1; + } + + private void pauseCapture() { + int end = current == -1 ? index : index - 1; + captureBuffer.append(buffer, captureStart, end - captureStart); + captureStart = -1; + } + + private String endCapture() { + int end = current == -1 ? index : index - 1; + String captured; + if (captureBuffer.length() > 0) { + captureBuffer.append(buffer, captureStart, end - captureStart); + captured = captureBuffer.toString(); + captureBuffer.setLength(0); + } else { + captured = new String(buffer, captureStart, end - captureStart); + } + captureStart = -1; + return captured; + } + + private ParseException expected(String expected) { + if (isEndOfText()) { + return error("Unexpected end of input"); + } + return error("Expected " + expected); + } + + private ParseException error(String message) { + int absIndex = bufferOffset + index; + int column = absIndex - lineOffset; + int offset = isEndOfText() ? absIndex : absIndex - 1; + return new ParseException(message, offset, line, column - 1); + } + + private boolean isWhiteSpace() { + return current == ' ' || current == '\t' || current == '\n' || current == '\r'; + } + + private boolean isDigit() { + return current >= '0' && current <= '9'; + } + + private boolean isHexDigit() { + return current >= '0' && current <= '9' + || current >= 'a' && current <= 'f' + || current >= 'A' && current <= 'F'; + } + + private boolean isEndOfText() { + return current == -1; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonString.java b/blade-kit/src/main/java/blade/kit/json/JSONString.java similarity index 89% rename from blade-kit/src/main/java/blade/kit/json/JsonString.java rename to blade-kit/src/main/java/blade/kit/json/JSONString.java index 4d7a188bf..886271320 100644 --- a/blade-kit/src/main/java/blade/kit/json/JsonString.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONString.java @@ -1,74 +1,74 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; - - -@SuppressWarnings("serial") // use default serial UID -class JsonString extends JsonValue { - - private final String string; - - JsonString(String string) { - if (string == null) { - throw new NullPointerException("string is null"); - } - this.string = string; - } - - @Override - void write(JsonWriter writer) throws IOException { - writer.writeString(string); - } - - @Override - public boolean isString() { - return true; - } - - @Override - public String asString() { - return string; - } - - @Override - public int hashCode() { - return string.hashCode(); - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JsonString other = (JsonString)object; - return string.equals(other.string); - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; + + +@SuppressWarnings("serial") // use default serial UID +class JSONString extends JSONValue { + + private final String string; + + JSONString(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + this.string = string; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeString(string); + } + + @Override + public boolean isString() { + return true; + } + + @Override + public String asString() { + return string; + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONString other = (JSONString)object; + return string.equals(other.string); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonValue.java b/blade-kit/src/main/java/blade/kit/json/JSONValue.java similarity index 88% rename from blade-kit/src/main/java/blade/kit/json/JsonValue.java rename to blade-kit/src/main/java/blade/kit/json/JSONValue.java index 61b3f1792..123acc889 100644 --- a/blade-kit/src/main/java/blade/kit/json/JsonValue.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONValue.java @@ -1,500 +1,500 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Reader; -import java.io.Serializable; -import java.io.StringWriter; -import java.io.Writer; - - -/** - * Represents a JSON value. This can be a JSON object, an array, - * a number, a string, or one of the literals - * true, false, and null. - *

- * The literals true, false, and null are - * represented by the constants {@link #TRUE}, {@link #FALSE}, and {@link #NULL}. - *

- *

- * JSON objects and arrays are represented by the subtypes - * {@link JsonObject} and {@link JsonArray}. Instances of these types can be created using the - * public constructors of these classes. - *

- *

- * Instances that represent JSON numbers, strings and - * boolean values can be created using the static factory methods - * {@link #valueOf(String)}, {@link #valueOf(long)}, {@link #valueOf(double)}, etc. - *

- *

- * In order to find out whether an instance of this class is of a certain type, the methods - * {@link #isObject()}, {@link #isArray()}, {@link #isString()}, {@link #isNumber()} etc. can be - * used. - *

- *

- * If the type of a JSON value is known, the methods {@link #asObject()}, {@link #asArray()}, - * {@link #asString()}, {@link #asInt()}, etc. can be used to get this value directly in the - * appropriate target type. - *

- *

- * This class is not supposed to be extended by clients. - *

- */ -@SuppressWarnings("serial") // use default serial UID -public abstract class JsonValue implements Serializable { - - /** - * Represents the JSON literal true. - * @deprecated Use Json.TRUE instead - */ - @Deprecated - public static final JsonValue TRUE = new JsonLiteral("true"); - - /** - * Represents the JSON literal false. - * @deprecated Use Json.FALSE instead - */ - @Deprecated - public static final JsonValue FALSE = new JsonLiteral("false"); - - /** - * Represents the JSON literal null. - * @deprecated Use Json.NULL instead - */ - @Deprecated - public static final JsonValue NULL = new JsonLiteral("null"); - - JsonValue() { - // prevent subclasses outside of this package - } - - /** - * Reads a JSON value from the given reader. - *

- * Characters are read in chunks and buffered internally, therefore wrapping an existing reader in - * an additional BufferedReader does not improve reading - * performance. - *

- * - * @param reader - * the reader to read the JSON value from - * @return the JSON value that has been read - * @throws IOException - * if an I/O error occurs in the reader - * @throws ParseException - * if the input is not valid JSON - * @deprecated Use {@link Json#parse(Reader)} instead - */ - @Deprecated - public static JsonValue readFrom(Reader reader) throws IOException { - return new JsonParser(reader).parse(); - } - - /** - * Reads a JSON value from the given string. - * - * @param text - * the string that contains the JSON value - * @return the JSON value that has been read - * @throws ParseException - * if the input is not valid JSON - * @deprecated Use {@link Json#parse(String)} instead - */ - @Deprecated - public static JsonValue readFrom(String text) { - try { - return new JsonParser(text).parse(); - } catch (IOException exception) { - // JsonParser does not throw IOException for String - throw new RuntimeException(exception); - } - } - - /** - * Returns a JsonValue instance that represents the given int value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JsonValue valueOf(int value) { - return Json.value(value); - } - - /** - * Returns a JsonValue instance that represents the given long value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JsonValue valueOf(long value) { - return Json.value(value); - } - - /** - * Returns a JsonValue instance that represents the given float value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JsonValue valueOf(float value) { - return Json.value(value); - } - - /** - * Returns a JsonValue instance that represents the given double value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JsonValue valueOf(double value) { - return Json.value(value); - } - - /** - * Returns a JsonValue instance that represents the given string. - * - * @param string - * the string to get a JSON representation for - * @return a JSON value that represents the given string - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JsonValue valueOf(String string) { - return Json.value(string); - } - - /** - * Returns a JsonValue instance that represents the given boolean value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JsonValue valueOf(boolean value) { - return Json.value(value); - } - - /** - * Detects whether this value represents a JSON object. If this is the case, this value is an - * instance of {@link JsonObject}. - * - * @return true if this value is an instance of JsonObject - */ - public boolean isObject() { - return false; - } - - /** - * Detects whether this value represents a JSON array. If this is the case, this value is an - * instance of {@link JsonArray}. - * - * @return true if this value is an instance of JsonArray - */ - public boolean isArray() { - return false; - } - - /** - * Detects whether this value represents a JSON number. - * - * @return true if this value represents a JSON number - */ - public boolean isNumber() { - return false; - } - - /** - * Detects whether this value represents a JSON string. - * - * @return true if this value represents a JSON string - */ - public boolean isString() { - return false; - } - - /** - * Detects whether this value represents a boolean value. - * - * @return true if this value represents either the JSON literal true or - * false - */ - public boolean isBoolean() { - return false; - } - - /** - * Detects whether this value represents the JSON literal true. - * - * @return true if this value represents the JSON literal true - */ - public boolean isTrue() { - return false; - } - - /** - * Detects whether this value represents the JSON literal false. - * - * @return true if this value represents the JSON literal false - */ - public boolean isFalse() { - return false; - } - - /** - * Detects whether this value represents the JSON literal null. - * - * @return true if this value represents the JSON literal null - */ - public boolean isNull() { - return false; - } - - /** - * Returns this JSON value as {@link JsonObject}, assuming that this value represents a JSON - * object. If this is not the case, an exception is thrown. - * - * @return a JSONObject for this value - * @throws UnsupportedOperationException - * if this value is not a JSON object - */ - public JsonObject asObject() { - throw new UnsupportedOperationException("Not an object: " + toString()); - } - - /** - * Returns this JSON value as {@link JsonArray}, assuming that this value represents a JSON array. - * If this is not the case, an exception is thrown. - * - * @return a JSONArray for this value - * @throws UnsupportedOperationException - * if this value is not a JSON array - */ - public JsonArray asArray() { - throw new UnsupportedOperationException("Not an array: " + toString()); - } - - /** - * Returns this JSON value as an int value, assuming that this value represents a - * JSON number that can be interpreted as Java int. If this is not the case, an - * exception is thrown. - *

- * To be interpreted as Java int, the JSON number must neither contain an exponent - * nor a fraction part. Moreover, the number must be in the Integer range. - *

- * - * @return this value as int - * @throws UnsupportedOperationException - * if this value is not a JSON number - * @throws NumberFormatException - * if this JSON number can not be interpreted as int value - */ - public int asInt() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as a long value, assuming that this value represents a - * JSON number that can be interpreted as Java long. If this is not the case, an - * exception is thrown. - *

- * To be interpreted as Java long, the JSON number must neither contain an exponent - * nor a fraction part. Moreover, the number must be in the Long range. - *

- * - * @return this value as long - * @throws UnsupportedOperationException - * if this value is not a JSON number - * @throws NumberFormatException - * if this JSON number can not be interpreted as long value - */ - public long asLong() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as a float value, assuming that this value represents a - * JSON number. If this is not the case, an exception is thrown. - *

- * If the JSON number is out of the Float range, {@link Float#POSITIVE_INFINITY} or - * {@link Float#NEGATIVE_INFINITY} is returned. - *

- * - * @return this value as float - * @throws UnsupportedOperationException - * if this value is not a JSON number - */ - public float asFloat() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as a double value, assuming that this value represents a - * JSON number. If this is not the case, an exception is thrown. - *

- * If the JSON number is out of the Double range, {@link Double#POSITIVE_INFINITY} or - * {@link Double#NEGATIVE_INFINITY} is returned. - *

- * - * @return this value as double - * @throws UnsupportedOperationException - * if this value is not a JSON number - */ - public double asDouble() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as String, assuming that this value represents a JSON string. If this - * is not the case, an exception is thrown. - * - * @return the string represented by this value - * @throws UnsupportedOperationException - * if this value is not a JSON string - */ - public String asString() { - throw new UnsupportedOperationException("Not a string: " + toString()); - } - - /** - * Returns this JSON value as a boolean value, assuming that this value is either - * true or false. If this is not the case, an exception is thrown. - * - * @return this value as boolean - * @throws UnsupportedOperationException - * if this value is neither true or false - */ - public boolean asBoolean() { - throw new UnsupportedOperationException("Not a boolean: " + toString()); - } - - /** - * Writes the JSON representation of this value to the given writer in its minimal form, without - * any additional whitespace. - *

- * Writing performance can be improved by using a {@link java.io.BufferedWriter BufferedWriter}. - *

- * - * @param writer - * the writer to write this value to - * @throws IOException - * if an I/O error occurs in the writer - */ - public void writeTo(Writer writer) throws IOException { - writeTo(writer, WriterConfig.MINIMAL); - } - - /** - * Writes the JSON representation of this value to the given writer using the given formatting. - *

- * Writing performance can be improved by using a {@link java.io.BufferedWriter BufferedWriter}. - *

- * - * @param writer - * the writer to write this value to - * @param config - * a configuration that controls the formatting or null for the minimal form - * @throws IOException - * if an I/O error occurs in the writer - */ - public void writeTo(Writer writer, WriterConfig config) throws IOException { - if (writer == null) { - throw new NullPointerException("writer is null"); - } - if (config == null) { - throw new NullPointerException("config is null"); - } - WritingBuffer buffer = new WritingBuffer(writer, 128); - write(config.createWriter(buffer)); - buffer.flush(); - } - - /** - * Returns the JSON string for this value in its minimal form, without any additional whitespace. - * The result is guaranteed to be a valid input for the method {@link #readFrom(String)} and to - * create a value that is equal to this object. - * - * @return a JSON string that represents this value - */ - @Override - public String toString() { - return toString(WriterConfig.MINIMAL); - } - - /** - * Returns the JSON string for this value using the given formatting. - * - * @param config - * a configuration that controls the formatting or null for the minimal form - * @return a JSON string that represents this value - */ - public String toString(WriterConfig config) { - StringWriter writer = new StringWriter(); - try { - writeTo(writer, config); - } catch (IOException exception) { - // StringWriter does not throw IOExceptions - throw new RuntimeException(exception); - } - return writer.toString(); - } - - /** - * Indicates whether some other object is "equal to" this one according to the contract specified - * in {@link Object#equals(Object)}. - *

- * Two JsonValues are considered equal if and only if they represent the same JSON text. As a - * consequence, two given JsonObjects may be different even though they contain the same set of - * names with the same values, but in a different order. - *

- * - * @param object - * the reference object with which to compare - * @return true if this object is the same as the object argument; false otherwise - */ - @Override - public boolean equals(Object object) { - return super.equals(object); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - abstract void write(JsonWriter writer) throws IOException; - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Reader; +import java.io.Serializable; +import java.io.StringWriter; +import java.io.Writer; + + +/** + * Represents a JSON value. This can be a JSON object, an array, + * a number, a string, or one of the literals + * true, false, and null. + *

+ * The literals true, false, and null are + * represented by the constants {@link #TRUE}, {@link #FALSE}, and {@link #NULL}. + *

+ *

+ * JSON objects and arrays are represented by the subtypes + * {@link JSONObject} and {@link JSONArray}. Instances of these types can be created using the + * public constructors of these classes. + *

+ *

+ * Instances that represent JSON numbers, strings and + * boolean values can be created using the static factory methods + * {@link #valueOf(String)}, {@link #valueOf(long)}, {@link #valueOf(double)}, etc. + *

+ *

+ * In order to find out whether an instance of this class is of a certain type, the methods + * {@link #isObject()}, {@link #isArray()}, {@link #isString()}, {@link #isNumber()} etc. can be + * used. + *

+ *

+ * If the type of a JSON value is known, the methods {@link #asObject()}, {@link #asArray()}, + * {@link #asString()}, {@link #asInt()}, etc. can be used to get this value directly in the + * appropriate target type. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public abstract class JSONValue implements Serializable { + + /** + * Represents the JSON literal true. + * @deprecated Use Json.TRUE instead + */ + @Deprecated + public static final JSONValue TRUE = new JSONLiteral("true"); + + /** + * Represents the JSON literal false. + * @deprecated Use Json.FALSE instead + */ + @Deprecated + public static final JSONValue FALSE = new JSONLiteral("false"); + + /** + * Represents the JSON literal null. + * @deprecated Use Json.NULL instead + */ + @Deprecated + public static final JSONValue NULL = new JSONLiteral("null"); + + JSONValue() { + // prevent subclasses outside of this package + } + + /** + * Reads a JSON value from the given reader. + *

+ * Characters are read in chunks and buffered internally, therefore wrapping an existing reader in + * an additional BufferedReader does not improve reading + * performance. + *

+ * + * @param reader + * the reader to read the JSON value from + * @return the JSON value that has been read + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + * @deprecated Use {@link JSON#parse(Reader)} instead + */ + @Deprecated + public static JSONValue readFrom(Reader reader) throws IOException { + return new JSONParser(reader).parse(); + } + + /** + * Reads a JSON value from the given string. + * + * @param text + * the string that contains the JSON value + * @return the JSON value that has been read + * @throws ParseException + * if the input is not valid JSON + * @deprecated Use {@link JSON#parse(String)} instead + */ + @Deprecated + public static JSONValue readFrom(String text) { + try { + return new JSONParser(text).parse(); + } catch (IOException exception) { + // JsonParser does not throw IOException for String + throw new RuntimeException(exception); + } + } + + /** + * Returns a JsonValue instance that represents the given int value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JSONValue valueOf(int value) { + return JSON.value(value); + } + + /** + * Returns a JsonValue instance that represents the given long value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JSONValue valueOf(long value) { + return JSON.value(value); + } + + /** + * Returns a JsonValue instance that represents the given float value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JSONValue valueOf(float value) { + return JSON.value(value); + } + + /** + * Returns a JsonValue instance that represents the given double value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JSONValue valueOf(double value) { + return JSON.value(value); + } + + /** + * Returns a JsonValue instance that represents the given string. + * + * @param string + * the string to get a JSON representation for + * @return a JSON value that represents the given string + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JSONValue valueOf(String string) { + return JSON.value(string); + } + + /** + * Returns a JsonValue instance that represents the given boolean value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + * @deprecated Use Json.value() instead + */ + @Deprecated + public static JSONValue valueOf(boolean value) { + return JSON.value(value); + } + + /** + * Detects whether this value represents a JSON object. If this is the case, this value is an + * instance of {@link JSONObject}. + * + * @return true if this value is an instance of JsonObject + */ + public boolean isObject() { + return false; + } + + /** + * Detects whether this value represents a JSON array. If this is the case, this value is an + * instance of {@link JSONArray}. + * + * @return true if this value is an instance of JsonArray + */ + public boolean isArray() { + return false; + } + + /** + * Detects whether this value represents a JSON number. + * + * @return true if this value represents a JSON number + */ + public boolean isNumber() { + return false; + } + + /** + * Detects whether this value represents a JSON string. + * + * @return true if this value represents a JSON string + */ + public boolean isString() { + return false; + } + + /** + * Detects whether this value represents a boolean value. + * + * @return true if this value represents either the JSON literal true or + * false + */ + public boolean isBoolean() { + return false; + } + + /** + * Detects whether this value represents the JSON literal true. + * + * @return true if this value represents the JSON literal true + */ + public boolean isTrue() { + return false; + } + + /** + * Detects whether this value represents the JSON literal false. + * + * @return true if this value represents the JSON literal false + */ + public boolean isFalse() { + return false; + } + + /** + * Detects whether this value represents the JSON literal null. + * + * @return true if this value represents the JSON literal null + */ + public boolean isNull() { + return false; + } + + /** + * Returns this JSON value as {@link JSONObject}, assuming that this value represents a JSON + * object. If this is not the case, an exception is thrown. + * + * @return a JSONObject for this value + * @throws UnsupportedOperationException + * if this value is not a JSON object + */ + public JSONObject asObject() { + throw new UnsupportedOperationException("Not an object: " + toString()); + } + + /** + * Returns this JSON value as {@link JSONArray}, assuming that this value represents a JSON array. + * If this is not the case, an exception is thrown. + * + * @return a JSONArray for this value + * @throws UnsupportedOperationException + * if this value is not a JSON array + */ + public JSONArray asArray() { + throw new UnsupportedOperationException("Not an array: " + toString()); + } + + /** + * Returns this JSON value as an int value, assuming that this value represents a + * JSON number that can be interpreted as Java int. If this is not the case, an + * exception is thrown. + *

+ * To be interpreted as Java int, the JSON number must neither contain an exponent + * nor a fraction part. Moreover, the number must be in the Integer range. + *

+ * + * @return this value as int + * @throws UnsupportedOperationException + * if this value is not a JSON number + * @throws NumberFormatException + * if this JSON number can not be interpreted as int value + */ + public int asInt() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a long value, assuming that this value represents a + * JSON number that can be interpreted as Java long. If this is not the case, an + * exception is thrown. + *

+ * To be interpreted as Java long, the JSON number must neither contain an exponent + * nor a fraction part. Moreover, the number must be in the Long range. + *

+ * + * @return this value as long + * @throws UnsupportedOperationException + * if this value is not a JSON number + * @throws NumberFormatException + * if this JSON number can not be interpreted as long value + */ + public long asLong() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a float value, assuming that this value represents a + * JSON number. If this is not the case, an exception is thrown. + *

+ * If the JSON number is out of the Float range, {@link Float#POSITIVE_INFINITY} or + * {@link Float#NEGATIVE_INFINITY} is returned. + *

+ * + * @return this value as float + * @throws UnsupportedOperationException + * if this value is not a JSON number + */ + public float asFloat() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a double value, assuming that this value represents a + * JSON number. If this is not the case, an exception is thrown. + *

+ * If the JSON number is out of the Double range, {@link Double#POSITIVE_INFINITY} or + * {@link Double#NEGATIVE_INFINITY} is returned. + *

+ * + * @return this value as double + * @throws UnsupportedOperationException + * if this value is not a JSON number + */ + public double asDouble() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as String, assuming that this value represents a JSON string. If this + * is not the case, an exception is thrown. + * + * @return the string represented by this value + * @throws UnsupportedOperationException + * if this value is not a JSON string + */ + public String asString() { + throw new UnsupportedOperationException("Not a string: " + toString()); + } + + /** + * Returns this JSON value as a boolean value, assuming that this value is either + * true or false. If this is not the case, an exception is thrown. + * + * @return this value as boolean + * @throws UnsupportedOperationException + * if this value is neither true or false + */ + public boolean asBoolean() { + throw new UnsupportedOperationException("Not a boolean: " + toString()); + } + + /** + * Writes the JSON representation of this value to the given writer in its minimal form, without + * any additional whitespace. + *

+ * Writing performance can be improved by using a {@link java.io.BufferedWriter BufferedWriter}. + *

+ * + * @param writer + * the writer to write this value to + * @throws IOException + * if an I/O error occurs in the writer + */ + public void writeTo(Writer writer) throws IOException { + writeTo(writer, WriterConfig.MINIMAL); + } + + /** + * Writes the JSON representation of this value to the given writer using the given formatting. + *

+ * Writing performance can be improved by using a {@link java.io.BufferedWriter BufferedWriter}. + *

+ * + * @param writer + * the writer to write this value to + * @param config + * a configuration that controls the formatting or null for the minimal form + * @throws IOException + * if an I/O error occurs in the writer + */ + public void writeTo(Writer writer, WriterConfig config) throws IOException { + if (writer == null) { + throw new NullPointerException("writer is null"); + } + if (config == null) { + throw new NullPointerException("config is null"); + } + WritingBuffer buffer = new WritingBuffer(writer, 128); + write(config.createWriter(buffer)); + buffer.flush(); + } + + /** + * Returns the JSON string for this value in its minimal form, without any additional whitespace. + * The result is guaranteed to be a valid input for the method {@link #readFrom(String)} and to + * create a value that is equal to this object. + * + * @return a JSON string that represents this value + */ + @Override + public String toString() { + return toString(WriterConfig.MINIMAL); + } + + /** + * Returns the JSON string for this value using the given formatting. + * + * @param config + * a configuration that controls the formatting or null for the minimal form + * @return a JSON string that represents this value + */ + public String toString(WriterConfig config) { + StringWriter writer = new StringWriter(); + try { + writeTo(writer, config); + } catch (IOException exception) { + // StringWriter does not throw IOExceptions + throw new RuntimeException(exception); + } + return writer.toString(); + } + + /** + * Indicates whether some other object is "equal to" this one according to the contract specified + * in {@link Object#equals(Object)}. + *

+ * Two JsonValues are considered equal if and only if they represent the same JSON text. As a + * consequence, two given JsonObjects may be different even though they contain the same set of + * names with the same values, but in a different order. + *

+ * + * @param object + * the reference object with which to compare + * @return true if this object is the same as the object argument; false otherwise + */ + @Override + public boolean equals(Object object) { + return super.equals(object); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + abstract void write(JSONWriter writer) throws IOException; + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonWriter.java b/blade-kit/src/main/java/blade/kit/json/JSONWriter.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/json/JsonWriter.java rename to blade-kit/src/main/java/blade/kit/json/JSONWriter.java index 52acf7659..f628bdf52 100644 --- a/blade-kit/src/main/java/blade/kit/json/JsonWriter.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONWriter.java @@ -1,145 +1,145 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; - - -class JsonWriter { - - private static final int CONTROL_CHARACTERS_END = 0x001f; - - private static final char[] QUOT_CHARS = {'\\', '"'}; - private static final char[] BS_CHARS = {'\\', '\\'}; - private static final char[] LF_CHARS = {'\\', 'n'}; - private static final char[] CR_CHARS = {'\\', 'r'}; - private static final char[] TAB_CHARS = {'\\', 't'}; - // In JavaScript, U+2028 and U+2029 characters count as line endings and must be encoded. - // http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character - private static final char[] UNICODE_2028_CHARS = {'\\', 'u', '2', '0', '2', '8'}; - private static final char[] UNICODE_2029_CHARS = {'\\', 'u', '2', '0', '2', '9'}; - private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f'}; - - protected final Writer writer; - - JsonWriter(Writer writer) { - this.writer = writer; - } - - protected void writeLiteral(String value) throws IOException { - writer.write(value); - } - - protected void writeNumber(String string) throws IOException { - writer.write(string); - } - - protected void writeString(String string) throws IOException { - writer.write('"'); - writeJsonString(string); - writer.write('"'); - } - - protected void writeArrayOpen() throws IOException { - writer.write('['); - } - - protected void writeArrayClose() throws IOException { - writer.write(']'); - } - - protected void writeArraySeparator() throws IOException { - writer.write(','); - } - - protected void writeObjectOpen() throws IOException { - writer.write('{'); - } - - protected void writeObjectClose() throws IOException { - writer.write('}'); - } - - protected void writeMemberName(String name) throws IOException { - writer.write('"'); - writeJsonString(name); - writer.write('"'); - } - - protected void writeMemberSeparator() throws IOException { - writer.write(':'); - } - - protected void writeObjectSeparator() throws IOException { - writer.write(','); - } - - protected void writeJsonString(String string) throws IOException { - int length = string.length(); - int start = 0; - for (int index = 0; index < length; index++) { - char[] replacement = getReplacementChars(string.charAt(index)); - if (replacement != null) { - writer.write(string, start, index - start); - writer.write(replacement); - start = index + 1; - } - } - writer.write(string, start, length - start); - } - - private static char[] getReplacementChars(char ch) { - if (ch > '\\') { - if (ch < '\u2028' || ch > '\u2029') { - // The lower range contains 'a' .. 'z'. Only 2 checks required. - return null; - } - return ch == '\u2028' ? UNICODE_2028_CHARS : UNICODE_2029_CHARS; - } - if (ch == '\\') { - return BS_CHARS; - } - if (ch > '"') { - // This range contains '0' .. '9' and 'A' .. 'Z'. Need 3 checks to get here. - return null; - } - if (ch == '"') { - return QUOT_CHARS; - } - if (ch > CONTROL_CHARACTERS_END) { - return null; - } - if (ch == '\n') { - return LF_CHARS; - } - if (ch == '\r') { - return CR_CHARS; - } - if (ch == '\t') { - return TAB_CHARS; - } - return new char[] {'\\', 'u', '0', '0', HEX_DIGITS[ch >> 4 & 0x000f], HEX_DIGITS[ch & 0x000f]}; - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; + + +class JSONWriter { + + private static final int CONTROL_CHARACTERS_END = 0x001f; + + private static final char[] QUOT_CHARS = {'\\', '"'}; + private static final char[] BS_CHARS = {'\\', '\\'}; + private static final char[] LF_CHARS = {'\\', 'n'}; + private static final char[] CR_CHARS = {'\\', 'r'}; + private static final char[] TAB_CHARS = {'\\', 't'}; + // In JavaScript, U+2028 and U+2029 characters count as line endings and must be encoded. + // http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character + private static final char[] UNICODE_2028_CHARS = {'\\', 'u', '2', '0', '2', '8'}; + private static final char[] UNICODE_2029_CHARS = {'\\', 'u', '2', '0', '2', '9'}; + private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; + + protected final Writer writer; + + JSONWriter(Writer writer) { + this.writer = writer; + } + + protected void writeLiteral(String value) throws IOException { + writer.write(value); + } + + protected void writeNumber(String string) throws IOException { + writer.write(string); + } + + protected void writeString(String string) throws IOException { + writer.write('"'); + writeJsonString(string); + writer.write('"'); + } + + protected void writeArrayOpen() throws IOException { + writer.write('['); + } + + protected void writeArrayClose() throws IOException { + writer.write(']'); + } + + protected void writeArraySeparator() throws IOException { + writer.write(','); + } + + protected void writeObjectOpen() throws IOException { + writer.write('{'); + } + + protected void writeObjectClose() throws IOException { + writer.write('}'); + } + + protected void writeMemberName(String name) throws IOException { + writer.write('"'); + writeJsonString(name); + writer.write('"'); + } + + protected void writeMemberSeparator() throws IOException { + writer.write(':'); + } + + protected void writeObjectSeparator() throws IOException { + writer.write(','); + } + + protected void writeJsonString(String string) throws IOException { + int length = string.length(); + int start = 0; + for (int index = 0; index < length; index++) { + char[] replacement = getReplacementChars(string.charAt(index)); + if (replacement != null) { + writer.write(string, start, index - start); + writer.write(replacement); + start = index + 1; + } + } + writer.write(string, start, length - start); + } + + private static char[] getReplacementChars(char ch) { + if (ch > '\\') { + if (ch < '\u2028' || ch > '\u2029') { + // The lower range contains 'a' .. 'z'. Only 2 checks required. + return null; + } + return ch == '\u2028' ? UNICODE_2028_CHARS : UNICODE_2029_CHARS; + } + if (ch == '\\') { + return BS_CHARS; + } + if (ch > '"') { + // This range contains '0' .. '9' and 'A' .. 'Z'. Need 3 checks to get here. + return null; + } + if (ch == '"') { + return QUOT_CHARS; + } + if (ch > CONTROL_CHARACTERS_END) { + return null; + } + if (ch == '\n') { + return LF_CHARS; + } + if (ch == '\r') { + return CR_CHARS; + } + if (ch == '\t') { + return TAB_CHARS; + } + return new char[] {'\\', 'u', '0', '0', HEX_DIGITS[ch >> 4 & 0x000f], HEX_DIGITS[ch & 0x000f]}; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/Json.java b/blade-kit/src/main/java/blade/kit/json/Json.java deleted file mode 100644 index 447de974d..000000000 --- a/blade-kit/src/main/java/blade/kit/json/Json.java +++ /dev/null @@ -1,427 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Reader; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import blade.kit.CollectionKit; - -/** - * This class serves as the entry point to the minimal-json API. - *

- * To parse a given JSON input, use the parse() - * methods like in this example: - *

- * - *
- * JsonObject object = Json.parse(string).asObject();
- * 
- *

- * To create a JSON data structure to be serialized, use the - * methods value(), array(), and object() - * . For example, the following snippet will produce the JSON string - * {"foo": 23, "bar": true}: - *

- * - *
- * String string = Json.object().add("foo", 23).add("bar", true).toString();
- * 
- *

- * To create a JSON array from a given Java array, you can use one of the - * array() methods with varargs parameters: - *

- * - *
- * String[] names = ...
- * JsonArray array = Json.array(names);
- * 
- */ -@SuppressWarnings("unchecked") -public final class Json { - - private Json() { - // not meant to be instantiated - } - - /** - * Represents the JSON literal null. - */ - public static final JsonValue NULL = new JsonLiteral("null"); - - /** - * Represents the JSON literal true. - */ - public static final JsonValue TRUE = new JsonLiteral("true"); - - /** - * Represents the JSON literal false. - */ - public static final JsonValue FALSE = new JsonLiteral("false"); - - /** - * Returns a JsonValue instance that represents the given int - * value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - */ - public static JsonValue value(int value) { - return new JsonNumber(Integer.toString(value, 10)); - } - - /** - * Returns a JsonValue instance that represents the given long - * value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - */ - public static JsonValue value(long value) { - return new JsonNumber(Long.toString(value, 10)); - } - - /** - * Returns a JsonValue instance that represents the given float - * value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - */ - public static JsonValue value(float value) { - if (Float.isInfinite(value) || Float.isNaN(value)) { - throw new IllegalArgumentException("Infinite and NaN values not permitted in JSON"); - } - return new JsonNumber(cutOffPointZero(Float.toString(value))); - } - - /** - * Returns a JsonValue instance that represents the given - * double value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - */ - public static JsonValue value(double value) { - if (Double.isInfinite(value) || Double.isNaN(value)) { - throw new IllegalArgumentException("Infinite and NaN values not permitted in JSON"); - } - return new JsonNumber(cutOffPointZero(Double.toString(value))); - } - - /** - * Returns a JsonValue instance that represents the given string. - * - * @param string - * the string to get a JSON representation for - * @return a JSON value that represents the given string - */ - public static JsonValue value(String string) { - return string == null ? NULL : new JsonString(string); - } - - /** - * Returns a JsonValue instance that represents the given - * boolean value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - */ - public static JsonValue value(boolean value) { - return value ? TRUE : FALSE; - } - - /** - * Creates a new empty JsonArray. This is equivalent to creating a new - * JsonArray using the constructor. - * - * @return a new empty JSON array - */ - public static JsonValue array() { - return new JsonArray(); - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given int values. - * - * @param values the values to be included in the new JSON array - * @return a new JSON array that contains the given values - */ - public static JsonArray array(int... values) { - if (values == null) { - throw new NullPointerException("values is null"); - } - JsonArray array = new JsonArray(); - for (int value : values) { - array.add(value); - } - return array; - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given long values. - * - * @param values - * the values to be included in the new JSON array - * @return a new JSON array that contains the given values - */ - public static JsonArray array(long... values) { - if (values == null) { - throw new NullPointerException("values is null"); - } - JsonArray array = new JsonArray(); - for (long value : values) { - array.add(value); - } - return array; - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given float values. - * - * @param values - * the values to be included in the new JSON array - * @return a new JSON array that contains the given values - */ - public static JsonArray array(float... values) { - if (values == null) { - throw new NullPointerException("values is null"); - } - JsonArray array = new JsonArray(); - for (float value : values) { - array.add(value); - } - return array; - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given double values. - * - * @param values - * the values to be included in the new JSON array - * @return a new JSON array that contains the given values - */ - public static JsonArray array(double... values) { - if (values == null) { - throw new NullPointerException("values is null"); - } - JsonArray array = new JsonArray(); - for (double value : values) { - array.add(value); - } - return array; - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given boolean values. - * - * @param values - * the values to be included in the new JSON array - * @return a new JSON array that contains the given values - */ - public static JsonArray array(boolean... values) { - if (values == null) { - throw new NullPointerException("values is null"); - } - JsonArray array = new JsonArray(); - for (boolean value : values) { - array.add(value); - } - return array; - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given strings. - * - * @param strings - * the strings to be included in the new JSON array - * @return a new JSON array that contains the given strings - */ - public static JsonArray array(String... strings) { - if (strings == null) { - throw new NullPointerException("values is null"); - } - JsonArray array = new JsonArray(); - for (String value : strings) { - array.add(value); - } - return array; - } - - /** - * Creates a new empty JsonObject. This is equivalent to creating a new - * JsonObject using the constructor. - * - * @return a new empty JSON object - */ - public static JsonObject object() { - return new JsonObject(); - } - - /** - * Parses the given input string as JSON. The input must contain a valid - * JSON value, optionally padded with whitespace. - * - * @param string - * the input string, must be valid JSON - * @return a value that represents the parsed JSON - * @throws ParseException - * if the input is not valid JSON - */ - public static JsonValue parse(String string) { - if (string == null) { - throw new NullPointerException("string is null"); - } - try { - return new JsonParser(string).parse(); - } catch (IOException exception) { - // JsonParser does not throw IOException for String - throw new RuntimeException(exception); - } - } - - /** - * Reads the entire input stream from the given reader and parses it as - * JSON. The input must contain a valid JSON value, optionally padded with - * whitespace. - *

- * Characters are read in chunks and buffered internally, therefore wrapping - * an existing reader in an additional BufferedReader does - * not improve reading performance. - *

- * - * @param reader - * the reader to read the JSON value from - * @return a value that represents the parsed JSON - * @throws IOException - * if an I/O error occurs in the reader - * @throws ParseException - * if the input is not valid JSON - */ - public static JsonValue parse(Reader reader) throws IOException { - if (reader == null) { - throw new NullPointerException("reader is null"); - } - return new JsonParser(reader).parse(); - } - - /** - * 对象转换为JsonValue对象 - * - * @param bean - * @return - */ - public static JsonObject parse(Object bean) { - JsonObject json = new JsonObject(); - Class klass = bean.getClass(); - boolean includeSuperClass = klass.getClassLoader() != null; - - Method[] methods = includeSuperClass ? klass.getMethods() : klass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i += 1) { - try { - Method method = methods[i]; - if (Modifier.isPublic(method.getModifiers())) { - String name = method.getName(); - String key = ""; - if (name.startsWith("get")) { - if ("getClass".equals(name) || "getDeclaringClass".equals(name)) { - key = ""; - } else { - key = name.substring(3); - } - } else if (name.startsWith("is")) { - key = name.substring(2); - } - if (key.length() > 0 && Character.isUpperCase(key.charAt(0)) - && method.getParameterTypes().length == 0) { - if (key.length() == 1) { - key = key.toLowerCase(); - } else if (!Character.isUpperCase(key.charAt(1))) { - key = key.substring(0, 1).toLowerCase() + key.substring(1); - } - - Object result = method.invoke(bean, (Object[]) null); - if (result != null) { - json.add(name, result); - } - } - } - } catch (Exception ignore) { - } - } - return json; - } - - public static JsonObject parse(Map map) { - if (map != null && !map.isEmpty()) { - JsonObject jsonObject = new JsonObject(); - Iterator iterator = map.entrySet().iterator(); - while (iterator.hasNext()) { - Map.Entry entry = (Map.Entry) iterator.next(); - String key = entry.getKey(); - Object val = entry.getValue(); - jsonObject.add(key, val); - } - return jsonObject; - } - return null; - } - - public static Map parseToMap(JsonObject jo) { - Map map = CollectionKit.newHashMap(); - if (jo != null) { - List names = jo.names(); - for (String name : names) { - map.put(name, (V) jo.get(name)); - } - } - return map; - } - - public static Map parseToMap(String json) { - return parseToMap(parse(json).asObject()); - } - - private static String cutOffPointZero(String string) { - if (string.endsWith(".0")) { - return string.substring(0, string.length() - 2); - } - return string; - } - -} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonArray.java b/blade-kit/src/main/java/blade/kit/json/JsonArray.java deleted file mode 100644 index ac8e562c1..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JsonArray.java +++ /dev/null @@ -1,457 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - - -/** - * Represents a JSON array, an ordered collection of JSON values. - *

- * Elements can be added using the add(...) methods which accept instances of - * {@link JsonValue}, strings, primitive numbers, and boolean values. To replace an element of an - * array, use the set(int, ...) methods. - *

- *

- * Elements can be accessed by their index using {@link #get(int)}. This class also supports - * iterating over the elements in document order using an {@link #iterator()} or an enhanced for - * loop: - *

- *
- * for (JsonValue value : jsonArray) {
- *   ...
- * }
- * 
- *

- * An equivalent {@link List} can be obtained from the method {@link #values()}. - *

- *

- * Note that this class is not thread-safe. If multiple threads access a - * JsonArray instance concurrently, while at least one of these threads modifies the - * contents of this array, access to the instance must be synchronized externally. Failure to do so - * may lead to an inconsistent state. - *

- *

- * This class is not supposed to be extended by clients. - *

- */ -@SuppressWarnings("serial") // use default serial UID -public class JsonArray extends JsonValue implements Iterable { - - private final List values; - - /** - * Creates a new empty JsonArray. - */ - public JsonArray() { - values = new ArrayList(); - } - - /** - * Creates a new JsonArray with the contents of the specified JSON array. - * - * @param array - * the JsonArray to get the initial contents from, must not be null - */ - public JsonArray(JsonArray array) { - this(array, false); - } - - private JsonArray(JsonArray array, boolean unmodifiable) { - if (array == null) { - throw new NullPointerException("array is null"); - } - if (unmodifiable) { - values = Collections.unmodifiableList(array.values); - } else { - values = new ArrayList(array.values); - } - } - - /** - * Returns an unmodifiable wrapper for the specified JsonArray. This method allows to provide - * read-only access to a JsonArray. - *

- * The returned JsonArray is backed by the given array and reflects subsequent changes. Attempts - * to modify the returned JsonArray result in an UnsupportedOperationException. - *

- * - * @param array - * the JsonArray for which an unmodifiable JsonArray is to be returned - * @return an unmodifiable view of the specified JsonArray - */ - public static JsonArray unmodifiableArray(JsonArray array) { - return new JsonArray(array, true); - } - - /** - * Appends the JSON representation of the specified int value to the end of this - * array. - * - * @param value - * the value to add to the array - * @return the array itself, to enable method chaining - */ - public JsonArray add(int value) { - values.add(Json.value(value)); - return this; - } - - /** - * Appends the JSON representation of the specified long value to the end of this - * array. - * - * @param value - * the value to add to the array - * @return the array itself, to enable method chaining - */ - public JsonArray add(long value) { - values.add(Json.value(value)); - return this; - } - - /** - * Appends the JSON representation of the specified float value to the end of this - * array. - * - * @param value - * the value to add to the array - * @return the array itself, to enable method chaining - */ - public JsonArray add(float value) { - values.add(Json.value(value)); - return this; - } - - /** - * Appends the JSON representation of the specified double value to the end of this - * array. - * - * @param value - * the value to add to the array - * @return the array itself, to enable method chaining - */ - public JsonArray add(double value) { - values.add(Json.value(value)); - return this; - } - - /** - * Appends the JSON representation of the specified boolean value to the end of this - * array. - * - * @param value - * the value to add to the array - * @return the array itself, to enable method chaining - */ - public JsonArray add(boolean value) { - values.add(Json.value(value)); - return this; - } - - /** - * Appends the JSON representation of the specified string to the end of this array. - * - * @param value - * the string to add to the array - * @return the array itself, to enable method chaining - */ - public JsonArray add(String value) { - values.add(Json.value(value)); - return this; - } - - /** - * Appends the specified JSON value to the end of this array. - * - * @param value - * the JsonValue to add to the array, must not be null - * @return the array itself, to enable method chaining - */ - public JsonArray add(JsonValue value) { - if (value == null) { - throw new NullPointerException("value is null"); - } - values.add(value); - return this; - } - - /** - * Replaces the element at the specified position in this array with the JSON representation of - * the specified int value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 or - * index >= size - */ - public JsonArray set(int index, int value) { - values.set(index, Json.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the JSON representation of - * the specified long value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 or - * index >= size - */ - public JsonArray set(int index, long value) { - values.set(index, Json.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the JSON representation of - * the specified float value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 or - * index >= size - */ - public JsonArray set(int index, float value) { - values.set(index, Json.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the JSON representation of - * the specified double value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 or - * index >= size - */ - public JsonArray set(int index, double value) { - values.set(index, Json.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the JSON representation of - * the specified boolean value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 or - * index >= size - */ - public JsonArray set(int index, boolean value) { - values.set(index, Json.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the JSON representation of - * the specified string. - * - * @param index - * the index of the array element to replace - * @param value - * the string to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 or - * index >= size - */ - public JsonArray set(int index, String value) { - values.set(index, Json.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the specified JSON value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position, must not be null - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 or - * index >= size - */ - public JsonArray set(int index, JsonValue value) { - if (value == null) { - throw new NullPointerException("value is null"); - } - values.set(index, value); - return this; - } - - /** - * Removes the element at the specified index from this array. - * - * @param index - * the index of the element to remove - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 or - * index >= size - */ - public JsonArray remove(int index) { - values.remove(index); - return this; - } - - /** - * Returns the number of elements in this array. - * - * @return the number of elements in this array - */ - public int size() { - return values.size(); - } - - /** - * Returns true if this array contains no elements. - * - * @return true if this array contains no elements - */ - public boolean isEmpty() { - return values.isEmpty(); - } - - /** - * Returns the value of the element at the specified position in this array. - * - * @param index - * the index of the array element to return - * @return the value of the element at the specified position - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 or - * index >= size - */ - public JsonValue get(int index) { - return values.get(index); - } - - /** - * Returns a list of the values in this array in document order. The returned list is backed by - * this array and will reflect subsequent changes. It cannot be used to modify this array. - * Attempts to modify the returned list will result in an exception. - * - * @return a list of the values in this array - */ - public List values() { - return Collections.unmodifiableList(values); - } - - /** - * Returns an iterator over the values of this array in document order. The returned iterator - * cannot be used to modify this array. - * - * @return an iterator over the values of this array - */ - public Iterator iterator() { - final Iterator iterator = values.iterator(); - return new Iterator() { - - public boolean hasNext() { - return iterator.hasNext(); - } - - public JsonValue next() { - return iterator.next(); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - void write(JsonWriter writer) throws IOException { - writer.writeArrayOpen(); - Iterator iterator = iterator(); - boolean first = true; - while (iterator.hasNext()) { - if (!first) { - writer.writeArraySeparator(); - } - iterator.next().write(writer); - first = false; - } - writer.writeArrayClose(); - } - - @Override - public boolean isArray() { - return true; - } - - @Override - public JsonArray asArray() { - return this; - } - - @Override - public int hashCode() { - return values.hashCode(); - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JsonArray other = (JsonArray)object; - return values.equals(other.values); - } - -} diff --git a/blade-kit/src/main/java/blade/kit/json/JsonObject.java b/blade-kit/src/main/java/blade/kit/json/JsonObject.java deleted file mode 100644 index 2b863e692..000000000 --- a/blade-kit/src/main/java/blade/kit/json/JsonObject.java +++ /dev/null @@ -1,966 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import blade.kit.json.JsonObject.Member; - - -/** - * Represents a JSON object, a set of name/value pairs, where the names are strings and the values - * are JSON values. - *

- * Members can be added using the add(String, ...) methods which accept instances of - * {@link JsonValue}, strings, primitive numbers, and boolean values. To modify certain values of an - * object, use the set(String, ...) methods. Please note that the add - * methods are faster than set as they do not search for existing members. On the other - * hand, the add methods do not prevent adding multiple members with the same name. - * Duplicate names are discouraged but not prohibited by JSON. - *

- *

- * Members can be accessed by their name using {@link #get(String)}. A list of all names can be - * obtained from the method {@link #names()}. This class also supports iterating over the members in - * document order using an {@link #iterator()} or an enhanced for loop: - *

- *
- * for (Member member : jsonObject) {
- *   String name = member.getName();
- *   JsonValue value = member.getValue();
- *   ...
- * }
- * 
- *

- * Even though JSON objects are unordered by definition, instances of this class preserve the order - * of members to allow processing in document order and to guarantee a predictable output. - *

- *

- * Note that this class is not thread-safe. If multiple threads access a - * JsonObject instance concurrently, while at least one of these threads modifies the - * contents of this object, access to the instance must be synchronized externally. Failure to do so - * may lead to an inconsistent state. - *

- *

- * This class is not supposed to be extended by clients. - *

- */ -@SuppressWarnings("serial") // use default serial UID -public class JsonObject extends JsonValue implements Iterable { - - private final List names; - private final List values; - private transient HashIndexTable table; - - /** - * Creates a new empty JsonObject. - */ - public JsonObject() { - names = new ArrayList(); - values = new ArrayList(); - table = new HashIndexTable(); - } - - /** - * Creates a new JsonObject, initialized with the contents of the specified JSON object. - * - * @param object - * the JSON object to get the initial contents from, must not be null - */ - public JsonObject(JsonObject object) { - this(object, false); - } - - private JsonObject(JsonObject object, boolean unmodifiable) { - if (object == null) { - throw new NullPointerException("object is null"); - } - if (unmodifiable) { - names = Collections.unmodifiableList(object.names); - values = Collections.unmodifiableList(object.values); - } else { - names = new ArrayList(object.names); - values = new ArrayList(object.values); - } - table = new HashIndexTable(); - updateHashIndex(); - } - - /** - * Returns an unmodifiable JsonObject for the specified one. This method allows to provide - * read-only access to a JsonObject. - *

- * The returned JsonObject is backed by the given object and reflect changes that happen to it. - * Attempts to modify the returned JsonObject result in an - * UnsupportedOperationException. - *

- * - * @param object - * the JsonObject for which an unmodifiable JsonObject is to be returned - * @return an unmodifiable view of the specified JsonObject - */ - public static JsonObject unmodifiableObject(JsonObject object) { - return new JsonObject(object, true); - } - - /** - * Appends a new member to the end of this object, with the specified name and the JSON - * representation of the specified int value. - *

- * This method does not prevent duplicate names. Calling this method with a name - * that already exists in the object will append another member with the same name. In order to - * replace existing members, use the method set(name, value) instead. However, - * add is much faster than set (because it does not need to - * search for existing members). Therefore add should be preferred when constructing new - * objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JsonObject add(String name, int value) { - add(name, Json.value(value)); - return this; - } - - public JsonObject add(String name, Object value) { - - if(value instanceof String){ - add(name, Json.value((String) value)); - } - - if(value instanceof Integer){ - add(name, Json.value((Integer) value)); - } - - if(value instanceof Long){ - add(name, Json.value((Long) value)); - } - - if(value instanceof JsonValue){ - add(name, (JsonValue) value); - } - - if(value instanceof JsonObject){ - add(name, (JsonObject) value); - } - - if(value instanceof JsonArray){ - add(name, (JsonArray) value); - } - - if(value instanceof Boolean){ - add(name, Json.value((Boolean) value)); - } - - if(value instanceof Byte){ - add(name, Json.value((Byte) value)); - } - - if(value instanceof Character){ - add(name, Json.value((Character) value)); - } - - if(value instanceof Short){ - add(name, Json.value((Short) value)); - } - - if(value instanceof Float){ - add(name, Json.value((Float) value)); - } - - if(value instanceof Double){ - add(name, Json.value((Double) value)); - } - - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name and the JSON - * representation of the specified long value. - *

- * This method does not prevent duplicate names. Calling this method with a name - * that already exists in the object will append another member with the same name. In order to - * replace existing members, use the method set(name, value) instead. However, - * add is much faster than set (because it does not need to - * search for existing members). Therefore add should be preferred when constructing new - * objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JsonObject add(String name, long value) { - add(name, Json.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name and the JSON - * representation of the specified float value. - *

- * This method does not prevent duplicate names. Calling this method with a name - * that already exists in the object will append another member with the same name. In order to - * replace existing members, use the method set(name, value) instead. However, - * add is much faster than set (because it does not need to - * search for existing members). Therefore add should be preferred when constructing new - * objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JsonObject add(String name, float value) { - add(name, Json.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name and the JSON - * representation of the specified double value. - *

- * This method does not prevent duplicate names. Calling this method with a name - * that already exists in the object will append another member with the same name. In order to - * replace existing members, use the method set(name, value) instead. However, - * add is much faster than set (because it does not need to - * search for existing members). Therefore add should be preferred when constructing new - * objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JsonObject add(String name, double value) { - add(name, Json.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name and the JSON - * representation of the specified boolean value. - *

- * This method does not prevent duplicate names. Calling this method with a name - * that already exists in the object will append another member with the same name. In order to - * replace existing members, use the method set(name, value) instead. However, - * add is much faster than set (because it does not need to - * search for existing members). Therefore add should be preferred when constructing new - * objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JsonObject add(String name, boolean value) { - add(name, Json.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name and the JSON - * representation of the specified string. - *

- * This method does not prevent duplicate names. Calling this method with a name - * that already exists in the object will append another member with the same name. In order to - * replace existing members, use the method set(name, value) instead. However, - * add is much faster than set (because it does not need to - * search for existing members). Therefore add should be preferred when constructing new - * objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JsonObject add(String name, String value) { - add(name, Json.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name and the specified JSON - * value. - *

- * This method does not prevent duplicate names. Calling this method with a name - * that already exists in the object will append another member with the same name. In order to - * replace existing members, use the method set(name, value) instead. However, - * add is much faster than set (because it does not need to - * search for existing members). Therefore add should be preferred when constructing new - * objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add, must not be null - * @return the object itself, to enable method chaining - */ - public JsonObject add(String name, JsonValue value) { - if (name == null) { - throw new NullPointerException("name is null"); - } - if (value == null) { - throw new NullPointerException("value is null"); - } - table.add(name, names.size()); - names.add(name); - values.add(value); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON representation of the - * specified int value. If this object does not contain a member with this name, a - * new member is added at the end of the object. If this object contains multiple members with - * this name, only the last one is changed. - *

- * This method should only be used to modify existing objects. To fill a new - * object with members, the method add(name, value) should be preferred which is much - * faster (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to replace - * @param value - * the value to set to the member - * @return the object itself, to enable method chaining - */ - public JsonObject set(String name, int value) { - set(name, Json.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON representation of the - * specified long value. If this object does not contain a member with this name, a - * new member is added at the end of the object. If this object contains multiple members with - * this name, only the last one is changed. - *

- * This method should only be used to modify existing objects. To fill a new - * object with members, the method add(name, value) should be preferred which is much - * faster (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to replace - * @param value - * the value to set to the member - * @return the object itself, to enable method chaining - */ - public JsonObject set(String name, long value) { - set(name, Json.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON representation of the - * specified float value. If this object does not contain a member with this name, a - * new member is added at the end of the object. If this object contains multiple members with - * this name, only the last one is changed. - *

- * This method should only be used to modify existing objects. To fill a new - * object with members, the method add(name, value) should be preferred which is much - * faster (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JsonObject set(String name, float value) { - set(name, Json.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON representation of the - * specified double value. If this object does not contain a member with this name, a - * new member is added at the end of the object. If this object contains multiple members with - * this name, only the last one is changed. - *

- * This method should only be used to modify existing objects. To fill a new - * object with members, the method add(name, value) should be preferred which is much - * faster (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JsonObject set(String name, double value) { - set(name, Json.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON representation of the - * specified boolean value. If this object does not contain a member with this name, - * a new member is added at the end of the object. If this object contains multiple members with - * this name, only the last one is changed. - *

- * This method should only be used to modify existing objects. To fill a new - * object with members, the method add(name, value) should be preferred which is much - * faster (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JsonObject set(String name, boolean value) { - set(name, Json.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON representation of the - * specified string. If this object does not contain a member with this name, a new member is - * added at the end of the object. If this object contains multiple members with this name, only - * the last one is changed. - *

- * This method should only be used to modify existing objects. To fill a new - * object with members, the method add(name, value) should be preferred which is much - * faster (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JsonObject set(String name, String value) { - set(name, Json.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the specified JSON value. If this - * object does not contain a member with this name, a new member is added at the end of the - * object. If this object contains multiple members with this name, only the last one is changed. - *

- * This method should only be used to modify existing objects. To fill a new - * object with members, the method add(name, value) should be preferred which is much - * faster (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add, must not be null - * @return the object itself, to enable method chaining - */ - public JsonObject set(String name, JsonValue value) { - if (name == null) { - throw new NullPointerException("name is null"); - } - if (value == null) { - throw new NullPointerException("value is null"); - } - int index = indexOf(name); - if (index != -1) { - values.set(index, value); - } else { - table.add(name, names.size()); - names.add(name); - values.add(value); - } - return this; - } - - /** - * Removes a member with the specified name from this object. If this object contains multiple - * members with the given name, only the last one is removed. If this object does not contain a - * member with the specified name, the object is not modified. - * - * @param name - * the name of the member to remove - * @return the object itself, to enable method chaining - */ - public JsonObject remove(String name) { - if (name == null) { - throw new NullPointerException("name is null"); - } - int index = indexOf(name); - if (index != -1) { - table.remove(index); - names.remove(index); - values.remove(index); - } - return this; - } - - /** - * Copies all members of the specified object into this object. When the specified object contains - * members with names that also exist in this object, the existing values in this object will be - * replaced by the corresponding values in the specified object. - * - * @param object - * the object to merge - * @return the object itself, to enable method chaining - */ - public JsonObject merge(JsonObject object) { - if (object == null) { - throw new NullPointerException("object is null"); - } - for (Member member : object) { - this.set(member.name, member.value); - } - return this; - } - - /** - * Returns the value of the member with the specified name in this object. If this object contains - * multiple members with the given name, this method will return the last one. - * - * @param name - * the name of the member whose value is to be returned - * @return the value of the last member with the specified name, or null if this - * object does not contain a member with that name - */ - public JsonValue get(String name) { - if (name == null) { - throw new NullPointerException("name is null"); - } - int index = indexOf(name); - return index != -1 ? values.get(index) : null; - } - - /** - * Returns the int value of the member with the specified name in this object. If - * this object does not contain a member with this name, the given default value is returned. If - * this object contains multiple members with the given name, the last one will be picked. If this - * member's value does not represent a JSON number or if it cannot be interpreted as Java - * int, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the given default value if - * this object does not contain a member with that name - */ - public int getInt(String name, int defaultValue) { - JsonValue value = get(name); - return value != null ? value.asInt() : defaultValue; - } - - public Integer getInt(String name) { - JsonValue value = get(name); - if(null != value){ - return value.asInt(); - } - return null; - } - - /** - * Returns the long value of the member with the specified name in this object. If - * this object does not contain a member with this name, the given default value is returned. If - * this object contains multiple members with the given name, the last one will be picked. If this - * member's value does not represent a JSON number or if it cannot be interpreted as Java - * long, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the given default value if - * this object does not contain a member with that name - */ - public long getLong(String name, long defaultValue) { - JsonValue value = get(name); - return value != null ? value.asLong() : defaultValue; - } - - public Long getLong(String name) { - JsonValue value = get(name); - if(null != value){ - return value.asLong(); - } - return null; - } - - /** - * Returns the float value of the member with the specified name in this object. If - * this object does not contain a member with this name, the given default value is returned. If - * this object contains multiple members with the given name, the last one will be picked. If this - * member's value does not represent a JSON number or if it cannot be interpreted as Java - * float, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the given default value if - * this object does not contain a member with that name - */ - public float getFloat(String name, float defaultValue) { - JsonValue value = get(name); - return value != null ? value.asFloat() : defaultValue; - } - - public Float getFloat(String name) { - JsonValue value = get(name); - if(null != value){ - return value.asFloat(); - } - return null; - } - - /** - * Returns the double value of the member with the specified name in this object. If - * this object does not contain a member with this name, the given default value is returned. If - * this object contains multiple members with the given name, the last one will be picked. If this - * member's value does not represent a JSON number or if it cannot be interpreted as Java - * double, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the given default value if - * this object does not contain a member with that name - */ - public double getDouble(String name, double defaultValue) { - JsonValue value = get(name); - return value != null ? value.asDouble() : defaultValue; - } - - public Double getDouble(String name) { - JsonValue value = get(name); - if(null != value){ - return value.asDouble(); - } - return null; - } - - /** - * Returns the boolean value of the member with the specified name in this object. If - * this object does not contain a member with this name, the given default value is returned. If - * this object contains multiple members with the given name, the last one will be picked. If this - * member's value does not represent a JSON true or false value, an - * exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the given default value if - * this object does not contain a member with that name - */ - public boolean getBoolean(String name, boolean defaultValue) { - JsonValue value = get(name); - return value != null ? value.asBoolean() : defaultValue; - } - - public Boolean getBoolean(String name) { - JsonValue value = get(name); - if(null != value){ - return value.asBoolean(); - } - return null; - } - - /** - * Returns the String value of the member with the specified name in this object. If - * this object does not contain a member with this name, the given default value is returned. If - * this object contains multiple members with the given name, the last one is picked. If this - * member's value does not represent a JSON string, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the given default value if - * this object does not contain a member with that name - */ - public String getString(String name, String defaultValue) { - JsonValue value = get(name); - return value != null ? value.asString() : defaultValue; - } - - public String getString(String name) { - JsonValue value = get(name); - if(null != value){ - return value.asString(); - } - return null; - } - - /** - * Returns the number of members (name/value pairs) in this object. - * - * @return the number of members in this object - */ - public int size() { - return names.size(); - } - - /** - * Returns true if this object contains no members. - * - * @return true if this object contains no members - */ - public boolean isEmpty() { - return names.isEmpty(); - } - - /** - * Returns a list of the names in this object in document order. The returned list is backed by - * this object and will reflect subsequent changes. It cannot be used to modify this object. - * Attempts to modify the returned list will result in an exception. - * - * @return a list of the names in this object - */ - public List names() { - return Collections.unmodifiableList(names); - } - - /** - * Returns an iterator over the members of this object in document order. The returned iterator - * cannot be used to modify this object. - * - * @return an iterator over the members of this object - */ - public Iterator iterator() { - final Iterator namesIterator = names.iterator(); - final Iterator valuesIterator = values.iterator(); - return new Iterator() { - - public boolean hasNext() { - return namesIterator.hasNext(); - } - - public Member next() { - String name = namesIterator.next(); - JsonValue value = valuesIterator.next(); - return new Member(name, value); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } - - @Override - void write(JsonWriter writer) throws IOException { - writer.writeObjectOpen(); - Iterator namesIterator = names.iterator(); - Iterator valuesIterator = values.iterator(); - boolean first = true; - while (namesIterator.hasNext()) { - if (!first) { - writer.writeObjectSeparator(); - } - writer.writeMemberName(namesIterator.next()); - writer.writeMemberSeparator(); - valuesIterator.next().write(writer); - first = false; - } - writer.writeObjectClose(); - } - - @Override - public boolean isObject() { - return true; - } - - @Override - public JsonObject asObject() { - return this; - } - - @Override - public int hashCode() { - int result = 1; - result = 31 * result + names.hashCode(); - result = 31 * result + values.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - JsonObject other = (JsonObject)obj; - return names.equals(other.names) && values.equals(other.values); - } - - int indexOf(String name) { - int index = table.get(name); - if (index != -1 && name.equals(names.get(index))) { - return index; - } - return names.lastIndexOf(name); - } - - private synchronized void readObject(ObjectInputStream inputStream) - throws IOException, ClassNotFoundException - { - inputStream.defaultReadObject(); - table = new HashIndexTable(); - updateHashIndex(); - } - - private void updateHashIndex() { - int size = names.size(); - for (int i = 0; i < size; i++) { - table.add(names.get(i), i); - } - } - - /** - * Represents a member of a JSON object, a pair of a name and a value. - */ - public static class Member { - - private final String name; - private final JsonValue value; - - Member(String name, JsonValue value) { - this.name = name; - this.value = value; - } - - /** - * Returns the name of this member. - * - * @return the name of this member, never null - */ - public String getName() { - return name; - } - - /** - * Returns the value of this member. - * - * @return the value of this member, never null - */ - public JsonValue getValue() { - return value; - } - - @Override - public int hashCode() { - int result = 1; - result = 31 * result + name.hashCode(); - result = 31 * result + value.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Member other = (Member)obj; - return name.equals(other.name) && value.equals(other.value); - } - - } - - static class HashIndexTable { - - private final byte[] hashTable = new byte[32]; // must be a power of two - - public HashIndexTable() { - } - - public HashIndexTable(HashIndexTable original) { - System.arraycopy(original.hashTable, 0, hashTable, 0, hashTable.length); - } - - void add(String name, int index) { - int slot = hashSlotFor(name); - if (index < 0xff) { - // increment by 1, 0 stands for empty - hashTable[slot] = (byte)(index + 1); - } else { - hashTable[slot] = 0; - } - } - - void remove(int index) { - for (int i = 0; i < hashTable.length; i++) { - if (hashTable[i] == index + 1) { - hashTable[i] = 0; - } else if (hashTable[i] > index + 1) { - hashTable[i]--; - } - } - } - - int get(Object name) { - int slot = hashSlotFor(name); - // subtract 1, 0 stands for empty - return (hashTable[slot] & 0xff) - 1; - } - - private int hashSlotFor(Object element) { - return element.hashCode() & hashTable.length - 1; - } - - } - -} diff --git a/blade-kit/src/main/java/blade/kit/json/ParseException.java b/blade-kit/src/main/java/blade/kit/json/ParseException.java index bf60c6ba6..623eb6d50 100644 --- a/blade-kit/src/main/java/blade/kit/json/ParseException.java +++ b/blade-kit/src/main/java/blade/kit/json/ParseException.java @@ -1,70 +1,70 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -/** - * An unchecked exception to indicate that an input does not qualify as valid JSON. - */ -@SuppressWarnings("serial") // use default serial UID -public class ParseException extends RuntimeException { - - private final int offset; - private final int line; - private final int column; - - ParseException(String message, int offset, int line, int column) { - super(message + " at " + line + ":" + column); - this.offset = offset; - this.line = line; - this.column = column; - } - - /** - * Returns the absolute index of the character at which the error occurred. The index of the first - * character of a document is 0. - * - * @return the character offset at which the error occurred, will be >= 0 - */ - public int getOffset() { - return offset; - } - - /** - * Returns the number of the line in which the error occurred. The first line counts as 1. - * - * @return the line in which the error occurred, will be >= 1 - */ - public int getLine() { - return line; - } - - /** - * Returns the index of the character at which the error occurred, relative to the line. The index - * of the first character of a line is 0. - * - * @return the column in which the error occurred, will be >= 0 - */ - public int getColumn() { - return column; - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +/** + * An unchecked exception to indicate that an input does not qualify as valid JSON. + */ +@SuppressWarnings("serial") // use default serial UID +public class ParseException extends RuntimeException { + + private final int offset; + private final int line; + private final int column; + + ParseException(String message, int offset, int line, int column) { + super(message + " at " + line + ":" + column); + this.offset = offset; + this.line = line; + this.column = column; + } + + /** + * Returns the absolute index of the character at which the error occurred. The index of the first + * character of a document is 0. + * + * @return the character offset at which the error occurred, will be >= 0 + */ + public int getOffset() { + return offset; + } + + /** + * Returns the number of the line in which the error occurred. The first line counts as 1. + * + * @return the line in which the error occurred, will be >= 1 + */ + public int getLine() { + return line; + } + + /** + * Returns the index of the character at which the error occurred, relative to the line. The index + * of the first character of a line is 0. + * + * @return the column in which the error occurred, will be >= 0 + */ + public int getColumn() { + return column; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java b/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java index c7de761b8..c78cb0475 100644 --- a/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java +++ b/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java @@ -1,157 +1,157 @@ -/******************************************************************************* - * Copyright (c) 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; -import java.util.Arrays; - - -/** - * Enables human readable JSON output by inserting whitespace between values.after commas and - * colons. Example: - * - *
- * jsonValue.writeTo(writer, PrettyPrint.singleLine());
- * 
- */ -public class PrettyPrint extends WriterConfig { - - private final char[] indentChars; - - protected PrettyPrint(char[] indentChars) { - this.indentChars = indentChars; - } - - /** - * Print every value on a separate line. Use tabs (\t) for indentation. - * - * @return A PrettyPrint instance for wrapped mode with tab indentation - */ - public static PrettyPrint singleLine() { - return new PrettyPrint(null); - } - - /** - * Print every value on a separate line. Use the given number of spaces for indentation. - * - * @param number - * the number of spaces to use - * @return A PrettyPrint instance for wrapped mode with spaces indentation - */ - public static PrettyPrint indentWithSpaces(int number) { - if (number < 0) { - throw new IllegalArgumentException("number is negative"); - } - char[] chars = new char[number]; - Arrays.fill(chars, ' '); - return new PrettyPrint(chars); - } - - /** - * Do not break lines, but still insert whitespace between values. - * - * @return A PrettyPrint instance for single-line mode - */ - public static PrettyPrint indentWithTabs() { - return new PrettyPrint(new char[] {'\t'}); - } - - @Override - protected JsonWriter createWriter(Writer writer) { - return new PrettyPrintWriter(writer, indentChars); - } - - private static class PrettyPrintWriter extends JsonWriter { - - private final char[] indentChars; - private int indent; - - private PrettyPrintWriter(Writer writer, char[] indentChars) { - super(writer); - this.indentChars = indentChars; - } - - @Override - protected void writeArrayOpen() throws IOException { - indent++; - writer.write('['); - writeNewLine(); - } - - @Override - protected void writeArrayClose() throws IOException { - indent--; - writeNewLine(); - writer.write(']'); - } - - @Override - protected void writeArraySeparator() throws IOException { - writer.write(','); - if (!writeNewLine()) { - writer.write(' '); - } - } - - @Override - protected void writeObjectOpen() throws IOException { - indent++; - writer.write('{'); - writeNewLine(); - } - - @Override - protected void writeObjectClose() throws IOException { - indent--; - writeNewLine(); - writer.write('}'); - } - - @Override - protected void writeMemberSeparator() throws IOException { - writer.write(':'); - writer.write(' '); - } - - @Override - protected void writeObjectSeparator() throws IOException { - writer.write(','); - if (!writeNewLine()) { - writer.write(' '); - } - } - - private boolean writeNewLine() throws IOException { - if (indentChars == null) { - return false; - } - writer.write('\n'); - for (int i = 0; i < indent; i++) { - writer.write(indentChars); - } - return true; - } - - } - -} +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; +import java.util.Arrays; + + +/** + * Enables human readable JSON output by inserting whitespace between values.after commas and + * colons. Example: + * + *
+ * jsonValue.writeTo(writer, PrettyPrint.singleLine());
+ * 
+ */ +public class PrettyPrint extends WriterConfig { + + private final char[] indentChars; + + protected PrettyPrint(char[] indentChars) { + this.indentChars = indentChars; + } + + /** + * Print every value on a separate line. Use tabs (\t) for indentation. + * + * @return A PrettyPrint instance for wrapped mode with tab indentation + */ + public static PrettyPrint singleLine() { + return new PrettyPrint(null); + } + + /** + * Print every value on a separate line. Use the given number of spaces for indentation. + * + * @param number + * the number of spaces to use + * @return A PrettyPrint instance for wrapped mode with spaces indentation + */ + public static PrettyPrint indentWithSpaces(int number) { + if (number < 0) { + throw new IllegalArgumentException("number is negative"); + } + char[] chars = new char[number]; + Arrays.fill(chars, ' '); + return new PrettyPrint(chars); + } + + /** + * Do not break lines, but still insert whitespace between values. + * + * @return A PrettyPrint instance for single-line mode + */ + public static PrettyPrint indentWithTabs() { + return new PrettyPrint(new char[] {'\t'}); + } + + @Override + protected JSONWriter createWriter(Writer writer) { + return new PrettyPrintWriter(writer, indentChars); + } + + private static class PrettyPrintWriter extends JSONWriter { + + private final char[] indentChars; + private int indent; + + private PrettyPrintWriter(Writer writer, char[] indentChars) { + super(writer); + this.indentChars = indentChars; + } + + @Override + protected void writeArrayOpen() throws IOException { + indent++; + writer.write('['); + writeNewLine(); + } + + @Override + protected void writeArrayClose() throws IOException { + indent--; + writeNewLine(); + writer.write(']'); + } + + @Override + protected void writeArraySeparator() throws IOException { + writer.write(','); + if (!writeNewLine()) { + writer.write(' '); + } + } + + @Override + protected void writeObjectOpen() throws IOException { + indent++; + writer.write('{'); + writeNewLine(); + } + + @Override + protected void writeObjectClose() throws IOException { + indent--; + writeNewLine(); + writer.write('}'); + } + + @Override + protected void writeMemberSeparator() throws IOException { + writer.write(':'); + writer.write(' '); + } + + @Override + protected void writeObjectSeparator() throws IOException { + writer.write(','); + if (!writeNewLine()) { + writer.write(' '); + } + } + + private boolean writeNewLine() throws IOException { + if (indentChars == null) { + return false; + } + writer.write('\n'); + for (int i = 0; i < indent; i++) { + writer.write(indentChars); + } + return true; + } + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/WriterConfig.java b/blade-kit/src/main/java/blade/kit/json/WriterConfig.java index 3cc828241..59869517b 100644 --- a/blade-kit/src/main/java/blade/kit/json/WriterConfig.java +++ b/blade-kit/src/main/java/blade/kit/json/WriterConfig.java @@ -1,50 +1,50 @@ -/******************************************************************************* - * Copyright (c) 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.Writer; - - -/** - * Controls the formatting of the JSON output. Use one of the available constants. - */ -public abstract class WriterConfig { - - /** - * Write JSON in its minimal form, without any additional whitespace. This is the default. - */ - public static WriterConfig MINIMAL = new WriterConfig() { - @Override - JsonWriter createWriter(Writer writer) { - return new JsonWriter(writer); - } - }; - - /** - * Write JSON in pretty-print, with each value on a separate line and an indentation of two - * spaces. - */ - public static WriterConfig PRETTY_PRINT = PrettyPrint.indentWithSpaces(2); - - abstract JsonWriter createWriter(Writer writer); - -} +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.Writer; + + +/** + * Controls the formatting of the JSON output. Use one of the available constants. + */ +public abstract class WriterConfig { + + /** + * Write JSON in its minimal form, without any additional whitespace. This is the default. + */ + public static WriterConfig MINIMAL = new WriterConfig() { + @Override + JSONWriter createWriter(Writer writer) { + return new JSONWriter(writer); + } + }; + + /** + * Write JSON in pretty-print, with each value on a separate line and an indentation of two + * spaces. + */ + public static WriterConfig PRETTY_PRINT = PrettyPrint.indentWithSpaces(2); + + abstract JSONWriter createWriter(Writer writer); + +} diff --git a/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java b/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java index 58a779b0c..a6bba01ee 100644 --- a/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java +++ b/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java @@ -1,99 +1,99 @@ -/******************************************************************************* - * Copyright (c) 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; - - -/** - * A lightweight writing buffer to reduce the amount of write operations to be performed on the - * underlying writer. This implementation is not thread-safe. It deliberately deviates from the - * contract of Writer. In particular, it does not flush or close the wrapped writer nor does it - * ensure that the wrapped writer is open. - */ -class WritingBuffer extends Writer { - - private final Writer writer; - private final char[] buffer; - private int fill = 0; - - WritingBuffer(Writer writer) { - this(writer, 16); - } - - WritingBuffer(Writer writer, int bufferSize) { - this.writer = writer; - buffer = new char[bufferSize]; - } - - @Override - public void write(int c) throws IOException { - if (fill > buffer.length - 1) { - flush(); - } - buffer[fill++] = (char)c; - } - - @Override - public void write(char[] cbuf, int off, int len) throws IOException { - if (fill > buffer.length - len) { - flush(); - if (len > buffer.length) { - writer.write(cbuf, off, len); - return; - } - } - System.arraycopy(cbuf, off, buffer, fill, len); - fill += len; - } - - @Override - public void write(String str, int off, int len) throws IOException { - if (fill > buffer.length - len) { - flush(); - if (len > buffer.length) { - writer.write(str, off, len); - return; - } - } - str.getChars(off, off + len, buffer, fill); - fill += len; - } - - /** - * Flushes the internal buffer but does not flush the wrapped writer. - */ - @Override - public void flush() throws IOException { - writer.write(buffer, 0, fill); - fill = 0; - } - - /** - * Does not close or flush the wrapped writer. - */ - @Override - public void close() throws IOException { - } - -} +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; + + +/** + * A lightweight writing buffer to reduce the amount of write operations to be performed on the + * underlying writer. This implementation is not thread-safe. It deliberately deviates from the + * contract of Writer. In particular, it does not flush or close the wrapped writer nor does it + * ensure that the wrapped writer is open. + */ +class WritingBuffer extends Writer { + + private final Writer writer; + private final char[] buffer; + private int fill = 0; + + WritingBuffer(Writer writer) { + this(writer, 16); + } + + WritingBuffer(Writer writer, int bufferSize) { + this.writer = writer; + buffer = new char[bufferSize]; + } + + @Override + public void write(int c) throws IOException { + if (fill > buffer.length - 1) { + flush(); + } + buffer[fill++] = (char)c; + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + if (fill > buffer.length - len) { + flush(); + if (len > buffer.length) { + writer.write(cbuf, off, len); + return; + } + } + System.arraycopy(cbuf, off, buffer, fill, len); + fill += len; + } + + @Override + public void write(String str, int off, int len) throws IOException { + if (fill > buffer.length - len) { + flush(); + if (len > buffer.length) { + writer.write(str, off, len); + return; + } + } + str.getChars(off, off + len, buffer, fill); + fill += len; + } + + /** + * Flushes the internal buffer but does not flush the wrapped writer. + */ + @Override + public void flush() throws IOException { + writer.write(buffer, 0, fill); + fill = 0; + } + + /** + * Does not close or flush the wrapped writer. + */ + @Override + public void close() throws IOException { + } + +} diff --git a/blade-kit/src/test/java/com/blade/kit/JSONTest.java b/blade-kit/src/test/java/com/blade/kit/JSONTest.java index b66e5fccc..464a8db5c 100644 --- a/blade-kit/src/test/java/com/blade/kit/JSONTest.java +++ b/blade-kit/src/test/java/com/blade/kit/JSONTest.java @@ -5,11 +5,10 @@ import java.util.List; import java.util.Map; +import blade.kit.json.JSONArray; import blade.kit.json.JSONKit; -import blade.kit.json.Json; -import blade.kit.json.JsonArray; -import blade.kit.json.JsonObject; -import blade.kit.json.JsonValue; +import blade.kit.json.JSONObject; +import blade.kit.json.JSONValue; public class JSONTest { @@ -33,15 +32,15 @@ public static void main(String[] args) { String string = JSONKit.toJSONString(list); System.out.println(string); - List list2 = Json.parse(json).asArray().values(); + List list2 = JSONKit.parse(json).asArray().values(); System.out.println(list2); - JsonObject obj1 = new JsonObject(); - obj1.add("name", "jack"); + JSONObject obj1 = new JSONObject(); + obj1.put("name", "jack"); System.out.println(obj1); - JsonArray obj2 = new JsonArray(); + JSONArray obj2 = new JSONArray(); obj2.add("123"); System.out.println(obj2); From 61aa56743a88fba63537626c17fe2153e5e9da2c Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 20:56:17 +0800 Subject: [PATCH 390/545] - --- .../src/main/java/com/blade/oauth2/OAuthRequest.java | 8 ++++---- .../blade/oauth2/base/request/OAuthTokenBaseRequest.java | 8 ++++---- .../oauth2/parameters/JSONBodyParametersApplier.java | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java index 5dae2c07d..a75a4c519 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java @@ -3,9 +3,6 @@ */ package com.blade.oauth2; -import blade.kit.StringKit; - -import com.blade.Aop; import com.blade.oauth2.base.request.OAuthBaseRequest; import com.blade.oauth2.base.validator.OAuthValidator; import com.blade.oauth2.exception.OAuthProblemException; @@ -15,6 +12,9 @@ import com.blade.oauth2.validator.ImplicitCodeValidator; import com.blade.web.http.Request; +import blade.kit.StringKit; +import blade.kit.reflect.ReflectKit; + /** * * @author BruceZCQ [zcq@zhucongqi.cn] @@ -41,7 +41,7 @@ protected OAuthValidator initValidator() throws OAuthProblemException { if (clazz == null) { throw OAuthKit.handleOAuthProblemException("Invalid response_type parameter value"); } - return Aop.createT(clazz); + return ReflectKit.newBean(clazz); } public String getResponseType() { diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java index bcecbbecc..f5f8b720b 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java @@ -4,15 +4,15 @@ package com.blade.oauth2.base.request; -import blade.kit.StringKit; - -import com.blade.Aop; import com.blade.oauth2.OAuth; import com.blade.oauth2.base.validator.OAuthValidator; import com.blade.oauth2.exception.OAuthProblemException; import com.blade.oauth2.kit.OAuthKit; import com.blade.web.http.Request; +import blade.kit.StringKit; +import blade.kit.reflect.ReflectKit; + /** * Abstract OAuth Token request class * @@ -38,7 +38,7 @@ protected OAuthValidator initValidator() throw OAuthKit .handleOAuthProblemException("Invalid grant_type parameter value"); } - return Aop.createT(clazz); + return ReflectKit.newBean(clazz); } public String getPassword() { diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java b/blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java index b7f038a34..ddfef8fb6 100644 --- a/blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java +++ b/blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java @@ -6,14 +6,14 @@ import java.util.Map; -import blade.kit.json.Json; - import com.blade.oauth2.message.OAuthMessage; +import blade.kit.json.JSONHelper; + public class JSONBodyParametersApplier { public OAuthMessage applyOAuthParameters(OAuthMessage message, Map params) { - String json = Json.parse(params).toString(); + String json = JSONHelper.mapAsJsonObject(params).toString(); message.setBody(json); return message; } From e6def43b249db87eb05524ebe8be1824ca3f4580 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 21:35:35 +0800 Subject: [PATCH 391/545] add http request cookie manage --- .../src/main/java/blade/kit/StringKit.java | 3 - .../src/main/java/blade/kit/http/Header.java | 10 + .../main/java/blade/kit/http/HttpRequest.java | 5374 +++++++++-------- .../main/java/blade/kit/http/TokenQueue.java | 394 ++ blade-oauth2/pom.xml | 2 +- pom.xml | 2 +- 6 files changed, 3120 insertions(+), 2665 deletions(-) create mode 100644 blade-kit/src/main/java/blade/kit/http/TokenQueue.java diff --git a/blade-kit/src/main/java/blade/kit/StringKit.java b/blade-kit/src/main/java/blade/kit/StringKit.java index 91ade75ae..12629c2d9 100644 --- a/blade-kit/src/main/java/blade/kit/StringKit.java +++ b/blade-kit/src/main/java/blade/kit/StringKit.java @@ -945,15 +945,12 @@ public static boolean isWhitespace(String str) { if (str == null) { return false; } - int length = str.length(); - for (int i = 0; i < length; i++) { if (!Character.isWhitespace(str.charAt(i))) { return false; } } - return true; } diff --git a/blade-kit/src/main/java/blade/kit/http/Header.java b/blade-kit/src/main/java/blade/kit/http/Header.java index 77c29dd89..3b8eba01f 100644 --- a/blade-kit/src/main/java/blade/kit/http/Header.java +++ b/blade-kit/src/main/java/blade/kit/http/Header.java @@ -64,6 +64,16 @@ public class Header { * 'Content-Type' header name */ public static final String HEADER_CONTENT_TYPE = "Content-Type"; + + /** + * 'Cookie' header name + */ + public static final String HEADER_COOKIE = "Cookie"; + + /** + * 'Set-Cookie' header name + */ + public static final String HEADER_SET_COOKIE = "Set-Cookie"; /** * 'Date' header name diff --git a/blade-kit/src/main/java/blade/kit/http/HttpRequest.java b/blade-kit/src/main/java/blade/kit/http/HttpRequest.java index 23872dd0b..407a79540 100644 --- a/blade-kit/src/main/java/blade/kit/http/HttpRequest.java +++ b/blade-kit/src/main/java/blade/kit/http/HttpRequest.java @@ -85,2676 +85,2730 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import blade.kit.Assert; import blade.kit.Base64; /** * Http请求类 * - * @author biezhi - * @since 1.0 + * @author biezhi + * @since 1.0 */ public class HttpRequest { - private static final String BOUNDARY = "00content0boundary00"; - - private static final String CONTENT_TYPE_MULTIPART = "multipart/form-data; boundary=" + BOUNDARY; - - private static final String CRLF = "\r\n"; - - private static final String[] EMPTY_STRINGS = new String[0]; - - private static SSLSocketFactory TRUSTED_FACTORY; - - private static HostnameVerifier TRUSTED_VERIFIER; - - private static ConnectionFactory CONNECTION_FACTORY = ConnectionFactory.DEFAULT; - - public static String getValidCharset(final String charset) { - if (charset != null && charset.length() > 0) - return charset; - else - return Header.CHARSET_UTF8; - } - - /** - * @return 返回SSL套接字工厂 - * @throws HttpRequestException - */ - private static SSLSocketFactory getTrustedFactory() - throws HttpRequestException { - if (TRUSTED_FACTORY == null) { - final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { - - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - - public void checkClientTrusted(X509Certificate[] chain, String authType) { - // Intentionally left blank - } - - public void checkServerTrusted(X509Certificate[] chain, String authType) { - // Intentionally left blank - } - } }; - try { - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, trustAllCerts, new SecureRandom()); - TRUSTED_FACTORY = context.getSocketFactory(); - } catch (GeneralSecurityException e) { - IOException ioException = new IOException( - "Security exception configuring SSL context"); - ioException.initCause(e); - throw new HttpRequestException(ioException); - } - } - - return TRUSTED_FACTORY; - } - - private static HostnameVerifier getTrustedVerifier() { - if (TRUSTED_VERIFIER == null) - TRUSTED_VERIFIER = new HostnameVerifier() { - - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - - return TRUSTED_VERIFIER; - } - - private static StringBuilder addPathSeparator(final String baseUrl, - final StringBuilder result) { - // Add trailing slash if the base URL doesn't have any path segments. - // - // The following test is checking for the last slash not being part of - // the protocol to host separator: '://'. - if (baseUrl.indexOf(':') + 2 == baseUrl.lastIndexOf('/')) - result.append('/'); - return result; - } - - private static StringBuilder addParamPrefix(final String baseUrl, - final StringBuilder result) { - // Add '?' if missing and add '&' if params already exist in base url - final int queryStart = baseUrl.indexOf('?'); - final int lastChar = result.length() - 1; - if (queryStart == -1) - result.append('?'); - else if (queryStart < lastChar && baseUrl.charAt(lastChar) != '&') - result.append('&'); - return result; - } - - private static StringBuilder addParam(final Object key, Object value, - final StringBuilder result) { - if (value != null && value.getClass().isArray()) - value = arrayToList(value); - - if (value instanceof Iterable) { - Iterator iterator = ((Iterable) value).iterator(); - while (iterator.hasNext()) { - result.append(key); - result.append("[]="); - Object element = iterator.next(); - if (element != null) - result.append(element); - if (iterator.hasNext()) - result.append("&"); - } - } else { - result.append(key); - result.append("="); - if (value != null) - result.append(value); - } - - return result; - } - - /** - * 设置一个ConnectionFactory,用于创建新的请求 - */ - public static void setConnectionFactory(final ConnectionFactory connectionFactory) { - if (connectionFactory == null) - CONNECTION_FACTORY = ConnectionFactory.DEFAULT; - else - CONNECTION_FACTORY = connectionFactory; - } - - /** - * 操作执行一个回调处理完成后和处理嵌套的异常 - * - * @param - */ - protected static abstract class Operation implements Callable { - - /** - * 执行操作 - * - * @return result - * @throws HttpRequestException - * @throws IOException - */ - protected abstract V run() throws HttpRequestException, IOException; - - /** - * 操作完成回调 - * - * @throws IOException - */ - protected abstract void done() throws IOException; - - public V call() throws HttpRequestException { - boolean thrown = false; - try { - return run(); - } catch (HttpRequestException e) { - thrown = true; - throw e; - } catch (IOException e) { - thrown = true; - throw new HttpRequestException(e); - } finally { - try { - done(); - } catch (IOException e) { - if (!thrown) - throw new HttpRequestException(e); - } - } - } - } - - /** - * 确保Closeable类关闭,使用适当的异常处理 - * - * @param - */ - protected static abstract class CloseOperation extends Operation { - - private final Closeable closeable; - - private final boolean ignoreCloseExceptions; - - /** - * 创建一个关闭操作 - * - * @param closeable - * @param ignoreCloseExceptions - */ - protected CloseOperation(final Closeable closeable, final boolean ignoreCloseExceptions) { - this.closeable = closeable; - this.ignoreCloseExceptions = ignoreCloseExceptions; - } - - @Override - protected void done() throws IOException { - if (closeable instanceof Flushable) - ((Flushable) closeable).flush(); - if (ignoreCloseExceptions) - try { - closeable.close(); - } catch (IOException e) { - // Ignored - } - else - closeable.close(); - } - } - - /** - * Class that and ensures a {@link Flushable} gets flushed with proper - * exception handling. - * - * @param - */ - protected static abstract class FlushOperation extends Operation { - - private final Flushable flushable; - - /** - * Create flush operation - * - * @param flushable - */ - protected FlushOperation(final Flushable flushable) { - this.flushable = flushable; - } - - @Override - protected void done() throws IOException { - flushable.flush(); - } - } - - - - /** - * 表示任何类型的数组的对象列表,让我们可以很容易地遍历 - * @param array of elements - * @return list with the same elements - */ - private static List arrayToList(final Object array) { - if (array instanceof Object[]) - return Arrays.asList((Object[]) array); - - List result = new ArrayList(); - // Arrays of the primitive types can't be cast to array of Object, so this: - if (array instanceof int[]) - for (int value : (int[]) array) result.add(value); - else if (array instanceof boolean[]) - for (boolean value : (boolean[]) array) result.add(value); - else if (array instanceof long[]) - for (long value : (long[]) array) result.add(value); - else if (array instanceof float[]) - for (float value : (float[]) array) result.add(value); - else if (array instanceof double[]) - for (double value : (double[]) array) result.add(value); - else if (array instanceof short[]) - for (short value : (short[]) array) result.add(value); - else if (array instanceof byte[]) - for (byte value : (byte[]) array) result.add(value); - else if (array instanceof char[]) - for (char value : (char[]) array) result.add(value); - return result; - } - - /** - * Encode the given URL as an ASCII {@link String} - *

- * This method ensures the path and query segments of the URL are properly - * encoded such as ' ' characters being encoded to '%20' or any UTF-8 - * characters that are non-ASCII. No encoding of URLs is done by default by - * the {@link HttpRequest} constructors and so if URL encoding is needed this - * method should be called before calling the {@link HttpRequest} constructor. - * - * @param url - * @return encoded URL - * @throws HttpRequestException - */ - public static String encode(final String url) throws HttpRequestException { - URL parsed; - try { - parsed = new URL(url.toString()); - } catch (IOException e) { - throw new HttpRequestException(e); - } - - String host = parsed.getHost(); - int port = parsed.getPort(); - if (port != -1) - host = host + ':' + Integer.toString(port); - - try { - String encoded = new URI(parsed.getProtocol(), host, parsed.getPath(), - parsed.getQuery(), null).toASCIIString(); - int paramsStart = encoded.indexOf('?'); - if (paramsStart > 0 && paramsStart + 1 < encoded.length()) - encoded = encoded.substring(0, paramsStart + 1) - + encoded.substring(paramsStart + 1).replace("+", "%2B"); - return encoded; - } catch (URISyntaxException e) { - IOException io = new IOException("Parsing URI failed"); - io.initCause(e); - throw new HttpRequestException(io); - } - } - - /** - * Append given map as query parameters to the base URL - *

- * Each map entry's key will be a parameter name and the value's - * {@link Object#toString()} will be the parameter value. - * - * @param url - * @param params - * @return URL with appended query params - */ - public static String append(final String url, final Map params) { - final String baseUrl = url.toString(); - if (params == null || params.isEmpty()) - return baseUrl; - - final StringBuilder result = new StringBuilder(baseUrl); - - addPathSeparator(baseUrl, result); - addParamPrefix(baseUrl, result); - - Entry entry; - Iterator iterator = params.entrySet().iterator(); - entry = (Entry) iterator.next(); - addParam(entry.getKey().toString(), entry.getValue(), result); - - while (iterator.hasNext()) { - result.append('&'); - entry = (Entry) iterator.next(); - addParam(entry.getKey().toString(), entry.getValue(), result); - } - - return result.toString(); - } - - /** - * Append given name/value pairs as query parameters to the base URL - *

- * The params argument is interpreted as a sequence of name/value pairs so the - * given number of params must be divisible by 2. - * - * @param url - * @param params - * name/value pairs - * @return URL with appended query params - */ - public static String append(final String url, final Object... params) { - final String baseUrl = url.toString(); - if (params == null || params.length == 0) - return baseUrl; - - if (params.length % 2 != 0) - throw new IllegalArgumentException( - "Must specify an even number of parameter names/values"); - - final StringBuilder result = new StringBuilder(baseUrl); - - addPathSeparator(baseUrl, result); - addParamPrefix(baseUrl, result); - - addParam(params[0], params[1], result); - - for (int i = 2; i < params.length; i += 2) { - result.append('&'); - addParam(params[i], params[i + 1], result); - } - - return result.toString(); - } - - /** - * Start a 'GET' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest get(final String url) - throws HttpRequestException { - return new HttpRequest(url, MethodType.GET); - } - - /** - * Start a 'GET' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest get(final URL url) throws HttpRequestException { - return new HttpRequest(url, MethodType.GET); - } - - /** - * Start a 'GET' request to the given URL along with the query params - * - * @param baseUrl - * @param params - * The query parameters to include as part of the baseUrl - * @param encode - * true to encode the full URL - * - * @see #append(CharSequence, Map) - * @see #encode(CharSequence) - * - * @return request - */ - public static HttpRequest get(final String baseUrl, - final Map params, final boolean encode) { - String url = append(baseUrl, params); - return get(encode ? encode(url) : url); - } - - /** - * Start a 'GET' request to the given URL along with the query params - * - * @param baseUrl - * @param encode - * true to encode the full URL - * @param params - * the name/value query parameter pairs to include as part of the - * baseUrl - * - * @see #append(CharSequence, Object...) - * @see #encode(CharSequence) - * - * @return request - */ - public static HttpRequest get(final String baseUrl, final boolean encode, final Object... params) { - String url = append(baseUrl, params); - return get(encode ? encode(url) : url); - } - - /** - * Start a 'POST' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest post(final String url) throws HttpRequestException { - return new HttpRequest(url, MethodType.POST); - } - - /** - * Start a 'POST' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest post(final URL url) throws HttpRequestException { - return new HttpRequest(url, MethodType.POST); - } - - /** - * Start a 'POST' request to the given URL along with the query params - * - * @param baseUrl - * @param params - * the query parameters to include as part of the baseUrl - * @param encode - * true to encode the full URL - * - * @see #append(String, Map) - * @see #encode(String) - * - * @return request - */ - public static HttpRequest post(final String baseUrl, - final Map params, final boolean encode) { - String url = append(baseUrl, params); - return post(encode ? encode(url) : url); - } - - /** - * Start a 'POST' request to the given URL along with the query params - * - * @param baseUrl - * @param encode - * true to encode the full URL - * @param params - * the name/value query parameter pairs to include as part of the - * baseUrl - * - * @see #append(String, Object...) - * @see #encode(String) - * - * @return request - */ - public static HttpRequest post(final String baseUrl, - final boolean encode, final Object... params) { - String url = append(baseUrl, params); - return post(encode ? encode(url) : url); - } - - /** - * Start a 'PUT' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest put(final String url) - throws HttpRequestException { - return new HttpRequest(url, MethodType.PUT); - } - - /** - * Start a 'PUT' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest put(final URL url) throws HttpRequestException { - return new HttpRequest(url, MethodType.PUT); - } - - /** - * Start a 'PUT' request to the given URL along with the query params - * - * @param baseUrl - * @param params - * the query parameters to include as part of the baseUrl - * @param encode - * true to encode the full URL - * - * @see #append(String, Map) - * @see #encode(String) - * - * @return request - */ - public static HttpRequest put(final String baseUrl, - final Map params, final boolean encode) { - String url = append(baseUrl, params); - return put(encode ? encode(url) : url); - } - - /** - * Start a 'PUT' request to the given URL along with the query params - * - * @param baseUrl - * @param encode - * true to encode the full URL - * @param params - * the name/value query parameter pairs to include as part of the - * baseUrl - * - * @see #append(String, Object...) - * @see #encode(String) - * - * @return request - */ - public static HttpRequest put(final String baseUrl, - final boolean encode, final Object... params) { - String url = append(baseUrl, params); - return put(encode ? encode(url) : url); - } - - /** - * Start a 'DELETE' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest delete(final String url) - throws HttpRequestException { - return new HttpRequest(url, MethodType.DELETE); - } - - /** - * Start a 'DELETE' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest delete(final URL url) throws HttpRequestException { - return new HttpRequest(url, MethodType.DELETE); - } - - /** - * Start a 'DELETE' request to the given URL along with the query params - * - * @param baseUrl - * @param params - * The query parameters to include as part of the baseUrl - * @param encode - * true to encode the full URL - * - * @see #append(String, Map) - * @see #encode(String) - * - * @return request - */ - public static HttpRequest delete(final String baseUrl, - final Map params, final boolean encode) { - String url = append(baseUrl, params); - return delete(encode ? encode(url) : url); - } - - /** - * Start a 'DELETE' request to the given URL along with the query params - * - * @param baseUrl - * @param encode - * true to encode the full URL - * @param params - * the name/value query parameter pairs to include as part of the - * baseUrl - * - * @see #append(String, Object...) - * @see #encode(String) - * - * @return request - */ - public static HttpRequest delete(final String baseUrl, - final boolean encode, final Object... params) { - String url = append(baseUrl, params); - return delete(encode ? encode(url) : url); - } - - /** - * Start a 'HEAD' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest head(final String url) - throws HttpRequestException { - return new HttpRequest(url, MethodType.HEAD); - } - - /** - * Start a 'HEAD' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest head(final URL url) throws HttpRequestException { - return new HttpRequest(url, MethodType.HEAD); - } - - /** - * Start a 'HEAD' request to the given URL along with the query params - * - * @param baseUrl - * @param params - * The query parameters to include as part of the baseUrl - * @param encode - * true to encode the full URL - * - * @see #append(String, Map) - * @see #encode(String) - * - * @return request - */ - public static HttpRequest head(final String baseUrl, - final Map params, final boolean encode) { - String url = append(baseUrl, params); - return head(encode ? encode(url) : url); - } - - /** - * Start a 'GET' request to the given URL along with the query params - * - * @param baseUrl - * @param encode - * true to encode the full URL - * @param params - * the name/value query parameter pairs to include as part of the - * baseUrl - * - * @see #append(String, Object...) - * @see #encode(String) - * - * @return request - */ - public static HttpRequest head(final String baseUrl, - final boolean encode, final Object... params) { - String url = append(baseUrl, params); - return head(encode ? encode(url) : url); - } - - /** - * Start an 'OPTIONS' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest options(final String url) - throws HttpRequestException { - return new HttpRequest(url, MethodType.OPTIONS); - } - - /** - * Start an 'OPTIONS' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest options(final URL url) throws HttpRequestException { - return new HttpRequest(url, MethodType.OPTIONS); - } - - /** - * Start a 'TRACE' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest trace(final String url) - throws HttpRequestException { - return new HttpRequest(url, MethodType.TRACE); - } - - /** - * Start a 'TRACE' request to the given URL - * - * @param url - * @return request - * @throws HttpRequestException - */ - public static HttpRequest trace(final URL url) throws HttpRequestException { - return new HttpRequest(url, MethodType.TRACE); - } - - /** - * Set the 'http.keepAlive' property to the given value. - *

- * This setting will apply to all requests. - * - * @param keepAlive - */ - public static void keepAlive(final boolean keepAlive) { - setProperty("http.keepAlive", Boolean.toString(keepAlive)); - } - - /** - * Set the 'http.maxConnections' property to the given value. - *

- * This setting will apply to all requests. - * - * @param maxConnections - */ - public static void maxConnections(final int maxConnections) { - setProperty("http.maxConnections", Integer.toString(maxConnections)); - } - - /** - * Set the 'http.proxyHost' and 'https.proxyHost' properties to the given host - * value. - *

- * This setting will apply to all requests. - * - * @param host - */ - public static void proxyHost(final String host) { - setProperty("http.proxyHost", host); - setProperty("https.proxyHost", host); - } - - /** - * Set the 'http.proxyPort' and 'https.proxyPort' properties to the given port - * number. - *

- * This setting will apply to all requests. - * - * @param port - */ - public static void proxyPort(final int port) { - final String portValue = Integer.toString(port); - setProperty("http.proxyPort", portValue); - setProperty("https.proxyPort", portValue); - } - - /** - * Set the 'http.nonProxyHosts' property to the given host values. - *

- * Hosts will be separated by a '|' character. - *

- * This setting will apply to all requests. - * - * @param hosts - */ - public static void nonProxyHosts(final String... hosts) { - if (hosts != null && hosts.length > 0) { - StringBuilder separated = new StringBuilder(); - int last = hosts.length - 1; - for (int i = 0; i < last; i++) - separated.append(hosts[i]).append('|'); - separated.append(hosts[last]); - setProperty("http.nonProxyHosts", separated.toString()); - } else - setProperty("http.nonProxyHosts", null); - } - - /** - * Set property to given value. - *

- * Specifying a null value will cause the property to be cleared - * - * @param name - * @param value - * @return previous value - */ - private static String setProperty(final String name, final String value) { - final PrivilegedAction action; - if (value != null) - action = new PrivilegedAction() { - - public String run() { - return System.setProperty(name, value); - } - }; - else - action = new PrivilegedAction() { - - public String run() { - return System.clearProperty(name); - } - }; - return AccessController.doPrivileged(action); - } - - private HttpURLConnection connection = null; - - private final URL url; - - private final String requestMethod; - - private RequestOutputStream output; - - private boolean multipart; - - private boolean form; - - private boolean ignoreCloseExceptions = true; - - private boolean uncompress = false; - - private int bufferSize = 8192; - - private long totalSize = -1; - - private long totalWritten = 0; - - private String httpProxyHost; - - private int httpProxyPort; - - private UploadProgress progress = UploadProgress.DEFAULT; - - /** - * Create HTTP connection wrapper - * - * @param url Remote resource URL. - * @param method HTTP request method (e.g., "GET", "POST"). - * @throws HttpRequestException - */ - public HttpRequest(final String url, final String method) - throws HttpRequestException { - try { - this.url = new URL(url.toString()); - } catch (MalformedURLException e) { - throw new HttpRequestException(e); - } - this.requestMethod = method; - } - - /** - * Create HTTP connection wrapper - * - * @param url Remote resource URL. - * @param method HTTP request method (e.g., "GET", "POST"). - * @throws HttpRequestException - */ - public HttpRequest(final URL url, final String method) - throws HttpRequestException { - this.url = url; - this.requestMethod = method; - } - - private Proxy createProxy() { - return new Proxy(HTTP, new InetSocketAddress(httpProxyHost, httpProxyPort)); - } - - private HttpURLConnection createConnection() { - try { - final HttpURLConnection connection; - if (httpProxyHost != null) - connection = CONNECTION_FACTORY.create(url, createProxy()); - else - connection = CONNECTION_FACTORY.create(url); - connection.setRequestMethod(requestMethod); - return connection; - } catch (IOException e) { - throw new HttpRequestException(e); - } - } - - @Override - public String toString() { - return method() + ' ' + url(); - } - - /** - * Get underlying connection - * - * @return connection - */ - public HttpURLConnection getConnection() { - if (connection == null) - connection = createConnection(); - return connection; - } - - /** - * Set whether or not to ignore exceptions that occur from calling - * {@link Closeable#close()} - *

- * The default value of this setting is true - * - * @param ignore - * @return this request - */ - public HttpRequest ignoreCloseExceptions(final boolean ignore) { - ignoreCloseExceptions = ignore; - return this; - } - - /** - * Get whether or not exceptions thrown by {@link Closeable#close()} are - * ignored - * - * @return true if ignoring, false if throwing - */ - public boolean ignoreCloseExceptions() { - return ignoreCloseExceptions; - } - - /** - * Get the status code of the response - * - * @return the response code - * @throws HttpRequestException - */ - public int code() throws HttpRequestException { - try { - closeOutput(); - return getConnection().getResponseCode(); - } catch (IOException e) { - throw new HttpRequestException(e); - } - } - - /** - * Set the value of the given {@link AtomicInteger} to the status code of the - * response - * - * @param output - * @return this request - * @throws HttpRequestException - */ - public HttpRequest code(final AtomicInteger output) - throws HttpRequestException { - output.set(code()); - return this; - } - - /** - * Is the response code a 200 OK? - * - * @return true if 200, false otherwise - * @throws HttpRequestException - */ - public boolean ok() throws HttpRequestException { - return HTTP_OK == code(); - } - - /** - * Is the response code a 201 Created? - * - * @return true if 201, false otherwise - * @throws HttpRequestException - */ - public boolean created() throws HttpRequestException { - return HTTP_CREATED == code(); - } - - /** - * Is the response code a 204 No Content? - * - * @return true if 204, false otherwise - * @throws HttpRequestException - */ - public boolean noContent() throws HttpRequestException { - return HTTP_NO_CONTENT == code(); - } - - /** - * Is the response code a 500 Internal Server Error? - * - * @return true if 500, false otherwise - * @throws HttpRequestException - */ - public boolean serverError() throws HttpRequestException { - return HTTP_INTERNAL_ERROR == code(); - } - - /** - * Is the response code a 400 Bad Request? - * - * @return true if 400, false otherwise - * @throws HttpRequestException - */ - public boolean badRequest() throws HttpRequestException { - return HTTP_BAD_REQUEST == code(); - } - - /** - * Is the response code a 404 Not Found? - * - * @return true if 404, false otherwise - * @throws HttpRequestException - */ - public boolean notFound() throws HttpRequestException { - return HTTP_NOT_FOUND == code(); - } - - /** - * Is the response code a 304 Not Modified? - * - * @return true if 304, false otherwise - * @throws HttpRequestException - */ - public boolean notModified() throws HttpRequestException { - return HTTP_NOT_MODIFIED == code(); - } - - /** - * Get status message of the response - * - * @return message - * @throws HttpRequestException - */ - public String message() throws HttpRequestException { - try { - closeOutput(); - return getConnection().getResponseMessage(); - } catch (IOException e) { - throw new HttpRequestException(e); - } - } - - /** - * Disconnect the connection - * - * @return this request - */ - public HttpRequest disconnect() { - getConnection().disconnect(); - return this; - } - - /** - * Set chunked streaming mode to the given size - * - * @param size - * @return this request - */ - public HttpRequest chunk(final int size) { - getConnection().setChunkedStreamingMode(size); - return this; - } - - /** - * Set the size used when buffering and copying between streams - *

- * This size is also used for send and receive buffers created for both char - * and byte arrays - *

- * The default buffer size is 8,192 bytes - * - * @param size - * @return this request - */ - public HttpRequest bufferSize(final int size) { - if (size < 1) - throw new IllegalArgumentException("Size must be greater than zero"); - bufferSize = size; - return this; - } - - /** - * Get the configured buffer size - *

- * The default buffer size is 8,192 bytes - * - * @return buffer size - */ - public int bufferSize() { - return bufferSize; - } - - /** - * Set whether or not the response body should be automatically uncompressed - * when read from. - *

- * This will only affect requests that have the 'Content-Encoding' response - * header set to 'gzip'. - *

- * This causes all receive methods to use a {@link GZIPInputStream} when - * applicable so that higher level streams and readers can read the data - * uncompressed. - *

- * Setting this option does not cause any request headers to be set - * automatically so {@link #acceptGzipEncoding()} should be used in - * conjunction with this setting to tell the server to gzip the response. - * - * @param uncompress - * @return this request - */ - public HttpRequest uncompress(final boolean uncompress) { - this.uncompress = uncompress; - return this; - } - - /** - * Create byte array output stream - * - * @return stream - */ - protected ByteArrayOutputStream byteStream() { - final int size = contentLength(); - if (size > 0) - return new ByteArrayOutputStream(size); - else - return new ByteArrayOutputStream(); - } - - /** - * Get response as {@link String} in given character set - *

- * This will fall back to using the UTF-8 character set if the given charset - * is null - * - * @param charset - * @return string - * @throws HttpRequestException - */ - public String body(final String charset) throws HttpRequestException { - final ByteArrayOutputStream output = byteStream(); - try { - copy(buffer(), output); - return output.toString(getValidCharset(charset)); - } catch (IOException e) { - throw new HttpRequestException(e); - } - } - - /** - * Get response as {@link String} using character set returned from - * {@link #charset()} - * - * @return string - * @throws HttpRequestException - */ - public String body() throws HttpRequestException { - return body(charset()); - } - - /** - * Get the response body as a {@link String} and set it as the value of the - * given reference. - * - * @param output - * @return this request - * @throws HttpRequestException - */ - public HttpRequest body(final AtomicReference output) throws HttpRequestException { - output.set(body()); - return this; - } - - /** - * Get the response body as a {@link String} and set it as the value of the - * given reference. - * - * @param output - * @param charset - * @return this request - * @throws HttpRequestException - */ - public HttpRequest body(final AtomicReference output, final String charset) throws HttpRequestException { - output.set(body(charset)); - return this; - } - - - /** - * Is the response body empty? - * - * @return true if the Content-Length response header is 0, false otherwise - * @throws HttpRequestException - */ - public boolean isBodyEmpty() throws HttpRequestException { - return contentLength() == 0; - } - - /** - * Get response as byte array - * - * @return byte array - * @throws HttpRequestException - */ - public byte[] bytes() throws HttpRequestException { - final ByteArrayOutputStream output = byteStream(); - try { - copy(buffer(), output); - } catch (IOException e) { - throw new HttpRequestException(e); - } - return output.toByteArray(); - } - - /** - * Get response in a buffered stream - * - * @see #bufferSize(int) - * @return stream - * @throws HttpRequestException - */ - public BufferedInputStream buffer() throws HttpRequestException { - return new BufferedInputStream(stream(), bufferSize); - } - - /** - * Get stream to response body - * - * @return stream - * @throws HttpRequestException - */ - public InputStream stream() throws HttpRequestException { - InputStream stream; - if (code() < HTTP_BAD_REQUEST) - try { - stream = getConnection().getInputStream(); - } catch (IOException e) { - throw new HttpRequestException(e); - } - else { - stream = getConnection().getErrorStream(); - if (stream == null) - try { - stream = getConnection().getInputStream(); - } catch (IOException e) { - if (contentLength() > 0) - throw new HttpRequestException(e); - else - stream = new ByteArrayInputStream(new byte[0]); - } - } - - if (!uncompress || !Header.ENCODING_GZIP.equals(contentEncoding())) - return stream; - else - try { - return new GZIPInputStream(stream); - } catch (IOException e) { - throw new HttpRequestException(e); - } - } - - /** - * Get reader to response body using given character set. - *

- * This will fall back to using the UTF-8 character set if the given charset - * is null - * - * @param charset - * @return reader - * @throws HttpRequestException - */ - public InputStreamReader reader(final String charset) - throws HttpRequestException { - try { - return new InputStreamReader(stream(), getValidCharset(charset)); - } catch (UnsupportedEncodingException e) { - throw new HttpRequestException(e); - } - } - - /** - * Get reader to response body using the character set returned from - * {@link #charset()} - * - * @return reader - * @throws HttpRequestException - */ - public InputStreamReader reader() throws HttpRequestException { - return reader(charset()); - } - - /** - * Get buffered reader to response body using the given character set r and - * the configured buffer size - * - * - * @see #bufferSize(int) - * @param charset - * @return reader - * @throws HttpRequestException - */ - public BufferedReader bufferedReader(final String charset) - throws HttpRequestException { - return new BufferedReader(reader(charset), bufferSize); - } - - /** - * Get buffered reader to response body using the character set returned from - * {@link #charset()} and the configured buffer size - * - * @see #bufferSize(int) - * @return reader - * @throws HttpRequestException - */ - public BufferedReader bufferedReader() throws HttpRequestException { - return bufferedReader(charset()); - } - - /** - * Stream response body to file - * - * @param file - * @return this request - * @throws HttpRequestException - */ - public HttpRequest receive(final File file) throws HttpRequestException { - final OutputStream output; - try { - output = new BufferedOutputStream(new FileOutputStream(file), bufferSize); - } catch (FileNotFoundException e) { - throw new HttpRequestException(e); - } - return new CloseOperation(output, ignoreCloseExceptions) { - - @Override - protected HttpRequest run() throws HttpRequestException, IOException { - return receive(output); - } - }.call(); - } - - /** - * Stream response to given output stream - * - * @param output - * @return this request - * @throws HttpRequestException - */ - public HttpRequest receive(final OutputStream output) - throws HttpRequestException { - try { - return copy(buffer(), output); - } catch (IOException e) { - throw new HttpRequestException(e); - } - } - - /** - * Stream response to given print stream - * - * @param output - * @return this request - * @throws HttpRequestException - */ - public HttpRequest receive(final PrintStream output) - throws HttpRequestException { - return receive((OutputStream) output); - } - - /** - * Receive response into the given appendable - * - * @param appendable - * @return this request - * @throws HttpRequestException - */ - public HttpRequest receive(final Appendable appendable) - throws HttpRequestException { - final BufferedReader reader = bufferedReader(); - return new CloseOperation(reader, ignoreCloseExceptions) { - - @Override - public HttpRequest run() throws IOException { - final CharBuffer buffer = CharBuffer.allocate(bufferSize); - int read; - while ((read = reader.read(buffer)) != -1) { - buffer.rewind(); - appendable.append(buffer, 0, read); - buffer.rewind(); - } - return HttpRequest.this; - } - }.call(); - } - - /** - * Receive response into the given writer - * - * @param writer - * @return this request - * @throws HttpRequestException - */ - public HttpRequest receive(final Writer writer) throws HttpRequestException { - final BufferedReader reader = bufferedReader(); - return new CloseOperation(reader, ignoreCloseExceptions) { - - @Override - public HttpRequest run() throws IOException { - return copy(reader, writer); - } - }.call(); - } - - /** - * Set read timeout on connection to given value - * - * @param timeout - * @return this request - */ - public HttpRequest readTimeout(final int timeout) { - getConnection().setReadTimeout(timeout); - return this; - } - - /** - * Set connect timeout on connection to given value - * - * @param timeout - * @return this request - */ - public HttpRequest connectTimeout(final int timeout) { - getConnection().setConnectTimeout(timeout); - return this; - } - - /** - * Set header name to given value - * - * @param name - * @param value - * @return this request - */ - public HttpRequest header(final String name, final String value) { - getConnection().setRequestProperty(name, value); - return this; - } - - /** - * Set header name to given value - * - * @param name - * @param value - * @return this request - */ - public HttpRequest header(final String name, final Number value) { - return header(name, value != null ? value.toString() : null); - } - - /** - * Set all headers found in given map where the keys are the header names and - * the values are the header values - * - * @param headers - * @return this request - */ - public HttpRequest headers(final Map headers) { - if (!headers.isEmpty()) - for (Entry header : headers.entrySet()) - header(header); - return this; - } - - /** - * Set header to have given entry's key as the name and value as the value - * - * @param header - * @return this request - */ - public HttpRequest header(final Entry header) { - return header(header.getKey(), header.getValue()); - } - - /** - * Get a response header - * - * @param name - * @return response header - * @throws HttpRequestException - */ - public String header(final String name) throws HttpRequestException { - closeOutputQuietly(); - return getConnection().getHeaderField(name); - } - - /** - * Get all the response headers - * - * @return map of response header names to their value(s) - * @throws HttpRequestException - */ - public Map> headers() throws HttpRequestException { - closeOutputQuietly(); - return getConnection().getHeaderFields(); - } - - /** - * Get a date header from the response falling back to returning -1 if the - * header is missing or parsing fails - * - * @param name - * @return date, -1 on failures - * @throws HttpRequestException - */ - public long dateHeader(final String name) throws HttpRequestException { - return dateHeader(name, -1L); - } - - /** - * Get a date header from the response falling back to returning the given - * default value if the header is missing or parsing fails - * - * @param name - * @param defaultValue - * @return date, default value on failures - * @throws HttpRequestException - */ - public long dateHeader(final String name, final long defaultValue) - throws HttpRequestException { - closeOutputQuietly(); - return getConnection().getHeaderFieldDate(name, defaultValue); - } - - /** - * Get an integer header from the response falling back to returning -1 if the - * header is missing or parsing fails - * - * @param name - * @return header value as an integer, -1 when missing or parsing fails - * @throws HttpRequestException - */ - public int intHeader(final String name) throws HttpRequestException { - return intHeader(name, -1); - } - - /** - * Get an integer header value from the response falling back to the given - * default value if the header is missing or if parsing fails - * - * @param name - * @param defaultValue - * @return header value as an integer, default value when missing or parsing - * fails - * @throws HttpRequestException - */ - public int intHeader(final String name, final int defaultValue) - throws HttpRequestException { - closeOutputQuietly(); - return getConnection().getHeaderFieldInt(name, defaultValue); - } - - /** - * Get all values of the given header from the response - * - * @param name - * @return non-null but possibly empty array of {@link String} header values - */ - public String[] headers(final String name) { - final Map> headers = headers(); - if (headers == null || headers.isEmpty()) - return EMPTY_STRINGS; - - final List values = headers.get(name); - if (values != null && !values.isEmpty()) - return values.toArray(new String[values.size()]); - else - return EMPTY_STRINGS; - } - - /** - * Get parameter with given name from header value in response - * - * @param headerName - * @param paramName - * @return parameter value or null if missing - */ - public String parameter(final String headerName, final String paramName) { - return getParam(header(headerName), paramName); - } - - /** - * Get all parameters from header value in response - *

- * This will be all key=value pairs after the first ';' that are separated by - * a ';' - * - * @param headerName - * @return non-null but possibly empty map of parameter headers - */ - public Map parameters(final String headerName) { - return getParams(header(headerName)); - } - - /** - * Get parameter values from header value - * - * @param header - * @return parameter value or null if none - */ - protected Map getParams(final String header) { - if (header == null || header.length() == 0) - return Collections.emptyMap(); - - final int headerLength = header.length(); - int start = header.indexOf(';') + 1; - if (start == 0 || start == headerLength) - return Collections.emptyMap(); - - int end = header.indexOf(';', start); - if (end == -1) - end = headerLength; - - Map params = new LinkedHashMap(); - while (start < end) { - int nameEnd = header.indexOf('=', start); - if (nameEnd != -1 && nameEnd < end) { - String name = header.substring(start, nameEnd).trim(); - if (name.length() > 0) { - String value = header.substring(nameEnd + 1, end).trim(); - int length = value.length(); - if (length != 0) - if (length > 2 && '"' == value.charAt(0) - && '"' == value.charAt(length - 1)) - params.put(name, value.substring(1, length - 1)); + private static final String BOUNDARY = "00content0boundary00"; + + private static final String CONTENT_TYPE_MULTIPART = "multipart/form-data; boundary=" + BOUNDARY; + + private static final String CRLF = "\r\n"; + + private static final String[] EMPTY_STRINGS = new String[0]; + + private static SSLSocketFactory TRUSTED_FACTORY; + + private static HostnameVerifier TRUSTED_VERIFIER; + + private static ConnectionFactory CONNECTION_FACTORY = ConnectionFactory.DEFAULT; + + public static String getValidCharset(final String charset) { + if (charset != null && charset.length() > 0) + return charset; + else + return Header.CHARSET_UTF8; + } + + /** + * @return 返回SSL套接字工厂 + * @throws HttpRequestException + */ + private static SSLSocketFactory getTrustedFactory() throws HttpRequestException { + if (TRUSTED_FACTORY == null) { + final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) { + // Intentionally left blank + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) { + // Intentionally left blank + } + } }; + try { + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, trustAllCerts, new SecureRandom()); + TRUSTED_FACTORY = context.getSocketFactory(); + } catch (GeneralSecurityException e) { + IOException ioException = new IOException("Security exception configuring SSL context"); + ioException.initCause(e); + throw new HttpRequestException(ioException); + } + } + + return TRUSTED_FACTORY; + } + + private static HostnameVerifier getTrustedVerifier() { + if (TRUSTED_VERIFIER == null) + TRUSTED_VERIFIER = new HostnameVerifier() { + + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + return TRUSTED_VERIFIER; + } + + private static StringBuilder addPathSeparator(final String baseUrl, final StringBuilder result) { + // Add trailing slash if the base URL doesn't have any path segments. + // + // The following test is checking for the last slash not being part of + // the protocol to host separator: '://'. + if (baseUrl.indexOf(':') + 2 == baseUrl.lastIndexOf('/')) + result.append('/'); + return result; + } + + private static StringBuilder addParamPrefix(final String baseUrl, final StringBuilder result) { + // Add '?' if missing and add '&' if params already exist in base url + final int queryStart = baseUrl.indexOf('?'); + final int lastChar = result.length() - 1; + if (queryStart == -1) + result.append('?'); + else if (queryStart < lastChar && baseUrl.charAt(lastChar) != '&') + result.append('&'); + return result; + } + + private static StringBuilder addParam(final Object key, Object value, final StringBuilder result) { + if (value != null && value.getClass().isArray()) + value = arrayToList(value); + + if (value instanceof Iterable) { + Iterator iterator = ((Iterable) value).iterator(); + while (iterator.hasNext()) { + result.append(key); + result.append("[]="); + Object element = iterator.next(); + if (element != null) + result.append(element); + if (iterator.hasNext()) + result.append("&"); + } + } else { + result.append(key); + result.append("="); + if (value != null) + result.append(value); + } + + return result; + } + + /** + * 设置一个ConnectionFactory,用于创建新的请求 + */ + public static void setConnectionFactory(final ConnectionFactory connectionFactory) { + if (connectionFactory == null) + CONNECTION_FACTORY = ConnectionFactory.DEFAULT; + else + CONNECTION_FACTORY = connectionFactory; + } + + /** + * 操作执行一个回调处理完成后和处理嵌套的异常 + * + * @param + */ + protected static abstract class Operation implements Callable { + + /** + * 执行操作 + * + * @return result + * @throws HttpRequestException + * @throws IOException + */ + protected abstract V run() throws HttpRequestException, IOException; + + /** + * 操作完成回调 + * + * @throws IOException + */ + protected abstract void done() throws IOException; + + public V call() throws HttpRequestException { + boolean thrown = false; + try { + return run(); + } catch (HttpRequestException e) { + thrown = true; + throw e; + } catch (IOException e) { + thrown = true; + throw new HttpRequestException(e); + } finally { + try { + done(); + } catch (IOException e) { + if (!thrown) + throw new HttpRequestException(e); + } + } + } + } + + /** + * 确保Closeable类关闭,使用适当的异常处理 + * + * @param + */ + protected static abstract class CloseOperation extends Operation { + + private final Closeable closeable; + + private final boolean ignoreCloseExceptions; + + /** + * 创建一个关闭操作 + * + * @param closeable + * @param ignoreCloseExceptions + */ + protected CloseOperation(final Closeable closeable, final boolean ignoreCloseExceptions) { + this.closeable = closeable; + this.ignoreCloseExceptions = ignoreCloseExceptions; + } + + @Override + protected void done() throws IOException { + if (closeable instanceof Flushable) + ((Flushable) closeable).flush(); + if (ignoreCloseExceptions) + try { + closeable.close(); + } catch (IOException e) { + // Ignored + } + else + closeable.close(); + } + } + + /** + * Class that and ensures a {@link Flushable} gets flushed with proper + * exception handling. + * + * @param + */ + protected static abstract class FlushOperation extends Operation { + + private final Flushable flushable; + + /** + * Create flush operation + * + * @param flushable + */ + protected FlushOperation(final Flushable flushable) { + this.flushable = flushable; + } + + @Override + protected void done() throws IOException { + flushable.flush(); + } + } + + /** + * 表示任何类型的数组的对象列表,让我们可以很容易地遍历 + * + * @param array + * of elements + * @return list with the same elements + */ + private static List arrayToList(final Object array) { + if (array instanceof Object[]) + return Arrays.asList((Object[]) array); + + List result = new ArrayList(); + // Arrays of the primitive types can't be cast to array of Object, so + // this: + if (array instanceof int[]) + for (int value : (int[]) array) + result.add(value); + else if (array instanceof boolean[]) + for (boolean value : (boolean[]) array) + result.add(value); + else if (array instanceof long[]) + for (long value : (long[]) array) + result.add(value); + else if (array instanceof float[]) + for (float value : (float[]) array) + result.add(value); + else if (array instanceof double[]) + for (double value : (double[]) array) + result.add(value); + else if (array instanceof short[]) + for (short value : (short[]) array) + result.add(value); + else if (array instanceof byte[]) + for (byte value : (byte[]) array) + result.add(value); + else if (array instanceof char[]) + for (char value : (char[]) array) + result.add(value); + return result; + } + + /** + * Encode the given URL as an ASCII {@link String} + *

+ * This method ensures the path and query segments of the URL are properly + * encoded such as ' ' characters being encoded to '%20' or any UTF-8 + * characters that are non-ASCII. No encoding of URLs is done by default by + * the {@link HttpRequest} constructors and so if URL encoding is needed + * this method should be called before calling the {@link HttpRequest} + * constructor. + * + * @param url + * @return encoded URL + * @throws HttpRequestException + */ + public static String encode(final String url) throws HttpRequestException { + URL parsed; + try { + parsed = new URL(url.toString()); + } catch (IOException e) { + throw new HttpRequestException(e); + } + + String host = parsed.getHost(); + int port = parsed.getPort(); + if (port != -1) + host = host + ':' + Integer.toString(port); + + try { + String encoded = new URI(parsed.getProtocol(), host, parsed.getPath(), parsed.getQuery(), null) + .toASCIIString(); + int paramsStart = encoded.indexOf('?'); + if (paramsStart > 0 && paramsStart + 1 < encoded.length()) + encoded = encoded.substring(0, paramsStart + 1) + + encoded.substring(paramsStart + 1).replace("+", "%2B"); + return encoded; + } catch (URISyntaxException e) { + IOException io = new IOException("Parsing URI failed"); + io.initCause(e); + throw new HttpRequestException(io); + } + } + + /** + * Append given map as query parameters to the base URL + *

+ * Each map entry's key will be a parameter name and the value's + * {@link Object#toString()} will be the parameter value. + * + * @param url + * @param params + * @return URL with appended query params + */ + public static String append(final String url, final Map params) { + final String baseUrl = url.toString(); + if (params == null || params.isEmpty()) + return baseUrl; + + final StringBuilder result = new StringBuilder(baseUrl); + + addPathSeparator(baseUrl, result); + addParamPrefix(baseUrl, result); + + Entry entry; + Iterator iterator = params.entrySet().iterator(); + entry = (Entry) iterator.next(); + addParam(entry.getKey().toString(), entry.getValue(), result); + + while (iterator.hasNext()) { + result.append('&'); + entry = (Entry) iterator.next(); + addParam(entry.getKey().toString(), entry.getValue(), result); + } + + return result.toString(); + } + + /** + * Append given name/value pairs as query parameters to the base URL + *

+ * The params argument is interpreted as a sequence of name/value pairs so + * the given number of params must be divisible by 2. + * + * @param url + * @param params + * name/value pairs + * @return URL with appended query params + */ + public static String append(final String url, final Object... params) { + final String baseUrl = url.toString(); + if (params == null || params.length == 0) + return baseUrl; + + if (params.length % 2 != 0) + throw new IllegalArgumentException("Must specify an even number of parameter names/values"); + + final StringBuilder result = new StringBuilder(baseUrl); + + addPathSeparator(baseUrl, result); + addParamPrefix(baseUrl, result); + + addParam(params[0], params[1], result); + + for (int i = 2; i < params.length; i += 2) { + result.append('&'); + addParam(params[i], params[i + 1], result); + } + + return result.toString(); + } + + /** + * Start a 'GET' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest get(final String url) throws HttpRequestException { + return new HttpRequest(url, MethodType.GET); + } + + /** + * Start a 'GET' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest get(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.GET); + } + + /** + * Start a 'GET' request to the given URL along with the query params + * + * @param baseUrl + * @param params + * The query parameters to include as part of the baseUrl + * @param encode + * true to encode the full URL + * + * @see #append(CharSequence, Map) + * @see #encode(CharSequence) + * + * @return request + */ + public static HttpRequest get(final String baseUrl, final Map params, final boolean encode) { + String url = append(baseUrl, params); + return get(encode ? encode(url) : url); + } + + /** + * Start a 'GET' request to the given URL along with the query params + * + * @param baseUrl + * @param encode + * true to encode the full URL + * @param params + * the name/value query parameter pairs to include as part of the + * baseUrl + * + * @see #append(CharSequence, Object...) + * @see #encode(CharSequence) + * + * @return request + */ + public static HttpRequest get(final String baseUrl, final boolean encode, final Object... params) { + String url = append(baseUrl, params); + return get(encode ? encode(url) : url); + } + + /** + * Start a 'POST' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest post(final String url) throws HttpRequestException { + return new HttpRequest(url, MethodType.POST); + } + + /** + * Start a 'POST' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest post(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.POST); + } + + /** + * Start a 'POST' request to the given URL along with the query params + * + * @param baseUrl + * @param params + * the query parameters to include as part of the baseUrl + * @param encode + * true to encode the full URL + * + * @see #append(String, Map) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest post(final String baseUrl, final Map params, final boolean encode) { + String url = append(baseUrl, params); + return post(encode ? encode(url) : url); + } + + /** + * Start a 'POST' request to the given URL along with the query params + * + * @param baseUrl + * @param encode + * true to encode the full URL + * @param params + * the name/value query parameter pairs to include as part of the + * baseUrl + * + * @see #append(String, Object...) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest post(final String baseUrl, final boolean encode, final Object... params) { + String url = append(baseUrl, params); + return post(encode ? encode(url) : url); + } + + /** + * Start a 'PUT' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest put(final String url) throws HttpRequestException { + return new HttpRequest(url, MethodType.PUT); + } + + /** + * Start a 'PUT' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest put(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.PUT); + } + + /** + * Start a 'PUT' request to the given URL along with the query params + * + * @param baseUrl + * @param params + * the query parameters to include as part of the baseUrl + * @param encode + * true to encode the full URL + * + * @see #append(String, Map) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest put(final String baseUrl, final Map params, final boolean encode) { + String url = append(baseUrl, params); + return put(encode ? encode(url) : url); + } + + /** + * Start a 'PUT' request to the given URL along with the query params + * + * @param baseUrl + * @param encode + * true to encode the full URL + * @param params + * the name/value query parameter pairs to include as part of the + * baseUrl + * + * @see #append(String, Object...) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest put(final String baseUrl, final boolean encode, final Object... params) { + String url = append(baseUrl, params); + return put(encode ? encode(url) : url); + } + + /** + * Start a 'DELETE' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest delete(final String url) throws HttpRequestException { + return new HttpRequest(url, MethodType.DELETE); + } + + /** + * Start a 'DELETE' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest delete(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.DELETE); + } + + /** + * Start a 'DELETE' request to the given URL along with the query params + * + * @param baseUrl + * @param params + * The query parameters to include as part of the baseUrl + * @param encode + * true to encode the full URL + * + * @see #append(String, Map) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest delete(final String baseUrl, final Map params, final boolean encode) { + String url = append(baseUrl, params); + return delete(encode ? encode(url) : url); + } + + /** + * Start a 'DELETE' request to the given URL along with the query params + * + * @param baseUrl + * @param encode + * true to encode the full URL + * @param params + * the name/value query parameter pairs to include as part of the + * baseUrl + * + * @see #append(String, Object...) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest delete(final String baseUrl, final boolean encode, final Object... params) { + String url = append(baseUrl, params); + return delete(encode ? encode(url) : url); + } + + /** + * Start a 'HEAD' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest head(final String url) throws HttpRequestException { + return new HttpRequest(url, MethodType.HEAD); + } + + /** + * Start a 'HEAD' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest head(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.HEAD); + } + + /** + * Start a 'HEAD' request to the given URL along with the query params + * + * @param baseUrl + * @param params + * The query parameters to include as part of the baseUrl + * @param encode + * true to encode the full URL + * + * @see #append(String, Map) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest head(final String baseUrl, final Map params, final boolean encode) { + String url = append(baseUrl, params); + return head(encode ? encode(url) : url); + } + + /** + * Start a 'GET' request to the given URL along with the query params + * + * @param baseUrl + * @param encode + * true to encode the full URL + * @param params + * the name/value query parameter pairs to include as part of the + * baseUrl + * + * @see #append(String, Object...) + * @see #encode(String) + * + * @return request + */ + public static HttpRequest head(final String baseUrl, final boolean encode, final Object... params) { + String url = append(baseUrl, params); + return head(encode ? encode(url) : url); + } + + /** + * Start an 'OPTIONS' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest options(final String url) throws HttpRequestException { + return new HttpRequest(url, MethodType.OPTIONS); + } + + /** + * Start an 'OPTIONS' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest options(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.OPTIONS); + } + + /** + * Start a 'TRACE' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest trace(final String url) throws HttpRequestException { + return new HttpRequest(url, MethodType.TRACE); + } + + /** + * Start a 'TRACE' request to the given URL + * + * @param url + * @return request + * @throws HttpRequestException + */ + public static HttpRequest trace(final URL url) throws HttpRequestException { + return new HttpRequest(url, MethodType.TRACE); + } + + /** + * Set the 'http.keepAlive' property to the given value. + *

+ * This setting will apply to all requests. + * + * @param keepAlive + */ + public static void keepAlive(final boolean keepAlive) { + setProperty("http.keepAlive", Boolean.toString(keepAlive)); + } + + /** + * Set the 'http.maxConnections' property to the given value. + *

+ * This setting will apply to all requests. + * + * @param maxConnections + */ + public static void maxConnections(final int maxConnections) { + setProperty("http.maxConnections", Integer.toString(maxConnections)); + } + + /** + * Set the 'http.proxyHost' and 'https.proxyHost' properties to the given + * host value. + *

+ * This setting will apply to all requests. + * + * @param host + */ + public static void proxyHost(final String host) { + setProperty("http.proxyHost", host); + setProperty("https.proxyHost", host); + } + + /** + * Set the 'http.proxyPort' and 'https.proxyPort' properties to the given + * port number. + *

+ * This setting will apply to all requests. + * + * @param port + */ + public static void proxyPort(final int port) { + final String portValue = Integer.toString(port); + setProperty("http.proxyPort", portValue); + setProperty("https.proxyPort", portValue); + } + + /** + * Set the 'http.nonProxyHosts' property to the given host values. + *

+ * Hosts will be separated by a '|' character. + *

+ * This setting will apply to all requests. + * + * @param hosts + */ + public static void nonProxyHosts(final String... hosts) { + if (hosts != null && hosts.length > 0) { + StringBuilder separated = new StringBuilder(); + int last = hosts.length - 1; + for (int i = 0; i < last; i++) + separated.append(hosts[i]).append('|'); + separated.append(hosts[last]); + setProperty("http.nonProxyHosts", separated.toString()); + } else + setProperty("http.nonProxyHosts", null); + } + + /** + * Set property to given value. + *

+ * Specifying a null value will cause the property to be cleared + * + * @param name + * @param value + * @return previous value + */ + private static String setProperty(final String name, final String value) { + final PrivilegedAction action; + if (value != null) + action = new PrivilegedAction() { + + public String run() { + return System.setProperty(name, value); + } + }; + else + action = new PrivilegedAction() { + + public String run() { + return System.clearProperty(name); + } + }; + return AccessController.doPrivileged(action); + } + + private HttpURLConnection connection = null; + + private final URL url; + + private final String requestMethod; + + private RequestOutputStream output; + + private boolean multipart; + + private boolean form; + + private boolean ignoreCloseExceptions = true; + + private boolean uncompress = false; + + private int bufferSize = 8192; + + private long totalSize = -1; + + private long totalWritten = 0; + + private String httpProxyHost; + + private int httpProxyPort; + + private UploadProgress progress = UploadProgress.DEFAULT; + + private Map cookies; + + /** + * Create HTTP connection wrapper + * + * @param url + * Remote resource URL. + * @param method + * HTTP request method (e.g., "GET", "POST"). + * @throws HttpRequestException + */ + public HttpRequest(final String url, final String method) throws HttpRequestException { + try { + this.url = new URL(url.toString()); + } catch (MalformedURLException e) { + throw new HttpRequestException(e); + } + this.requestMethod = method; + this.cookies = new LinkedHashMap(); + } + + /** + * Create HTTP connection wrapper + * + * @param url + * Remote resource URL. + * @param method + * HTTP request method (e.g., "GET", "POST"). + * @throws HttpRequestException + */ + public HttpRequest(final URL url, final String method) throws HttpRequestException { + this.url = url; + this.requestMethod = method; + this.cookies = new LinkedHashMap(); + } + + private Proxy createProxy() { + return new Proxy(HTTP, new InetSocketAddress(httpProxyHost, httpProxyPort)); + } + + private HttpURLConnection createConnection() { + try { + final HttpURLConnection connection; + if (httpProxyHost != null) + connection = CONNECTION_FACTORY.create(url, createProxy()); + else + connection = CONNECTION_FACTORY.create(url); + connection.setRequestMethod(requestMethod); + return connection; + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + @Override + public String toString() { + return method() + ' ' + url(); + } + + /** + * Get underlying connection + * + * @return connection + */ + public HttpURLConnection getConnection() { + if (connection == null) + connection = createConnection(); + return connection; + } + + /** + * Set whether or not to ignore exceptions that occur from calling + * {@link Closeable#close()} + *

+ * The default value of this setting is true + * + * @param ignore + * @return this request + */ + public HttpRequest ignoreCloseExceptions(final boolean ignore) { + ignoreCloseExceptions = ignore; + return this; + } + + /** + * Get whether or not exceptions thrown by {@link Closeable#close()} are + * ignored + * + * @return true if ignoring, false if throwing + */ + public boolean ignoreCloseExceptions() { + return ignoreCloseExceptions; + } + + /** + * Get the status code of the response + * + * @return the response code + * @throws HttpRequestException + */ + public int code() throws HttpRequestException { + try { + closeOutput(); + return getConnection().getResponseCode(); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Set the value of the given {@link AtomicInteger} to the status code of + * the response + * + * @param output + * @return this request + * @throws HttpRequestException + */ + public HttpRequest code(final AtomicInteger output) throws HttpRequestException { + output.set(code()); + return this; + } + + /** + * Is the response code a 200 OK? + * + * @return true if 200, false otherwise + * @throws HttpRequestException + */ + public boolean ok() throws HttpRequestException { + return HTTP_OK == code(); + } + + /** + * Is the response code a 201 Created? + * + * @return true if 201, false otherwise + * @throws HttpRequestException + */ + public boolean created() throws HttpRequestException { + return HTTP_CREATED == code(); + } + + /** + * Is the response code a 204 No Content? + * + * @return true if 204, false otherwise + * @throws HttpRequestException + */ + public boolean noContent() throws HttpRequestException { + return HTTP_NO_CONTENT == code(); + } + + /** + * Is the response code a 500 Internal Server Error? + * + * @return true if 500, false otherwise + * @throws HttpRequestException + */ + public boolean serverError() throws HttpRequestException { + return HTTP_INTERNAL_ERROR == code(); + } + + /** + * Is the response code a 400 Bad Request? + * + * @return true if 400, false otherwise + * @throws HttpRequestException + */ + public boolean badRequest() throws HttpRequestException { + return HTTP_BAD_REQUEST == code(); + } + + /** + * Is the response code a 404 Not Found? + * + * @return true if 404, false otherwise + * @throws HttpRequestException + */ + public boolean notFound() throws HttpRequestException { + return HTTP_NOT_FOUND == code(); + } + + /** + * Is the response code a 304 Not Modified? + * + * @return true if 304, false otherwise + * @throws HttpRequestException + */ + public boolean notModified() throws HttpRequestException { + return HTTP_NOT_MODIFIED == code(); + } + + /** + * Get status message of the response + * + * @return message + * @throws HttpRequestException + */ + public String message() throws HttpRequestException { + try { + closeOutput(); + return getConnection().getResponseMessage(); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Disconnect the connection + * + * @return this request + */ + public HttpRequest disconnect() { + getConnection().disconnect(); + return this; + } + + /** + * Set chunked streaming mode to the given size + * + * @param size + * @return this request + */ + public HttpRequest chunk(final int size) { + getConnection().setChunkedStreamingMode(size); + return this; + } + + /** + * Set the size used when buffering and copying between streams + *

+ * This size is also used for send and receive buffers created for both char + * and byte arrays + *

+ * The default buffer size is 8,192 bytes + * + * @param size + * @return this request + */ + public HttpRequest bufferSize(final int size) { + if (size < 1) + throw new IllegalArgumentException("Size must be greater than zero"); + bufferSize = size; + return this; + } + + /** + * Get the configured buffer size + *

+ * The default buffer size is 8,192 bytes + * + * @return buffer size + */ + public int bufferSize() { + return bufferSize; + } + + /** + * Set whether or not the response body should be automatically uncompressed + * when read from. + *

+ * This will only affect requests that have the 'Content-Encoding' response + * header set to 'gzip'. + *

+ * This causes all receive methods to use a {@link GZIPInputStream} when + * applicable so that higher level streams and readers can read the data + * uncompressed. + *

+ * Setting this option does not cause any request headers to be set + * automatically so {@link #acceptGzipEncoding()} should be used in + * conjunction with this setting to tell the server to gzip the response. + * + * @param uncompress + * @return this request + */ + public HttpRequest uncompress(final boolean uncompress) { + this.uncompress = uncompress; + return this; + } + + /** + * Create byte array output stream + * + * @return stream + */ + protected ByteArrayOutputStream byteStream() { + final int size = contentLength(); + if (size > 0) + return new ByteArrayOutputStream(size); + else + return new ByteArrayOutputStream(); + } + + /** + * Get response as {@link String} in given character set + *

+ * This will fall back to using the UTF-8 character set if the given charset + * is null + * + * @param charset + * @return string + * @throws HttpRequestException + */ + public String body(final String charset) throws HttpRequestException { + final ByteArrayOutputStream output = byteStream(); + try { + copy(buffer(), output); + return output.toString(getValidCharset(charset)); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Get response as {@link String} using character set returned from + * {@link #charset()} + * + * @return string + * @throws HttpRequestException + */ + public String body() throws HttpRequestException { + return body(charset()); + } + + /** + * Get the response body as a {@link String} and set it as the value of the + * given reference. + * + * @param output + * @return this request + * @throws HttpRequestException + */ + public HttpRequest body(final AtomicReference output) throws HttpRequestException { + output.set(body()); + return this; + } + + /** + * Get the response body as a {@link String} and set it as the value of the + * given reference. + * + * @param output + * @param charset + * @return this request + * @throws HttpRequestException + */ + public HttpRequest body(final AtomicReference output, final String charset) throws HttpRequestException { + output.set(body(charset)); + return this; + } + + /** + * Is the response body empty? + * + * @return true if the Content-Length response header is 0, false otherwise + * @throws HttpRequestException + */ + public boolean isBodyEmpty() throws HttpRequestException { + return contentLength() == 0; + } + + /** + * Get response as byte array + * + * @return byte array + * @throws HttpRequestException + */ + public byte[] bytes() throws HttpRequestException { + final ByteArrayOutputStream output = byteStream(); + try { + copy(buffer(), output); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return output.toByteArray(); + } + + /** + * Get response in a buffered stream + * + * @see #bufferSize(int) + * @return stream + * @throws HttpRequestException + */ + public BufferedInputStream buffer() throws HttpRequestException { + return new BufferedInputStream(stream(), bufferSize); + } + + /** + * Get stream to response body + * + * @return stream + * @throws HttpRequestException + */ + public InputStream stream() throws HttpRequestException { + InputStream stream; + if (code() < HTTP_BAD_REQUEST) + try { + stream = getConnection().getInputStream(); + } catch (IOException e) { + throw new HttpRequestException(e); + } + else { + stream = getConnection().getErrorStream(); + if (stream == null) + try { + stream = getConnection().getInputStream(); + } catch (IOException e) { + if (contentLength() > 0) + throw new HttpRequestException(e); + else + stream = new ByteArrayInputStream(new byte[0]); + } + } + + if (!uncompress || !Header.ENCODING_GZIP.equals(contentEncoding())) + return stream; + else + try { + return new GZIPInputStream(stream); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Get reader to response body using given character set. + *

+ * This will fall back to using the UTF-8 character set if the given charset + * is null + * + * @param charset + * @return reader + * @throws HttpRequestException + */ + public InputStreamReader reader(final String charset) throws HttpRequestException { + try { + return new InputStreamReader(stream(), getValidCharset(charset)); + } catch (UnsupportedEncodingException e) { + throw new HttpRequestException(e); + } + } + + /** + * Get reader to response body using the character set returned from + * {@link #charset()} + * + * @return reader + * @throws HttpRequestException + */ + public InputStreamReader reader() throws HttpRequestException { + return reader(charset()); + } + + /** + * Get buffered reader to response body using the given character set r and + * the configured buffer size + * + * + * @see #bufferSize(int) + * @param charset + * @return reader + * @throws HttpRequestException + */ + public BufferedReader bufferedReader(final String charset) throws HttpRequestException { + return new BufferedReader(reader(charset), bufferSize); + } + + /** + * Get buffered reader to response body using the character set returned + * from {@link #charset()} and the configured buffer size + * + * @see #bufferSize(int) + * @return reader + * @throws HttpRequestException + */ + public BufferedReader bufferedReader() throws HttpRequestException { + return bufferedReader(charset()); + } + + /** + * Stream response body to file + * + * @param file + * @return this request + * @throws HttpRequestException + */ + public HttpRequest receive(final File file) throws HttpRequestException { + final OutputStream output; + try { + output = new BufferedOutputStream(new FileOutputStream(file), bufferSize); + } catch (FileNotFoundException e) { + throw new HttpRequestException(e); + } + return new CloseOperation(output, ignoreCloseExceptions) { + + @Override + protected HttpRequest run() throws HttpRequestException, IOException { + return receive(output); + } + }.call(); + } + + /** + * Stream response to given output stream + * + * @param output + * @return this request + * @throws HttpRequestException + */ + public HttpRequest receive(final OutputStream output) throws HttpRequestException { + try { + return copy(buffer(), output); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Stream response to given print stream + * + * @param output + * @return this request + * @throws HttpRequestException + */ + public HttpRequest receive(final PrintStream output) throws HttpRequestException { + return receive((OutputStream) output); + } + + /** + * Receive response into the given appendable + * + * @param appendable + * @return this request + * @throws HttpRequestException + */ + public HttpRequest receive(final Appendable appendable) throws HttpRequestException { + final BufferedReader reader = bufferedReader(); + return new CloseOperation(reader, ignoreCloseExceptions) { + + @Override + public HttpRequest run() throws IOException { + final CharBuffer buffer = CharBuffer.allocate(bufferSize); + int read; + while ((read = reader.read(buffer)) != -1) { + buffer.rewind(); + appendable.append(buffer, 0, read); + buffer.rewind(); + } + return HttpRequest.this; + } + }.call(); + } + + /** + * Receive response into the given writer + * + * @param writer + * @return this request + * @throws HttpRequestException + */ + public HttpRequest receive(final Writer writer) throws HttpRequestException { + final BufferedReader reader = bufferedReader(); + return new CloseOperation(reader, ignoreCloseExceptions) { + + @Override + public HttpRequest run() throws IOException { + return copy(reader, writer); + } + }.call(); + } + + /** + * Set read timeout on connection to given value + * + * @param timeout + * @return this request + */ + public HttpRequest readTimeout(final int timeout) { + getConnection().setReadTimeout(timeout); + return this; + } + + /** + * Set connect timeout on connection to given value + * + * @param timeout + * @return this request + */ + public HttpRequest connectTimeout(final int timeout) { + getConnection().setConnectTimeout(timeout); + return this; + } + + /** + * Set header name to given value + * + * @param name + * @param value + * @return this request + */ + public HttpRequest header(final String name, final String value) { + getConnection().setRequestProperty(name, value); + return this; + } + + /** + * Set cookie. e.g: key1=val1; key2=val2; + * + * @param key + * @param val + * @return + */ + public HttpRequest cookie(final String name, final String value) { + Assert.notEmpty(name, "Cookie name must not be empty"); + Assert.notNull(value); + + this.cookies.put(name, value); + this.executeCookie(getConnection()); + return this; + } + + public HttpRequest cookies(final Map cookies) { + if(null != cookies){ + this.cookies.putAll(cookies); + this.executeCookie(getConnection()); + } + return this; + } + + private void executeCookie(HttpURLConnection connection){ + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (Map.Entry cookie : this.cookies.entrySet()) { + if (!first) + sb.append("; "); else - params.put(name, value); + first = false; + sb.append(cookie.getKey()).append('=').append(cookie.getValue()); + // todo: spec says only ascii, no escaping / encoding defined. validate on set? or escape somehow here? } - } - - start = end + 1; - end = header.indexOf(';', start); - if (end == -1) - end = headerLength; - } - - return params; - } - - /** - * Get parameter value from header value - * - * @param value - * @param paramName - * @return parameter value or null if none - */ - protected String getParam(final String value, final String paramName) { - if (value == null || value.length() == 0) - return null; - - final int length = value.length(); - int start = value.indexOf(';') + 1; - if (start == 0 || start == length) - return null; - - int end = value.indexOf(';', start); - if (end == -1) - end = length; - - while (start < end) { - int nameEnd = value.indexOf('=', start); - if (nameEnd != -1 && nameEnd < end - && paramName.equals(value.substring(start, nameEnd).trim())) { - String paramValue = value.substring(nameEnd + 1, end).trim(); - int valueLength = paramValue.length(); - if (valueLength != 0) - if (valueLength > 2 && '"' == paramValue.charAt(0) - && '"' == paramValue.charAt(valueLength - 1)) - return paramValue.substring(1, valueLength - 1); - else - return paramValue; - } - - start = end + 1; - end = value.indexOf(';', start); - if (end == -1) - end = length; - } - - return null; - } - - /** - * Get 'charset' parameter from 'Content-Type' response header - * - * @return charset or null if none - */ - public String charset() { - return parameter(Header.HEADER_CONTENT_TYPE, Header.PARAM_CHARSET); - } - - /** - * Set the 'User-Agent' header to given value - * - * @param userAgent - * @return this request - */ - public HttpRequest userAgent(final String userAgent) { - return header(Header.HEADER_USER_AGENT, userAgent); - } - - /** - * Set the 'Referer' header to given value - * - * @param referer - * @return this request - */ - public HttpRequest referer(final String referer) { - return header(Header.HEADER_REFERER, referer); - } - - /** - * Set value of {@link HttpURLConnection#setUseCaches(boolean)} - * - * @param useCaches - * @return this request - */ - public HttpRequest useCaches(final boolean useCaches) { - getConnection().setUseCaches(useCaches); - return this; - } - - /** - * Set the 'Accept-Encoding' header to given value - * - * @param acceptEncoding - * @return this request - */ - public HttpRequest acceptEncoding(final String acceptEncoding) { - return header(Header.HEADER_ACCEPT_ENCODING, acceptEncoding); - } - - /** - * Set the 'Accept-Encoding' header to 'gzip' - * - * @see #uncompress(boolean) - * @return this request - */ - public HttpRequest acceptGzipEncoding() { - return acceptEncoding(Header.ENCODING_GZIP); - } - - /** - * Set the 'Accept-Charset' header to given value - * - * @param acceptCharset - * @return this request - */ - public HttpRequest acceptCharset(final String acceptCharset) { - return header(Header.HEADER_ACCEPT_CHARSET, acceptCharset); - } - - /** - * Get the 'Content-Encoding' header from the response - * - * @return this request - */ - public String contentEncoding() { - return header(Header.HEADER_CONTENT_ENCODING); - } - - /** - * Get the 'Server' header from the response - * - * @return server - */ - public String server() { - return header(Header.HEADER_SERVER); - } - - /** - * Get the 'Date' header from the response - * - * @return date value, -1 on failures - */ - public long date() { - return dateHeader(Header.HEADER_DATE); - } - - /** - * Get the 'Cache-Control' header from the response - * - * @return cache control - */ - public String cacheControl() { - return header(Header.HEADER_CACHE_CONTROL); - } - - /** - * Get the 'ETag' header from the response - * - * @return entity tag - */ - public String eTag() { - return header(Header.HEADER_ETAG); - } - - /** - * Get the 'Expires' header from the response - * - * @return expires value, -1 on failures - */ - public long expires() { - return dateHeader(Header.HEADER_EXPIRES); - } - - /** - * Get the 'Last-Modified' header from the response - * - * @return last modified value, -1 on failures - */ - public long lastModified() { - return dateHeader(Header.HEADER_LAST_MODIFIED); - } - - /** - * Get the 'Location' header from the response - * - * @return location - */ - public String location() { - return header(Header.HEADER_LOCATION); - } - - /** - * Set the 'Authorization' header to given value - * - * @param authorization - * @return this request - */ - public HttpRequest authorization(final String authorization) { - return header(Header.HEADER_AUTHORIZATION, authorization); - } - - /** - * Set the 'Proxy-Authorization' header to given value - * - * @param proxyAuthorization - * @return this request - */ - public HttpRequest proxyAuthorization(final String proxyAuthorization) { - return header(Header.HEADER_PROXY_AUTHORIZATION, proxyAuthorization); - } - - /** - * Set the 'Authorization' header to given values in Basic authentication - * format - * - * @param name - * @param password - * @return this request - */ - public HttpRequest basic(final String name, final String password) { - return authorization("Basic " + Base64.encode(name + ':' + password)); - } - - /** - * Set the 'Proxy-Authorization' header to given values in Basic authentication - * format - * - * @param name - * @param password - * @return this request - */ - public HttpRequest proxyBasic(final String name, final String password) { - return proxyAuthorization("Basic " + Base64.encode(name + ':' + password)); - } - - /** - * Set the 'If-Modified-Since' request header to the given value - * - * @param ifModifiedSince - * @return this request - */ - public HttpRequest ifModifiedSince(final long ifModifiedSince) { - getConnection().setIfModifiedSince(ifModifiedSince); - return this; - } - - /** - * Set the 'If-None-Match' request header to the given value - * - * @param ifNoneMatch - * @return this request - */ - public HttpRequest ifNoneMatch(final String ifNoneMatch) { - return header(Header.HEADER_IF_NONE_MATCH, ifNoneMatch); - } - - /** - * Set the 'Content-Type' request header to the given value - * - * @param contentType - * @return this request - */ - public HttpRequest contentType(final String contentType) { - return contentType(contentType, null); - } - - /** - * Set the 'Content-Type' request header to the given value and charset - * - * @param contentType - * @param charset - * @return this request - */ - public HttpRequest contentType(final String contentType, final String charset) { - if (charset != null && charset.length() > 0) { - final String separator = "; " + Header.PARAM_CHARSET + '='; - return header(Header.HEADER_CONTENT_TYPE, contentType + separator + charset); - } else - return header(Header.HEADER_CONTENT_TYPE, contentType); - } - - /** - * Get the 'Content-Type' header from the response - * - * @return response header value - */ - public String contentType() { - return header(Header.HEADER_CONTENT_TYPE); - } - - /** - * Get the 'Content-Length' header from the response - * - * @return response header value - */ - public int contentLength() { - return intHeader(Header.HEADER_CONTENT_LENGTH); - } - - /** - * Set the 'Content-Length' request header to the given value - * - * @param contentLength - * @return this request - */ - public HttpRequest contentLength(final String contentLength) { - return contentLength(Integer.parseInt(contentLength)); - } - - /** - * Set the 'Content-Length' request header to the given value - * - * @param contentLength - * @return this request - */ - public HttpRequest contentLength(final int contentLength) { - getConnection().setFixedLengthStreamingMode(contentLength); - return this; - } - - /** - * Set the 'Accept' header to given value - * - * @param accept - * @return this request - */ - public HttpRequest accept(final String accept) { - return header(Header.HEADER_ACCEPT, accept); - } - - /** - * Set the 'Accept' header to 'application/json' - * - * @return this request - */ - public HttpRequest acceptJson() { - return accept(Header.CONTENT_TYPE_JSON); - } - - /** - * Copy from input stream to output stream - * - * @param input - * @param output - * @return this request - * @throws IOException - */ - protected HttpRequest copy(final InputStream input, final OutputStream output) - throws IOException { - return new CloseOperation(input, ignoreCloseExceptions) { - - @Override - public HttpRequest run() throws IOException { - final byte[] buffer = new byte[bufferSize]; - int read; - while ((read = input.read(buffer)) != -1) { - output.write(buffer, 0, read); - totalWritten += read; - progress.onUpload(totalWritten, totalSize); + String cookies = sb.toString(); + connection.setRequestProperty(Header.HEADER_COOKIE, cookies); + } + + + /** + * Set header name to given value + * + * @param name + * @param value + * @return this request + */ + public HttpRequest header(final String name, final Number value) { + return header(name, value != null ? value.toString() : null); + } + + /** + * Set all headers found in given map where the keys are the header names + * and the values are the header values + * + * @param headers + * @return this request + */ + public HttpRequest headers(final Map headers) { + if (!headers.isEmpty()) + for (Entry header : headers.entrySet()) + header(header); + return this; + } + + /** + * Set header to have given entry's key as the name and value as the value + * + * @param header + * @return this request + */ + public HttpRequest header(final Entry header) { + return header(header.getKey(), header.getValue()); + } + + /** + * Get a response header + * + * @param name + * @return response header + * @throws HttpRequestException + */ + public String header(final String name) throws HttpRequestException { + closeOutputQuietly(); + return getConnection().getHeaderField(name); + } + + /** + * Get all the response headers + * + * @return map of response header names to their value(s) + * @throws HttpRequestException + */ + public Map> headers() throws HttpRequestException { + closeOutputQuietly(); + return getConnection().getHeaderFields(); + } + + /** + * Get response cookie + * + * @param name cookie name + * @return cookie value + */ + public String cookie(final String name) { + Assert.notEmpty(name, "Cookie name must not be empty"); + return this.cookies().get(name); + } + + /** + * Get response cookies + * + * @return cookies map + */ + public Map cookies() { + closeOutputQuietly(); + this.cookies.clear(); + Map> resHeaders = getConnection().getHeaderFields(); + processResponseHeaders(resHeaders); + return this.cookies; + } + + void processResponseHeaders(Map> resHeaders) { + for (Map.Entry> entry : resHeaders.entrySet()) { + String name = entry.getKey(); + if (name == null) + continue; // http/1.1 line + List values = entry.getValue(); + if (name.equalsIgnoreCase(Header.HEADER_SET_COOKIE)) { + for (String value : values) { + if (value == null) + continue; + TokenQueue cd = new TokenQueue(value); + String cookieName = cd.chompTo("=").trim(); + String cookieVal = cd.consumeTo(";").trim(); + // ignores path, date, domain, validateTLSCertificates et al. req'd? + // name not blank, value not null + if (cookieName.length() > 0) + cookie(cookieName, cookieVal); + } + } } - return HttpRequest.this; - } - }.call(); - } - - /** - * Copy from reader to writer - * - * @param input - * @param output - * @return this request - * @throws IOException - */ - protected HttpRequest copy(final Reader input, final Writer output) - throws IOException { - return new CloseOperation(input, ignoreCloseExceptions) { - - @Override - public HttpRequest run() throws IOException { - final char[] buffer = new char[bufferSize]; - int read; - while ((read = input.read(buffer)) != -1) { - output.write(buffer, 0, read); - totalWritten += read; - progress.onUpload(totalWritten, -1); - } - return HttpRequest.this; - } - }.call(); - } - - /** - * Set the UploadProgress callback for this request - * - * @param callback - * @return this request - */ - public HttpRequest progress(final UploadProgress callback) { - if (callback == null) - progress = UploadProgress.DEFAULT; - else - progress = callback; - return this; - } - - private HttpRequest incrementTotalSize(final long size) { - if (totalSize == -1) - totalSize = 0; - totalSize += size; - return this; - } - - /** - * Close output stream - * - * @return this request - * @throws HttpRequestException - * @throws IOException - */ - protected HttpRequest closeOutput() throws IOException { - progress(null); - if (output == null) - return this; - if (multipart) - output.write(CRLF + "--" + BOUNDARY + "--" + CRLF); - if (ignoreCloseExceptions) - try { - output.close(); - } catch (IOException ignored) { - // Ignored - } - else - output.close(); - output = null; - return this; - } - - /** - * Call {@link #closeOutput()} and re-throw a caught {@link IOException}s as - * an {@link HttpRequestException} - * - * @return this request - * @throws HttpRequestException - */ - protected HttpRequest closeOutputQuietly() throws HttpRequestException { - try { - return closeOutput(); - } catch (IOException e) { - throw new HttpRequestException(e); - } - } - - /** - * Open output stream - * - * @return this request - * @throws IOException - */ - protected HttpRequest openOutput() throws IOException { - if (output != null) - return this; - getConnection().setDoOutput(true); - final String charset = getParam( - getConnection().getRequestProperty(Header.HEADER_CONTENT_TYPE), Header.PARAM_CHARSET); - output = new RequestOutputStream(getConnection().getOutputStream(), charset, - bufferSize); - return this; - } - - /** - * Start part of a multipart - * - * @return this request - * @throws IOException - */ - protected HttpRequest startPart() throws IOException { - if (!multipart) { - multipart = true; - contentType(CONTENT_TYPE_MULTIPART).openOutput(); - output.write("--" + BOUNDARY + CRLF); - } else - output.write(CRLF + "--" + BOUNDARY + CRLF); - return this; - } - - /** - * Write part header - * - * @param name - * @param filename - * @return this request - * @throws IOException - */ - protected HttpRequest writePartHeader(final String name, final String filename) - throws IOException { - return writePartHeader(name, filename, null); - } - - /** - * Write part header - * - * @param name - * @param filename - * @param contentType - * @return this request - * @throws IOException - */ - protected HttpRequest writePartHeader(final String name, - final String filename, final String contentType) throws IOException { - final StringBuilder partBuffer = new StringBuilder(); - partBuffer.append("form-data; name=\"").append(name); - if (filename != null) - partBuffer.append("\"; filename=\"").append(filename); - partBuffer.append('"'); - partHeader("Content-Disposition", partBuffer.toString()); - if (contentType != null) - partHeader(Header.HEADER_CONTENT_TYPE, contentType); - return send(CRLF); - } - - /** - * Write part of a multipart request to the request body - * - * @param name - * @param part - * @return this request - */ - public HttpRequest part(final String name, final String part) { - return part(name, null, part); - } - - /** - * Write part of a multipart request to the request body - * - * @param name - * @param filename - * @param part - * @return this request - * @throws HttpRequestException - */ - public HttpRequest part(final String name, final String filename, - final String part) throws HttpRequestException { - return part(name, filename, null, part); - } - - /** - * Write part of a multipart request to the request body - * - * @param name - * @param filename - * @param contentType - * value of the Content-Type part header - * @param part - * @return this request - * @throws HttpRequestException - */ - public HttpRequest part(final String name, final String filename, - final String contentType, final String part) throws HttpRequestException { - try { - startPart(); - writePartHeader(name, filename, contentType); - output.write(part); - } catch (IOException e) { - throw new HttpRequestException(e); - } - return this; - } - - /** - * Write part of a multipart request to the request body - * - * @param name - * @param part - * @return this request - * @throws HttpRequestException - */ - public HttpRequest part(final String name, final Number part) - throws HttpRequestException { - return part(name, null, part); - } - - /** - * Write part of a multipart request to the request body - * - * @param name - * @param filename - * @param part - * @return this request - * @throws HttpRequestException - */ - public HttpRequest part(final String name, final String filename, - final Number part) throws HttpRequestException { - return part(name, filename, part != null ? part.toString() : null); - } - - /** - * Write part of a multipart request to the request body - * - * @param name - * @param part - * @return this request - * @throws HttpRequestException - */ - public HttpRequest part(final String name, final File part) - throws HttpRequestException { - return part(name, null, part); - } - - /** - * Write part of a multipart request to the request body - * - * @param name - * @param filename - * @param part - * @return this request - * @throws HttpRequestException - */ - public HttpRequest part(final String name, final String filename, - final File part) throws HttpRequestException { - return part(name, filename, null, part); - } - - /** - * Write part of a multipart request to the request body - * - * @param name - * @param filename - * @param contentType - * value of the Content-Type part header - * @param part - * @return this request - * @throws HttpRequestException - */ - public HttpRequest part(final String name, final String filename, - final String contentType, final File part) throws HttpRequestException { - final InputStream stream; - try { - stream = new BufferedInputStream(new FileInputStream(part)); - incrementTotalSize(part.length()); - } catch (IOException e) { - throw new HttpRequestException(e); - } - return part(name, filename, contentType, stream); - } - - /** - * Write part of a multipart request to the request body - * - * @param name - * @param part - * @return this request - * @throws HttpRequestException - */ - public HttpRequest part(final String name, final InputStream part) - throws HttpRequestException { - return part(name, null, null, part); - } - - /** - * Write part of a multipart request to the request body - * - * @param name - * @param filename - * @param contentType - * value of the Content-Type part header - * @param part - * @return this request - * @throws HttpRequestException - */ - public HttpRequest part(final String name, final String filename, - final String contentType, final InputStream part) - throws HttpRequestException { - try { - startPart(); - writePartHeader(name, filename, contentType); - copy(part, output); - } catch (IOException e) { - throw new HttpRequestException(e); - } - return this; - } - - /** - * Write a multipart header to the response body - * - * @param name - * @param value - * @return this request - * @throws HttpRequestException - */ - public HttpRequest partHeader(final String name, final String value) - throws HttpRequestException { - return send(name).send(": ").send(value).send(CRLF); - } - - /** - * Write contents of file to request body - * - * @param input - * @return this request - * @throws HttpRequestException - */ - public HttpRequest send(final File input) throws HttpRequestException { - final InputStream stream; - try { - stream = new BufferedInputStream(new FileInputStream(input)); - incrementTotalSize(input.length()); - } catch (FileNotFoundException e) { - throw new HttpRequestException(e); - } - return send(stream); - } - - /** - * Write byte array to request body - * - * @param input - * @return this request - * @throws HttpRequestException - */ - public HttpRequest send(final byte[] input) throws HttpRequestException { - if (input != null) - incrementTotalSize(input.length); - return send(new ByteArrayInputStream(input)); - } - - /** - * Write stream to request body - *

- * The given stream will be closed once sending completes - * - * @param input - * @return this request - * @throws HttpRequestException - */ - public HttpRequest send(final InputStream input) throws HttpRequestException { - try { - openOutput(); - copy(input, output); - } catch (IOException e) { - throw new HttpRequestException(e); - } - return this; - } - - /** - * Write reader to request body - *

- * The given reader will be closed once sending completes - * - * @param input - * @return this request - * @throws HttpRequestException - */ - public HttpRequest send(final Reader input) throws HttpRequestException { - try { - openOutput(); - } catch (IOException e) { - throw new HttpRequestException(e); - } - final Writer writer = new OutputStreamWriter(output, - output.encoder.charset()); - return new FlushOperation(writer) { - - @Override - protected HttpRequest run() throws IOException { - return copy(input, writer); - } - }.call(); - } - - /** - * Write char sequence to request body - *

- * The charset configured via {@link #contentType(String)} will be used and - * UTF-8 will be used if it is unset. - * - * @param value - * @return this request - * @throws HttpRequestException - */ - public HttpRequest send(final String value) throws HttpRequestException { - try { - openOutput(); - output.write(value.toString()); - } catch (IOException e) { - throw new HttpRequestException(e); - } - return this; - } - - /** - * Create writer to request output stream - * - * @return writer - * @throws HttpRequestException - */ - public OutputStreamWriter writer() throws HttpRequestException { - try { - openOutput(); - return new OutputStreamWriter(output, output.encoder.charset()); - } catch (IOException e) { - throw new HttpRequestException(e); - } - } - - /** - * Write the values in the map as form data to the request body - *

- * The pairs specified will be URL-encoded in UTF-8 and sent with the - * 'application/x-www-form-urlencoded' content-type - * - * @param values - * @return this request - * @throws HttpRequestException - */ - public HttpRequest form(final Map values) throws HttpRequestException { - return form(values, Header.CHARSET_UTF8); - } - - /** - * Write the key and value in the entry as form data to the request body - *

- * The pair specified will be URL-encoded in UTF-8 and sent with the - * 'application/x-www-form-urlencoded' content-type - * - * @param entry - * @return this request - * @throws HttpRequestException - */ - public HttpRequest form(final Entry entry) throws HttpRequestException { - return form(entry, Header.CHARSET_UTF8); - } - - /** - * Write the key and value in the entry as form data to the request body - *

- * The pair specified will be URL-encoded and sent with the - * 'application/x-www-form-urlencoded' content-type - * - * @param entry - * @param charset - * @return this request - * @throws HttpRequestException - */ - public HttpRequest form(final Entry entry, final String charset) - throws HttpRequestException { - return form(entry.getKey(), entry.getValue(), charset); - } - - /** - * Write the name/value pair as form data to the request body - *

- * The pair specified will be URL-encoded in UTF-8 and sent with the - * 'application/x-www-form-urlencoded' content-type - * - * @param name - * @param value - * @return this request - * @throws HttpRequestException - */ - public HttpRequest form(final Object name, final Object value) - throws HttpRequestException { - return form(name, value, Header.CHARSET_UTF8); - } - - /** - * Write the name/value pair as form data to the request body - *

- * The values specified will be URL-encoded and sent with the - * 'application/x-www-form-urlencoded' content-type - * - * @param name - * @param value - * @param charset - * @return this request - * @throws HttpRequestException - */ - public HttpRequest form(final Object name, final Object value, String charset) - throws HttpRequestException { - final boolean first = !form; - if (first) { - contentType(Header.CONTENT_TYPE_FORM, charset); - form = true; - } - charset = getValidCharset(charset); - try { - openOutput(); - if (!first) - output.write('&'); - output.write(URLEncoder.encode(name.toString(), charset)); - output.write('='); - if (value != null) - output.write(URLEncoder.encode(value.toString(), charset)); - } catch (IOException e) { - throw new HttpRequestException(e); } - return this; - } - - /** - * Write the values in the map as encoded form data to the request body - * - * @param values - * @param charset - * @return this request - * @throws HttpRequestException - */ - public HttpRequest form(final Map values, final String charset) - throws HttpRequestException { - if (!values.isEmpty()) - for (Entry entry : values.entrySet()) - form(entry, charset); - return this; - } - - /** - * Configure HTTPS connection to trust all certificates - *

- * This method does nothing if the current request is not a HTTPS request - * - * @return this request - * @throws HttpRequestException - */ - public HttpRequest trustAllCerts() throws HttpRequestException { - final HttpURLConnection connection = getConnection(); - if (connection instanceof HttpsURLConnection) - ((HttpsURLConnection) connection) - .setSSLSocketFactory(getTrustedFactory()); - return this; - } - - /** - * Configure HTTPS connection to trust all hosts using a custom - * {@link HostnameVerifier} that always returns true for each - * host verified - *

- * This method does nothing if the current request is not a HTTPS request - * - * @return this request - */ - public HttpRequest trustAllHosts() { - final HttpURLConnection connection = getConnection(); - if (connection instanceof HttpsURLConnection) - ((HttpsURLConnection) connection) - .setHostnameVerifier(getTrustedVerifier()); - return this; - } - - /** - * Get the {@link URL} of this request's connection - * - * @return request URL - */ - public URL url() { - return getConnection().getURL(); - } - - /** - * Get the HTTP method of this request - * - * @return method - */ - public String method() { - return getConnection().getRequestMethod(); - } - - /** - * Configure an HTTP proxy on this connection. Use {{@link #proxyBasic(String, String)} if - * this proxy requires basic authentication. - * - * @param proxyHost - * @param proxyPort - * @return this request - */ - public HttpRequest useProxy(final String proxyHost, final int proxyPort) { - if (connection != null) - throw new IllegalStateException("The connection has already been created. This method must be called before reading or writing to the request."); - - this.httpProxyHost = proxyHost; - this.httpProxyPort = proxyPort; - return this; - } - - /** - * Set whether or not the underlying connection should follow redirects in - * the response. - * - * @param followRedirects - true fo follow redirects, false to not. - * @return this request - */ - public HttpRequest followRedirects(final boolean followRedirects) { - getConnection().setInstanceFollowRedirects(followRedirects); - return this; - } + + /** + * Get a date header from the response falling back to returning -1 if the + * header is missing or parsing fails + * + * @param name + * @return date, -1 on failures + * @throws HttpRequestException + */ + public long dateHeader(final String name) throws HttpRequestException { + return dateHeader(name, -1L); + } + + /** + * Get a date header from the response falling back to returning the given + * default value if the header is missing or parsing fails + * + * @param name + * @param defaultValue + * @return date, default value on failures + * @throws HttpRequestException + */ + public long dateHeader(final String name, final long defaultValue) throws HttpRequestException { + closeOutputQuietly(); + return getConnection().getHeaderFieldDate(name, defaultValue); + } + + /** + * Get an integer header from the response falling back to returning -1 if + * the header is missing or parsing fails + * + * @param name + * @return header value as an integer, -1 when missing or parsing fails + * @throws HttpRequestException + */ + public int intHeader(final String name) throws HttpRequestException { + return intHeader(name, -1); + } + + /** + * Get an integer header value from the response falling back to the given + * default value if the header is missing or if parsing fails + * + * @param name + * @param defaultValue + * @return header value as an integer, default value when missing or parsing + * fails + * @throws HttpRequestException + */ + public int intHeader(final String name, final int defaultValue) throws HttpRequestException { + closeOutputQuietly(); + return getConnection().getHeaderFieldInt(name, defaultValue); + } + + /** + * Get all values of the given header from the response + * + * @param name + * @return non-null but possibly empty array of {@link String} header values + */ + public String[] headers(final String name) { + final Map> headers = headers(); + if (headers == null || headers.isEmpty()) + return EMPTY_STRINGS; + + final List values = headers.get(name); + if (values != null && !values.isEmpty()) + return values.toArray(new String[values.size()]); + else + return EMPTY_STRINGS; + } + + /** + * Get parameter with given name from header value in response + * + * @param headerName + * @param paramName + * @return parameter value or null if missing + */ + public String parameter(final String headerName, final String paramName) { + return getParam(header(headerName), paramName); + } + + /** + * Get all parameters from header value in response + *

+ * This will be all key=value pairs after the first ';' that are separated + * by a ';' + * + * @param headerName + * @return non-null but possibly empty map of parameter headers + */ + public Map parameters(final String headerName) { + return getParams(header(headerName)); + } + + /** + * Get parameter values from header value + * + * @param header + * @return parameter value or null if none + */ + protected Map getParams(final String header) { + if (header == null || header.length() == 0) + return Collections.emptyMap(); + + final int headerLength = header.length(); + int start = header.indexOf(';') + 1; + if (start == 0 || start == headerLength) + return Collections.emptyMap(); + + int end = header.indexOf(';', start); + if (end == -1) + end = headerLength; + + Map params = new LinkedHashMap(); + while (start < end) { + int nameEnd = header.indexOf('=', start); + if (nameEnd != -1 && nameEnd < end) { + String name = header.substring(start, nameEnd).trim(); + if (name.length() > 0) { + String value = header.substring(nameEnd + 1, end).trim(); + int length = value.length(); + if (length != 0) + if (length > 2 && '"' == value.charAt(0) && '"' == value.charAt(length - 1)) + params.put(name, value.substring(1, length - 1)); + else + params.put(name, value); + } + } + + start = end + 1; + end = header.indexOf(';', start); + if (end == -1) + end = headerLength; + } + + return params; + } + + /** + * Get parameter value from header value + * + * @param value + * @param paramName + * @return parameter value or null if none + */ + protected String getParam(final String value, final String paramName) { + if (value == null || value.length() == 0) + return null; + + final int length = value.length(); + int start = value.indexOf(';') + 1; + if (start == 0 || start == length) + return null; + + int end = value.indexOf(';', start); + if (end == -1) + end = length; + + while (start < end) { + int nameEnd = value.indexOf('=', start); + if (nameEnd != -1 && nameEnd < end && paramName.equals(value.substring(start, nameEnd).trim())) { + String paramValue = value.substring(nameEnd + 1, end).trim(); + int valueLength = paramValue.length(); + if (valueLength != 0) + if (valueLength > 2 && '"' == paramValue.charAt(0) && '"' == paramValue.charAt(valueLength - 1)) + return paramValue.substring(1, valueLength - 1); + else + return paramValue; + } + + start = end + 1; + end = value.indexOf(';', start); + if (end == -1) + end = length; + } + + return null; + } + + /** + * Get 'charset' parameter from 'Content-Type' response header + * + * @return charset or null if none + */ + public String charset() { + return parameter(Header.HEADER_CONTENT_TYPE, Header.PARAM_CHARSET); + } + + /** + * Set the 'User-Agent' header to given value + * + * @param userAgent + * @return this request + */ + public HttpRequest userAgent(final String userAgent) { + return header(Header.HEADER_USER_AGENT, userAgent); + } + + /** + * Set the 'Referer' header to given value + * + * @param referer + * @return this request + */ + public HttpRequest referer(final String referer) { + return header(Header.HEADER_REFERER, referer); + } + + /** + * Set value of {@link HttpURLConnection#setUseCaches(boolean)} + * + * @param useCaches + * @return this request + */ + public HttpRequest useCaches(final boolean useCaches) { + getConnection().setUseCaches(useCaches); + return this; + } + + /** + * Set the 'Accept-Encoding' header to given value + * + * @param acceptEncoding + * @return this request + */ + public HttpRequest acceptEncoding(final String acceptEncoding) { + return header(Header.HEADER_ACCEPT_ENCODING, acceptEncoding); + } + + /** + * Set the 'Accept-Encoding' header to 'gzip' + * + * @see #uncompress(boolean) + * @return this request + */ + public HttpRequest acceptGzipEncoding() { + return acceptEncoding(Header.ENCODING_GZIP); + } + + /** + * Set the 'Accept-Charset' header to given value + * + * @param acceptCharset + * @return this request + */ + public HttpRequest acceptCharset(final String acceptCharset) { + return header(Header.HEADER_ACCEPT_CHARSET, acceptCharset); + } + + /** + * Get the 'Content-Encoding' header from the response + * + * @return this request + */ + public String contentEncoding() { + return header(Header.HEADER_CONTENT_ENCODING); + } + + /** + * Get the 'Server' header from the response + * + * @return server + */ + public String server() { + return header(Header.HEADER_SERVER); + } + + /** + * Get the 'Date' header from the response + * + * @return date value, -1 on failures + */ + public long date() { + return dateHeader(Header.HEADER_DATE); + } + + /** + * Get the 'Cache-Control' header from the response + * + * @return cache control + */ + public String cacheControl() { + return header(Header.HEADER_CACHE_CONTROL); + } + + /** + * Get the 'ETag' header from the response + * + * @return entity tag + */ + public String eTag() { + return header(Header.HEADER_ETAG); + } + + /** + * Get the 'Expires' header from the response + * + * @return expires value, -1 on failures + */ + public long expires() { + return dateHeader(Header.HEADER_EXPIRES); + } + + /** + * Get the 'Last-Modified' header from the response + * + * @return last modified value, -1 on failures + */ + public long lastModified() { + return dateHeader(Header.HEADER_LAST_MODIFIED); + } + + /** + * Get the 'Location' header from the response + * + * @return location + */ + public String location() { + return header(Header.HEADER_LOCATION); + } + + /** + * Set the 'Authorization' header to given value + * + * @param authorization + * @return this request + */ + public HttpRequest authorization(final String authorization) { + return header(Header.HEADER_AUTHORIZATION, authorization); + } + + /** + * Set the 'Proxy-Authorization' header to given value + * + * @param proxyAuthorization + * @return this request + */ + public HttpRequest proxyAuthorization(final String proxyAuthorization) { + return header(Header.HEADER_PROXY_AUTHORIZATION, proxyAuthorization); + } + + /** + * Set the 'Authorization' header to given values in Basic authentication + * format + * + * @param name + * @param password + * @return this request + */ + public HttpRequest basic(final String name, final String password) { + return authorization("Basic " + Base64.encode(name + ':' + password)); + } + + /** + * Set the 'Proxy-Authorization' header to given values in Basic + * authentication format + * + * @param name + * @param password + * @return this request + */ + public HttpRequest proxyBasic(final String name, final String password) { + return proxyAuthorization("Basic " + Base64.encode(name + ':' + password)); + } + + /** + * Set the 'If-Modified-Since' request header to the given value + * + * @param ifModifiedSince + * @return this request + */ + public HttpRequest ifModifiedSince(final long ifModifiedSince) { + getConnection().setIfModifiedSince(ifModifiedSince); + return this; + } + + /** + * Set the 'If-None-Match' request header to the given value + * + * @param ifNoneMatch + * @return this request + */ + public HttpRequest ifNoneMatch(final String ifNoneMatch) { + return header(Header.HEADER_IF_NONE_MATCH, ifNoneMatch); + } + + /** + * Set the 'Content-Type' request header to the given value + * + * @param contentType + * @return this request + */ + public HttpRequest contentType(final String contentType) { + return contentType(contentType, null); + } + + /** + * Set the 'Content-Type' request header to the given value and charset + * + * @param contentType + * @param charset + * @return this request + */ + public HttpRequest contentType(final String contentType, final String charset) { + if (charset != null && charset.length() > 0) { + final String separator = "; " + Header.PARAM_CHARSET + '='; + return header(Header.HEADER_CONTENT_TYPE, contentType + separator + charset); + } else + return header(Header.HEADER_CONTENT_TYPE, contentType); + } + + /** + * Get the 'Content-Type' header from the response + * + * @return response header value + */ + public String contentType() { + return header(Header.HEADER_CONTENT_TYPE); + } + + /** + * Get the 'Content-Length' header from the response + * + * @return response header value + */ + public int contentLength() { + return intHeader(Header.HEADER_CONTENT_LENGTH); + } + + /** + * Set the 'Content-Length' request header to the given value + * + * @param contentLength + * @return this request + */ + public HttpRequest contentLength(final String contentLength) { + return contentLength(Integer.parseInt(contentLength)); + } + + /** + * Set the 'Content-Length' request header to the given value + * + * @param contentLength + * @return this request + */ + public HttpRequest contentLength(final int contentLength) { + getConnection().setFixedLengthStreamingMode(contentLength); + return this; + } + + /** + * Set the 'Accept' header to given value + * + * @param accept + * @return this request + */ + public HttpRequest accept(final String accept) { + return header(Header.HEADER_ACCEPT, accept); + } + + /** + * Set the 'Accept' header to 'application/json' + * + * @return this request + */ + public HttpRequest acceptJson() { + return accept(Header.CONTENT_TYPE_JSON); + } + + /** + * Copy from input stream to output stream + * + * @param input + * @param output + * @return this request + * @throws IOException + */ + protected HttpRequest copy(final InputStream input, final OutputStream output) throws IOException { + return new CloseOperation(input, ignoreCloseExceptions) { + + @Override + public HttpRequest run() throws IOException { + final byte[] buffer = new byte[bufferSize]; + int read; + while ((read = input.read(buffer)) != -1) { + output.write(buffer, 0, read); + totalWritten += read; + progress.onUpload(totalWritten, totalSize); + } + return HttpRequest.this; + } + }.call(); + } + + /** + * Copy from reader to writer + * + * @param input + * @param output + * @return this request + * @throws IOException + */ + protected HttpRequest copy(final Reader input, final Writer output) throws IOException { + return new CloseOperation(input, ignoreCloseExceptions) { + + @Override + public HttpRequest run() throws IOException { + final char[] buffer = new char[bufferSize]; + int read; + while ((read = input.read(buffer)) != -1) { + output.write(buffer, 0, read); + totalWritten += read; + progress.onUpload(totalWritten, -1); + } + return HttpRequest.this; + } + }.call(); + } + + /** + * Set the UploadProgress callback for this request + * + * @param callback + * @return this request + */ + public HttpRequest progress(final UploadProgress callback) { + if (callback == null) + progress = UploadProgress.DEFAULT; + else + progress = callback; + return this; + } + + private HttpRequest incrementTotalSize(final long size) { + if (totalSize == -1) + totalSize = 0; + totalSize += size; + return this; + } + + /** + * Close output stream + * + * @return this request + * @throws HttpRequestException + * @throws IOException + */ + protected HttpRequest closeOutput() throws IOException { + progress(null); + if (output == null) + return this; + if (multipart) + output.write(CRLF + "--" + BOUNDARY + "--" + CRLF); + if (ignoreCloseExceptions) + try { + output.close(); + } catch (IOException ignored) { + // Ignored + } + else + output.close(); + output = null; + return this; + } + + /** + * Call {@link #closeOutput()} and re-throw a caught {@link IOException}s as + * an {@link HttpRequestException} + * + * @return this request + * @throws HttpRequestException + */ + protected HttpRequest closeOutputQuietly() throws HttpRequestException { + try { + return closeOutput(); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Open output stream + * + * @return this request + * @throws IOException + */ + protected HttpRequest openOutput() throws IOException { + if (output != null) + return this; + getConnection().setDoOutput(true); + final String charset = getParam(getConnection().getRequestProperty(Header.HEADER_CONTENT_TYPE), + Header.PARAM_CHARSET); + output = new RequestOutputStream(getConnection().getOutputStream(), charset, bufferSize); + return this; + } + + /** + * Start part of a multipart + * + * @return this request + * @throws IOException + */ + protected HttpRequest startPart() throws IOException { + if (!multipart) { + multipart = true; + contentType(CONTENT_TYPE_MULTIPART).openOutput(); + output.write("--" + BOUNDARY + CRLF); + } else + output.write(CRLF + "--" + BOUNDARY + CRLF); + return this; + } + + /** + * Write part header + * + * @param name + * @param filename + * @return this request + * @throws IOException + */ + protected HttpRequest writePartHeader(final String name, final String filename) throws IOException { + return writePartHeader(name, filename, null); + } + + /** + * Write part header + * + * @param name + * @param filename + * @param contentType + * @return this request + * @throws IOException + */ + protected HttpRequest writePartHeader(final String name, final String filename, final String contentType) + throws IOException { + final StringBuilder partBuffer = new StringBuilder(); + partBuffer.append("form-data; name=\"").append(name); + if (filename != null) + partBuffer.append("\"; filename=\"").append(filename); + partBuffer.append('"'); + partHeader("Content-Disposition", partBuffer.toString()); + if (contentType != null) + partHeader(Header.HEADER_CONTENT_TYPE, contentType); + return send(CRLF); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param part + * @return this request + */ + public HttpRequest part(final String name, final String part) { + return part(name, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, final String part) throws HttpRequestException { + return part(name, filename, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param contentType + * value of the Content-Type part header + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, final String contentType, final String part) + throws HttpRequestException { + try { + startPart(); + writePartHeader(name, filename, contentType); + output.write(part); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return this; + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final Number part) throws HttpRequestException { + return part(name, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, final Number part) throws HttpRequestException { + return part(name, filename, part != null ? part.toString() : null); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final File part) throws HttpRequestException { + return part(name, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, final File part) throws HttpRequestException { + return part(name, filename, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param contentType + * value of the Content-Type part header + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, final String contentType, final File part) + throws HttpRequestException { + final InputStream stream; + try { + stream = new BufferedInputStream(new FileInputStream(part)); + incrementTotalSize(part.length()); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return part(name, filename, contentType, stream); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final InputStream part) throws HttpRequestException { + return part(name, null, null, part); + } + + /** + * Write part of a multipart request to the request body + * + * @param name + * @param filename + * @param contentType + * value of the Content-Type part header + * @param part + * @return this request + * @throws HttpRequestException + */ + public HttpRequest part(final String name, final String filename, final String contentType, final InputStream part) + throws HttpRequestException { + try { + startPart(); + writePartHeader(name, filename, contentType); + copy(part, output); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return this; + } + + /** + * Write a multipart header to the response body + * + * @param name + * @param value + * @return this request + * @throws HttpRequestException + */ + public HttpRequest partHeader(final String name, final String value) throws HttpRequestException { + return send(name).send(": ").send(value).send(CRLF); + } + + /** + * Write contents of file to request body + * + * @param input + * @return this request + * @throws HttpRequestException + */ + public HttpRequest send(final File input) throws HttpRequestException { + final InputStream stream; + try { + stream = new BufferedInputStream(new FileInputStream(input)); + incrementTotalSize(input.length()); + } catch (FileNotFoundException e) { + throw new HttpRequestException(e); + } + return send(stream); + } + + /** + * Write byte array to request body + * + * @param input + * @return this request + * @throws HttpRequestException + */ + public HttpRequest send(final byte[] input) throws HttpRequestException { + if (input != null) + incrementTotalSize(input.length); + return send(new ByteArrayInputStream(input)); + } + + /** + * Write stream to request body + *

+ * The given stream will be closed once sending completes + * + * @param input + * @return this request + * @throws HttpRequestException + */ + public HttpRequest send(final InputStream input) throws HttpRequestException { + try { + openOutput(); + copy(input, output); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return this; + } + + /** + * Write reader to request body + *

+ * The given reader will be closed once sending completes + * + * @param input + * @return this request + * @throws HttpRequestException + */ + public HttpRequest send(final Reader input) throws HttpRequestException { + try { + openOutput(); + } catch (IOException e) { + throw new HttpRequestException(e); + } + final Writer writer = new OutputStreamWriter(output, output.encoder.charset()); + return new FlushOperation(writer) { + + @Override + protected HttpRequest run() throws IOException { + return copy(input, writer); + } + }.call(); + } + + /** + * Write char sequence to request body + *

+ * The charset configured via {@link #contentType(String)} will be used and + * UTF-8 will be used if it is unset. + * + * @param value + * @return this request + * @throws HttpRequestException + */ + public HttpRequest send(final String value) throws HttpRequestException { + try { + openOutput(); + output.write(value.toString()); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return this; + } + + /** + * Create writer to request output stream + * + * @return writer + * @throws HttpRequestException + */ + public OutputStreamWriter writer() throws HttpRequestException { + try { + openOutput(); + return new OutputStreamWriter(output, output.encoder.charset()); + } catch (IOException e) { + throw new HttpRequestException(e); + } + } + + /** + * Write the values in the map as form data to the request body + *

+ * The pairs specified will be URL-encoded in UTF-8 and sent with the + * 'application/x-www-form-urlencoded' content-type + * + * @param values + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Map values) throws HttpRequestException { + return form(values, Header.CHARSET_UTF8); + } + + /** + * Write the key and value in the entry as form data to the request body + *

+ * The pair specified will be URL-encoded in UTF-8 and sent with the + * 'application/x-www-form-urlencoded' content-type + * + * @param entry + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Entry entry) throws HttpRequestException { + return form(entry, Header.CHARSET_UTF8); + } + + /** + * Write the key and value in the entry as form data to the request body + *

+ * The pair specified will be URL-encoded and sent with the + * 'application/x-www-form-urlencoded' content-type + * + * @param entry + * @param charset + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Entry entry, final String charset) throws HttpRequestException { + return form(entry.getKey(), entry.getValue(), charset); + } + + /** + * Write the name/value pair as form data to the request body + *

+ * The pair specified will be URL-encoded in UTF-8 and sent with the + * 'application/x-www-form-urlencoded' content-type + * + * @param name + * @param value + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Object name, final Object value) throws HttpRequestException { + return form(name, value, Header.CHARSET_UTF8); + } + + /** + * Write the name/value pair as form data to the request body + *

+ * The values specified will be URL-encoded and sent with the + * 'application/x-www-form-urlencoded' content-type + * + * @param name + * @param value + * @param charset + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Object name, final Object value, String charset) throws HttpRequestException { + final boolean first = !form; + if (first) { + contentType(Header.CONTENT_TYPE_FORM, charset); + form = true; + } + charset = getValidCharset(charset); + try { + openOutput(); + if (!first) + output.write('&'); + output.write(URLEncoder.encode(name.toString(), charset)); + output.write('='); + if (value != null) + output.write(URLEncoder.encode(value.toString(), charset)); + } catch (IOException e) { + throw new HttpRequestException(e); + } + return this; + } + + /** + * Write the values in the map as encoded form data to the request body + * + * @param values + * @param charset + * @return this request + * @throws HttpRequestException + */ + public HttpRequest form(final Map values, final String charset) throws HttpRequestException { + if (!values.isEmpty()) + for (Entry entry : values.entrySet()) + form(entry, charset); + return this; + } + + /** + * Configure HTTPS connection to trust all certificates + *

+ * This method does nothing if the current request is not a HTTPS request + * + * @return this request + * @throws HttpRequestException + */ + public HttpRequest trustAllCerts() throws HttpRequestException { + final HttpURLConnection connection = getConnection(); + if (connection instanceof HttpsURLConnection) + ((HttpsURLConnection) connection).setSSLSocketFactory(getTrustedFactory()); + return this; + } + + /** + * Configure HTTPS connection to trust all hosts using a custom + * {@link HostnameVerifier} that always returns true for each + * host verified + *

+ * This method does nothing if the current request is not a HTTPS request + * + * @return this request + */ + public HttpRequest trustAllHosts() { + final HttpURLConnection connection = getConnection(); + if (connection instanceof HttpsURLConnection) + ((HttpsURLConnection) connection).setHostnameVerifier(getTrustedVerifier()); + return this; + } + + /** + * Get the {@link URL} of this request's connection + * + * @return request URL + */ + public URL url() { + return getConnection().getURL(); + } + + /** + * Get the HTTP method of this request + * + * @return method + */ + public String method() { + return getConnection().getRequestMethod(); + } + + /** + * Configure an HTTP proxy on this connection. Use { + * {@link #proxyBasic(String, String)} if this proxy requires basic + * authentication. + * + * @param proxyHost + * @param proxyPort + * @return this request + */ + public HttpRequest useProxy(final String proxyHost, final int proxyPort) { + if (connection != null) + throw new IllegalStateException( + "The connection has already been created. This method must be called before reading or writing to the request."); + + this.httpProxyHost = proxyHost; + this.httpProxyPort = proxyPort; + return this; + } + + /** + * Set whether or not the underlying connection should follow redirects in + * the response. + * + * @param followRedirects + * - true fo follow redirects, false to not. + * @return this request + */ + public HttpRequest followRedirects(final boolean followRedirects) { + getConnection().setInstanceFollowRedirects(followRedirects); + return this; + } } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/http/TokenQueue.java b/blade-kit/src/main/java/blade/kit/http/TokenQueue.java new file mode 100644 index 000000000..2194c3820 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/http/TokenQueue.java @@ -0,0 +1,394 @@ +package blade.kit.http; + +import blade.kit.Assert; + +/** + * A character queue with parsing helpers. + * + * @author Jonathan Hedley + */ +public class TokenQueue { + private String queue; + private int pos = 0; + + private static final char ESC = '\\'; // escape char for chomp balanced. + + /** + Create a new TokenQueue. + @param data string of data to back queue. + */ + public TokenQueue(String data) { + Assert.notNull(data); + queue = data; + } + + /** + * Is the queue empty? + * @return true if no data left in queue. + */ + public boolean isEmpty() { + return remainingLength() == 0; + } + + private int remainingLength() { + return queue.length() - pos; + } + + /** + * Retrieves but does not remove the first character from the queue. + * @return First character, or 0 if empty. + */ + public char peek() { + return isEmpty() ? 0 : queue.charAt(pos); + } + + /** + Add a character to the start of the queue (will be the next character retrieved). + @param c character to add + */ + public void addFirst(Character c) { + addFirst(c.toString()); + } + + /** + Add a string to the start of the queue. + @param seq string to add. + */ + public void addFirst(String seq) { + // not very performant, but an edge case + queue = seq + queue.substring(pos); + pos = 0; + } + + /** + * Tests if the next characters on the queue match the sequence. Case insensitive. + * @param seq String to check queue for. + * @return true if the next characters match. + */ + public boolean matches(String seq) { + return queue.regionMatches(true, pos, seq, 0, seq.length()); + } + + /** + * Case sensitive match test. + * @param seq string to case sensitively check for + * @return true if matched, false if not + */ + public boolean matchesCS(String seq) { + return queue.startsWith(seq, pos); + } + + + /** + Tests if the next characters match any of the sequences. Case insensitive. + @param seq list of strings to case insensitively check for + @return true of any matched, false if none did + */ + public boolean matchesAny(String... seq) { + for (String s : seq) { + if (matches(s)) + return true; + } + return false; + } + + public boolean matchesAny(char... seq) { + if (isEmpty()) + return false; + + for (char c: seq) { + if (queue.charAt(pos) == c) + return true; + } + return false; + } + + public boolean matchesStartTag() { + // micro opt for matching "= 2 && queue.charAt(pos) == '<' && Character.isLetter(queue.charAt(pos+1))); + } + + /** + * Tests if the queue matches the sequence (as with match), and if they do, removes the matched string from the + * queue. + * @param seq String to search for, and if found, remove from queue. + * @return true if found and removed, false if not found. + */ + public boolean matchChomp(String seq) { + if (matches(seq)) { + pos += seq.length(); + return true; + } else { + return false; + } + } + + /** + Tests if queue starts with a whitespace character. + @return if starts with whitespace + */ + public boolean matchesWhitespace() { + return !isEmpty() && Character.isWhitespace(queue.charAt(pos)); + } + + /** + Test if the queue matches a word character (letter or digit). + @return if matches a word character + */ + public boolean matchesWord() { + return !isEmpty() && Character.isLetterOrDigit(queue.charAt(pos)); + } + + /** + * Drops the next character off the queue. + */ + public void advance() { + if (!isEmpty()) pos++; + } + + /** + * Consume one character off queue. + * @return first character on queue. + */ + public char consume() { + return queue.charAt(pos++); + } + + /** + * Consumes the supplied sequence of the queue. If the queue does not start with the supplied sequence, will + * throw an illegal state exception -- but you should be running match() against that condition. +

+ Case insensitive. + * @param seq sequence to remove from head of queue. + */ + public void consume(String seq) { + if (!matches(seq)) + throw new IllegalStateException("Queue did not match expected sequence"); + int len = seq.length(); + if (len > remainingLength()) + throw new IllegalStateException("Queue not long enough to consume sequence"); + + pos += len; + } + + /** + * Pulls a string off the queue, up to but exclusive of the match sequence, or to the queue running out. + * @param seq String to end on (and not include in return, but leave on queue). Case sensitive. + * @return The matched data consumed from queue. + */ + public String consumeTo(String seq) { + int offset = queue.indexOf(seq, pos); + if (offset != -1) { + String consumed = queue.substring(pos, offset); + pos += consumed.length(); + return consumed; + } else { + return remainder(); + } + } + + public String consumeToIgnoreCase(String seq) { + int start = pos; + String first = seq.substring(0, 1); + boolean canScan = first.toLowerCase().equals(first.toUpperCase()); // if first is not cased, use index of + while (!isEmpty()) { + if (matches(seq)) + break; + + if (canScan) { + int skip = queue.indexOf(first, pos) - pos; + if (skip == 0) // this char is the skip char, but not match, so force advance of pos + pos++; + else if (skip < 0) // no chance of finding, grab to end + pos = queue.length(); + else + pos += skip; + } + else + pos++; + } + + return queue.substring(start, pos); + } + + /** + Consumes to the first sequence provided, or to the end of the queue. Leaves the terminator on the queue. + @param seq any number of terminators to consume to. Case insensitive. + @return consumed string + */ + // todo: method name. not good that consumeTo cares for case, and consume to any doesn't. And the only use for this + // is is a case sensitive time... + public String consumeToAny(String... seq) { + int start = pos; + while (!isEmpty() && !matchesAny(seq)) { + pos++; + } + + return queue.substring(start, pos); + } + + /** + * Pulls a string off the queue (like consumeTo), and then pulls off the matched string (but does not return it). + *

+ * If the queue runs out of characters before finding the seq, will return as much as it can (and queue will go + * isEmpty() == true). + * @param seq String to match up to, and not include in return, and to pull off queue. Case sensitive. + * @return Data matched from queue. + */ + public String chompTo(String seq) { + String data = consumeTo(seq); + matchChomp(seq); + return data; + } + + public String chompToIgnoreCase(String seq) { + String data = consumeToIgnoreCase(seq); // case insensitive scan + matchChomp(seq); + return data; + } + + /** + * Pulls a balanced string off the queue. E.g. if queue is "(one (two) three) four", (,) will return "one (two) three", + * and leave " four" on the queue. Unbalanced openers and closers can be escaped (with \). Those escapes will be left + * in the returned string, which is suitable for regexes (where we need to preserve the escape), but unsuitable for + * contains text strings; use unescape for that. + * @param open opener + * @param close closer + * @return data matched from the queue + */ + public String chompBalanced(char open, char close) { + int start = -1; + int end = -1; + int depth = 0; + char last = 0; + + do { + if (isEmpty()) break; + Character c = consume(); + if (last == 0 || last != ESC) { + if (c.equals(open)) { + depth++; + if (start == -1) + start = pos; + } + else if (c.equals(close)) + depth--; + } + + if (depth > 0 && last != 0) + end = pos; // don't include the outer match pair in the return + last = c; + } while (depth > 0); + return (end >= 0) ? queue.substring(start, end) : ""; + } + + /** + * Unescaped a \ escaped string. + * @param in backslash escaped string + * @return unescaped string + */ + public static String unescape(String in) { + StringBuilder out = new StringBuilder(); + char last = 0; + for (char c : in.toCharArray()) { + if (c == ESC) { + if (last != 0 && last == ESC) + out.append(c); + } + else + out.append(c); + last = c; + } + return out.toString(); + } + + /** + * Pulls the next run of whitespace characters of the queue. + * @return Whether consuming whitespace or not + */ + public boolean consumeWhitespace() { + boolean seen = false; + while (matchesWhitespace()) { + pos++; + seen = true; + } + return seen; + } + + /** + * Retrieves the next run of word type (letter or digit) off the queue. + * @return String of word characters from queue, or empty string if none. + */ + public String consumeWord() { + int start = pos; + while (matchesWord()) + pos++; + return queue.substring(start, pos); + } + + /** + * Consume an tag name off the queue (word or :, _, -) + * + * @return tag name + */ + public String consumeTagName() { + int start = pos; + while (!isEmpty() && (matchesWord() || matchesAny(':', '_', '-'))) + pos++; + + return queue.substring(start, pos); + } + + /** + * Consume a CSS element selector (tag name, but | instead of : for namespaces, to not conflict with :pseudo selects). + * + * @return tag name + */ + public String consumeElementSelector() { + int start = pos; + while (!isEmpty() && (matchesWord() || matchesAny('|', '_', '-'))) + pos++; + + return queue.substring(start, pos); + } + + /** + Consume a CSS identifier (ID or class) off the queue (letter, digit, -, _) + http://www.w3.org/TR/CSS2/syndata.html#value-def-identifier + @return identifier + */ + public String consumeCssIdentifier() { + int start = pos; + while (!isEmpty() && (matchesWord() || matchesAny('-', '_'))) + pos++; + + return queue.substring(start, pos); + } + + /** + Consume an attribute key off the queue (letter, digit, -, _, :") + @return attribute key + */ + public String consumeAttributeKey() { + int start = pos; + while (!isEmpty() && (matchesWord() || matchesAny('-', '_', ':'))) + pos++; + + return queue.substring(start, pos); + } + + /** + Consume and return whatever is left on the queue. + @return remained of queue. + */ + public String remainder() { + final String remainder = queue.substring(pos, queue.length()); + pos = queue.length(); + return remainder; + } + + @Override + public String toString() { + return queue.substring(pos); + } +} \ No newline at end of file diff --git a/blade-oauth2/pom.xml b/blade-oauth2/pom.xml index 841adf97e..d5dccffb5 100644 --- a/blade-oauth2/pom.xml +++ b/blade-oauth2/pom.xml @@ -9,7 +9,7 @@ 1.0 blade-oauth2 - 1.0.2 + 1.0.3 blade-oauth2 https://github.com/biezhi/blade/tree/master/blade-oauth2 diff --git a/pom.xml b/pom.xml index 20cb34a13..03cbabd17 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.5.1 + 1.5.2-alpha 4.12 From 67e797d253309cdd5b53df37f4b43236857d47a6 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 21:55:20 +0800 Subject: [PATCH 392/545] add route group --- blade-core/src/main/java/com/blade/Blade.java | 12 +++ .../main/java/com/blade/route/RouteGroup.java | 76 +++++++++++++++++++ .../main/java/com/blade/route/Routers.java | 13 ++++ 3 files changed, 101 insertions(+) create mode 100644 blade-core/src/main/java/com/blade/route/RouteGroup.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index c7b0d5232..45c54a070 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -31,6 +31,7 @@ import com.blade.render.Render; import com.blade.route.Route; import com.blade.route.RouteException; +import com.blade.route.RouteGroup; import com.blade.route.RouteHandler; import com.blade.route.Routers; import com.blade.server.Server; @@ -330,6 +331,7 @@ public Blade route(String path, Class clazz, String method, HttpMethod httpMe * @return return blade */ public Blade routes(List routes){ + Assert.notEmpty(routes, "Routes not is empty!"); routers.addRoutes(routes); return this; } @@ -406,6 +408,16 @@ public Blade any(String path, RouteHandler handler){ return this; } + /** + * Route Group. e.g blade.group('/users').get().post() + * @param g + * @return + */ + public RouteGroup group(String prefix){ + Assert.notNull(prefix, "Route group prefix not is null"); + return new RouteGroup(this, prefix); + } + /** * Register a pre routing request interceptor * diff --git a/blade-core/src/main/java/com/blade/route/RouteGroup.java b/blade-core/src/main/java/com/blade/route/RouteGroup.java new file mode 100644 index 000000000..75df3684b --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/RouteGroup.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import com.blade.Blade; + +/** + * Route Group. + * + * @author biezhi + * @since 1.0 + */ +public class RouteGroup { + + private Blade blade; + private String prefix; + + public RouteGroup(Blade blade, String prefix) { + this.blade = blade; + this.prefix = prefix; + } + + public RouteGroup get(RouteHandler routeHandler){ + blade.get(prefix, routeHandler); + return this; + } + + public RouteGroup get(String path, RouteHandler routeHandler){ + blade.get(prefix + path, routeHandler); + return this; + } + + public RouteGroup post(RouteHandler routeHandler){ + blade.post(prefix, routeHandler); + return this; + } + + public RouteGroup post(String path, RouteHandler routeHandler){ + blade.post(prefix + path, routeHandler); + return this; + } + + public RouteGroup delete(RouteHandler routeHandler){ + blade.delete(prefix, routeHandler); + return this; + } + + public RouteGroup delete(String path, RouteHandler routeHandler){ + blade.delete(prefix + path, routeHandler); + return this; + } + + public RouteGroup put(RouteHandler routeHandler){ + blade.put(prefix, routeHandler); + return this; + } + + public RouteGroup put(String path, RouteHandler routeHandler){ + blade.put(prefix + path, routeHandler); + return this; + } + +} diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 4bca4328b..0247a9dc8 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -136,6 +136,10 @@ public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) { public void route(String path, Object target, String methodName) { try { + Assert.notNull(path, "Route path not is null!"); + Assert.notNull(target, "Target Controller not is null!"); + Assert.notNull(methodName, "Method name not is null"); + Method method = target.getClass().getMethod(methodName, Request.class, Response.class); addRoute(HttpMethod.ALL, path, target, method); } catch (NoSuchMethodException e) { @@ -147,6 +151,10 @@ public void route(String path, Object target, String methodName) { public void route(String path, Class clazz, String methodName) { + Assert.notNull(path, "Route path not is null!"); + Assert.notNull(clazz, "Class Type not is null!"); + Assert.notNull(methodName, "Method name not is null"); + HttpMethod httpMethod = HttpMethod.ALL; if(methodName.indexOf(":") != -1){ String[] methodArr = methodName.split(":"); @@ -178,6 +186,11 @@ public void route(String path, Class clazz, String methodName) { public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) { try { + Assert.notNull(path, "Route path not is null!"); + Assert.notNull(clazz, "Class Type not is null!"); + Assert.notNull(methodName, "Method name not is null"); + Assert.notNull(httpMethod, "Request Method not is null"); + Object controller = ioc.getBean(clazz); if(null == controller){ ioc.addBean(clazz); From 4d9896696e1ec84769dd57e1985a99dc0b2ae692 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 11 Feb 2016 22:09:26 +0800 Subject: [PATCH 393/545] add default conf file --- blade-core/src/main/java/com/blade/Blade.java | 10 +++ blade-core/src/main/java/com/blade/Const.java | 13 ++++ .../java/com/blade/loader/BladeConfig.java | 12 +-- .../java/com/blade/loader/Configurator.java | 75 ++++++++----------- .../java/com/blade/loader/RouteLoader.java | 4 +- 5 files changed, 63 insertions(+), 51 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 45c54a070..463e3b82f 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -784,6 +784,16 @@ public T plugin(Class plugin){ return (T) object; } + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage controller package name + * @return return blade + */ + public Blade routeConf(String basePackage) { + return routeConf(basePackage, "route.conf"); + } + /** * Registration of a configuration file, e.g: "com.xxx.route","route.conf" * diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index c468bf22d..7353c5b23 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -49,4 +49,17 @@ public interface Const { * Request ThreadPoll context key */ String BLADE_EXECUTOR = "blade-req-executor"; + + String BLADE_ROUTE = "blade.route"; + String BLADE_INTERCEPTOR = "blade.interceptor"; + String BLADE_IOC = "blade.ioc"; + String BLADE_PREFIX = "blade.prefix"; + String BLADE_SUFFIX = "blade.suffix"; + String BLADE_FILTER_FOLDER = "blade.filter_folder"; + String BLADE_ENCODING = "blade.encoding"; + String BLADE_VIEW_404 = "blade.view404"; + String BLADE_VIEW_500 = "blade.view500"; + String BLADE_DEV = "blade.dev"; + String BLADE_ENABLE_XSS = "blade.enableXSS"; + } diff --git a/blade-core/src/main/java/com/blade/loader/BladeConfig.java b/blade-core/src/main/java/com/blade/loader/BladeConfig.java index de4877704..3ed961c72 100644 --- a/blade-core/src/main/java/com/blade/loader/BladeConfig.java +++ b/blade-core/src/main/java/com/blade/loader/BladeConfig.java @@ -16,10 +16,10 @@ package com.blade.loader; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; -import blade.kit.CollectionKit; import blade.kit.PatternKit; /** @@ -32,16 +32,16 @@ public class BladeConfig { // Store all variables - private Map configMap = CollectionKit.newHashMap(); + private Map configMap = Collections.emptyMap(); // Storage of all routing packets - private List routePackages = CollectionKit.newArrayList(); + private List routePackages = Collections.emptyList(); // Store all IOC packages - private List iocPackages = CollectionKit.newArrayList(); + private List iocPackages = Collections.emptyList(); // Store all filter directories - private List staticFolders = CollectionKit.newArrayList(); + private List staticFolders = Collections.emptyList(); // Base package private String basePackage; @@ -53,7 +53,7 @@ public class BladeConfig { private String encoding = "utf-8"; // View prefix - private String viewPrefix = "/WEB-INF/"; + private String viewPrefix = "/WEB-INF/views/"; // View suffix private String viewSuffix = ".jsp"; diff --git a/blade-core/src/main/java/com/blade/loader/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java index 00e81b86b..5fcb8c01e 100644 --- a/blade-core/src/main/java/com/blade/loader/Configurator.java +++ b/blade-core/src/main/java/com/blade/loader/Configurator.java @@ -17,97 +17,86 @@ import java.util.Map; +import com.blade.Const; + import blade.kit.StringKit; /** * Blade configuration * - * @author biezhi - * @since 1.0 + * @author biezhi + * @since 1.0 */ public class Configurator { - // Configuration object + // Configuration object private BladeConfig bladeConfig; - + // Configuration Map private Map configMap; - - public Configurator(BladeConfig bladeConfig, - Map configMap) { + + public Configurator(BladeConfig bladeConfig, Map configMap) { this.bladeConfig = bladeConfig; this.configMap = configMap; } - - private static final String BLADE_ROUTE = "blade.route"; - private static final String BLADE_INTERCEPTOR = "blade.interceptor"; - private static final String BLADE_IOC = "blade.ioc"; - private static final String BLADE_PREFIX = "blade.prefix"; - private static final String BLADE_SUFFIX = "blade.suffix"; - private static final String BLADE_FILTER_FOLDER = "blade.filter_folder"; - private static final String BLADE_ENCODING = "blade.encoding"; - private static final String BLADE_VIEW_404 = "blade.view404"; - private static final String BLADE_VIEW_500 = "blade.view500"; - private static final String BLADE_DEV = "blade.dev"; - private static final String BLADE_ENABLEXSS = "blade.enableXSS"; - + public void run() { - + if (null != configMap && configMap.size() > 0) { - + bladeConfig.setConfigMap(configMap); - String route = configMap.get(BLADE_ROUTE); - String interceptor = configMap.get(BLADE_INTERCEPTOR); - String ioc = configMap.get(BLADE_IOC); - String prefix = configMap.get(BLADE_PREFIX); - String suffix = configMap.get(BLADE_SUFFIX); - String filter_folder = configMap.get(BLADE_FILTER_FOLDER); - String encoding = configMap.get(BLADE_ENCODING); - String view404 = configMap.get(BLADE_VIEW_404); - String view500 = configMap.get(BLADE_VIEW_500); - String dev = configMap.get(BLADE_DEV); - String xss = configMap.get(BLADE_ENABLEXSS); - + String route = configMap.get(Const.BLADE_ROUTE); + String interceptor = configMap.get(Const.BLADE_INTERCEPTOR); + String ioc = configMap.get(Const.BLADE_IOC); + String prefix = configMap.get(Const.BLADE_PREFIX); + String suffix = configMap.get(Const.BLADE_SUFFIX); + String filter_folder = configMap.get(Const.BLADE_FILTER_FOLDER); + String encoding = configMap.get(Const.BLADE_ENCODING); + String view404 = configMap.get(Const.BLADE_VIEW_404); + String view500 = configMap.get(Const.BLADE_VIEW_500); + String dev = configMap.get(Const.BLADE_DEV); + String xss = configMap.get(Const.BLADE_ENABLE_XSS); + if (StringKit.isNotBlank(route)) { String[] blade_routes = StringKit.split(route, ","); bladeConfig.setRoutePackages(blade_routes); } - + if (StringKit.isNotBlank(filter_folder)) { String[] blade_filter_folders = StringKit.split(filter_folder, ","); bladeConfig.setStaticFolders(blade_filter_folders); } - + if (StringKit.isNotBlank(interceptor)) { bladeConfig.setInterceptorPackage(interceptor); } - + if (StringKit.isNotBlank(ioc)) { String[] blade_iocs = StringKit.split(ioc, ","); bladeConfig.setIocPackages(blade_iocs); } - + if (StringKit.isNotBlank(prefix)) { bladeConfig.setViewPrefix(prefix); } - + if (StringKit.isNotBlank(suffix)) { bladeConfig.setViewSuffix(suffix); } - + if (StringKit.isNotBlank(encoding)) { bladeConfig.setEncoding(encoding); } - + if (StringKit.isNotBlank(view404)) { bladeConfig.setView404(view404); } - + if (StringKit.isNotBlank(view500)) { bladeConfig.setView500(view500); } - + if (StringKit.isNotBlank(dev)) { Boolean isDev = Boolean.parseBoolean(dev); bladeConfig.setDev(isDev); diff --git a/blade-core/src/main/java/com/blade/loader/RouteLoader.java b/blade-core/src/main/java/com/blade/loader/RouteLoader.java index 00932075d..327fc5b21 100644 --- a/blade-core/src/main/java/com/blade/loader/RouteLoader.java +++ b/blade-core/src/main/java/com/blade/loader/RouteLoader.java @@ -30,5 +30,5 @@ public interface RouteLoader { List load() throws ParseException, RouteException; - -} + +} \ No newline at end of file From d5215f32c97db92cc3a1deb08c0ce54658ba43e2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 14 Feb 2016 14:27:58 +0800 Subject: [PATCH 394/545] removing the configuration directory prefixes and suffixes, logging and modify slf4j. --- blade-core/pom.xml | 7 +- blade-core/src/main/java/com/blade/Blade.java | 55 +---- blade-core/src/main/java/com/blade/Const.java | 2 +- .../main/java/com/blade/IocApplication.java | 8 +- .../blade/context/BladeContextListener.java | 8 +- .../main/java/com/blade/ioc/SampleIoc.java | 14 +- .../java/com/blade/render/BeetlRender.java | 121 ---------- .../java/com/blade/render/JetbrickRender.java | 164 ------------- .../java/com/blade/render/VelocityRender.java | 144 ------------ .../java/com/blade/render/package-info.java | 4 - .../main/java/com/blade/route/Routers.java | 22 +- .../main/java/com/blade/server/Server.java | 8 +- .../com/blade/verify/CSRFTokenManager.java | 8 +- .../template/JspEngine.java} | 25 +- .../template}/ModelAndView.java | 2 +- .../template}/RenderException.java | 2 +- .../template/TemplteEngine.java} | 4 +- .../com/blade/view/template/package-info.java | 4 + .../java/com/blade/web/AppAsyncListener.java | 34 --- .../com/blade/web/AsynRequestHandler.java | 219 ------------------ .../main/java/com/blade/web/BladeBanner.java | 22 ++ .../java/com/blade/web/DispatcherServlet.java | 23 +- .../com/blade/web/SyncRequestHandler.java | 14 +- .../java/com/blade/web/http/Response.java | 2 +- .../web/http/wrapper/ServletResponse.java | 8 +- 25 files changed, 116 insertions(+), 808 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/render/BeetlRender.java delete mode 100644 blade-core/src/main/java/com/blade/render/JetbrickRender.java delete mode 100644 blade-core/src/main/java/com/blade/render/VelocityRender.java delete mode 100644 blade-core/src/main/java/com/blade/render/package-info.java rename blade-core/src/main/java/com/blade/{render/JspRender.java => view/template/JspEngine.java} (75%) rename blade-core/src/main/java/com/blade/{render => view/template}/ModelAndView.java (98%) rename blade-core/src/main/java/com/blade/{render => view/template}/RenderException.java (93%) rename blade-core/src/main/java/com/blade/{render/Render.java => view/template/TemplteEngine.java} (90%) create mode 100644 blade-core/src/main/java/com/blade/view/template/package-info.java delete mode 100644 blade-core/src/main/java/com/blade/web/AppAsyncListener.java delete mode 100644 blade-core/src/main/java/com/blade/web/AsynRequestHandler.java create mode 100644 blade-core/src/main/java/com/blade/web/BladeBanner.java diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 168865ba2..ac72c7853 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -31,10 +31,9 @@ 1.2.9-alpha - com.bladejava - blade-aop - 1.0.0 - provided + org.slf4j + slf4j-api + 1.7.16 javax.servlet diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 463e3b82f..f9302ec09 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -27,14 +27,14 @@ import com.blade.loader.BladeConfig; import com.blade.loader.Configurator; import com.blade.plugin.Plugin; -import com.blade.render.JspRender; -import com.blade.render.Render; import com.blade.route.Route; import com.blade.route.RouteException; import com.blade.route.RouteGroup; import com.blade.route.RouteHandler; import com.blade.route.Routers; import com.blade.server.Server; +import com.blade.view.template.JspEngine; +import com.blade.view.template.TemplteEngine; import com.blade.web.http.HttpMethod; import blade.kit.Assert; @@ -83,7 +83,7 @@ public class Blade { /** * default render is jspRender */ - private Render render = null; + private TemplteEngine render = null; /** * manage route @@ -105,7 +105,7 @@ private Blade() { this.ioc = new SampleIoc(); this.iocApplication = new IocApplication(ioc); this.routers = new Routers(ioc); - this.render = new JspRender(); + this.render = new JspEngine(); } public static final class BladeHolder { @@ -448,55 +448,12 @@ public Blade after(String path, RouteHandler handler){ * @param render Render engine object * @return return blade */ - public Blade viewEngin(Render render) { + public Blade viewEngin(TemplteEngine render) { Assert.notNull(render); this.render = render; return this; } - /** - * Setting default view prefix, default is WEBROOT/WEB-INF/ - * - * @param prefix views path, e.g:/WEB-INF/views/ - * @return return blade - */ - public Blade viewPrefix(final String prefix) { - Assert.notBlank(prefix); - if(prefix.startsWith("/")){ - config.setViewPrefix(prefix); - } - return this; - } - - /** - * Setting view default suffix, default is .jsp - * - * @param suffix view suffix, e.g:.html .vm - * @return return blade - */ - public Blade viewSuffix(final String suffix) { - Assert.notBlank(suffix); - if(suffix.startsWith(".")){ - config.setViewSuffix(suffix); - } - return this; - } - - /** - * Also set the view's directory and view the suffix name - * - * @param viewPath views path, e.g:/WEB-INF/views - * @param viewExt view suffix, e.g:.html .vm - * @return return blade - */ - public Blade view(final String viewPath, final String viewExt) { - Assert.notBlank(viewPath); - Assert.notBlank(viewExt); - viewPrefix(viewPath); - viewSuffix(viewExt); - return this; - } - /** * Setting the frame static file folder * @@ -756,7 +713,7 @@ public Bootstrap bootstrap(){ /** * @return Return current render engine */ - public Render render() { + public TemplteEngine render() { return this.render; } diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 7353c5b23..56d97c5ab 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * Current version */ - String BLADE_VERSION = "1.5.2-alpha"; + String BLADE_VERSION = "1.6.0-alpha"; /** * Server 500 error HTML diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/IocApplication.java index 8b0e56ab0..1d5a53602 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/IocApplication.java @@ -19,10 +19,12 @@ import java.util.List; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.ioc.Ioc; import com.blade.plugin.Plugin; -import blade.kit.log.Logger; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; @@ -34,7 +36,7 @@ */ public class IocApplication { - private static final Logger LOGGER = Logger.getLogger(IocApplication.class); + private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); /** * Ioc Container @@ -81,7 +83,7 @@ public void init(String[] iocs, Bootstrap bootstrap){ Set names = ioc.getBeanNames(); for(String name : names){ - LOGGER.info("Add Object:" + name + "=" + ioc.getBean(name)); + LOGGER.info("Add Object:{}={}", name, ioc.getBean(name)); } } diff --git a/blade-core/src/main/java/com/blade/context/BladeContextListener.java b/blade-core/src/main/java/com/blade/context/BladeContextListener.java index 6ade4d668..83761b3d7 100644 --- a/blade-core/src/main/java/com/blade/context/BladeContextListener.java +++ b/blade-core/src/main/java/com/blade/context/BladeContextListener.java @@ -4,15 +4,17 @@ import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; -import blade.kit.TaskKit; -import blade.kit.log.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.blade.Blade; +import blade.kit.TaskKit; + @WebListener public class BladeContextListener implements ServletContextListener { - private static final Logger LOGGER = Logger.getLogger(BladeContextListener.class); + private static final Logger LOGGER = LoggerFactory.getLogger(BladeContextListener.class); @Override public void contextInitialized(final ServletContextEvent sce) { diff --git a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java index 1a59d71f4..601de6258 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java @@ -22,10 +22,12 @@ import java.util.Map; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.ioc.loader.IocLoader; import blade.kit.Assert; -import blade.kit.log.Logger; /** * The default IOC container implementation @@ -35,7 +37,7 @@ */ public class SampleIoc implements Ioc { - private static final Logger LOGGER = Logger.getLogger(Ioc.class); + private static final Logger LOGGER = LoggerFactory.getLogger(Ioc.class); private final Map pool = new HashMap(); @@ -89,10 +91,10 @@ public void addBean(String name, BeanDefine beanDefine) { Assert.notNull(name); Assert.notNull(beanDefine); - LOGGER.debug("addBean: %s", name); + LOGGER.debug("addBean: {}", name); if (pool.put(name, beanDefine) != null) { - LOGGER.warn("Duplicated Bean: %s", name); + LOGGER.warn("Duplicated Bean: {}", name); } } @@ -123,12 +125,12 @@ public void addBean(String name, Class beanClass, boolean singleton) { Assert.isFalse(beanClass.isInterface(), "Must not be interface: %s", beanClass.getName()); Assert.isFalse(Modifier.isAbstract(beanClass.getModifiers()), "Must not be abstract class: %s", beanClass.getName()); - LOGGER.debug("addBean: %s", name, beanClass.getName()); + LOGGER.debug("addBean: {}={}", name, beanClass.getName()); BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton); if (pool.put(name, beanDefine) != null) { - LOGGER.warn("Duplicated Bean: %s", name); + LOGGER.warn("Duplicated Bean: {}", name); } // add interface diff --git a/blade-core/src/main/java/com/blade/render/BeetlRender.java b/blade-core/src/main/java/com/blade/render/BeetlRender.java deleted file mode 100644 index e12cdaf11..000000000 --- a/blade-core/src/main/java/com/blade/render/BeetlRender.java +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.render; - -import java.io.IOException; -import java.io.Writer; -import java.util.Map; -import java.util.Set; - -import org.beetl.core.Configuration; -import org.beetl.core.GroupTemplate; -import org.beetl.core.Template; -import org.beetl.core.exception.BeetlException; -import org.beetl.core.resource.WebAppResourceLoader; - -import com.blade.Blade; -import com.blade.context.BladeWebContext; -import com.blade.web.http.Request; -import com.blade.web.http.wrapper.Session; - -import blade.kit.log.Logger; - -/** - * Beetl Render - * - * @author biezhi - * @since 1.0 - */ -public class BeetlRender implements Render { - - private static final Logger LOGGER = Logger.getLogger(BeetlRender.class); - - /** - * Beetl GroupTemplate Object - */ - private GroupTemplate groupTemplate = null; - - private String webRoot; - - public BeetlRender() { - try { - Blade blade = Blade.me(); - this.webRoot = blade.webRoot(); - WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); - resourceLoader.setAutoCheck(true); - resourceLoader.setRoot(this.webRoot); - Configuration cfg = Configuration.defaultConfiguration(); - groupTemplate = new GroupTemplate(resourceLoader, cfg); - } catch (IOException e) { - LOGGER.error(e); - } - } - - public BeetlRender(GroupTemplate groupTemplate) { - this.groupTemplate = groupTemplate; - } - - public BeetlRender(Configuration configuration) { - try { - Blade blade = Blade.me(); - this.webRoot = blade.webRoot(); - WebAppResourceLoader resourceLoader = new WebAppResourceLoader(); - resourceLoader.setAutoCheck(true); - resourceLoader.setRoot(this.webRoot); - Configuration cfg = Configuration.defaultConfiguration(); - groupTemplate = new GroupTemplate(resourceLoader, cfg); - groupTemplate.setConf(configuration); - } catch (IOException e) { - LOGGER.error(e); - } - } - - @Override - public void render(ModelAndView modelAndView, Writer writer) throws RenderException { - Request request = BladeWebContext.request(); - Session session = request.session(); - - Template template = groupTemplate.getTemplate(modelAndView.getView()); - - Map context = modelAndView.getModel(); - if(null != context && context.size() > 0){ - Set keys = context.keySet(); - for(String key : keys){ - template.binding(key, context.get(key)); - } - } - - Set attrs = request.attributes(); - if(null != attrs && attrs.size() > 0){ - for(String attr : attrs){ - template.binding(attr, request.attribute(attr)); - } - } - - Set session_attrs = session.attributes(); - if(null != session_attrs && session_attrs.size() > 0){ - for(String attr : session_attrs){ - template.binding(attr, session.attribute(attr)); - } - } - try { - template.renderTo(writer); - } catch (BeetlException e) { - e.printStackTrace(); - LOGGER.error(e); - } - } -} diff --git a/blade-core/src/main/java/com/blade/render/JetbrickRender.java b/blade-core/src/main/java/com/blade/render/JetbrickRender.java deleted file mode 100644 index b99a7781f..000000000 --- a/blade-core/src/main/java/com/blade/render/JetbrickRender.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.render; - -import java.io.IOException; -import java.io.Writer; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import com.blade.Blade; -import com.blade.context.BladeWebContext; -import com.blade.render.ModelAndView; -import com.blade.render.Render; -import com.blade.web.http.Request; -import com.blade.web.http.wrapper.Session; - -import blade.kit.log.Logger; -import jetbrick.template.JetEngine; -import jetbrick.template.JetTemplate; - -/** - * Velocity Render - * - * @author biezhi - * @since 1.0 - */ -public class JetbrickRender implements Render { - - private static final Logger LOGGER = Logger.getLogger(JetbrickRender.class); - - private JetEngine jetEngine; - - private Properties config; - - private String webRoot; - - public JetbrickRender() { - Blade blade = Blade.me(); - this.webRoot = blade.webRoot(); - config = new Properties(); - config.put("jetx.input.encoding", blade.encoding()); - config.put("jetx.output.encoding", blade.encoding()); - config.put("jetx.template.suffix", ".html"); - config.put("jetx.template.loaders", "jetbrick.template.loader.FileSystemResourceLoader"); - jetEngine = JetEngine.create(config); - } - - /** - * @return return JetEngine - */ - public JetEngine getJetEngine(){ - return jetEngine; - } - - /** - * clean config - */ - public void clean(){ - if(null != config){ - config.clear(); - } - } - - /** - * add config - * - * @param key key - * @param value value - */ - public void put(String key, Object value){ - if(null == config){ - config = new Properties(); - } - config.put(key, value); - } - - /** - * Construct a JetEngine engine based on the configuration file - * - * @param configLocation configuration file path for ClassPath - * @throws IOException io exception - */ - public JetbrickRender(String configLocation) throws IOException { - Blade blade = Blade.me(); - this.webRoot = blade.webRoot(); - jetEngine = JetEngine.create(configLocation); - } - - /** - * According to the construction of a JetEngine engine - * - * @param config properties configuration - */ - public JetbrickRender(Properties config) { - Blade blade = Blade.me(); - this.webRoot = blade.webRoot(); - this.config = config; - jetEngine = JetEngine.create(this.config); - } - - /** - * Manually constructed JetEngine engine - * - * @param jetEngine jetEngine engine object - */ - public JetbrickRender(JetEngine jetEngine) { - this.jetEngine = jetEngine; - } - - /** - * @return return config object - */ - public Properties getConfig() { - return config; - } - - @Override - public void render(ModelAndView modelAndView, Writer writer) { - Request request = BladeWebContext.request(); - Session session = request.session(); - - String view = webRoot + modelAndView.getView(); - - JetTemplate template = jetEngine.getTemplate(view); - - Map context = modelAndView.getModel(); - - Set attrs = request.attributes(); - if(null != attrs && attrs.size() > 0){ - for(String attr : attrs){ - context.put(attr, request.attribute(attr)); - } - } - - Set session_attrs = session.attributes(); - if(null != session_attrs && session_attrs.size() > 0){ - for(String attr : session_attrs){ - context.put(attr, session.attribute(attr)); - } - } - - try { - template.render(context, writer); - } catch (Exception e) { - e.printStackTrace(); - LOGGER.error(e); - } - } - -} diff --git a/blade-core/src/main/java/com/blade/render/VelocityRender.java b/blade-core/src/main/java/com/blade/render/VelocityRender.java deleted file mode 100644 index 9ac758ed3..000000000 --- a/blade-core/src/main/java/com/blade/render/VelocityRender.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.render; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.Writer; -import java.util.Properties; -import java.util.Set; - -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.Velocity; -import org.apache.velocity.app.VelocityEngine; - -import com.blade.Blade; -import com.blade.context.BladeWebContext; -import com.blade.web.http.Request; -import com.blade.web.http.wrapper.Session; - -import blade.kit.log.Logger; - -/** - * Velocity Render - * - * @author biezhi - * @since 1.0 - */ -public class VelocityRender implements Render { - - private static final Logger LOGGER = Logger.getLogger(VelocityRender.class); - - private final VelocityEngine velocityEngine; - - private String webRoot; - - public VelocityRender() { - Blade blade = Blade.me(); - this.webRoot = blade.webRoot(); - Properties properties = new Properties(); - - properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, blade.webRoot()); - properties.setProperty(Velocity.ENCODING_DEFAULT, blade.encoding()); - properties.setProperty(Velocity.INPUT_ENCODING, blade.encoding()); - properties.setProperty(Velocity.OUTPUT_ENCODING, blade.encoding()); - velocityEngine = new VelocityEngine(properties); - } - - /** - * Construct a Velocity engine based on the configuration file - * - * @param propertiesFile properties file path - * @throws IOException IO Exception - */ - public VelocityRender(String propertiesFile) throws IOException { - Blade blade = Blade.me(); - this.webRoot = blade.webRoot(); - String loadPath = VelocityRender.class.getClassLoader().getResource("/").getPath(); - String fileName = loadPath + propertiesFile; - - Properties properties = new Properties(); - InputStream inStream = new FileInputStream(new File(fileName)); - properties.load(inStream); - - // Default query path - if(!properties.contains(Velocity.FILE_RESOURCE_LOADER_PATH)){ - properties.put(Velocity.FILE_RESOURCE_LOADER_PATH, blade.webRoot()); - } - velocityEngine = new VelocityEngine(properties); - } - - /** - * According to the construction of a Velocity engine - * - * @param properties Properties document - */ - public VelocityRender(Properties properties) { - Blade blade = Blade.me(); - this.webRoot = blade.webRoot(); - velocityEngine = new VelocityEngine(properties); - } - - /** - * Manually constructed Velocity engine - * - * @param velocityEngine velocity engine object - */ - public VelocityRender(VelocityEngine velocityEngine) { - Blade blade = Blade.me(); - this.webRoot = blade.webRoot(); - this.velocityEngine = velocityEngine; - } - - @Override - public void render(ModelAndView modelAndView, Writer writer) throws RenderException { - Request request = BladeWebContext.request(); - Session session = request.session(); - - String viewPath = webRoot + modelAndView.getView(); - - VelocityContext context = new VelocityContext(modelAndView.getModel()); - - Set attrs = request.attributes(); - if(null != attrs && attrs.size() > 0){ - for(String attr : attrs){ - context.put(attr, request.attribute(attr)); - } - } - - Set session_attrs = session.attributes(); - if(null != session_attrs && session_attrs.size() > 0){ - for(String attr : session_attrs){ - context.put(attr, session.attribute(attr)); - } - } - - try { - Template template = velocityEngine.getTemplate(viewPath); - template.merge(context, writer); - writer.flush(); - writer.close(); - } catch (IOException e) { - e.printStackTrace(); - LOGGER.error(e); - } - - } - -} diff --git a/blade-core/src/main/java/com/blade/render/package-info.java b/blade-core/src/main/java/com/blade/render/package-info.java deleted file mode 100644 index f80838ca2..000000000 --- a/blade-core/src/main/java/com/blade/render/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Blade Render - */ -package com.blade.render; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 0247a9dc8..f46ce107b 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -20,13 +20,15 @@ import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.ioc.Ioc; import com.blade.web.http.HttpMethod; import com.blade.web.http.Request; import com.blade.web.http.Response; import blade.kit.Assert; -import blade.kit.log.Logger; /** * Registration, management route @@ -36,7 +38,7 @@ */ public class Routers { - private Logger LOGGER = Logger.getLogger(Routers.class); + private Logger LOGGER = LoggerFactory.getLogger(Routers.class); private Ioc ioc = null; @@ -67,18 +69,18 @@ public void addRoute(Route route) { // existent if (null != this.routes.get(key)) { - LOGGER.warn("\tRoute "+ path + " -> " + httpMethod.toString() +" has exist"); + LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); } if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ if (null != this.interceptors.get(key)) { - LOGGER.warn("\tInterceptor "+ path + " -> " + httpMethod.toString() +" has exist"); + LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); } this.interceptors.put(key, route); - LOGGER.debug("Add Interceptor:" + route); + LOGGER.debug("Add Interceptor:{}", route); } else { this.routes.put(key, route); - LOGGER.debug("Add Route:" + route); + LOGGER.debug("Add Route:{}", route); } } @@ -103,19 +105,19 @@ public void addRoute(HttpMethod httpMethod, String path, Object controller, Meth String key = path + "#" + httpMethod.toString(); // existent if (null != this.routes.get(key)) { - LOGGER.warn("\tRoute "+ path + " -> " + httpMethod.toString() +" has exist"); + LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); } Route route = new Route(httpMethod, path, controller, method); if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ if (null != this.interceptors.get(key)) { - LOGGER.warn("\tInterceptor "+ path + " -> " + httpMethod.toString() +" has exist"); + LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); } this.interceptors.put(key, route); - LOGGER.debug("Add Interceptor:" + route); + LOGGER.debug("Add Interceptor:{}", route); } else { this.routes.put(key, route); - LOGGER.debug("Add Route:" + route); + LOGGER.debug("Add Route:{}", route); } } diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java index f71cf1ce6..a210a3e07 100644 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -17,8 +17,8 @@ import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; - -import blade.kit.log.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.blade.web.DispatcherServlet; @@ -30,7 +30,7 @@ */ public class Server { - private static final Logger LOGGER = Logger.getLogger(Server.class); + private static final Logger LOGGER = LoggerFactory.getLogger(Server.class); private int port = 9000; @@ -68,7 +68,7 @@ public void start(String contextPath) throws Exception{ server.setHandler(this.context); server.start(); // server.dump(System.err); - LOGGER.info("Blade Server Listen on 0.0.0.0:" + this.port); + LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); } public void join() throws InterruptedException { diff --git a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java index f898910a4..13e9a48a5 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java +++ b/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java @@ -15,13 +15,15 @@ */ package com.blade.verify; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.web.http.Request; import com.blade.web.http.Response; import com.blade.web.http.wrapper.Session; import blade.kit.HashidKit; import blade.kit.StringKit; -import blade.kit.log.Logger; /** * CSRF token Manager @@ -31,7 +33,7 @@ */ public class CSRFTokenManager { - private static Logger LOGGER = Logger.getLogger(CSRFTokenManager.class); + private static Logger LOGGER = LoggerFactory.getLogger(CSRFTokenManager.class); private static CSRFConfig config = new CSRFConfig(); @@ -69,7 +71,7 @@ public static String createToken(Request request, Response response) { if(config.setCookie){ response.cookie(config.cookiePath, config.cookie, token, config.expire, config.secured); } - LOGGER.info("create csrf_token:" + token); + LOGGER.debug("create csrf_token:{}", token); } return token; } diff --git a/blade-core/src/main/java/com/blade/render/JspRender.java b/blade-core/src/main/java/com/blade/view/template/JspEngine.java similarity index 75% rename from blade-core/src/main/java/com/blade/render/JspRender.java rename to blade-core/src/main/java/com/blade/view/template/JspEngine.java index 76a80c843..dd240cba1 100644 --- a/blade-core/src/main/java/com/blade/render/JspRender.java +++ b/blade-core/src/main/java/com/blade/view/template/JspEngine.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.render; +package com.blade.view.template; import java.io.IOException; import java.io.Writer; @@ -24,7 +24,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import blade.kit.log.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.blade.context.BladeWebContext; @@ -34,11 +35,17 @@ * @author biezhi * @since 1.0 */ -public final class JspRender implements Render { +public final class JspEngine implements TemplteEngine { - private static final Logger LOGGER = Logger.getLogger(JspRender.class); + private static final Logger LOGGER = LoggerFactory.getLogger(JspEngine.class); - public JspRender() { + private String viewPath = "/WEB-INF/"; + + public JspEngine() { + } + + public JspEngine(String viewPath) { + this.viewPath = viewPath; } @Override @@ -48,7 +55,7 @@ public void render(ModelAndView modelAndView, Writer writer) { try { Map model = modelAndView.getModel(); - String viewPath = modelAndView.getView(); + String realPath = viewPath + modelAndView.getView(); if (null != model && !model.isEmpty()) { Set keys = model.keySet(); @@ -56,13 +63,13 @@ public void render(ModelAndView modelAndView, Writer writer) { servletRequest.setAttribute(key, model.get(key)); } } - servletRequest.getRequestDispatcher(viewPath).forward(servletRequest, servletResponse); + servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); } catch (ServletException e) { e.printStackTrace(); - LOGGER.error(e); + LOGGER.error("", e); } catch (IOException e) { e.printStackTrace(); - LOGGER.error(e); + LOGGER.error("", e); } } diff --git a/blade-core/src/main/java/com/blade/render/ModelAndView.java b/blade-core/src/main/java/com/blade/view/template/ModelAndView.java similarity index 98% rename from blade-core/src/main/java/com/blade/render/ModelAndView.java rename to blade-core/src/main/java/com/blade/view/template/ModelAndView.java index bcb7159bf..77ad65924 100644 --- a/blade-core/src/main/java/com/blade/render/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/view/template/ModelAndView.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.render; +package com.blade.view.template; import java.util.Map; diff --git a/blade-core/src/main/java/com/blade/render/RenderException.java b/blade-core/src/main/java/com/blade/view/template/RenderException.java similarity index 93% rename from blade-core/src/main/java/com/blade/render/RenderException.java rename to blade-core/src/main/java/com/blade/view/template/RenderException.java index 9882b9399..d50991a1c 100644 --- a/blade-core/src/main/java/com/blade/render/RenderException.java +++ b/blade-core/src/main/java/com/blade/view/template/RenderException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.render; +package com.blade.view.template; /** * RenderException diff --git a/blade-core/src/main/java/com/blade/render/Render.java b/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java similarity index 90% rename from blade-core/src/main/java/com/blade/render/Render.java rename to blade-core/src/main/java/com/blade/view/template/TemplteEngine.java index b614228a4..4f4f60747 100644 --- a/blade-core/src/main/java/com/blade/render/Render.java +++ b/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.render; +package com.blade.view.template; import java.io.Writer; @@ -23,7 +23,7 @@ * @author biezhi * @since 1.0 */ -public interface Render { +public interface TemplteEngine { public void render(ModelAndView modelAndView, Writer writer) throws RenderException; diff --git a/blade-core/src/main/java/com/blade/view/template/package-info.java b/blade-core/src/main/java/com/blade/view/template/package-info.java new file mode 100644 index 000000000..deeda47f3 --- /dev/null +++ b/blade-core/src/main/java/com/blade/view/template/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade Render + */ +package com.blade.view.template; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/AppAsyncListener.java b/blade-core/src/main/java/com/blade/web/AppAsyncListener.java deleted file mode 100644 index 559535b29..000000000 --- a/blade-core/src/main/java/com/blade/web/AppAsyncListener.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.blade.web; - -import java.io.IOException; - -import javax.servlet.AsyncEvent; -import javax.servlet.AsyncListener; - -//@WebListener -public class AppAsyncListener implements AsyncListener { - - @Override - public void onComplete(AsyncEvent asyncEvent) throws IOException { -// System.out.println("AppAsyncListener onComplete"); - } - - @Override - public void onError(AsyncEvent asyncEvent) throws IOException { -// System.out.println("AppAsyncListener onError"); - } - - @Override - public void onStartAsync(AsyncEvent asyncEvent) throws IOException { -// System.out.println("AppAsyncListener onStartAsync"); - } - - @Override - public void onTimeout(AsyncEvent asyncEvent) throws IOException { -// System.out.println("AppAsyncListener onTimeout"); -// ServletResponse response = asyncEvent.getAsyncContext().getResponse(); -// PrintWriter out = response.getWriter(); -// out.write("TimeOut Error in Processing"); - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java b/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java deleted file mode 100644 index 853b12deb..000000000 --- a/blade-core/src/main/java/com/blade/web/AsynRequestHandler.java +++ /dev/null @@ -1,219 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; - -import java.lang.reflect.Method; -import java.util.List; - -import javax.servlet.AsyncContext; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import blade.kit.StringKit; -import blade.kit.log.Logger; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.context.BladeWebContext; -import com.blade.render.ModelAndView; -import com.blade.route.Route; -import com.blade.route.RouteHandler; -import com.blade.route.RouteMatcher; -import com.blade.web.http.HttpStatus; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.ResponsePrint; -import com.blade.web.http.wrapper.ServletRequest; -import com.blade.web.http.wrapper.ServletResponse; - -/** - * Asynchronous request processor - * - * @author biezhi - * @since 1.0 - */ -public class AsynRequestHandler implements Runnable { - - private static final Logger LOGGER = Logger.getLogger(AsynRequestHandler.class); - - private Blade blade = Blade.me(); - - private ServletContext servletContext; - - static RouteMatcher routeMatcher; - - private HttpServletRequest httpRequest; - - private HttpServletResponse httpResponse; - - private AsyncContext asyncContext; - - public AsynRequestHandler(ServletContext servletContext, AsyncContext asyncCtx) { - this.asyncContext = asyncCtx; - this.servletContext = servletContext; - this.httpRequest = (HttpServletRequest) asyncCtx.getRequest(); - this.httpResponse = (HttpServletResponse) asyncCtx.getResponse(); - } - - @Override - public void run(){ - - Response response = null; - try { - // http method, GET/POST ... - String method = httpRequest.getMethod(); - - // reuqest uri - String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - - // If it is static, the resource is handed over to the filter - if(null != blade.staticFolder() && blade.staticFolder().length > 0){ - if(!filterStaticFolder(uri)){ - if(LOGGER.isDebugEnabled()){ - LOGGER.debug("Request : " + method + "\t" + uri); - } - String realpath = httpRequest.getServletContext().getRealPath(uri); - ResponsePrint.printStatic(uri, realpath, httpResponse); - return; - } - } - - LOGGER.info("Request : " + method + "\t" + uri); - - - // Create Request - Request request = new ServletRequest(httpRequest); - - // Create Response - response = new ServletResponse(httpResponse, blade.render()); - - // Init Context - BladeWebContext.setContext(servletContext, request, response); - - Route route = routeMatcher.getRoute(method, uri); - - // If find it - if (route != null) { - request.setRoute(route); - - boolean result = false; - // before inteceptor - List befores = routeMatcher.getBefore(uri); - result = invokeInterceptor(request, response, befores); - if(result){ - // execute - handle(request, response, route); - - if(!request.isAbort()){ - // after inteceptor - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - } - } - } else { - // Not found - render404(response, uri); - } - asyncContext.complete(); - return; - } catch (Exception e) { - ResponsePrint.printError(e, 500, httpResponse); - } - } - - /** - * 404 view render - * - * @param response response object - * @param uri 404 uri - */ - private void render404(Response response, String uri) { - String view404 = blade.view404(); - if(StringKit.isNotBlank(view404)){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", uri); - response.render( modelAndView ); - } else { - response.status(HttpStatus.NOT_FOUND); - response.html(String.format(Const.VIEW_NOTFOUND, uri)); - } - } - - /** - * Methods to perform the interceptor - * - * @param request request object - * @param response response object - * @param interceptors execute the interceptor list - * @return Return execute is ok - */ - private boolean invokeInterceptor(Request request, Response response, List interceptors) { - for(Route route : interceptors){ - handle(request, response, route); - if(request.isAbort()){ - return false; - } - } - return true; - } - - /** - * Actual routing method execution - * - * @param request request object - * @param response response object - * @param route route object - */ - private void handle(Request request, Response response, Route route){ - - Object target = route.getTarget(); - if(null == target){ - Class clazz = route.getAction().getDeclaringClass(); - target = Blade.me().ioc().getBean(clazz); - } - request.initPathParams(route.getPath()); - - // Init context - BladeWebContext.setContext(servletContext, request, response); - if(target instanceof RouteHandler){ - RouteHandler routeHandler = (RouteHandler)target; - routeHandler.handle(request, response); - } else { - Method actionMethod = route.getAction(); - // execute - RouteArgument.executeMethod(target, actionMethod, request, response); - } - } - - /** - * Filter out the directory - * - * @param uri URI represents the current path, filtering in a static directory - * @return Return false, filter the success; return true, do not filter - */ - private boolean filterStaticFolder(String uri){ - int len = blade.staticFolder().length; - for(int i=0; i 0){ if(!filterStaticFolder(uri)){ if(LOGGER.isDebugEnabled()){ - LOGGER.debug("Request : " + method + "\t" + uri); + LOGGER.debug("Request : {}\t{}", method, uri); } String realpath = httpRequest.getServletContext().getRealPath(uri); ResponsePrint.printStatic(uri, realpath, httpResponse); @@ -84,7 +86,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo } } - LOGGER.info("Request : " + method + "\t" + uri); + LOGGER.info("Request : {}\t{}", method, uri); try { // Create Request diff --git a/blade-core/src/main/java/com/blade/web/http/Response.java b/blade-core/src/main/java/com/blade/web/http/Response.java index 46140ccb2..2cc2c8dd3 100644 --- a/blade-core/src/main/java/com/blade/web/http/Response.java +++ b/blade-core/src/main/java/com/blade/web/http/Response.java @@ -21,7 +21,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; -import com.blade.render.ModelAndView; +import com.blade.view.template.ModelAndView; /** * HTTP Response diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index 6aa4a4fa0..7ff33bfa1 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -27,8 +27,8 @@ import com.blade.Blade; import com.blade.context.BladeWebContext; -import com.blade.render.ModelAndView; -import com.blade.render.Render; +import com.blade.view.template.ModelAndView; +import com.blade.view.template.TemplteEngine; import com.blade.web.http.HttpStatus; import com.blade.web.http.Path; import com.blade.web.http.Request; @@ -46,9 +46,9 @@ public class ServletResponse implements Response { private boolean written = false; - private Render render; + private TemplteEngine render; - public ServletResponse(HttpServletResponse response, Render render) { + public ServletResponse(HttpServletResponse response, TemplteEngine render) { this.response = response; this.render = render; } From 0f0cf97d2df39132b9aedd961a917334c12919cf Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 14 Feb 2016 14:33:25 +0800 Subject: [PATCH 395/545] reset package --- blade-core/src/main/java/com/blade/Blade.java | 2 +- blade-core/src/main/java/com/blade/Const.java | 3 --- .../java/com/blade/loader/Configurator.java | 19 ++----------------- .../loader/AbstractFileRouteLoader.java | 2 +- .../loader/ClassPathControllerLoader.java | 2 +- .../loader/ClassPathRouteLoader.java | 2 +- .../{ => route}/loader/ControllerLoader.java | 2 +- .../loader/FileSystemRouteLoader.java | 2 +- .../blade/{ => route}/loader/RouteLoader.java | 2 +- .../blade/view/template/TemplteEngine.java | 2 +- ...erException.java => TemplteException.java} | 10 +++++----- .../blade/{ => web}/verify/CSRFConfig.java | 2 +- .../{ => web}/verify/CSRFTokenManager.java | 2 +- .../blade/{ => web}/verify/package-info.java | 2 +- 14 files changed, 18 insertions(+), 36 deletions(-) rename blade-core/src/main/java/com/blade/{ => route}/loader/AbstractFileRouteLoader.java (96%) rename blade-core/src/main/java/com/blade/{ => route}/loader/ClassPathControllerLoader.java (98%) rename blade-core/src/main/java/com/blade/{ => route}/loader/ClassPathRouteLoader.java (98%) rename blade-core/src/main/java/com/blade/{ => route}/loader/ControllerLoader.java (96%) rename blade-core/src/main/java/com/blade/{ => route}/loader/FileSystemRouteLoader.java (97%) rename blade-core/src/main/java/com/blade/{ => route}/loader/RouteLoader.java (96%) rename blade-core/src/main/java/com/blade/view/template/{RenderException.java => TemplteException.java} (76%) rename blade-core/src/main/java/com/blade/{ => web}/verify/CSRFConfig.java (95%) rename blade-core/src/main/java/com/blade/{ => web}/verify/CSRFTokenManager.java (96%) rename blade-core/src/main/java/com/blade/{ => web}/verify/package-info.java (57%) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index f9302ec09..fa0cda38a 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -23,7 +23,6 @@ import com.blade.ioc.Ioc; import com.blade.ioc.SampleIoc; -import com.blade.loader.ClassPathRouteLoader; import com.blade.loader.BladeConfig; import com.blade.loader.Configurator; import com.blade.plugin.Plugin; @@ -32,6 +31,7 @@ import com.blade.route.RouteGroup; import com.blade.route.RouteHandler; import com.blade.route.Routers; +import com.blade.route.loader.ClassPathRouteLoader; import com.blade.server.Server; import com.blade.view.template.JspEngine; import com.blade.view.template.TemplteEngine; diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 56d97c5ab..ed0a31e90 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -51,10 +51,7 @@ public interface Const { String BLADE_EXECUTOR = "blade-req-executor"; String BLADE_ROUTE = "blade.route"; - String BLADE_INTERCEPTOR = "blade.interceptor"; String BLADE_IOC = "blade.ioc"; - String BLADE_PREFIX = "blade.prefix"; - String BLADE_SUFFIX = "blade.suffix"; String BLADE_FILTER_FOLDER = "blade.filter_folder"; String BLADE_ENCODING = "blade.encoding"; String BLADE_VIEW_404 = "blade.view404"; diff --git a/blade-core/src/main/java/com/blade/loader/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java index 5fcb8c01e..a4a4ac043 100644 --- a/blade-core/src/main/java/com/blade/loader/Configurator.java +++ b/blade-core/src/main/java/com/blade/loader/Configurator.java @@ -47,10 +47,7 @@ public void run() { bladeConfig.setConfigMap(configMap); String route = configMap.get(Const.BLADE_ROUTE); - String interceptor = configMap.get(Const.BLADE_INTERCEPTOR); String ioc = configMap.get(Const.BLADE_IOC); - String prefix = configMap.get(Const.BLADE_PREFIX); - String suffix = configMap.get(Const.BLADE_SUFFIX); String filter_folder = configMap.get(Const.BLADE_FILTER_FOLDER); String encoding = configMap.get(Const.BLADE_ENCODING); String view404 = configMap.get(Const.BLADE_VIEW_404); @@ -67,24 +64,12 @@ public void run() { String[] blade_filter_folders = StringKit.split(filter_folder, ","); bladeConfig.setStaticFolders(blade_filter_folders); } - - if (StringKit.isNotBlank(interceptor)) { - bladeConfig.setInterceptorPackage(interceptor); - } - + if (StringKit.isNotBlank(ioc)) { String[] blade_iocs = StringKit.split(ioc, ","); bladeConfig.setIocPackages(blade_iocs); } - - if (StringKit.isNotBlank(prefix)) { - bladeConfig.setViewPrefix(prefix); - } - - if (StringKit.isNotBlank(suffix)) { - bladeConfig.setViewSuffix(suffix); - } - + if (StringKit.isNotBlank(encoding)) { bladeConfig.setEncoding(encoding); } diff --git a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java similarity index 96% rename from blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java rename to blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java index c8aa507d4..157336eff 100644 --- a/blade-core/src/main/java/com/blade/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.loader; +package com.blade.route.loader; import java.io.BufferedReader; import java.io.IOException; diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java similarity index 98% rename from blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java rename to blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java index db773ff13..75f49f5e2 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.loader; +package com.blade.route.loader; import com.blade.Blade; import com.blade.ioc.Ioc; diff --git a/blade-core/src/main/java/com/blade/loader/ClassPathRouteLoader.java b/blade-core/src/main/java/com/blade/route/loader/ClassPathRouteLoader.java similarity index 98% rename from blade-core/src/main/java/com/blade/loader/ClassPathRouteLoader.java rename to blade-core/src/main/java/com/blade/route/loader/ClassPathRouteLoader.java index 301d06f39..9a1478016 100644 --- a/blade-core/src/main/java/com/blade/loader/ClassPathRouteLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/ClassPathRouteLoader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.loader; +package com.blade.route.loader; import java.io.File; import java.io.FileInputStream; diff --git a/blade-core/src/main/java/com/blade/loader/ControllerLoader.java b/blade-core/src/main/java/com/blade/route/loader/ControllerLoader.java similarity index 96% rename from blade-core/src/main/java/com/blade/loader/ControllerLoader.java rename to blade-core/src/main/java/com/blade/route/loader/ControllerLoader.java index bcff33a5a..93c6f3c61 100644 --- a/blade-core/src/main/java/com/blade/loader/ControllerLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/ControllerLoader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.loader; +package com.blade.route.loader; import com.blade.route.RouteException; diff --git a/blade-core/src/main/java/com/blade/loader/FileSystemRouteLoader.java b/blade-core/src/main/java/com/blade/route/loader/FileSystemRouteLoader.java similarity index 97% rename from blade-core/src/main/java/com/blade/loader/FileSystemRouteLoader.java rename to blade-core/src/main/java/com/blade/route/loader/FileSystemRouteLoader.java index 37f69ee15..c97a1acd0 100644 --- a/blade-core/src/main/java/com/blade/loader/FileSystemRouteLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/FileSystemRouteLoader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.loader; +package com.blade.route.loader; import java.io.File; import java.io.FileInputStream; diff --git a/blade-core/src/main/java/com/blade/loader/RouteLoader.java b/blade-core/src/main/java/com/blade/route/loader/RouteLoader.java similarity index 96% rename from blade-core/src/main/java/com/blade/loader/RouteLoader.java rename to blade-core/src/main/java/com/blade/route/loader/RouteLoader.java index 327fc5b21..d518de82c 100644 --- a/blade-core/src/main/java/com/blade/loader/RouteLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/RouteLoader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.loader; +package com.blade.route.loader; import java.text.ParseException; import java.util.List; diff --git a/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java b/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java index 4f4f60747..7f7fff089 100644 --- a/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java @@ -25,6 +25,6 @@ */ public interface TemplteEngine { - public void render(ModelAndView modelAndView, Writer writer) throws RenderException; + public void render(ModelAndView modelAndView, Writer writer) throws TemplteException; } diff --git a/blade-core/src/main/java/com/blade/view/template/RenderException.java b/blade-core/src/main/java/com/blade/view/template/TemplteException.java similarity index 76% rename from blade-core/src/main/java/com/blade/view/template/RenderException.java rename to blade-core/src/main/java/com/blade/view/template/TemplteException.java index d50991a1c..cbd95c986 100644 --- a/blade-core/src/main/java/com/blade/view/template/RenderException.java +++ b/blade-core/src/main/java/com/blade/view/template/TemplteException.java @@ -21,23 +21,23 @@ * @author biezhi * @since 1.0 */ -public class RenderException extends RuntimeException { +public class TemplteException extends RuntimeException { private static final long serialVersionUID = 1L; - public RenderException() { + public TemplteException() { super(); } - public RenderException(String message, Throwable cause) { + public TemplteException(String message, Throwable cause) { super(message, cause); } - public RenderException(String message) { + public TemplteException(String message) { super(message); } - public RenderException(Throwable cause) { + public TemplteException(Throwable cause) { super(cause); } diff --git a/blade-core/src/main/java/com/blade/verify/CSRFConfig.java b/blade-core/src/main/java/com/blade/web/verify/CSRFConfig.java similarity index 95% rename from blade-core/src/main/java/com/blade/verify/CSRFConfig.java rename to blade-core/src/main/java/com/blade/web/verify/CSRFConfig.java index cc003869c..e2afe8908 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFConfig.java +++ b/blade-core/src/main/java/com/blade/web/verify/CSRFConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.verify; +package com.blade.web.verify; /** * CSRF Config diff --git a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/web/verify/CSRFTokenManager.java similarity index 96% rename from blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java rename to blade-core/src/main/java/com/blade/web/verify/CSRFTokenManager.java index 13e9a48a5..95e780afc 100644 --- a/blade-core/src/main/java/com/blade/verify/CSRFTokenManager.java +++ b/blade-core/src/main/java/com/blade/web/verify/CSRFTokenManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.verify; +package com.blade.web.verify; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/blade-core/src/main/java/com/blade/verify/package-info.java b/blade-core/src/main/java/com/blade/web/verify/package-info.java similarity index 57% rename from blade-core/src/main/java/com/blade/verify/package-info.java rename to blade-core/src/main/java/com/blade/web/verify/package-info.java index fcae53082..23bd98799 100644 --- a/blade-core/src/main/java/com/blade/verify/package-info.java +++ b/blade-core/src/main/java/com/blade/web/verify/package-info.java @@ -1,4 +1,4 @@ /** * Authentication And Security */ -package com.blade.verify; \ No newline at end of file +package com.blade.web.verify; \ No newline at end of file From 3e20f778f3ec3dcd85b17075aa1ffbbaf83a1c93 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 14 Feb 2016 15:42:43 +0800 Subject: [PATCH 396/545] add default config --- blade-core/src/main/java/com/blade/Blade.java | 124 +++++------------- blade-core/src/main/java/com/blade/Const.java | 3 - .../src/main/java/com/blade/ioc/Ioc.java | 2 + .../java/com/blade/loader/BladeConfig.java | 61 +++++---- .../java/com/blade/loader/Configurator.java | 103 +++++---------- .../main/java/com/blade/server/Server.java | 2 +- .../main/java/com/blade/web/BladeBanner.java | 10 +- .../java/com/blade/web/DispatcherServlet.java | 2 - .../web/http/wrapper/ServletResponse.java | 20 +-- blade-core/src/main/java/default.properties | 5 + 10 files changed, 119 insertions(+), 213 deletions(-) create mode 100644 blade-core/src/main/java/default.properties diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index fa0cda38a..326ed772c 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -15,11 +15,9 @@ */ package com.blade; -import java.io.IOException; import java.io.InputStream; import java.text.ParseException; import java.util.List; -import java.util.Map; import com.blade.ioc.Ioc; import com.blade.ioc.SampleIoc; @@ -35,12 +33,12 @@ import com.blade.server.Server; import com.blade.view.template.JspEngine; import com.blade.view.template.TemplteEngine; +import com.blade.web.BladeBanner; import com.blade.web.http.HttpMethod; import blade.kit.Assert; -import blade.kit.IOKit; import blade.kit.config.loader.ConfigLoader; -import blade.kit.json.JSONKit; +import blade.kit.reflect.ReflectKit; /** * Blade Core Class @@ -68,7 +66,7 @@ public class Blade { /** * Global configuration Object */ - private BladeConfig config = null; + private BladeConfig bladeConfig = null; /** * IOC Container, save javabean @@ -101,7 +99,7 @@ public class Blade { private Server bladeServer; private Blade() { - this.config = new BladeConfig(); + this.bladeConfig = new BladeConfig(); this.ioc = new SampleIoc(); this.iocApplication = new IocApplication(ioc); this.routers = new Routers(ioc); @@ -125,6 +123,7 @@ public static final Blade me(){ */ public void setInit(boolean isInit) { this.isInit = isInit; + new BladeBanner().print(System.out); } /** @@ -171,54 +170,10 @@ public Blade container(Ioc ioc){ public Blade setAppConf(String confName){ Assert.notBlank(confName); blade.kit.config.Config config = ConfigLoader.load(confName); - this.configuration(config.getConfigMap()); + Configurator.init(bladeConfig, config); return this; } - /** - * Setting JSON file configuration - * File path based on classpath - * - * @param fileName json file name - * @return return blade - */ - public Blade setJsonConf(String fileName){ - Assert.notBlank(fileName); - InputStream inputStream = Blade.class.getResourceAsStream(fileName); - if(null != inputStream){ - try { - String json = IOKit.toString(inputStream); - Map configMap = JSONKit.toMap(json); - configuration(configMap); - } catch (IOException e) { - e.printStackTrace(); - } - } - return this; - } - - /** - * Setting json character config, Not recommended - * - * @param json json character - * @return return blade - */ - public Blade setAppJson(String json){ - Assert.notBlank(json); - Map configMap = JSONKit.toMap(json); - configuration(configMap); - return this; - } - - /** - * Setting Map config - * @param configMap set config map - */ - private void configuration(Map configMap){ - Assert.notEmpty(configMap); - new Configurator(config, configMap).run(); - } - /** * Setting route package,e.g:com.baldejava.route * Can be introduced into multiple packages, all of which are in the package. @@ -228,7 +183,7 @@ private void configuration(Map configMap){ */ public Blade routes(String...packages){ Assert.notNull(packages); - config.setRoutePackages(packages); + bladeConfig.setRoutePackages(packages); return this; } @@ -241,7 +196,7 @@ public Blade routes(String...packages){ */ public Blade defaultRoute(String basePackage){ Assert.notBlank(basePackage); - config.setBasePackage(basePackage); + bladeConfig.setBasePackage(basePackage); return this; } @@ -253,7 +208,7 @@ public Blade defaultRoute(String basePackage){ */ public Blade interceptor(String packageName) { Assert.notBlank(packageName); - config.setInterceptorPackage(packageName); + bladeConfig.setInterceptorPackage(packageName); return this; } @@ -266,7 +221,7 @@ public Blade interceptor(String packageName) { public Blade ioc(String...packages){ Assert.notNull(packages); if(packages.length >0){ - config.setIocPackages(packages); + bladeConfig.setIocPackages(packages); } return this; } @@ -462,7 +417,7 @@ public Blade viewEngin(TemplteEngine render) { */ public Blade staticFolder(final String ... folders) { Assert.notNull(folders); - config.setStaticFolders(folders); + bladeConfig.setStaticFolders(folders); return this; } @@ -472,8 +427,8 @@ public Blade staticFolder(final String ... folders) { * @param enableXSS enable XSS, default is false * @return return blade */ - public Blade enableXSS(boolean enableXSS){ - config.setEnableXSS(enableXSS); + public Blade enableXSS(boolean httpXss){ + bladeConfig.setHttpXss(httpXss); return this; } @@ -497,7 +452,11 @@ public Blade app(Bootstrap bootstrap){ */ public Blade app(Class bootstrap){ Assert.notNull(bootstrap); - ioc.addBean(bootstrap); + try { + ioc.addBean(Bootstrap.class.getName(), ReflectKit.newInstance(bootstrap)); + } catch (Exception e) { + e.printStackTrace(); + } return this; } @@ -509,7 +468,7 @@ public Blade app(Class bootstrap){ */ public Blade setView404(final String view404){ Assert.notBlank(view404); - config.setView404(view404); + bladeConfig.setView404(view404); return this; } @@ -521,7 +480,7 @@ public Blade setView404(final String view404){ */ public Blade setView500(final String view500){ Assert.notBlank(view500); - config.setView500(view500); + bladeConfig.setView500(view500); return this; } @@ -533,7 +492,7 @@ public Blade setView500(final String view500){ */ public Blade webRoot(final String webRoot){ Assert.notBlank(webRoot); - config.setWebRoot(webRoot); + bladeConfig.setWebRoot(webRoot); return this; } @@ -544,7 +503,7 @@ public Blade webRoot(final String webRoot){ * @return return blade */ public Blade isDev(boolean isDev){ - config.setDev(isDev); + bladeConfig.setDev(isDev); return this; } @@ -615,92 +574,77 @@ public void join() throws InterruptedException { * @return Return blade config object */ public BladeConfig config(){ - return config; + return bladeConfig; } /** * @return Return blade scan base package */ public String basePackage(){ - return config.getBasePackage(); + return bladeConfig.getBasePackage(); } /** * @return Return route packages */ public String[] routePackages(){ - return config.getRoutePackages(); + return bladeConfig.getRoutePackages(); } /** * @return Return ioc packages */ public String[] iocs(){ - return config.getIocPackages(); + return bladeConfig.getIocPackages(); } /** * @return Returns the interceptor array, only one element here use String[] */ public String interceptorPackage(){ - return config.getInterceptorPackage(); - } - - - /** - * @return Return views prefix - */ - public String viewPrefix(){ - return config.getViewPrefix(); + return bladeConfig.getInterceptorPackage(); } /** * @return Return blade encoding, default is UTF-8 */ public String encoding(){ - return config.getEncoding(); - } - - /** - * @return Return view suffix - */ - public String viewSuffix(){ - return config.getViewSuffix(); + return bladeConfig.getEncoding(); } /** * @return Return 404 view */ public String view404(){ - return config.getView404(); + return bladeConfig.getView404(); } /** * @return Return 500 view */ public String view500(){ - return config.getView500(); + return bladeConfig.getView500(); } /** * @return Return blade web root path */ public String webRoot(){ - return config.getWebRoot(); + return bladeConfig.getWebRoot(); } /** * @return Return is dev mode */ public boolean isDev(){ - return config.isDev(); + return bladeConfig.isDev(); } /** * @return Return static resource directory */ public String[] staticFolder(){ - return config.getStaticFolders(); + return bladeConfig.getStaticFolders(); } /** @@ -721,7 +665,7 @@ public TemplteEngine render() { * @return Return XSS is enabled */ public boolean enableXSS(){ - return config.isEnableXSS(); + return bladeConfig.isHttpXss(); } /** diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index ed0a31e90..2c60a9183 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -52,11 +52,8 @@ public interface Const { String BLADE_ROUTE = "blade.route"; String BLADE_IOC = "blade.ioc"; - String BLADE_FILTER_FOLDER = "blade.filter_folder"; - String BLADE_ENCODING = "blade.encoding"; String BLADE_VIEW_404 = "blade.view404"; String BLADE_VIEW_500 = "blade.view500"; String BLADE_DEV = "blade.dev"; - String BLADE_ENABLE_XSS = "blade.enableXSS"; } diff --git a/blade-core/src/main/java/com/blade/ioc/Ioc.java b/blade-core/src/main/java/com/blade/ioc/Ioc.java index 59a6424df..358a47f34 100644 --- a/blade-core/src/main/java/com/blade/ioc/Ioc.java +++ b/blade-core/src/main/java/com/blade/ioc/Ioc.java @@ -34,6 +34,8 @@ public interface Ioc { void addBean(Class type); + void addBean(String name, Object bean); + Object getBean(String name); T getBean(Class type); diff --git a/blade-core/src/main/java/com/blade/loader/BladeConfig.java b/blade-core/src/main/java/com/blade/loader/BladeConfig.java index 3ed961c72..ffab6e32a 100644 --- a/blade-core/src/main/java/com/blade/loader/BladeConfig.java +++ b/blade-core/src/main/java/com/blade/loader/BladeConfig.java @@ -21,6 +21,8 @@ import java.util.Map; import blade.kit.PatternKit; +import blade.kit.config.Config; +import blade.kit.config.loader.ConfigLoader; /** * Blade Config Class @@ -32,7 +34,7 @@ public class BladeConfig { // Store all variables - private Map configMap = Collections.emptyMap(); + private Map configMap; // Storage of all routing packets private List routePackages = Collections.emptyList(); @@ -52,12 +54,6 @@ public class BladeConfig { // Encoding private String encoding = "utf-8"; - // View prefix - private String viewPrefix = "/WEB-INF/views/"; - - // View suffix - private String viewSuffix = ".jsp"; - // web root path private String webRoot; @@ -71,9 +67,25 @@ public class BladeConfig { private boolean isDev = false; // Enabled XSS - private boolean enableXSS = false; + private boolean httpXss = false; + + private boolean httpCache = false; public BladeConfig() { + init(); + } + + private void init(){ + Config config = ConfigLoader.load("default.properties"); + Configurator.init(this, config); + + try { + config = ConfigLoader.load("blade.properties"); + if(null != config){ + Configurator.init(this, config); + } + } catch (Exception e) { + } } public Map getConfigMap() { @@ -162,23 +174,6 @@ public void setInterceptorPackage(String interceptorPackage) { this.interceptorPackage = interceptorPackage; } - public String getViewPrefix() { - return viewPrefix; - } - - public void setViewPrefix(String viewPrefix) { - this.viewPrefix = viewPrefix; - } - - public String getViewSuffix() { - return viewSuffix; - } - - - public void setViewSuffix(String viewSuffix) { - this.viewSuffix = viewSuffix; - } - public String[] getStaticFolders() { String[] folderArr = new String[staticFolders.size()]; return staticFolders.toArray(folderArr); @@ -228,12 +223,20 @@ public void setEncoding(String encoding) { this.encoding = encoding; } - public boolean isEnableXSS() { - return enableXSS; + public boolean isHttpXss() { + return httpXss; } - public void setEnableXSS(boolean enableXSS) { - this.enableXSS = enableXSS; + public void setHttpXss(boolean httpXss) { + this.httpXss = httpXss; } + public boolean isHttpCache() { + return httpCache; + } + + public void setHttpCache(boolean httpCache) { + this.httpCache = httpCache; + } + } diff --git a/blade-core/src/main/java/com/blade/loader/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java index a4a4ac043..07c23b460 100644 --- a/blade-core/src/main/java/com/blade/loader/Configurator.java +++ b/blade-core/src/main/java/com/blade/loader/Configurator.java @@ -15,11 +15,9 @@ */ package com.blade.loader; -import java.util.Map; - -import com.blade.Const; - +import blade.kit.Assert; import blade.kit.StringKit; +import blade.kit.config.Config; /** * Blade configuration @@ -27,70 +25,39 @@ * @author biezhi * @since 1.0 */ -public class Configurator { - - // Configuration object - private BladeConfig bladeConfig; - - // Configuration Map - private Map configMap; - - public Configurator(BladeConfig bladeConfig, Map configMap) { - this.bladeConfig = bladeConfig; - this.configMap = configMap; - } - - public void run() { - - if (null != configMap && configMap.size() > 0) { - - bladeConfig.setConfigMap(configMap); - - String route = configMap.get(Const.BLADE_ROUTE); - String ioc = configMap.get(Const.BLADE_IOC); - String filter_folder = configMap.get(Const.BLADE_FILTER_FOLDER); - String encoding = configMap.get(Const.BLADE_ENCODING); - String view404 = configMap.get(Const.BLADE_VIEW_404); - String view500 = configMap.get(Const.BLADE_VIEW_500); - String dev = configMap.get(Const.BLADE_DEV); - String xss = configMap.get(Const.BLADE_ENABLE_XSS); - - if (StringKit.isNotBlank(route)) { - String[] blade_routes = StringKit.split(route, ","); - bladeConfig.setRoutePackages(blade_routes); - } - - if (StringKit.isNotBlank(filter_folder)) { - String[] blade_filter_folders = StringKit.split(filter_folder, ","); - bladeConfig.setStaticFolders(blade_filter_folders); - } - - if (StringKit.isNotBlank(ioc)) { - String[] blade_iocs = StringKit.split(ioc, ","); - bladeConfig.setIocPackages(blade_iocs); - } - - if (StringKit.isNotBlank(encoding)) { - bladeConfig.setEncoding(encoding); - } - - if (StringKit.isNotBlank(view404)) { - bladeConfig.setView404(view404); - } - - if (StringKit.isNotBlank(view500)) { - bladeConfig.setView500(view500); - } - - if (StringKit.isNotBlank(dev)) { - Boolean isDev = Boolean.parseBoolean(dev); - bladeConfig.setDev(isDev); - } - - if (StringKit.isNotBlank(xss)) { - Boolean enableXssBool = Boolean.valueOf(xss); - bladeConfig.setEnableXSS(enableXssBool); - } +public final class Configurator { + + public static void init(BladeConfig bladeConfig, Config config) { + + Assert.notNull(bladeConfig); + Assert.notNull(config); + + Boolean dev = config.getBoolean("blade.dev"); + Boolean httpCache = config.getBoolean("blade.http.cache"); + Boolean httpXss = config.getBoolean("blade.http.xss"); + + String httpEncoding = config.getString("blade.http.encoding"); + String httpFilters = config.getString("blade.http.filters"); + + if(null != dev){ + bladeConfig.setDev(dev); + } + + if(null != httpCache){ + bladeConfig.setHttpCache(httpCache); + } + + if(StringKit.isNotBlank(httpEncoding)){ + bladeConfig.setEncoding(httpEncoding); + } + + if(null != httpXss){ + bladeConfig.setHttpXss(httpXss); + } + + if(StringKit.isNotBlank(httpFilters)){ + bladeConfig.setStaticFolders(httpFilters.split(",")); } } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java index a210a3e07..160653fec 100644 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -34,7 +34,7 @@ public class Server { private int port = 9000; - private boolean async = true; + private boolean async = false; private org.eclipse.jetty.server.Server server; diff --git a/blade-core/src/main/java/com/blade/web/BladeBanner.java b/blade-core/src/main/java/com/blade/web/BladeBanner.java index 07b08d333..634ed1b2c 100644 --- a/blade-core/src/main/java/com/blade/web/BladeBanner.java +++ b/blade-core/src/main/java/com/blade/web/BladeBanner.java @@ -13,10 +13,12 @@ public class BladeBanner { " ~ ~~~ ~ ~ ~ ~~~" }; - void print(PrintStream printStream){ - for (String s : banner) { - printStream.println('\t' + s); + public void print(final PrintStream printStream){ + synchronized (BladeBanner.class) { + for (String s : banner) { + printStream.println('\t' + s); + } + printStream.println("\t :: Blade :: (v" + Const.BLADE_VERSION + ")\r\n"); } - printStream.println("\t :: Blade :: (v" + Const.BLADE_VERSION + ")"); } } diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index ef1ff4283..2dac382ac 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -95,8 +95,6 @@ public void init(Blade blade) { blade.setInit(true); - new BladeBanner().print(System.out); - LOGGER.info("blade init complete!"); } } diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index 7ff33bfa1..80a9a344b 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -23,9 +23,6 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; -import blade.kit.Assert; - -import com.blade.Blade; import com.blade.context.BladeWebContext; import com.blade.view.template.ModelAndView; import com.blade.view.template.TemplteEngine; @@ -34,6 +31,8 @@ import com.blade.web.http.Request; import com.blade.web.http.Response; +import blade.kit.Assert; + /** * ServletResponse * @@ -272,14 +271,8 @@ public Response render(String view) { try { Assert.notBlank(view, "view not is null"); - Blade blade = Blade.me(); - String viewPath = blade.viewPrefix() + view + blade.viewSuffix(); - if(view.endsWith(blade.viewSuffix())){ - viewPath = blade.viewPrefix() + view; - } - viewPath = Path.cleanPath(viewPath); + String viewPath = Path.cleanPath(view); ModelAndView modelAndView = new ModelAndView(viewPath); - render.render(modelAndView, response.getWriter()); return this; } catch (IOException e) { @@ -294,12 +287,7 @@ public Response render(ModelAndView modelAndView) { Assert.notNull(modelAndView, "ModelAndView not is null!"); Assert.notBlank(modelAndView.getView(), "view not is null"); - Blade blade = Blade.me(); - String viewPath = blade.viewPrefix() + modelAndView.getView() + blade.viewSuffix(); - if(modelAndView.getView().endsWith(blade.viewSuffix())){ - viewPath = blade.viewPrefix() + modelAndView.getView(); - } - viewPath = Path.cleanPath(viewPath); + String viewPath = Path.cleanPath(modelAndView.getView()); modelAndView.setView(viewPath); render.render(modelAndView, response.getWriter()); diff --git a/blade-core/src/main/java/default.properties b/blade-core/src/main/java/default.properties new file mode 100644 index 000000000..618726946 --- /dev/null +++ b/blade-core/src/main/java/default.properties @@ -0,0 +1,5 @@ +blade.dev = true +blade.http.encoding = utf-8 +blade.http.cache = false +blade.http.xss = false +blade.http.filters = public \ No newline at end of file From 4d71e1a9caf83ac6f6a6c39eea6f33836bd3d6ef Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 14 Feb 2016 15:45:25 +0800 Subject: [PATCH 397/545] - --- blade-kit/src/main/java/blade/kit/log/Logger.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/log/Logger.java b/blade-kit/src/main/java/blade/kit/log/Logger.java index 3f32a9538..a96549ec6 100644 --- a/blade-kit/src/main/java/blade/kit/log/Logger.java +++ b/blade-kit/src/main/java/blade/kit/log/Logger.java @@ -188,11 +188,11 @@ protected String format(Object message, Object... args) { if (message == null) { return null; } - - if (args == null || args.length == 0) + if (args == null || args.length == 0) { return message.toString(); - else + } else { return String.format(message.toString(), args); + } } public boolean isDebugEnabled() { From ace75ad1189b468b6d60abe4b1e9c2e931021aed Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 14 Feb 2016 15:47:01 +0800 Subject: [PATCH 398/545] remove blade-sql2o --- blade-sql2o/README.md | 106 -- blade-sql2o/pom.xml | 37 - .../java/blade/plugin/sql2o/Condition.java | 437 ----- .../java/blade/plugin/sql2o/Constant.java | 33 - .../java/blade/plugin/sql2o/DBConfig.java | 67 - .../main/java/blade/plugin/sql2o/Model.java | 1511 ----------------- .../main/java/blade/plugin/sql2o/Page.java | 184 -- .../java/blade/plugin/sql2o/Sql2oPlugin.java | 173 -- .../java/blade/plugin/sql2o/SqlBuider.java | 292 ---- .../main/java/blade/plugin/sql2o/Table.java | 26 - .../java/blade/plugin/sql2o/WhereParam.java | 189 --- .../blade/plugin/sql2o/cache/CacheType.java | 7 - .../plugin/sql2o/cache/SimpleSql2oCache.java | 121 -- .../blade/plugin/sql2o/cache/Sql2oCache.java | 36 - .../plugin/sql2o/cache/Sql2oCacheFactory.java | 27 - .../plugin/sql2o/ds/DataSourceManager.java | 70 - .../sql2o/exception/DataSourceException.java | 27 - 17 files changed, 3343 deletions(-) delete mode 100644 blade-sql2o/README.md delete mode 100644 blade-sql2o/pom.xml delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/Constant.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/Page.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/SqlBuider.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/Table.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/cache/CacheType.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCacheFactory.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java delete mode 100644 blade-sql2o/src/main/java/blade/plugin/sql2o/exception/DataSourceException.java diff --git a/blade-sql2o/README.md b/blade-sql2o/README.md deleted file mode 100644 index 3d5b8ee3c..000000000 --- a/blade-sql2o/README.md +++ /dev/null @@ -1,106 +0,0 @@ -# Blade-Sql2o - -轻小,简单,快速,高效的数据库框架。 - -### 特性 -基于`blade`框架为核心搭建的操作数据库基础框架,一行代码即可完成增删改查,分页等操作; -内置基于LRU的缓存机制进行缓存,可配置的缓存开关以及扩展。 - -##快速入门 -它使用起来非常方便,首先配置好数据库 - -```java -// 配置数据库插件 -Sql2oPlugin sql2oPlugin = Sql2oPlugin.INSTANCE; -sql2oPlugin.config("jdbc:mysql://localhost:3306/test", "com.mysql.jdbc.Driver", "root", "root"); -// 开启缓存 -sql2oPlugin.openCache(); -sql2oPlugin.run(); -``` -* 添加一条数据 -```java -User model = new User(); - -Date birthday = new Date(); -Long uid = model.insert().param("name", "jack").param("birthday", birthday).param("sex", "男").executeAndCommit(); -LOGGER.INFO("uid = " + uid); -``` - -* 查询一条数据 -```java -User model = new User(); - -// 根据主键查询User -User user = model.select().fetchByPk(1); -LOGGER.INFO("user = " + user); - -// 查询性别为男性,名字以`张`开头,年龄在50一下的User -User user = model.select().where("sex", "男").like("name", "张%").less("age", 50).fetchOne(); -LOGGER.INFO("user = " + user); -``` - -* 查询一个数据集合 -```java -User model = new User(); - -// 查询性别为男性,名字以`张`开头,年龄在50一下的User集合 -List users = model.select().where("sex", "男").like("name", "张%").less("age", 50).order("age asc").fetchList(); -LOGGER.INFO("user = " + user); -``` - - -* 分页查询一个数据集合 -```java -Post model = new Post(); - -Page postPage = model.select("select pid, title, type, access_count, create_time, update_time from post") - .where("status", "publish") - .like("title", "%java") - .orderBy("pid desc") - .fetchPage(1, 10); -``` - - -* 联合查询一个数据集合 -```java -Post model = new Post(); - -List posts = model.select("select a.* from post a inner join relation b on a.pid = b.pid") - .where("a.type", "post") - .where("b.mid", 15) - .like("a.title", "%java") - .orderBy("a.pid desc") - .fetchList(); -``` - -* 修改数据 -```java -Post model = new Post(); - -Long count = model.update() - .param("title", "test1") - .where("pid", 11).executeAndCommit(); - -``` - -* 删除数据 -```java -Post model = new Post(); - -Long count = model.delete().where("pid", pid).executeAndCommit(); - -``` - -### v1.2.x - 1. 修复分页bug - 2. 修复按主键查询bug - 3. 添加内置缓存支持 - -### v1.1.x - 1. 适配`blade`最新版本 - 2. 添加动态数据源支持 - -### 联系我 -Mail: biezhi.me#gmail.com - -Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) \ No newline at end of file diff --git a/blade-sql2o/pom.xml b/blade-sql2o/pom.xml deleted file mode 100644 index bd0f7ef9c..000000000 --- a/blade-sql2o/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-sql2o - jar - 1.3.0-alpha - blade-sql2o - https://github.com/biezhi/blade/tree/master/blade-sql2o - - - - com.bladejava - blade-core - ${blade.version} - provided - - - com.bladejava - blade-cache - 1.2.3 - provided - - - org.sql2o - sql2o - 1.5.4 - - - diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java deleted file mode 100644 index 1b755ad4a..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Condition.java +++ /dev/null @@ -1,437 +0,0 @@ -package blade.plugin.sql2o; - -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import blade.kit.CollectionKit; -import blade.kit.StringKit; -import blade.kit.log.Logger; - -public class Condition { - - private static final Logger LOGGER = Logger.getLogger(Condition.class); - - String tableName; - - String pkName; - - // 存储sql - String sql; - - // 存储排序 - String orderby; - - // 存储操作,增删改查 - DmlType dmlType; - - // 存储设置的参数,insert-update用 - Map params; - - // 存储where条件,select-update-delete用 - Map equalsParams; - - // 大于 - Map greaterParams; - // 大于等于 - Map greaterThanParams; - // 小于 - Map lessParams; - // 小于等于 - Map lessThanParams; - // like - Map likeParams; - // in - Map inParams; - - List logParams = new LinkedList(); - - enum DmlType { - SELECT, COUNT, INSERT, UPDATE, DELETE - } - - - public Condition(String tableName, String pkName) { - this.tableName = tableName; - this.pkName = pkName; - this.params = CollectionKit.newHashMap(); - this.equalsParams = CollectionKit.newHashMap(); - this.greaterParams = CollectionKit.newHashMap(); - this.greaterThanParams = CollectionKit.newHashMap(); - this.lessParams = CollectionKit.newHashMap(); - this.lessThanParams = CollectionKit.newHashMap(); - this.likeParams = CollectionKit.newHashMap(); - this.inParams = CollectionKit.newHashMap(); - } - - public String getConditionSql() { - return getConditionSql(null); - } - - public String getConditionSql(String sql) { - - String sqlEnd = this.sql; - - if (null != sql) { - sqlEnd = sql; - } - - String conditionSql = SqlBuider.create(this, sqlEnd) - .addEquals() - .addGreater() - .addLess() - .addGreaterThan() - .addLessThan() - .addLike() - .addIn() - .addAsString(); - - - if (conditionSql.lastIndexOf(" and ") != -1) { - conditionSql = conditionSql.substring(0, conditionSql.length() - 5); - } - return conditionSql; - } - - /** - * 过滤mysql、posrgresql、oracle关键字 - * - * @param field - * @return - */ - public String filterKeyWord(String field) { - String[] filters = { "`", "\"" }; - for (String f : filters) { - if (field.startsWith(f) && field.endsWith(f)) { - return field.substring(1, field.length() - 1); - } - } - if (field.indexOf(".") != -1) { - return field.replace(".", "_"); - } - return field; - } - - /** - * 打印参数列表 - */ - public void printLog() { - - if (null != logParams && logParams.size() > 0) { - LOGGER.debug("execute parameter:" + logParams.toString()); - } - } - - /** - * 参数全部清空 - */ - public void clearMap() { - - if(null != this.params){ - this.params.clear(); - } - - if(null != this.equalsParams){ - this.equalsParams.clear(); - } - - if(null != this.greaterParams){ - this.greaterParams.clear(); - } - - if(null != this.greaterThanParams){ - this.greaterThanParams.clear(); - } - - if(null != this.lessParams){ - this.lessParams.clear(); - } - - if(null != this.lessThanParams){ - this.lessThanParams.clear(); - } - - if(null != this.likeParams){ - this.likeParams.clear(); - } - - if(null != this.inParams){ - this.inParams.clear(); - } - - if(null != this.logParams){ - this.logParams.clear(); - } - } - - public void select() { - this.sql = "select * from " + this.tableName; - clearMap(); - this.equalsParams = CollectionKit.newLinkedHashMap(); - this.dmlType = DmlType.SELECT; - this.orderby = null; - } - - /** - * 自定义sql返回查询model对象 - * @param sql - */ - public void select(String sql) { - this.sql = sql; - clearMap(); - this.equalsParams = CollectionKit.newLinkedHashMap(); - this.dmlType = DmlType.SELECT; - this.orderby = null; - } - - /** - * @return 返回计算count - */ - public void count(){ - this.sql = "select count(1) from " + this.tableName; - clearMap(); - this.equalsParams = CollectionKit.newLinkedHashMap(); - this.dmlType = DmlType.COUNT; - this.orderby = null; - } - - /** - * 自定义sql返回查询model对象 - * - * @param sql - */ - public void count(String sql){ - this.sql = sql; - clearMap(); - this.equalsParams = CollectionKit.newLinkedHashMap(); - this.dmlType = DmlType.COUNT; - this.orderby = null; - } - - public Condition update(){ - this.sql = "update " + this.tableName; - clearMap(); - this.params = CollectionKit.newLinkedHashMap(); - this.equalsParams = CollectionKit.newLinkedHashMap(); - this.dmlType = DmlType.UPDATE; - return this; - } - - /** - * 自定义更新语句 - * @param sql - */ - public Condition update(String sql){ - this.sql = sql; - clearMap(); - this.params = CollectionKit.newLinkedHashMap(); - this.equalsParams = CollectionKit.newLinkedHashMap(); - this.dmlType = DmlType.UPDATE; - return this; - } - - public void insert(){ - this.sql = "insert into " + this.tableName; - clearMap(); - this.params = CollectionKit.newLinkedHashMap(); - this.dmlType = DmlType.INSERT; - } - - /** - * 设置插入sql - * @param sql - */ - public void insert(String sql){ - this.sql = sql; - clearMap(); - this.params = CollectionKit.newLinkedHashMap(); - this.dmlType = DmlType.INSERT; - } - - public void delete(){ - this.sql = "delete from " + this.tableName; - clearMap(); - this.equalsParams = CollectionKit.newLinkedHashMap(); - this.dmlType = DmlType.DELETE; - } - - /** - * 设置删除sql - * @param sql - */ - public void delete(String sql){ - this.sql = sql; - clearMap(); - this.equalsParams = CollectionKit.newLinkedHashMap(); - this.dmlType = DmlType.DELETE; - } - - /** - * 设置参数列表,新增,更新用到 - * - * @param name - * @param value - */ - public void param(String name, Object value){ - if(StringKit.isNotBlank(name) && null != value){ - this.params.put(name, value); - this.logParams.add(value); - } - } - - public void where(WhereParam whereParam){ - if(null != whereParam){ - if(whereParam.equalsParams.size() > 0){ - this.equalsParams.putAll(whereParam.equalsParams); - } - - if(whereParam.greaterParams.size() > 0){ - this.greaterParams.putAll(whereParam.greaterParams); - } - - if(whereParam.greaterThanParams.size() > 0){ - this.greaterThanParams.putAll(whereParam.greaterThanParams); - } - - if(whereParam.lessParams.size() > 0){ - this.lessParams.putAll(whereParam.lessParams); - } - - if(whereParam.lessThanParams.size() > 0){ - this.lessThanParams.putAll(whereParam.lessThanParams); - } - - if(whereParam.likeParams.size() > 0){ - this.likeParams.putAll(whereParam.likeParams); - } - - if(whereParam.inParams.size() > 0){ - this.inParams.putAll(whereParam.inParams); - } - - if(whereParam.params.size() > 0){ - this.params.putAll(whereParam.params); - } - - if(whereParam.logParams.size() > 0){ - this.logParams.addAll(whereParam.logParams); - } - } - } - - /** - * 设置where参数列表,查询,更新,删除用到 - * - * @param name - * @param value - */ - public void eq(String name, Object value){ - if(StringKit.isNotBlank(name) && null != value){ - this.equalsParams.put(name, value); - this.logParams.add(value); - } - } - - /** - * 大于条件 - * - * @param name - * @param value - */ - public void greater(String name, Object value){ - if(StringKit.isNotBlank(name) && null != value){ - if(null == this.greaterParams){ - this.greaterParams = CollectionKit.newLinkedHashMap(); - } - this.greaterParams.put(name, value); - this.logParams.add(value); - } - } - - /** - * 大于等于条件 - * - * @param name - * @param value - */ - public void greaterThan(String name, Object value){ - if(StringKit.isNotBlank(name) && null != value){ - if(null == this.greaterThanParams){ - this.greaterThanParams = CollectionKit.newLinkedHashMap(); - } - this.greaterThanParams.put(name, value); - this.logParams.add(value); - } - } - - /** - * 小于条件 - * - * @param name - * @param value - * @return - */ - public void less(String name, Object value){ - if(StringKit.isNotBlank(name) && null != value){ - if(null == this.lessParams){ - this.lessParams = CollectionKit.newLinkedHashMap(); - } - this.lessParams.put(name, value); - this.logParams.add(value); - } - } - - /** - * 小于等于条件 - * - * @param name - * @param value - */ - public void lessThan(String name, Object value){ - if(StringKit.isNotBlank(name) && null != value){ - - if(null == this.lessThanParams){ - this.lessThanParams = CollectionKit.newLinkedHashMap(); - } - this.lessThanParams.put(name, value); - this.logParams.add(value); - } - } - - /** - * like条件 - * - * @param name - * @param value - */ - public void like(String name, String value){ - - if(StringKit.isNotBlank(name) && StringKit.isNotBlank(value) - && value.indexOf("%null")==-1 && value.indexOf("null%")==-1 && !value.equals("%%")){ - - if(null == this.likeParams){ - this.likeParams = CollectionKit.newLinkedHashMap(); - } - this.likeParams.put(name, value); - this.logParams.add(value); - } - } - - /** - * in条件 - * - * @param name - * @param value - */ - public void in(String name, Object... values){ - if(StringKit.isNotBlank(name) && null != values && values.length > 1){ - if(null == this.inParams){ - this.inParams = CollectionKit.newLinkedHashMap(); - } - this.inParams.put(name, values); - this.logParams.add(Arrays.toString(values)); - } - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Constant.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Constant.java deleted file mode 100644 index be3a41714..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Constant.java +++ /dev/null @@ -1,33 +0,0 @@ -package blade.plugin.sql2o; - -/** - * 连接池常量 - */ -public final class Constant { - - /** - * 数据库驱动 - */ - public static final String DRIVE = "blade.db.drive"; - - /** - * 数据库URL - */ - public static final String URL = "blade.db.url"; - - /** - * 用户名 - */ - public static final String USERNAME = "blade.db.username"; - - /** - * 密码 - */ - public static final String PASSWORD = "blade.db.password"; - - /** - * 是否开启缓存 - */ - public static final String OPEN_CACHE = "blade.db.opencache"; - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java deleted file mode 100644 index b88b37ab7..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/DBConfig.java +++ /dev/null @@ -1,67 +0,0 @@ -package blade.plugin.sql2o; - -public class DBConfig { - - /** - * 驱动名称 - */ - private String driverName; - - /** - * 连接地址 - */ - private String url; - - /** - * 用户名 - */ - private String userName; - - /** - * 密码 - */ - private String passWord; - - public DBConfig() { - // TODO Auto-generated constructor stub - } - - public String getDriverName() { - return driverName; - } - - public void setDriverName(String driverName) { - this.driverName = driverName; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassWord() { - return passWord; - } - - public void setPassWord(String passWord) { - this.passWord = passWord; - } - - @Override - public String toString() { - return "DBConfig [driverName=" + driverName + ", url=" + url - + ", userName=" + userName + ", passWord=" + passWord + "]"; - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java deleted file mode 100644 index a04d3bb91..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Model.java +++ /dev/null @@ -1,1511 +0,0 @@ -package blade.plugin.sql2o; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.sql2o.Connection; -import org.sql2o.Query; -import org.sql2o.Sql2o; - -import com.blade.Blade; - -import blade.kit.EncrypKit; -import blade.kit.StringKit; -import blade.kit.log.Logger; -import blade.plugin.sql2o.Condition.DmlType; -import blade.plugin.sql2o.cache.CacheType; -import blade.plugin.sql2o.cache.Sql2oCache; -import blade.plugin.sql2o.cache.Sql2oCacheFactory; -import blade.plugin.sql2o.ds.DataSourceManager; - -/** - * 实体对象基类 - * - * @author biezhi - * @since 1.0 - */ -public class Model { - - private static final Logger LOGGER = Logger.getLogger(Model.class); - - /** - * sql2o对象,操作数据库 - */ - private Sql2o sql2o = DataSourceManager.me().getSql2o(); - - private static final Sql2oPlugin SQL2O_PLUGIN = Blade.me().plugin(Sql2oPlugin.class); - - /** - * 缓存对象 - */ - public Sql2oCache sql2oCache = SQL2O_PLUGIN.isOpenCache() ? Sql2oCacheFactory.getSql2oCache() : null; - - /** - * 当前class实例 - */ - private Class model; - - /** - * 本次查询是否开启缓存 - */ - private boolean cache = false; - - /** - * 是否在单次查询的时候开启缓存,如果开启,则忽略默认不开启缓存 - */ - private boolean queryIsOpen = false; - - /** - * 条件对象 - */ - private Condition condition; - - private String CACHE_KEY_LIST; - private String CACHE_KEY_COUNT; - private String CACHE_KEY_DETAIL; - // 自定义sql - private String CACHE_KEY_SQL_LIST; - private String CACHE_KEY_SQL_COUNT; - private String CACHE_KEY_SQL_DETAIL; - - /** - * 创建一个Model - * @param clazz model class - * @return 返回Model对象 - */ - public static Model create(Class clazz) { - return new Model(clazz); - } - - public Model(Class clazz) { - this.model = clazz; - this.condition = new Condition(table(), pk()); - - CACHE_KEY_LIST = model.getName() + ":" + CacheType.list.toString(); - CACHE_KEY_COUNT = model.getName() + ":" + CacheType.count.toString(); - CACHE_KEY_DETAIL = model.getName() + ":" + CacheType.detail.toString(); - } - - public Sql2o getSql2o(){ - return sql2o; - } - - /** - * @return 返回表名称 - */ - public String table(){ - return model.getAnnotation(Table.class).value(); - } - - /** - * @return 返回表主键 - */ - public String pk(){ - return model.getAnnotation(Table.class).PK(); - } - - /** - * @return 返回表是否需要缓存 - */ - private boolean isCache(){ - if(this.queryIsOpen){ - return true; - } - return SQL2O_PLUGIN.isOpenCache() && model.getAnnotation(Table.class).isCache() && this.cache; - } - - /** - * 设置当前执行方法不缓存 - */ - public Model cache(boolean cache){ - if(cache){ - if(null == sql2oCache){ - sql2oCache = Sql2oCacheFactory.getSql2oCache(); - } - this.queryIsOpen = true; - } - this.cache = cache; - return this; - } - - /** - * 初始化操作 - * 初始化是否缓存,每次查询都走一次 - */ - private void init(){ - this.queryIsOpen = false; - this.cache = SQL2O_PLUGIN.isOpenCache(); - if(null == this.sql2o){ - this.sql2o = DataSourceManager.me().getSql2o(); - } - } - - /** - * @return 返回查询model对象,推荐方式 - */ - public Model select(){ - init(); - condition.select(); - return this; - } - - public boolean isOpenCache() { - return SQL2O_PLUGIN.isOpenCache(); - } - - /** - * 自定义sql返回查询model对象 - * - * @param sql 要查询的sql语句 - * @return 返回查询model对象 - */ - public Model select(String sql){ - init(); - CACHE_KEY_SQL_LIST = model.getName() + ":" + CacheType.sqllist.toString(); - CACHE_KEY_SQL_DETAIL = model.getName() + ":" + CacheType.sqldetail.toString(); - condition.select(sql); - return this; - } - - /** - * @return 返回计算count - */ - public Model count(){ - init(); - condition.count(); - return this; - } - - /** - * 自定义sql返回查询model对象 - * - * @param sql 要查询的sql语句 - * @return 返回查询model对象 - */ - public Model count(String sql){ - init(); - CACHE_KEY_SQL_COUNT = model.getName() + ":" + CacheType.sqlcount.toString(); - condition.count(sql); - return this; - } - - /** - * @return 返回更新model对象,推荐方式 - */ - public Model update(){ - init(); - condition.update(); - return this; - } - - /** - * 返回更新model对象 - * - * @param sql 自定义更新语句 - * @return 返回更新model对象 - */ - public Model update(String sql){ - init(); - condition.update(sql); - return this; - } - - /** - * @return 返回插入model对象,推荐方式 - */ - public Model insert(){ - init(); - condition.insert(); - return this; - } - - /** - * 根据自定义sql返回插入model对象 - * @param sql 自定义插入语句 - * @return 返回插入model对象 - */ - public Model insert(String sql){ - init(); - condition.insert(sql); - return this; - } - - /** - * @return 返回删除model对象 - */ - public Model delete(){ - init(); - condition.delete(); - return this; - } - - /** - * 返回自定义删除model对象 - * - * @param sql 自定义删除语句 - * @return 返回自定义删除model对象 - */ - public Model delete(String sql){ - init(); - condition.delete(sql); - return this; - } - - /** - * 设置参数列表,新增,更新用到 - * - * @param name 参数键 - * @param value 参数值 - * @return 返回model对象 - */ - public Model set(String name, Object value){ - condition.param(name, value); - return this; - } - - /** - * 设置参数列表,新增,更新用到 - * - * @param name 参数键 - * @param value 参数值 - * @return 返回model对象 - */ - public Model param(String name, Object value){ - condition.param(name, value); - return this; - } - - /** - * 设置equals参数列表,查询,更新,删除用到 - * - * @param name 参数键 - * @param value 参数值 - * @return 返回model对象 - */ - public Model eq(String name, Object value){ - condition.eq(name, value); - return this; - } - - /** - * 设置where参数列表,查询,更新,删除用到 - * - * @param whereParam 保存参数的对象 - * @return 返回model对象 - */ - public Model where(WhereParam whereParam){ - condition.where(whereParam); - return this; - } - - /** - * 大于 - * @param name - * @param value - * @return - */ - public Model greater(String name, Object value){ - condition.greater(name, value); - return this; - } - - /** - * 大于等于 - * - * @param name 参数键 - * @param value 参数值 - * @return 返回model对象 - */ - public Model greaterThan(String name, Object value){ - condition.greaterThan(name, value); - return this; - } - - /** - * 小于 - * @param name 参数键 - * @param value 参数值 - * @return 返回model对象 - */ - public Model less(String name, Object value){ - condition.less(name, value); - return this; - } - - /** - * 小于等于 - * @param name 参数键 - * @param value 参数值 - * @return 返回model对象 - */ - public Model lessThan(String name, Object value){ - condition.lessThan(name, value); - return this; - } - - /** - * like - * @param name - * @param value - * @return - */ - public Model like(String name, String value){ - condition.like(name, value); - return this; - } - - /** - * in - * @param name - * @param value - * @return - */ - public Model in(String name, Object... values){ - condition.in(name, values); - return this; - } - - /** - * 设置排序规则 - * - * @param orderby 排序字段和排序规则,如:ordernum desc - * @return 返回model对象 - */ - public Model orderBy(String orderby){ - condition.orderby = orderby; - return this; - } - - ////////////////////E////////////////////////// - - private String getCacheCountKey(){ - String cacheSql = getCacheKey(null); - if(cacheSql.indexOf("from ") != -1 && cacheSql.indexOf("count(") == -1){ - int start = cacheSql.indexOf("from ") + 5; - cacheSql = "selectcount(1)from " + cacheSql.substring(start); - } - cacheSql = cacheSql.replaceAll("\\s", ""); - return cacheSql; - } - - private String getCacheKey(String sql){ - - String sqlEnd = condition.sql; - if(StringKit.isNotBlank(sql)){ - sqlEnd = sql; - } - - String cacheSql = SqlBuider.create(condition, sqlEnd) - .appendEquals() - .appendGreater() - .appendGreaterThan() - .appendLess() - .appendLessThan() - .appendLike() - .appendIn().appendAsString(); - - - if(cacheSql.lastIndexOf(" and ") != -1){ - cacheSql = cacheSql.substring(0, cacheSql.length() - 5); - } - - if(StringKit.isNotBlank(condition.orderby)){ - cacheSql += " order by " + condition.orderby; - } - - cacheSql = cacheSql.replaceAll("\\s", ""); - - return cacheSql; - } - - /** - * 将参数加入到query中 - * @param query - * @return - */ - private Query parseParams(Query query){ - - // insert、update参数 - if(null != condition.params){ - Set keys = condition.params.keySet(); - for(String name : keys){ - query.addParameter(condition.filterKeyWord(name), condition.params.get(name)); - } - } - - // 基础equals条件 - if(null != condition.equalsParams){ - Set keys = condition.equalsParams.keySet(); - for(String name : keys){ - query.addParameter(condition.filterKeyWord(name), condition.equalsParams.get(name)); - } - } - - // 大于条件 - if(null != condition.greaterParams){ - Set keys = condition.greaterParams.keySet(); - for(String name : keys){ - query.addParameter(condition.filterKeyWord(name), condition.greaterParams.get(name)); - } - } - - // 小于条件 - if(null != condition.lessParams){ - Set keys = condition.lessParams.keySet(); - for(String name : keys){ - query.addParameter(condition.filterKeyWord(name), condition.lessParams.get(name)); - } - } - - // 大于等于条件 - if(null != condition.greaterThanParams){ - Set keys = condition.greaterThanParams.keySet(); - for(String name : keys){ - query.addParameter(condition.filterKeyWord(name), condition.greaterThanParams.get(name)); - } - } - - // 小于等于条件 - if(null != condition.lessThanParams){ - Set keys = condition.lessThanParams.keySet(); - for(String name : keys){ - query.addParameter(condition.filterKeyWord(name), condition.lessThanParams.get(name)); - } - } - - // like条件 - if(null != condition.likeParams){ - Set keys = condition.likeParams.keySet(); - for(String name : keys){ - query.addParameter(condition.filterKeyWord(name), condition.likeParams.get(name)); - } - } - - // in条件 - if(null != condition.inParams){ - Set keys = condition.inParams.keySet(); - - for(String name : keys){ - Object[] objects = condition.inParams.get(name); - int len = objects.length; - - for(int i=0; i modelClazz){ - if(null != cacheType && null != modelClazz){ - String key = modelClazz.getName() + ":" + cacheType; - sql2oCache.hdel(key); - } - } - - /** - * 刷新缓存 - */ - public void cleanAll(){ - - LOGGER.debug("更新缓存:" + model.getName() + " -> count,list,detail,sqlcount,sqllist,sqldetail"); - sql2oCache.hdel(CACHE_KEY_COUNT); - sql2oCache.hdel(CACHE_KEY_LIST); - sql2oCache.hdel(CACHE_KEY_DETAIL); - - String countkey = model.getName() + ":" + CacheType.sqlcount.toString(); - String listkey = model.getName() + ":" + CacheType.sqllist.toString(); - String detailkey = model.getName() + ":" + CacheType.sqldetail.toString(); - - sql2oCache.hdel(countkey); - sql2oCache.hdel(listkey); - sql2oCache.hdel(detailkey); - } - - /** - * 刷新缓存 - */ - public void cleanAll(Class modelClazz){ - - LOGGER.debug("更新缓存:" + modelClazz.getName() + " -> count,list,detail,sqlcount,sqllist,sqldetail"); - - String countkey = modelClazz.getName() + ":" + CacheType.count.toString(); - String listkey = modelClazz.getName() + ":" + CacheType.list.toString(); - String detailkey = modelClazz.getName() + ":" + CacheType.detail.toString(); - - String sqlcountkey = modelClazz.getName() + ":" + CacheType.sqlcount.toString(); - String sqllistkey = modelClazz.getName() + ":" + CacheType.sqllist.toString(); - String sqldetailkey = modelClazz.getName() + ":" + CacheType.sqldetail.toString(); - - sql2oCache.hdel(countkey); - sql2oCache.hdel(listkey); - sql2oCache.hdel(detailkey); - - sql2oCache.hdel(sqlcountkey); - sql2oCache.hdel(sqllistkey); - sql2oCache.hdel(sqldetailkey); - } - - /** - * @return 返回查询一个对象 - */ - public Map fetchMap(){ - - if(condition.dmlType.equals(DmlType.SELECT)){ - - String sqlEnd = condition.getConditionSql(); - - Map res = null; - String field = null; - - // 是否开启缓存查询 - if(isCache()){ - field = EncrypKit.md5(getCacheKey(null)); - - String key = (null == CACHE_KEY_SQL_DETAIL) ? CACHE_KEY_DETAIL : CACHE_KEY_SQL_DETAIL; - - res = sql2oCache.hgetV(key, field); - if(null != res){ - return res; - } - } - Connection conn = null; - try { - conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - condition.clearMap(); - - org.sql2o.data.Table table = query.executeAndFetchTable(); - if(null != table){ - - List> list = tableAsList(table); - - if(null != list && list.size() > 0){ - res = list.get(0); - } - } - - // 重新放入缓存 - if(isCache() && null != res){ - String key = (null == CACHE_KEY_SQL_DETAIL) ? CACHE_KEY_DETAIL : CACHE_KEY_SQL_DETAIL; - sql2oCache.hsetV(key, field, res); - } - return res; - } catch (Exception e) { - e.printStackTrace(); - } finally{ - if(null != conn){ - conn.close(); - } - } - } - return null; - } - - public T fetchByPk(Serializable pk){ - T res = null; - - if(null != pk){ - - this.select().eq(this.pk(), pk); - - String field = null; - // 启用缓存 - if(isCache()){ - field = EncrypKit.md5(getCacheKey(null)); - String key = (null == CACHE_KEY_SQL_DETAIL) ? CACHE_KEY_DETAIL : CACHE_KEY_SQL_DETAIL; - res = sql2oCache.hget(key, field); - if(null != res){ - return res; - } - } - - String sqlEnd = condition.sql + " where " + pk() + " = :pk"; - Connection conn = null; - try { - conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd).addParameter("pk", pk); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - condition.clearMap(); - - res = (T) query.executeAndFetchFirst(this.model); - - if(isCache() && null != res){ - String key = (null == CACHE_KEY_SQL_DETAIL) ? CACHE_KEY_DETAIL : CACHE_KEY_SQL_DETAIL; - sql2oCache.hset(key, field, res); - } - } catch (Exception e) { - e.printStackTrace(); - } finally{ - if(null != conn){ - conn.close(); - } - } - } - return res; - } - - /** - * @return 返回查询一个对象 - */ - @SuppressWarnings("unchecked") - public M fetchColum(){ - if(condition.dmlType.equals(DmlType.SELECT)){ - - String sqlEnd = condition.getConditionSql(); - Connection conn = null; - try { - conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - condition.clearMap(); - - return (M) query.executeScalar(); - } catch (Exception e) { - e.printStackTrace(); - } finally{ - if(null != conn){ - conn.close(); - } - } - } - return null; - } - - /** - * @return 查询list数据 - */ - @SuppressWarnings("unchecked") - public List fetchList(){ - if(condition.dmlType.equals(DmlType.SELECT)){ - - String field = null; - List result = null; - - // 开启缓存 - if(isCache()){ - field = EncrypKit.md5(getCacheKey(null)); - String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; - result = (List) sql2oCache.hgetlist(key, field); - if(null != result){ - return result; - } - } - - String sqlEnd = condition.getConditionSql(); - - if(null != condition.orderby){ - sqlEnd += " order by " + condition.orderby; - } - Connection conn = null; - try { - conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - - condition.printLog(); - condition.clearMap(); - - result = (List) query.executeAndFetch(this.model); - - if(isCache() && null != result){ - String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; - sql2oCache.hsetlist(key, field, result); - } - return result; - } catch (Exception e) { - e.printStackTrace(); - } finally{ - if(null != conn){ - conn.close(); - } - } - } - return null; - } - - - /** - * @return 查询list数据 - */ - public List executeAndFetch(Class clazz){ - if(condition.dmlType.equals(DmlType.SELECT)){ - - String field = null; - List result = null; - - // 开启缓存 - if(isCache()){ - field = EncrypKit.md5(getCacheKey(null)); - String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; - result = sql2oCache.hgetlists(key, field); - if(null != result){ - return result; - } - } - - String sqlEnd = condition.getConditionSql(); - - if(null != condition.orderby){ - sqlEnd += " order by " + condition.orderby; - } - Connection conn = null; - try { - conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - - condition.printLog(); - condition.clearMap(); - - result = query.executeAndFetch(clazz); - - if(isCache() && null != result){ - String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; - sql2oCache.hsetlists(key, field, result); - } - return result; - } catch (Exception e) { - e.printStackTrace(); - } finally{ - if(null != conn){ - conn.close(); - } - } - } - return null; - } - - /** - * @return 返回一个listmap类型的数据 - */ - public List> fetchListMap(){ - - if(condition.dmlType.equals(DmlType.SELECT)){ - - String field = null; - List> result = null; - - // 开启缓存 - if(isCache()){ - field = EncrypKit.md5(getCacheKey(null)); - String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; - result = sql2oCache.hgetlistmap(key, field); - if(null != result){ - return result; - } - } - - String sqlEnd = condition.getConditionSql(); - - if(null != condition.orderby){ - sqlEnd += " order by " + condition.orderby; - } - Connection conn = null; - try { - conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - - condition.printLog(); - condition.clearMap(); - - result = query.executeAndFetchTable().asList(); - - if(isCache() && null != result){ - String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; - sql2oCache.hsetlistmap(key, field, result); - } - - return result; - } catch (Exception e) { - e.printStackTrace(); - } finally{ - if(null != conn){ - conn.close(); - } - } - } - return null; - } - - /** - * 分页检索 - * - * @param page 当前页码 - * @param pageSize 每页条数 - * @return 返回分页后的Page对象 - */ - public Page fetchPage(Integer page, Integer pageSize){ - - if(null == page || page < 1){ - page = 1; - } - - if(null == pageSize || pageSize < 1){ - pageSize = 1; - } - - Page pageModel = new Page(0, page, pageSize); - - if(condition.dmlType.equals(DmlType.SELECT) && null != page && null != pageSize && page > 0 && pageSize > 0){ - - // 查询总记录数 - long totalCount = getPageCount(); - - String field = null; - List results = null; - - // 开启缓存 - if(isCache()){ - String cacheSql = getCacheKey(null) + "limit"+ (page - 1) +"," + pageSize; - cacheSql = cacheSql.replaceAll("\\s", ""); - field = EncrypKit.md5(cacheSql); - - String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; - - results = sql2oCache.hgetlist(key, field); - - pageModel = new Page(totalCount, page, pageSize); - - if(null != results && results.size() > 0){ - pageModel.setResults((List) results); - return pageModel; - } - - } - - String sqlEnd = condition.getConditionSql(); - - if(null != condition.orderby){ - sqlEnd += " order by " + condition.orderby; - } - - sqlEnd += " limit :page, :pageSize"; - - Connection conn = null; - try { - // 设置query - conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - query.addParameter("page", page - 1); - query.addParameter("pageSize", pageSize); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - - results = (List) query.executeAndFetch(this.model); - if(null != results && results.size() > 0){ - - if(isCache()){ - String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; - sql2oCache.hsetlist(key, field, results); - } - pageModel.setResults((List) results); - } - - return pageModel; - } catch (Exception e) { - e.printStackTrace(); - } finally{ - if(null != conn){ - conn.close(); - } - } - } - - condition.clearMap(); - - return pageModel; - } - - /** - * 分页检索 - * - * @param page 当前页码 - * @param pageSize 每页条数 - * @return 返回分页后的Page对象 - */ - public Page> fetchPageMap(Integer page, Integer pageSize){ - - if(null == page || page < 1){ - page = 1; - } - - if(null == pageSize || pageSize < 1){ - pageSize = 1; - } - - Page> pageMap = new Page>(0, page, pageSize); - - if(condition.dmlType.equals(DmlType.SELECT) && null != page && null != pageSize && page > 0 && pageSize > 0){ - - // 查询总记录数 - long totalCount = getPageCount(); - - String field = null; - List> results = null; - // 开启缓存 - if(isCache()){ - - String cacheSql = getCacheKey(null) + "limit"+ (page - 1) +"," + pageSize; - cacheSql = cacheSql.replaceAll("\\s", ""); - field = EncrypKit.md5(cacheSql); - - String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; - - results = sql2oCache.hgetlistmap(key, field); - - if(null != results && results.size() > 0){ - pageMap = new Page>(totalCount, page, pageSize); - pageMap.setResults(results); - return pageMap; - } - - } - - String sqlEnd = condition.getConditionSql(); - - if(null != condition.orderby){ - sqlEnd += " order by " + condition.orderby; - } - - sqlEnd += " limit :page, :pageSize"; - -// condition.eq("page", page - 1); -// condition.eq("pageSize", pageSize); - Connection conn = null; - try { - // 设置query - conn = sql2o.open(); - Query query = conn.createQuery(sqlEnd); - query = parseParams(query); - query.addParameter("page", page - 1); - query.addParameter("pageSize", pageSize); - - LOGGER.debug("execute sql:" + query.toString()); - condition.printLog(); - - results = tableAsList(query.executeAndFetchTable()); - - pageMap = new Page>(totalCount, page, pageSize); - - if(null != results && results.size() > 0){ - if(isCache()){ - String key = (null == CACHE_KEY_SQL_LIST) ? CACHE_KEY_LIST : CACHE_KEY_SQL_LIST; - sql2oCache.hsetlistmap(key, field, results); - } - pageMap.setResults(results); - } - - } catch (Exception e) { - e.printStackTrace(); - } finally{ - if(null != conn){ - conn.close(); - } - } - condition.clearMap(); - - return pageMap; - } - - return pageMap; - } - - /*************************************SELECT:E*****************************************/ - - - /** - * 执行并提交 - * @return - */ - public Integer executeAndCommit() { - return executeAndCommit(Integer.class); - } - - /** - * 执行并提交,事务一致 - * - * @return 返回主键 - */ - @SuppressWarnings({ "unchecked"}) - public V executeAndCommit(Class returnType) { - V key = null; - Query query = null; - try { - // 插入 - if(condition.dmlType.equals(DmlType.INSERT)){ - query = insertCommit(null); - - if(isCache()){ - LOGGER.debug("更新缓存:" + model.getName() + " -> count,list"); - cleanAll(); - } - - if(null == query){ - LOGGER.error("query is null"); - } else { - if(null != returnType){ - key = query.executeUpdate().getKey(returnType); - } else { - key = (V) query.executeUpdate().getKey(); - } - } - - } - - // 更新 - if(condition.dmlType.equals(DmlType.UPDATE)){ - query = updateCommit(null); - - if(isCache()){ - LOGGER.debug("更新缓存:" + model.getName() + " -> detail,list"); - cleanAll(); - } - - if(null == query){ - LOGGER.error("query is null"); - } else { - key = (V) ((Integer) query.executeUpdate().getResult()); - } - } - - // 删除 - if(condition.dmlType.equals(DmlType.DELETE)){ - query = deleteCommit(null); - - if(isCache()){ - LOGGER.debug("更新缓存:" + model.getName() + " -> count,list,detail"); - cleanAll(); - } - if(null == query){ - LOGGER.error("query is null"); - } else { - key = (V) Integer.valueOf(query.executeUpdate().getResult()); - } - - } - - condition.clearMap(); - return key; - } catch (Exception e) { - e.printStackTrace(); - } finally{ - if(null != query){ - Connection connection = query.getConnection(); - if(null != connection){ - connection.close(); - } - } - } - return null; - } - - /** - * 执行并提交,事务一致 - * - * @param connection - * @return - */ - public Connection execute(Connection connection){ - Query query = null; - try { - if (null == connection) { - connection = sql2o.beginTransaction(); - } - // 插入 - if (condition.dmlType.equals(DmlType.INSERT)) { - query = insertCommit(connection); - if(isCache()){ - sql2oCache.hdel(CACHE_KEY_COUNT); - sql2oCache.hdel(CACHE_KEY_LIST); - } - } - // 更新 - if (condition.dmlType.equals(DmlType.UPDATE)) { - query = updateCommit(connection); - if(isCache()){ - sql2oCache.hdel(CACHE_KEY_DETAIL); - sql2oCache.hdel(CACHE_KEY_LIST); - } - } - // 删除 - if (condition.dmlType.equals(DmlType.DELETE)) { - query = deleteCommit(connection); - if(isCache()){ - sql2oCache.hdel(CACHE_KEY_COUNT); - sql2oCache.hdel(CACHE_KEY_LIST); - sql2oCache.hdel(CACHE_KEY_DETAIL); - } - } - condition.clearMap(); - if(null != query){ - return query.getConnection(); - } - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** - * @return 删除并返回连接 - */ - private Query deleteCommit(Connection conn) { - - String deleteSql = condition.getConditionSql(); - - if(null == conn){ - conn = sql2o.open(); - } - - Query query = conn.createQuery(deleteSql); - query = parseParams(query); - query.executeUpdate(); - - LOGGER.debug("execute sql:" + query.toString()); - LOGGER.debug("execute parameter:" + condition.equalsParams.values()); - - return query; - } - - /** - * @return 插入并返回连接 - */ - private Query insertCommit(Connection conn){ - - String insertSql = condition.sql; - - if(null != condition.params){ - - StringBuffer paramBuf = new StringBuffer("("); - StringBuffer valuesBuf = new StringBuffer(" values("); - - Set keys = condition.params.keySet(); - for(String name : keys){ - paramBuf.append(name + ", "); - valuesBuf.append(":" + condition.filterKeyWord(name) + ", "); - - } - - if(paramBuf.lastIndexOf(", ") != -1 && valuesBuf.lastIndexOf(", ") != -1){ - String start = paramBuf.substring(0, paramBuf.length() - 2); - String end = valuesBuf.substring(0, valuesBuf.length() - 2); - - insertSql = condition.sql + start + ") " + end + ")"; - } - } - - if(null == conn){ - conn = sql2o.open(); - } - - Query query = conn.createQuery(insertSql); - query = parseParams(query); - LOGGER.debug("execute sql:" + query.toString()); - LOGGER.debug("execute parameter:" + condition.params.values()); - return query; - } - - /** - * @return 更新并返回连接 - */ - private Query updateCommit(Connection conn){ - - if(null != condition.params){ - - StringBuffer setBuf = new StringBuffer(" set "); - StringBuffer whereBuf = new StringBuffer("("); - - String setSql = ""; - String whereSql = ""; - - Set keys = condition.params.keySet(); - for(String name : keys){ - setBuf.append(name + " = :" + condition.filterKeyWord(name) + ", "); - } - - if(setBuf.lastIndexOf(", ") != -1){ - setSql = setBuf.substring(0, setBuf.length() - 2); - } - - whereSql = condition.getConditionSql(""); - - if(whereBuf.lastIndexOf(", ") != -1){ - whereSql = whereBuf.substring(0, whereBuf.length() - 2); - } - - String updateSql = condition.sql + setSql + whereSql; - - updateSql = processUpdateSql(updateSql); - - if(null == conn){ - conn = sql2o.open(); - } - - Query query = conn.createQuery(updateSql); - query = parseParams(query); - - LOGGER.debug("execute sql:" + query.toString()); - LOGGER.debug("execute parameter:" + condition.params.values() + condition.equalsParams.values()); - - return query; - } - return null; - } - - /** - * 处理更新语句 - */ - private String processUpdateSql(String updateSql) { - String[] sqlArr = updateSql.split(" set"); - StringBuffer s = new StringBuffer(sqlArr[0] + " set"); - int len = sqlArr.length; - for(int i=1; i> tableAsList(org.sql2o.data.Table table) { - if(null != table){ - List> list = table.asList(); - - List> result = new ArrayList>(list.size()); - if(null != list && list.size() > 0){ - for(Map map : list){ - Map m = getMap(map); - if(null != m && m.size() > 0){ - result.add(m); - } - } - - return result; - } - } - return null; - } - - /** - * map转换 - * @param m - * @return - */ - private Map getMap(Map m) { - // 一个map就是数据库一行记录 - Set names = m.keySet(); - if(null != names && names.size() > 0){ - Map map = new HashMap(names.size()); - for(String name : names){ - map.put(name, m.get(name)); - } - return map; - } - return null; - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Page.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Page.java deleted file mode 100644 index 9fb0b03d1..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Page.java +++ /dev/null @@ -1,184 +0,0 @@ -package blade.plugin.sql2o; - -import java.util.ArrayList; -import java.util.List; - -/** - * 分页类 - * - * @author biezhi - * @since 1.0 - * @param - */ -public class Page { - - /** - * 当前页 - */ - private int page = 1; - - /** - * 每页条数 - */ - private int pageSize = 10; - - /** - * 总页数 - */ - private int totalPage = 1; - - /** - * 总记录数 - */ - private long totalCount = 0L; - /** - * 上一页 - */ - private int prev_page = 1; - /** - * 下一页 - */ - private int next_page = 1; - /** - * 首页 - */ - private int home_page = 1; - /** - * 尾页 - */ - private Integer last_page = 1; - - /** - * 链接 - */ - private String url = ""; - /** - * 固定导航数 - */ - private Integer navNum = 1; - - /** - * 数据集 - */ - private List results = new ArrayList(); - - /** - * @param totleCount 总记录数 - * @param page 当前第几页 - * @param pageSize 每页显示条数 - */ - public Page(long totalCount, int page, int pageSize) { - - this.page = page; - - this.pageSize = pageSize; - - //总条数 - this.totalCount = totalCount; - - //总页数 - this.totalPage = ((int) ((this.totalCount + this.pageSize - 1) / pageSize)); - - //首页 - this.home_page = 1; - - //尾页 - this.last_page = totalPage; - - //上一页 - this.prev_page = Math.max(this.page - 1, home_page); - - //下一页 - this.next_page = Math.min(this.page + 1, last_page); - - } - - public int getPage() { - return this.page; - } - - public Integer getPageSize() { - return this.pageSize; - } - - public int getTotalPage() { - return this.totalPage; - } - - public long getTotalCount() { - return totalCount; - } - - public Integer getPrev_page() { - return this.prev_page; - } - - public Integer getNext_page() { - return this.next_page; - } - - public Integer getHome_page() { - return this.home_page; - } - - public Integer getLast_page() { - return this.last_page; - } - - public List getResults() { - return this.results; - } - - public void setResults(List results) { - this.results = results; - } - - public Integer getNavNum() { - return this.navNum; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public void setPage(int page) { - this.page = page; - } - - public void setPageSize(int pageSize) { - this.pageSize = pageSize; - } - - public void setTotalPage(int totalPage) { - this.totalPage = totalPage; - } - - public void setTotalCount(long totalCount) { - this.totalCount = totalCount; - } - - public void setPrev_page(int prev_page) { - this.prev_page = prev_page; - } - - public void setNext_page(int next_page) { - this.next_page = next_page; - } - - public void setHome_page(int home_page) { - this.home_page = home_page; - } - - public void setLast_page(Integer last_page) { - this.last_page = last_page; - } - - public void setNavNum(Integer navNum) { - this.navNum = navNum; - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java deleted file mode 100644 index eba61b9ec..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Sql2oPlugin.java +++ /dev/null @@ -1,173 +0,0 @@ -package blade.plugin.sql2o; - -import java.sql.Driver; -import java.sql.DriverManager; -import java.util.Enumeration; -import java.util.Properties; - -import javax.sql.DataSource; - -import com.blade.Blade; -import com.blade.plugin.Plugin; - -import blade.kit.PropertyKit; -import blade.kit.StringKit; -import blade.kit.base.ThrowableKit; -import blade.kit.log.Logger; -import blade.plugin.sql2o.cache.Sql2oCache; -import blade.plugin.sql2o.cache.Sql2oCacheFactory; -import blade.plugin.sql2o.ds.DataSourceManager; - -/** - * sql2o数据库插件 - * - * @author biezhi - * @since 1.0 - */ -public class Sql2oPlugin implements Plugin { - - private Logger LOGGER = Logger.getLogger(Sql2oPlugin.class); - - private DBConfig dbConfig; - - private boolean isOpenCache = false; - - public Sql2oPlugin() { - } - - /** - * 设置数据库配置 - * - * @param dbConfig 数据库配置 - */ - public Sql2oPlugin load(String filePath){ - - Properties configProperties = PropertyKit.getProperty(filePath); - String drive = configProperties.getProperty(Constant.DRIVE); - String url = configProperties.getProperty(Constant.URL); - String username = configProperties.getProperty(Constant.USERNAME); - String password = configProperties.getProperty(Constant.PASSWORD); - String openCache = configProperties.getProperty(Constant.OPEN_CACHE); - - if(null == dbConfig){ - dbConfig = new DBConfig(); - } - - if(StringKit.isNotBlank(drive)){ - dbConfig.setDriverName(drive); - } - - if(StringKit.isNotBlank(url)){ - dbConfig.setUrl(url); - } - - if(StringKit.isNotBlank(username)){ - dbConfig.setUserName(username); - } - - if(StringKit.isNotBlank(password)){ - dbConfig.setPassWord(password); - } - - if(StringKit.isNotBlank(openCache)){ - isOpenCache = Boolean.valueOf(openCache.trim()); - } - return this; - } - - /** - * 设置数据库配置 - * - * @param dbConfig 数据库配置 - */ - public Sql2oPlugin config(DBConfig dbConfig){ - this.dbConfig = dbConfig; - return this; - } - - /** - * 设置数据源 - * @param dataSource 数据源对象 - */ - public Sql2oPlugin config(DataSource dataSource){ - String opencache = Blade.me().config().get("blade.db.opencache"); - if(StringKit.isNotBlank(opencache)){ - isOpenCache = Boolean.valueOf(opencache); - } - DataSourceManager.me().setDataSource(dataSource); - return this; - } - - public Sql2oPlugin openCache(){ - isOpenCache = true; - return this; - } - - /** - * 数据库配置 - * @param driver - * @param url - * @param user - * @param pass - * @return - */ - public Sql2oPlugin config(String driver, String url, String user, String pass){ - if(null == dbConfig){ - dbConfig = new DBConfig(); - } - dbConfig.setDriverName(driver); - dbConfig.setUrl(url); - dbConfig.setUserName(user); - dbConfig.setPassWord(pass); - return this; - } - - public boolean isOpenCache() { - return isOpenCache; - } - - public DBConfig dbConfig(){ - return dbConfig; - } - - @Override - public void run() { - DataSourceManager dm = DataSourceManager.me(); - dm.run(); - DataSource dataSource = dm.getDataSource(); - if(null == dataSource && null == dm.getSql2o()){ - LOGGER.error("blade sql2o config fail!"); - System.exit(0); - } else { - LOGGER.debug("blade sql2o config success!"); - } - } - - @Override - public void destroy() { - - LOGGER.debug("sql2o destroy!"); - - // 卸载数据库驱动 - try { - Enumeration em = DriverManager.getDrivers(); - if(null != em && em.hasMoreElements()){ - DriverManager.deregisterDriver(em.nextElement()); - } - // 清理缓存处理线程 - if(isOpenCache){ - Sql2oCache sql2oCache = Sql2oCacheFactory.getSql2oCache(); - sql2oCache.destroy(); - } - } catch (Exception e) { - LOGGER.error(ThrowableKit.getStackTraceAsString(e)); - } - - } - - public Sql2oPlugin cache(Boolean cache) { - this.isOpenCache = cache; - return this; - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/SqlBuider.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/SqlBuider.java deleted file mode 100644 index f94276eda..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/SqlBuider.java +++ /dev/null @@ -1,292 +0,0 @@ -package blade.plugin.sql2o; - -import java.util.Set; - -import blade.plugin.sql2o.Condition; - -/** - * sql组装器 - * - * @author biezhi - * @since 1.0 - */ -public class SqlBuider { - - private Condition condition; - private StringBuffer addSqlBuf; - private StringBuffer appendSqlBuf; - - public static SqlBuider create(Condition condition, String baseSql) { - return new SqlBuider(condition, baseSql); - } - - private SqlBuider(Condition condition, String baseSql) { - this.condition = condition; - this.addSqlBuf = new StringBuffer(baseSql); - this.appendSqlBuf = new StringBuffer(baseSql); - } - - /***************************APPEND:S********************************/ - public SqlBuider appendEquals(){ - // 基础where equals条件 - if(null != condition.equalsParams && condition.equalsParams.size() > 0){ - if(appendSqlBuf.indexOf("where") == -1){ - appendSqlBuf.append(" where "); - } - Set keys = condition.equalsParams.keySet(); - for(String name : keys){ - appendSqlBuf.append(name + "=" + condition.equalsParams.get(name) + " and "); - } - } - return this; - } - - /** - * 大于条件 - * @param sql - * @return - */ - public SqlBuider appendGreater(){ - if(null != condition.greaterParams && condition.greaterParams.size() > 0){ - if(appendSqlBuf.indexOf("where") == -1){ - appendSqlBuf.append(" where "); - } - Set keys = condition.greaterParams.keySet(); - for(String name : keys){ - appendSqlBuf.append(name + " > " + condition.greaterParams.get(name) + " and "); - } - } - return this; - } - - /** - * 小于条件 - * - * @param sql - * @return - */ - public SqlBuider appendLess(){ - if(null != condition.lessParams && condition.lessParams.size() > 0){ - if(appendSqlBuf.indexOf("where") == -1){ - appendSqlBuf.append(" where "); - } - Set keys = condition.lessParams.keySet(); - for(String name : keys){ - appendSqlBuf.append(name + " < " + condition.lessParams.get(name) + " and "); - } - } - return this; - } - - /** - * 大于等于条件 - * @param sql - * @return - */ - public SqlBuider appendGreaterThan(){ - if(null != condition.greaterThanParams && condition.greaterThanParams.size() > 0){ - if(appendSqlBuf.indexOf("where") == -1){ - appendSqlBuf.append(" where "); - } - Set keys = condition.greaterThanParams.keySet(); - for(String name : keys){ - appendSqlBuf.append(name + " >= " + condition.greaterThanParams.get(name) + " and "); - } - } - return this; - } - - public SqlBuider appendLessThan(){ - // 小于等于条件 - if(null != condition.lessThanParams && condition.lessThanParams.size() > 0){ - if(appendSqlBuf.indexOf("where") == -1){ - appendSqlBuf.append(" where "); - } - Set keys = condition.lessThanParams.keySet(); - for(String name : keys){ - appendSqlBuf.append(name + " <= " + condition.lessThanParams.get(name) + " and "); - } - } - return this; - } - - public SqlBuider appendLike(){ - // like条件 - if(null != condition.likeParams && condition.likeParams.size() > 0){ - if(appendSqlBuf.indexOf("where") == -1){ - appendSqlBuf.append(" where "); - } - Set keys = condition.likeParams.keySet(); - for(String name : keys){ - appendSqlBuf.append(name + " like " + condition.likeParams.get(name) + " and "); - } - } - return this; - } - - public SqlBuider appendIn(){ - // in条件 - if(null != condition.inParams && condition.inParams.size() > 0){ - if(appendSqlBuf.indexOf("where") == -1){ - appendSqlBuf.append(" where "); - } - Set keys = condition.inParams.keySet(); - - for(String name : keys){ - int len = condition.inParams.get(name).length; - - appendSqlBuf.append(name + " in ("); - - for(int i=0; i 0){ - if(addSqlBuf.indexOf("where") == -1){ - addSqlBuf.append(" where "); - } - Set keys = condition.equalsParams.keySet(); - for(String name : keys){ - addSqlBuf.append(name + " = :" + condition.filterKeyWord(name) + " and "); - } - } - return this; - } - - /** - * 大于条件 - * @param sql - * @return - */ - public SqlBuider addGreater(){ - if(null != condition.greaterParams && condition.greaterParams.size() > 0){ - if(addSqlBuf.indexOf("where") == -1){ - addSqlBuf.append(" where "); - } - Set keys = condition.greaterParams.keySet(); - for(String name : keys){ - addSqlBuf.append(name + " > :" + condition.filterKeyWord(name) + " and "); - } - } - return this; - } - - /** - * 小于条件 - * - * @param sql - * @return - */ - public SqlBuider addLess(){ - if(null != condition.lessParams && condition.lessParams.size() > 0){ - if(addSqlBuf.indexOf("where") == -1){ - addSqlBuf.append(" where "); - } - Set keys = condition.lessParams.keySet(); - for(String name : keys){ - addSqlBuf.append(name + " < :" + condition.filterKeyWord(name) + " and "); - } - } - return this; - } - - /** - * 大于等于条件 - * @param sql - * @return - */ - public SqlBuider addGreaterThan(){ - if(null != condition.greaterThanParams && condition.greaterThanParams.size() > 0){ - if(addSqlBuf.indexOf("where") == -1){ - addSqlBuf.append(" where "); - } - Set keys = condition.greaterThanParams.keySet(); - for(String name : keys){ - addSqlBuf.append(name + " >= :" + condition.filterKeyWord(name) + " and "); - } - } - return this; - } - - public SqlBuider addLessThan(){ - // 小于等于条件 - if(null != condition.lessThanParams && condition.lessThanParams.size() > 0){ - if(addSqlBuf.indexOf("where") == -1){ - addSqlBuf.append(" where "); - } - Set keys = condition.lessThanParams.keySet(); - for(String name : keys){ - addSqlBuf.append(name + " <= :" + condition.filterKeyWord(name) + " and "); - } - } - return this; - } - - public SqlBuider addLike(){ - // like条件 - if(null != condition.likeParams && condition.likeParams.size() > 0){ - if(addSqlBuf.indexOf("where") == -1){ - addSqlBuf.append(" where "); - } - Set keys = condition.likeParams.keySet(); - for(String name : keys){ - addSqlBuf.append(name + " like :" + condition.filterKeyWord(name) + " and "); - } - } - return this; - } - - public SqlBuider addIn(){ - // in条件 - if(null != condition.inParams && condition.inParams.size() > 0){ - if(addSqlBuf.indexOf("where") == -1){ - addSqlBuf.append(" where "); - } - Set keys = condition.inParams.keySet(); - for (String name : keys) { - int len = condition.inParams.get(name).length; - addSqlBuf.append(name + " in ("); - for (int i = 0; i < len; i++) { - if (i != len - 1) { - addSqlBuf.append(":" + condition.filterKeyWord(name) + "_" + i - + ", "); - } else { - addSqlBuf.append(":" + condition.filterKeyWord(name) + "_" + i); - } - } - addSqlBuf.append(") and "); - } - } - return this; - } - - public String addAsString(){ - if(null == addSqlBuf){ - return ""; - } - return addSqlBuf.toString(); - } - - /******************************A:E**********************************/ -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/Table.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/Table.java deleted file mode 100644 index 8d9ba4eb4..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/Table.java +++ /dev/null @@ -1,26 +0,0 @@ -package blade.plugin.sql2o; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * model表关联注解 - * - * @author biezhi - * @since 1.0 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Table { - - String value(); - - String PK() default "id"; - - boolean isCache() default true; - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java deleted file mode 100644 index cd6ed2107..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/WhereParam.java +++ /dev/null @@ -1,189 +0,0 @@ -package blade.plugin.sql2o; - -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import blade.kit.CollectionKit; -import blade.kit.StringKit; - - -/** - * 参数存储对象 - * @author biezhi - * @since 1.0 - * @param - */ -public class WhereParam { - - // 存储设置的参数,insert-update用 - Map params; - - // 存储where条件,select-update-delete用 - Map equalsParams; - - // 大于 - Map greaterParams; - // 大于等于 - Map greaterThanParams; - // 小于 - Map lessParams; - // 小于等于 - Map lessThanParams; - // like - Map likeParams; - // in - Map inParams; - - List logParams = new LinkedList(); - - public WhereParam() { - params = CollectionKit.newHashMap(); - equalsParams = CollectionKit.newHashMap(); - greaterParams = CollectionKit.newHashMap(); - greaterThanParams = CollectionKit.newHashMap(); - lessParams = CollectionKit.newHashMap(); - lessThanParams = CollectionKit.newHashMap(); - likeParams = CollectionKit.newHashMap(); - inParams = CollectionKit.newHashMap(); - } - - public static WhereParam me(){ - return new WhereParam(); - } - - public WhereParam eq(String field, Object value){ - if(StringKit.isNotBlank(field) && null != value){ - this.equalsParams.put(field, value); - this.logParams.add(value); - } - return this; - } - - public Object eq(String field){ - if(StringKit.isNotBlank(field)){ - return this.equalsParams.get(field); - } - return null; - } - - public String like(String field){ - if(StringKit.isNotBlank(field)){ - return this.likeParams.get(field); - } - return null; - } - - public Object less(String field){ - if(StringKit.isNotBlank(field)){ - return this.lessParams.get(field); - } - return null; - } - - public Object lessThan(String field){ - if(StringKit.isNotBlank(field)){ - return this.lessThanParams.get(field); - } - return null; - } - - public Object greater(String field){ - if(StringKit.isNotBlank(field)){ - return this.greaterParams.get(field); - } - return null; - } - - public Object greaterThan(String field){ - if(StringKit.isNotBlank(field)){ - return this.greaterThanParams.get(field); - } - return null; - } - - public Object[] in(String field){ - if(StringKit.isNotBlank(field)){ - return this.inParams.get(field); - } - return null; - } - - public WhereParam like(String field, String value){ - if(StringKit.isNotBlank(field) && StringKit.isNotBlank(value) - && value.indexOf("%null")==-1 && value.indexOf("null%")==-1 && !value.equals("%%")){ - - if(null == this.likeParams){ - this.likeParams = CollectionKit.newLinkedHashMap(); - } - this.likeParams.put(field, value); - this.logParams.add(value); - } - return this; - } - - public WhereParam in(String field, Object... values){ - if(StringKit.isNotBlank(field) && null != values && values.length > 0){ - if(null == this.inParams){ - this.inParams = CollectionKit.newLinkedHashMap(); - } - this.inParams.put(field, values); - this.logParams.add(Arrays.toString(values)); - } - return this; - } - - public WhereParam less(String field, Object value){ - if(StringKit.isNotBlank(field) && null != value){ - if(null == this.lessParams){ - this.lessParams = CollectionKit.newLinkedHashMap(); - } - this.lessParams.put(field, value); - this.logParams.add(value); - } - return this; - } - - public WhereParam lessThan(String field, Object value){ - if(StringKit.isNotBlank(field) && null != value){ - - if(null == this.lessThanParams){ - this.lessThanParams = CollectionKit.newLinkedHashMap(); - } - this.lessThanParams.put(field, value); - this.logParams.add(value); - } - return this; - } - - public WhereParam greater(String field, Object value){ - if(StringKit.isNotBlank(field) && null != value){ - if(null == this.greaterParams){ - this.greaterParams = CollectionKit.newLinkedHashMap(); - } - this.greaterParams.put(field, value); - this.logParams.add(value); - } - return this; - } - - public WhereParam greaterThan(String field, Object value){ - if(StringKit.isNotBlank(field) && null != value){ - if(null == this.greaterThanParams){ - this.greaterThanParams = CollectionKit.newLinkedHashMap(); - } - this.greaterThanParams.put(field, value); - this.logParams.add(value); - } - return this; - } - - public WhereParam set(String field, Object value){ - if(StringKit.isNotBlank(field) && null != value){ - this.params.put(field, value); - this.logParams.add(value); - } - return this; - } -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/CacheType.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/CacheType.java deleted file mode 100644 index ed6b2b0f9..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/CacheType.java +++ /dev/null @@ -1,7 +0,0 @@ -package blade.plugin.sql2o.cache; - -public enum CacheType { - - list, count, detail, sqllist, sqlcount, sqldetail - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java deleted file mode 100644 index 3275c1727..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/SimpleSql2oCache.java +++ /dev/null @@ -1,121 +0,0 @@ -package blade.plugin.sql2o.cache; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; - -import blade.cache.Cache; -import blade.cache.CacheException; -import blade.cache.CacheManager; - -@SuppressWarnings("unchecked") -public class SimpleSql2oCache implements Sql2oCache { - - private CacheManager cm = CacheManager.me(); - - private static final String CACHE_ID = "sql2o_cache"; - - private Cache cache; - - public SimpleSql2oCache() { - // 5小时清理一次 - long cleanTime = 1000 * 3600 * 300; - cm.setCleanInterval(cleanTime); - // 存放1000个缓存,超过即自动清除 - cache = cm.newLRUCache(CACHE_ID).cacheSize(1000); - } - - @Override - public void hset(String key, String field, Serializable value) { - cache.hset(key, field, value); - } - - @Override - public V hgetV(String key, String field) { - Object value = cache.hget(key, field); - if(null != value){ - return (V) value; - } - return null; - } - - @Override - public void hsetV(String key, String field, Object value) { - cache.hset(key, field, value); - } - - @Override - public Serializable hget(String key, String field) { - Object object = cache.hget(key, field); - if(null != object){ - return (Serializable) object; - } - return null; - } - - - @Override - public List hgetlist(String key, String field) { - Object object = cache.hget(key, field); - if(null != object){ - return (List) object; - } - return null; - } - - @Override - public List> hgetlistmap(String key, String field) { - Object object = cache.hget(key, field); - if(null != object){ - return (List>) object; - } - return null; - } - - @Override - public List hgetlists(String key, String field) { - Object object = cache.hget(key, field); - if(null != object){ - return (List) object; - } - return null; - } - - @Override - public void hdel(String key) { - cache.hdel(key); - } - - @Override - public void hsetlist(String key, String field, List value) { - cache.hset(key, field, value); - } - - @Override - public void hsetlistmap(String key, String field, List> value) { - cache.hset(key, field, value); - } - - @Override - public void hsetlists(String key, String field, List value) { - cache.hset(key, field, value); - } - - @Override - public void clean() { - cache.clear(); - } - - @Override - public void destroy() throws CacheException { - try { - CacheManager.me().destroy(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java deleted file mode 100644 index 7e4afb8b5..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCache.java +++ /dev/null @@ -1,36 +0,0 @@ -package blade.plugin.sql2o.cache; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; - -import blade.cache.CacheException; - -public interface Sql2oCache { - - void hset(String key, String field, Serializable value); - - void hsetV(String key, String field, Object value); - - void hsetlist(String key, String field, List value); - - void hsetlistmap(String key, String field, List> value); - - void hsetlists(String key, String field, List value); - - T hget(String key, String field); - - V hgetV(String key, String field); - - List hgetlist(String key, String field); - - List> hgetlistmap(String key, String field); - - List hgetlists(String key, String field); - - void hdel(String key); - - void clean(); - - void destroy() throws CacheException; -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCacheFactory.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCacheFactory.java deleted file mode 100644 index 689277f97..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/cache/Sql2oCacheFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package blade.plugin.sql2o.cache; - - -/** - * 缓存获取工厂 - * - * @author biezhi - * @since 1.0 - */ -public final class Sql2oCacheFactory { - - private static Sql2oCache sql2oCache = new SimpleSql2oCache(); - - public static Sql2oCache getSql2oCache(){ - return sql2oCache; - } - - /** - * 设置缓存 - * - * @param sql2oCache - */ - public static void setSql2oCache(Sql2oCache sql2oCache){ - Sql2oCacheFactory.sql2oCache = sql2oCache; - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java deleted file mode 100644 index e27d0fac2..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/ds/DataSourceManager.java +++ /dev/null @@ -1,70 +0,0 @@ -package blade.plugin.sql2o.ds; - -import javax.sql.DataSource; - -import org.sql2o.Sql2o; - -import com.blade.Blade; - -import blade.plugin.sql2o.DBConfig; -import blade.plugin.sql2o.Sql2oPlugin; -import blade.plugin.sql2o.exception.DataSourceException; - -/** - * 数据源连接管理器 - * @author biezhi - * @version 1.0 - */ -public final class DataSourceManager { - - private static final DataSourceManager DATA_SOURCE_MANAGER = new DataSourceManager(); - - private DataSource dataSource; - - private Sql2o sql2o = null; - - private DataSourceManager() { - } - - public static DataSourceManager me(){ - return DATA_SOURCE_MANAGER; - } - - public void run(){ - if(null != this.dataSource){ - sql2o = new Sql2o(this.dataSource); - } else { - Sql2oPlugin sql2oPlugin = Blade.me().plugin(Sql2oPlugin.class); - DBConfig dbConfig = sql2oPlugin.dbConfig(); - if(null == dbConfig){ - throw new DataSourceException("数据库配置失败"); - } - try { - Class.forName(dbConfig.getDriverName()); - sql2o = new Sql2o(dbConfig.getUrl(), dbConfig.getUserName(), dbConfig.getPassWord()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } - } - - public synchronized Sql2o getSql2o(){ - return sql2o; - } - - /** - * 提供动态注入datasource - * @param dataSource_ - */ - public void setDataSource(DataSource dataSource){ - this.dataSource = dataSource; - if(null != this.dataSource){ - sql2o = new Sql2o(this.dataSource); - } - } - - public DataSource getDataSource(){ - return dataSource; - } - -} diff --git a/blade-sql2o/src/main/java/blade/plugin/sql2o/exception/DataSourceException.java b/blade-sql2o/src/main/java/blade/plugin/sql2o/exception/DataSourceException.java deleted file mode 100644 index 04b590657..000000000 --- a/blade-sql2o/src/main/java/blade/plugin/sql2o/exception/DataSourceException.java +++ /dev/null @@ -1,27 +0,0 @@ -package blade.plugin.sql2o.exception; - - -/** - * DataSourceException - *

- *

- * - * @author biezhi - * @since 1.0 - */ -public class DataSourceException extends RuntimeException{ - - private static final long serialVersionUID = 4566581404090220394L; - - public DataSourceException() { - throw new RuntimeException(); - } - - public DataSourceException(String e) { - throw new RuntimeException(e); - } - - public DataSourceException(Exception e) { - throw new RuntimeException(e); - } -} From f826c854d3870414e9fd66c6e7e54409526c0910 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 14 Feb 2016 15:49:02 +0800 Subject: [PATCH 399/545] add blade-jdbc --- .../src/main/java/com/blade/jdbc/Page.java | 184 ++++++++++++++++++ .../src/main/java/com/blade/jdbc/Table.java | 26 +++ .../java/com/blade/jdbc/cache/CacheType.java | 7 + .../blade/jdbc/cache/SimpleSql2oCache.java | 121 ++++++++++++ .../java/com/blade/jdbc/cache/Sql2oCache.java | 36 ++++ .../blade/jdbc/cache/Sql2oCacheFactory.java | 27 +++ .../jdbc/exception/DataSourceException.java | 27 +++ 7 files changed, 428 insertions(+) create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/Page.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/Table.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/cache/CacheType.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/cache/SimpleSql2oCache.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCache.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCacheFactory.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/exception/DataSourceException.java diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/Page.java b/blade-jdbc/src/main/java/com/blade/jdbc/Page.java new file mode 100644 index 000000000..5a789cee6 --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/Page.java @@ -0,0 +1,184 @@ +package com.blade.jdbc; + +import java.util.ArrayList; +import java.util.List; + +/** + * 分页类 + * + * @author biezhi + * @since 1.0 + * @param + */ +public class Page { + + /** + * 当前页 + */ + private int page = 1; + + /** + * 每页条数 + */ + private int pageSize = 10; + + /** + * 总页数 + */ + private int totalPage = 1; + + /** + * 总记录数 + */ + private long totalCount = 0L; + /** + * 上一页 + */ + private int prev_page = 1; + /** + * 下一页 + */ + private int next_page = 1; + /** + * 首页 + */ + private int home_page = 1; + /** + * 尾页 + */ + private Integer last_page = 1; + + /** + * 链接 + */ + private String url = ""; + /** + * 固定导航数 + */ + private Integer navNum = 1; + + /** + * 数据集 + */ + private List results = new ArrayList(); + + /** + * @param totleCount 总记录数 + * @param page 当前第几页 + * @param pageSize 每页显示条数 + */ + public Page(long totalCount, int page, int pageSize) { + + this.page = page; + + this.pageSize = pageSize; + + //总条数 + this.totalCount = totalCount; + + //总页数 + this.totalPage = ((int) ((this.totalCount + this.pageSize - 1) / pageSize)); + + //首页 + this.home_page = 1; + + //尾页 + this.last_page = totalPage; + + //上一页 + this.prev_page = Math.max(this.page - 1, home_page); + + //下一页 + this.next_page = Math.min(this.page + 1, last_page); + + } + + public int getPage() { + return this.page; + } + + public Integer getPageSize() { + return this.pageSize; + } + + public int getTotalPage() { + return this.totalPage; + } + + public long getTotalCount() { + return totalCount; + } + + public Integer getPrev_page() { + return this.prev_page; + } + + public Integer getNext_page() { + return this.next_page; + } + + public Integer getHome_page() { + return this.home_page; + } + + public Integer getLast_page() { + return this.last_page; + } + + public List getResults() { + return this.results; + } + + public void setResults(List results) { + this.results = results; + } + + public Integer getNavNum() { + return this.navNum; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setPage(int page) { + this.page = page; + } + + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + } + + public void setTotalPage(int totalPage) { + this.totalPage = totalPage; + } + + public void setTotalCount(long totalCount) { + this.totalCount = totalCount; + } + + public void setPrev_page(int prev_page) { + this.prev_page = prev_page; + } + + public void setNext_page(int next_page) { + this.next_page = next_page; + } + + public void setHome_page(int home_page) { + this.home_page = home_page; + } + + public void setLast_page(Integer last_page) { + this.last_page = last_page; + } + + public void setNavNum(Integer navNum) { + this.navNum = navNum; + } + +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/Table.java b/blade-jdbc/src/main/java/com/blade/jdbc/Table.java new file mode 100644 index 000000000..4d26bf4f0 --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/Table.java @@ -0,0 +1,26 @@ +package com.blade.jdbc; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * model表关联注解 + * + * @author biezhi + * @since 1.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Table { + + String value(); + + String PK() default "id"; + + boolean isCache() default true; + +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/cache/CacheType.java b/blade-jdbc/src/main/java/com/blade/jdbc/cache/CacheType.java new file mode 100644 index 000000000..f9f8f7e82 --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/cache/CacheType.java @@ -0,0 +1,7 @@ +package com.blade.jdbc.cache; + +public enum CacheType { + + list, count, detail, sqllist, sqlcount, sqldetail + +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/cache/SimpleSql2oCache.java b/blade-jdbc/src/main/java/com/blade/jdbc/cache/SimpleSql2oCache.java new file mode 100644 index 000000000..90984111a --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/cache/SimpleSql2oCache.java @@ -0,0 +1,121 @@ +package com.blade.jdbc.cache; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import blade.cache.Cache; +import blade.cache.CacheException; +import blade.cache.CacheManager; + +@SuppressWarnings("unchecked") +public class SimpleSql2oCache implements Sql2oCache { + + private CacheManager cm = CacheManager.me(); + + private static final String CACHE_ID = "sql2o_cache"; + + private Cache cache; + + public SimpleSql2oCache() { + // 5小时清理一次 + long cleanTime = 1000 * 3600 * 300; + cm.setCleanInterval(cleanTime); + // 存放1000个缓存,超过即自动清除 + cache = cm.newLRUCache(CACHE_ID).cacheSize(1000); + } + + @Override + public void hset(String key, String field, Serializable value) { + cache.hset(key, field, value); + } + + @Override + public V hgetV(String key, String field) { + Object value = cache.hget(key, field); + if(null != value){ + return (V) value; + } + return null; + } + + @Override + public void hsetV(String key, String field, Object value) { + cache.hset(key, field, value); + } + + @Override + public Serializable hget(String key, String field) { + Object object = cache.hget(key, field); + if(null != object){ + return (Serializable) object; + } + return null; + } + + + @Override + public List hgetlist(String key, String field) { + Object object = cache.hget(key, field); + if(null != object){ + return (List) object; + } + return null; + } + + @Override + public List> hgetlistmap(String key, String field) { + Object object = cache.hget(key, field); + if(null != object){ + return (List>) object; + } + return null; + } + + @Override + public List hgetlists(String key, String field) { + Object object = cache.hget(key, field); + if(null != object){ + return (List) object; + } + return null; + } + + @Override + public void hdel(String key) { + cache.hdel(key); + } + + @Override + public void hsetlist(String key, String field, List value) { + cache.hset(key, field, value); + } + + @Override + public void hsetlistmap(String key, String field, List> value) { + cache.hset(key, field, value); + } + + @Override + public void hsetlists(String key, String field, List value) { + cache.hset(key, field, value); + } + + @Override + public void clean() { + cache.clear(); + } + + @Override + public void destroy() throws CacheException { + try { + CacheManager.me().destroy(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCache.java b/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCache.java new file mode 100644 index 000000000..15715d77f --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCache.java @@ -0,0 +1,36 @@ +package com.blade.jdbc.cache; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +import blade.cache.CacheException; + +public interface Sql2oCache { + + void hset(String key, String field, Serializable value); + + void hsetV(String key, String field, Object value); + + void hsetlist(String key, String field, List value); + + void hsetlistmap(String key, String field, List> value); + + void hsetlists(String key, String field, List value); + + T hget(String key, String field); + + V hgetV(String key, String field); + + List hgetlist(String key, String field); + + List> hgetlistmap(String key, String field); + + List hgetlists(String key, String field); + + void hdel(String key); + + void clean(); + + void destroy() throws CacheException; +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCacheFactory.java b/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCacheFactory.java new file mode 100644 index 000000000..d133f5137 --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCacheFactory.java @@ -0,0 +1,27 @@ +package com.blade.jdbc.cache; + + +/** + * 缓存获取工厂 + * + * @author biezhi + * @since 1.0 + */ +public final class Sql2oCacheFactory { + + private static Sql2oCache sql2oCache = new SimpleSql2oCache(); + + public static Sql2oCache getSql2oCache(){ + return sql2oCache; + } + + /** + * 设置缓存 + * + * @param sql2oCache + */ + public static void setSql2oCache(Sql2oCache sql2oCache){ + Sql2oCacheFactory.sql2oCache = sql2oCache; + } + +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/exception/DataSourceException.java b/blade-jdbc/src/main/java/com/blade/jdbc/exception/DataSourceException.java new file mode 100644 index 000000000..00666a0aa --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/exception/DataSourceException.java @@ -0,0 +1,27 @@ +package com.blade.jdbc.exception; + + +/** + * DataSourceException + *

+ *

+ * + * @author biezhi + * @since 1.0 + */ +public class DataSourceException extends RuntimeException{ + + private static final long serialVersionUID = 4566581404090220394L; + + public DataSourceException() { + throw new RuntimeException(); + } + + public DataSourceException(String e) { + throw new RuntimeException(e); + } + + public DataSourceException(Exception e) { + throw new RuntimeException(e); + } +} From 460f06c81c430ca6502723250c46a856c63897bd Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 14 Feb 2016 15:49:50 +0800 Subject: [PATCH 400/545] add blade-jdbc --- LAST_VERSION.md | 12 ++---------- blade-jdbc/pom.xml | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 blade-jdbc/pom.xml diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 07d10f28b..7d495e53d 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -24,7 +24,7 @@     com.bladejava     blade-kit -    1.2.8 +    1.2.9-alpha ``` @@ -33,15 +33,7 @@     com.bladejava     blade-core -    1.5.1 - -``` -## [blade-sql2o](http://search.maven.org/#search%7Cga%7C1%7Cblade-sql2o) -```xml - -    com.bladejava -    blade-sql2o -    1.3.0-alpha +    1.6.0-alpha ``` diff --git a/blade-jdbc/pom.xml b/blade-jdbc/pom.xml new file mode 100644 index 000000000..cb9af838b --- /dev/null +++ b/blade-jdbc/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + + blade-jdbc + jar + 0.0.1 + blade-jdbc + https://github.com/biezhi/blade/tree/master/blade-jdbc + + + + com.bladejava + blade-core + ${blade.version} + provided + + + com.bladejava + blade-cache + 1.2.3 + provided + + + org.sql2o + sql2o + 1.5.4 + + + From 970e5280dd84734afd9026a475d737ad52242131 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 14 Feb 2016 15:50:13 +0800 Subject: [PATCH 401/545] update Class name --- blade-core/src/main/java/com/blade/Blade.java | 25 +++++++------------ .../blade/view/template/TemplteEngine.java | 2 +- .../com/blade/web/SyncRequestHandler.java | 2 +- pom.xml | 4 +-- 4 files changed, 13 insertions(+), 20 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 326ed772c..32893f5a9 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -81,7 +81,7 @@ public class Blade { /** * default render is jspRender */ - private TemplteEngine render = null; + private TemplteEngine templteEngine = null; /** * manage route @@ -103,7 +103,7 @@ private Blade() { this.ioc = new SampleIoc(); this.iocApplication = new IocApplication(ioc); this.routers = new Routers(ioc); - this.render = new JspEngine(); + this.templteEngine = new JspEngine(); } public static final class BladeHolder { @@ -187,14 +187,7 @@ public Blade routes(String...packages){ return this; } - /** - * Setting top package frame automatically for routing packets and packet interceptor, e.g:com.bladejava - * As above, it will be over:com.bladejava.route、com.bladejava.interceptor Routing and interceptor inside - * - * @param basePackage default package path - * @return return blade - */ - public Blade defaultRoute(String basePackage){ + public Blade basePackage(String basePackage){ Assert.notBlank(basePackage); bladeConfig.setBasePackage(basePackage); return this; @@ -400,12 +393,12 @@ public Blade after(String path, RouteHandler handler){ /** * Setting Render Engin, Default is JspRender * - * @param render Render engine object + * @param templteEngine Render engine object * @return return blade */ - public Blade viewEngin(TemplteEngine render) { - Assert.notNull(render); - this.render = render; + public Blade viewEngin(TemplteEngine templteEngine) { + Assert.notNull(templteEngine); + this.templteEngine = templteEngine; return this; } @@ -657,8 +650,8 @@ public Bootstrap bootstrap(){ /** * @return Return current render engine */ - public TemplteEngine render() { - return this.render; + public TemplteEngine templteEngine() { + return this.templteEngine; } /** diff --git a/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java b/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java index 7f7fff089..15d062fe9 100644 --- a/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java @@ -18,7 +18,7 @@ import java.io.Writer; /** - * Render Interface, For view layer to display data + * TemplteEngine Interface, For view layer to display data * * @author biezhi * @since 1.0 diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index a4a9b0ddd..6bc0e61b8 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -93,7 +93,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo Request request = new ServletRequest(httpRequest); // Create Response - response = new ServletResponse(httpResponse, blade.render()); + response = new ServletResponse(httpResponse, blade.templteEngine()); // Init Context BladeWebContext.setContext(servletContext, request, response); diff --git a/pom.xml b/pom.xml index 03cbabd17..0e387335f 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.5.2-alpha + 1.6.0-alpha 4.12 @@ -23,7 +23,7 @@ blade-kit blade-core blade-cache - blade-sql2o + blade-jdbc blade-redis blade-startup blade-aop From 9d785999af1e6e224a329e447179064980e2c5d1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 14 Feb 2016 15:59:29 +0800 Subject: [PATCH 402/545] fix name --- blade-core/src/main/java/com/blade/Blade.java | 22 +++++++++---------- .../src/main/java/com/blade/route/C.java | 17 ++++++++++++++ .../com/blade/view/template/JspEngine.java | 2 +- ...TemplteEngine.java => TemplateEngine.java} | 6 ++--- ...eException.java => TemplateException.java} | 12 +++++----- .../com/blade/web/SyncRequestHandler.java | 2 +- .../web/http/wrapper/ServletResponse.java | 6 ++--- 7 files changed, 42 insertions(+), 25 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/route/C.java rename blade-core/src/main/java/com/blade/view/template/{TemplteEngine.java => TemplateEngine.java} (85%) rename blade-core/src/main/java/com/blade/view/template/{TemplteException.java => TemplateException.java} (74%) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 32893f5a9..435cca52a 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -32,7 +32,7 @@ import com.blade.route.loader.ClassPathRouteLoader; import com.blade.server.Server; import com.blade.view.template.JspEngine; -import com.blade.view.template.TemplteEngine; +import com.blade.view.template.TemplateEngine; import com.blade.web.BladeBanner; import com.blade.web.http.HttpMethod; @@ -81,7 +81,7 @@ public class Blade { /** * default render is jspRender */ - private TemplteEngine templteEngine = null; + private TemplateEngine templateEngine = null; /** * manage route @@ -103,7 +103,7 @@ private Blade() { this.ioc = new SampleIoc(); this.iocApplication = new IocApplication(ioc); this.routers = new Routers(ioc); - this.templteEngine = new JspEngine(); + this.templateEngine = new JspEngine(); } public static final class BladeHolder { @@ -393,12 +393,12 @@ public Blade after(String path, RouteHandler handler){ /** * Setting Render Engin, Default is JspRender * - * @param templteEngine Render engine object - * @return return blade + * @param templateEngine Render engine object + * @return return blade */ - public Blade viewEngin(TemplteEngine templteEngine) { - Assert.notNull(templteEngine); - this.templteEngine = templteEngine; + public Blade viewEngin(TemplateEngine templateEngine) { + Assert.notNull(templateEngine); + this.templateEngine = templateEngine; return this; } @@ -648,10 +648,10 @@ public Bootstrap bootstrap(){ } /** - * @return Return current render engine + * @return Return current templateEngine */ - public TemplteEngine templteEngine() { - return this.templteEngine; + public TemplateEngine templateEngine() { + return this.templateEngine; } /** diff --git a/blade-core/src/main/java/com/blade/route/C.java b/blade-core/src/main/java/com/blade/route/C.java new file mode 100644 index 000000000..4166f4ce9 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/C.java @@ -0,0 +1,17 @@ +package com.blade.route; + +import java.util.Map; + +import com.blade.view.template.ModelAndView; + +public class C { + + public ModelAndView render(String view){ + return new ModelAndView(view); + } + + public ModelAndView render(Map model, String view){ + return new ModelAndView(model, view); + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/view/template/JspEngine.java index dd240cba1..ee91ee970 100644 --- a/blade-core/src/main/java/com/blade/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/JspEngine.java @@ -35,7 +35,7 @@ * @author biezhi * @since 1.0 */ -public final class JspEngine implements TemplteEngine { +public final class JspEngine implements TemplateEngine { private static final Logger LOGGER = LoggerFactory.getLogger(JspEngine.class); diff --git a/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java b/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java similarity index 85% rename from blade-core/src/main/java/com/blade/view/template/TemplteEngine.java rename to blade-core/src/main/java/com/blade/view/template/TemplateEngine.java index 15d062fe9..38ac929b6 100644 --- a/blade-core/src/main/java/com/blade/view/template/TemplteEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java @@ -18,13 +18,13 @@ import java.io.Writer; /** - * TemplteEngine Interface, For view layer to display data + * TemplateEngine Interface, For view layer to display data * * @author biezhi * @since 1.0 */ -public interface TemplteEngine { +public interface TemplateEngine { - public void render(ModelAndView modelAndView, Writer writer) throws TemplteException; + public void render(ModelAndView modelAndView, Writer writer) throws TemplateException; } diff --git a/blade-core/src/main/java/com/blade/view/template/TemplteException.java b/blade-core/src/main/java/com/blade/view/template/TemplateException.java similarity index 74% rename from blade-core/src/main/java/com/blade/view/template/TemplteException.java rename to blade-core/src/main/java/com/blade/view/template/TemplateException.java index cbd95c986..517d6f0b0 100644 --- a/blade-core/src/main/java/com/blade/view/template/TemplteException.java +++ b/blade-core/src/main/java/com/blade/view/template/TemplateException.java @@ -16,28 +16,28 @@ package com.blade.view.template; /** - * RenderException + * TemplateException * * @author biezhi * @since 1.0 */ -public class TemplteException extends RuntimeException { +public class TemplateException extends RuntimeException { private static final long serialVersionUID = 1L; - public TemplteException() { + public TemplateException() { super(); } - public TemplteException(String message, Throwable cause) { + public TemplateException(String message, Throwable cause) { super(message, cause); } - public TemplteException(String message) { + public TemplateException(String message) { super(message); } - public TemplteException(Throwable cause) { + public TemplateException(Throwable cause) { super(cause); } diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index 6bc0e61b8..44ee1c761 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -93,7 +93,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo Request request = new ServletRequest(httpRequest); // Create Response - response = new ServletResponse(httpResponse, blade.templteEngine()); + response = new ServletResponse(httpResponse, blade.templateEngine()); // Init Context BladeWebContext.setContext(servletContext, request, response); diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index 80a9a344b..6ee07fb5c 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -25,7 +25,7 @@ import com.blade.context.BladeWebContext; import com.blade.view.template.ModelAndView; -import com.blade.view.template.TemplteEngine; +import com.blade.view.template.TemplateEngine; import com.blade.web.http.HttpStatus; import com.blade.web.http.Path; import com.blade.web.http.Request; @@ -45,9 +45,9 @@ public class ServletResponse implements Response { private boolean written = false; - private TemplteEngine render; + private TemplateEngine render; - public ServletResponse(HttpServletResponse response, TemplteEngine render) { + public ServletResponse(HttpServletResponse response, TemplateEngine render) { this.response = response; this.render = render; } From 6c30faa4a12f657098bc73227b2a925f92ab4690 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 14 Feb 2016 21:42:57 +0800 Subject: [PATCH 403/545] support for no web project --- blade-core/src/main/java/com/blade/Blade.java | 18 +++++-- .../com/blade/{ => ioc}/IocApplication.java | 4 +- .../java/com/blade/loader/BladeConfig.java | 14 ++--- .../main/java/com/blade/route/Routers.java | 4 +- .../main/java/com/blade/server/Server.java | 21 ++++---- .../main/java/com/blade/web/DispatchKit.java | 52 +++++++++++++++++++ .../java/com/blade/web/DispatcherServlet.java | 26 ++++++++-- .../java/com/blade/web/RouteArgument.java | 3 +- .../java/com/blade/web/StaticFileFilter.java | 41 +++++++++++++++ .../com/blade/web/SyncRequestHandler.java | 43 ++++++--------- .../java/com/blade/web/http/Response.java | 2 +- blade-core/src/main/java/default.properties | 2 +- .../kit/config/adapter/PropConfigAdapter.java | 2 +- 13 files changed, 169 insertions(+), 63 deletions(-) rename blade-core/src/main/java/com/blade/{ => ioc}/IocApplication.java (94%) create mode 100644 blade-core/src/main/java/com/blade/web/DispatchKit.java create mode 100644 blade-core/src/main/java/com/blade/web/StaticFileFilter.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 435cca52a..c6014e77e 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -18,8 +18,10 @@ import java.io.InputStream; import java.text.ParseException; import java.util.List; +import java.util.Set; import com.blade.ioc.Ioc; +import com.blade.ioc.IocApplication; import com.blade.ioc.SampleIoc; import com.blade.loader.BladeConfig; import com.blade.loader.Configurator; @@ -121,9 +123,11 @@ public static final Blade me(){ * Set Blade initialize * @param isInit initialize */ - public void setInit(boolean isInit) { - this.isInit = isInit; - new BladeBanner().print(System.out); + public synchronized void init() { + if(!this.isInit){ + this.isInit = true; + new BladeBanner().print(System.out); + } } /** @@ -636,7 +640,7 @@ public boolean isDev(){ /** * @return Return static resource directory */ - public String[] staticFolder(){ + public Set staticFolder(){ return bladeConfig.getStaticFolders(); } @@ -734,4 +738,8 @@ public boolean isInit() { return isInit; } -} + public boolean httpCache() { + return bladeConfig.isHttpCache(); + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java similarity index 94% rename from blade-core/src/main/java/com/blade/IocApplication.java rename to blade-core/src/main/java/com/blade/ioc/IocApplication.java index 1d5a53602..1084928ee 100644 --- a/blade-core/src/main/java/com/blade/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade; +package com.blade.ioc; import java.util.ArrayList; import java.util.List; @@ -22,7 +22,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.blade.ioc.Ioc; +import com.blade.Bootstrap; import com.blade.plugin.Plugin; import blade.kit.resource.ClassPathClassReader; diff --git a/blade-core/src/main/java/com/blade/loader/BladeConfig.java b/blade-core/src/main/java/com/blade/loader/BladeConfig.java index ffab6e32a..77b27dd4c 100644 --- a/blade-core/src/main/java/com/blade/loader/BladeConfig.java +++ b/blade-core/src/main/java/com/blade/loader/BladeConfig.java @@ -16,10 +16,11 @@ package com.blade.loader; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; +import blade.kit.CollectionKit; import blade.kit.PatternKit; import blade.kit.config.Config; import blade.kit.config.loader.ConfigLoader; @@ -37,13 +38,13 @@ public class BladeConfig { private Map configMap; // Storage of all routing packets - private List routePackages = Collections.emptyList(); + private List routePackages = CollectionKit.newArrayList(); // Store all IOC packages - private List iocPackages = Collections.emptyList(); + private List iocPackages = CollectionKit.newArrayList(); // Store all filter directories - private List staticFolders = Collections.emptyList(); + private Set staticFolders = CollectionKit.newHashSet(); // Base package private String basePackage; @@ -174,9 +175,8 @@ public void setInterceptorPackage(String interceptorPackage) { this.interceptorPackage = interceptorPackage; } - public String[] getStaticFolders() { - String[] folderArr = new String[staticFolders.size()]; - return staticFolders.toArray(folderArr); + public Set getStaticFolders() { + return staticFolders; } public void setStaticFolders(String ... packages) { diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index f46ce107b..b90d87ad4 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -114,10 +114,10 @@ public void addRoute(HttpMethod httpMethod, String path, Object controller, Meth LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); } this.interceptors.put(key, route); - LOGGER.debug("Add Interceptor:{}", route); + LOGGER.info("Add Interceptor:{}", route); } else { this.routes.put(key, route); - LOGGER.debug("Add Route:{}", route); + LOGGER.info("Add Route:{}", route); } } diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java index 160653fec..34166ef76 100644 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -34,41 +34,40 @@ public class Server { private int port = 9000; - private boolean async = false; - private org.eclipse.jetty.server.Server server; private ServletContextHandler context; public Server(int port, boolean async) { this.port = port; - this.async = async; } public void setPort(int port){ this.port = port; } - public void setAsync(boolean async) { - this.async = async; - } - public void start(String contextPath) throws Exception{ server = new org.eclipse.jetty.server.Server(this.port); - + // 设置在JVM退出时关闭Jetty的钩子。 + server.setStopAtShutdown(true); + context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath(contextPath); - context.setResourceBase(System.getProperty("java.io.tmpdir")); + + context.setResourceBase(Thread.currentThread().getContextClassLoader() + .getResource("").getPath()); ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); - servletHolder.setAsyncSupported(async); + servletHolder.setAsyncSupported(false); + servletHolder.setInitOrder(1); context.addServlet(servletHolder, "/"); server.setHandler(this.context); server.start(); + // server.dump(System.err); - LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); + LOGGER.info("Blade Server Listen on http://127.0.0.1:{}", this.port); } public void join() throws InterruptedException { diff --git a/blade-core/src/main/java/com/blade/web/DispatchKit.java b/blade-core/src/main/java/com/blade/web/DispatchKit.java new file mode 100644 index 000000000..93b7f8751 --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/DispatchKit.java @@ -0,0 +1,52 @@ +package com.blade.web; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletResponse; + +public class DispatchKit { + + public static File getWebroot(ServletContext sc) { + String dir = sc.getRealPath("/"); + if (dir == null) { + try { + URL url = sc.getResource("/"); + if (url != null && "file".equals(url.getProtocol())) { + dir = URLDecoder.decode(url.getFile(), "utf-8"); + } else { + throw new IllegalStateException("Can't get webroot dir, url = " + url); + } + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + return new File(dir); + } + + public static void setNoCache(HttpServletResponse response) { + // Http 1.0 header + response.setHeader("Buffer", "false"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 1L); + // Http 1.1 header + response.setHeader("Cache-Control", "no-cache, no-store, max-age=0"); + } + + public static void setFileDownloadHeader(HttpServletResponse response, String fileName, String contentType) { + if (contentType == null) { + contentType = "application/x-download"; + } + response.setContentType(contentType); + // 中文文件名支持 + try { + String encodedfileName = new String(fileName.getBytes(), "ISO8859-1"); + response.setHeader("Content-Disposition", "attachment; filename=" + encodedfileName); + } catch (UnsupportedEncodingException e) { + } + } +} diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 2dac382ac..4077fcce0 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -32,6 +32,7 @@ import com.blade.route.RouteBuilder; import blade.kit.StringKit; +import blade.kit.SystemKit; /** * Blade Core DispatcherServlet @@ -58,14 +59,28 @@ public DispatcherServlet() { public DispatcherServlet(Bootstrap bootstrap) { this.bootstrap = bootstrap; - blade.setInit(true); + blade.init(); } @Override public void init(ServletConfig config) throws ServletException { servletContext = config.getServletContext(); if(!blade.isInit()){ - blade.webRoot(servletContext.getRealPath("/")); + + LOGGER.info("DispatcherServlet start ..."); + LOGGER.info("jdk.version = {}", SystemKit.getJavaInfo().getVersion()); + LOGGER.info("user.dir = {}", System.getProperty("user.dir")); + LOGGER.info("java.io.tmpdir = {}", System.getProperty("java.io.tmpdir")); + LOGGER.info("user.timezone = {}", System.getProperty("user.timezone")); + LOGGER.info("file.encoding = {}", System.getProperty("file.encoding")); + + long initStart = System.currentTimeMillis(); + + blade.webRoot(DispatchKit.getWebroot(servletContext).getPath()); + + LOGGER.info("blade.webroot = {}", blade.webRoot()); + LOGGER.info("blade.isDev = {}", blade.isDev()); + this.bootstrap = blade.bootstrap(); if(null == bootstrap){ String bootStrapClassName = config.getInitParameter("bootstrap"); @@ -93,9 +108,9 @@ public void init(Blade blade) { syncRequestHandler = new SyncRequestHandler(servletContext, blade.routers()); - blade.setInit(true); + blade.init(); - LOGGER.info("blade init complete!"); + LOGGER.info("DispatcherFilter initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); } } @@ -103,6 +118,9 @@ public void init(Blade blade) { protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { httpRequest.setCharacterEncoding(blade.encoding()); httpResponse.setCharacterEncoding(blade.encoding()); + if(!blade.httpCache()){ + DispatchKit.setNoCache(httpResponse); + } syncRequestHandler.handle(httpRequest, httpResponse); } diff --git a/blade-core/src/main/java/com/blade/web/RouteArgument.java b/blade-core/src/main/java/com/blade/web/RouteArgument.java index a81acaa39..6acb7067d 100644 --- a/blade-core/src/main/java/com/blade/web/RouteArgument.java +++ b/blade-core/src/main/java/com/blade/web/RouteArgument.java @@ -81,4 +81,5 @@ public static Object executeMethod(Object object, Method method, Request request } return null; } -} + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/StaticFileFilter.java b/blade-core/src/main/java/com/blade/web/StaticFileFilter.java new file mode 100644 index 000000000..9c8ca4e26 --- /dev/null +++ b/blade-core/src/main/java/com/blade/web/StaticFileFilter.java @@ -0,0 +1,41 @@ +package com.blade.web; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class StaticFileFilter { + + private Set prefixList; + private Map cache; + + public StaticFileFilter(Set prefixList) { + this.prefixList = prefixList; + this.cache = new HashMap(128); + } + + public boolean isStatic(String path){ + if (cache != null) { + Boolean found = cache.get(path); + if (found != null) { + return found == Boolean.TRUE; + } + } + + for(String prefix : prefixList){ + if(path.startsWith(prefix)){ + if (cache != null) { + cache.put(path, Boolean.TRUE); + } + return true; + } + } + + if (cache != null) { + cache.put(path, Boolean.FALSE); + } + + return false; + } + +} diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java index 44ee1c761..1b19f778b 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java @@ -51,17 +51,21 @@ */ public class SyncRequestHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(SyncRequestHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); - private Blade blade = Blade.me(); + private Blade blade; private ServletContext servletContext; private RouteMatcher routeMatcher; + private StaticFileFilter staticFileFilter; + public SyncRequestHandler(ServletContext servletContext, Routers routers) { + this.blade = Blade.me(); this.servletContext = servletContext; this.routeMatcher = new RouteMatcher(routers); + this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); } public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ @@ -75,16 +79,14 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); // If it is static, the resource is handed over to the filter - if(null != blade.staticFolder() && blade.staticFolder().length > 0){ - if(!filterStaticFolder(uri)){ - if(LOGGER.isDebugEnabled()){ - LOGGER.debug("Request : {}\t{}", method, uri); - } - String realpath = httpRequest.getServletContext().getRealPath(uri); - ResponsePrint.printStatic(uri, realpath, httpResponse); - return; - } - } + if(staticFileFilter.isStatic(uri)){ + if(LOGGER.isDebugEnabled()){ + LOGGER.debug("Request : {}\t{}", method, uri); + } + String realpath = httpRequest.getServletContext().getRealPath(uri); + ResponsePrint.printStatic(uri, realpath, httpResponse); + return; + } LOGGER.info("Request : {}\t{}", method, uri); @@ -110,6 +112,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo if(result){ // execute handle(request, response, route); + response.status(HttpStatus.OK); if(!request.isAbort()){ // after inteceptor List afters = routeMatcher.getAfter(uri); @@ -190,22 +193,6 @@ private void handle(Request request, Response response, Route route){ RouteArgument.executeMethod(target, actionMethod, request, response); } } - - /** - * Filter out the directory - * - * @param uri URI represents the current path, filtering in a static directory - * @return Return false, filter the success; return true, do not filter - */ - private boolean filterStaticFolder(String uri){ - int len = blade.staticFolder().length; - for(int i=0; i Date: Sun, 14 Feb 2016 22:08:12 +0800 Subject: [PATCH 404/545] remove blade-aop, blade-tx --- LAST_VERSION.md | 9 - blade-aop/pom.xml | 29 --- .../blade/aop/AbstractMethodInterceptor.java | 45 ---- .../java/com/blade/aop/AdviceMatcher.java | 235 ------------------ .../src/main/java/com/blade/aop/AopProxy.java | 80 ------ .../blade/aop/DefaultMethodInvocation.java | 98 -------- .../main/java/com/blade/aop/DefaultProxy.java | 77 ------ .../com/blade/aop/annotation/AfterAdvice.java | 33 --- .../blade/aop/annotation/BeforeAdvice.java | 33 --- .../aop/exception/AdviceMatcherException.java | 39 --- .../AbstractMethodInterceptorFactory.java | 59 ----- .../com/blade/aop/intercept/Interceptor.java | 24 -- .../com/blade/aop/intercept/Invocation.java | 27 -- .../com/blade/aop/intercept/Joinpoint.java | 27 -- .../aop/intercept/MethodInterceptor.java | 33 --- .../blade/aop/intercept/MethodInvocation.java | 33 --- .../main/java/com/blade/proxy/AopProxy.java | 18 -- .../src/main/java/com/blade/proxy/Aspect.java | 10 - .../java/com/blade/proxy/AspectFactory.java | 44 ---- .../java/com/blade/proxy/AspectHandler.java | 70 ------ .../com/blade/aop/test/AnnoInterceptor.java | 21 -- .../com/blade/aop/test/TestInterceptor.java | 21 -- .../java/com/blade/aop/test/TestMain.java | 17 -- .../test/java/com/blade/aop/test/Work.java | 15 -- blade-tx/pom.xml | 28 --- .../blade/plugin/tx/TransactionHolder.java | 46 ---- .../plugin/tx/TransactionInterceptor.java | 42 ---- .../blade/plugin/tx/TransactionManager.java | 15 -- .../plugin/tx/TransactionManagerImpl.java | 76 ------ .../java/com/blade/plugin/tx/TxPlugin.java | 38 --- .../plugin/tx/annotation/Transactional.java | 16 -- pom.xml | 2 - 32 files changed, 1360 deletions(-) delete mode 100644 blade-aop/pom.xml delete mode 100644 blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/AopProxy.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/DefaultProxy.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/annotation/AfterAdvice.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/annotation/BeforeAdvice.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/Interceptor.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/Invocation.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/Joinpoint.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/MethodInterceptor.java delete mode 100644 blade-aop/src/main/java/com/blade/aop/intercept/MethodInvocation.java delete mode 100644 blade-aop/src/main/java/com/blade/proxy/AopProxy.java delete mode 100644 blade-aop/src/main/java/com/blade/proxy/Aspect.java delete mode 100644 blade-aop/src/main/java/com/blade/proxy/AspectFactory.java delete mode 100644 blade-aop/src/main/java/com/blade/proxy/AspectHandler.java delete mode 100644 blade-aop/src/test/java/com/blade/aop/test/AnnoInterceptor.java delete mode 100644 blade-aop/src/test/java/com/blade/aop/test/TestInterceptor.java delete mode 100644 blade-aop/src/test/java/com/blade/aop/test/TestMain.java delete mode 100644 blade-aop/src/test/java/com/blade/aop/test/Work.java delete mode 100644 blade-tx/pom.xml delete mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java delete mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java delete mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TransactionManager.java delete mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TransactionManagerImpl.java delete mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java delete mode 100644 blade-tx/src/main/java/com/blade/plugin/tx/annotation/Transactional.java diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 7d495e53d..bbf994216 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -81,12 +81,3 @@     1.0.2 ``` - -## [blade-aop](http://search.maven.org/#search%7Cga%7C1%7Cblade-aop) -```xml - -    com.bladejava -    blade-aop -    1.0.0 - -``` diff --git a/blade-aop/pom.xml b/blade-aop/pom.xml deleted file mode 100644 index fdf1ce56a..000000000 --- a/blade-aop/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - blade-aop - 1.0.0 - blade-aop - http://maven.apache.org - - - - com.bladejava - blade-kit - 1.2.8-alpha - - - - cglib - cglib-nodep - 3.1 - - - diff --git a/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java b/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java deleted file mode 100644 index 997a3465f..000000000 --- a/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; - -import com.blade.aop.intercept.MethodInterceptor; -import com.blade.aop.intercept.MethodInvocation; - -/** - * 抽象方法拦截器 - * @author biezhi - * @since 1.0 - */ -public abstract class AbstractMethodInterceptor implements MethodInterceptor { - - /** - * 执行方法 - */ - public Object invoke(MethodInvocation invocation) throws Throwable { - return invocation.proceed(); - } - - /** - * 前置执行 - */ - protected abstract void beforeAdvice(); - - /** - * 后置执行 - */ - protected abstract void afterAdvice(); - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java b/blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java deleted file mode 100644 index 28ea4d67c..000000000 --- a/blade-aop/src/main/java/com/blade/aop/AdviceMatcher.java +++ /dev/null @@ -1,235 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - -import com.blade.aop.annotation.AfterAdvice; -import com.blade.aop.annotation.BeforeAdvice; -import com.blade.aop.exception.AdviceMatcherException; -import com.blade.aop.intercept.MethodInvocation; - -import blade.kit.log.Logger; - -/** - * 方法和切点的匹配器 - * @author biezhi - * @since 1.0 - */ -public class AdviceMatcher { - - private Logger logger = Logger.getLogger(AdviceMatcher.class); - - private AbstractMethodInterceptor interceptor; - private MethodInvocation invocation; - - public AdviceMatcher(AbstractMethodInterceptor interceptor, MethodInvocation invocation) { - this.interceptor = interceptor; - this.invocation = invocation; - } - - public boolean match(Class adviceAnnotationType, String joinPoint) { - // 要执行的方法 - try { - Method adviceMethod = interceptor.getClass().getDeclaredMethod(joinPoint, new Class[] {}); - if (adviceAnnotationType == BeforeAdvice.class) { - BeforeAdvice before = adviceMethod.getAnnotation(BeforeAdvice.class); - if (before == null) - return false; - String pointcut = before.expression(); - if(null == pointcut || pointcut.equals("")){ - return true; - } - return beforeOrAfterMatch(pointcut, invocation.getMethod()); - } else if (adviceAnnotationType == AfterAdvice.class) { - AfterAdvice after = adviceMethod.getAnnotation(AfterAdvice.class); - if (after == null) - return false; - String pointcut = after.expression(); - if(null == pointcut || pointcut.equals("")){ - return true; - } - return beforeOrAfterMatch(pointcut, invocation.getMethod()); - } - } catch (SecurityException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - logger.warn(joinPoint + ":" + e.getMessage()); - return false; - } - return true; - } - - /** - * 支持的方法名表达式有: - * 1)*xxx, 以*开头 - * 2)xxx*, 以*结尾 - * 3)* 所有 - * 4)没有*,指定方法名 - * 5)指定的annotation - * - * @param pointcut - * @param methodName - * @return - */ - private boolean beforeOrAfterMatch(String pointcut, Method method) { - - if(null == pointcut){ - return false; - } - // 注解/方法 - String[] pointcuts = pointcut.split(":"); - if(pointcuts.length == 1){ - // 注解 - return isMethod(pointcut, method); - } else{ - if(pointcuts.length == 2){ - String point1 = pointcuts[0]; - String point2 = pointcuts[1]; - // 第一个是注解,(expression = "注解:方法") - if(point1.startsWith("@")){ - return isAnnotationAndMatchMehtod(point1, point2, method); - } else{ - //(expression = "类:方法") - //(expression = "类:注解") - //(expression = "包:方法") - //(expression = "包:注解") - - // 类或者包级别 - if(isClass(point1, method) || isPackage(point1, method)){ - return isClassOrPackageMethod(point1, point2, method); - } - return false; - } - } - if(pointcuts.length == 3){ - //类:注解:方法 - String point1 = pointcuts[0]; - String point2 = pointcuts[1]; - String point3 = pointcuts[2]; - if(isClass(point1, method)){ - return isAnnotationAndMatchMehtod(point2, point3, method); - } - } - return false; - } - } - - private boolean isClassOrPackageMethod(String classPoint, String methodPoint, Method method){ - if(methodPoint.startsWith("@")){ - return isAnnotationMehtod(methodPoint, method); - } else{ - return isMatchMethod(methodPoint, method.getName()); - } - } - - private boolean isMethod(String pointcut, Method method){ - // 注解 - if(pointcut.startsWith("@")){ - return isAnnotationMehtod(pointcut, method); - } else{ - return isMatchMethod(pointcut, method.getName()); - } - } - - /** - * 是否匹配一个带注解的方法 - * @param pointcut - * @param method - * @return - */ - @SuppressWarnings("unchecked") - private boolean isAnnotationMehtod(String pointcut, Method method){ - try { - Class annotationClass = (Class) Class.forName(pointcut.substring(1)); - if(null != method.getAnnotation(annotationClass)){ - return true; - } - } catch (ClassNotFoundException e) { - throw new AdviceMatcherException("错误的注解类型"); - } - return false; - } - - /** - * 是否匹配一个表达式中的方法 - * @param pointcut - * @param methodName - * @return - */ - private boolean isMatchMethod(String pointcut, String methodName){ - int indexOfStar = pointcut.indexOf("*"); - if (indexOfStar != -1) {// 方法名中有*号 - if (indexOfStar == 0) {// 以*开头 - if ("*".equals(pointcut)) {// 只有* - return true; - } else { - return methodName.endsWith(pointcut.substring(1)); - } - } else {// 以*结尾,中间有*也算以*结尾 - return methodName.startsWith(pointcut.substring(0, indexOfStar)); - } - } else { - if(pointcut.indexOf(".") != -1){ - throw new AdviceMatcherException("错误的方法表达式"); - } - return methodName.equals(pointcut); - } - } - - /** - * 是否同时匹配annotation和method - * @param annotationPointcut - * @param methodPointcut - * @param method - * @return - */ - private boolean isAnnotationAndMatchMehtod(String annotationPointcut, String methodPointcut, Method method){ - boolean isMatch = isMatchMethod(methodPointcut, method.getName()); - boolean isAnnotation = isAnnotationMehtod(annotationPointcut, method); - return isMatch && isAnnotation; - } - - /** - * 判断给出的包名是否是方法所属包 - * @param packageName - * @param method - * @return - */ - private boolean isPackage(String packageName, Method method){ - if(null != packageName){ - String packName = method.getDeclaringClass().getPackage().getName(); - return packName.equals(packageName); - } - return false; - } - - /** - * 判断给出的类名是否是方法所属类 - * @param className - * @param method - * @return - */ - private boolean isClass(String className, Method method){ - if(null != className){ - String CanonicalName = method.getDeclaringClass().getCanonicalName(); - return CanonicalName.equals(className); - } - return false; - } - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/AopProxy.java b/blade-aop/src/main/java/com/blade/aop/AopProxy.java deleted file mode 100644 index 09c25be0f..000000000 --- a/blade-aop/src/main/java/com/blade/aop/AopProxy.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; - -import net.sf.cglib.core.ReflectUtils; - -/** - * AOP代理操作类,用于创建代理、添加拦截器 - * - * @author biezhi - * @since 1.0 - */ -@SuppressWarnings("unchecked") -public final class AopProxy { - - private static DefaultProxy defaultProxy = new DefaultProxy(); - - private AopProxy() { - } - - /** - * 根据Class创建一个代理 - * @param clazz Class对象 - * @return 返回代理对象 - */ - public static T create(Class clazz){ - Object target = ReflectUtils.newInstance(clazz); - Object proxy = defaultProxy.getProxy(target); - return (T) proxy; - } - - /** - * 根据Class创建一个代理 - * @param clazz Class对象 - * @return 返回代理对象 - */ - public static Object createProxy(Class clazz){ - Object target = ReflectUtils.newInstance(clazz); - Object proxy = defaultProxy.getProxy(target); - return proxy; - } - - /** - * 创建一个代理对象 - * @param target 原始java对象 - * @return 返回代理对象 - */ - public static T create(Object target){ - Object proxy = defaultProxy.getProxy(target); - return (T) proxy; - } - - /** - * 创建一个代理对象 - * @param target 原始java对象 - * @return 返回代理对象 - */ - public static Object createProxy(Object target){ - Object proxy = defaultProxy.getProxy(target); - return proxy; - } - - public static void addInterceptor(AbstractMethodInterceptor abstractMethodInterceptor){ - defaultProxy.addInterceptor(abstractMethodInterceptor); - } - -} diff --git a/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java b/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java deleted file mode 100644 index 1d5eef2aa..000000000 --- a/blade-aop/src/main/java/com/blade/aop/DefaultMethodInvocation.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Method; -import java.util.List; - -import net.sf.cglib.proxy.MethodInterceptor; - -import com.blade.aop.annotation.AfterAdvice; -import com.blade.aop.annotation.BeforeAdvice; -import com.blade.aop.intercept.MethodInvocation; - -/** - * 默认的方法执行器实现 - * @author biezhi - * @since 1.0 - */ -public class DefaultMethodInvocation implements MethodInvocation { - - List interceptors; - private MethodInterceptor proxy; - private Method method; - private Object target; - private Object[] args; - int index = 0; - private boolean executed = false; - - public DefaultMethodInvocation(MethodInterceptor proxy, Method method, Object target, Object[] args, List interceptorChain) { - this.interceptors = interceptorChain; - this.method = method; - this.target = target; - this.args = args; - this.proxy = proxy; - } - - public Object proceed() throws Throwable { - AbstractMethodInterceptor interceptor = null; - Object result = null; - if (interceptors.size() > 0 && index < interceptors.size()) { - interceptor = interceptors.get(index++); - if (new AdviceMatcher(interceptor, this).match(BeforeAdvice.class, "beforeAdvice")) { - interceptor.beforeAdvice(); // 执行前置建议 - } - proceed(); // 执行下一个拦截器 - } - // 执行真正的方法调用 - if (!executed) { - executed = true; - result = method.invoke(target, args); - /*try { - result = method.invoke(target, args); - } catch (RuntimeException e) { - LOGGER.error(e.getMessage()); - }*/ - } - if (index > 0) { - interceptor = interceptors.get(--index); - if (new AdviceMatcher(interceptor, this).match(AfterAdvice.class, "afterAdvice")) { - interceptor.afterAdvice(); // 执行后置建议 - } - } - return result; - } - - public Object getThis() { - return target; - } - - public AccessibleObject getStaticPart() { - return null; - } - - public Method getMethod() { - return method; - } - - public MethodInterceptor getProxy() { - return proxy; - } - - public Object[] getArguments() { - return args; - } -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/DefaultProxy.java b/blade-aop/src/main/java/com/blade/aop/DefaultProxy.java deleted file mode 100644 index b00867373..000000000 --- a/blade-aop/src/main/java/com/blade/aop/DefaultProxy.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop; -/** - * - * 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. - */ - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; - -/** - * 默认代理获取类 - * @author biezhi - * @since 1.0 - */ -public class DefaultProxy implements MethodInterceptor { - - private Object target; - - private List interceptorChain = new ArrayList(); - - public DefaultProxy() { - - } - - public void addInterceptor(AbstractMethodInterceptor abstractMethodInterceptor){ - interceptorChain.add(abstractMethodInterceptor); - } - - public Object getProxy(Object target) { - this.target = target; - // cglib 中加强器,用来创建动态代理 - Enhancer enhancer = new Enhancer(); - // 设置要创建动态代理的类 - enhancer.setSuperclass(target.getClass()); - // 设置回调,这里相当于是对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实行intercept()方法进行拦截 - enhancer.setCallback(this); - Object proxy = enhancer.create(); - return proxy; - } - - @Override - public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { - DefaultMethodInvocation methodInvocation = new DefaultMethodInvocation(this, method, target, args, interceptorChain); - return methodInvocation.proceed(); - } - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/annotation/AfterAdvice.java b/blade-aop/src/main/java/com/blade/aop/annotation/AfterAdvice.java deleted file mode 100644 index 3ac1ccb10..000000000 --- a/blade-aop/src/main/java/com/blade/aop/annotation/AfterAdvice.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 后置执行注解 - * @author biezhi - * @since 1.0 - */ -@Target(value={ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface AfterAdvice{ - - String expression() default ""; -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/annotation/BeforeAdvice.java b/blade-aop/src/main/java/com/blade/aop/annotation/BeforeAdvice.java deleted file mode 100644 index 330c54e43..000000000 --- a/blade-aop/src/main/java/com/blade/aop/annotation/BeforeAdvice.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 前置执行注解 - * @author biezhi - * @since 1.0 - */ -@Target(value={ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface BeforeAdvice { - - String expression() default ""; - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java b/blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java deleted file mode 100644 index 7d028cde5..000000000 --- a/blade-aop/src/main/java/com/blade/aop/exception/AdviceMatcherException.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.exception; - -/** - * 切入点匹配异常 - * @author biezhi - * @since 1.0 - */ -public class AdviceMatcherException extends RuntimeException { - - private static final long serialVersionUID = -5143613620732802399L; - - public AdviceMatcherException() { - super(); - } - - public AdviceMatcherException(Exception e) { - super(e); - } - - public AdviceMatcherException(String msg) { - super(msg); - } - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java b/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java deleted file mode 100644 index c0825e9ee..000000000 --- a/blade-aop/src/main/java/com/blade/aop/intercept/AbstractMethodInterceptorFactory.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; - -import java.util.ArrayList; -import java.util.List; - -import com.blade.aop.AbstractMethodInterceptor; - -/** - * 拦截器方法工厂 - * @author biezhi - * @since 1.0 - */ -public final class AbstractMethodInterceptorFactory { - - /** - * 普通拦截器列表 - */ - private static final List interceptorList = new ArrayList(); - - /** - * 获取所有普通拦截器 - * @return - */ - public static List getAbstractInterceptors() { - return interceptorList; - } - - /** - * 添加一个拦截器 - * @param routeInterceptors - */ - public static void addInterceptor(List routeInterceptors) { - interceptorList.addAll(routeInterceptors); - } - - /** - * 添加一组拦截器 - * @param routeInterceptor - */ - public static void addInterceptor(AbstractMethodInterceptor routeInterceptor) { - interceptorList.add(routeInterceptor); - } - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/Interceptor.java b/blade-aop/src/main/java/com/blade/aop/intercept/Interceptor.java deleted file mode 100644 index 0e39ed7b5..000000000 --- a/blade-aop/src/main/java/com/blade/aop/intercept/Interceptor.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; - -/** - * 拦截器顶层接口 - * @author biezhi - * @since 1.0 - */ -public interface Interceptor { -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/Invocation.java b/blade-aop/src/main/java/com/blade/aop/intercept/Invocation.java deleted file mode 100644 index 4894cf547..000000000 --- a/blade-aop/src/main/java/com/blade/aop/intercept/Invocation.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; - -/** - * 执行器接口 - * @author biezhi - * @since 1.0 - */ -public interface Invocation extends Joinpoint { - - Object[] getArguments(); - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/Joinpoint.java b/blade-aop/src/main/java/com/blade/aop/intercept/Joinpoint.java deleted file mode 100644 index ed162d02d..000000000 --- a/blade-aop/src/main/java/com/blade/aop/intercept/Joinpoint.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; - -/** - * 切入点 - * @author biezhi - * @since 1.0 - */ -public interface Joinpoint { - - Object proceed() throws Throwable; - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/MethodInterceptor.java b/blade-aop/src/main/java/com/blade/aop/intercept/MethodInterceptor.java deleted file mode 100644 index 68c33c9ab..000000000 --- a/blade-aop/src/main/java/com/blade/aop/intercept/MethodInterceptor.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; - -/** - * 方法拦截器 - * @author biezhi - * @since 1.0 - */ -public interface MethodInterceptor extends Interceptor{ - - /** - * 执行方法 - * @param invocation - * @return - * @throws Throwable - */ - public Object invoke(MethodInvocation invocation) throws Throwable; - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/intercept/MethodInvocation.java b/blade-aop/src/main/java/com/blade/aop/intercept/MethodInvocation.java deleted file mode 100644 index 400e3a76d..000000000 --- a/blade-aop/src/main/java/com/blade/aop/intercept/MethodInvocation.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2014-2015, biezhi 王爵 (biezhi.me@gmail.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.blade.aop.intercept; - -import java.lang.reflect.Method; - -/** - * 方法执行器 - * @author biezhi - * @since 1.0 - */ -public interface MethodInvocation extends Invocation { - - /** - * 获取方法 - * @return - */ - Method getMethod(); - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/proxy/AopProxy.java b/blade-aop/src/main/java/com/blade/proxy/AopProxy.java deleted file mode 100644 index 5b1766bd4..000000000 --- a/blade-aop/src/main/java/com/blade/proxy/AopProxy.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.blade.proxy; - -import java.util.ArrayList; -import java.util.List; - -public class AopProxy { - - private static final List INTERCEPTORS = new ArrayList(); - - public static void addInterceptor(Aspect aspect){ - INTERCEPTORS.add(aspect); - } - - public static T create(Class target){ - T obj = AspectFactory.newProxy(target, INTERCEPTORS); - return obj; - } -} diff --git a/blade-aop/src/main/java/com/blade/proxy/Aspect.java b/blade-aop/src/main/java/com/blade/proxy/Aspect.java deleted file mode 100644 index 89ffbbe84..000000000 --- a/blade-aop/src/main/java/com/blade/proxy/Aspect.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.blade.proxy; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; - -public interface Aspect { - - public Object aspect(InvocationHandler ih, Object proxy, Method method, Object[] args) throws Throwable; - -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/proxy/AspectFactory.java b/blade-aop/src/main/java/com/blade/proxy/AspectFactory.java deleted file mode 100644 index ac88ff418..000000000 --- a/blade-aop/src/main/java/com/blade/proxy/AspectFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.blade.proxy; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Proxy; -import java.util.List; - -import blade.kit.ReflectKit; -import blade.kit.log.Logger; - -public class AspectFactory { - - private static final Logger logger = Logger.getLogger(AspectFactory.class); - - /** - * 私有构造方法 - */ - private AspectFactory() { - } - - /** - * 工厂方法 - * - * @param target - * 代理目标对象 - * @param aspects - * 切面集合 - */ - public static Object newInstance(Object target, List aspects) { - AspectHandler hander = new AspectHandler(target, aspects); - Class clazz = target.getClass(); - if (logger.isDebugEnabled()) { - logger.debug("Instance of " + clazz + "," + clazz.getInterfaces()); - } - return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), hander); - } - - public static T newProxy(Class target, List aspects) { - Object object = ReflectKit.newInstance(target); - AspectHandler handler = new AspectHandler(object, aspects); - - object = Proxy.newProxyInstance(target.getClassLoader(), new Class[] { target }, handler); - return target.cast(object); - } -} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/proxy/AspectHandler.java b/blade-aop/src/main/java/com/blade/proxy/AspectHandler.java deleted file mode 100644 index ab06cb85a..000000000 --- a/blade-aop/src/main/java/com/blade/proxy/AspectHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.blade.proxy; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.util.List; - -import blade.kit.log.Logger; - -public class AspectHandler implements InvocationHandler { - - private static final Logger logger = Logger.getLogger(AspectHandler.class); - - private Object target = null; - private List aspects = null; - private int index = -1; - - public AspectHandler(int index, Object target, List aspects) { - this.index = index; - this.target = target; - this.aspects = aspects; - } - - public AspectHandler(Object target, List aspects) { - this.target = target; - this.aspects = aspects; - } - - - public Object getTarget() { - return target; - } - - - public void setTarget(Object target) { - this.target = target; - } - - public List getAspects() { - return aspects; - } - - - public void setAspects(List aspects) { - this.aspects = aspects; - } - - /** - * 委托方法 - * - * @param proxy 代理对象 - * @param method 代理方法 - * @param args 方法参数 - */ - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - if (index == -1) { - logger.info("Instance an AspectHandler to invoke method %s.", method.getName()); - return new AspectHandler(0, target, aspects).invoke(proxy, method, args); - } - Object result = null; - int len = aspects.size(); - if (index < len) { - result = aspects.get(index++).aspect(this, proxy, method, args); - } else if (index++ == len) { - result = method.invoke(target, args); - } - return result; - } - -} \ No newline at end of file diff --git a/blade-aop/src/test/java/com/blade/aop/test/AnnoInterceptor.java b/blade-aop/src/test/java/com/blade/aop/test/AnnoInterceptor.java deleted file mode 100644 index f6db3f941..000000000 --- a/blade-aop/src/test/java/com/blade/aop/test/AnnoInterceptor.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.blade.aop.test; - -import com.blade.aop.AbstractMethodInterceptor; -import com.blade.aop.annotation.AfterAdvice; -import com.blade.aop.annotation.BeforeAdvice; - -public class AnnoInterceptor extends AbstractMethodInterceptor { - - @Override - @BeforeAdvice(expression = "@javax.annotation.Resource") - protected void beforeAdvice() { - System.out.println("before Resource XXX"); - } - - @Override - @AfterAdvice(expression = "@javax.annotation.Resource") - protected void afterAdvice() { - System.out.println("after Resource XXX"); - } - -} diff --git a/blade-aop/src/test/java/com/blade/aop/test/TestInterceptor.java b/blade-aop/src/test/java/com/blade/aop/test/TestInterceptor.java deleted file mode 100644 index 8fed1b539..000000000 --- a/blade-aop/src/test/java/com/blade/aop/test/TestInterceptor.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.blade.aop.test; - -import com.blade.aop.AbstractMethodInterceptor; -import com.blade.aop.annotation.AfterAdvice; -import com.blade.aop.annotation.BeforeAdvice; - -public class TestInterceptor extends AbstractMethodInterceptor { - - @Override - @BeforeAdvice - protected void beforeAdvice() { - System.out.println("before"); - } - - @Override - @AfterAdvice - protected void afterAdvice() { - System.out.println("after"); - } - -} diff --git a/blade-aop/src/test/java/com/blade/aop/test/TestMain.java b/blade-aop/src/test/java/com/blade/aop/test/TestMain.java deleted file mode 100644 index 8e4de9614..000000000 --- a/blade-aop/src/test/java/com/blade/aop/test/TestMain.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.blade.aop.test; - -import com.blade.aop.AopProxy; - -public class TestMain { - - public static void main(String[] args) { - - AopProxy.addInterceptor(new TestInterceptor()); - AopProxy.addInterceptor(new AnnoInterceptor()); - Work work = AopProxy.create(Work.class); - work.run(); - - work.save(); - - } -} diff --git a/blade-aop/src/test/java/com/blade/aop/test/Work.java b/blade-aop/src/test/java/com/blade/aop/test/Work.java deleted file mode 100644 index 53edab3c9..000000000 --- a/blade-aop/src/test/java/com/blade/aop/test/Work.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.blade.aop.test; - -import javax.annotation.Resource; - -public class Work { - - public void run(){ - System.out.println("run in work!!"); - } - - @Resource - public void save(){ - System.out.println("save ..."); - } -} diff --git a/blade-tx/pom.xml b/blade-tx/pom.xml deleted file mode 100644 index f30dbbb7f..000000000 --- a/blade-tx/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - blade-tx - 1.0.0 - blade-tx - http://maven.apache.org - - - - com.bladejava - blade-core - ${blade.version} - - - com.bladejava - blade-aop - 1.0.0 - - - diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java deleted file mode 100644 index 8bfbc8434..000000000 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionHolder.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.blade.plugin.tx; - -import java.sql.Connection; - -import javax.sql.DataSource; - -import blade.kit.log.Logger; - -public class TransactionHolder implements TransactionManager { - - private static final Logger LOGGER = Logger.getLogger(TransactionHolder.class); - - private static DataSource dataSource; - - public TransactionHolder(DataSource dataSource) { - TransactionHolder.dataSource = dataSource; - } - - private static final ThreadLocal tranManager = new ThreadLocal() { - protected TransactionManager initialValue() { - LOGGER.info("TransactionHolder Initialize"); - return new TransactionManagerImpl(dataSource); - } - }; - - @Override - public void beginTransaction() { - tranManager.get().beginTransaction(); - } - - @Override - public void commit() { - tranManager.get().commit(); - } - - @Override - public void rollback() { - tranManager.get().rollback(); - } - - @Override - public Connection getConnection() { - return tranManager.get().getConnection(); - } - -} diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java deleted file mode 100644 index 1fc34e48a..000000000 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionInterceptor.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.blade.plugin.tx; - -import javax.sql.DataSource; - -import com.blade.aop.AbstractMethodInterceptor; -import com.blade.aop.annotation.AfterAdvice; -import com.blade.aop.annotation.BeforeAdvice; -import com.blade.aop.intercept.MethodInvocation; - -public class TransactionInterceptor extends AbstractMethodInterceptor { - - private TransactionHolder local = null; - - public TransactionInterceptor(DataSource dataSource) { - local = new TransactionHolder(dataSource); - } - - @BeforeAdvice(expression = "@com.blade.plugin.tx.annotation.Transactional") - public void beforeAdvice() { - local.beginTransaction(); - } - - @Override - public Object invoke(MethodInvocation invocation) { - try { - return super.invoke(invocation); - } catch (Exception e) { - local.rollback(); - e.printStackTrace(); - } catch (Throwable e) { - local.rollback(); - e.printStackTrace(); - } - return null; - } - - @AfterAdvice(expression = "@com.blade.plugin.tx.annotation.Transactional") - public void afterAdvice() { - local.commit(); - } - -} \ No newline at end of file diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManager.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManager.java deleted file mode 100644 index da54bd3fe..000000000 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManager.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.blade.plugin.tx; - -import java.sql.Connection; - -public interface TransactionManager { - - Connection getConnection(); - - void beginTransaction(); - - void commit(); - - void rollback(); - -} diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManagerImpl.java b/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManagerImpl.java deleted file mode 100644 index 11f651b1a..000000000 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TransactionManagerImpl.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.blade.plugin.tx; - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Stack; - -import javax.sql.DataSource; - -import blade.kit.log.Logger; - -public class TransactionManagerImpl implements TransactionManager { - - private static final Logger LOGGER = Logger.getLogger(TransactionManagerImpl.class); - - private Stackconnections = new Stack(); - - private DataSource dataSource; - - public TransactionManagerImpl(DataSource dataSource) { - this.dataSource = dataSource; - } - - @Override - public Connection getConnection() { - - if (connections.isEmpty()) { - this.addConn(); - } - - return connections.peek(); - } - - @Override - public void beginTransaction() { - this.addConn(); - } - - @Override - public void commit() { - try { - if (connections.peek() != null&& !connections.peek().isClosed()) { - LOGGER.info(connections.peek() + "--> commit"); - connections.peek().commit(); - connections.pop().close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - - } - - @Override - public void rollback() { - try { - if (connections.peek() != null&& !connections.peek().isClosed()) { - LOGGER.info(connections.peek() + "--> rollback"); - connections.peek().rollback(); - connections.pop().close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } - - private void addConn() { - try { - Connection con = dataSource.getConnection(); - con.setAutoCommit(false); - connections.push(con); - LOGGER.info(con + "--> connection"); - } catch (SQLException e) { - e.printStackTrace(); - } - } - -} diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java b/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java deleted file mode 100644 index 4f4fff654..000000000 --- a/blade-tx/src/main/java/com/blade/plugin/tx/TxPlugin.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.blade.plugin.tx; - -import javax.sql.DataSource; - -import blade.kit.Assert; - -import com.blade.aop.AopProxy; -import com.blade.plugin.Plugin; - -/** - * 事务插件 - * @author biezhi - * @since 1.0 - */ -public class TxPlugin implements Plugin { - - TransactionInterceptor transactionInterceptor = null; - - public TxPlugin() { - } - - public TxPlugin dataSource(DataSource dataSource){ - transactionInterceptor = new TransactionInterceptor(dataSource); - return this; - } - - @Override - public void run() { - Assert.notNull(transactionInterceptor); - AopProxy.addInterceptor(transactionInterceptor); - } - - @Override - public void destroy() { - - } - -} diff --git a/blade-tx/src/main/java/com/blade/plugin/tx/annotation/Transactional.java b/blade-tx/src/main/java/com/blade/plugin/tx/annotation/Transactional.java deleted file mode 100644 index 3c9c40b48..000000000 --- a/blade-tx/src/main/java/com/blade/plugin/tx/annotation/Transactional.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.blade.plugin.tx.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ ElementType.METHOD, ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Inherited -@Documented -public @interface Transactional { - -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 0e387335f..9af7e6792 100644 --- a/pom.xml +++ b/pom.xml @@ -26,8 +26,6 @@ blade-jdbc blade-redis blade-startup - blade-aop - blade-tx blade-oauth2 blade-patchca From f40ad732df0a334c72ffd36e8616faf1937b5afa Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 15 Feb 2016 09:59:50 +0800 Subject: [PATCH 405/545] remove log and add slf4j --- blade-kit/pom.xml | 11 +- .../src/main/java/blade/kit/TaskKit.java | 7 +- .../src/main/java/blade/kit/TimwKit.java | 10 +- .../kit/config/adapter/PropConfigAdapter.java | 8 +- .../main/java/blade/kit/log/JdkLogger.java | 76 ------- .../java/blade/kit/log/JdkLoggerFactory.java | 12 - .../src/main/java/blade/kit/log/Level.java | 22 -- .../main/java/blade/kit/log/Log4jLogger.java | 186 --------------- .../blade/kit/log/Log4jLoggerFactory.java | 12 - .../src/main/java/blade/kit/log/Logger.java | 214 ------------------ .../java/blade/kit/log/LoggerFactory.java | 8 - .../main/java/blade/kit/log/SimpleLogger.java | 75 ------ .../blade/kit/log/SimpleLoggerFactory.java | 12 - .../main/java/blade/kit/log/package-info.java | 4 - .../main/java/blade/kit/mail/EmailHandle.java | 9 +- .../java/blade/kit/reflect/ReflectKit.java | 18 +- .../kit/resource/AbstractClassReader.java | 10 +- .../blade/kit/resource/JarReaderImpl.java | 12 +- .../src/test/java/com/blade/kit/LogTest.java | 19 -- 19 files changed, 46 insertions(+), 679 deletions(-) delete mode 100644 blade-kit/src/main/java/blade/kit/log/JdkLogger.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/JdkLoggerFactory.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/Level.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/Log4jLogger.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/Log4jLoggerFactory.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/Logger.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/LoggerFactory.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/SimpleLogger.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java delete mode 100644 blade-kit/src/main/java/blade/kit/log/package-info.java delete mode 100644 blade-kit/src/test/java/com/blade/kit/LogTest.java diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index 51e33607c..ca6d3065a 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -24,18 +24,17 @@ junit junit + + org.slf4j + slf4j-api + 1.7.16 + javax.mail mail 1.5.0-b01 provided - - log4j - log4j - 1.2.17 - provided - dom4j dom4j diff --git a/blade-kit/src/main/java/blade/kit/TaskKit.java b/blade-kit/src/main/java/blade/kit/TaskKit.java index aa59e5663..f842e809a 100644 --- a/blade-kit/src/main/java/blade/kit/TaskKit.java +++ b/blade-kit/src/main/java/blade/kit/TaskKit.java @@ -25,7 +25,8 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import blade.kit.log.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * 定时任务 @@ -35,7 +36,7 @@ */ public abstract class TaskKit { - private static Logger logger = Logger.getLogger(TaskKit.class); + private static Logger logger = LoggerFactory.getLogger(TaskKit.class); private static ScheduledThreadPoolExecutor taskScheduler = new ScheduledThreadPoolExecutor(getBestPoolSize()); private static List timerList = new ArrayList(); @@ -174,7 +175,7 @@ public static void depose() { } List awaitingExecution = taskScheduler.shutdownNow(); - logger.info("Tasks stopping. Tasks awaiting execution: %d", timerNum + awaitingExecution.size()); + logger.info("Tasks stopping. Tasks awaiting execution: {}", timerNum + awaitingExecution.size()); } /** diff --git a/blade-kit/src/main/java/blade/kit/TimwKit.java b/blade-kit/src/main/java/blade/kit/TimwKit.java index 409cf284e..b7e06ab07 100644 --- a/blade-kit/src/main/java/blade/kit/TimwKit.java +++ b/blade-kit/src/main/java/blade/kit/TimwKit.java @@ -19,7 +19,8 @@ import java.util.ArrayList; import java.util.List; -import blade.kit.log.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * 计数均衡器 @@ -32,7 +33,7 @@ */ public class TimwKit { - private static final Logger LOGGER = Logger.getLogger(TimwKit.class); + private static final Logger LOGGER = LoggerFactory.getLogger(TimwKit.class); private ArrayList numList = new ArrayList(); @@ -92,7 +93,7 @@ public Number avg() { * @return */ public String print() { - String str = "执行(" + size() + ")次,耗时: " + numList + " ms"; + String str = "Execute count = " + size() + ", elapsed time: " + numList + " ms."; LOGGER.debug(str); return str; } @@ -106,8 +107,7 @@ public String printAvg() { Number number = avg(); BigDecimal b = new BigDecimal(number.doubleValue()); double avg = b.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue(); - String str = "平均耗时: " + avg + " ms"; - + String str = "average time cost: " + avg + " ms"; LOGGER.debug(str); return str; } diff --git a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java index 0c84ff864..e899ec854 100644 --- a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java +++ b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java @@ -8,10 +8,12 @@ import java.util.Properties; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import blade.kit.IOKit; import blade.kit.config.Config; import blade.kit.config.exception.ConfigAdapterException; -import blade.kit.log.Logger; /** * 解析Properties配置文件 @@ -19,7 +21,7 @@ */ public class PropConfigAdapter extends ConfigAdapter { - private static final Logger LOGGER = Logger.getLogger(PropConfigAdapter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PropConfigAdapter.class); @Override public Config read(String prop_file) { @@ -46,7 +48,7 @@ public Config read(String prop_file) { configMap.put(key, value); } - LOGGER.debug("Loading config file: [classpath:/" + prop_file + "]"); + LOGGER.info("Loading config file: [classpath:/" + prop_file + "]"); return this; } catch (IOException e) { throw new ConfigAdapterException("load properties file error!"); diff --git a/blade-kit/src/main/java/blade/kit/log/JdkLogger.java b/blade-kit/src/main/java/blade/kit/log/JdkLogger.java deleted file mode 100644 index 7c14839d0..000000000 --- a/blade-kit/src/main/java/blade/kit/log/JdkLogger.java +++ /dev/null @@ -1,76 +0,0 @@ -package blade.kit.log; - -import java.util.logging.Level; - -/** - * JDK的日志实现 - * - * @author biezhi - * @since 1.0 - */ -public class JdkLogger extends Logger { - - private java.util.logging.Logger logger; - - public JdkLogger(Class clazz) { - this(clazz.getName()); - } - - public JdkLogger(String name) { - this.name = name; - logger = java.util.logging.Logger.getLogger(name); - } - - private Level getLevel(int level) { - switch (level) { - case blade.kit.log.Level.TRACE: - return Level.FINEST; - case blade.kit.log.Level.DEBUG: - return Level.FINE; - case blade.kit.log.Level.INFO: - return Level.INFO; - case blade.kit.log.Level.WARN: - return Level.WARNING; - case blade.kit.log.Level.ERROR: - case blade.kit.log.Level.FATAL: - return Level.SEVERE; - } - return Level.INFO; - } - - @Override - public void log(int level, Object message, Object... args) { - log(level, message, null, args); - } - - @Override - public void log(int level, Object message, Throwable t, Object... args) { - - log(getLevel(level), format(message, args), t); - - } - - private void log(Level level, String msg, Throwable ex) { - if (logger.isLoggable(level)) { - // Hack (?) to get the stack trace. - Throwable dummyException = new Throwable(); - StackTraceElement locations[] = dummyException.getStackTrace(); - // Caller will be the third element - String cname = "unknown"; - String method = "unknown"; - if (locations != null && locations.length > 3) { - StackTraceElement caller = locations[3]; - cname = caller.getClassName(); - method = caller.getMethodName(); - } - - if (ex == null) { - logger.logp(level, cname, method, msg); - } else { - logger.logp(level, cname, method, msg, ex); - } - } - - } - -} diff --git a/blade-kit/src/main/java/blade/kit/log/JdkLoggerFactory.java b/blade-kit/src/main/java/blade/kit/log/JdkLoggerFactory.java deleted file mode 100644 index b9dee5345..000000000 --- a/blade-kit/src/main/java/blade/kit/log/JdkLoggerFactory.java +++ /dev/null @@ -1,12 +0,0 @@ -package blade.kit.log; - -public class JdkLoggerFactory implements LoggerFactory { - - public Logger getLogger(Class clazz) { - return new JdkLogger(clazz); - } - - public Logger getLogger(String name) { - return new JdkLogger(name); - } -} diff --git a/blade-kit/src/main/java/blade/kit/log/Level.java b/blade-kit/src/main/java/blade/kit/log/Level.java deleted file mode 100644 index efe75650a..000000000 --- a/blade-kit/src/main/java/blade/kit/log/Level.java +++ /dev/null @@ -1,22 +0,0 @@ -package blade.kit.log; - -/** - * 日志级别 - * @author biezhi - * - */ -public final class Level { - - public static final int TRACE = 100; - - public static final int DEBUG = 200; - - public static final int INFO = 300; - - public static final int WARN = 400; - - public static final int ERROR = 500; - - public static final int FATAL = 600; - -} diff --git a/blade-kit/src/main/java/blade/kit/log/Log4jLogger.java b/blade-kit/src/main/java/blade/kit/log/Log4jLogger.java deleted file mode 100644 index 2dd73380f..000000000 --- a/blade-kit/src/main/java/blade/kit/log/Log4jLogger.java +++ /dev/null @@ -1,186 +0,0 @@ -package blade.kit.log; - -import org.apache.log4j.Level; -import org.apache.log4j.Priority; - -/** - * Log4j的日志实现 - * - * @author biezhi - * @since 1.0 - */ -@SuppressWarnings("deprecation") -public class Log4jLogger extends Logger{ - - private static final String FQCN = Log4jLogger.class.getName(); - private static Priority traceLevel; - private org.apache.log4j.Logger logger; - - static { - try { - traceLevel = (Priority) Level.class.getDeclaredField("TRACE").get(null); - } catch (Exception ex) { - traceLevel = Priority.DEBUG; - } - } - - public Log4jLogger(String name) { - this.name = name; - logger = org.apache.log4j.Logger.getLogger(name); - } - - @Override - public String getName() { - return this.name; - } - - private Priority getLevel(int level) { - switch (level) { - case blade.kit.log.Level.TRACE: - return traceLevel; - case blade.kit.log.Level.DEBUG: - return Priority.DEBUG; - case blade.kit.log.Level.INFO: - return Priority.INFO; - case blade.kit.log.Level.WARN: - return Priority.WARN; - case blade.kit.log.Level.ERROR: - return Priority.ERROR; - case blade.kit.log.Level.FATAL: - return Priority.FATAL; - } - return Priority.DEBUG; - } - - @Override - public void log(int level, Object message, Object... args) { - message = format(message, args); - logger.log(FQCN, getLevel(level), message, null); - } - - @Override - public void log(int level, Object message, Throwable t, Object... args) { - message = format(message, args); - logger.log(FQCN, getLevel(level), message, t); - } - - @Override - public void trace(Object message) { - - } - - @Override - public void trace(Object message, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void trace(Object message, Throwable t) { - // TODO Auto-generated method stub - - } - - @Override - public void trace(Object message, Throwable t, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void debug(Object message) { - // TODO Auto-generated method stub - - } - - @Override - public void debug(Object message, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void debug(Object message, Throwable t) { - // TODO Auto-generated method stub - - } - - @Override - public void debug(Object message, Throwable t, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void info(Object message) { - // TODO Auto-generated method stub - - } - - @Override - public void info(Object message, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void info(Object message, Throwable t) { - // TODO Auto-generated method stub - - } - - @Override - public void info(Object message, Throwable t, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void warn(Object message) { - // TODO Auto-generated method stub - - } - - @Override - public void warn(Object message, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void warn(Object message, Throwable t) { - // TODO Auto-generated method stub - - } - - @Override - public void warn(Object message, Throwable t, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void error(Object message) { - // TODO Auto-generated method stub - - } - - @Override - public void error(Object message, Object... args) { - // TODO Auto-generated method stub - - } - - @Override - public void error(Object message, Throwable t) { - // TODO Auto-generated method stub - - } - - @Override - public void error(Object message, Throwable t, Object... args) { - // TODO Auto-generated method stub - - } - -} diff --git a/blade-kit/src/main/java/blade/kit/log/Log4jLoggerFactory.java b/blade-kit/src/main/java/blade/kit/log/Log4jLoggerFactory.java deleted file mode 100644 index 0d0f3fb90..000000000 --- a/blade-kit/src/main/java/blade/kit/log/Log4jLoggerFactory.java +++ /dev/null @@ -1,12 +0,0 @@ -package blade.kit.log; - -public class Log4jLoggerFactory implements LoggerFactory { - - public Logger getLogger(Class clazz) { - return new JdkLogger(clazz); - } - - public Logger getLogger(String name) { - return new JdkLogger(name); - } -} diff --git a/blade-kit/src/main/java/blade/kit/log/Logger.java b/blade-kit/src/main/java/blade/kit/log/Logger.java deleted file mode 100644 index a96549ec6..000000000 --- a/blade-kit/src/main/java/blade/kit/log/Logger.java +++ /dev/null @@ -1,214 +0,0 @@ -package blade.kit.log; - -/** - * 日志输出 - * - * @author biezhi - * @since 1.0 - */ -public abstract class Logger { - - private static LoggerFactory factory; - - private int level = Level.DEBUG; - - /** - * 日志名称 - */ - protected String name; - - public abstract void log(int level, Object message, Throwable t, Object... args); - - public abstract void log(int level, Object message, Object... args); - - static{ - try { - Class.forName("org.apache.log4j.Logger"); - factory = new Log4jLoggerFactory(); - } catch (Exception e) { - factory = new SimpleLoggerFactory(); - } - } - - public static void setLoggerFactory(LoggerFactory loggerFactory){ - factory = loggerFactory; - } - - public static Logger getLogger(String name) { - return factory.getLogger(name); - } - - public static Logger getLogger(Class clazz) { - return factory.getLogger(clazz); - } - - public static Logger getLogger() { - String currentClassName = Thread.currentThread().getStackTrace()[2].getClassName(); - return getLogger(currentClassName); - } - - public String getName() { - return this.name; - } - - public void setLevel(int level) { - this.level = level; - } - - public void trace(Object message) { - if (level <= Level.TRACE) - log(Level.TRACE, message); - } - - public void trace(Object message, Object... args) { - if (level <= Level.TRACE) - log(Level.TRACE, message, args); - } - - public void trace(Object message, Throwable t) { - if (level <= Level.TRACE) - log(Level.TRACE, message, t); - } - - - public void trace(Object message, Throwable t, Object... args) { - if (level <= Level.TRACE) - log(Level.TRACE, message, t, args); - } - - - public void debug(Object message) { - if (level <= Level.DEBUG) - log(Level.DEBUG, message); - } - - - public void debug(Object message, Object... args) { - if (level <= Level.DEBUG) - log(Level.DEBUG, message, args); - } - - - public void debug(Object message, Throwable t) { - if (level <= Level.DEBUG) - log(Level.DEBUG, message, t); - } - - - public void debug(Object message, Throwable t, Object... args) { - if (level <= Level.DEBUG) - log(Level.DEBUG, message, t, args); - } - - - public void info(Object message) { - if (level <= Level.INFO) - log(Level.INFO, message); - } - - - public void info(Object message, Object... args) { - if (level <= Level.INFO) - log(Level.INFO, message, args); - } - - - public void info(Object message, Throwable t) { - if (level <= Level.INFO) - log(Level.INFO, message, t); - } - - - public void info(Object message, Throwable t, Object... args) { - if (level <= Level.INFO) - log(Level.INFO, message, t, args); - } - - - public void warn(Object message) { - if (level <= Level.WARN) - log(Level.WARN, message); - } - - - public void warn(Object message, Object... args) { - if (level <= Level.WARN) - log(Level.WARN, message, args); - } - - - public void warn(Object message, Throwable t) { - if (level <= Level.WARN) - log(Level.WARN, message, t); - } - - - public void warn(Object message, Throwable t, Object... args) { - if (level <= Level.WARN) - log(Level.WARN, message, t, args); - } - - - public void error(Object message) { - if (level <= Level.ERROR) - log(Level.ERROR, message); - } - - - public void error(Object message, Object... args) { - if (level <= Level.ERROR) - log(Level.ERROR, message, args); - } - - - public void error(Object message, Throwable t) { - if (level <= Level.ERROR) - log(Level.ERROR, message, t); - } - - - public void error(Object message, Throwable t, Object... args) { - if (level <= Level.ERROR) - log(Level.ERROR, message, t, args); - } - - - public void fatal(Object message, Object... args) { - if (level <= Level.FATAL) - log(Level.FATAL, message, args); - } - - - public void fatal(Object message, Throwable t, Object... args) { - if (level <= Level.FATAL) - log(Level.FATAL, message, t, args); - } - - protected String format(Object message, Object... args) { - if (message == null) { - return null; - } - if (args == null || args.length == 0) { - return message.toString(); - } else { - return String.format(message.toString(), args); - } - } - - public boolean isDebugEnabled() { - return level <= Level.DEBUG; - } - - public boolean isErrorEnabled() { - return level <= Level.ERROR; - } - - public boolean isInfoEnabled() { - return level <= Level.INFO; - } - - public boolean isWarnEnabled() { - return level <= Level.WARN; - } - -} diff --git a/blade-kit/src/main/java/blade/kit/log/LoggerFactory.java b/blade-kit/src/main/java/blade/kit/log/LoggerFactory.java deleted file mode 100644 index 89fb57d6f..000000000 --- a/blade-kit/src/main/java/blade/kit/log/LoggerFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -package blade.kit.log; - -public interface LoggerFactory { - - Logger getLogger(Class clazz); - - Logger getLogger(String name); -} diff --git a/blade-kit/src/main/java/blade/kit/log/SimpleLogger.java b/blade-kit/src/main/java/blade/kit/log/SimpleLogger.java deleted file mode 100644 index 07ea0921d..000000000 --- a/blade-kit/src/main/java/blade/kit/log/SimpleLogger.java +++ /dev/null @@ -1,75 +0,0 @@ -package blade.kit.log; - -import java.io.PrintStream; -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * 默认日志实现 - * - * @author biezhi - * @since 1.0 - */ -public class SimpleLogger extends Logger { - - private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"); - - private static PrintStream outprint = System.out; - - public SimpleLogger() { - } - - public SimpleLogger(String name) { - this.name = name; - } - - private String getLevel(int level){ - if(level <= blade.kit.log.Level.TRACE){ - return "TRACE"; - } - if(level <= blade.kit.log.Level.DEBUG){ - return "DEBUG"; - } - if(level <= blade.kit.log.Level.INFO){ - return "INFO"; - } - if(level <= blade.kit.log.Level.WARN){ - return "WARN"; - } - if(level <= blade.kit.log.Level.ERROR){ - outprint = System.err; - return "ERROR"; - } - if(level <= blade.kit.log.Level.FATAL){ - return "FATAL"; - } - return "DEBUG"; - } - - private String now() { - return sdf.format(new Date()); - } - - @Override - public void log(int level, Object message, Object... args) { - log(level, message, null, args); - - } - - @Override - public void log(int level, Object message, Throwable t, Object... args) { - - StringBuilder sb = new StringBuilder(now()); - sb.append(" ").append(getLevel(level)).append(" "); - sb.append("[").append(Thread.currentThread().getName()).append("]").append(" "); - sb.append(getName()).append(" | "); - sb.append(format(message, args)); - - outprint.println(sb.toString()); - if (t != null) { - t.printStackTrace(System.err); - System.err.flush(); - } - } - -} diff --git a/blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java b/blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java deleted file mode 100644 index 46bc4ae5d..000000000 --- a/blade-kit/src/main/java/blade/kit/log/SimpleLoggerFactory.java +++ /dev/null @@ -1,12 +0,0 @@ -package blade.kit.log; - -public class SimpleLoggerFactory implements LoggerFactory { - - public Logger getLogger(Class clazz) { - return new SimpleLogger(clazz.getName()); - } - - public Logger getLogger(String name) { - return new SimpleLogger(name); - } -} diff --git a/blade-kit/src/main/java/blade/kit/log/package-info.java b/blade-kit/src/main/java/blade/kit/log/package-info.java deleted file mode 100644 index 798e9707a..000000000 --- a/blade-kit/src/main/java/blade/kit/log/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 内置日志系统包 - */ -package blade.kit.log; \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java b/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java index 1480aebd3..65c3aa10b 100644 --- a/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java +++ b/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java @@ -18,7 +18,8 @@ import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimeUtility; -import blade.kit.log.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * 邮件发送处理工具类 @@ -27,7 +28,7 @@ */ public class EmailHandle { - private static final Logger LOGGER = Logger.getLogger(EmailHandle.class); + private static final Logger LOGGER = LoggerFactory.getLogger(EmailHandle.class); /** 邮件对象 **/ private MimeMessage mimeMsg; @@ -266,7 +267,7 @@ public boolean setCopyToList(String copytoList) { * @return */ public boolean sendEmail() throws Exception { - LOGGER.debug("正在发送邮件...."); + LOGGER.debug("Sending mail ..."); mimeMsg.setContent(mp); mimeMsg.saveChanges(); @@ -279,7 +280,7 @@ public boolean sendEmail() throws Exception { /** 发送邮件 **/ transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.TO)); transport.close(); - LOGGER.debug("发送邮件成功!"); + LOGGER.debug("Send mail success."); return true; } diff --git a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java index bdda07446..f43a76a39 100644 --- a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java @@ -31,11 +31,13 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import blade.kit.Emptys; import blade.kit.ExceptionKit; import blade.kit.StringKit; import blade.kit.SystemKit; -import blade.kit.log.Logger; /** * 有关 Reflection处理的工具类。 @@ -47,7 +49,7 @@ */ public abstract class ReflectKit { - private static final Logger LOGGER = Logger.getLogger(ReflectKit.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ReflectKit.class); /** 新建对象 * @throws IllegalAccessException @@ -57,7 +59,7 @@ public static Object newInstance(String className) throws InstantiationException Object obj = null; Class clazz = Class.forName(className); obj = clazz.newInstance(); - LOGGER.debug("new %s", className); + LOGGER.debug("New {}", className); return obj; } @@ -238,20 +240,18 @@ public static List scanPackageClass(String rootPackageName) { ClassLoader loader = Thread.currentThread().getContextClassLoader(); URL url = loader.getResource(rootPackageName.replace('.', '/')); - ExceptionKit.makeRunTimeWhen(url == null, - "package[%s] not found!", rootPackageName); + ExceptionKit.makeRunTimeWhen(url == null, "package[%s] not found!", rootPackageName); String protocol = url.getProtocol(); if ("file".equals(protocol)) { - LOGGER.debug("scan in file"); + LOGGER.debug("Scan in file ..."); File[] files = new File(url.toURI()).listFiles(); for (File f : files) { scanPackageClassInFile(rootPackageName, f, classNames); } } else if ("jar".equals(protocol)) { - LOGGER.debug("scan in jar"); - JarFile jar = ((JarURLConnection) url.openConnection()) - .getJarFile(); + LOGGER.debug("Scan in jar ..."); + JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile(); scanPackageClassInJar(jar, rootPackageName, classNames); } diff --git a/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java b/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java index 75c2893f5..6454430ad 100644 --- a/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java +++ b/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java @@ -24,9 +24,11 @@ import java.util.Enumeration; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import blade.kit.Assert; import blade.kit.CollectionKit; -import blade.kit.log.Logger; /** * 抽象类读取器 @@ -36,7 +38,7 @@ */ public abstract class AbstractClassReader implements ClassReader { - private static final Logger LOGGER = Logger.getLogger(AbstractClassReader.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractClassReader.class); @Override public Set> getClass(String packageName, boolean recursive) { @@ -65,7 +67,7 @@ private Set> findClassByPackage(final String packageName, final String File dir = new File(packagePath); // 如果不存在或者 也不是目录就直接返回 if ((!dir.exists()) || (!dir.isDirectory())) { - LOGGER.warn("包 " + packageName + " 不存在!"); + LOGGER.warn("The package [{}] not found.", packageName); } // 如果存在 就获取包下的所有文件 包括目录 File[] dirfiles = accept(dir, recursive); @@ -156,7 +158,7 @@ public Set> getClassByAnnotation(String packageName, Class parent, C } } } catch (IOException e) { - LOGGER.error(e.getMessage()); + LOGGER.error(e.getMessage(), e); } return classes; } diff --git a/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java b/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java index 6b5e10847..8cee7e2ad 100644 --- a/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java +++ b/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java @@ -24,10 +24,12 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import blade.kit.Assert; import blade.kit.CollectionKit; import blade.kit.exception.ClassReaderException; -import blade.kit.log.Logger; /** * 根据jar文件读取类 @@ -37,7 +39,7 @@ */ public class JarReaderImpl extends AbstractClassReader implements ClassReader { - private static final Logger LOGGER = Logger.getLogger(JarReaderImpl.class); + private static final Logger LOGGER = LoggerFactory.getLogger(JarReaderImpl.class); @Override public Set> getClass(String packageName, boolean recursive) { @@ -74,7 +76,7 @@ public Set> getClassByAnnotation(String packageName, Class parent, C } } } catch (IOException e) { - LOGGER.error(e.getMessage()); + LOGGER.error(e.getMessage(), e); } return classes; } @@ -138,7 +140,7 @@ private Set> getClasses(final URL url, final String packageDirName, Str } classes.add(clazz); } catch (ClassNotFoundException e) { - LOGGER.error("添加用户自定义视图类错误 找不到此类的.class文件"); + LOGGER.error("Add user custom view class error Can't find such Class files."); throw new ClassReaderException(e); } } @@ -147,7 +149,7 @@ private Set> getClasses(final URL url, final String packageDirName, Str } } } catch (IOException e) { - LOGGER.error("在扫描用户定义视图时从jar包获取文件出错:{}", e.getMessage()); + LOGGER.error("The scan error when the user to define the view from a jar package file.", e); } return classes; } diff --git a/blade-kit/src/test/java/com/blade/kit/LogTest.java b/blade-kit/src/test/java/com/blade/kit/LogTest.java deleted file mode 100644 index 904e6d109..000000000 --- a/blade-kit/src/test/java/com/blade/kit/LogTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.blade.kit; -import blade.kit.log.Logger; - - -public class LogTest { - - private static final Logger LOGGER = Logger.getLogger(LogTest.class); - - public static void main(String[] args) { -// LOGGER.setLevel(Level.INFO); - LOGGER.debug("debug hello"); - LOGGER.info("info hello %s", "aaa"); - LOGGER.warn("warn hello"); - - System.out.println(LOGGER.isDebugEnabled()); - System.out.println(LOGGER.isInfoEnabled()); - System.out.println(LOGGER.isErrorEnabled()); - } -} From f015e918f5f164cb04548e2084bb615461d216d2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 15 Feb 2016 10:15:58 +0800 Subject: [PATCH 406/545] Add configuration null judgments --- .../kit/config/adapter/PropConfigAdapter.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java index e899ec854..1c4951c40 100644 --- a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java +++ b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java @@ -11,6 +11,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import blade.kit.CollectionKit; import blade.kit.IOKit; import blade.kit.config.Config; import blade.kit.config.exception.ConfigAdapterException; @@ -25,7 +26,6 @@ public class PropConfigAdapter extends ConfigAdapter { @Override public Config read(String prop_file) { - Properties props = new Properties(); InputStream in = null; try { @@ -35,21 +35,23 @@ public Config read(String prop_file) { } // 解析properties文件 Set> set = props.entrySet(); - Iterator> it = set.iterator(); - while (it.hasNext()) { - Entry entry = it.next(); - String key = entry.getKey().toString(); - String value = entry.getValue().toString(); - String fuKey = getWildcard(value); - if(null != fuKey && null != props.get(fuKey)){ - String fuValue = props.get(fuKey).toString(); - value = value.replaceAll("\\$\\{" + fuKey + "\\}", fuValue); + if(CollectionKit.isNotEmpty(set)){ + Iterator> it = set.iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + String key = entry.getKey().toString(); + String value = entry.getValue().toString(); + String fuKey = getWildcard(value); + if(null != fuKey && null != props.get(fuKey)){ + String fuValue = props.get(fuKey).toString(); + value = value.replaceAll("\\$\\{" + fuKey + "\\}", fuValue); + } + configMap.put(key, value); } - configMap.put(key, value); + LOGGER.info("Loading config file [classpath:/" + prop_file + "]"); + return this; } - - LOGGER.info("Loading config file: [classpath:/" + prop_file + "]"); - return this; + return null; } catch (IOException e) { throw new ConfigAdapterException("load properties file error!"); } finally { From 8db76132d2d3311ad1f328495920c378d66d3ea7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 15 Feb 2016 13:22:11 +0800 Subject: [PATCH 407/545] - --- .../java/blade/kit/reflect/ConvertKit.java | 32 +++++++++++++++++++ .../java/blade/kit/reflect/ReflectKit.java | 14 ++++++++ .../main/java/blade/kit/reflect/TypeKit.java | 7 ---- 3 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 blade-kit/src/main/java/blade/kit/reflect/ConvertKit.java delete mode 100644 blade-kit/src/main/java/blade/kit/reflect/TypeKit.java diff --git a/blade-kit/src/main/java/blade/kit/reflect/ConvertKit.java b/blade-kit/src/main/java/blade/kit/reflect/ConvertKit.java new file mode 100644 index 000000000..07f614531 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/reflect/ConvertKit.java @@ -0,0 +1,32 @@ +package blade.kit.reflect; + +import java.util.HashSet; +import java.util.Set; + +public final class ConvertKit { + + private static final Set> basicTypes; + + static { + basicTypes = new HashSet>(); + basicTypes.add(Boolean.class); + basicTypes.add(boolean.class); + basicTypes.add(Integer.class); + basicTypes.add(int.class); + basicTypes.add(Short.class); + basicTypes.add(short.class); + basicTypes.add(Long.class); + basicTypes.add(long.class); + basicTypes.add(Float.class); + basicTypes.add(float.class); + basicTypes.add(Double.class); + basicTypes.add(double.class); + basicTypes.add(Character.class); + basicTypes.add(char.class); + } + + public static boolean isBasicType(Class type){ + return basicTypes.contains(type); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java index f43a76a39..8a1dfd058 100644 --- a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java @@ -456,4 +456,18 @@ public static void forceAccess(AccessibleObject object) { } } + public static boolean hasInterface(Class type, Class interfaceType) { + if(null != type && null != interfaceType){ + Class[] interfaces = type.getInterfaces(); + if(null != interfaces && interfaces.length > 0){ + for(Class inte : interfaces){ + if(inte == interfaceType){ + return true; + } + } + } + } + return false; + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/reflect/TypeKit.java b/blade-kit/src/main/java/blade/kit/reflect/TypeKit.java deleted file mode 100644 index 724a445e6..000000000 --- a/blade-kit/src/main/java/blade/kit/reflect/TypeKit.java +++ /dev/null @@ -1,7 +0,0 @@ -package blade.kit.reflect; - -public final class TypeKit { - - public static void main(String[] args) { - } -} From bb3df7d5f223c336e35100061084dbcd2b866fd0 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 15 Feb 2016 13:22:42 +0800 Subject: [PATCH 408/545] reconsitution interceptor --- blade-core/pom.xml | 5 - blade-core/src/main/java/com/blade/Blade.java | 20 +-- .../com/blade/interceptor/Interceptor.java | 12 ++ .../annotation/Intercept.java} | 9 +- .../java/com/blade/ioc/IocApplication.java | 8 +- .../main/java/com/blade/ioc/SampleIoc.java | 5 +- .../java/com/blade/loader/BladeConfig.java | 41 +++--- .../src/main/java/com/blade/route/Route.java | 14 +- .../java/com/blade/route/RouteBuilder.java | 125 ++++++------------ .../main/java/com/blade/route/Routers.java | 29 ++-- .../com/blade/route/annotation/After.java | 52 -------- .../com/blade/route/annotation/Before.java | 52 -------- .../route/loader/AbstractFileRouteLoader.java | 12 +- .../blade/view/handle/RouteViewHandler.java | 110 +++++++++++++++ .../main/java/com/blade/web/DispatchKit.java | 102 ++++++++++++++ ...estHandler.java => DispatcherHandler.java} | 46 ++++--- .../java/com/blade/web/DispatcherServlet.java | 10 +- .../java/com/blade/web/RouteArgument.java | 85 ------------ .../main/java/com/blade/web/http/Request.java | 6 +- .../java/com/blade/web/http/Response.java | 16 +-- .../com/blade/web/http/ResponsePrint.java | 113 ---------------- .../web/http/wrapper/ServletRequest.java | 4 +- 22 files changed, 385 insertions(+), 491 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/interceptor/Interceptor.java rename blade-core/src/main/java/com/blade/{route/annotation/Interceptor.java => interceptor/annotation/Intercept.java} (86%) delete mode 100644 blade-core/src/main/java/com/blade/route/annotation/After.java delete mode 100644 blade-core/src/main/java/com/blade/route/annotation/Before.java create mode 100644 blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java rename blade-core/src/main/java/com/blade/web/{SyncRequestHandler.java => DispatcherHandler.java} (83%) delete mode 100644 blade-core/src/main/java/com/blade/web/RouteArgument.java delete mode 100644 blade-core/src/main/java/com/blade/web/http/ResponsePrint.java diff --git a/blade-core/pom.xml b/blade-core/pom.xml index ac72c7853..a20f6b42a 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -30,11 +30,6 @@ blade-kit 1.2.9-alpha - - org.slf4j - slf4j-api - 1.7.16 - javax.servlet javax.servlet-api diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index c6014e77e..763923cb2 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -187,13 +187,16 @@ public Blade setAppConf(String confName){ */ public Blade routes(String...packages){ Assert.notNull(packages); - bladeConfig.setRoutePackages(packages); + bladeConfig.addRoutePackages(packages); return this; } public Blade basePackage(String basePackage){ Assert.notBlank(basePackage); bladeConfig.setBasePackage(basePackage); + bladeConfig.addIocPackages(basePackage + ".service.*"); + bladeConfig.addRoutePackages(basePackage + ".controller"); + bladeConfig.setInterceptorPackage(basePackage + ".interceptor"); return this; } @@ -217,9 +220,7 @@ public Blade interceptor(String packageName) { */ public Blade ioc(String...packages){ Assert.notNull(packages); - if(packages.length >0){ - bladeConfig.setIocPackages(packages); - } + bladeConfig.addIocPackages(packages); return this; } @@ -463,7 +464,7 @@ public Blade app(Class bootstrap){ * @param view404 404 view page * @return return blade */ - public Blade setView404(final String view404){ + public Blade view404(final String view404){ Assert.notBlank(view404); bladeConfig.setView404(view404); return this; @@ -475,7 +476,7 @@ public Blade setView404(final String view404){ * @param view500 500 view page * @return return blade */ - public Blade setView500(final String view500){ + public Blade view500(final String view500){ Assert.notBlank(view500); bladeConfig.setView500(view500); return this; @@ -574,13 +575,6 @@ public BladeConfig config(){ return bladeConfig; } - /** - * @return Return blade scan base package - */ - public String basePackage(){ - return bladeConfig.getBasePackage(); - } - /** * @return Return route packages */ diff --git a/blade-core/src/main/java/com/blade/interceptor/Interceptor.java b/blade-core/src/main/java/com/blade/interceptor/Interceptor.java new file mode 100644 index 000000000..08f48b2ff --- /dev/null +++ b/blade-core/src/main/java/com/blade/interceptor/Interceptor.java @@ -0,0 +1,12 @@ +package com.blade.interceptor; + +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +public interface Interceptor { + + boolean before(Request request, Response response); + + boolean after(Request request, Response response); + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/annotation/Interceptor.java b/blade-core/src/main/java/com/blade/interceptor/annotation/Intercept.java similarity index 86% rename from blade-core/src/main/java/com/blade/route/annotation/Interceptor.java rename to blade-core/src/main/java/com/blade/interceptor/annotation/Intercept.java index c29170808..4e210581d 100644 --- a/blade-core/src/main/java/com/blade/route/annotation/Interceptor.java +++ b/blade-core/src/main/java/com/blade/interceptor/annotation/Intercept.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route.annotation; +package com.blade.interceptor.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -24,7 +24,7 @@ * Interceptor notes, written in the class * e.g: *
- * {@link Interceptor}
+ * {@link Intercept}
  * public class BaseInterceptor {...}
  * 
* @author biezhi @@ -33,5 +33,8 @@ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -public @interface Interceptor{ +public @interface Intercept{ + + String value() default "/.*"; + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 1084928ee..d4a6229f5 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -78,13 +78,7 @@ public void init(String[] iocs, Bootstrap bootstrap){ } } - // Initialization injection -// container.initWired(); - - Set names = ioc.getBeanNames(); - for(String name : names){ - LOGGER.info("Add Object:{}={}", name, ioc.getBean(name)); - } + LOGGER.info("Add Object: {}", ioc.getBeans()); } diff --git a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java index 601de6258..987d79454 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java @@ -125,7 +125,7 @@ public void addBean(String name, Class beanClass, boolean singleton) { Assert.isFalse(beanClass.isInterface(), "Must not be interface: %s", beanClass.getName()); Assert.isFalse(Modifier.isAbstract(beanClass.getModifiers()), "Must not be abstract class: %s", beanClass.getName()); - LOGGER.debug("addBean: {}={}", name, beanClass.getName()); + LOGGER.debug("addBean: {} = {}", name, beanClass.getName()); BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton); @@ -137,6 +137,9 @@ public void addBean(String name, Class beanClass, boolean singleton) { Class[] interfaces = beanClass.getInterfaces(); if(interfaces.length > 0){ for(Class interfaceClazz : interfaces){ + if(null != this.getBean(interfaceClazz)){ + break; + } this.addBean(interfaceClazz.getName(), beanDefine); } } diff --git a/blade-core/src/main/java/com/blade/loader/BladeConfig.java b/blade-core/src/main/java/com/blade/loader/BladeConfig.java index 77b27dd4c..060428997 100644 --- a/blade-core/src/main/java/com/blade/loader/BladeConfig.java +++ b/blade-core/src/main/java/com/blade/loader/BladeConfig.java @@ -16,7 +16,6 @@ package com.blade.loader; import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.Set; @@ -38,10 +37,10 @@ public class BladeConfig { private Map configMap; // Storage of all routing packets - private List routePackages = CollectionKit.newArrayList(); + private Set routePackages = CollectionKit.newHashSet(); // Store all IOC packages - private List iocPackages = CollectionKit.newArrayList(); + private Set iocPackages = CollectionKit.newHashSet(); // Store all filter directories private Set staticFolders = CollectionKit.newHashSet(); @@ -72,20 +71,24 @@ public class BladeConfig { private boolean httpCache = false; + private boolean configInit = false; + public BladeConfig() { - init(); } - private void init(){ - Config config = ConfigLoader.load("default.properties"); - Configurator.init(this, config); - - try { - config = ConfigLoader.load("blade.properties"); - if(null != config){ - Configurator.init(this, config); + public void init(){ + if(!configInit){ + try { + Config config = ConfigLoader.load("default.properties"); + if(null != config){ + Configurator.init(this, config); + } + config = ConfigLoader.load("blade.properties"); + if(null != config){ + Configurator.init(this, config); + } + } catch (Exception e) { } - } catch (Exception e) { } } @@ -146,8 +149,10 @@ public String[] getRoutePackages() { return routePackages.toArray(routeArr); } - public void setRoutePackages(String ... packages) { - routePackages.addAll(Arrays.asList(packages)); + public void addRoutePackages(String ... packages) { + if(null != packages && packages.length > 0){ + routePackages.addAll(Arrays.asList(packages)); + } } public String getBasePackage() { @@ -163,8 +168,10 @@ public String[] getIocPackages() { return iocPackages.toArray(iocArr); } - public void setIocPackages(String ... packages) { - iocPackages.addAll(Arrays.asList(packages)); + public void addIocPackages(String ... packages) { + if(null != packages && packages.length > 0){ + iocPackages.addAll(Arrays.asList(packages)); + } } public String getInterceptorPackage() { diff --git a/blade-core/src/main/java/com/blade/route/Route.java b/blade-core/src/main/java/com/blade/route/Route.java index fc81f9ae8..9b528f3de 100644 --- a/blade-core/src/main/java/com/blade/route/Route.java +++ b/blade-core/src/main/java/com/blade/route/Route.java @@ -42,7 +42,12 @@ public class Route { * Logical controller object */ private Object target; - + + /** + * Controller Class Type + */ + private Class targetType; + /** * Implementation logic controller method */ @@ -51,11 +56,12 @@ public class Route { public Route() { } - public Route(HttpMethod httpMethod, String path, Object target, Method action) { + public Route(HttpMethod httpMethod, String path, Object target, Class targetType, Method action) { super(); this.httpMethod = httpMethod; this.path = Path.fixPath(path); this.target = target; + this.targetType = targetType; this.action = action; } @@ -91,6 +97,10 @@ public void setAction(Method action) { this.action = action; } + public Class getTargetType() { + return targetType; + } + @Override public int hashCode() { final int prime = 31; diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index c958d7ec7..b24f5558e 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -19,15 +19,17 @@ import java.util.Set; import com.blade.Blade; +import com.blade.interceptor.Interceptor; +import com.blade.interceptor.annotation.Intercept; import com.blade.ioc.Ioc; -import com.blade.route.annotation.After; -import com.blade.route.annotation.Before; -import com.blade.route.annotation.Interceptor; import com.blade.route.annotation.Path; import com.blade.route.annotation.Route; import com.blade.web.http.HttpMethod; +import com.blade.web.http.Request; +import com.blade.web.http.Response; import blade.kit.StringKit; +import blade.kit.reflect.ReflectKit; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; @@ -39,25 +41,15 @@ */ public class RouteBuilder { - /** - * Default route suffix package, the user scan route location, the default is route, users can customize - */ - private String pkgRoute = "route"; - - /** - * Default interceptor suffix package, the user scans the interceptor location, the default is interceptor, users can customize - */ - private String pkgInterceptor = "interceptor"; - /** * Class reader, used to scan the class specified in the rules */ - private ClassReader classReader = new ClassPathClassReader(); + private ClassReader classReader; /** * IOC container, storage route to IOC */ - private Ioc ioc = null; + private Ioc ioc; private Blade blade; @@ -67,39 +59,26 @@ public RouteBuilder(Blade blade) { this.blade = blade; this.routers = blade.routers(); this.ioc = blade.ioc(); + this.classReader = new ClassPathClassReader(); } /** * Start building route */ public void building() { - String basePackage = blade.basePackage(); - - if(StringKit.isNotBlank(basePackage)){ - - // Processing e.g: com.xxx.* representation of recursive scanning package - String suffix = basePackage.endsWith(".*") ? ".*" : ""; - basePackage = basePackage.endsWith(".*") ? basePackage.substring(0, basePackage.length() - 2) : basePackage; - - String routePackage = basePackage + "." + pkgRoute + suffix; - String interceptorPackage = basePackage + "." + pkgInterceptor + suffix; - - buildRoute(routePackage); - buildInterceptor(interceptorPackage); - - } else { - // Route - String[] routePackages = blade.routePackages(); - if(null != routePackages && routePackages.length > 0){ - buildRoute(routePackages); - } - - // Inteceptor - String interceptorPackage = blade.interceptorPackage(); - if(StringKit.isNotBlank(interceptorPackage)){ - buildInterceptor(interceptorPackage); - } - } + + // Route + String[] routePackages = blade.routePackages(); + if(null != routePackages && routePackages.length > 0){ + this.buildRoute(routePackages); + } + + // Inteceptor + String interceptorPackage = blade.interceptorPackage(); + if(StringKit.isNotBlank(interceptorPackage)){ + this.buildInterceptor(interceptorPackage); + } + } /** @@ -123,7 +102,8 @@ private void buildInterceptor(String... interceptorPackages){ } // Scan all Interceptor - classes = classReader.getClassByAnnotation(packageName, Interceptor.class, recursive); + classes = classReader.getClass(packageName, Interceptor.class, recursive); +// classes = classReader.getClassByAnnotation(packageName, Intercept.class, recursive); if(null != classes && classes.size() > 0){ for(Class interceptorClazz : classes){ @@ -169,52 +149,31 @@ private void buildRoute(String... routePackages){ */ private void parseInterceptor(final Class interceptor){ - Method[] methods = interceptor.getMethods(); - if(null == methods || methods.length == 0){ + boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); + + if(null == interceptor || !hasInterface){ return; } ioc.addBean(interceptor); - for (Method method : methods) { - - Before before = method.getAnnotation(Before.class); - After after = method.getAnnotation(After.class); - - if (null != before) { - - String suffix = before.suffix(); - - String path = getRoutePath(before.value(), "", suffix); - - buildInterceptor(path, interceptor, method, HttpMethod.BEFORE); - - String[] paths = before.values(); - if(null != paths && paths.length > 0){ - for(String value : paths){ - String pathV = getRoutePath(value, "", suffix); - buildInterceptor(pathV, interceptor, method, HttpMethod.BEFORE); - } - } - } - - if (null != after) { - - String suffix = after.suffix(); - - String path = getRoutePath(after.value(), "", suffix); - - buildInterceptor(path, interceptor, method, HttpMethod.AFTER); - - String[] paths = after.values(); - if(null != paths && paths.length > 0){ - for(String value : paths){ - String pathV = getRoutePath(value, "", suffix); - buildInterceptor(pathV, interceptor, method, HttpMethod.AFTER); - } - } - } + Intercept intercept = interceptor.getAnnotation(Intercept.class); + String partten = "/.*"; + if(null != intercept){ + partten = intercept.value(); + } + + try { + Method before = interceptor.getMethod("before", Request.class, Response.class); + Method after = interceptor.getMethod("after", Request.class, Response.class); + buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); + buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); } + } /** diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index b90d87ad4..180c41ea8 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -77,10 +77,10 @@ public void addRoute(Route route) { LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); } this.interceptors.put(key, route); - LOGGER.debug("Add Interceptor:{}", route); + LOGGER.debug("Add Interceptor: {}", route); } else { this.routes.put(key, route); - LOGGER.debug("Add Route:{}", route); + LOGGER.debug("Add Route: {}", route); } } @@ -92,11 +92,12 @@ public void addRoutes(List routes) { } public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, String methodName) throws NoSuchMethodException { - Method method = handler.getClass().getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, handler, method); + Class handleType = handler.getClass(); + Method method = handleType.getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, handler, handleType, method); } - public void addRoute(HttpMethod httpMethod, String path, Object controller, Method method) { + public void addRoute(HttpMethod httpMethod, String path, Object controller, Class controllerType, Method method) { Assert.notNull(httpMethod); Assert.notBlank(path); @@ -108,16 +109,16 @@ public void addRoute(HttpMethod httpMethod, String path, Object controller, Meth LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); } - Route route = new Route(httpMethod, path, controller, method); + Route route = new Route(httpMethod, path, controller, controllerType, method); if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ if (null != this.interceptors.get(key)) { LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); } this.interceptors.put(key, route); - LOGGER.info("Add Interceptor:{}", route); + LOGGER.info("Add Interceptor: {}", route); } else { this.routes.put(key, route); - LOGGER.info("Add Route:{}", route); + LOGGER.info("Add Route: {}", route); } } @@ -143,7 +144,7 @@ public void route(String path, Object target, String methodName) { Assert.notNull(methodName, "Method name not is null"); Method method = target.getClass().getMethod(methodName, Request.class, Response.class); - addRoute(HttpMethod.ALL, path, target, method); + addRoute(HttpMethod.ALL, path, target, target.getClass(), method); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { @@ -171,11 +172,11 @@ public void route(String path, Class clazz, String methodName) { try { Method method = clazz.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, controller, method); + addRoute(httpMethod, path, controller, clazz, method); } catch (NoSuchMethodException e) { try { Method method = clazz.getMethod(methodName, Response.class, Request.class); - addRoute(httpMethod, path, controller, method); + addRoute(httpMethod, path, controller, clazz, method); } catch (NoSuchMethodException e1) { e1.printStackTrace(); } catch (SecurityException e1) { @@ -199,7 +200,7 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt controller = ioc.getBean(clazz); } Method method = clazz.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, controller, method); + addRoute(httpMethod, path, controller, clazz, method); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { @@ -214,7 +215,7 @@ public void buildRoute(String path, Class clazz, Method method, HttpMethod ht ioc.addBean(clazz); controller = ioc.getBean(clazz); } - addRoute(httpMethod, path, null, method); + addRoute(httpMethod, path, controller, clazz, method); } catch (SecurityException e) { e.printStackTrace(); } @@ -225,7 +226,7 @@ public void route(String path, Object target, String methodName, HttpMethod http Class clazz = target.getClass(); ioc.addBean(target); Method method = clazz.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, target, method); + addRoute(httpMethod, path, target, target.getClass(), method); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { diff --git a/blade-core/src/main/java/com/blade/route/annotation/After.java b/blade-core/src/main/java/com/blade/route/annotation/After.java deleted file mode 100644 index 585052e8f..000000000 --- a/blade-core/src/main/java/com/blade/route/annotation/After.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Interceptor post event annotations, write in method - * e.g: - *
- *  {@link After}
- *	public void after(Request request){...}
- * 
- * - * @author biezhi - * @since 1.0 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface After { - - /** - * @return After event to intercept URL - */ - String value() default ""; - - /** - * @return Route suffix - */ - String suffix() default ""; - - /** - * @return Multiple after intercept - */ - String[] values() default {}; -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/annotation/Before.java b/blade-core/src/main/java/com/blade/route/annotation/Before.java deleted file mode 100644 index 84cdb7110..000000000 --- a/blade-core/src/main/java/com/blade/route/annotation/Before.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Interceptor pre event annotation, write in method - * e.g: - *
- *  {@link Before}
- *	public void before(Request request){...}
- *
- * - * @author biezhi - * @since 1.0 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface Before { - - /** - * @return Pre event to intercept URL - */ - String value() default ""; - - /** - * @return Route suffix - */ - String suffix() default ""; - - /** - * @return Multiple front intercept - */ - String[] values() default {}; -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java index 157336eff..22f8269df 100644 --- a/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java @@ -195,14 +195,14 @@ private String validateControllerAndMethod(String beanAndMethod, int line) throw */ private Route buildRoute(String httpMethod, String path, String controllerName, String methodName) throws RouteException { Object controller = controllerLoader.load(controllerName); - Method method = getMethod(controller, methodName); - - return new Route(HttpMethod.valueOf(httpMethod.toUpperCase()), path, null, method); + Class controllerType = controller.getClass(); + Method method = getMethod(controllerType, methodName); + return new Route(HttpMethod.valueOf(httpMethod.toUpperCase()), path, controller, controllerType, method); } - - private Method getMethod(Object controller, String methodName) throws RouteException { + + private Method getMethod(Class controllerType, String methodName) throws RouteException { try { - return controller.getClass().getMethod(methodName, Request.class, Response.class); + return controllerType.getMethod(methodName, Request.class, Response.class); } catch (Exception e) { throw new RouteException(e); } diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java new file mode 100644 index 000000000..0488aaffb --- /dev/null +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -0,0 +1,110 @@ +package com.blade.view.handle; + +import java.lang.reflect.Method; + +import com.blade.route.Route; +import com.blade.view.template.ModelAndView; +import com.blade.web.DispatchKit; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +import blade.kit.json.JSONHelper; +import blade.kit.json.JSONValue; +import blade.kit.reflect.ConvertKit; +import blade.kit.reflect.ReflectKit; + +public class RouteViewHandler { + + /** + * Parameters in the method + * + * @param request Request object for injection to the method parameter list + * @param response Response object for injection to the method parameter list + * @param params Params parameter list + * @return Return the generated array of parameters + */ + public Object[] getArgs(Request request, Response response, Class[] params){ + + int len = params.length; + Object[] args = new Object[len]; + + for(int i=0; i paramTypeClazz = params[i]; + if(paramTypeClazz.getName().equals(Request.class.getName())){ + args[i] = request; + } + if(paramTypeClazz.getName().equals(Response.class.getName())){ + args[i] = response; + } + } + return args; + } + + public void handle(Request request, Response response, Route route){ + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + // execute + + int len = actionMethod.getParameterTypes().length; + actionMethod.setAccessible(true); + try { + Object returnParam = null; + if(len > 0){ + Object[] args = getArgs(request, response, actionMethod.getParameterTypes()); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if(null != returnParam){ + Class returnType = returnParam.getClass(); + if(returnType == String.class){ + response.text(returnParam.toString()); + } else if(returnType == ModelAndView.class){ + ModelAndView modelAndView = (ModelAndView) returnParam; + response.render( modelAndView ); + } else if(ConvertKit.isBasicType(returnType)){ + response.text(returnParam.toString()); + } else { + JSONValue jsonValue = JSONHelper.objectAsJsonValue(returnParam); + String json = jsonValue.toString(); + response.json(json); + } + } + } catch (Exception e) { + request.abort(); + DispatchKit.printError(e, 500, response.raw()); + } + + } + + public boolean intercept(Request request, Response response, Route route){ + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + // execute + int len = actionMethod.getParameterTypes().length; + actionMethod.setAccessible(true); + try { + Object returnParam = null; + if(len > 0){ + Object[] args = getArgs(request, response, actionMethod.getParameterTypes()); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if(null != returnParam){ + Class returnType = returnParam.getClass(); + if(returnType == Boolean.class || returnType == boolean.class){ + return (Boolean) returnParam; + } + } + } catch (Exception e) { + request.abort(); + DispatchKit.printError(e, 500, response.raw()); + } + return false; + } + +} diff --git a/blade-core/src/main/java/com/blade/web/DispatchKit.java b/blade-core/src/main/java/com/blade/web/DispatchKit.java index 93b7f8751..7cdabea92 100644 --- a/blade-core/src/main/java/com/blade/web/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/web/DispatchKit.java @@ -1,7 +1,14 @@ package com.blade.web; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLDecoder; @@ -9,6 +16,13 @@ import javax.servlet.ServletContext; import javax.servlet.http.HttpServletResponse; +import com.blade.Blade; +import com.blade.Const; +import com.blade.web.http.HttpException; + +import blade.kit.FileKit; +import blade.kit.StreamKit; + public class DispatchKit { public static File getWebroot(ServletContext sc) { @@ -49,4 +63,92 @@ public static void setFileDownloadHeader(HttpServletResponse response, String fi } catch (UnsupportedEncodingException e) { } } + + private static boolean isDev = Blade.me().isDev(); + + /** + * Print Error Message + * @param err + * @param code + * @param response + */ + public static void printError(Throwable err, int code, HttpServletResponse response){ + err.printStackTrace(); + try { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final PrintWriter writer = new PrintWriter(baos); + + // If the developer mode, the error output to the page + if(isDev){ + writer.println(String.format(HTML, err.getClass() + " : " + err.getMessage())); + writer.println(); + err.printStackTrace(writer); + writer.println(END); + } else { + if(code == 404){ + writer.write(err.getMessage()); + } else { + writer.write(Const.INTERNAL_ERROR); + } + } + writer.close(); + response.setStatus(code); + InputStream body = new ByteArrayInputStream(baos.toByteArray()); + print(body, response.getOutputStream()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Print + * @param body + * @param out + * @throws IOException + */ + public static void print(InputStream body, OutputStream out) throws IOException { + StreamKit.io(body, out, true, true); + /* + try { + int size = in.available(); + byte[] content = new byte[size]; + in.read(content); + out.write(content); + } finally { + in.close(); + out.close(); + }*/ + } + + + /** + * Print static file + * @param uri + * @param realpath + * @param httpResponse + */ + public static void printStatic(String uri, String realpath, HttpServletResponse httpResponse) { + try { + File file = new File(realpath); + if(FileKit.exist(file)){ + FileInputStream in = new FileInputStream(file); + print(in, httpResponse.getOutputStream()); + } else { + HttpException httpException = new HttpException(404, uri + " not found"); + DispatchKit.printError(httpException, 404, httpResponse); + } + } catch (FileNotFoundException e) { + DispatchKit.printError(e, 404, httpResponse); + } catch (IOException e) { + DispatchKit.printError(e, 500, httpResponse); + } + } + + private static final String HTML = "Blade Framework Error Page" + + "" + + "

%s

";
+	
+	
+	private static final String END = "
Blade-" + Const.BLADE_VERSION + "(Blade Framework
"; + } diff --git a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java similarity index 83% rename from blade-core/src/main/java/com/blade/web/SyncRequestHandler.java rename to blade-core/src/main/java/com/blade/web/DispatcherHandler.java index 1b19f778b..3c42bdab2 100644 --- a/blade-core/src/main/java/com/blade/web/SyncRequestHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -15,7 +15,6 @@ */ package com.blade.web; -import java.lang.reflect.Method; import java.util.List; import javax.servlet.ServletContext; @@ -28,16 +27,17 @@ import com.blade.Blade; import com.blade.Const; import com.blade.context.BladeWebContext; +import com.blade.ioc.Ioc; import com.blade.route.Route; import com.blade.route.RouteHandler; import com.blade.route.RouteMatcher; import com.blade.route.Routers; +import com.blade.view.handle.RouteViewHandler; import com.blade.view.template.ModelAndView; import com.blade.web.http.HttpStatus; import com.blade.web.http.Path; import com.blade.web.http.Request; import com.blade.web.http.Response; -import com.blade.web.http.ResponsePrint; import com.blade.web.http.wrapper.ServletRequest; import com.blade.web.http.wrapper.ServletResponse; @@ -49,10 +49,12 @@ * @author biezhi * @since 1.0 */ -public class SyncRequestHandler { +public class DispatcherHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); + + private Ioc ioc; - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); - private Blade blade; private ServletContext servletContext; @@ -61,11 +63,15 @@ public class SyncRequestHandler { private StaticFileFilter staticFileFilter; - public SyncRequestHandler(ServletContext servletContext, Routers routers) { - this.blade = Blade.me(); + private RouteViewHandler routeViewHandler; + + public DispatcherHandler(ServletContext servletContext, Routers routers) { this.servletContext = servletContext; + this.blade = Blade.me(); + this.ioc = blade.ioc(); this.routeMatcher = new RouteMatcher(routers); this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); + this.routeViewHandler = new RouteViewHandler(); } public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ @@ -84,7 +90,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo LOGGER.debug("Request : {}\t{}", method, uri); } String realpath = httpRequest.getServletContext().getRealPath(uri); - ResponsePrint.printStatic(uri, realpath, httpResponse); + DispatchKit.printStatic(uri, realpath, httpResponse); return; } @@ -111,8 +117,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo result = invokeInterceptor(request, response, befores); if(result){ // execute - handle(request, response, route); - response.status(HttpStatus.OK); + this.routeHandle(request, response, route); if(!request.isAbort()){ // after inteceptor List afters = routeMatcher.getAfter(uri); @@ -125,7 +130,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo } return; } catch (Exception e) { - ResponsePrint.printError(e, 500, httpResponse); + DispatchKit.printError(e, 500, httpResponse); } return; } @@ -158,8 +163,8 @@ private void render404(Response response, String uri) { */ private boolean invokeInterceptor(Request request, Response response, List interceptors) { for(Route route : interceptors){ - handle(request, response, route); - if(request.isAbort()){ + boolean flag = routeViewHandler.intercept(request, response, route); + if(!flag){ return false; } } @@ -173,26 +178,25 @@ private boolean invokeInterceptor(Request request, Response response, List clazz = route.getAction().getDeclaringClass(); - target = Blade.me().ioc().getBean(clazz); + target = ioc.getBean(clazz); + route.setTarget(target); } + request.initPathParams(route.getPath()); // Init context BladeWebContext.setContext(servletContext, request, response); - if(target instanceof RouteHandler){ + if(route.getTargetType() == RouteHandler.class){ RouteHandler routeHandler = (RouteHandler) target; routeHandler.handle(request, response); } else { - Method actionMethod = route.getAction(); - // execute - RouteArgument.executeMethod(target, actionMethod, request, response); + routeViewHandler.handle(request, response, route); } } - -} +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 4077fcce0..f001f0c33 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -52,7 +52,7 @@ public class DispatcherServlet extends HttpServlet { private ServletContext servletContext; - private SyncRequestHandler syncRequestHandler; + private DispatcherHandler dispatcherHandler; public DispatcherServlet() { } @@ -81,6 +81,8 @@ public void init(ServletConfig config) throws ServletException { LOGGER.info("blade.webroot = {}", blade.webRoot()); LOGGER.info("blade.isDev = {}", blade.isDev()); + blade.config().init(); + this.bootstrap = blade.bootstrap(); if(null == bootstrap){ String bootStrapClassName = config.getInitParameter("bootstrap"); @@ -106,11 +108,11 @@ public void init(Blade blade) { this.bootstrap.contextInitialized(blade); - syncRequestHandler = new SyncRequestHandler(servletContext, blade.routers()); + dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); blade.init(); - LOGGER.info("DispatcherFilter initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); + LOGGER.info("DispatcherServlet initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); } } @@ -121,7 +123,7 @@ protected void service(HttpServletRequest httpRequest, HttpServletResponse httpR if(!blade.httpCache()){ DispatchKit.setNoCache(httpResponse); } - syncRequestHandler.handle(httpRequest, httpResponse); + dispatcherHandler.handle(httpRequest, httpResponse); } /** diff --git a/blade-core/src/main/java/com/blade/web/RouteArgument.java b/blade-core/src/main/java/com/blade/web/RouteArgument.java deleted file mode 100644 index 6acb7067d..000000000 --- a/blade-core/src/main/java/com/blade/web/RouteArgument.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; - -import java.lang.reflect.Method; - -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.ResponsePrint; - -import blade.kit.reflect.ReflectKit; - -/** - * Route parameters of injector - * - * @author biezhi - * @since 1.0 - */ -public final class RouteArgument { - - /** - * Parameters in the method - * - * @param request Request object for injection to the method parameter list - * @param response Response object for injection to the method parameter list - * @param params Params parameter list - * @return Return the generated array of parameters - */ - public static Object[] getArgs(Request request, Response response, Class[] params){ - - int len = params.length; - Object[] args = new Object[len]; - - for(int i=0; i paramTypeClazz = params[i]; - if(paramTypeClazz.getName().equals(Request.class.getName())){ - args[i] = request; - } - if(paramTypeClazz.getName().equals(Response.class.getName())){ - args[i] = response; - } - } - return args; - } - - /** - * Implementation route - * - * @param object The instance of the method, that is, the object of the method's class. - * @param method Method to execute - * @param request Request object, as parameter injection - * @param response Response object, as parameter injection - * @return Return value after the method returns - */ - public static Object executeMethod(Object object, Method method, Request request, Response response){ - int len = method.getParameterTypes().length; - method.setAccessible(true); - try { - if(len > 0){ - Object[] args = getArgs(request, response, method.getParameterTypes()); - return ReflectKit.invokeMehod(object, method, args); - } else { - return ReflectKit.invokeMehod(object, method); - } - } catch (Exception e) { - request.abort(); - ResponsePrint.printError(e, 500, response.raw()); - } - return null; - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/http/Request.java b/blade-core/src/main/java/com/blade/web/http/Request.java index 9634738d4..66f5ccc93 100644 --- a/blade-core/src/main/java/com/blade/web/http/Request.java +++ b/blade-core/src/main/java/com/blade/web/http/Request.java @@ -60,7 +60,7 @@ public interface Request { /** * @return Return request URI */ - String path(); + String uri(); /** * @return Return UA @@ -358,5 +358,5 @@ interface BodyParser { InputStream asInputStream(); byte[] asByte(); } - -} + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/http/Response.java b/blade-core/src/main/java/com/blade/web/http/Response.java index b5c211e92..9445ee868 100644 --- a/blade-core/src/main/java/com/blade/web/http/Response.java +++ b/blade-core/src/main/java/com/blade/web/http/Response.java @@ -168,34 +168,34 @@ public interface Response { /** * Render by text * - * @param output text content + * @param text text content * @return Return Response */ - Response text(String output); + Response text(String text); /** * Render by html * - * @param output html content + * @param html html content * @return Return Response */ - Response html(String output); + Response html(String html); /** * Render by json * - * @param output json content + * @param json json content * @return Return Response */ - Response json(String output); + Response json(String json); /** * Render by xml * - * @param output xml content + * @param xml xml content * @return Return Response */ - Response xml(String output); + Response xml(String xml); /** * @return Return OutputStream diff --git a/blade-core/src/main/java/com/blade/web/http/ResponsePrint.java b/blade-core/src/main/java/com/blade/web/http/ResponsePrint.java deleted file mode 100644 index e55930a65..000000000 --- a/blade-core/src/main/java/com/blade/web/http/ResponsePrint.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.blade.web.http; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; - -import javax.servlet.http.HttpServletResponse; - -import blade.kit.FileKit; -import blade.kit.StreamKit; - -import com.blade.Blade; -import com.blade.Const; - -public final class ResponsePrint { - - private static boolean isDev = Blade.me().isDev(); - - private ResponsePrint() { - } - - /** - * Print Error Message - * @param err - * @param code - * @param response - */ - public static void printError(Throwable err, int code, HttpServletResponse response){ - err.printStackTrace(); - try { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final PrintWriter writer = new PrintWriter(baos); - - // If the developer mode, the error output to the page - if(isDev){ - writer.println(String.format(HTML, err.getClass() + " : " + err.getMessage())); - writer.println(); - err.printStackTrace(writer); - writer.println(END); - } else { - if(code == 404){ - writer.write(err.getMessage()); - } else { - writer.write(Const.INTERNAL_ERROR); - } - } - writer.close(); - response.setStatus(code); - InputStream body = new ByteArrayInputStream(baos.toByteArray()); - print(body, response.getOutputStream()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Print - * @param body - * @param out - * @throws IOException - */ - public static void print(InputStream body, OutputStream out) throws IOException { - StreamKit.io(body, out, true, true); - /* - try { - int size = in.available(); - byte[] content = new byte[size]; - in.read(content); - out.write(content); - } finally { - in.close(); - out.close(); - }*/ - } - - - /** - * Print static file - * @param uri - * @param realpath - * @param httpResponse - */ - public static void printStatic(String uri, String realpath, HttpServletResponse httpResponse) { - try { - File file = new File(realpath); - if(FileKit.exist(file)){ - FileInputStream in = new FileInputStream(file); - print(in, httpResponse.getOutputStream()); - } else { - HttpException httpException = new HttpException(404, uri + " not found"); - ResponsePrint.printError(httpException, 404, httpResponse); - } - } catch (FileNotFoundException e) { - ResponsePrint.printError(e, 404, httpResponse); - } catch (IOException e) { - ResponsePrint.printError(e, 500, httpResponse); - } - } - - private static final String HTML = "Blade Framework Error Page" - + "" - + "

%s

";
-	
-	
-	private static final String END = "
Blade-" + Const.BLADE_VERSION + "(Blade Framework
"; - -} diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index 0a1be2e76..b3e73bc1c 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -126,7 +126,7 @@ public void initPathParams(String routePath) { List variables = getPathParam(routePath); String regexPath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); - Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(path()); + Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(uri()); matcher.matches(); // start index at 1 as group(0) always stands for the entire expression @@ -161,7 +161,7 @@ public String url() { } @Override - public String path() { + public String uri() { return Path.fixPath(request.getRequestURI()); } From acba19fb1d1ef610697cddd0eab0fabcb42aee4e Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 15 Feb 2016 14:58:45 +0800 Subject: [PATCH 409/545] update logger --- .../src/main/java/com/blade/patchca/PatchcaService.java | 8 ++++---- .../src/main/java/blade/plugin/redis/RedisPlugin.java | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java index 1b88eaf3b..7fb86f137 100644 --- a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java +++ b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java @@ -14,8 +14,8 @@ import org.patchca.utils.encoder.EncoderHelper; import org.patchca.word.RandomWordFactory; import org.patchca.word.WordFactory; - -import blade.kit.log.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.blade.web.http.Response; import com.blade.web.http.wrapper.Session; @@ -25,7 +25,7 @@ */ public class PatchcaService { - private static final Logger LOGGER = Logger.getLogger(PatchcaService.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PatchcaService.class); private ConfigurableCaptchaService cs = null; private static Random random = new Random(); @@ -80,7 +80,7 @@ public void session(Session session, Response response, String patchca){ setResponseHeaders(response); String token = EncoderHelper.getChallangeAndWriteImage(cs, "png", response.outputStream()); session.attribute(patchca, token); - LOGGER.info("当前sessionid = " + session.id() + ", 验证码 = " + token); + LOGGER.debug("current sessionid = {}, token = {}", session.id(), token); } catch (IOException e) { e.printStackTrace(); } diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java b/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java index e8e691791..8cdf2d599 100644 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java +++ b/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java @@ -3,9 +3,11 @@ import java.util.ArrayList; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.plugin.Plugin; -import blade.kit.log.Logger; import redis.clients.jedis.JedisShardInfo; /** @@ -18,7 +20,7 @@ public enum RedisPlugin implements Plugin { INSTANCE; - private Logger LOGGER = Logger.getLogger(RedisPlugin.class); + private final Logger LOGGER = LoggerFactory.getLogger(RedisPlugin.class); private RedisPlugin() { redisPoolConfig = new RedisPoolConfig(); From b5b89b9bfe9a2d07c337b8018d7aa7634789c3c1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 16 Feb 2016 11:42:30 +0800 Subject: [PATCH 410/545] init blade jdbc --- .../com/blade/interceptor/package-info.java | 4 + .../src/main/java/com/blade/jdbc/DB.java | 19 + .../src/main/java/com/blade/jdbc/Model.java | 134 ++ .../com/blade/jdbc/annotation}/Table.java | 2 +- blade-jdbc/pom.xml | 25 +- .../src/main/java/com/blade/jdbc/DB.java | 44 + .../src/main/java/com/blade/jdbc/DBJob.java | 43 + .../src/main/java/com/blade/jdbc/Page.java | 184 -- .../java/com/blade/jdbc/annotation/Table.java | 26 + .../java/com/blade/jdbc/cache/CacheType.java | 7 - .../blade/jdbc/cache/SimpleSql2oCache.java | 121 -- .../java/com/blade/jdbc/cache/Sql2oCache.java | 36 - .../blade/jdbc/cache/Sql2oCacheFactory.java | 27 - .../com/blade/jdbc/ds/BasicDataSource.java | 17 + .../blade/jdbc/ds/BasicDataSourceImpl.java | 287 +++ .../com/blade/jdbc/ds/ConnectionWrapper.java | 546 +++++ .../blade/jdbc/ds/ConnectionXAResource.java | 92 + .../com/blade/jdbc/ds/StatementWrapper.java | 1783 +++++++++++++++++ .../blade/jdbc/exception/CallException.java | 15 + .../jdbc/exception/DataSourceException.java | 27 - .../java/com/blade/jdbc/test/CRUDTest.java | 124 ++ .../test/java/com/blade/jdbc/test/User.java | 51 + pom.xml | 6 + 23 files changed, 3209 insertions(+), 411 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/interceptor/package-info.java create mode 100644 blade-core/src/main/java/com/blade/jdbc/DB.java create mode 100644 blade-core/src/main/java/com/blade/jdbc/Model.java rename {blade-jdbc/src/main/java/com/blade/jdbc => blade-core/src/main/java/com/blade/jdbc/annotation}/Table.java (89%) create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/DB.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/DBJob.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/Page.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/annotation/Table.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/cache/CacheType.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/cache/SimpleSql2oCache.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCache.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCacheFactory.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSource.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSourceImpl.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionWrapper.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionXAResource.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/ds/StatementWrapper.java create mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/exception/CallException.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/exception/DataSourceException.java create mode 100644 blade-jdbc/src/test/java/com/blade/jdbc/test/CRUDTest.java create mode 100644 blade-jdbc/src/test/java/com/blade/jdbc/test/User.java diff --git a/blade-core/src/main/java/com/blade/interceptor/package-info.java b/blade-core/src/main/java/com/blade/interceptor/package-info.java new file mode 100644 index 000000000..0a1ac0a52 --- /dev/null +++ b/blade-core/src/main/java/com/blade/interceptor/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade Interceptor + */ +package com.blade.interceptor; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/jdbc/DB.java b/blade-core/src/main/java/com/blade/jdbc/DB.java new file mode 100644 index 000000000..acefc7bce --- /dev/null +++ b/blade-core/src/main/java/com/blade/jdbc/DB.java @@ -0,0 +1,19 @@ +package com.blade.jdbc; + +import javax.sql.DataSource; + +import org.sql2o.Sql2o; + +public class DB { + + static Sql2o sql2o; + + public static void open(DataSource dataSource) { + sql2o = new Sql2o(dataSource); + } + + public static void open(String url, String user, String pass){ + sql2o = new Sql2o(url, user, pass); + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/jdbc/Model.java b/blade-core/src/main/java/com/blade/jdbc/Model.java new file mode 100644 index 000000000..30ebda980 --- /dev/null +++ b/blade-core/src/main/java/com/blade/jdbc/Model.java @@ -0,0 +1,134 @@ +package com.blade.jdbc; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sql2o.Connection; +import org.sql2o.Query; +import org.sql2o.Sql2o; + +import com.blade.jdbc.annotation.Table; + + +public class Model { + + private static final Sql2o sql2o = DB.sql2o; + + private static final Logger LOGGER = LoggerFactory.getLogger(Model.class); + + private static String getTableName(Class type) { + return type.getAnnotation(Table.class).value(); + } + + private static String getPkName(Class type) { + return type.getAnnotation(Table.class).PK(); + } + + public static List findAll(final Class type) { + String tbName = getTableName(type); + String sql = "select * from " + tbName; + + LOGGER.debug("execute sql: {}", sql); + + Connection con = sql2o.open(); + List result = con.createQuery(sql).executeAndFetch(type); + con.close(); + return result; + } + + public static T findById(final Class type, Serializable id) { + String tbName = getTableName(type); + String pkName = getPkName(type); + String sql = "select * from " + tbName + " where " + pkName + " = :" + pkName; + LOGGER.debug("execute sql: {}", sql); + + Connection con = sql2o.open(); + T result = con.createQuery(sql).addParameter(pkName, id).executeAndFetchFirst(type); + con.close(); + return result; + } + + /** + * "where name like ? and age > ? oredr by ?" + * @param type + * @param condition + * @param params + * @return + */ + public static T find(final Class type, String condition, Object ... args) { + String tbName = getTableName(type); + StringBuffer sql = new StringBuffer("select * from "); + sql.append(tbName).append(" "); + + Map params = getConditionSql(sql, condition, args); + + LOGGER.debug("execute sql: {}", sql.toString()); + + Connection con = sql2o.open(); + T result = query(con.createQuery(sql.toString()), params).executeAndFetchFirst(type); + con.close(); + return result; + } + + public static List findList(final Class type, String condition, Object ... args) { + + String tbName = getTableName(type); + StringBuffer sql = new StringBuffer("select * from "); + sql.append(tbName).append(" "); + + Map params = getConditionSql(sql, condition, args); + + LOGGER.debug("execute sql: {}", sql.toString()); + + Connection con = sql2o.open(); + List result = query(con.createQuery(sql.toString()), params).executeAndFetch(type); + con.close(); + return result; + } + + public static List findPage(final Class type, int page, int count, String condition, Object ... args) { + String tbName = getTableName(type); + StringBuffer sql = new StringBuffer("select * from "); + sql.append(tbName).append(" "); + + Map params = getConditionSql(sql, condition, args); + + LOGGER.debug("execute sql: {}", sql.toString()); + + Connection con = sql2o.open(); + List result = query(con.createQuery(sql.toString()), params) + .executeAndFetch(type); + con.close(); + return result; + } + + private static Query query(Query query, Map params){ + Set keys = params.keySet(); + for(String key : keys){ + query.addParameter(key, params.get(key)); + } + return query; + } + + private static Map getConditionSql(StringBuffer sql, String condition, Object ... params){ + Map maps = new HashMap(); + int pos = condition.indexOf("?"); + for(int i=0; pos != -1; i++){ + maps.put("param_" + i, params[i]); + condition = condition.replaceFirst("(\\?)", ":param_" + i); + pos = condition.indexOf("?"); + } + sql.append(condition); + return maps; + } + + public static T insert(T type) { + + return type; + } +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/Table.java b/blade-core/src/main/java/com/blade/jdbc/annotation/Table.java similarity index 89% rename from blade-jdbc/src/main/java/com/blade/jdbc/Table.java rename to blade-core/src/main/java/com/blade/jdbc/annotation/Table.java index 4d26bf4f0..947aadcf6 100644 --- a/blade-jdbc/src/main/java/com/blade/jdbc/Table.java +++ b/blade-core/src/main/java/com/blade/jdbc/annotation/Table.java @@ -1,4 +1,4 @@ -package com.blade.jdbc; +package com.blade.jdbc.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/blade-jdbc/pom.xml b/blade-jdbc/pom.xml index cb9af838b..616a2d431 100644 --- a/blade-jdbc/pom.xml +++ b/blade-jdbc/pom.xml @@ -17,21 +17,30 @@ - com.bladejava - blade-core - ${blade.version} - provided + junit + junit + test - com.bladejava - blade-cache - 1.2.3 - provided + org.slf4j + slf4j-api org.sql2o sql2o 1.5.4 + + mysql + mysql-connector-java + 5.1.38 + test + + + org.slf4j + slf4j-simple + 1.7.16 + test + diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/DB.java b/blade-jdbc/src/main/java/com/blade/jdbc/DB.java new file mode 100644 index 000000000..cf44d83af --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/DB.java @@ -0,0 +1,44 @@ +package com.blade.jdbc; + +import javax.sql.DataSource; + +import org.sql2o.Sql2o; + +import com.blade.jdbc.ds.BasicDataSourceImpl; + +public class DB { + + static Sql2o sql2o; + + public static void open(DataSource dataSource) { + try { + sql2o = new Sql2o(dataSource); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void open(String url, String user, String pass) { + sql2o = new Sql2o(url, user, pass); + } + + public static void open(String driver, String url, String user, String pass){ + open(driver, url, user, pass, false); + } + + public static void open(String driver, String url, String user, String pass, boolean useDs){ + if(useDs){ + BasicDataSourceImpl dataSource = new BasicDataSourceImpl("blade-jdbc-ds", driver, url, user, pass); + open(dataSource); + } else { + try { + Class.forName(driver); + open(url, user, pass); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + } + + +} \ No newline at end of file diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/DBJob.java b/blade-jdbc/src/main/java/com/blade/jdbc/DBJob.java new file mode 100644 index 000000000..b5028779e --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/DBJob.java @@ -0,0 +1,43 @@ +package com.blade.jdbc; + +import org.sql2o.Connection; +import org.sql2o.Sql2oException; + +import com.blade.jdbc.exception.CallException; + +public abstract class DBJob { + + protected Connection connection; + + public abstract T execute(); + + public T call(){ + return call(false); + } + + public synchronized T call(boolean dml){ + try { + connection = DB.sql2o.beginTransaction(); + T t = execute(); + if(dml){ + connection.commit(); + } + return t; + } catch (Sql2oException e) { + if(dml){ + connection.rollback(); + } + throw new CallException(e.getMessage()); + } catch (Exception e) { + if(dml){ + connection.rollback(); + } + throw new CallException(e); + } finally { + if(null != connection){ + connection.close(); + } + } + } + +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/Page.java b/blade-jdbc/src/main/java/com/blade/jdbc/Page.java deleted file mode 100644 index 5a789cee6..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/Page.java +++ /dev/null @@ -1,184 +0,0 @@ -package com.blade.jdbc; - -import java.util.ArrayList; -import java.util.List; - -/** - * 分页类 - * - * @author biezhi - * @since 1.0 - * @param - */ -public class Page { - - /** - * 当前页 - */ - private int page = 1; - - /** - * 每页条数 - */ - private int pageSize = 10; - - /** - * 总页数 - */ - private int totalPage = 1; - - /** - * 总记录数 - */ - private long totalCount = 0L; - /** - * 上一页 - */ - private int prev_page = 1; - /** - * 下一页 - */ - private int next_page = 1; - /** - * 首页 - */ - private int home_page = 1; - /** - * 尾页 - */ - private Integer last_page = 1; - - /** - * 链接 - */ - private String url = ""; - /** - * 固定导航数 - */ - private Integer navNum = 1; - - /** - * 数据集 - */ - private List results = new ArrayList(); - - /** - * @param totleCount 总记录数 - * @param page 当前第几页 - * @param pageSize 每页显示条数 - */ - public Page(long totalCount, int page, int pageSize) { - - this.page = page; - - this.pageSize = pageSize; - - //总条数 - this.totalCount = totalCount; - - //总页数 - this.totalPage = ((int) ((this.totalCount + this.pageSize - 1) / pageSize)); - - //首页 - this.home_page = 1; - - //尾页 - this.last_page = totalPage; - - //上一页 - this.prev_page = Math.max(this.page - 1, home_page); - - //下一页 - this.next_page = Math.min(this.page + 1, last_page); - - } - - public int getPage() { - return this.page; - } - - public Integer getPageSize() { - return this.pageSize; - } - - public int getTotalPage() { - return this.totalPage; - } - - public long getTotalCount() { - return totalCount; - } - - public Integer getPrev_page() { - return this.prev_page; - } - - public Integer getNext_page() { - return this.next_page; - } - - public Integer getHome_page() { - return this.home_page; - } - - public Integer getLast_page() { - return this.last_page; - } - - public List getResults() { - return this.results; - } - - public void setResults(List results) { - this.results = results; - } - - public Integer getNavNum() { - return this.navNum; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public void setPage(int page) { - this.page = page; - } - - public void setPageSize(int pageSize) { - this.pageSize = pageSize; - } - - public void setTotalPage(int totalPage) { - this.totalPage = totalPage; - } - - public void setTotalCount(long totalCount) { - this.totalCount = totalCount; - } - - public void setPrev_page(int prev_page) { - this.prev_page = prev_page; - } - - public void setNext_page(int next_page) { - this.next_page = next_page; - } - - public void setHome_page(int home_page) { - this.home_page = home_page; - } - - public void setLast_page(Integer last_page) { - this.last_page = last_page; - } - - public void setNavNum(Integer navNum) { - this.navNum = navNum; - } - -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/annotation/Table.java b/blade-jdbc/src/main/java/com/blade/jdbc/annotation/Table.java new file mode 100644 index 000000000..947aadcf6 --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/annotation/Table.java @@ -0,0 +1,26 @@ +package com.blade.jdbc.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * model表关联注解 + * + * @author biezhi + * @since 1.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Table { + + String value(); + + String PK() default "id"; + + boolean isCache() default true; + +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/cache/CacheType.java b/blade-jdbc/src/main/java/com/blade/jdbc/cache/CacheType.java deleted file mode 100644 index f9f8f7e82..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/cache/CacheType.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.blade.jdbc.cache; - -public enum CacheType { - - list, count, detail, sqllist, sqlcount, sqldetail - -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/cache/SimpleSql2oCache.java b/blade-jdbc/src/main/java/com/blade/jdbc/cache/SimpleSql2oCache.java deleted file mode 100644 index 90984111a..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/cache/SimpleSql2oCache.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.blade.jdbc.cache; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; - -import blade.cache.Cache; -import blade.cache.CacheException; -import blade.cache.CacheManager; - -@SuppressWarnings("unchecked") -public class SimpleSql2oCache implements Sql2oCache { - - private CacheManager cm = CacheManager.me(); - - private static final String CACHE_ID = "sql2o_cache"; - - private Cache cache; - - public SimpleSql2oCache() { - // 5小时清理一次 - long cleanTime = 1000 * 3600 * 300; - cm.setCleanInterval(cleanTime); - // 存放1000个缓存,超过即自动清除 - cache = cm.newLRUCache(CACHE_ID).cacheSize(1000); - } - - @Override - public void hset(String key, String field, Serializable value) { - cache.hset(key, field, value); - } - - @Override - public V hgetV(String key, String field) { - Object value = cache.hget(key, field); - if(null != value){ - return (V) value; - } - return null; - } - - @Override - public void hsetV(String key, String field, Object value) { - cache.hset(key, field, value); - } - - @Override - public Serializable hget(String key, String field) { - Object object = cache.hget(key, field); - if(null != object){ - return (Serializable) object; - } - return null; - } - - - @Override - public List hgetlist(String key, String field) { - Object object = cache.hget(key, field); - if(null != object){ - return (List) object; - } - return null; - } - - @Override - public List> hgetlistmap(String key, String field) { - Object object = cache.hget(key, field); - if(null != object){ - return (List>) object; - } - return null; - } - - @Override - public List hgetlists(String key, String field) { - Object object = cache.hget(key, field); - if(null != object){ - return (List) object; - } - return null; - } - - @Override - public void hdel(String key) { - cache.hdel(key); - } - - @Override - public void hsetlist(String key, String field, List value) { - cache.hset(key, field, value); - } - - @Override - public void hsetlistmap(String key, String field, List> value) { - cache.hset(key, field, value); - } - - @Override - public void hsetlists(String key, String field, List value) { - cache.hset(key, field, value); - } - - @Override - public void clean() { - cache.clear(); - } - - @Override - public void destroy() throws CacheException { - try { - CacheManager.me().destroy(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } - -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCache.java b/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCache.java deleted file mode 100644 index 15715d77f..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCache.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.blade.jdbc.cache; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; - -import blade.cache.CacheException; - -public interface Sql2oCache { - - void hset(String key, String field, Serializable value); - - void hsetV(String key, String field, Object value); - - void hsetlist(String key, String field, List value); - - void hsetlistmap(String key, String field, List> value); - - void hsetlists(String key, String field, List value); - - T hget(String key, String field); - - V hgetV(String key, String field); - - List hgetlist(String key, String field); - - List> hgetlistmap(String key, String field); - - List hgetlists(String key, String field); - - void hdel(String key); - - void clean(); - - void destroy() throws CacheException; -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCacheFactory.java b/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCacheFactory.java deleted file mode 100644 index d133f5137..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/cache/Sql2oCacheFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.blade.jdbc.cache; - - -/** - * 缓存获取工厂 - * - * @author biezhi - * @since 1.0 - */ -public final class Sql2oCacheFactory { - - private static Sql2oCache sql2oCache = new SimpleSql2oCache(); - - public static Sql2oCache getSql2oCache(){ - return sql2oCache; - } - - /** - * 设置缓存 - * - * @param sql2oCache - */ - public static void setSql2oCache(Sql2oCache sql2oCache){ - Sql2oCacheFactory.sql2oCache = sql2oCache; - } - -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSource.java b/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSource.java new file mode 100644 index 000000000..a583f85c3 --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSource.java @@ -0,0 +1,17 @@ +package com.blade.jdbc.ds; + +public interface BasicDataSource { + + String getUrl(); + + int activeCount(); + + int getIdleConnections(); + + int getMaxConnections(); + + long getBorrowTimeout(); + + long getLockTimeout(); + +} \ No newline at end of file diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSourceImpl.java b/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSourceImpl.java new file mode 100644 index 000000000..db45a301b --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSourceImpl.java @@ -0,0 +1,287 @@ +package com.blade.jdbc.ds; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.Driver; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Properties; + +import javax.sql.DataSource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BasicDataSourceImpl implements DataSource, BasicDataSource { + + private static final Logger log = LoggerFactory.getLogger(BasicDataSourceImpl.class); + + private final LinkedList pool = new LinkedList(); + + private int loginTimeout = 10; + private PrintWriter logWriter; + + private final String name; + private final Driver driver; + private final String url; + private final String user; + private final String password; + private final long keepAlive; + private final long borrowTimeout; + private final int lockTimeout; + private final int poolSize; + + private long checkIdleConnectionsTime; + private int activeCount; + private int waitingThreads; + private boolean closed; + + public BasicDataSourceImpl(String name, String driver, String url, String user, String pass) { + try { + this.name = name; + this.driver = (Driver) Class.forName(driver).newInstance(); + this.url = url; + this.user = user; + this.password = pass; + this.keepAlive = 1800 * 1000L; + this.borrowTimeout = 3 * 1000L; + this.lockTimeout = -1; + this.poolSize = 10; + } catch (Exception e) { + throw new IllegalArgumentException("Invalid DataSource descriptor for " + name, e); + } + } + + public void close() { + synchronized (pool) { + for (ConnectionWrapper connection : pool) { + connection.closeUnderlyingConnection(); + } + activeCount = 0; + closed = true; + pool.clear(); + pool.notifyAll(); + } + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "DataSourceImpl{" + name + '}'; + } + + @Override + public Connection getConnection() throws SQLException { + return borrowConnection(); + } + + @Override + public Connection getConnection(String username, String password) throws SQLException { + return getConnection(); + } + + @Override + public PrintWriter getLogWriter() { + return logWriter; + } + + @Override + public void setLogWriter(PrintWriter out) { + this.logWriter = out; + } + + @Override + public void setLoginTimeout(int seconds) { + this.loginTimeout = seconds; + } + + @Override + public int getLoginTimeout() { + return loginTimeout; + } + + public T unwrap(Class iface) throws SQLException { + throw new SQLException("Impossible to unwrap"); + } + + public boolean isWrapperFor(Class iface) { + return false; + } + + private ConnectionWrapper borrowConnection() throws SQLException { + long accessTime = System.currentTimeMillis(); + long waited = 0; + + if (accessTime > checkIdleConnectionsTime) { + checkIdleConnectionsTime = accessTime + keepAlive / 10; + closeIdleConnections(accessTime - keepAlive); + } + + reuse: + synchronized (pool) { + while (!closed) { + // First try to get an idle object from the queue + ConnectionWrapper connection = pool.pollFirst(); + if (connection != null) { + connection.lastAccessTime = accessTime; + return connection; + } + + // If capacity permits, create a new object out of the lock + if (activeCount < poolSize) { + activeCount++; + break reuse; + } + + // Lastly wait until an existing connection becomes free + waitForFreeConnection(borrowTimeout - waited); + waited = System.currentTimeMillis() - accessTime; + } + throw new SQLException("DataSource is closed"); + } + + ConnectionWrapper connection = null; + try { + return connection = new ConnectionWrapper(getRawConnection(), this, accessTime); + } finally { + if (connection == null) decreaseCount(); + } + } + + private Connection getRawConnection() throws SQLException { + Properties props = new Properties(); + if (user != null) props.put("user", user); + if (password != null) props.put("password", password); + + Connection connection = driver.connect(url, props); + if (connection == null) { + throw new SQLException("Unsupported connection string: " + url); + } + + if (lockTimeout >= 0) { + executeRawSQL(connection, "SET LOCK_TIMEOUT " + lockTimeout); + } + + return connection; + } + + private void executeRawSQL(Connection connection, String sql) { + try { + Statement stmt = connection.createStatement(); + try { + stmt.executeUpdate(sql); + } finally { + stmt.close(); + } + } catch (Throwable e) { + log.error("Cannot execute " + sql + " on " + toString(), e); + } + } + + private void closeIdleConnections(long closeTime) { + ArrayList idleConnections = new ArrayList(); + + synchronized (pool) { + for (Iterator iterator = pool.iterator(); iterator.hasNext(); ) { + ConnectionWrapper connection = iterator.next(); + if (connection.lastAccessTime < closeTime) { + idleConnections.add(connection); + iterator.remove(); + decreaseCount(); + } + } + } + + if (!idleConnections.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("Closing " + idleConnections.size() + " idle connections on " + toString()); + } + for (ConnectionWrapper connection : idleConnections) { + connection.closeUnderlyingConnection(); + } + } + } + + private void waitForFreeConnection(long waitTime) throws SQLException { + if (waitTime <= 0) { + throw new SQLException("DataSource timed out waiting for a free connection"); + } + + waitingThreads++; + try { + pool.wait(waitTime); + } catch (InterruptedException e) { + throw new SQLException("Interrupted while waiting for a free connection"); + } + waitingThreads--; + } + + private void decreaseCount() { + synchronized (pool) { + if (!closed) { + activeCount--; + if (waitingThreads > 0) pool.notify(); + } + } + } + + void releaseConnection(ConnectionWrapper connection) { + if (connection.invalidate) { + decreaseCount(); + } else { + synchronized (pool) { + if (!closed) { + pool.addFirst(connection); + if (waitingThreads > 0) pool.notify(); + return; + } + } + } + connection.closeUnderlyingConnection(); + } + + @Override + public String getUrl() { + return url; + } + + @Override + public int activeCount() { + return activeCount; + } + + @Override + public int getIdleConnections() { + synchronized (pool) { + return pool.size(); + } + } + + @Override + public int getMaxConnections() { + return poolSize; + } + + @Override + public long getBorrowTimeout() { + return borrowTimeout; + } + + @Override + public long getLockTimeout() { + return lockTimeout; + } + + @Override + public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { + return null; + } + +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionWrapper.java b/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionWrapper.java new file mode 100644 index 000000000..29f1aef2d --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionWrapper.java @@ -0,0 +1,546 @@ +package com.blade.jdbc.ds; + +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +class ConnectionWrapper implements Connection { + final Connection delegate; + final BasicDataSourceImpl dataSource; + long lastAccessTime; + boolean invalidate; + + ConnectionWrapper(Connection delegate, BasicDataSourceImpl dataSource, long accessTime) { + this.delegate = delegate; + this.dataSource = dataSource; + this.lastAccessTime = accessTime; + } + + void closeUnderlyingConnection() { + try { + delegate.close(); + } catch (SQLException e) { + // Ignore + } + } + + public String nativeSQL(String sql) throws SQLException { + checkValid(); + try { + return delegate.nativeSQL(sql); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setAutoCommit(boolean autoCommit) throws SQLException { + checkValid(); + try { + delegate.setAutoCommit(autoCommit); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean getAutoCommit() throws SQLException { + checkValid(); + try { + return delegate.getAutoCommit(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void commit() throws SQLException { + checkValid(); + try { + delegate.commit(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void rollback() throws SQLException { + checkValid(); + try { + delegate.rollback(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void close() throws SQLException { + dataSource.releaseConnection(this); + } + + public boolean isClosed() throws SQLException { + checkValid(); + try { + return delegate.isClosed(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public DatabaseMetaData getMetaData() throws SQLException { + checkValid(); + try { + return delegate.getMetaData(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setReadOnly(boolean readOnly) throws SQLException { + checkValid(); + try { + delegate.setReadOnly(readOnly); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean isReadOnly() throws SQLException { + checkValid(); + try { + return delegate.isReadOnly(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setCatalog(String catalog) throws SQLException { + checkValid(); + try { + delegate.setCatalog(catalog); + } catch (Throwable e) { + throw handleException(e); + } + } + + public String getCatalog() throws SQLException { + checkValid(); + try { + return delegate.getCatalog(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setTransactionIsolation(int level) throws SQLException { + checkValid(); + try { + delegate.setTransactionIsolation(level); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getTransactionIsolation() throws SQLException { + checkValid(); + try { + return delegate.getTransactionIsolation(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public SQLWarning getWarnings() throws SQLException { + checkValid(); + try { + return delegate.getWarnings(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void clearWarnings() throws SQLException { + checkValid(); + try { + delegate.clearWarnings(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Map> getTypeMap() throws SQLException { + checkValid(); + try { + return delegate.getTypeMap(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setTypeMap(Map> map) throws SQLException { + checkValid(); + try { + delegate.setTypeMap(map); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setHoldability(int holdability) throws SQLException { + checkValid(); + try { + delegate.setHoldability(holdability); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getHoldability() throws SQLException { + checkValid(); + try { + return delegate.getHoldability(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Savepoint setSavepoint() throws SQLException { + checkValid(); + try { + return delegate.setSavepoint(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Savepoint setSavepoint(String name) throws SQLException { + checkValid(); + try { + return delegate.setSavepoint(name); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void rollback(Savepoint savepoint) throws SQLException { + checkValid(); + try { + delegate.rollback(savepoint); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + checkValid(); + try { + delegate.releaseSavepoint(savepoint); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Clob createClob() throws SQLException { + checkValid(); + try { + return delegate.createClob(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Blob createBlob() throws SQLException { + checkValid(); + try { + return delegate.createBlob(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public NClob createNClob() throws SQLException { + checkValid(); + try { + return delegate.createNClob(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public SQLXML createSQLXML() throws SQLException { + checkValid(); + try { + return delegate.createSQLXML(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean isValid(int timeout) throws SQLException { + checkValid(); + try { + return delegate.isValid(timeout); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setClientInfo(String name, String value) throws SQLClientInfoException { + try { + delegate.setClientInfo(name, value); + } catch (Throwable e) { + throw handleClientInfoException(e); + } + } + + public void setClientInfo(Properties properties) throws SQLClientInfoException { + try { + delegate.setClientInfo(properties); + } catch (Throwable e) { + throw handleClientInfoException(e); + } + } + + public String getClientInfo(String name) throws SQLException { + checkValid(); + try { + return delegate.getClientInfo(name); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Properties getClientInfo() throws SQLException { + checkValid(); + try { + return delegate.getClientInfo(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + checkValid(); + try { + return delegate.createArrayOf(typeName, elements); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + checkValid(); + try { + return delegate.createStruct(typeName, attributes); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setSchema(String schema) throws SQLException { + throw new SQLException("JDK 7 feature unavailable"); + } + + public String getSchema() throws SQLException { + throw new SQLException("JDK 7 feature unavailable"); + } + + public void abort(Executor executor) throws SQLException { + throw new SQLException("JDK 7 feature unavailable"); + } + + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + throw new SQLException("JDK 7 feature unavailable"); + } + + public int getNetworkTimeout() throws SQLException { + throw new SQLException("JDK 7 feature unavailable"); + } + + public T unwrap(Class iface) throws SQLException { + try { + return delegate.unwrap(iface); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean isWrapperFor(Class iface) throws SQLException { + try { + return delegate.isWrapperFor(iface); + } catch (Throwable e) { + throw handleException(e); + } + } + + SQLException handleException(Throwable e) { + if (e instanceof SQLException) { + SQLException se = (SQLException) e; + invalidate |= isFatalException(se); + return se; + } + invalidate = true; + return new SQLException(e); + } + + private SQLClientInfoException handleClientInfoException(Throwable e) { + invalidate = true; + if (e instanceof SQLClientInfoException) { + return (SQLClientInfoException) e; + } + throw new IllegalStateException(e); + } + + private void checkValid() throws SQLException { + if (invalidate) { + throw new SQLException("Connection to " + dataSource + " has been invalidated"); + } + } + + private static boolean isFatalException(SQLException e) { + // PK constraint is not fatal for connection + if (e.getErrorCode() == 2627 || e.getErrorCode() == 2601) { + return false; + } else if (e.getMessage() != null && e.getMessage().contains("Violation of PRIMARY KEY constraint")) { + return false; + } + return true; + } + + @Override + public Statement createStatement() throws SQLException { + checkValid(); + try { + return new StatementWrapper(delegate.createStatement(), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + checkValid(); + try { + return new StatementWrapper(delegate.prepareStatement(sql), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + checkValid(); + try { + return new StatementWrapper(delegate.prepareCall(sql), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + checkValid(); + try { + return new StatementWrapper(delegate.createStatement(resultSetType, resultSetConcurrency), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + checkValid(); + try { + return new StatementWrapper(delegate.prepareStatement(sql, resultSetType, resultSetConcurrency), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + checkValid(); + try { + return new StatementWrapper(delegate.prepareCall(sql, resultSetType, resultSetConcurrency), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + checkValid(); + try { + return new StatementWrapper( + delegate.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + checkValid(); + try { + return new StatementWrapper( + delegate.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + checkValid(); + try { + return new StatementWrapper( + delegate.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + checkValid(); + try { + return new StatementWrapper(delegate.prepareStatement(sql, autoGeneratedKeys), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + checkValid(); + try { + return new StatementWrapper(delegate.prepareStatement(sql, columnIndexes), this); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + checkValid(); + try { + return new StatementWrapper(delegate.prepareStatement(sql, columnNames), this); + } catch (Throwable e) { + throw handleException(e); + } + } +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionXAResource.java b/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionXAResource.java new file mode 100644 index 000000000..24e4091dc --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionXAResource.java @@ -0,0 +1,92 @@ +package com.blade.jdbc.ds; + +import javax.transaction.xa.XAException; +import javax.transaction.xa.XAResource; +import javax.transaction.xa.Xid; +import java.sql.SQLException; + +class ConnectionXAResource implements XAResource { + + private final ConnectionWrapper connection; + private Xid xid; + + ConnectionXAResource(ConnectionWrapper connection) { + this.connection = connection; + } + + @Override + public String toString() { + return "ConnectionXAResource{" + connection.dataSource.getName() + ':' + xid + '}'; + } + + @Override + public void start(Xid xid, int flags) throws XAException { + if (this.xid != null) throw new XAException(XAException.XAER_DUPID); + this.xid = xid; + } + + @Override + public void end(Xid xid, int flags) throws XAException { + if (this.xid != xid) throw new XAException(XAException.XAER_INVAL); + this.xid = null; + } + + @Override + public void forget(Xid xid) throws XAException { + if (this.xid != xid) throw new XAException(XAException.XAER_INVAL); + this.xid = null; + } + + @Override + public int prepare(Xid xid) { + return XA_OK; + } + + @Override + public void commit(Xid xid, boolean onePhase) throws XAException { + if (this.xid != xid) throw new XAException(XAException.XAER_INVAL); + + try { + connection.commit(); + } catch (SQLException e) { + throw XAException(e); + } + } + + @Override + public void rollback(Xid xid) throws XAException { + if (this.xid != xid) throw new XAException(XAException.XAER_INVAL); + + try { + connection.rollback(); + } catch (SQLException e) { + throw XAException(e); + } + } + + @Override + public boolean isSameRM(XAResource xaResource) { + return xaResource == this; + } + + @Override + public Xid[] recover(int flag) { + return xid == null ? new Xid[0] : new Xid[]{xid}; + } + + @Override + public int getTransactionTimeout() { + return 0; + } + + @Override + public boolean setTransactionTimeout(int seconds) { + return false; + } + + private static XAException XAException(SQLException e) { + XAException wrapper = new XAException(XAException.XA_RBCOMMFAIL); + wrapper.initCause(e); + return wrapper; + } +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/ds/StatementWrapper.java b/blade-jdbc/src/main/java/com/blade/jdbc/ds/StatementWrapper.java new file mode 100644 index 000000000..19154bb4e --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/ds/StatementWrapper.java @@ -0,0 +1,1783 @@ +package com.blade.jdbc.ds; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.NClob; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Map; + +class StatementWrapper implements CallableStatement { + + final Statement delegate; + final ConnectionWrapper connection; + + StatementWrapper(Statement delegate, ConnectionWrapper connection) { + this.delegate = delegate; + this.connection = connection; + } + + @Override + public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException { + try { + ((CallableStatement) delegate).registerOutParameter(parameterIndex, sqlType); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException { + try { + ((CallableStatement) delegate).registerOutParameter(parameterIndex, sqlType, scale); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public boolean wasNull() throws SQLException { + try { + return ((CallableStatement) delegate).wasNull(); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public String getString(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getString(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public boolean getBoolean(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getBoolean(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public byte getByte(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getByte(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public short getShort(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getShort(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public int getInt(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getInt(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public long getLong(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getLong(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public float getFloat(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getFloat(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public double getDouble(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getDouble(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException { + try { + return ((CallableStatement) delegate).getBigDecimal(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public byte[] getBytes(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getBytes(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Date getDate(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getDate(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Time getTime(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getTime(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Timestamp getTimestamp(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getTimestamp(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Object getObject(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getObject(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public BigDecimal getBigDecimal(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getBigDecimal(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Object getObject(int parameterIndex, Map> map) throws SQLException { + try { + return ((CallableStatement) delegate).getObject(parameterIndex, map); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Ref getRef(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getRef(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Blob getBlob(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getBlob(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Clob getClob(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getClob(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Array getArray(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getArray(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Date getDate(int parameterIndex, Calendar cal) throws SQLException { + try { + return ((CallableStatement) delegate).getDate(parameterIndex, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Time getTime(int parameterIndex, Calendar cal) throws SQLException { + try { + return ((CallableStatement) delegate).getTime(parameterIndex, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException { + try { + return ((CallableStatement) delegate).getTimestamp(parameterIndex, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException { + try { + ((CallableStatement) delegate).registerOutParameter(parameterIndex, sqlType, typeName); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void registerOutParameter(String parameterName, int sqlType) throws SQLException { + try { + ((CallableStatement) delegate).registerOutParameter(parameterName, sqlType); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException { + try { + ((CallableStatement) delegate).registerOutParameter(parameterName, sqlType, scale); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException { + try { + ((CallableStatement) delegate).registerOutParameter(parameterName, sqlType, typeName); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public URL getURL(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getURL(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setURL(String parameterName, URL val) throws SQLException { + try { + ((CallableStatement) delegate).setURL(parameterName, val); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setNull(String parameterName, int sqlType) throws SQLException { + try { + ((CallableStatement) delegate).setNull(parameterName, sqlType); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setBoolean(String parameterName, boolean x) throws SQLException { + try { + ((CallableStatement) delegate).setBoolean(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setByte(String parameterName, byte x) throws SQLException { + try { + ((CallableStatement) delegate).setByte(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setShort(String parameterName, short x) throws SQLException { + try { + ((CallableStatement) delegate).setShort(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setInt(String parameterName, int x) throws SQLException { + try { + ((CallableStatement) delegate).setInt(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setLong(String parameterName, long x) throws SQLException { + try { + ((CallableStatement) delegate).setLong(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setFloat(String parameterName, float x) throws SQLException { + try { + ((CallableStatement) delegate).setFloat(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setDouble(String parameterName, double x) throws SQLException { + try { + ((CallableStatement) delegate).setDouble(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException { + try { + ((CallableStatement) delegate).setBigDecimal(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setString(String parameterName, String x) throws SQLException { + try { + ((CallableStatement) delegate).setString(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setBytes(String parameterName, byte[] x) throws SQLException { + try { + ((CallableStatement) delegate).setBytes(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setDate(String parameterName, Date x) throws SQLException { + try { + ((CallableStatement) delegate).setDate(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setTime(String parameterName, Time x) throws SQLException { + try { + ((CallableStatement) delegate).setTime(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setTimestamp(String parameterName, Timestamp x) throws SQLException { + try { + ((CallableStatement) delegate).setTimestamp(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException { + try { + ((CallableStatement) delegate).setAsciiStream(parameterName, x, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException { + try { + ((CallableStatement) delegate).setBinaryStream(parameterName, x, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException { + try { + ((CallableStatement) delegate).setObject(parameterName, x, targetSqlType, scale); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException { + try { + ((CallableStatement) delegate).setObject(parameterName, x, targetSqlType); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setObject(String parameterName, Object x) throws SQLException { + try { + ((CallableStatement) delegate).setObject(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException { + try { + ((CallableStatement) delegate).setCharacterStream(parameterName, reader, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setDate(String parameterName, Date x, Calendar cal) throws SQLException { + try { + ((CallableStatement) delegate).setDate(parameterName, x, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setTime(String parameterName, Time x, Calendar cal) throws SQLException { + try { + ((CallableStatement) delegate).setTime(parameterName, x, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException { + try { + ((CallableStatement) delegate).setTimestamp(parameterName, x, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setNull(String parameterName, int sqlType, String typeName) throws SQLException { + try { + ((CallableStatement) delegate).setNull(parameterName, sqlType, typeName); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public String getString(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getString(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public boolean getBoolean(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getBoolean(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public byte getByte(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getByte(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public short getShort(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getShort(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getInt(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getInt(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public long getLong(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getLong(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public float getFloat(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getFloat(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public double getDouble(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getDouble(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public byte[] getBytes(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getBytes(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Date getDate(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getDate(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Time getTime(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getTime(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Timestamp getTimestamp(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getTimestamp(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Object getObject(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getObject(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public BigDecimal getBigDecimal(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getBigDecimal(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Object getObject(String parameterName, Map> map) throws SQLException { + try { + return ((CallableStatement) delegate).getObject(parameterName, map); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Ref getRef(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getRef(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Blob getBlob(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getBlob(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Clob getClob(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getClob(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Array getArray(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getArray(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Date getDate(String parameterName, Calendar cal) throws SQLException { + try { + return ((CallableStatement) delegate).getDate(parameterName, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Time getTime(String parameterName, Calendar cal) throws SQLException { + try { + return ((CallableStatement) delegate).getTime(parameterName, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException { + try { + return ((CallableStatement) delegate).getTimestamp(parameterName, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + public URL getURL(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getURL(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public RowId getRowId(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getRowId(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + public RowId getRowId(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getRowId(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setRowId(String parameterName, RowId x) throws SQLException { + try { + ((CallableStatement) delegate).setRowId(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNString(String parameterName, String value) throws SQLException { + try { + ((CallableStatement) delegate).setNString(parameterName, value); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException { + try { + ((CallableStatement) delegate).setNCharacterStream(parameterName, value, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNClob(String parameterName, NClob value) throws SQLException { + try { + ((CallableStatement) delegate).setNClob(parameterName, value); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setClob(String parameterName, Reader reader, long length) throws SQLException { + try { + ((CallableStatement) delegate).setClob(parameterName, reader, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException { + try { + ((CallableStatement) delegate).setBlob(parameterName, inputStream, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNClob(String parameterName, Reader reader, long length) throws SQLException { + try { + ((CallableStatement) delegate).setNClob(parameterName, reader, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public NClob getNClob(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getNClob(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + public NClob getNClob(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getNClob(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { + try { + ((CallableStatement) delegate).setSQLXML(parameterName, xmlObject); + } catch (Throwable e) { + throw handleException(e); + } + } + + public SQLXML getSQLXML(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getSQLXML(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + public SQLXML getSQLXML(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getSQLXML(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public String getNString(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getNString(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + public String getNString(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getNString(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Reader getNCharacterStream(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getNCharacterStream(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Reader getNCharacterStream(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getNCharacterStream(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Reader getCharacterStream(int parameterIndex) throws SQLException { + try { + return ((CallableStatement) delegate).getCharacterStream(parameterIndex); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Reader getCharacterStream(String parameterName) throws SQLException { + try { + return ((CallableStatement) delegate).getCharacterStream(parameterName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBlob(String parameterName, Blob x) throws SQLException { + try { + ((CallableStatement) delegate).setBlob(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setClob(String parameterName, Clob x) throws SQLException { + try { + ((CallableStatement) delegate).setClob(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException { + try { + ((CallableStatement) delegate).setAsciiStream(parameterName, x, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException { + try { + ((CallableStatement) delegate).setBinaryStream(parameterName, x, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException { + try { + ((CallableStatement) delegate).setCharacterStream(parameterName, reader, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setAsciiStream(String parameterName, InputStream x) throws SQLException { + try { + ((CallableStatement) delegate).setAsciiStream(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBinaryStream(String parameterName, InputStream x) throws SQLException { + try { + ((CallableStatement) delegate).setBinaryStream(parameterName, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setCharacterStream(String parameterName, Reader reader) throws SQLException { + try { + ((CallableStatement) delegate).setCharacterStream(parameterName, reader); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNCharacterStream(String parameterName, Reader value) throws SQLException { + try { + ((CallableStatement) delegate).setNCharacterStream(parameterName, value); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setClob(String parameterName, Reader reader) throws SQLException { + try { + ((CallableStatement) delegate).setClob(parameterName, reader); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBlob(String parameterName, InputStream inputStream) throws SQLException { + try { + ((CallableStatement) delegate).setBlob(parameterName, inputStream); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNClob(String parameterName, Reader reader) throws SQLException { + try { + ((CallableStatement) delegate).setNClob(parameterName, reader); + } catch (Throwable e) { + throw handleException(e); + } + } + + public T getObject(int parameterIndex, Class type) throws SQLException { + throw new SQLException("JDK 7 feature unavailable"); + } + + public T getObject(String parameterName, Class type) throws SQLException { + throw new SQLException("JDK 7 feature unavailable"); + } + + public ResultSet executeQuery() throws SQLException { + try { + return ((PreparedStatement) delegate).executeQuery(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int executeUpdate() throws SQLException { + try { + return ((PreparedStatement) delegate).executeUpdate(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNull(int parameterIndex, int sqlType) throws SQLException { + try { + ((PreparedStatement) delegate).setNull(parameterIndex, sqlType); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBoolean(int parameterIndex, boolean x) throws SQLException { + try { + ((PreparedStatement) delegate).setBoolean(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setByte(int parameterIndex, byte x) throws SQLException { + try { + ((PreparedStatement) delegate).setByte(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setShort(int parameterIndex, short x) throws SQLException { + try { + ((PreparedStatement) delegate).setShort(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setInt(int parameterIndex, int x) throws SQLException { + try { + ((PreparedStatement) delegate).setInt(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setLong(int parameterIndex, long x) throws SQLException { + try { + ((PreparedStatement) delegate).setLong(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setFloat(int parameterIndex, float x) throws SQLException { + try { + ((PreparedStatement) delegate).setFloat(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setDouble(int parameterIndex, double x) throws SQLException { + try { + ((PreparedStatement) delegate).setDouble(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { + try { + ((PreparedStatement) delegate).setBigDecimal(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setString(int parameterIndex, String x) throws SQLException { + try { + ((PreparedStatement) delegate).setString(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBytes(int parameterIndex, byte[] x) throws SQLException { + try { + ((PreparedStatement) delegate).setBytes(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setDate(int parameterIndex, Date x) throws SQLException { + try { + ((PreparedStatement) delegate).setDate(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setTime(int parameterIndex, Time x) throws SQLException { + try { + ((PreparedStatement) delegate).setTime(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { + try { + ((PreparedStatement) delegate).setTimestamp(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { + try { + ((PreparedStatement) delegate).setAsciiStream(parameterIndex, x, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + @SuppressWarnings("deprecation") + public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { + try { + ((PreparedStatement) delegate).setUnicodeStream(parameterIndex, x, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { + try { + ((PreparedStatement) delegate).setBinaryStream(parameterIndex, x, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void clearParameters() throws SQLException { + try { + ((PreparedStatement) delegate).clearParameters(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { + try { + ((PreparedStatement) delegate).setObject(parameterIndex, x, targetSqlType); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setObject(int parameterIndex, Object x) throws SQLException { + try { + ((PreparedStatement) delegate).setObject(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean execute() throws SQLException { + try { + return ((PreparedStatement) delegate).execute(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void addBatch() throws SQLException { + try { + ((PreparedStatement) delegate).addBatch(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { + try { + ((PreparedStatement) delegate).setCharacterStream(parameterIndex, reader, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setRef(int parameterIndex, Ref x) throws SQLException { + try { + ((PreparedStatement) delegate).setRef(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBlob(int parameterIndex, Blob x) throws SQLException { + try { + ((PreparedStatement) delegate).setBlob(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setClob(int parameterIndex, Clob x) throws SQLException { + try { + ((PreparedStatement) delegate).setClob(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setArray(int parameterIndex, Array x) throws SQLException { + try { + ((PreparedStatement) delegate).setArray(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public ResultSetMetaData getMetaData() throws SQLException { + try { + return ((PreparedStatement) delegate).getMetaData(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { + try { + ((PreparedStatement) delegate).setDate(parameterIndex, x, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { + try { + ((PreparedStatement) delegate).setTime(parameterIndex, x, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { + try { + ((PreparedStatement) delegate).setTimestamp(parameterIndex, x, cal); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + try { + ((PreparedStatement) delegate).setNull(parameterIndex, sqlType, typeName); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setURL(int parameterIndex, URL x) throws SQLException { + try { + ((PreparedStatement) delegate).setURL(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public ParameterMetaData getParameterMetaData() throws SQLException { + try { + return ((PreparedStatement) delegate).getParameterMetaData(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + try { + ((PreparedStatement) delegate).setRowId(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNString(int parameterIndex, String value) throws SQLException { + try { + ((PreparedStatement) delegate).setNString(parameterIndex, value); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { + try { + ((PreparedStatement) delegate).setNCharacterStream(parameterIndex, value, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNClob(int parameterIndex, NClob value) throws SQLException { + try { + ((PreparedStatement) delegate).setNClob(parameterIndex, value); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + try { + ((PreparedStatement) delegate).setClob(parameterIndex, reader, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { + try { + ((PreparedStatement) delegate).setBlob(parameterIndex, inputStream, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + try { + ((PreparedStatement) delegate).setNClob(parameterIndex, reader, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + try { + ((PreparedStatement) delegate).setSQLXML(parameterIndex, xmlObject); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { + try { + ((PreparedStatement) delegate).setObject(parameterIndex, x, targetSqlType, scaleOrLength); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + try { + ((PreparedStatement) delegate).setAsciiStream(parameterIndex, x, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + try { + ((PreparedStatement) delegate).setBinaryStream(parameterIndex, x, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { + try { + ((PreparedStatement) delegate).setCharacterStream(parameterIndex, reader, length); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + try { + ((PreparedStatement) delegate).setAsciiStream(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + try { + ((PreparedStatement) delegate).setBinaryStream(parameterIndex, x); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + try { + ((PreparedStatement) delegate).setCharacterStream(parameterIndex, reader); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + try { + ((PreparedStatement) delegate).setNCharacterStream(parameterIndex, value); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setClob(int parameterIndex, Reader reader) throws SQLException { + try { + ((PreparedStatement) delegate).setClob(parameterIndex, reader); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + try { + ((PreparedStatement) delegate).setBlob(parameterIndex, inputStream); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + try { + ((PreparedStatement) delegate).setNClob(parameterIndex, reader); + } catch (Throwable e) { + throw handleException(e); + } + } + + public ResultSet executeQuery(String sql) throws SQLException { + try { + return delegate.executeQuery(sql); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int executeUpdate(String sql) throws SQLException { + try { + return delegate.executeUpdate(sql); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void close() throws SQLException { + try { + delegate.close(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getMaxFieldSize() throws SQLException { + try { + return delegate.getMaxFieldSize(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setMaxFieldSize(int max) throws SQLException { + try { + delegate.setMaxFieldSize(max); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getMaxRows() throws SQLException { + try { + return delegate.getMaxRows(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setMaxRows(int max) throws SQLException { + try { + delegate.setMaxRows(max); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setEscapeProcessing(boolean enable) throws SQLException { + try { + delegate.setEscapeProcessing(enable); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getQueryTimeout() throws SQLException { + try { + return delegate.getQueryTimeout(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setQueryTimeout(int seconds) throws SQLException { + try { + delegate.setQueryTimeout(seconds); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void cancel() throws SQLException { + try { + delegate.cancel(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public SQLWarning getWarnings() throws SQLException { + try { + return delegate.getWarnings(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void clearWarnings() throws SQLException { + try { + delegate.clearWarnings(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setCursorName(String name) throws SQLException { + try { + delegate.setCursorName(name); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean execute(String sql) throws SQLException { + try { + return delegate.execute(sql); + } catch (Throwable e) { + throw handleException(e); + } + } + + public ResultSet getResultSet() throws SQLException { + try { + return delegate.getResultSet(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getUpdateCount() throws SQLException { + try { + return delegate.getUpdateCount(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean getMoreResults() throws SQLException { + try { + return delegate.getMoreResults(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setFetchDirection(int direction) throws SQLException { + try { + delegate.setFetchDirection(direction); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getFetchDirection() throws SQLException { + try { + return delegate.getFetchDirection(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setFetchSize(int rows) throws SQLException { + try { + delegate.setFetchSize(rows); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getFetchSize() throws SQLException { + try { + return delegate.getFetchSize(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getResultSetConcurrency() throws SQLException { + try { + return delegate.getResultSetConcurrency(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getResultSetType() throws SQLException { + try { + return delegate.getResultSetType(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void addBatch(String sql) throws SQLException { + try { + delegate.addBatch(sql); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void clearBatch() throws SQLException { + try { + delegate.clearBatch(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int[] executeBatch() throws SQLException { + try { + return delegate.executeBatch(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public Connection getConnection() throws SQLException { + try { + return delegate.getConnection(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean getMoreResults(int current) throws SQLException { + try { + return delegate.getMoreResults(current); + } catch (Throwable e) { + throw handleException(e); + } + } + + public ResultSet getGeneratedKeys() throws SQLException { + try { + return delegate.getGeneratedKeys(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + try { + return delegate.executeUpdate(sql, autoGeneratedKeys); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + try { + return delegate.executeUpdate(sql, columnIndexes); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + try { + return delegate.executeUpdate(sql, columnNames); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + try { + return delegate.execute(sql, autoGeneratedKeys); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + try { + return delegate.execute(sql, columnIndexes); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean execute(String sql, String[] columnNames) throws SQLException { + try { + return delegate.execute(sql, columnNames); + } catch (Throwable e) { + throw handleException(e); + } + } + + public int getResultSetHoldability() throws SQLException { + try { + return delegate.getResultSetHoldability(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean isClosed() throws SQLException { + try { + return delegate.isClosed(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void setPoolable(boolean poolable) throws SQLException { + try { + delegate.setPoolable(poolable); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean isPoolable() throws SQLException { + try { + return delegate.isPoolable(); + } catch (Throwable e) { + throw handleException(e); + } + } + + public void closeOnCompletion() throws SQLException { + throw new SQLException("JDK 7 feature unavailable"); + } + + public boolean isCloseOnCompletion() throws SQLException { + throw new SQLException("JDK 7 feature unavailable"); + } + + public T unwrap(Class iface) throws SQLException { + try { + return delegate.unwrap(iface); + } catch (Throwable e) { + throw handleException(e); + } + } + + public boolean isWrapperFor(Class iface) throws SQLException { + try { + return delegate.isWrapperFor(iface); + } catch (Throwable e) { + throw handleException(e); + } + } + + private SQLException handleException(Throwable e) { + return connection.handleException(e); + } +} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/exception/CallException.java b/blade-jdbc/src/main/java/com/blade/jdbc/exception/CallException.java new file mode 100644 index 000000000..d9c5379b0 --- /dev/null +++ b/blade-jdbc/src/main/java/com/blade/jdbc/exception/CallException.java @@ -0,0 +1,15 @@ +package com.blade.jdbc.exception; + +public class CallException extends RuntimeException { + + private static final long serialVersionUID = 4813572976178058533L; + + public CallException(Throwable t) { + super(t); + } + + public CallException(String msg) { + super(msg); + } + +} \ No newline at end of file diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/exception/DataSourceException.java b/blade-jdbc/src/main/java/com/blade/jdbc/exception/DataSourceException.java deleted file mode 100644 index 00666a0aa..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/exception/DataSourceException.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.blade.jdbc.exception; - - -/** - * DataSourceException - *

- *

- * - * @author biezhi - * @since 1.0 - */ -public class DataSourceException extends RuntimeException{ - - private static final long serialVersionUID = 4566581404090220394L; - - public DataSourceException() { - throw new RuntimeException(); - } - - public DataSourceException(String e) { - throw new RuntimeException(e); - } - - public DataSourceException(Exception e) { - throw new RuntimeException(e); - } -} diff --git a/blade-jdbc/src/test/java/com/blade/jdbc/test/CRUDTest.java b/blade-jdbc/src/test/java/com/blade/jdbc/test/CRUDTest.java new file mode 100644 index 000000000..b33c2e843 --- /dev/null +++ b/blade-jdbc/src/test/java/com/blade/jdbc/test/CRUDTest.java @@ -0,0 +1,124 @@ +package com.blade.jdbc.test; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.jdbc.DB; +import com.blade.jdbc.DBJob; + +public class CRUDTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(CRUDTest.class); + + @Before + public void before() { + DB.open("com.mysql.jdbc.Driver", "jdbc:mysql://127.0.0.1/test", "root", "root", true); + } + + @Test + public void testQuery() { + User user = new DBJob() { + @Override + public User execute() { + return connection.createQuery("select * from user_t").executeAndFetchFirst(User.class); + } + }.call(); + + LOGGER.info(user.toString()); + + List list = new DBJob>() { + @Override + public List execute() { + return connection.createQuery("select * from user_t").executeAndFetch(User.class); + } + }.call(); + + LOGGER.info(list.toString()); + } + + @Test + public void testUpdate() { + int count = new DBJob() { + @Override + public Integer execute() { + return connection.createQuery("update user_t set password = :password where id = :id") + .addParameter("password", "p@s1wd*").addParameter("id", 4).executeUpdate().getResult(); + + } + }.call(); + + LOGGER.info("update count = {}", count); + } + + @Test + public void testInsert() { + Long id = (Long) new DBJob() { + @Override + public Object execute() { + return connection.createQuery("insert into user_t(user_name, password, age) values (:user_name, :password, :age)") + .addParameter("user_name", "test_insert") + .addParameter("password", "test_insert") + .addParameter("age", 15).executeUpdate().getKey(); + } + }.call(true); + + LOGGER.info("insert userid = {}", id); + } + + @Test + public void testInsertWithModel() { + final User user = new User(); + user.setUser_name("model1"); + user.setPassword("pwd1"); + user.setAge(18); + + Long id = (Long) new DBJob() { + @Override + public Object execute() { + return connection.createQuery("INSERT INTO user_t(user_name, password, age) VALUES (:user_name, :password, :age)") + .bind(user).executeUpdate().getKey(); + } + }.call(true); + + LOGGER.info("insert userid = {}", id); + } + + + @Test + public void testDelete() { + + int count = new DBJob() { + @Override + public Integer execute() { + return connection.createQuery("delete from user_t where id = :id").addParameter("id", 4).executeUpdate() + .getResult(); + } + }.call(); + + LOGGER.info("delete count = {}", count); + } + + @Test + public void testTrans() { + boolean flag = new DBJob() { + @Override + public Boolean execute() { + + connection.createQuery("update user_t set password = :password where id = :id") + .addParameter("p@scwrd", "p@s1wd*").addParameter("id", 4).executeUpdate(); + + connection.createQuery("update user_t set password = :password where id = :id") + .addParameter("password", "p@s1wd*").addParameter("id", 1).executeUpdate(); + + return true; + } + }.call(true); + + LOGGER.info("trans flag = {}", flag); + } + +} diff --git a/blade-jdbc/src/test/java/com/blade/jdbc/test/User.java b/blade-jdbc/src/test/java/com/blade/jdbc/test/User.java new file mode 100644 index 000000000..b8f2c642a --- /dev/null +++ b/blade-jdbc/src/test/java/com/blade/jdbc/test/User.java @@ -0,0 +1,51 @@ +package com.blade.jdbc.test; + +public class User { + + private Integer id; + private String user_name; + private String password; + private Integer age; + + public User() { + + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUser_name() { + return user_name; + } + + public void setUser_name(String user_name) { + this.user_name = user_name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + @Override + public String toString() { + return "User [id=" + id + ", user_name=" + user_name + ", password=" + password + ", age=" + age + "]"; + } + +} diff --git a/pom.xml b/pom.xml index 9af7e6792..e31827477 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ 3.0.1 1.6.0-alpha 4.12 + 1.7.16 @@ -51,6 +52,11 @@ ${junit.version} test + + org.slf4j + slf4j-api + ${slf4j-api.version} + From 5e96f70d6217a34a2231114ee62546e3b7af4f2d Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 16 Feb 2016 11:42:49 +0800 Subject: [PATCH 411/545] update pom --- blade-kit/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index ca6d3065a..ed8a85f13 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -27,7 +27,6 @@ org.slf4j slf4j-api - 1.7.16 javax.mail From 4a99f32654dedf47ae5de00a2719b3568d5e1f8d Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 16 Feb 2016 11:47:14 +0800 Subject: [PATCH 412/545] move blade-jdbc to bladejava repo. --- LAST_VERSION.md | 9 + blade-core/pom.xml | 18 +- blade-jdbc/pom.xml | 46 - .../src/main/java/com/blade/jdbc/DB.java | 44 - .../src/main/java/com/blade/jdbc/DBJob.java | 43 - .../java/com/blade/jdbc/annotation/Table.java | 26 - .../com/blade/jdbc/ds/BasicDataSource.java | 17 - .../blade/jdbc/ds/BasicDataSourceImpl.java | 287 --- .../com/blade/jdbc/ds/ConnectionWrapper.java | 546 ----- .../blade/jdbc/ds/ConnectionXAResource.java | 92 - .../com/blade/jdbc/ds/StatementWrapper.java | 1783 ----------------- .../blade/jdbc/exception/CallException.java | 15 - .../java/com/blade/jdbc/test/CRUDTest.java | 124 -- .../test/java/com/blade/jdbc/test/User.java | 51 - pom.xml | 1 - 15 files changed, 12 insertions(+), 3090 deletions(-) delete mode 100644 blade-jdbc/pom.xml delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/DB.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/DBJob.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/annotation/Table.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSource.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSourceImpl.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionWrapper.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionXAResource.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/ds/StatementWrapper.java delete mode 100644 blade-jdbc/src/main/java/com/blade/jdbc/exception/CallException.java delete mode 100644 blade-jdbc/src/test/java/com/blade/jdbc/test/CRUDTest.java delete mode 100644 blade-jdbc/src/test/java/com/blade/jdbc/test/User.java diff --git a/LAST_VERSION.md b/LAST_VERSION.md index bbf994216..6fbfb6452 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -37,6 +37,15 @@ ``` +## [blade-jdbc](http://search.maven.org/#search%7Cga%7C1%7Cblade-jdbc) +```xml + +    com.bladejava +    blade-jdbc +    0.0.1 + +``` + ## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache) ```xml diff --git a/blade-core/pom.xml b/blade-core/pom.xml index a20f6b42a..6a5d2581c 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -37,21 +37,9 @@ provided - com.github.subchen - jetbrick-template - ${jetbrick.version} - provided - - - org.beetl - beetl-core - ${beetl.version} - provided - - - org.apache.velocity - velocity - ${velocity.version} + org.sql2o + sql2o + 1.5.4 provided diff --git a/blade-jdbc/pom.xml b/blade-jdbc/pom.xml deleted file mode 100644 index 616a2d431..000000000 --- a/blade-jdbc/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-jdbc - jar - 0.0.1 - blade-jdbc - https://github.com/biezhi/blade/tree/master/blade-jdbc - - - - junit - junit - test - - - org.slf4j - slf4j-api - - - org.sql2o - sql2o - 1.5.4 - - - mysql - mysql-connector-java - 5.1.38 - test - - - org.slf4j - slf4j-simple - 1.7.16 - test - - - diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/DB.java b/blade-jdbc/src/main/java/com/blade/jdbc/DB.java deleted file mode 100644 index cf44d83af..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/DB.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.blade.jdbc; - -import javax.sql.DataSource; - -import org.sql2o.Sql2o; - -import com.blade.jdbc.ds.BasicDataSourceImpl; - -public class DB { - - static Sql2o sql2o; - - public static void open(DataSource dataSource) { - try { - sql2o = new Sql2o(dataSource); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static void open(String url, String user, String pass) { - sql2o = new Sql2o(url, user, pass); - } - - public static void open(String driver, String url, String user, String pass){ - open(driver, url, user, pass, false); - } - - public static void open(String driver, String url, String user, String pass, boolean useDs){ - if(useDs){ - BasicDataSourceImpl dataSource = new BasicDataSourceImpl("blade-jdbc-ds", driver, url, user, pass); - open(dataSource); - } else { - try { - Class.forName(driver); - open(url, user, pass); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } - } - - -} \ No newline at end of file diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/DBJob.java b/blade-jdbc/src/main/java/com/blade/jdbc/DBJob.java deleted file mode 100644 index b5028779e..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/DBJob.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.blade.jdbc; - -import org.sql2o.Connection; -import org.sql2o.Sql2oException; - -import com.blade.jdbc.exception.CallException; - -public abstract class DBJob { - - protected Connection connection; - - public abstract T execute(); - - public T call(){ - return call(false); - } - - public synchronized T call(boolean dml){ - try { - connection = DB.sql2o.beginTransaction(); - T t = execute(); - if(dml){ - connection.commit(); - } - return t; - } catch (Sql2oException e) { - if(dml){ - connection.rollback(); - } - throw new CallException(e.getMessage()); - } catch (Exception e) { - if(dml){ - connection.rollback(); - } - throw new CallException(e); - } finally { - if(null != connection){ - connection.close(); - } - } - } - -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/annotation/Table.java b/blade-jdbc/src/main/java/com/blade/jdbc/annotation/Table.java deleted file mode 100644 index 947aadcf6..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/annotation/Table.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.blade.jdbc.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * model表关联注解 - * - * @author biezhi - * @since 1.0 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Table { - - String value(); - - String PK() default "id"; - - boolean isCache() default true; - -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSource.java b/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSource.java deleted file mode 100644 index a583f85c3..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSource.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.blade.jdbc.ds; - -public interface BasicDataSource { - - String getUrl(); - - int activeCount(); - - int getIdleConnections(); - - int getMaxConnections(); - - long getBorrowTimeout(); - - long getLockTimeout(); - -} \ No newline at end of file diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSourceImpl.java b/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSourceImpl.java deleted file mode 100644 index db45a301b..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/ds/BasicDataSourceImpl.java +++ /dev/null @@ -1,287 +0,0 @@ -package com.blade.jdbc.ds; - -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.Driver; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Properties; - -import javax.sql.DataSource; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BasicDataSourceImpl implements DataSource, BasicDataSource { - - private static final Logger log = LoggerFactory.getLogger(BasicDataSourceImpl.class); - - private final LinkedList pool = new LinkedList(); - - private int loginTimeout = 10; - private PrintWriter logWriter; - - private final String name; - private final Driver driver; - private final String url; - private final String user; - private final String password; - private final long keepAlive; - private final long borrowTimeout; - private final int lockTimeout; - private final int poolSize; - - private long checkIdleConnectionsTime; - private int activeCount; - private int waitingThreads; - private boolean closed; - - public BasicDataSourceImpl(String name, String driver, String url, String user, String pass) { - try { - this.name = name; - this.driver = (Driver) Class.forName(driver).newInstance(); - this.url = url; - this.user = user; - this.password = pass; - this.keepAlive = 1800 * 1000L; - this.borrowTimeout = 3 * 1000L; - this.lockTimeout = -1; - this.poolSize = 10; - } catch (Exception e) { - throw new IllegalArgumentException("Invalid DataSource descriptor for " + name, e); - } - } - - public void close() { - synchronized (pool) { - for (ConnectionWrapper connection : pool) { - connection.closeUnderlyingConnection(); - } - activeCount = 0; - closed = true; - pool.clear(); - pool.notifyAll(); - } - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return "DataSourceImpl{" + name + '}'; - } - - @Override - public Connection getConnection() throws SQLException { - return borrowConnection(); - } - - @Override - public Connection getConnection(String username, String password) throws SQLException { - return getConnection(); - } - - @Override - public PrintWriter getLogWriter() { - return logWriter; - } - - @Override - public void setLogWriter(PrintWriter out) { - this.logWriter = out; - } - - @Override - public void setLoginTimeout(int seconds) { - this.loginTimeout = seconds; - } - - @Override - public int getLoginTimeout() { - return loginTimeout; - } - - public T unwrap(Class iface) throws SQLException { - throw new SQLException("Impossible to unwrap"); - } - - public boolean isWrapperFor(Class iface) { - return false; - } - - private ConnectionWrapper borrowConnection() throws SQLException { - long accessTime = System.currentTimeMillis(); - long waited = 0; - - if (accessTime > checkIdleConnectionsTime) { - checkIdleConnectionsTime = accessTime + keepAlive / 10; - closeIdleConnections(accessTime - keepAlive); - } - - reuse: - synchronized (pool) { - while (!closed) { - // First try to get an idle object from the queue - ConnectionWrapper connection = pool.pollFirst(); - if (connection != null) { - connection.lastAccessTime = accessTime; - return connection; - } - - // If capacity permits, create a new object out of the lock - if (activeCount < poolSize) { - activeCount++; - break reuse; - } - - // Lastly wait until an existing connection becomes free - waitForFreeConnection(borrowTimeout - waited); - waited = System.currentTimeMillis() - accessTime; - } - throw new SQLException("DataSource is closed"); - } - - ConnectionWrapper connection = null; - try { - return connection = new ConnectionWrapper(getRawConnection(), this, accessTime); - } finally { - if (connection == null) decreaseCount(); - } - } - - private Connection getRawConnection() throws SQLException { - Properties props = new Properties(); - if (user != null) props.put("user", user); - if (password != null) props.put("password", password); - - Connection connection = driver.connect(url, props); - if (connection == null) { - throw new SQLException("Unsupported connection string: " + url); - } - - if (lockTimeout >= 0) { - executeRawSQL(connection, "SET LOCK_TIMEOUT " + lockTimeout); - } - - return connection; - } - - private void executeRawSQL(Connection connection, String sql) { - try { - Statement stmt = connection.createStatement(); - try { - stmt.executeUpdate(sql); - } finally { - stmt.close(); - } - } catch (Throwable e) { - log.error("Cannot execute " + sql + " on " + toString(), e); - } - } - - private void closeIdleConnections(long closeTime) { - ArrayList idleConnections = new ArrayList(); - - synchronized (pool) { - for (Iterator iterator = pool.iterator(); iterator.hasNext(); ) { - ConnectionWrapper connection = iterator.next(); - if (connection.lastAccessTime < closeTime) { - idleConnections.add(connection); - iterator.remove(); - decreaseCount(); - } - } - } - - if (!idleConnections.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("Closing " + idleConnections.size() + " idle connections on " + toString()); - } - for (ConnectionWrapper connection : idleConnections) { - connection.closeUnderlyingConnection(); - } - } - } - - private void waitForFreeConnection(long waitTime) throws SQLException { - if (waitTime <= 0) { - throw new SQLException("DataSource timed out waiting for a free connection"); - } - - waitingThreads++; - try { - pool.wait(waitTime); - } catch (InterruptedException e) { - throw new SQLException("Interrupted while waiting for a free connection"); - } - waitingThreads--; - } - - private void decreaseCount() { - synchronized (pool) { - if (!closed) { - activeCount--; - if (waitingThreads > 0) pool.notify(); - } - } - } - - void releaseConnection(ConnectionWrapper connection) { - if (connection.invalidate) { - decreaseCount(); - } else { - synchronized (pool) { - if (!closed) { - pool.addFirst(connection); - if (waitingThreads > 0) pool.notify(); - return; - } - } - } - connection.closeUnderlyingConnection(); - } - - @Override - public String getUrl() { - return url; - } - - @Override - public int activeCount() { - return activeCount; - } - - @Override - public int getIdleConnections() { - synchronized (pool) { - return pool.size(); - } - } - - @Override - public int getMaxConnections() { - return poolSize; - } - - @Override - public long getBorrowTimeout() { - return borrowTimeout; - } - - @Override - public long getLockTimeout() { - return lockTimeout; - } - - @Override - public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { - return null; - } - -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionWrapper.java b/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionWrapper.java deleted file mode 100644 index 29f1aef2d..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionWrapper.java +++ /dev/null @@ -1,546 +0,0 @@ -package com.blade.jdbc.ds; - -import java.sql.Array; -import java.sql.Blob; -import java.sql.CallableStatement; -import java.sql.Clob; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.NClob; -import java.sql.PreparedStatement; -import java.sql.SQLClientInfoException; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Savepoint; -import java.sql.Statement; -import java.sql.Struct; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.Executor; - -class ConnectionWrapper implements Connection { - final Connection delegate; - final BasicDataSourceImpl dataSource; - long lastAccessTime; - boolean invalidate; - - ConnectionWrapper(Connection delegate, BasicDataSourceImpl dataSource, long accessTime) { - this.delegate = delegate; - this.dataSource = dataSource; - this.lastAccessTime = accessTime; - } - - void closeUnderlyingConnection() { - try { - delegate.close(); - } catch (SQLException e) { - // Ignore - } - } - - public String nativeSQL(String sql) throws SQLException { - checkValid(); - try { - return delegate.nativeSQL(sql); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setAutoCommit(boolean autoCommit) throws SQLException { - checkValid(); - try { - delegate.setAutoCommit(autoCommit); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean getAutoCommit() throws SQLException { - checkValid(); - try { - return delegate.getAutoCommit(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void commit() throws SQLException { - checkValid(); - try { - delegate.commit(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void rollback() throws SQLException { - checkValid(); - try { - delegate.rollback(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void close() throws SQLException { - dataSource.releaseConnection(this); - } - - public boolean isClosed() throws SQLException { - checkValid(); - try { - return delegate.isClosed(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public DatabaseMetaData getMetaData() throws SQLException { - checkValid(); - try { - return delegate.getMetaData(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setReadOnly(boolean readOnly) throws SQLException { - checkValid(); - try { - delegate.setReadOnly(readOnly); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean isReadOnly() throws SQLException { - checkValid(); - try { - return delegate.isReadOnly(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setCatalog(String catalog) throws SQLException { - checkValid(); - try { - delegate.setCatalog(catalog); - } catch (Throwable e) { - throw handleException(e); - } - } - - public String getCatalog() throws SQLException { - checkValid(); - try { - return delegate.getCatalog(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setTransactionIsolation(int level) throws SQLException { - checkValid(); - try { - delegate.setTransactionIsolation(level); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getTransactionIsolation() throws SQLException { - checkValid(); - try { - return delegate.getTransactionIsolation(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public SQLWarning getWarnings() throws SQLException { - checkValid(); - try { - return delegate.getWarnings(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void clearWarnings() throws SQLException { - checkValid(); - try { - delegate.clearWarnings(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Map> getTypeMap() throws SQLException { - checkValid(); - try { - return delegate.getTypeMap(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setTypeMap(Map> map) throws SQLException { - checkValid(); - try { - delegate.setTypeMap(map); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setHoldability(int holdability) throws SQLException { - checkValid(); - try { - delegate.setHoldability(holdability); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getHoldability() throws SQLException { - checkValid(); - try { - return delegate.getHoldability(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Savepoint setSavepoint() throws SQLException { - checkValid(); - try { - return delegate.setSavepoint(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Savepoint setSavepoint(String name) throws SQLException { - checkValid(); - try { - return delegate.setSavepoint(name); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void rollback(Savepoint savepoint) throws SQLException { - checkValid(); - try { - delegate.rollback(savepoint); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void releaseSavepoint(Savepoint savepoint) throws SQLException { - checkValid(); - try { - delegate.releaseSavepoint(savepoint); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Clob createClob() throws SQLException { - checkValid(); - try { - return delegate.createClob(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Blob createBlob() throws SQLException { - checkValid(); - try { - return delegate.createBlob(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public NClob createNClob() throws SQLException { - checkValid(); - try { - return delegate.createNClob(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public SQLXML createSQLXML() throws SQLException { - checkValid(); - try { - return delegate.createSQLXML(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean isValid(int timeout) throws SQLException { - checkValid(); - try { - return delegate.isValid(timeout); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setClientInfo(String name, String value) throws SQLClientInfoException { - try { - delegate.setClientInfo(name, value); - } catch (Throwable e) { - throw handleClientInfoException(e); - } - } - - public void setClientInfo(Properties properties) throws SQLClientInfoException { - try { - delegate.setClientInfo(properties); - } catch (Throwable e) { - throw handleClientInfoException(e); - } - } - - public String getClientInfo(String name) throws SQLException { - checkValid(); - try { - return delegate.getClientInfo(name); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Properties getClientInfo() throws SQLException { - checkValid(); - try { - return delegate.getClientInfo(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Array createArrayOf(String typeName, Object[] elements) throws SQLException { - checkValid(); - try { - return delegate.createArrayOf(typeName, elements); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Struct createStruct(String typeName, Object[] attributes) throws SQLException { - checkValid(); - try { - return delegate.createStruct(typeName, attributes); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setSchema(String schema) throws SQLException { - throw new SQLException("JDK 7 feature unavailable"); - } - - public String getSchema() throws SQLException { - throw new SQLException("JDK 7 feature unavailable"); - } - - public void abort(Executor executor) throws SQLException { - throw new SQLException("JDK 7 feature unavailable"); - } - - public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { - throw new SQLException("JDK 7 feature unavailable"); - } - - public int getNetworkTimeout() throws SQLException { - throw new SQLException("JDK 7 feature unavailable"); - } - - public T unwrap(Class iface) throws SQLException { - try { - return delegate.unwrap(iface); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean isWrapperFor(Class iface) throws SQLException { - try { - return delegate.isWrapperFor(iface); - } catch (Throwable e) { - throw handleException(e); - } - } - - SQLException handleException(Throwable e) { - if (e instanceof SQLException) { - SQLException se = (SQLException) e; - invalidate |= isFatalException(se); - return se; - } - invalidate = true; - return new SQLException(e); - } - - private SQLClientInfoException handleClientInfoException(Throwable e) { - invalidate = true; - if (e instanceof SQLClientInfoException) { - return (SQLClientInfoException) e; - } - throw new IllegalStateException(e); - } - - private void checkValid() throws SQLException { - if (invalidate) { - throw new SQLException("Connection to " + dataSource + " has been invalidated"); - } - } - - private static boolean isFatalException(SQLException e) { - // PK constraint is not fatal for connection - if (e.getErrorCode() == 2627 || e.getErrorCode() == 2601) { - return false; - } else if (e.getMessage() != null && e.getMessage().contains("Violation of PRIMARY KEY constraint")) { - return false; - } - return true; - } - - @Override - public Statement createStatement() throws SQLException { - checkValid(); - try { - return new StatementWrapper(delegate.createStatement(), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public PreparedStatement prepareStatement(String sql) throws SQLException { - checkValid(); - try { - return new StatementWrapper(delegate.prepareStatement(sql), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public CallableStatement prepareCall(String sql) throws SQLException { - checkValid(); - try { - return new StatementWrapper(delegate.prepareCall(sql), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { - checkValid(); - try { - return new StatementWrapper(delegate.createStatement(resultSetType, resultSetConcurrency), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) - throws SQLException { - checkValid(); - try { - return new StatementWrapper(delegate.prepareStatement(sql, resultSetType, resultSetConcurrency), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - checkValid(); - try { - return new StatementWrapper(delegate.prepareCall(sql, resultSetType, resultSetConcurrency), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) - throws SQLException { - checkValid(); - try { - return new StatementWrapper( - delegate.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, - int resultSetHoldability) throws SQLException { - checkValid(); - try { - return new StatementWrapper( - delegate.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, - int resultSetHoldability) throws SQLException { - checkValid(); - try { - return new StatementWrapper( - delegate.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { - checkValid(); - try { - return new StatementWrapper(delegate.prepareStatement(sql, autoGeneratedKeys), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { - checkValid(); - try { - return new StatementWrapper(delegate.prepareStatement(sql, columnIndexes), this); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { - checkValid(); - try { - return new StatementWrapper(delegate.prepareStatement(sql, columnNames), this); - } catch (Throwable e) { - throw handleException(e); - } - } -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionXAResource.java b/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionXAResource.java deleted file mode 100644 index 24e4091dc..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/ds/ConnectionXAResource.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.blade.jdbc.ds; - -import javax.transaction.xa.XAException; -import javax.transaction.xa.XAResource; -import javax.transaction.xa.Xid; -import java.sql.SQLException; - -class ConnectionXAResource implements XAResource { - - private final ConnectionWrapper connection; - private Xid xid; - - ConnectionXAResource(ConnectionWrapper connection) { - this.connection = connection; - } - - @Override - public String toString() { - return "ConnectionXAResource{" + connection.dataSource.getName() + ':' + xid + '}'; - } - - @Override - public void start(Xid xid, int flags) throws XAException { - if (this.xid != null) throw new XAException(XAException.XAER_DUPID); - this.xid = xid; - } - - @Override - public void end(Xid xid, int flags) throws XAException { - if (this.xid != xid) throw new XAException(XAException.XAER_INVAL); - this.xid = null; - } - - @Override - public void forget(Xid xid) throws XAException { - if (this.xid != xid) throw new XAException(XAException.XAER_INVAL); - this.xid = null; - } - - @Override - public int prepare(Xid xid) { - return XA_OK; - } - - @Override - public void commit(Xid xid, boolean onePhase) throws XAException { - if (this.xid != xid) throw new XAException(XAException.XAER_INVAL); - - try { - connection.commit(); - } catch (SQLException e) { - throw XAException(e); - } - } - - @Override - public void rollback(Xid xid) throws XAException { - if (this.xid != xid) throw new XAException(XAException.XAER_INVAL); - - try { - connection.rollback(); - } catch (SQLException e) { - throw XAException(e); - } - } - - @Override - public boolean isSameRM(XAResource xaResource) { - return xaResource == this; - } - - @Override - public Xid[] recover(int flag) { - return xid == null ? new Xid[0] : new Xid[]{xid}; - } - - @Override - public int getTransactionTimeout() { - return 0; - } - - @Override - public boolean setTransactionTimeout(int seconds) { - return false; - } - - private static XAException XAException(SQLException e) { - XAException wrapper = new XAException(XAException.XA_RBCOMMFAIL); - wrapper.initCause(e); - return wrapper; - } -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/ds/StatementWrapper.java b/blade-jdbc/src/main/java/com/blade/jdbc/ds/StatementWrapper.java deleted file mode 100644 index 19154bb4e..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/ds/StatementWrapper.java +++ /dev/null @@ -1,1783 +0,0 @@ -package com.blade.jdbc.ds; - -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.sql.Array; -import java.sql.Blob; -import java.sql.CallableStatement; -import java.sql.Clob; -import java.sql.Connection; -import java.sql.Date; -import java.sql.NClob; -import java.sql.ParameterMetaData; -import java.sql.PreparedStatement; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.Map; - -class StatementWrapper implements CallableStatement { - - final Statement delegate; - final ConnectionWrapper connection; - - StatementWrapper(Statement delegate, ConnectionWrapper connection) { - this.delegate = delegate; - this.connection = connection; - } - - @Override - public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException { - try { - ((CallableStatement) delegate).registerOutParameter(parameterIndex, sqlType); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException { - try { - ((CallableStatement) delegate).registerOutParameter(parameterIndex, sqlType, scale); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public boolean wasNull() throws SQLException { - try { - return ((CallableStatement) delegate).wasNull(); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public String getString(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getString(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public boolean getBoolean(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getBoolean(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public byte getByte(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getByte(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public short getShort(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getShort(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public int getInt(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getInt(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public long getLong(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getLong(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public float getFloat(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getFloat(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public double getDouble(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getDouble(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException { - try { - return ((CallableStatement) delegate).getBigDecimal(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public byte[] getBytes(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getBytes(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Date getDate(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getDate(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Time getTime(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getTime(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Timestamp getTimestamp(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getTimestamp(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Object getObject(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getObject(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public BigDecimal getBigDecimal(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getBigDecimal(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Object getObject(int parameterIndex, Map> map) throws SQLException { - try { - return ((CallableStatement) delegate).getObject(parameterIndex, map); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Ref getRef(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getRef(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Blob getBlob(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getBlob(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Clob getClob(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getClob(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Array getArray(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getArray(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Date getDate(int parameterIndex, Calendar cal) throws SQLException { - try { - return ((CallableStatement) delegate).getDate(parameterIndex, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Time getTime(int parameterIndex, Calendar cal) throws SQLException { - try { - return ((CallableStatement) delegate).getTime(parameterIndex, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException { - try { - return ((CallableStatement) delegate).getTimestamp(parameterIndex, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException { - try { - ((CallableStatement) delegate).registerOutParameter(parameterIndex, sqlType, typeName); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void registerOutParameter(String parameterName, int sqlType) throws SQLException { - try { - ((CallableStatement) delegate).registerOutParameter(parameterName, sqlType); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException { - try { - ((CallableStatement) delegate).registerOutParameter(parameterName, sqlType, scale); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException { - try { - ((CallableStatement) delegate).registerOutParameter(parameterName, sqlType, typeName); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public URL getURL(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getURL(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setURL(String parameterName, URL val) throws SQLException { - try { - ((CallableStatement) delegate).setURL(parameterName, val); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setNull(String parameterName, int sqlType) throws SQLException { - try { - ((CallableStatement) delegate).setNull(parameterName, sqlType); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setBoolean(String parameterName, boolean x) throws SQLException { - try { - ((CallableStatement) delegate).setBoolean(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setByte(String parameterName, byte x) throws SQLException { - try { - ((CallableStatement) delegate).setByte(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setShort(String parameterName, short x) throws SQLException { - try { - ((CallableStatement) delegate).setShort(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setInt(String parameterName, int x) throws SQLException { - try { - ((CallableStatement) delegate).setInt(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setLong(String parameterName, long x) throws SQLException { - try { - ((CallableStatement) delegate).setLong(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setFloat(String parameterName, float x) throws SQLException { - try { - ((CallableStatement) delegate).setFloat(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setDouble(String parameterName, double x) throws SQLException { - try { - ((CallableStatement) delegate).setDouble(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException { - try { - ((CallableStatement) delegate).setBigDecimal(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setString(String parameterName, String x) throws SQLException { - try { - ((CallableStatement) delegate).setString(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setBytes(String parameterName, byte[] x) throws SQLException { - try { - ((CallableStatement) delegate).setBytes(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setDate(String parameterName, Date x) throws SQLException { - try { - ((CallableStatement) delegate).setDate(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setTime(String parameterName, Time x) throws SQLException { - try { - ((CallableStatement) delegate).setTime(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setTimestamp(String parameterName, Timestamp x) throws SQLException { - try { - ((CallableStatement) delegate).setTimestamp(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException { - try { - ((CallableStatement) delegate).setAsciiStream(parameterName, x, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException { - try { - ((CallableStatement) delegate).setBinaryStream(parameterName, x, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException { - try { - ((CallableStatement) delegate).setObject(parameterName, x, targetSqlType, scale); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException { - try { - ((CallableStatement) delegate).setObject(parameterName, x, targetSqlType); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setObject(String parameterName, Object x) throws SQLException { - try { - ((CallableStatement) delegate).setObject(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException { - try { - ((CallableStatement) delegate).setCharacterStream(parameterName, reader, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setDate(String parameterName, Date x, Calendar cal) throws SQLException { - try { - ((CallableStatement) delegate).setDate(parameterName, x, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setTime(String parameterName, Time x, Calendar cal) throws SQLException { - try { - ((CallableStatement) delegate).setTime(parameterName, x, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException { - try { - ((CallableStatement) delegate).setTimestamp(parameterName, x, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setNull(String parameterName, int sqlType, String typeName) throws SQLException { - try { - ((CallableStatement) delegate).setNull(parameterName, sqlType, typeName); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public String getString(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getString(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public boolean getBoolean(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getBoolean(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public byte getByte(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getByte(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public short getShort(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getShort(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getInt(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getInt(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public long getLong(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getLong(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public float getFloat(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getFloat(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public double getDouble(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getDouble(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public byte[] getBytes(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getBytes(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Date getDate(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getDate(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Time getTime(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getTime(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Timestamp getTimestamp(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getTimestamp(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Object getObject(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getObject(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public BigDecimal getBigDecimal(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getBigDecimal(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Object getObject(String parameterName, Map> map) throws SQLException { - try { - return ((CallableStatement) delegate).getObject(parameterName, map); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Ref getRef(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getRef(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Blob getBlob(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getBlob(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Clob getClob(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getClob(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Array getArray(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getArray(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Date getDate(String parameterName, Calendar cal) throws SQLException { - try { - return ((CallableStatement) delegate).getDate(parameterName, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Time getTime(String parameterName, Calendar cal) throws SQLException { - try { - return ((CallableStatement) delegate).getTime(parameterName, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException { - try { - return ((CallableStatement) delegate).getTimestamp(parameterName, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - public URL getURL(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getURL(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public RowId getRowId(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getRowId(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - public RowId getRowId(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getRowId(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setRowId(String parameterName, RowId x) throws SQLException { - try { - ((CallableStatement) delegate).setRowId(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNString(String parameterName, String value) throws SQLException { - try { - ((CallableStatement) delegate).setNString(parameterName, value); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException { - try { - ((CallableStatement) delegate).setNCharacterStream(parameterName, value, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNClob(String parameterName, NClob value) throws SQLException { - try { - ((CallableStatement) delegate).setNClob(parameterName, value); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setClob(String parameterName, Reader reader, long length) throws SQLException { - try { - ((CallableStatement) delegate).setClob(parameterName, reader, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException { - try { - ((CallableStatement) delegate).setBlob(parameterName, inputStream, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNClob(String parameterName, Reader reader, long length) throws SQLException { - try { - ((CallableStatement) delegate).setNClob(parameterName, reader, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public NClob getNClob(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getNClob(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - public NClob getNClob(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getNClob(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { - try { - ((CallableStatement) delegate).setSQLXML(parameterName, xmlObject); - } catch (Throwable e) { - throw handleException(e); - } - } - - public SQLXML getSQLXML(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getSQLXML(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - public SQLXML getSQLXML(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getSQLXML(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public String getNString(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getNString(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - public String getNString(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getNString(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Reader getNCharacterStream(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getNCharacterStream(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Reader getNCharacterStream(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getNCharacterStream(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Reader getCharacterStream(int parameterIndex) throws SQLException { - try { - return ((CallableStatement) delegate).getCharacterStream(parameterIndex); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Reader getCharacterStream(String parameterName) throws SQLException { - try { - return ((CallableStatement) delegate).getCharacterStream(parameterName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBlob(String parameterName, Blob x) throws SQLException { - try { - ((CallableStatement) delegate).setBlob(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setClob(String parameterName, Clob x) throws SQLException { - try { - ((CallableStatement) delegate).setClob(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException { - try { - ((CallableStatement) delegate).setAsciiStream(parameterName, x, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException { - try { - ((CallableStatement) delegate).setBinaryStream(parameterName, x, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException { - try { - ((CallableStatement) delegate).setCharacterStream(parameterName, reader, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setAsciiStream(String parameterName, InputStream x) throws SQLException { - try { - ((CallableStatement) delegate).setAsciiStream(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBinaryStream(String parameterName, InputStream x) throws SQLException { - try { - ((CallableStatement) delegate).setBinaryStream(parameterName, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setCharacterStream(String parameterName, Reader reader) throws SQLException { - try { - ((CallableStatement) delegate).setCharacterStream(parameterName, reader); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNCharacterStream(String parameterName, Reader value) throws SQLException { - try { - ((CallableStatement) delegate).setNCharacterStream(parameterName, value); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setClob(String parameterName, Reader reader) throws SQLException { - try { - ((CallableStatement) delegate).setClob(parameterName, reader); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBlob(String parameterName, InputStream inputStream) throws SQLException { - try { - ((CallableStatement) delegate).setBlob(parameterName, inputStream); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNClob(String parameterName, Reader reader) throws SQLException { - try { - ((CallableStatement) delegate).setNClob(parameterName, reader); - } catch (Throwable e) { - throw handleException(e); - } - } - - public T getObject(int parameterIndex, Class type) throws SQLException { - throw new SQLException("JDK 7 feature unavailable"); - } - - public T getObject(String parameterName, Class type) throws SQLException { - throw new SQLException("JDK 7 feature unavailable"); - } - - public ResultSet executeQuery() throws SQLException { - try { - return ((PreparedStatement) delegate).executeQuery(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int executeUpdate() throws SQLException { - try { - return ((PreparedStatement) delegate).executeUpdate(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNull(int parameterIndex, int sqlType) throws SQLException { - try { - ((PreparedStatement) delegate).setNull(parameterIndex, sqlType); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBoolean(int parameterIndex, boolean x) throws SQLException { - try { - ((PreparedStatement) delegate).setBoolean(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setByte(int parameterIndex, byte x) throws SQLException { - try { - ((PreparedStatement) delegate).setByte(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setShort(int parameterIndex, short x) throws SQLException { - try { - ((PreparedStatement) delegate).setShort(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setInt(int parameterIndex, int x) throws SQLException { - try { - ((PreparedStatement) delegate).setInt(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setLong(int parameterIndex, long x) throws SQLException { - try { - ((PreparedStatement) delegate).setLong(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setFloat(int parameterIndex, float x) throws SQLException { - try { - ((PreparedStatement) delegate).setFloat(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setDouble(int parameterIndex, double x) throws SQLException { - try { - ((PreparedStatement) delegate).setDouble(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { - try { - ((PreparedStatement) delegate).setBigDecimal(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setString(int parameterIndex, String x) throws SQLException { - try { - ((PreparedStatement) delegate).setString(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBytes(int parameterIndex, byte[] x) throws SQLException { - try { - ((PreparedStatement) delegate).setBytes(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setDate(int parameterIndex, Date x) throws SQLException { - try { - ((PreparedStatement) delegate).setDate(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setTime(int parameterIndex, Time x) throws SQLException { - try { - ((PreparedStatement) delegate).setTime(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { - try { - ((PreparedStatement) delegate).setTimestamp(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { - try { - ((PreparedStatement) delegate).setAsciiStream(parameterIndex, x, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - @SuppressWarnings("deprecation") - public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { - try { - ((PreparedStatement) delegate).setUnicodeStream(parameterIndex, x, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { - try { - ((PreparedStatement) delegate).setBinaryStream(parameterIndex, x, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void clearParameters() throws SQLException { - try { - ((PreparedStatement) delegate).clearParameters(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { - try { - ((PreparedStatement) delegate).setObject(parameterIndex, x, targetSqlType); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setObject(int parameterIndex, Object x) throws SQLException { - try { - ((PreparedStatement) delegate).setObject(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean execute() throws SQLException { - try { - return ((PreparedStatement) delegate).execute(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void addBatch() throws SQLException { - try { - ((PreparedStatement) delegate).addBatch(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { - try { - ((PreparedStatement) delegate).setCharacterStream(parameterIndex, reader, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setRef(int parameterIndex, Ref x) throws SQLException { - try { - ((PreparedStatement) delegate).setRef(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBlob(int parameterIndex, Blob x) throws SQLException { - try { - ((PreparedStatement) delegate).setBlob(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setClob(int parameterIndex, Clob x) throws SQLException { - try { - ((PreparedStatement) delegate).setClob(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setArray(int parameterIndex, Array x) throws SQLException { - try { - ((PreparedStatement) delegate).setArray(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public ResultSetMetaData getMetaData() throws SQLException { - try { - return ((PreparedStatement) delegate).getMetaData(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { - try { - ((PreparedStatement) delegate).setDate(parameterIndex, x, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { - try { - ((PreparedStatement) delegate).setTime(parameterIndex, x, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { - try { - ((PreparedStatement) delegate).setTimestamp(parameterIndex, x, cal); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { - try { - ((PreparedStatement) delegate).setNull(parameterIndex, sqlType, typeName); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setURL(int parameterIndex, URL x) throws SQLException { - try { - ((PreparedStatement) delegate).setURL(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public ParameterMetaData getParameterMetaData() throws SQLException { - try { - return ((PreparedStatement) delegate).getParameterMetaData(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setRowId(int parameterIndex, RowId x) throws SQLException { - try { - ((PreparedStatement) delegate).setRowId(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNString(int parameterIndex, String value) throws SQLException { - try { - ((PreparedStatement) delegate).setNString(parameterIndex, value); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { - try { - ((PreparedStatement) delegate).setNCharacterStream(parameterIndex, value, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNClob(int parameterIndex, NClob value) throws SQLException { - try { - ((PreparedStatement) delegate).setNClob(parameterIndex, value); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { - try { - ((PreparedStatement) delegate).setClob(parameterIndex, reader, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { - try { - ((PreparedStatement) delegate).setBlob(parameterIndex, inputStream, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { - try { - ((PreparedStatement) delegate).setNClob(parameterIndex, reader, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { - try { - ((PreparedStatement) delegate).setSQLXML(parameterIndex, xmlObject); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { - try { - ((PreparedStatement) delegate).setObject(parameterIndex, x, targetSqlType, scaleOrLength); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { - try { - ((PreparedStatement) delegate).setAsciiStream(parameterIndex, x, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { - try { - ((PreparedStatement) delegate).setBinaryStream(parameterIndex, x, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { - try { - ((PreparedStatement) delegate).setCharacterStream(parameterIndex, reader, length); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { - try { - ((PreparedStatement) delegate).setAsciiStream(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { - try { - ((PreparedStatement) delegate).setBinaryStream(parameterIndex, x); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { - try { - ((PreparedStatement) delegate).setCharacterStream(parameterIndex, reader); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { - try { - ((PreparedStatement) delegate).setNCharacterStream(parameterIndex, value); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setClob(int parameterIndex, Reader reader) throws SQLException { - try { - ((PreparedStatement) delegate).setClob(parameterIndex, reader); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { - try { - ((PreparedStatement) delegate).setBlob(parameterIndex, inputStream); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setNClob(int parameterIndex, Reader reader) throws SQLException { - try { - ((PreparedStatement) delegate).setNClob(parameterIndex, reader); - } catch (Throwable e) { - throw handleException(e); - } - } - - public ResultSet executeQuery(String sql) throws SQLException { - try { - return delegate.executeQuery(sql); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int executeUpdate(String sql) throws SQLException { - try { - return delegate.executeUpdate(sql); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void close() throws SQLException { - try { - delegate.close(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getMaxFieldSize() throws SQLException { - try { - return delegate.getMaxFieldSize(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setMaxFieldSize(int max) throws SQLException { - try { - delegate.setMaxFieldSize(max); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getMaxRows() throws SQLException { - try { - return delegate.getMaxRows(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setMaxRows(int max) throws SQLException { - try { - delegate.setMaxRows(max); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setEscapeProcessing(boolean enable) throws SQLException { - try { - delegate.setEscapeProcessing(enable); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getQueryTimeout() throws SQLException { - try { - return delegate.getQueryTimeout(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setQueryTimeout(int seconds) throws SQLException { - try { - delegate.setQueryTimeout(seconds); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void cancel() throws SQLException { - try { - delegate.cancel(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public SQLWarning getWarnings() throws SQLException { - try { - return delegate.getWarnings(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void clearWarnings() throws SQLException { - try { - delegate.clearWarnings(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setCursorName(String name) throws SQLException { - try { - delegate.setCursorName(name); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean execute(String sql) throws SQLException { - try { - return delegate.execute(sql); - } catch (Throwable e) { - throw handleException(e); - } - } - - public ResultSet getResultSet() throws SQLException { - try { - return delegate.getResultSet(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getUpdateCount() throws SQLException { - try { - return delegate.getUpdateCount(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean getMoreResults() throws SQLException { - try { - return delegate.getMoreResults(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setFetchDirection(int direction) throws SQLException { - try { - delegate.setFetchDirection(direction); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getFetchDirection() throws SQLException { - try { - return delegate.getFetchDirection(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setFetchSize(int rows) throws SQLException { - try { - delegate.setFetchSize(rows); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getFetchSize() throws SQLException { - try { - return delegate.getFetchSize(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getResultSetConcurrency() throws SQLException { - try { - return delegate.getResultSetConcurrency(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getResultSetType() throws SQLException { - try { - return delegate.getResultSetType(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void addBatch(String sql) throws SQLException { - try { - delegate.addBatch(sql); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void clearBatch() throws SQLException { - try { - delegate.clearBatch(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int[] executeBatch() throws SQLException { - try { - return delegate.executeBatch(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public Connection getConnection() throws SQLException { - try { - return delegate.getConnection(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean getMoreResults(int current) throws SQLException { - try { - return delegate.getMoreResults(current); - } catch (Throwable e) { - throw handleException(e); - } - } - - public ResultSet getGeneratedKeys() throws SQLException { - try { - return delegate.getGeneratedKeys(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - try { - return delegate.executeUpdate(sql, autoGeneratedKeys); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - try { - return delegate.executeUpdate(sql, columnIndexes); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int executeUpdate(String sql, String[] columnNames) throws SQLException { - try { - return delegate.executeUpdate(sql, columnNames); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - try { - return delegate.execute(sql, autoGeneratedKeys); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean execute(String sql, int[] columnIndexes) throws SQLException { - try { - return delegate.execute(sql, columnIndexes); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean execute(String sql, String[] columnNames) throws SQLException { - try { - return delegate.execute(sql, columnNames); - } catch (Throwable e) { - throw handleException(e); - } - } - - public int getResultSetHoldability() throws SQLException { - try { - return delegate.getResultSetHoldability(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean isClosed() throws SQLException { - try { - return delegate.isClosed(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void setPoolable(boolean poolable) throws SQLException { - try { - delegate.setPoolable(poolable); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean isPoolable() throws SQLException { - try { - return delegate.isPoolable(); - } catch (Throwable e) { - throw handleException(e); - } - } - - public void closeOnCompletion() throws SQLException { - throw new SQLException("JDK 7 feature unavailable"); - } - - public boolean isCloseOnCompletion() throws SQLException { - throw new SQLException("JDK 7 feature unavailable"); - } - - public T unwrap(Class iface) throws SQLException { - try { - return delegate.unwrap(iface); - } catch (Throwable e) { - throw handleException(e); - } - } - - public boolean isWrapperFor(Class iface) throws SQLException { - try { - return delegate.isWrapperFor(iface); - } catch (Throwable e) { - throw handleException(e); - } - } - - private SQLException handleException(Throwable e) { - return connection.handleException(e); - } -} diff --git a/blade-jdbc/src/main/java/com/blade/jdbc/exception/CallException.java b/blade-jdbc/src/main/java/com/blade/jdbc/exception/CallException.java deleted file mode 100644 index d9c5379b0..000000000 --- a/blade-jdbc/src/main/java/com/blade/jdbc/exception/CallException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.blade.jdbc.exception; - -public class CallException extends RuntimeException { - - private static final long serialVersionUID = 4813572976178058533L; - - public CallException(Throwable t) { - super(t); - } - - public CallException(String msg) { - super(msg); - } - -} \ No newline at end of file diff --git a/blade-jdbc/src/test/java/com/blade/jdbc/test/CRUDTest.java b/blade-jdbc/src/test/java/com/blade/jdbc/test/CRUDTest.java deleted file mode 100644 index b33c2e843..000000000 --- a/blade-jdbc/src/test/java/com/blade/jdbc/test/CRUDTest.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.blade.jdbc.test; - -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.jdbc.DB; -import com.blade.jdbc.DBJob; - -public class CRUDTest { - - private static final Logger LOGGER = LoggerFactory.getLogger(CRUDTest.class); - - @Before - public void before() { - DB.open("com.mysql.jdbc.Driver", "jdbc:mysql://127.0.0.1/test", "root", "root", true); - } - - @Test - public void testQuery() { - User user = new DBJob() { - @Override - public User execute() { - return connection.createQuery("select * from user_t").executeAndFetchFirst(User.class); - } - }.call(); - - LOGGER.info(user.toString()); - - List list = new DBJob>() { - @Override - public List execute() { - return connection.createQuery("select * from user_t").executeAndFetch(User.class); - } - }.call(); - - LOGGER.info(list.toString()); - } - - @Test - public void testUpdate() { - int count = new DBJob() { - @Override - public Integer execute() { - return connection.createQuery("update user_t set password = :password where id = :id") - .addParameter("password", "p@s1wd*").addParameter("id", 4).executeUpdate().getResult(); - - } - }.call(); - - LOGGER.info("update count = {}", count); - } - - @Test - public void testInsert() { - Long id = (Long) new DBJob() { - @Override - public Object execute() { - return connection.createQuery("insert into user_t(user_name, password, age) values (:user_name, :password, :age)") - .addParameter("user_name", "test_insert") - .addParameter("password", "test_insert") - .addParameter("age", 15).executeUpdate().getKey(); - } - }.call(true); - - LOGGER.info("insert userid = {}", id); - } - - @Test - public void testInsertWithModel() { - final User user = new User(); - user.setUser_name("model1"); - user.setPassword("pwd1"); - user.setAge(18); - - Long id = (Long) new DBJob() { - @Override - public Object execute() { - return connection.createQuery("INSERT INTO user_t(user_name, password, age) VALUES (:user_name, :password, :age)") - .bind(user).executeUpdate().getKey(); - } - }.call(true); - - LOGGER.info("insert userid = {}", id); - } - - - @Test - public void testDelete() { - - int count = new DBJob() { - @Override - public Integer execute() { - return connection.createQuery("delete from user_t where id = :id").addParameter("id", 4).executeUpdate() - .getResult(); - } - }.call(); - - LOGGER.info("delete count = {}", count); - } - - @Test - public void testTrans() { - boolean flag = new DBJob() { - @Override - public Boolean execute() { - - connection.createQuery("update user_t set password = :password where id = :id") - .addParameter("p@scwrd", "p@s1wd*").addParameter("id", 4).executeUpdate(); - - connection.createQuery("update user_t set password = :password where id = :id") - .addParameter("password", "p@s1wd*").addParameter("id", 1).executeUpdate(); - - return true; - } - }.call(true); - - LOGGER.info("trans flag = {}", flag); - } - -} diff --git a/blade-jdbc/src/test/java/com/blade/jdbc/test/User.java b/blade-jdbc/src/test/java/com/blade/jdbc/test/User.java deleted file mode 100644 index b8f2c642a..000000000 --- a/blade-jdbc/src/test/java/com/blade/jdbc/test/User.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.blade.jdbc.test; - -public class User { - - private Integer id; - private String user_name; - private String password; - private Integer age; - - public User() { - - } - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getUser_name() { - return user_name; - } - - public void setUser_name(String user_name) { - this.user_name = user_name; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Integer getAge() { - return age; - } - - public void setAge(Integer age) { - this.age = age; - } - - @Override - public String toString() { - return "User [id=" + id + ", user_name=" + user_name + ", password=" + password + ", age=" + age + "]"; - } - -} diff --git a/pom.xml b/pom.xml index e31827477..41e997b1c 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,6 @@ blade-kit blade-core blade-cache - blade-jdbc blade-redis blade-startup blade-oauth2 From abad2ccf27300f6e968cafe9ec728736cda65191 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 16 Feb 2016 12:58:59 +0800 Subject: [PATCH 413/545] move jdbc to https://github.com/bladejava/blade-jdbc --- blade-core/pom.xml | 6 - .../src/main/java/com/blade/jdbc/DB.java | 19 --- .../src/main/java/com/blade/jdbc/Model.java | 134 ------------------ .../java/com/blade/jdbc/annotation/Table.java | 26 ---- 4 files changed, 185 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/jdbc/DB.java delete mode 100644 blade-core/src/main/java/com/blade/jdbc/Model.java delete mode 100644 blade-core/src/main/java/com/blade/jdbc/annotation/Table.java diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 6a5d2581c..b07408d37 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -36,12 +36,6 @@ 3.1.0 provided - - org.sql2o - sql2o - 1.5.4 - provided - org.eclipse.jetty jetty-server diff --git a/blade-core/src/main/java/com/blade/jdbc/DB.java b/blade-core/src/main/java/com/blade/jdbc/DB.java deleted file mode 100644 index acefc7bce..000000000 --- a/blade-core/src/main/java/com/blade/jdbc/DB.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.blade.jdbc; - -import javax.sql.DataSource; - -import org.sql2o.Sql2o; - -public class DB { - - static Sql2o sql2o; - - public static void open(DataSource dataSource) { - sql2o = new Sql2o(dataSource); - } - - public static void open(String url, String user, String pass){ - sql2o = new Sql2o(url, user, pass); - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/jdbc/Model.java b/blade-core/src/main/java/com/blade/jdbc/Model.java deleted file mode 100644 index 30ebda980..000000000 --- a/blade-core/src/main/java/com/blade/jdbc/Model.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.blade.jdbc; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sql2o.Connection; -import org.sql2o.Query; -import org.sql2o.Sql2o; - -import com.blade.jdbc.annotation.Table; - - -public class Model { - - private static final Sql2o sql2o = DB.sql2o; - - private static final Logger LOGGER = LoggerFactory.getLogger(Model.class); - - private static String getTableName(Class type) { - return type.getAnnotation(Table.class).value(); - } - - private static String getPkName(Class type) { - return type.getAnnotation(Table.class).PK(); - } - - public static List findAll(final Class type) { - String tbName = getTableName(type); - String sql = "select * from " + tbName; - - LOGGER.debug("execute sql: {}", sql); - - Connection con = sql2o.open(); - List result = con.createQuery(sql).executeAndFetch(type); - con.close(); - return result; - } - - public static T findById(final Class type, Serializable id) { - String tbName = getTableName(type); - String pkName = getPkName(type); - String sql = "select * from " + tbName + " where " + pkName + " = :" + pkName; - LOGGER.debug("execute sql: {}", sql); - - Connection con = sql2o.open(); - T result = con.createQuery(sql).addParameter(pkName, id).executeAndFetchFirst(type); - con.close(); - return result; - } - - /** - * "where name like ? and age > ? oredr by ?" - * @param type - * @param condition - * @param params - * @return - */ - public static T find(final Class type, String condition, Object ... args) { - String tbName = getTableName(type); - StringBuffer sql = new StringBuffer("select * from "); - sql.append(tbName).append(" "); - - Map params = getConditionSql(sql, condition, args); - - LOGGER.debug("execute sql: {}", sql.toString()); - - Connection con = sql2o.open(); - T result = query(con.createQuery(sql.toString()), params).executeAndFetchFirst(type); - con.close(); - return result; - } - - public static List findList(final Class type, String condition, Object ... args) { - - String tbName = getTableName(type); - StringBuffer sql = new StringBuffer("select * from "); - sql.append(tbName).append(" "); - - Map params = getConditionSql(sql, condition, args); - - LOGGER.debug("execute sql: {}", sql.toString()); - - Connection con = sql2o.open(); - List result = query(con.createQuery(sql.toString()), params).executeAndFetch(type); - con.close(); - return result; - } - - public static List findPage(final Class type, int page, int count, String condition, Object ... args) { - String tbName = getTableName(type); - StringBuffer sql = new StringBuffer("select * from "); - sql.append(tbName).append(" "); - - Map params = getConditionSql(sql, condition, args); - - LOGGER.debug("execute sql: {}", sql.toString()); - - Connection con = sql2o.open(); - List result = query(con.createQuery(sql.toString()), params) - .executeAndFetch(type); - con.close(); - return result; - } - - private static Query query(Query query, Map params){ - Set keys = params.keySet(); - for(String key : keys){ - query.addParameter(key, params.get(key)); - } - return query; - } - - private static Map getConditionSql(StringBuffer sql, String condition, Object ... params){ - Map maps = new HashMap(); - int pos = condition.indexOf("?"); - for(int i=0; pos != -1; i++){ - maps.put("param_" + i, params[i]); - condition = condition.replaceFirst("(\\?)", ":param_" + i); - pos = condition.indexOf("?"); - } - sql.append(condition); - return maps; - } - - public static T insert(T type) { - - return type; - } -} diff --git a/blade-core/src/main/java/com/blade/jdbc/annotation/Table.java b/blade-core/src/main/java/com/blade/jdbc/annotation/Table.java deleted file mode 100644 index 947aadcf6..000000000 --- a/blade-core/src/main/java/com/blade/jdbc/annotation/Table.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.blade.jdbc.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * model表关联注解 - * - * @author biezhi - * @since 1.0 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Table { - - String value(); - - String PK() default "id"; - - boolean isCache() default true; - -} From 25a93e9962ae28dd1a47f51b657264a9802e8427 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 16 Feb 2016 13:03:06 +0800 Subject: [PATCH 414/545] update readme --- README.md | 4 ++-- README_CN.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ec4472961..7f9f35d60 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Grab via `Maven`: com.bladejava blade-core - 1.5.1 + 1.6.0-alpha com.bladejava @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.5.1' +compile 'com.bladejava:blade-core:1.6.0-alpha' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/README_CN.md b/README_CN.md index c55841e26..a194ae9e8 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,7 +38,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.5.1 + 1.6.0-alpha com.bladejava @@ -50,7 +50,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 或者 `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.5.1' +compile 'com.bladejava:blade-core:1.6.0-alpha' compile 'com.bladejava:blade-startup:1.0.1' ``` From 8c572deff3bfc31dd9d00ef77e69beb2caf0e276 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 16 Feb 2016 13:45:24 +0800 Subject: [PATCH 415/545] fix print banner insanity --- blade-core/src/main/java/com/blade/Blade.java | 4 +--- .../java/com/blade/view/handle/RouteViewHandler.java | 3 +++ .../src/main/java/com/blade/web/BladeBanner.java | 11 +++++------ .../main/java/com/blade/web/DispatcherServlet.java | 2 ++ 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 763923cb2..f6e9928d5 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -35,7 +35,6 @@ import com.blade.server.Server; import com.blade.view.template.JspEngine; import com.blade.view.template.TemplateEngine; -import com.blade.web.BladeBanner; import com.blade.web.http.HttpMethod; import blade.kit.Assert; @@ -123,10 +122,9 @@ public static final Blade me(){ * Set Blade initialize * @param isInit initialize */ - public synchronized void init() { + public void init() { if(!this.isInit){ this.isInit = true; - new BladeBanner().print(System.out); } } diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 0488aaffb..3672a5e7b 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -100,6 +100,9 @@ public boolean intercept(Request request, Response response, Route route){ return (Boolean) returnParam; } } + + return true; + } catch (Exception e) { request.abort(); DispatchKit.printError(e, 500, response.raw()); diff --git a/blade-core/src/main/java/com/blade/web/BladeBanner.java b/blade-core/src/main/java/com/blade/web/BladeBanner.java index 634ed1b2c..fc4b62abc 100644 --- a/blade-core/src/main/java/com/blade/web/BladeBanner.java +++ b/blade-core/src/main/java/com/blade/web/BladeBanner.java @@ -13,12 +13,11 @@ public class BladeBanner { " ~ ~~~ ~ ~ ~ ~~~" }; - public void print(final PrintStream printStream){ - synchronized (BladeBanner.class) { - for (String s : banner) { - printStream.println('\t' + s); - } - printStream.println("\t :: Blade :: (v" + Const.BLADE_VERSION + ")\r\n"); + public void print(final PrintStream printStream) { + for (String s : banner) { + printStream.println('\t' + s); } + printStream.println("\t :: Blade :: (v" + Const.BLADE_VERSION + ")"); + printStream.println(); } } diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index f001f0c33..369f4a5e3 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -113,6 +113,8 @@ public void init(Blade blade) { blade.init(); LOGGER.info("DispatcherServlet initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); + + new BladeBanner().print(System.out); } } From d443d9f54b58f1a19ca6f516fc788af6808e444d Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 16 Feb 2016 15:46:23 +0800 Subject: [PATCH 416/545] - --- .../kit/config/adapter/PropConfigAdapter.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java index 1c4951c40..450a6d8e2 100644 --- a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java +++ b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java @@ -32,24 +32,24 @@ public Config read(String prop_file) { in = Thread.currentThread().getContextClassLoader().getResourceAsStream(prop_file); if (in != null) { props.load(in); - } - // 解析properties文件 - Set> set = props.entrySet(); - if(CollectionKit.isNotEmpty(set)){ - Iterator> it = set.iterator(); - while (it.hasNext()) { - Entry entry = it.next(); - String key = entry.getKey().toString(); - String value = entry.getValue().toString(); - String fuKey = getWildcard(value); - if(null != fuKey && null != props.get(fuKey)){ - String fuValue = props.get(fuKey).toString(); - value = value.replaceAll("\\$\\{" + fuKey + "\\}", fuValue); + // 解析properties文件 + Set> set = props.entrySet(); + if(CollectionKit.isNotEmpty(set)){ + Iterator> it = set.iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + String key = entry.getKey().toString(); + String value = entry.getValue().toString(); + String fuKey = getWildcard(value); + if(null != fuKey && null != props.get(fuKey)){ + String fuValue = props.get(fuKey).toString(); + value = value.replaceAll("\\$\\{" + fuKey + "\\}", fuValue); + } + configMap.put(key, value); } - configMap.put(key, value); + LOGGER.info("Loading config file [classpath:/" + prop_file + "]"); + return this; } - LOGGER.info("Loading config file [classpath:/" + prop_file + "]"); - return this; } return null; } catch (IOException e) { From ebdb2e1fb7881baf8ca3b80f6f8f4b27b9c5056b Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 16 Feb 2016 15:57:36 +0800 Subject: [PATCH 417/545] remove default.properties --- blade-core/pom.xml | 6 +- blade-core/src/main/java/com/blade/Blade.java | 74 ++++------------ .../blade/context/BladeContextListener.java | 31 ------- .../java/com/blade/ioc/IocApplication.java | 84 ++++++++++++++----- .../main/java/com/blade/ioc/SampleIoc.java | 3 +- .../com/blade/ioc/injector/FieldInjector.java | 13 ++- .../java/com/blade/loader/BladeConfig.java | 19 ++--- .../java/com/blade/route/RouteBuilder.java | 2 +- .../main/java/com/blade/route/Routers.java | 25 +++--- .../main/java/com/blade/web/BladeBanner.java | 12 +-- .../java/com/blade/web/DispatcherServlet.java | 26 ++++-- blade-core/src/main/java/default.properties | 5 -- 12 files changed, 140 insertions(+), 160 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/context/BladeContextListener.java delete mode 100644 blade-core/src/main/java/default.properties diff --git a/blade-core/pom.xml b/blade-core/pom.xml index b07408d37..fe4365631 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -14,7 +14,7 @@ ${blade.version} blade-core https://github.com/biezhi/blade/blade-core - + 9.2.12.v20150709 2.0.12 @@ -25,6 +25,10 @@ + + org.slf4j + slf4j-api + com.bladejava blade-kit diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index f6e9928d5..7ea684ad9 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -17,11 +17,11 @@ import java.io.InputStream; import java.text.ParseException; +import java.util.HashSet; import java.util.List; import java.util.Set; import com.blade.ioc.Ioc; -import com.blade.ioc.IocApplication; import com.blade.ioc.SampleIoc; import com.blade.loader.BladeConfig; import com.blade.loader.Configurator; @@ -74,11 +74,6 @@ public class Blade { */ private Ioc ioc = null; - /** - * ioc application object - */ - private IocApplication iocApplication = null; - /** * default render is jspRender */ @@ -99,15 +94,17 @@ public class Blade { */ private Server bladeServer; + private Set> plugins; + private Blade() { this.bladeConfig = new BladeConfig(); this.ioc = new SampleIoc(); - this.iocApplication = new IocApplication(ioc); this.routers = new Routers(ioc); this.templateEngine = new JspEngine(); + this.plugins = new HashSet>(); } - public static final class BladeHolder { + static final class BladeHolder { private static final Blade ME = new Blade(); } @@ -222,33 +219,6 @@ public Blade ioc(String...packages){ return this; } - /** - * Add a route - * - * @param path route path - * @param target Target object for routing - * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @return return blade - */ - public Blade route(String path, Object target, String method){ - routers.route(path, target, method); - return this; - } - - /** - * Add a route - * - * @param path route path - * @param target Target object for routing - * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @param httpMethod HTTPMethod - * @return return blade - */ - public Blade route(String path, Object target, String method, HttpMethod httpMethod){ - routers.route(path, target, method, httpMethod); - return this; - } - /** * Add a route * @@ -640,7 +610,7 @@ public Set staticFolder(){ * @return Return bootstrap object */ public Bootstrap bootstrap(){ - return ioc.getBean(Bootstrap.class); + return this.bootstrap; } /** @@ -661,17 +631,12 @@ public boolean enableXSS(){ * return register plugin object * * @param plugin plugin class - * @param generic - * @return return plugin object + * @return return blade */ - @SuppressWarnings("unchecked") - public T plugin(Class plugin){ + public Blade plugin(Class plugin){ Assert.notNull(plugin); - Object object = iocApplication.getPlugin(plugin); - if(null == object){ - object = iocApplication.registerPlugin(plugin); - } - return (T) object; + plugins.add(plugin); + return this; } /** @@ -708,21 +673,6 @@ public Blade routeConf(String basePackage, String conf) { return this; } - /** - * @return Return IocApplication object - */ - public IocApplication iocApplication(){ - return iocApplication; - } - - /** - * @return Initialize ioc application and return blade - */ - public Blade iocInit(){ - iocApplication.init(iocs(), bootstrap); - return this; - } - /** * @return Return blade is initialize */ @@ -734,4 +684,8 @@ public boolean httpCache() { return bladeConfig.isHttpCache(); } + public Set> plugins() { + return this.plugins; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/context/BladeContextListener.java b/blade-core/src/main/java/com/blade/context/BladeContextListener.java deleted file mode 100644 index 83761b3d7..000000000 --- a/blade-core/src/main/java/com/blade/context/BladeContextListener.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.blade.context; - -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.annotation.WebListener; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; - -import blade.kit.TaskKit; - -@WebListener -public class BladeContextListener implements ServletContextListener { - - private static final Logger LOGGER = LoggerFactory.getLogger(BladeContextListener.class); - - @Override - public void contextInitialized(final ServletContextEvent sce) { - LOGGER.info("blade context Initialized!"); - } - - @Override - public void contextDestroyed(final ServletContextEvent sce) { - LOGGER.info("blade destroy!"); - BladeWebContext.remove(); - Blade.me().iocApplication().destroy(); - TaskKit.depose(); - } -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index d4a6229f5..1b09c9021 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -15,16 +15,23 @@ */ package com.blade.ioc; -import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.blade.Blade; import com.blade.Bootstrap; +import com.blade.ioc.annotation.Component; import com.blade.plugin.Plugin; +import com.blade.route.Route; +import com.blade.route.RouteHandler; +import com.blade.route.Routers; +import blade.kit.CollectionKit; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; @@ -48,15 +55,26 @@ public class IocApplication { */ private ClassReader classReader = null; + private String[] iocs; + private Bootstrap bootstrap; + /** * Plugin List */ private List plugins = null; - public IocApplication(Ioc ioc) { + private Set> pluginTypes; + + private Blade blade; + + public IocApplication(Blade blade) { + this.blade = blade; this.classReader = new ClassPathClassReader(); - this.plugins = new ArrayList(); - this.ioc = ioc; + this.plugins = CollectionKit.newArrayList(); + this.pluginTypes = blade.plugins(); + this.ioc = blade.ioc(); + this.iocs = blade.iocs(); + this.bootstrap = blade.bootstrap(); } /** @@ -64,7 +82,7 @@ public IocApplication(Ioc ioc) { * @param iocs ioc packages * @param bootstrap bootstrap object */ - public void init(String[] iocs, Bootstrap bootstrap){ + public void init(){ // Initialize the global configuration class if(null == ioc.getBean(Bootstrap.class)){ @@ -78,22 +96,41 @@ public void init(String[] iocs, Bootstrap bootstrap){ } } - LOGGER.info("Add Object: {}", ioc.getBeans()); + for(Class type : pluginTypes){ + ioc.addBean(type); + Plugin plugin = ioc.getBean(type); + plugins.add(plugin); + } - } - - public T registerPlugin(Class plugin){ - ioc.addBean(plugin); - T t = ioc.getBean(plugin); - plugins.add(t); - return t; - } - - public T getPlugin(Class plugin){ - if(null != plugin && null != ioc){ - return ioc.getBean(plugin); + // init controllers + Routers routers = blade.routers(); + Map routes = routers.getRoutes(); + if(CollectionKit.isNotEmpty(routes)){ + Collection routesList = routes.values(); + if(CollectionKit.isNotEmpty(routesList)){ + for(Route route : routesList){ + Class type = route.getTargetType(); + if(null != type && type != RouteHandler.class && null == ioc.getBean(type)){ + ioc.addBean(type); + } + } + } } - return null; + + Map interceptors = routers.getInterceptors(); + if(CollectionKit.isNotEmpty(interceptors)){ + Collection routesList = interceptors.values(); + if(CollectionKit.isNotEmpty(routesList)){ + for(Route route : routesList){ + Class type = route.getTargetType(); + if(null != type && type != RouteHandler.class && null == ioc.getBean(type)){ + ioc.addBean(type); + } + } + } + } + + LOGGER.info("Add Object: {}", ioc.getBeans()); } /** @@ -113,15 +150,18 @@ private void registerBean(String packageName) { // Scan package all class Set> classes = classReader.getClass(packageName, recursive); for (Class clazz : classes) { - // Register classes - ioc.addBean(clazz); + Component component = clazz.getAnnotation(Component.class); + if(null != component){ + // Register classes + ioc.addBean(clazz); + } } } public List getPlugins() { return plugins; } - + /** * destroy */ diff --git a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java index 987d79454..9f9fef90c 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java @@ -159,7 +159,8 @@ private BeanDefine getBeanDefine(Class beanClass, boolean singleton) { @Override public T getBean(Class type) { - return type.cast(getBean(type.getName())); + Object bean = this.getBean(type.getName()); + return type.cast(bean); } @Override diff --git a/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java b/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java index cb7153765..665267b47 100644 --- a/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java +++ b/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java @@ -33,10 +33,17 @@ public FieldInjector(Ioc ioc, Field field) { @Override public void injection(Object bean) { try { - String name = field.getType().getName(); - Object value = ioc.getBean(name); + Class fieldType = field.getType(); + Object value = ioc.getBean(fieldType); if (value == null) { - throw new IllegalStateException("Can't inject bean: " + name + " for field: " + field); + throw new IllegalStateException("Can't inject bean: " + fieldType.getName() + " for field: " + field); + + /*Component component = fieldType.getAnnotation(Component.class); + if(null == component){ + throw new IllegalStateException("Can't inject bean: " + fieldType.getName() + " for field: " + field); + } + ioc.addBean(fieldType); + value = ioc.getBean(fieldType);*/ } field.setAccessible(true); field.set(bean, value); diff --git a/blade-core/src/main/java/com/blade/loader/BladeConfig.java b/blade-core/src/main/java/com/blade/loader/BladeConfig.java index 060428997..5b835d81d 100644 --- a/blade-core/src/main/java/com/blade/loader/BladeConfig.java +++ b/blade-core/src/main/java/com/blade/loader/BladeConfig.java @@ -16,10 +16,10 @@ package com.blade.loader; import java.util.Arrays; +import java.util.HashSet; import java.util.Map; import java.util.Set; -import blade.kit.CollectionKit; import blade.kit.PatternKit; import blade.kit.config.Config; import blade.kit.config.loader.ConfigLoader; @@ -37,13 +37,13 @@ public class BladeConfig { private Map configMap; // Storage of all routing packets - private Set routePackages = CollectionKit.newHashSet(); + private Set routePackages = new HashSet(); // Store all IOC packages - private Set iocPackages = CollectionKit.newHashSet(); + private Set iocPackages = new HashSet(); // Store all filter directories - private Set staticFolders = CollectionKit.newHashSet(); + private Set staticFolders = new HashSet(); // Base package private String basePackage; @@ -64,7 +64,7 @@ public class BladeConfig { private String view500; // Is dev mode - private boolean isDev = false; + private boolean isDev = true; // Enabled XSS private boolean httpXss = false; @@ -74,16 +74,15 @@ public class BladeConfig { private boolean configInit = false; public BladeConfig() { + staticFolders.add("/public"); + staticFolders.add("/assets"); + staticFolders.add("/static"); } public void init(){ if(!configInit){ try { - Config config = ConfigLoader.load("default.properties"); - if(null != config){ - Configurator.init(this, config); - } - config = ConfigLoader.load("blade.properties"); + Config config = ConfigLoader.load("blade.properties"); if(null != config){ Configurator.init(this, config); } diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index b24f5558e..2f908297f 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -188,7 +188,7 @@ private void parseRouter(final Class router){ return; } - ioc.addBean(router); +// ioc.addBean(router); final String nameSpace = router.getAnnotation(Path.class).value(); diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 180c41ea8..413676220 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -94,7 +94,7 @@ public void addRoutes(List routes) { public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, String methodName) throws NoSuchMethodException { Class handleType = handler.getClass(); Method method = handleType.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, handler, handleType, method); + addRoute(httpMethod, path, handler, RouteHandler.class, method); } public void addRoute(HttpMethod httpMethod, String path, Object controller, Class controllerType, Method method) { @@ -165,10 +165,10 @@ public void route(String path, Class clazz, String methodName) { methodName = methodArr[1]; } Object controller = ioc.getBean(clazz); - if(null == controller){ - ioc.addBean(clazz); - controller = ioc.getBean(clazz); - } +// if(null == controller){ +// ioc.addBean(clazz); +// controller = ioc.getBean(clazz); +// } try { Method method = clazz.getMethod(methodName, Request.class, Response.class); @@ -194,13 +194,8 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt Assert.notNull(methodName, "Method name not is null"); Assert.notNull(httpMethod, "Request Method not is null"); - Object controller = ioc.getBean(clazz); - if(null == controller){ - ioc.addBean(clazz); - controller = ioc.getBean(clazz); - } Method method = clazz.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, controller, clazz, method); + addRoute(httpMethod, path, null, clazz, method); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { @@ -211,10 +206,10 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { try { Object controller = ioc.getBean(clazz); - if(null == controller){ - ioc.addBean(clazz); - controller = ioc.getBean(clazz); - } +// if(null == controller){ +// ioc.addBean(clazz); +// controller = ioc.getBean(clazz); +// } addRoute(httpMethod, path, controller, clazz, method); } catch (SecurityException e) { e.printStackTrace(); diff --git a/blade-core/src/main/java/com/blade/web/BladeBanner.java b/blade-core/src/main/java/com/blade/web/BladeBanner.java index fc4b62abc..868a83733 100644 --- a/blade-core/src/main/java/com/blade/web/BladeBanner.java +++ b/blade-core/src/main/java/com/blade/web/BladeBanner.java @@ -1,11 +1,14 @@ package com.blade.web; -import java.io.PrintStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.blade.Const; public class BladeBanner { + private static final Logger LOGGER = LoggerFactory.getLogger(BladeBanner.class); + private static final String[] banner = { " __, _, _, __, __,", " |_) | /_\\ | \\ |_", @@ -13,11 +16,10 @@ public class BladeBanner { " ~ ~~~ ~ ~ ~ ~~~" }; - public void print(final PrintStream printStream) { + public void print() { for (String s : banner) { - printStream.println('\t' + s); + LOGGER.info('\t' + s); } - printStream.println("\t :: Blade :: (v" + Const.BLADE_VERSION + ")"); - printStream.println(); + LOGGER.info("\t :: Blade :: (v" + Const.BLADE_VERSION + ")\r\n"); } } diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 369f4a5e3..34f44d5ce 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -29,6 +29,7 @@ import com.blade.Blade; import com.blade.Bootstrap; +import com.blade.ioc.IocApplication; import com.blade.route.RouteBuilder; import blade.kit.StringKit; @@ -50,6 +51,8 @@ public class DispatcherServlet extends HttpServlet { private Bootstrap bootstrap; + private IocApplication iocApplication; + private ServletContext servletContext; private DispatcherHandler dispatcherHandler; @@ -79,7 +82,6 @@ public void init(ServletConfig config) throws ServletException { blade.webRoot(DispatchKit.getWebroot(servletContext).getPath()); LOGGER.info("blade.webroot = {}", blade.webRoot()); - LOGGER.info("blade.isDev = {}", blade.isDev()); blade.config().init(); @@ -100,21 +102,25 @@ public void init(Blade blade) { this.bootstrap.init(blade); + LOGGER.info("blade.isDev = {}", blade.isDev()); + // buiding route new RouteBuilder(blade).building(); // initialization ioc - blade.iocInit(); + iocApplication = new IocApplication(blade); + + iocApplication.init(); this.bootstrap.contextInitialized(blade); + + blade.init(); - dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); + dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); - blade.init(); + new BladeBanner().print(); LOGGER.info("DispatcherServlet initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); - - new BladeBanner().print(System.out); } } @@ -128,6 +134,14 @@ protected void service(HttpServletRequest httpRequest, HttpServletResponse httpR dispatcherHandler.handle(httpRequest, httpResponse); } + @Override + public void destroy() { + super.destroy(); + if(null != iocApplication){ + iocApplication.destroy(); + } + } + /** * Get global initialization object, the application of the initialization * diff --git a/blade-core/src/main/java/default.properties b/blade-core/src/main/java/default.properties deleted file mode 100644 index 7d2f3d265..000000000 --- a/blade-core/src/main/java/default.properties +++ /dev/null @@ -1,5 +0,0 @@ -blade.dev = true -blade.http.encoding = utf-8 -blade.http.cache = false -blade.http.xss = false -blade.http.filters = /public,/assets,/static \ No newline at end of file From e5011b6c719f35fd39b401b59852d62a45b02058 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 16 Feb 2016 15:59:17 +0800 Subject: [PATCH 418/545] fix route controller class is null --- blade-core/src/main/java/com/blade/ioc/IocApplication.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 1b09c9021..8a229d240 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -110,7 +110,7 @@ public void init(){ if(CollectionKit.isNotEmpty(routesList)){ for(Route route : routesList){ Class type = route.getTargetType(); - if(null != type && type != RouteHandler.class && null == ioc.getBean(type)){ + if(null != type && null == route.getTarget() && type != RouteHandler.class && null == ioc.getBean(type)){ ioc.addBean(type); } } @@ -123,7 +123,7 @@ public void init(){ if(CollectionKit.isNotEmpty(routesList)){ for(Route route : routesList){ Class type = route.getTargetType(); - if(null != type && type != RouteHandler.class && null == ioc.getBean(type)){ + if(null != type && null == route.getTarget() && type != RouteHandler.class && null == ioc.getBean(type)){ ioc.addBean(type); } } From 0beb4f8403f0cf063b4a046aa68249493c9b06c8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 16 Feb 2016 16:16:36 +0800 Subject: [PATCH 419/545] remove Routers ioc object. --- blade-core/src/main/java/com/blade/Blade.java | 2 +- .../main/java/com/blade/route/Routers.java | 40 ++----------------- 2 files changed, 5 insertions(+), 37 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 7ea684ad9..0e45af1ab 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -99,7 +99,7 @@ public class Blade { private Blade() { this.bladeConfig = new BladeConfig(); this.ioc = new SampleIoc(); - this.routers = new Routers(ioc); + this.routers = new Routers(); this.templateEngine = new JspEngine(); this.plugins = new HashSet>(); } diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 413676220..16901aced 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -23,7 +23,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.blade.ioc.Ioc; import com.blade.web.http.HttpMethod; import com.blade.web.http.Request; import com.blade.web.http.Response; @@ -40,16 +39,13 @@ public class Routers { private Logger LOGGER = LoggerFactory.getLogger(Routers.class); - private Ioc ioc = null; - private Map routes = null; private Map interceptors = null; private static final String METHOD_NAME = "handle"; - public Routers(Ioc ioc) { - this.ioc = ioc; + public Routers() { this.routes = new HashMap(); this.interceptors = new HashMap(); } @@ -164,19 +160,13 @@ public void route(String path, Class clazz, String methodName) { httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); methodName = methodArr[1]; } - Object controller = ioc.getBean(clazz); -// if(null == controller){ -// ioc.addBean(clazz); -// controller = ioc.getBean(clazz); -// } try { Method method = clazz.getMethod(methodName, Request.class, Response.class); - - addRoute(httpMethod, path, controller, clazz, method); + addRoute(httpMethod, path, null, clazz, method); } catch (NoSuchMethodException e) { try { Method method = clazz.getMethod(methodName, Response.class, Request.class); - addRoute(httpMethod, path, controller, clazz, method); + addRoute(httpMethod, path, null, clazz, method); } catch (NoSuchMethodException e1) { e1.printStackTrace(); } catch (SecurityException e1) { @@ -193,7 +183,6 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt Assert.notNull(clazz, "Class Type not is null!"); Assert.notNull(methodName, "Method name not is null"); Assert.notNull(httpMethod, "Request Method not is null"); - Method method = clazz.getMethod(methodName, Request.class, Response.class); addRoute(httpMethod, path, null, clazz, method); } catch (NoSuchMethodException e) { @@ -204,28 +193,7 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt } public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { - try { - Object controller = ioc.getBean(clazz); -// if(null == controller){ -// ioc.addBean(clazz); -// controller = ioc.getBean(clazz); -// } - addRoute(httpMethod, path, controller, clazz, method); - } catch (SecurityException e) { - e.printStackTrace(); - } + addRoute(httpMethod, path, null, clazz, method); } - public void route(String path, Object target, String methodName, HttpMethod httpMethod) { - try { - Class clazz = target.getClass(); - ioc.addBean(target); - Method method = clazz.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, target, target.getClass(), method); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - } } From e7a87329ed9e50c4872ec355f58027a6ce3bb634 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 17 Feb 2016 18:05:05 +0800 Subject: [PATCH 420/545] add log spi --- blade-kit/pom.xml | 7 + .../blade/kit/logging/FeatureDetector.java | 65 +++++ .../main/java/blade/kit/logging/Level.java | 22 ++ .../java/blade/kit/logging/Log4jLogger.java | 55 +++++ .../main/java/blade/kit/logging/Logger.java | 25 ++ .../java/blade/kit/logging/LoggerFactory.java | 18 ++ .../java/blade/kit/logging/SimpleLogger.java | 222 ++++++++++++++++++ .../java/blade/kit/logging/Slf4jLogger.java | 58 +++++ 8 files changed, 472 insertions(+) create mode 100644 blade-kit/src/main/java/blade/kit/logging/FeatureDetector.java create mode 100644 blade-kit/src/main/java/blade/kit/logging/Level.java create mode 100644 blade-kit/src/main/java/blade/kit/logging/Log4jLogger.java create mode 100644 blade-kit/src/main/java/blade/kit/logging/Logger.java create mode 100644 blade-kit/src/main/java/blade/kit/logging/LoggerFactory.java create mode 100644 blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java create mode 100644 blade-kit/src/main/java/blade/kit/logging/Slf4jLogger.java diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index ed8a85f13..41e6a0a15 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -27,6 +27,13 @@ org.slf4j slf4j-api + provided + + + log4j + log4j + 1.2.17 + provided javax.mail diff --git a/blade-kit/src/main/java/blade/kit/logging/FeatureDetector.java b/blade-kit/src/main/java/blade/kit/logging/FeatureDetector.java new file mode 100644 index 000000000..e233cc1fe --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/logging/FeatureDetector.java @@ -0,0 +1,65 @@ +package blade.kit.logging; + +public final class FeatureDetector { + + private FeatureDetector() { + } + + static { + setCacheUnderscoreToCamelcaseEnabled(true); // enabled by default + } + + private static Boolean jodaTimeAvailable; + private static Boolean slf4jAvailable; + private static Boolean log4jAvailable; + private static Boolean oracleAvailable; + private static boolean cacheUnderscoreToCamelcaseEnabled; + + public static boolean isPresent(String className) { + try { + // what's wrong with old plain Class.forName + // this code supposed to work everywhere including containers + Class.forName(className); + // getClassLoader().loadClass(className); + return true; + } catch (Throwable ex) { + return false; + } + } + + public static boolean isJodaTimeAvailable() { + if (jodaTimeAvailable == null) { + jodaTimeAvailable = isPresent("org.joda.time.DateTime"); + } + return jodaTimeAvailable; + } + + public static boolean isSlf4jAvailable() { + if (slf4jAvailable == null) { + slf4jAvailable = isPresent("org.slf4j.Logger"); + } + return slf4jAvailable; + } + + public static boolean isLog4jAvailable() { + if (log4jAvailable == null) { + log4jAvailable = isPresent("org.apache.log4j.Logger"); + } + return log4jAvailable; + } + + public static boolean isOracleAvailable() { + if (oracleAvailable == null) { + oracleAvailable = isPresent("oracle.sql.TIMESTAMP"); + } + return oracleAvailable; + } + + public static boolean isCacheUnderscoreToCamelcaseEnabled() { + return cacheUnderscoreToCamelcaseEnabled; + } + + public static void setCacheUnderscoreToCamelcaseEnabled(boolean cacheUnderscoreToCamelcaseEnabled) { + FeatureDetector.cacheUnderscoreToCamelcaseEnabled = cacheUnderscoreToCamelcaseEnabled; + } +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/Level.java b/blade-kit/src/main/java/blade/kit/logging/Level.java new file mode 100644 index 000000000..5e3dcbe63 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/logging/Level.java @@ -0,0 +1,22 @@ +package blade.kit.logging; + +/** + * 日志级别 + * @author biezhi + * + */ +public final class Level { + + public static final int TRACE = 100; + + public static final int DEBUG = 200; + + public static final int INFO = 300; + + public static final int WARN = 400; + + public static final int ERROR = 500; + + public static final int FATAL = 600; + +} diff --git a/blade-kit/src/main/java/blade/kit/logging/Log4jLogger.java b/blade-kit/src/main/java/blade/kit/logging/Log4jLogger.java new file mode 100644 index 000000000..166dc584c --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/logging/Log4jLogger.java @@ -0,0 +1,55 @@ +package blade.kit.logging; + +public class Log4jLogger implements Logger { + + private final org.apache.log4j.Logger logger; + + public Log4jLogger(org.apache.log4j.Logger logger) { + this.logger = logger; + } + + @Override + public void debug(String msg) { + logger.debug(msg); + } + + @Override + public void debug(String msg, Object... args) { + } + + public void warn(String msg) { + logger.warn(msg); + } + + public void warn(String msg, Throwable t) { + logger.warn(msg, t); + } + + @Override + public void info(String msg) { + logger.info(msg); + } + + @Override + public void info(String msg, Object... args) { + } + + @Override + public void error(String msg) { + logger.error(msg); + } + + @Override + public void error(String msg, Object... args) { + } + + @Override + public void error(String msg, Throwable t) { + logger.error(msg, t); + } + + @Override + public void warn(String msg, Object... args) { + } + +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/Logger.java b/blade-kit/src/main/java/blade/kit/logging/Logger.java new file mode 100644 index 000000000..80f65dd0b --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/logging/Logger.java @@ -0,0 +1,25 @@ +package blade.kit.logging; + +public interface Logger { + + public void debug(String msg); + + public void debug(String msg, Object... args); + + public void info(String msg); + + public void info(String msg, Object... args); + + public void warn(String msg); + + public void warn(String msg, Object ...args); + + public void warn(String msg, Throwable exception); + + public void error(String msg); + + public void error(String msg, Object...args); + + public void error(String msg, Throwable t); + +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/LoggerFactory.java b/blade-kit/src/main/java/blade/kit/logging/LoggerFactory.java new file mode 100644 index 000000000..d6aaf1a13 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/logging/LoggerFactory.java @@ -0,0 +1,18 @@ +package blade.kit.logging; + +public class LoggerFactory { + + private static final boolean slf4jAvailable = FeatureDetector.isSlf4jAvailable(); + private static final boolean log4jAvailable = FeatureDetector.isLog4jAvailable(); + + public static Logger getLogger(Class clazz) { + if(slf4jAvailable){ + return new Slf4jLogger(org.slf4j.LoggerFactory.getLogger(clazz)); + } + if(log4jAvailable){ + return new Log4jLogger(org.apache.log4j.Logger.getLogger(clazz)); + } + return new SimpleLogger(clazz); + } + +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java b/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java new file mode 100644 index 000000000..a79b35f73 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java @@ -0,0 +1,222 @@ +package blade.kit.logging; + +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class SimpleLogger implements Logger { + + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"); + + private static PrintStream outprint = System.out; + + private int level = Level.DEBUG; + + protected String name; + + public SimpleLogger() { + String currentClassName = Thread.currentThread().getStackTrace()[2].getClassName(); + this.name = currentClassName; + } + + public SimpleLogger(Class type) { + this.name = type.getName(); + } + + private String getLevel(int level){ + if(level <= Level.TRACE){ + return "TRACE"; + } + if(level <= Level.DEBUG){ + return "DEBUG"; + } + if(level <= Level.INFO){ + return "INFO"; + } + if(level <= Level.WARN){ + return "WARN"; + } + if(level <= Level.ERROR){ + outprint = System.err; + return "ERROR"; + } + if(level <= Level.FATAL){ + return "FATAL"; + } + return "DEBUG"; + } + + private String now() { + return sdf.format(new Date()); + } + + public void trace(String message) { + if (level <= Level.TRACE) + log(Level.TRACE, message); + } + + public void trace(String message, Object... args) { + if (level <= Level.TRACE) + log(Level.TRACE, message, args); + } + + public void trace(String message, Throwable t) { + if (level <= Level.TRACE) + log(Level.TRACE, message, t); + } + + + public void trace(String message, Throwable t, Object... args) { + if (level <= Level.TRACE) + log(Level.TRACE, message, t, args); + } + + + public void debug(String message) { + if (level <= Level.DEBUG) + log(Level.DEBUG, message); + } + + + public void debug(String message, Object... args) { + if (level <= Level.DEBUG) + log(Level.DEBUG, message, args); + } + + + public void debug(String message, Throwable t) { + if (level <= Level.DEBUG) + log(Level.DEBUG, message, t); + } + + + public void debug(String message, Throwable t, Object... args) { + if (level <= Level.DEBUG) + log(Level.DEBUG, message, t, args); + } + + + public void info(String message) { + if (level <= Level.INFO) + log(Level.INFO, message); + } + + + public void info(String message, Object... args) { + if (level <= Level.INFO) + log(Level.INFO, message, args); + } + + + public void info(String message, Throwable t) { + if (level <= Level.INFO) + log(Level.INFO, message, t); + } + + + public void info(String message, Throwable t, Object... args) { + if (level <= Level.INFO) + log(Level.INFO, message, t, args); + } + + + public void warn(String message) { + if (level <= Level.WARN) + log(Level.WARN, message); + } + + + public void warn(String message, Object... args) { + if (level <= Level.WARN) + log(Level.WARN, message, args); + } + + + public void warn(String message, Throwable t) { + if (level <= Level.WARN) + log(Level.WARN, message, t); + } + + + public void warn(String message, Throwable t, Object... args) { + if (level <= Level.WARN) + log(Level.WARN, message, t, args); + } + + + public void error(String message) { + if (level <= Level.ERROR) + log(Level.ERROR, message); + } + + + public void error(String message, Object... args) { + if (level <= Level.ERROR) + log(Level.ERROR, message, args); + } + + + public void error(String message, Throwable t) { + if (level <= Level.ERROR) + log(Level.ERROR, message, t); + } + + + public void error(String message, Throwable t, Object... args) { + if (level <= Level.ERROR) + log(Level.ERROR, message, t, args); + } + + public boolean isDebugEnabled() { + return level <= Level.DEBUG; + } + + public boolean isErrorEnabled() { + return level <= Level.ERROR; + } + + public boolean isInfoEnabled() { + return level <= Level.INFO; + } + + public boolean isWarnEnabled() { + return level <= Level.WARN; + } + + public void log(int level, String message, Object... args) { + log(level, message, null, args); + } + + public void log(int level, String message, Throwable t, Object... args) { + + StringBuilder sb = new StringBuilder(now()); + sb.append(" ").append(getLevel(level)).append(" "); + sb.append("[").append(Thread.currentThread().getName()).append("]").append(" "); + sb.append(this.name).append(" | "); + sb.append(format(message, args)); + + outprint.println(sb.toString()); + if (t != null) { + t.printStackTrace(System.err); + System.err.flush(); + } + } + + protected String format(String message, Object... args) { + if (message == null) { + return null; + } + if (args == null || args.length == 0){ + return message.toString(); + } else { + String msg = String.format(message, args); + if(msg.indexOf("{}") != -1){ + for(Object arg : args){ + msg = msg.replaceFirst("\\{\\}", arg.toString()); + } + } + return msg; + } + } + +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/Slf4jLogger.java b/blade-kit/src/main/java/blade/kit/logging/Slf4jLogger.java new file mode 100644 index 000000000..996c1d321 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/logging/Slf4jLogger.java @@ -0,0 +1,58 @@ +package blade.kit.logging; + +public class Slf4jLogger implements Logger { + + private final org.slf4j.Logger logger; + + public Slf4jLogger(org.slf4j.Logger logger) { + this.logger = logger; + } + + @Override + public void debug(String msg, Object... args) { + logger.debug(msg, args); + } + + @Override + public void debug(String msg) { + logger.debug(msg); + } + + public void warn(String msg) { + logger.warn(msg); + } + + public void warn(String msg, Throwable t) { + logger.warn(msg, t); + } + + @Override + public void info(String msg) { + logger.info(msg); + } + + @Override + public void info(String msg, Object... args) { + logger.info(msg, args); + } + + @Override + public void error(String msg) { + logger.error(msg); + } + + @Override + public void error(String msg, Object... args) { + logger.error(msg, args); + } + + @Override + public void error(String msg, Throwable t) { + logger.error(msg, t); + } + + @Override + public void warn(String msg, Object... args) { + logger.warn(msg, args); + } +} From 9bac90d4762174701549f24215e04c6bc94cd009 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 17 Feb 2016 18:05:17 +0800 Subject: [PATCH 421/545] add log spi --- blade-core/pom.xml | 7 ------- .../src/main/java/com/blade/ioc/IocApplication.java | 5 ++--- blade-core/src/main/java/com/blade/ioc/SampleIoc.java | 5 ++--- blade-core/src/main/java/com/blade/route/Routers.java | 5 ++--- blade-core/src/main/java/com/blade/server/Server.java | 5 +++-- .../src/main/java/com/blade/view/template/JspEngine.java | 6 +++--- blade-core/src/main/java/com/blade/web/BladeBanner.java | 6 +++--- .../src/main/java/com/blade/web/DispatcherHandler.java | 9 +++------ .../src/main/java/com/blade/web/DispatcherServlet.java | 5 ++--- .../main/java/com/blade/web/verify/CSRFTokenManager.java | 5 ++--- 10 files changed, 22 insertions(+), 36 deletions(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index fe4365631..884d894f9 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -17,18 +17,11 @@ 9.2.12.v20150709 - 2.0.12 - 2.2.3 - 1.7 4.3.5 1.7.7 - - org.slf4j - slf4j-api - com.bladejava blade-kit diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 8a229d240..e827d9559 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -20,9 +20,6 @@ import java.util.Map; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.Blade; import com.blade.Bootstrap; import com.blade.ioc.annotation.Component; @@ -32,6 +29,8 @@ import com.blade.route.Routers; import blade.kit.CollectionKit; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; diff --git a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java index 9f9fef90c..fa7848670 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java @@ -22,12 +22,11 @@ import java.util.Map; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.ioc.loader.IocLoader; import blade.kit.Assert; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * The default IOC container implementation diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 16901aced..6143d29c9 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -20,14 +20,13 @@ import java.util.List; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.web.http.HttpMethod; import com.blade.web.http.Request; import com.blade.web.http.Response; import blade.kit.Assert; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * Registration, management route diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java index 34166ef76..2a7e86503 100644 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ b/blade-core/src/main/java/com/blade/server/Server.java @@ -17,11 +17,12 @@ import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.blade.web.DispatcherServlet; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; + /** * Jetty Server * diff --git a/blade-core/src/main/java/com/blade/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/view/template/JspEngine.java index ee91ee970..34e2d2c67 100644 --- a/blade-core/src/main/java/com/blade/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/JspEngine.java @@ -24,11 +24,11 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.context.BladeWebContext; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; + /** * JSP Render, Default Render * diff --git a/blade-core/src/main/java/com/blade/web/BladeBanner.java b/blade-core/src/main/java/com/blade/web/BladeBanner.java index 868a83733..ce219b564 100644 --- a/blade-core/src/main/java/com/blade/web/BladeBanner.java +++ b/blade-core/src/main/java/com/blade/web/BladeBanner.java @@ -1,10 +1,10 @@ package com.blade.web; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.Const; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; + public class BladeBanner { private static final Logger LOGGER = LoggerFactory.getLogger(BladeBanner.class); diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java index 3c42bdab2..ae7f3b1e4 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -21,9 +21,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.Blade; import com.blade.Const; import com.blade.context.BladeWebContext; @@ -42,6 +39,8 @@ import com.blade.web.http.wrapper.ServletResponse; import blade.kit.StringKit; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * Synchronous request processor @@ -86,9 +85,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo // If it is static, the resource is handed over to the filter if(staticFileFilter.isStatic(uri)){ - if(LOGGER.isDebugEnabled()){ - LOGGER.debug("Request : {}\t{}", method, uri); - } + LOGGER.debug("Request : {}\t{}", method, uri); String realpath = httpRequest.getServletContext().getRealPath(uri); DispatchKit.printStatic(uri, realpath, httpResponse); return; diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 34f44d5ce..31c41aa03 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -24,9 +24,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.Blade; import com.blade.Bootstrap; import com.blade.ioc.IocApplication; @@ -34,6 +31,8 @@ import blade.kit.StringKit; import blade.kit.SystemKit; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * Blade Core DispatcherServlet diff --git a/blade-core/src/main/java/com/blade/web/verify/CSRFTokenManager.java b/blade-core/src/main/java/com/blade/web/verify/CSRFTokenManager.java index 95e780afc..74d8ed71e 100644 --- a/blade-core/src/main/java/com/blade/web/verify/CSRFTokenManager.java +++ b/blade-core/src/main/java/com/blade/web/verify/CSRFTokenManager.java @@ -15,15 +15,14 @@ */ package com.blade.web.verify; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.web.http.Request; import com.blade.web.http.Response; import com.blade.web.http.wrapper.Session; import blade.kit.HashidKit; import blade.kit.StringKit; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * CSRF token Manager From 1952c64648c7c3bfed602acc72a823dad52cd98c Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 17 Feb 2016 18:13:58 +0800 Subject: [PATCH 422/545] update log --- .../src/main/java/blade/plugin/redis/RedisPlugin.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java b/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java index 8cdf2d599..7bc4dd852 100644 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java +++ b/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java @@ -3,11 +3,10 @@ import java.util.ArrayList; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.plugin.Plugin; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; import redis.clients.jedis.JedisShardInfo; /** From 6ecea6807d473d3d4ac2bb67d75df5f661842d71 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 17 Feb 2016 18:49:24 +0800 Subject: [PATCH 423/545] fix log match '\\', '$' --- blade-kit/src/main/java/blade/kit/TaskKit.java | 4 ++-- blade-kit/src/main/java/blade/kit/TimwKit.java | 4 ++-- .../java/blade/kit/config/adapter/PropConfigAdapter.java | 5 ++--- .../src/main/java/blade/kit/logging/SimpleLogger.java | 9 ++++++++- blade-kit/src/main/java/blade/kit/mail/EmailHandle.java | 4 ++-- .../src/main/java/blade/kit/reflect/ReflectKit.java | 5 ++--- .../java/blade/kit/resource/AbstractClassReader.java | 5 ++--- .../src/main/java/blade/kit/resource/JarReaderImpl.java | 5 ++--- 8 files changed, 22 insertions(+), 19 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/TaskKit.java b/blade-kit/src/main/java/blade/kit/TaskKit.java index f842e809a..e6fd1fcd0 100644 --- a/blade-kit/src/main/java/blade/kit/TaskKit.java +++ b/blade-kit/src/main/java/blade/kit/TaskKit.java @@ -25,8 +25,8 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * 定时任务 diff --git a/blade-kit/src/main/java/blade/kit/TimwKit.java b/blade-kit/src/main/java/blade/kit/TimwKit.java index b7e06ab07..01be0b17f 100644 --- a/blade-kit/src/main/java/blade/kit/TimwKit.java +++ b/blade-kit/src/main/java/blade/kit/TimwKit.java @@ -19,8 +19,8 @@ import java.util.ArrayList; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * 计数均衡器 diff --git a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java index 450a6d8e2..2815f1f6c 100644 --- a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java +++ b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java @@ -8,13 +8,12 @@ import java.util.Properties; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import blade.kit.CollectionKit; import blade.kit.IOKit; import blade.kit.config.Config; import blade.kit.config.exception.ConfigAdapterException; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * 解析Properties配置文件 diff --git a/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java b/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java index a79b35f73..5a217252f 100644 --- a/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java +++ b/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java @@ -212,7 +212,14 @@ protected String format(String message, Object... args) { String msg = String.format(message, args); if(msg.indexOf("{}") != -1){ for(Object arg : args){ - msg = msg.replaceFirst("\\{\\}", arg.toString()); + String arg_str = arg.toString(); + if(arg_str.indexOf("\\") != -1){ + arg_str = arg_str.replaceAll("\\\\","/"); + } + if(arg_str.indexOf("$") != -1){ + arg_str = arg_str.replaceAll("\\$","_"); + } + msg = msg.replaceFirst("\\{\\}", arg_str); } } return msg; diff --git a/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java b/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java index 65c3aa10b..9529a9b7b 100644 --- a/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java +++ b/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java @@ -18,8 +18,8 @@ import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimeUtility; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * 邮件发送处理工具类 diff --git a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java index 8a1dfd058..c636094fc 100644 --- a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java @@ -31,13 +31,12 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import blade.kit.Emptys; import blade.kit.ExceptionKit; import blade.kit.StringKit; import blade.kit.SystemKit; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * 有关 Reflection处理的工具类。 diff --git a/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java b/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java index 6454430ad..eb7a51843 100644 --- a/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java +++ b/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java @@ -24,11 +24,10 @@ import java.util.Enumeration; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import blade.kit.Assert; import blade.kit.CollectionKit; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * 抽象类读取器 diff --git a/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java b/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java index 8cee7e2ad..f932bfc15 100644 --- a/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java +++ b/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java @@ -24,12 +24,11 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import blade.kit.Assert; import blade.kit.CollectionKit; import blade.kit.exception.ClassReaderException; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; /** * 根据jar文件读取类 From 00d56ff3112a03ad1b6be0cebda2f01dc87d4fc4 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 17 Feb 2016 18:54:41 +0800 Subject: [PATCH 424/545] fix blade-patchca log --- .../src/main/java/com/blade/patchca/PatchcaService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java index 7fb86f137..bc96521ac 100644 --- a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java +++ b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java @@ -14,12 +14,13 @@ import org.patchca.utils.encoder.EncoderHelper; import org.patchca.word.RandomWordFactory; import org.patchca.word.WordFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.blade.web.http.Response; import com.blade.web.http.wrapper.Session; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; + /** * PatchcaService */ From acca09037d46c14ddcbce0e4314e9fd5fdefebd3 Mon Sep 17 00:00:00 2001 From: Jie Shen <1993sj1993@gmail.com> Date: Thu, 18 Feb 2016 15:10:07 +0800 Subject: [PATCH 425/545] Replace magic numbers. --- blade-kit/src/main/java/blade/kit/IOKit.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/IOKit.java b/blade-kit/src/main/java/blade/kit/IOKit.java index 2fc14061b..f226dd3d1 100644 --- a/blade-kit/src/main/java/blade/kit/IOKit.java +++ b/blade-kit/src/main/java/blade/kit/IOKit.java @@ -87,7 +87,7 @@ private static StringBuilder readFromBufferedReader(BufferedReader reader) throw StringBuilder builder = new StringBuilder(); char[] buffer = new char[DEFAULT_BUFFER_SIZE]; int numRead = 0; - while((numRead = reader.read(buffer)) != -1) { + while((numRead = reader.read(buffer)) != EOF) { builder.append(String.valueOf(buffer, 0, numRead)); buffer = new char[DEFAULT_BUFFER_SIZE]; } @@ -98,7 +98,7 @@ public static byte[] toByteArray(InputStream input) throws IOException { @SuppressWarnings("resource") FastByteArrayOutputStream os = new FastByteArrayOutputStream(); byte[] buf = new byte[1024]; - for (int n = input.read(buf); n != -1; n = input.read(buf)) { + for (int n = input.read(buf); n != EOF; n = input.read(buf)) { os.write(buf, 0, n); } return os.toByteArray(); @@ -111,7 +111,7 @@ public static long copyLarge(final InputStream input, final OutputStream output) byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; long count = 0; int n = 0; - while (-1 != (n = input.read(buffer))) { + while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } @@ -128,7 +128,7 @@ public static long copyLarge(Reader input, Writer output) throws IOException { char[] buffer = new char[DEFAULT_BUFFER_SIZE]; long count = 0; int n = 0; - while (-1 != (n = input.read(buffer))) { + while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } @@ -184,7 +184,7 @@ public static long copy(InputStream input, OutputStream output) byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; long count = 0L; int n = 0; - while (-1 != (n = input.read(buffer))) { + while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } @@ -206,7 +206,7 @@ public static long copy(Reader input, Writer output) throws IOException { char[] buffer = new char[DEFAULT_BUFFER_SIZE]; long count = 0L; int n = 0; - while (-1 != (n = input.read(buffer))) { + while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } From 8fafd68d33dd9a4db27804a1307620cb6e9816e8 Mon Sep 17 00:00:00 2001 From: Jie Shen <1993sj1993@gmail.com> Date: Thu, 18 Feb 2016 15:18:49 +0800 Subject: [PATCH 426/545] Distinguish copy from copyLarge. --- blade-kit/src/main/java/blade/kit/IOKit.java | 38 +++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/IOKit.java b/blade-kit/src/main/java/blade/kit/IOKit.java index f226dd3d1..d96ed74b5 100644 --- a/blade-kit/src/main/java/blade/kit/IOKit.java +++ b/blade-kit/src/main/java/blade/kit/IOKit.java @@ -109,7 +109,7 @@ public static byte[] toByteArray(InputStream input) throws IOException { public static long copyLarge(final InputStream input, final OutputStream output) throws IOException { byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; - long count = 0; + long count = 0L; int n = 0; while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); @@ -126,7 +126,7 @@ public static void copy(InputStream input, Writer output) public static long copyLarge(Reader input, Writer output) throws IOException { char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - long count = 0; + long count = 0L; int n = 0; while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); @@ -179,38 +179,32 @@ public static void write(String data, File file, Charset charset) { } } - public static long copy(InputStream input, OutputStream output) + public static int copy(InputStream input, OutputStream output) throws IOException { - byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; - long count = 0L; - int n = 0; - while (EOF != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; + long count = copyLarge(input, output); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; } - public static long copy(InputStream input, Writer output, String charsetName) + public static int copy(InputStream input, Writer output, String charsetName) throws IOException { return copy(new InputStreamReader(input, Charset.forName(charsetName)), output); } - public static long copy(InputStream input, Writer output, Charset charset) + public static int copy(InputStream input, Writer output, Charset charset) throws IOException { return copy(new InputStreamReader(input, charset), output); } - public static long copy(Reader input, Writer output) throws IOException { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - long count = 0L; - int n = 0; - while (EOF != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; + public static int copy(Reader input, Writer output) throws IOException { + long count = copyLarge(input, output); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; } public static void closeQuietly(ZipFile obj) { From c5f9dfb38583495716e0ace0c5570e2ea0d18508 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 18 Feb 2016 16:54:34 +0800 Subject: [PATCH 427/545] remove Third-party extensions --- blade-cache/README.md | 56 - blade-cache/pom.xml | 24 - .../main/java/blade/cache/AbstractCache.java | 322 ---- .../src/main/java/blade/cache/Cache.java | 168 -- .../main/java/blade/cache/CacheCleaner.java | 103 -- .../main/java/blade/cache/CacheException.java | 37 - .../main/java/blade/cache/CacheManager.java | 217 --- .../main/java/blade/cache/CacheObject.java | 113 -- .../main/java/blade/cache/impl/FIFOCache.java | 64 - .../main/java/blade/cache/impl/LFUCache.java | 85 - .../main/java/blade/cache/impl/LRUCache.java | 80 - .../src/test/java/blade/test/CacheTest.java | 56 - blade-oauth2/README.md | 12 - blade-oauth2/pom.xml | 24 - .../src/main/java/com/blade/oauth2/OAuth.java | 67 - .../java/com/blade/oauth2/OAuthError.java | 131 -- .../java/com/blade/oauth2/OAuthRequest.java | 51 - .../java/com/blade/oauth2/OAuthResponse.java | 183 --- .../oauth2/base/request/OAuthBaseRequest.java | 90 - .../base/request/OAuthTokenBaseRequest.java | 67 - .../base/validator/OAuthBaseValidator.java | 135 -- .../oauth2/base/validator/OAuthValidator.java | 30 - .../exception/OAuthProblemException.java | 97 -- .../com/blade/oauth2/issuer/MD5Generator.java | 15 - .../com/blade/oauth2/issuer/OAuthIssuer.java | 19 - .../blade/oauth2/issuer/OAuthIssuerKit.java | 31 - .../oauth2/issuer/UUIDValueGenerator.java | 20 - .../blade/oauth2/issuer/ValueGenerator.java | 21 - .../java/com/blade/oauth2/kit/OAuthKit.java | 408 ----- .../blade/oauth2/message/OAuthMessage.java | 31 - .../blade/oauth2/message/types/GrantType.java | 29 - .../oauth2/message/types/ParameterStyle.java | 27 - .../oauth2/message/types/ResponseType.java | 26 - .../blade/oauth2/message/types/TokenType.java | 26 - .../parameters/JSONBodyParametersApplier.java | 21 - .../oauth2/request/OAuthGrantRequest.java | 48 - .../com/blade/oauth2/request/RequestType.java | 27 - .../oauth2/response/OAuthASResponse.java | 136 -- .../validator/AuthorizationCodeValidator.java | 28 - .../validator/AuthorizationValidator.java | 158 -- .../validator/ClientCredentialValidator.java | 51 - .../validator/ImplicitCodeValidator.java | 188 --- .../PasswordCredentialValidator.java | 124 -- .../validator/RefreshTokenValidator.java | 90 - blade-patchca/README.md | 4 - blade-patchca/pom.xml | 23 - .../com/blade/patchca/PatchcaService.java | 133 -- .../patchca/background/BackgroundFactory.java | 27 - .../SingleColorBackgroundFactory.java | 51 - .../java/org/patchca/color/ColorFactory.java | 26 - .../patchca/color/GradientColorFactory.java | 48 - .../org/patchca/color/RandomColorFactory.java | 54 - .../org/patchca/color/SingleColorFactory.java | 44 - .../patchca/filter/AbstractFilterFactory.java | 41 - .../filter/ConfigurableFilterFactory.java | 37 - .../org/patchca/filter/FilterFactory.java | 27 - .../library/AbstractConvolveImageOp.java | 65 - .../filter/library/AbstractImageOp.java | 172 -- .../library/AbstractTransformImageOp.java | 55 - .../patchca/filter/library/BlurImageOp.java | 30 - .../patchca/filter/library/CurvesImageOp.java | 115 -- .../filter/library/DiffuseImageOp.java | 60 - .../filter/library/DoubleRippleImageOp.java | 31 - .../patchca/filter/library/MarbleImageOp.java | 91 - .../patchca/filter/library/PerlinNoise.java | 95 -- .../patchca/filter/library/RippleImageOp.java | 80 - .../patchca/filter/library/SoftenImageOp.java | 30 - .../patchca/filter/library/WobbleImageOp.java | 101 -- .../predefined/CurvesRippleFilterFactory.java | 58 - .../DiffuseRippleFilterFactory.java | 38 - .../predefined/DoubleRippleFilterFactory.java | 47 - .../predefined/MarbleRippleFilterFactory.java | 40 - .../predefined/RippleFilterFactory.java | 59 - .../predefined/WobbleRippleFilterFactory.java | 42 - .../java/org/patchca/font/FontFactory.java | 25 - .../org/patchca/font/RandomFontFactory.java | 90 - .../service/AbstractCaptchaService.java | 115 -- .../java/org/patchca/service/Captcha.java | 49 - .../org/patchca/service/CaptchaService.java | 24 - .../service/ConfigurableCaptchaService.java | 43 - .../patchca/service/SimpleCaptchaService.java | 59 - .../text/renderer/AbstractTextRenderer.java | 103 -- .../text/renderer/BestFitTextRenderer.java | 36 - .../renderer/RandomYBestFitTextRenderer.java | 41 - .../text/renderer/SimpleTextRenderer.java | 34 - .../patchca/text/renderer/TextCharacter.java | 117 -- .../patchca/text/renderer/TextRenderer.java | 38 - .../org/patchca/text/renderer/TextString.java | 83 - .../patchca/utils/encoder/EncoderHelper.java | 37 - .../word/AdaptiveRandomWordFactory.java | 58 - .../org/patchca/word/RandomWordFactory.java | 60 - .../java/org/patchca/word/WordFactory.java | 24 - .../test/java/org/blade/patchca/AppTest.java | 15 - blade-redis/README.md | 158 -- blade-redis/pom.xml | 31 - .../java/blade/plugin/redis/JedisCache.java | 157 -- .../blade/plugin/redis/RedisExecutor.java | 1459 ----------------- .../java/blade/plugin/redis/RedisLock.java | 120 -- .../java/blade/plugin/redis/RedisPlugin.java | 84 - .../blade/plugin/redis/RedisPoolConfig.java | 21 - pom.xml | 5 +- 101 files changed, 1 insertion(+), 8545 deletions(-) delete mode 100644 blade-cache/README.md delete mode 100644 blade-cache/pom.xml delete mode 100644 blade-cache/src/main/java/blade/cache/AbstractCache.java delete mode 100644 blade-cache/src/main/java/blade/cache/Cache.java delete mode 100644 blade-cache/src/main/java/blade/cache/CacheCleaner.java delete mode 100644 blade-cache/src/main/java/blade/cache/CacheException.java delete mode 100644 blade-cache/src/main/java/blade/cache/CacheManager.java delete mode 100644 blade-cache/src/main/java/blade/cache/CacheObject.java delete mode 100644 blade-cache/src/main/java/blade/cache/impl/FIFOCache.java delete mode 100644 blade-cache/src/main/java/blade/cache/impl/LFUCache.java delete mode 100644 blade-cache/src/main/java/blade/cache/impl/LRUCache.java delete mode 100644 blade-cache/src/test/java/blade/test/CacheTest.java delete mode 100644 blade-oauth2/README.md delete mode 100644 blade-oauth2/pom.xml delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/OAuth.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/OAuthError.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/exception/OAuthProblemException.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/issuer/MD5Generator.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuer.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuerKit.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/issuer/UUIDValueGenerator.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/issuer/ValueGenerator.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/message/OAuthMessage.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/message/types/GrantType.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/message/types/ParameterStyle.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/message/types/ResponseType.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/message/types/TokenType.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/request/RequestType.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java delete mode 100644 blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java delete mode 100644 blade-patchca/README.md delete mode 100644 blade-patchca/pom.xml delete mode 100644 blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java delete mode 100644 blade-patchca/src/main/java/org/patchca/background/BackgroundFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/background/SingleColorBackgroundFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/color/ColorFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/color/GradientColorFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/color/RandomColorFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/color/SingleColorFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/AbstractFilterFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/ConfigurableFilterFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/FilterFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/AbstractConvolveImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/AbstractImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/AbstractTransformImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/BlurImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/CurvesImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/DiffuseImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/DoubleRippleImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/MarbleImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/PerlinNoise.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/RippleImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/SoftenImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/library/WobbleImageOp.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/CurvesRippleFilterFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/DiffuseRippleFilterFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/DoubleRippleFilterFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/MarbleRippleFilterFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/RippleFilterFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/filter/predefined/WobbleRippleFilterFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/font/FontFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/font/RandomFontFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/service/AbstractCaptchaService.java delete mode 100644 blade-patchca/src/main/java/org/patchca/service/Captcha.java delete mode 100644 blade-patchca/src/main/java/org/patchca/service/CaptchaService.java delete mode 100644 blade-patchca/src/main/java/org/patchca/service/ConfigurableCaptchaService.java delete mode 100644 blade-patchca/src/main/java/org/patchca/service/SimpleCaptchaService.java delete mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/AbstractTextRenderer.java delete mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/BestFitTextRenderer.java delete mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/RandomYBestFitTextRenderer.java delete mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/SimpleTextRenderer.java delete mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/TextCharacter.java delete mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/TextRenderer.java delete mode 100644 blade-patchca/src/main/java/org/patchca/text/renderer/TextString.java delete mode 100644 blade-patchca/src/main/java/org/patchca/utils/encoder/EncoderHelper.java delete mode 100644 blade-patchca/src/main/java/org/patchca/word/AdaptiveRandomWordFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/word/RandomWordFactory.java delete mode 100644 blade-patchca/src/main/java/org/patchca/word/WordFactory.java delete mode 100644 blade-patchca/src/test/java/org/blade/patchca/AppTest.java delete mode 100644 blade-redis/README.md delete mode 100644 blade-redis/pom.xml delete mode 100644 blade-redis/src/main/java/blade/plugin/redis/JedisCache.java delete mode 100644 blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java delete mode 100644 blade-redis/src/main/java/blade/plugin/redis/RedisLock.java delete mode 100644 blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java delete mode 100644 blade-redis/src/main/java/blade/plugin/redis/RedisPoolConfig.java diff --git a/blade-cache/README.md b/blade-cache/README.md deleted file mode 100644 index 7f72ca454..000000000 --- a/blade-cache/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# blade-cache - -一个简单的缓存引擎,内部有基于`FIFO`,`LFU`,`LRU`算法的基本实现。 - -## 使用 -```java -public class CacheTest { - - @Test - public void testLRU2(){ - CacheManager cm = CacheManager.getInstance(); - - Cache cache = cm.newLRUCache(); - cache.set("name:1", "jack"); - cache.set("name:2", "jack2"); - - System.out.println(cache.get("name:2")); - - } - - @Test - public void testAutoClean(){ - CacheManager cm = CacheManager.getInstance(); - cm.setCleanInterval(1000); - - Cache cache = cm.newLRUCache(); - cache.set("name:1", "jack"); - cache.set("name:2", "jack2"); - - System.out.println(cache.get("name:2")); - - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println(cache.get("name:2")); - } - - @Test - public void testHashCache(){ - CacheManager cm = CacheManager.getInstance(); - - Cache cache = cm.newLRUCache(); - cache.hset("user:list", "a1", "123"); - cache.hset("user:list", "a2", "456"); - cache.hset("user:list", "a3", "789"); - - System.out.println(cache.hget("user:list", "a1")); - System.out.println(cache.hget("user:list", "a2")); - System.out.println(cache.hget("user:list", "a3")); - - } - -} -``` \ No newline at end of file diff --git a/blade-cache/pom.xml b/blade-cache/pom.xml deleted file mode 100644 index 55b636e64..000000000 --- a/blade-cache/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-cache - jar - 1.2.2 - blade-cache - https://github.com/biezhi/blade/tree/master/blade-cache - - - - junit - junit - - - diff --git a/blade-cache/src/main/java/blade/cache/AbstractCache.java b/blade-cache/src/main/java/blade/cache/AbstractCache.java deleted file mode 100644 index 1c03dd01b..000000000 --- a/blade-cache/src/main/java/blade/cache/AbstractCache.java +++ /dev/null @@ -1,322 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * - *

- * 抽象缓存基础实现 - *

- * - * @author biezhi - * @since 1.0 - */ -@SuppressWarnings("unchecked") -public abstract class AbstractCache implements Cache { - - /** - * 同步缓存容器 - */ - protected Map> _mCache; - - /** - * 同步缓存容器 - */ - protected Map>> _hCache; - - /** - * 缓存锁 - */ - protected final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock(); - - /** - * 读取锁 - */ - protected final Lock readLock = cacheLock.readLock(); - - /** - * 写入锁 - */ - protected final Lock writeLock = cacheLock.writeLock(); - - /** - * 最大缓存数 - */ - protected int cacheSize; - - /** - * 默认过期时间, 0 -> 永不过期 - */ - protected long defaultExpire; - - /** - * 是否设置默认过期时间 - */ - protected boolean existCustomExpire; - - /** - * 淘汰对象具体实现 - * @return - */ - protected abstract int eliminateCache(); - - /** - * 设置一个缓存大小并初始化 - * @param cacheSize - */ - public AbstractCache(int cacheSize) { - this.cacheSize = cacheSize; - this._mCache = Collections.synchronizedMap(new HashMap>()); - this._hCache = Collections.synchronizedMap(new HashMap>>()); - } - - /** - * 放一个缓存 - */ - public void set(K key, V obj) { - set(key, obj, defaultExpire); - } - - /** - * 放一个缓存并设置缓存时间 - */ - public void set(K key, V value, long expire) { - writeLock.lock(); - try { - CacheObject co = new CacheObject(key, value, expire); - if (expire != 0) { - existCustomExpire = true; - } - if (isFull()) { - eliminate() ; - } - _mCache.put(key, co); - } - finally { - writeLock.unlock(); - } - } - - /** - * 放一个缓存 - */ - public void hset(K key, F field, V obj) { - hset(key, field, obj, defaultExpire); - } - - /** - * 放一个hash类型缓存并设置缓存时间 - */ - public void hset(K key, F field, V value, long expire) { - writeLock.lock(); - try { - CacheObject co = new CacheObject(key, value, expire); - - if(expire != 0){ - existCustomExpire = true; - } - - if(isFull()){ - eliminate() ; - } - - Map> coMap = (Map>) _hCache.get(key); - if(null == coMap){ - coMap = new HashMap>(); - } - coMap.put(field, co); - - _hCache.put(key, coMap); - } - finally { - writeLock.unlock(); - } - } - - - /** - * 取一个缓存 - */ - public V get(K key) { - readLock.lock(); - try { - CacheObject co = _mCache.get(key); - if (co == null) { - return null; - } - if (co.isExpired() == true) { - _mCache.remove(key); - return null; - } - return co.getValue(); - } finally { - readLock.unlock(); - } - } - - /** - * 取一个缓存 - */ - public V hget(K key, F field) { - readLock.lock(); - try { - Map> coMap = _hCache.get(key); - - if(null == coMap){ - return null; - } - - CacheObject co = coMap.get(field); - - if(null == co){ - return null; - } - - if (co.isExpired() == true) { - coMap.remove(field); - return null; - } - - return co.getValue(); - } finally { - readLock.unlock(); - } - } - - /** - * 移除一个缓存 - */ - public void del(K key) { - writeLock.lock(); - try { - _mCache.remove(key); - } finally { - writeLock.unlock(); - } - } - - /** - * 移除一个缓存 - */ - public void hdel(K key) { - writeLock.lock(); - try { - _hCache.remove(key); - } finally { - writeLock.unlock(); - } - } - - /** - * 移除一个缓存 - */ - public void del(K key, F feild) { - writeLock.lock(); - try { - Map> coMap = _hCache.get(key); - if(null != coMap){ - coMap.remove(feild); - } - } finally { - writeLock.unlock(); - } - } - - @Override - public Set keys() { - return _mCache.keySet(); - } - - @Override - public Set flieds(K key) { - Map> coMap = _hCache.get(key); - if(null == coMap){ - return null; - } - return (Set) coMap.keySet(); - } - - public int elementsInCache() { - return ( _mCache.size() + _hCache.size() ); - } - - @Override - public int size() { - return ( _mCache.size() + _hCache.size() ); - } - - protected boolean isNeedClearExpiredObject(){ - return defaultExpire > 0 || existCustomExpire ; - } - - public final int eliminate() { - writeLock.lock(); - try { - return eliminateCache(); - } - finally { - writeLock.unlock(); - } - } - - @Override - public boolean isFull() { - if (cacheSize == 0) {// o -> 无限制 - return false; - } - return ( _mCache.size() + _hCache.size() ) >= cacheSize; - } - - @Override - public void clear() { - writeLock.lock(); - try { - _mCache.clear(); - } finally { - writeLock.unlock(); - } - } - - @Override - public int getCacheSize() { - return cacheSize; - } - - @Override - public boolean isEmpty() { - return size() == 0; - } - - @Override - public Cache cacheSize(int cacheSize) { - this.cacheSize = cacheSize; - return this; - } - - @Override - public Cache expire(long expire) { - this.defaultExpire = expire; - return this; - } - -} \ No newline at end of file diff --git a/blade-cache/src/main/java/blade/cache/Cache.java b/blade-cache/src/main/java/blade/cache/Cache.java deleted file mode 100644 index ab4238e77..000000000 --- a/blade-cache/src/main/java/blade/cache/Cache.java +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; - -import java.util.Set; - - -/** - * - *

- * 缓存顶级接口 - *

- * - * @author biezhi - * @since 1.0 - */ -public interface Cache { - - /** - * 向缓存添加value对象,其在缓存中生存时间为默认值 - * - * @param key - * @param value - * @throws CacheException - */ - void set(K key, V value); - - /** - * 向缓存添加value对象,并指定存活时间 - * - * @param key - * @param value 过期时间 - * @param expire - * @throws CacheException - */ - void set(K key, V value, long expire); - - /** - * 向缓存添加一个hash类型的数据 - * - * @param key - * @param field - * @param value - */ - void hset(K key, F field, V value); - - /** - * 向缓存添加一个hash类型的数据并设置有效期 - * - * @param key - * @param field - * @param value - * @param expire - */ - void hset(K key, F field, V value, long expire); - - /** - * 查找缓存对象 - * - * @param key - * @return - * @throws CacheException - */ - V get(K key); - - /** - * 查找缓存对象 - * - * @param key - * @param field - * @return - */ - V hget(K key, F field); - - /** - * 删除缓存对象 - * - * @param key - */ - void del(K key); - - /** - * 删除缓存对象 - * - * @param key - */ - void hdel(K key); - - /** - * 删除缓存对象 - * - * @param key - * @param field - */ - void del(K key, F field); - - /** - * @return 返回所有key - */ - Set keys(); - - /** - * @return 返回一个key所有flied - */ - Set flieds(K key); - - /** - * @return 返回当前缓存的大小 - */ - int size(); - - /** - * 淘汰对象 - * - * @return 被删除对象大小 - */ - int eliminate(); - - /** - * 缓存是否已经满 - * @return - */ - boolean isFull(); - - /** - * 清除所有缓存对象 - */ - void clear(); - - /** - * 返回缓存大小 - * - * @return - */ - int getCacheSize(); - - /** - * 缓存中是否为空 - */ - boolean isEmpty(); - - /** - * 设置缓存大小 - * @param cacheSize - * @return - */ - Cache cacheSize(int cacheSize); - - /** - * 设置缓存有效期 - * @param expire - * @return - */ - Cache expire(long expire); - } diff --git a/blade-cache/src/main/java/blade/cache/CacheCleaner.java b/blade-cache/src/main/java/blade/cache/CacheCleaner.java deleted file mode 100644 index 7dc8767b3..000000000 --- a/blade-cache/src/main/java/blade/cache/CacheCleaner.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; - -import java.util.Set; - -/** - * - *

- * 定时清理缓存线程 - *

- * - * @author biezhi - * @since 1.0 - */ -public class CacheCleaner extends Thread { - - /** - * 清理间隔 - */ - private long _cleanInterval; - - /** - * 是不是在睡眠中 - */ - private boolean _sleep = false; - - /** - * 设置清理间隔并初始化 - * - * @param cleanInterval - */ - public CacheCleaner(long cleanInterval) { - _cleanInterval = cleanInterval; - setName(this.getClass().getName()); - setDaemon(true); - } - - /** - * 设置清理间隔 - * - * @param cleanInterval - */ - public void setCleanInterval(long cleanInterval) { - _cleanInterval = cleanInterval; - synchronized (this) { - if (_sleep) { - interrupt(); - } - } - } - - /** - * 执行缓存清理工作 - */ - @Override - public void run() { - while (true) { - try { - try { - sleep(_cleanInterval); - } catch (Throwable t) { - } finally { - _sleep = false; - } - CacheManager cacheFactory = CacheManager.getInstance(); - Set cacheIds = cacheFactory.getCacheIds(); - if (null != cacheIds) { - for (String cacheId : cacheIds) { - Cache cache = cacheFactory.getCache(cacheId); - if (cache != null) { - cache.clear(); - } - yield(); - } - } - } catch (Throwable t) { - t.printStackTrace(); - } - _sleep = true; -// try { -// sleep(_cleanInterval); -// } catch (Throwable t) { -// } finally { -// _sleep = false; -// } - } - } - -} \ No newline at end of file diff --git a/blade-cache/src/main/java/blade/cache/CacheException.java b/blade-cache/src/main/java/blade/cache/CacheException.java deleted file mode 100644 index cb145f691..000000000 --- a/blade-cache/src/main/java/blade/cache/CacheException.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; - -/** - * - *

- * 缓存异常封装 - *

- * - * @author biezhi - * @since 1.0 - */ -public class CacheException extends Exception { - - private static final long serialVersionUID = 2794445171318574075L; - - public CacheException() { - } - - public CacheException(String msg) { - super(msg); - } -} \ No newline at end of file diff --git a/blade-cache/src/main/java/blade/cache/CacheManager.java b/blade-cache/src/main/java/blade/cache/CacheManager.java deleted file mode 100644 index 495165bf2..000000000 --- a/blade-cache/src/main/java/blade/cache/CacheManager.java +++ /dev/null @@ -1,217 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import blade.cache.impl.FIFOCache; -import blade.cache.impl.LFUCache; -import blade.cache.impl.LRUCache; - -/** - * - *

- * 缓存管理对象 - *

- * - * @author biezhi - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class CacheManager { - - private static final CacheManager _instance = new CacheManager(); - - private static final String CACHE_SUFFIX = "blade_cache_ID_"; - - private Map _cacheMap; - - private CacheCleaner _cleaner; - - private int _cacheSize = 100; - - // 一小时 - private static final int DEFAULT_CLEAN_TIME = 3600000; - - private static Object _mlock = new Object(); - - private CacheManager() { - _cacheMap = new HashMap(); - _cleaner = new CacheCleaner(DEFAULT_CLEAN_TIME); //默认30秒自动清空缓存 - _cleaner.start(); - } - - public static CacheManager getInstance(){ - return _instance; - } - - public void setCleanInterval(long time) { - _cleaner.setCleanInterval(time); - } - - public Cache getCache(String cacheId){ - if (cacheId == null) { - throw new NullPointerException("cacheId is null"); - } - synchronized (_mlock) { - return _cacheMap.get(cacheId); - } - } - - /***************************** LRUCache:START **************************************/ - public Cache newLRUCache(){ - synchronized (_mlock) { - String cacheId = CACHE_SUFFIX + System.currentTimeMillis(); - return newLRUCache(cacheId, _cacheSize); - } - } - - public Cache newLRUCache(String cacheId){ - if (cacheId == null) { - throw new NullPointerException("cacheId is null"); - } - return newLRUCache(cacheId, _cacheSize); - } - - public Cache newLRUCache(int cacheSize){ - synchronized (_mlock) { - String cacheId = CACHE_SUFFIX + System.currentTimeMillis(); - return newLRUCache(cacheId, cacheSize); - } - } - - public Cache newLRUCache(String cacheId, int cacheSize){ - synchronized (_mlock) { - Cache cache = new LRUCache(cacheSize); - _cacheMap.put(cacheId, cache); - return cache; - } - } - /***************************** LRUCache:END **************************************/ - - - /***************************** LFUCache:START **************************************/ - public Cache newLFUCache(){ - synchronized (_mlock) { - String cacheId = CACHE_SUFFIX + System.currentTimeMillis(); - return newLFUCache(cacheId, _cacheSize); - } - } - - public Cache newLFUCache(String cacheId){ - if (cacheId == null) { - throw new NullPointerException("cacheId is null"); - } - return newLFUCache(cacheId, _cacheSize); - } - - public Cache newLFUCache(int cacheSize){ - synchronized (_mlock) { - String cacheId = CACHE_SUFFIX + System.currentTimeMillis(); - return newLFUCache(cacheId, cacheSize); - } - } - - public Cache newLFUCache(String cacheId, int cacheSize){ - synchronized (_mlock) { - Cache cache = new LFUCache(cacheSize); - _cacheMap.put(cacheId, cache); - return cache; - } - } - /***************************** LFUCache:END **************************************/ - - - /***************************** LFUCache:START **************************************/ - public Cache newFIFOCache(){ - synchronized (_mlock) { - String cacheId = CACHE_SUFFIX + System.currentTimeMillis(); - return newFIFOCache(cacheId, _cacheSize); - } - } - - public Cache newFIFOCache(String cacheId){ - if (cacheId == null) { - throw new NullPointerException("cacheId is null"); - } - return newLFUCache(cacheId, _cacheSize); - } - - public Cache newFIFOCache(int cacheSize){ - synchronized (_mlock) { - String cacheId = CACHE_SUFFIX + System.currentTimeMillis(); - return newFIFOCache(cacheId, cacheSize); - } - } - - public Cache newFIFOCache(String cacheId, int cacheSize){ - synchronized (_mlock) { - Cache cache = new FIFOCache(cacheSize); - _cacheMap.put(cacheId, cache); - return cache; - } - } - /***************************** LFUCache:END **************************************/ - - /** - * @return 返回所有缓存id - */ - public Set getCacheIds(){ - synchronized (_mlock) { - if(null != _cacheMap && _cacheMap.size() > 0){ - return _cacheMap.keySet(); - } - } - return null; - } - - /** - * 移除一个缓存 - * @param cacheId - * @throws CacheException - */ - public void removeCache(String cacheId) throws CacheException { - if(cacheId == null) { - throw new NullPointerException("cacheId is null"); - } - synchronized(_mlock){ - _cacheMap.remove(cacheId); - } - } - - /** - * 移除所有缓存 - * @param cacheId - * @throws CacheException - */ - public void removeAll() { - synchronized(_mlock){ - if(null != _cacheMap && _cacheMap.size() > 0){ - - Set keys = _cacheMap.keySet(); - for(String key : keys){ - Cache cache = _cacheMap.get(key); - if(null != cache){ - cache.clear(); - } - } - _cacheMap.clear(); - } - } - } -} \ No newline at end of file diff --git a/blade-cache/src/main/java/blade/cache/CacheObject.java b/blade-cache/src/main/java/blade/cache/CacheObject.java deleted file mode 100644 index 4af5cb1f9..000000000 --- a/blade-cache/src/main/java/blade/cache/CacheObject.java +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache; - -/** - *

- * 缓存实体对象 - *

- * - * @author biezhi - * @since 1.0 - */ -public class CacheObject { - - private K key; - private V value; - private long expires; // 对象存活时间(time-to-live) - private long lastAccess; // 最后访问时间 - private long accessCount; // 访问次数 - private CacheObject previous; - private CacheObject next; - - public CacheObject(K k, V v, long expires) { - this.key = k; - this.value = v; - this.expires = expires; - } - - public CacheObject() { - } - - /** - * @return 返回是否已经过期 - */ - public boolean isExpired() { - if (expires == 0) { - return false; - } - return lastAccess + expires < System.currentTimeMillis(); - } - - public V getValue() { - lastAccess = System.currentTimeMillis(); - accessCount++; - return value; - } - - public K getKey() { - return key; - } - - public long getExpires() { - return expires; - } - - public void setExpires(long expires) { - this.expires = expires; - } - - public long getLastAccess() { - return lastAccess; - } - - public void setLastAccess(long lastAccess) { - this.lastAccess = lastAccess; - } - - public long getAccessCount() { - return accessCount; - } - - public void setAccessCount(long accessCount) { - this.accessCount = accessCount; - } - - public CacheObject getPrevious() { - return previous; - } - - public void setPrevious(CacheObject previous) { - this.previous = previous; - } - - public CacheObject getNext() { - return next; - } - - public void setNext(CacheObject next) { - this.next = next; - } - - public void setKey(K key) { - this.key = key; - } - - public void setValue(V value) { - this.value = value; - } - -} \ No newline at end of file diff --git a/blade-cache/src/main/java/blade/cache/impl/FIFOCache.java b/blade-cache/src/main/java/blade/cache/impl/FIFOCache.java deleted file mode 100644 index fec064c0a..000000000 --- a/blade-cache/src/main/java/blade/cache/impl/FIFOCache.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache.impl; - -import java.util.Iterator; - -import blade.cache.AbstractCache; -import blade.cache.CacheObject; - -/** - * - *

- * FIFO实现 - *

- * - * @author biezhi - * @since 1.0 - */ -public class FIFOCache extends AbstractCache { - - public FIFOCache(int cacheSize) { - super(cacheSize); - } - - @Override - protected int eliminateCache() { - - int count = 0; - K firstKey = null; - - Iterator> iterator = _mCache.values().iterator(); - while (iterator.hasNext()) { - CacheObject cacheObject = iterator.next(); - - if (cacheObject.isExpired()) { - iterator.remove(); - count++; - } else { - if (firstKey == null) - firstKey = cacheObject.getKey(); - } - } - - if (firstKey != null && isFull()) {// 删除过期对象还是满,继续删除链表第一个 - _mCache.remove(firstKey); - } - - return count; - } - -} \ No newline at end of file diff --git a/blade-cache/src/main/java/blade/cache/impl/LFUCache.java b/blade-cache/src/main/java/blade/cache/impl/LFUCache.java deleted file mode 100644 index db31021de..000000000 --- a/blade-cache/src/main/java/blade/cache/impl/LFUCache.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache.impl; - -import java.util.Iterator; - -import blade.cache.AbstractCache; -import blade.cache.CacheObject; - -/** - * - *

- * LFU实现 - *

- * - * @author biezhi - * @since 1.0 - */ -public class LFUCache extends AbstractCache { - - public LFUCache(int cacheSize) { - super(cacheSize); - } - - /** - * 实现删除过期对象 和 删除访问次数最少的对象 - * - */ - @Override - protected int eliminateCache() { - Iterator> iterator = _mCache.values().iterator(); - int count = 0; - long minAccessCount = Long.MAX_VALUE; - - while (iterator.hasNext()) { - CacheObject cacheObject = iterator.next(); - - if (cacheObject.isExpired()) { - iterator.remove(); - count++; - continue; - } else { - minAccessCount = Math.min(cacheObject.getAccessCount(), - minAccessCount); - } - } - - if (count > 0) - return count; - - if (minAccessCount != Long.MAX_VALUE) { - - iterator = _mCache.values().iterator(); - - while (iterator.hasNext()) { - CacheObject cacheObject = iterator.next(); - - cacheObject.setAccessCount(cacheObject.getAccessCount() - minAccessCount); - - if (cacheObject.getAccessCount() <= 0) { - iterator.remove(); - count++; - } - - } - - } - - return count; - } - -} \ No newline at end of file diff --git a/blade-cache/src/main/java/blade/cache/impl/LRUCache.java b/blade-cache/src/main/java/blade/cache/impl/LRUCache.java deleted file mode 100644 index 658dd89dd..000000000 --- a/blade-cache/src/main/java/blade/cache/impl/LRUCache.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.cache.impl; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; - -import blade.cache.AbstractCache; -import blade.cache.CacheObject; - -/** - * - *

- * LRU 实现 - *

- * - * @author biezhi - * @since 1.0 - */ -public class LRUCache extends AbstractCache { - - public LRUCache(int cacheSize) { - - super(cacheSize) ; - - //linkedHash已经实现LRU算法 是通过双向链表来实现,当某个位置被命中,通过调整链表的指向将该位置调整到头位置,新加入的内容直接放在链表头,如此一来,最近被命中的内容就向链表头移动,需要替换时,链表最后的位置就是最近最少使用的位置 - this._mCache = new LinkedHashMap>( cacheSize +1 , 1f,true ) { - - private static final long serialVersionUID = 1L; - - @Override - protected boolean removeEldestEntry(Map.Entry> eldest) { - return LRUCache.this.removeEldestEntry(eldest); - } - - }; - } - - private boolean removeEldestEntry(Map.Entry> eldest) { - if (cacheSize == 0) - return false; - return size() > cacheSize; - } - - /** - * 只需要实现清除过期对象就可以了,linkedHashMap已经实现LRU - */ - @Override - protected int eliminateCache() { - - if(!isNeedClearExpiredObject()){ return 0 ;} - - Iterator> iterator = _mCache.values().iterator(); - int count = 0 ; - while(iterator.hasNext()){ - CacheObject cacheObject = iterator.next(); - - if(cacheObject.isExpired() ){ - iterator.remove(); - count++ ; - } - } - - return count; - } - -} \ No newline at end of file diff --git a/blade-cache/src/test/java/blade/test/CacheTest.java b/blade-cache/src/test/java/blade/test/CacheTest.java deleted file mode 100644 index e4ab65144..000000000 --- a/blade-cache/src/test/java/blade/test/CacheTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package blade.test; - -import org.junit.Assert; -import org.junit.Test; - -import blade.cache.Cache; -import blade.cache.CacheManager; - -public class CacheTest { - - @Test - public void testLRU2(){ - CacheManager cm = CacheManager.getInstance(); - - Cache cache = cm.newLRUCache(); - cache.set("name:1", "jack"); - cache.set("name:2", "jack2"); - - Assert.assertEquals("jack", cache.get("name:1")); - Assert.assertEquals("jack2", cache.get("name:2")); - } - - @Test - public void testAutoClean(){ - CacheManager cm = CacheManager.getInstance(); - cm.setCleanInterval(1000); - - Cache cache = cm.newLRUCache(); - cache.set("name:1", "jack"); - cache.set("name:2", "jack2"); - - Assert.assertEquals("jack2", cache.get("name:2")); - - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Assert.assertEquals(null, cache.get("name:2")); - } - - @Test - public void testHashCache(){ - CacheManager cm = CacheManager.getInstance(); - - Cache cache = cm.newLRUCache(); - cache.hset("user:list", "a1", "123"); - cache.hset("user:list", "a2", "456"); - cache.hset("user:list", "a3", "789"); - - Assert.assertEquals("123", cache.hget("user:list", "a1")); - Assert.assertEquals("456", cache.hget("user:list", "a2")); - Assert.assertEquals("789", cache.hget("user:list", "a3")); - } - -} diff --git a/blade-oauth2/README.md b/blade-oauth2/README.md deleted file mode 100644 index abf626eac..000000000 --- a/blade-oauth2/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# blade-oauth2 - -修改自[jfinal-oauth2.0-server](http://git.oschina.net/brucezcq/jfinal-oauth2.0-server) - -参考[RFC6749](http://www.rfcreader.com/#rfc6749) - -实现了OAuth 2.0定义了四种授权方式 - -* 授权码模式(authorization code): 先获取下次请求token的code,然后在带着code去请求token -* 简化模式(implicit):直接请求token -* 密码模式(resource owner password credentials): 先完成授权,然后再获取token -* 客户端模式(client credentials): 类似密码保护模式 diff --git a/blade-oauth2/pom.xml b/blade-oauth2/pom.xml deleted file mode 100644 index d5dccffb5..000000000 --- a/blade-oauth2/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - blade-oauth2 - 1.0.3 - blade-oauth2 - https://github.com/biezhi/blade/tree/master/blade-oauth2 - - - - com.bladejava - blade-core - ${blade.version} - - - - diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuth.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuth.java deleted file mode 100644 index 863bd282d..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/OAuth.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.blade.oauth2; - -import com.blade.oauth2.message.types.ParameterStyle; -import com.blade.oauth2.message.types.TokenType; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public final class OAuth { - - public static final class HttpMethod { - public static final String POST = "POST"; - public static final String GET = "GET"; - public static final String DELETE = "DELETE"; - public static final String PUT = "PUT"; - } - - public static final class HeaderType { - public static final String CONTENT_TYPE = "Content-Type"; - public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; - public static final String AUTHORIZATION = "Authorization"; - } - - public static final class WWWAuthHeader { - public static final String REALM = "realm"; - } - - public static final class ContentType { - public static final String URL_ENCODED = "application/x-www-form-urlencoded"; - public static final String JSON = "application/json"; - } - - public static final String OAUTH_RESPONSE_TYPE = "response_type"; - public static final String OAUTH_CLIENT_ID = "client_id"; - public static final String OAUTH_CLIENT_SECRET = "client_secret"; - public static final String OAUTH_REDIRECT_URI = "redirect_uri"; - public static final String OAUTH_USERNAME = "username"; - public static final String OAUTH_PASSWORD = "password"; - public static final String OAUTH_ASSERTION_TYPE = "assertion_type"; - public static final String OAUTH_ASSERTION = "assertion"; - public static final String OAUTH_SCOPE = "scope"; - public static final String OAUTH_STATE = "state"; - public static final String OAUTH_GRANT_TYPE = "grant_type"; - - public static final String OAUTH_HEADER_NAME = "Bearer"; - - //Authorization response params - public static final String OAUTH_CODE = "code"; - public static final String OAUTH_ACCESS_TOKEN = "access_token"; - public static final String OAUTH_EXPIRES_IN = "expires_in"; - public static final String OAUTH_REFRESH_TOKEN = "refresh_token"; - public static final String OAUTH_EXAMPLE_PARAMETER = "example_parameter"; - - public static final String OAUTH_TOKEN_TYPE = "token_type"; - - public static final String OAUTH_TOKEN = "oauth_token"; - - public static final String OAUTH_TOKEN_DRAFT_0 = "access_token"; - public static final String OAUTH_BEARER_TOKEN = "access_token"; - - public static final ParameterStyle DEFAULT_PARAMETER_STYLE = ParameterStyle.HEADER; - public static final TokenType DEFAULT_TOKEN_TYPE = TokenType.BEARER; - - public static final String OAUTH_VERSION_DIFFER = "oauth_signature_method"; -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthError.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthError.java deleted file mode 100644 index d385da27e..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthError.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.blade.oauth2; - -public abstract class OAuthError { - - //error response params - public static final String OAUTH_ERROR = "error"; - public static final String OAUTH_ERROR_DESCRIPTION = "error_description"; - public static final String OAUTH_ERROR_URI = "error_uri"; - - public static final class CodeResponse { - /** - * The request is missing a required parameter, includes an - unsupported parameter value, or is otherwise malformed. - */ - public static final String INVALID_REQUEST = "invalid_request"; - - /** - * The client is not authorized to request an authorization - code using this method. - */ - public static final String UNAUTHORIZED_CLIENT = "unauthorized_client"; - - /** - * The resource owner or authorization server denied the - request. - */ - public static final String ACCESS_DENIED = "access_denied"; - - /** - * The authorization server does not support obtaining an - authorization code using this method. - */ - public static final String UNSUPPORTED_RESPONSE_TYPE = "unsupported_response_type"; - - /** - * The requested scope is invalid, unknown, or malformed. - */ - public static final String INVALID_SCOPE = "invalid_scope"; - - /** - * The authorization server encountered an unexpected - condition which prevented it from fulfilling the request. - */ - public static final String SERVER_ERROR = "server_error"; - - /** - * The authorization server is currently unable to handle - the request due to a temporary overloading or maintenance - of the server. - */ - public static final String TEMPORARILY_UNAVAILABLE = "temporarily_unavailable"; - - } - - public static final class TokenResponse { - /** - The request is missing a required parameter, includes an - unsupported parameter value, repeats a parameter, - includes multiple credentials, utilizes more than one - mechanism for authenticating the client, or is otherwise - malformed. - */ - public static final String INVALID_REQUEST = "invalid_request"; - /** - Client authentication failed (e.g. unknown client, no - client authentication included, or unsupported - authentication method). The authorization server MAY - return an HTTP 401 (Unauthorized) status code to indicate - which HTTP authentication schemes are supported. If the - client attempted to authenticate via the "Authorization" - request header field, the authorization server MUST - respond with an HTTP 401 (Unauthorized) status code, and - include the "WWW-Authenticate" response header field - matching the authentication scheme used by the client. - */ - public static final String INVALID_CLIENT = "invalid_client"; - - /** - The provided authorization grant (e.g. authorization - code, resource owner credentials, client credentials) is - invalid, expired, revoked, does not match the redirection - URI used in the authorization request, or was issued to - another client. - */ - public static final String INVALID_GRANT = "invalid_grant"; - - /** - The authenticated client is not authorized to use this - authorization grant type. - */ - public static final String UNAUTHORIZED_CLIENT = "unauthorized_client"; - - /** - The authorization grant type is not supported by the - authorization server. - */ - public static final String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type"; - - /** - * The requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner. - */ - public static final String INVALID_SCOPE = "invalid_scope"; - } - - public static final class ResourceResponse { - /** - The request is missing a required parameter, includes an - unsupported parameter value, repeats a parameter, - includes multiple credentials, utilizes more than one - mechanism for authenticating the client, or is otherwise - malformed. - */ - public static final String INVALID_REQUEST = "invalid_request"; - - - public static final String EXPIRED_TOKEN = "expired_token"; - - /** - * The request requires higher privileges than provided by the - * access token. - */ - public static final String INSUFFICIENT_SCOPE = "insufficient_scope"; - - /** - * The access token provided is expired, revoked, malformed, or - * invalid for other reasons. - */ - public static final String INVALID_TOKEN = "invalid_token"; - } - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java deleted file mode 100644 index a75a4c519..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthRequest.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * - */ -package com.blade.oauth2; - -import com.blade.oauth2.base.request.OAuthBaseRequest; -import com.blade.oauth2.base.validator.OAuthValidator; -import com.blade.oauth2.exception.OAuthProblemException; -import com.blade.oauth2.kit.OAuthKit; -import com.blade.oauth2.message.types.ResponseType; -import com.blade.oauth2.validator.AuthorizationValidator; -import com.blade.oauth2.validator.ImplicitCodeValidator; -import com.blade.web.http.Request; - -import blade.kit.StringKit; -import blade.kit.reflect.ReflectKit; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class OAuthRequest extends OAuthBaseRequest { - - public OAuthRequest(Request request) - throws OAuthProblemException { - super(request); - } - - @Override - protected OAuthValidator initValidator() throws OAuthProblemException { - // end user authorization validators - validators.put(ResponseType.CODE.toString(), AuthorizationValidator.class); - validators.put(ResponseType.TOKEN.toString(), ImplicitCodeValidator.class); - final String requestTypeValue = getParam(OAuth.OAUTH_RESPONSE_TYPE); - if (StringKit.isBlank(requestTypeValue)) { - throw OAuthKit.handleOAuthProblemException("Missing response_type parameter value"); - } - final Class> clazz = validators - .get(requestTypeValue); - if (clazz == null) { - throw OAuthKit.handleOAuthProblemException("Invalid response_type parameter value"); - } - return ReflectKit.newBean(clazz); - } - - public String getResponseType() { - return getParam(OAuth.OAUTH_RESPONSE_TYPE); - } - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java b/blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java deleted file mode 100644 index 42573497b..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/OAuthResponse.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.blade.oauth2; - -import java.util.HashMap; -import java.util.Map; - -import blade.kit.StringKit; - -import com.blade.oauth2.exception.OAuthProblemException; -import com.blade.oauth2.message.OAuthMessage; -import com.blade.oauth2.parameters.JSONBodyParametersApplier; -import com.blade.web.http.HttpStatus; -import com.blade.web.http.Request; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class OAuthResponse implements OAuthMessage { - - protected int responseStatus; - protected String uri; - protected String body; - - protected Map headers = new HashMap(); - - protected OAuthResponse(String uri, int responseStatus) { - this.uri = uri; - this.responseStatus = responseStatus; - } - - public static OAuthResponseBuilder status(int code) { - return new OAuthResponseBuilder(code); - } - - public static OAuthErrorResponseBuilder errorResponse(int code, Request request) { - return new OAuthErrorResponseBuilder(code, request); - } - - public static OAuthErrorResponseBuilder errorUnAuthResponse(Request request) { - OAuthErrorResponseBuilder errorRep = new OAuthErrorResponseBuilder(HttpStatus.UNAUTHORIZED, request); - errorRep.setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT); - return errorRep; - } - - public static OAuthErrorResponseBuilder errorBadReqResponse(Request request) { - return new OAuthErrorResponseBuilder(HttpStatus.BAD_REQUEST, request); - } - - @Override - public String getLocationUri() { - return uri; - } - - @Override - public void setLocationUri(String uri) { - this.uri = uri; - } - - @Override - public String getBody() { - return body; - } - - @Override - public void setBody(String body) { - this.body = body; - } - - @Override - public String getHeader(String name) { - return headers.get(name); - } - - @Override - public Map getHeaders() { - return headers; - } - - @Override - public void setHeaders(Map headers) { - this.headers = headers; - } - - public int getResponseStatus() { - return responseStatus; - } - - @Override - public void addHeader(String name, String header) { - headers.put(name, header); - } - - public static class OAuthResponseBuilder { - - protected JSONBodyParametersApplier applier; - protected Map parameters = new HashMap(); - protected int responseCode; - protected String location; - - public OAuthResponseBuilder(int responseCode) { - this.responseCode = responseCode; - } - - public OAuthResponseBuilder location(String location) { - this.location = location; - return this; - } - - public OAuthResponseBuilder setScope(String value) { - this.parameters.put(OAuth.OAUTH_SCOPE, value); - return this; - } - - public OAuthResponseBuilder setParam(String key, String value) { - this.parameters.put(key, value); - return this; - } - - public OAuthResponse buildJSONMessage() { - OAuthResponse msg = new OAuthResponse(location, responseCode); - this.applier = new JSONBodyParametersApplier(); - return (OAuthResponse)applier.applyOAuthParameters(msg, parameters); - } - - } - - public static class OAuthErrorResponseBuilder extends OAuthResponseBuilder { - - public OAuthErrorResponseBuilder(int responseCode, Request request) { - super(responseCode); - - String state = request.query(OAuth.OAUTH_STATE); - if (StringKit.isNotBlank(state)){ - this.setState(state); - }else{ - this.setState(null); - } - - String errorUri = request.query(OAuthError.OAUTH_ERROR_URI); - if (StringKit.isNotBlank(errorUri)) { - this.setErrorUri(errorUri); - } - } - - public OAuthErrorResponseBuilder error(OAuthProblemException ex) { - this.parameters.put(OAuthError.OAUTH_ERROR, ex.getError()); - this.parameters.put(OAuthError.OAUTH_ERROR_DESCRIPTION, ex.getDescription()); - return this; - } - - public OAuthErrorResponseBuilder setError(String error) { - this.parameters.put(OAuthError.OAUTH_ERROR, error); - return this; - } - - public OAuthErrorResponseBuilder setErrorDescription(String desc) { - this.parameters.put(OAuthError.OAUTH_ERROR_DESCRIPTION, desc); - return this; - } - - public OAuthErrorResponseBuilder setErrorUri(String state) { - this.parameters.put(OAuthError.OAUTH_ERROR_URI, state); - return this; - } - - public OAuthErrorResponseBuilder setState(String state) { - this.parameters.put(OAuth.OAUTH_STATE, state); - return this; - } - - public OAuthErrorResponseBuilder setRealm(String realm) { - this.parameters.put(OAuth.WWWAuthHeader.REALM, realm); - return this; - } - - public OAuthErrorResponseBuilder location(String location) { - this.location = location; - return this; - } - } - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java deleted file mode 100644 index c8c43fce6..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthBaseRequest.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * - */ - -package com.blade.oauth2.base.request; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.base.validator.OAuthValidator; -import com.blade.oauth2.exception.OAuthProblemException; -import com.blade.oauth2.kit.OAuthKit; -import com.blade.web.http.Request; - -/** - * The Abstract OAuth request for the Authorization server. - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public abstract class OAuthBaseRequest { - - protected Request request; - protected OAuthValidator validator; - - protected Map>> validators = - new HashMap>>(); - - public OAuthBaseRequest(Request request) throws OAuthProblemException { - this.request = request; - validate(); - } - - public OAuthBaseRequest() { - } - - protected void validate() throws OAuthProblemException { - validator = initValidator(); - validator.validateMethod(request); - validator.validateContentType(request); - validator.validateRequiredParameters(request); - validator.validateClientAuthenticationCredentials(request); - } - - protected abstract OAuthValidator initValidator() throws OAuthProblemException; - - public String getParam(String name) { - return request.query(name); - } - - public String getClientId() { - String[] creds = OAuthKit.decodeClientAuthenticationHeader(request.header(OAuth.HeaderType.AUTHORIZATION)); - if (creds != null) { - return creds[0]; - } - return getParam(OAuth.OAUTH_CLIENT_ID); - } - - public String getRedirectURI() { - return getParam(OAuth.OAUTH_REDIRECT_URI); - } - - public String getClientSecret() { - String[] creds = OAuthKit.decodeClientAuthenticationHeader(request.header(OAuth.HeaderType.AUTHORIZATION)); - if (creds != null) { - return creds[1]; - } - return getParam(OAuth.OAUTH_CLIENT_SECRET); - } - - /** - * - * @return - */ - public boolean isClientAuthHeaderUsed() { - return OAuthKit.decodeClientAuthenticationHeader(request.header(OAuth.HeaderType.AUTHORIZATION)) != null; - } - - public String getState() { - return getParam(OAuth.OAUTH_STATE); - } - - public Set getScopes() { - String scopes = getParam(OAuth.OAUTH_SCOPE); - return OAuthKit.decodeScopes(scopes); - } - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java deleted file mode 100644 index f5f8b720b..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/request/OAuthTokenBaseRequest.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * - */ - -package com.blade.oauth2.base.request; - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.base.validator.OAuthValidator; -import com.blade.oauth2.exception.OAuthProblemException; -import com.blade.oauth2.kit.OAuthKit; -import com.blade.web.http.Request; - -import blade.kit.StringKit; -import blade.kit.reflect.ReflectKit; - -/** - * Abstract OAuth Token request class - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public abstract class OAuthTokenBaseRequest extends OAuthBaseRequest { - - protected OAuthTokenBaseRequest(Request request) - throws OAuthProblemException { - super(request); - } - - protected OAuthValidator initValidator() - throws OAuthProblemException { - final String requestTypeValue = getParam(OAuth.OAUTH_GRANT_TYPE); - if (StringKit.isBlank(requestTypeValue)) { - throw OAuthKit - .handleOAuthProblemException("Missing grant_type parameter value"); - } - final Class> clazz = validators.get(requestTypeValue); - if (clazz == null) { - throw OAuthKit - .handleOAuthProblemException("Invalid grant_type parameter value"); - } - return ReflectKit.newBean(clazz); - } - - public String getPassword() { - return getParam(OAuth.OAUTH_PASSWORD); - } - - public String getUsername() { - return getParam(OAuth.OAUTH_USERNAME); - } - - public String getRefreshToken() { - return getParam(OAuth.OAUTH_REFRESH_TOKEN); - } - - /** - * response_type : code, 中获得的code - * @return - */ - public String getCode() { - return getParam(OAuth.OAUTH_CODE); - } - - public String getGrantType() { - return getParam(OAuth.OAUTH_GRANT_TYPE); - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java deleted file mode 100644 index c2b75f417..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthBaseValidator.java +++ /dev/null @@ -1,135 +0,0 @@ -/** - * - */ -package com.blade.oauth2.base.validator; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import blade.kit.StringKit; - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.exception.OAuthProblemException; -import com.blade.oauth2.kit.OAuthKit; -import com.blade.web.http.Request; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - * @param - */ -public abstract class OAuthBaseValidator implements OAuthValidator { - - protected List requiredParams = new ArrayList(); - protected Map optionalParams = new HashMap(); - protected List notAllowedParams = new ArrayList(); - protected boolean enforceClientAuthentication = false; - - @Override - public void validateMethod(T request) throws OAuthProblemException { - if (!request.method().equals(OAuth.HttpMethod.POST)) { - throw OAuthKit.handleOAuthProblemException("Method not set to POST."); - } - } - - @Override - public void validateContentType(T request) throws OAuthProblemException { - String contentType = request.contentType(); - final String expectedContentType = OAuth.ContentType.URL_ENCODED; - if (!OAuthKit.hasContentType(contentType, expectedContentType)) { - throw OAuthKit.handleBadContentTypeException(expectedContentType); - } - } - - @Override - public void validateRequiredParameters(T request) throws OAuthProblemException { - final Set missingParameters = new HashSet(); - for (String requiredParam : requiredParams) { - String val = request.query(requiredParam); - if (StringKit.isNotBlank(val)) { - missingParameters.add(requiredParam); - } - } - if (!missingParameters.isEmpty()) { - throw OAuthKit.handleMissingParameters(missingParameters); - } - } - - @Override - public void validateOptionalParameters(T request) throws OAuthProblemException { - final Set missingParameters = new HashSet(); - - for (Map.Entry requiredParam : optionalParams.entrySet()) { - final String paramName = requiredParam.getKey(); - String val = request.query(paramName); - if (StringKit.isNotBlank(val)) { - String[] dependentParams = requiredParam.getValue(); - if (null!=dependentParams&&dependentParams.length > 0) { - for (String dependentParam : dependentParams) { - val = request.query(dependentParam); - if (StringKit.isBlank(val)) { - missingParameters.add(dependentParam); - } - } - } - } - } - - if (!missingParameters.isEmpty()) { - throw OAuthKit.handleMissingParameters(missingParameters); - } - } - - @Override - public void validateNotAllowedParameters(T request) throws OAuthProblemException { - List notAllowedParameters = new ArrayList(); - for (String requiredParam : notAllowedParams) { - String val = request.query(requiredParam); - if (StringKit.isNotBlank(val)) { - notAllowedParameters.add(requiredParam); - } - } - if (!notAllowedParameters.isEmpty()) { - throw OAuthKit.handleNotAllowedParametersOAuthException(notAllowedParameters); - } - } - - @Override - public void validateClientAuthenticationCredentials(T request) throws OAuthProblemException { - if (enforceClientAuthentication) { - Set missingParameters = new HashSet(); - String clientAuthHeader = request.header(OAuth.HeaderType.AUTHORIZATION); - String[] clientCreds = OAuthKit.decodeClientAuthenticationHeader(clientAuthHeader); - - // Only fallback to params if the auth header is not correct. Don't allow a mix of auth header vs params - if (clientCreds == null || StringKit.isBlank(clientCreds[0]) || StringKit.isBlank(clientCreds[1])) { - - if (StringKit.isBlank(request.query(OAuth.OAUTH_CLIENT_ID))) { - missingParameters.add(OAuth.OAUTH_CLIENT_ID); - } - if (StringKit.isBlank(request.query(OAuth.OAUTH_CLIENT_SECRET))) { - missingParameters.add(OAuth.OAUTH_CLIENT_SECRET); - } - } - - if (!missingParameters.isEmpty()) { - throw OAuthKit.handleMissingParameters(missingParameters); - } - } - } - - @Override - public void performAllValidations(T request) throws OAuthProblemException { - this.validateContentType(request); - this.validateMethod(request); - this.validateRequiredParameters(request); - this.validateOptionalParameters(request); - this.validateNotAllowedParameters(request); - this.validateClientAuthenticationCredentials(request); - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java deleted file mode 100644 index c875ec4ce..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/base/validator/OAuthValidator.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - */ -package com.blade.oauth2.base.validator; - -import com.blade.oauth2.exception.OAuthProblemException; -import com.blade.web.http.Request; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - * @param - */ -public interface OAuthValidator { - - public void validateMethod(T request) throws OAuthProblemException; - - public void validateContentType(T request) throws OAuthProblemException; - - public void validateRequiredParameters(T request) throws OAuthProblemException; - - public void validateOptionalParameters(T request) throws OAuthProblemException; - - public void validateNotAllowedParameters(T request) throws OAuthProblemException; - - public void validateClientAuthenticationCredentials(T request) throws OAuthProblemException; - - public void performAllValidations(T request) throws OAuthProblemException; - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/exception/OAuthProblemException.java b/blade-oauth2/src/main/java/com/blade/oauth2/exception/OAuthProblemException.java deleted file mode 100644 index e80d72146..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/exception/OAuthProblemException.java +++ /dev/null @@ -1,97 +0,0 @@ - -package com.blade.oauth2.exception; - -import java.util.HashMap; -import java.util.Map; - -import blade.kit.StringKit; - -public class OAuthProblemException extends IllegalArgumentException { - - /** - * - */ - private static final long serialVersionUID = 1536483571040822380L; - private String error; - private String description; - - private int responseStatus; - - private Map parameters = new HashMap(); - - protected OAuthProblemException(String error) { - this(error, ""); - } - - protected OAuthProblemException(String error, String description) { - super(error + " " + description); - this.description = description; - this.error = error; - } - - public static OAuthProblemException error(String error) { - return new OAuthProblemException(error); - } - - public static OAuthProblemException error(String error, String description) { - return new OAuthProblemException(error, description); - } - - public OAuthProblemException description(String description) { - this.description = description; - return this; - } - - public OAuthProblemException responseStatus(int responseStatus) { - this.responseStatus = responseStatus; - return this; - } - - public OAuthProblemException setParameter(String name, String value) { - parameters.put(name, value); - return this; - } - - public String getError() { - return error; - } - - public String getDescription() { - return description; - } - - public int getResponseStatus() { - return responseStatus == 0 ? 400 : responseStatus; - } - - public String get(String name) { - return parameters.get(name); - } - - public Map getParameters() { - return parameters; - } - - @Override - public String getMessage() { - StringBuilder b = new StringBuilder(); - if (StringKit.isNotBlank(error)) { - b.append(error); - } - - if (StringKit.isNotBlank(description)) { - b.append(", ").append(description); - } - return b.toString(); - } - - @Override - public String toString() { - return "OAuthProblemException{" + - "error='" + error + '\'' + - ", description='" + description + '\'' + - ", responseStatus=" + responseStatus + - ", parameters=" + parameters + - '}'; - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/MD5Generator.java b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/MD5Generator.java deleted file mode 100644 index b777c67ed..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/MD5Generator.java +++ /dev/null @@ -1,15 +0,0 @@ -/** - * - */ -package com.blade.oauth2.issuer; - -import blade.kit.EncrypKit; - -public class MD5Generator extends ValueGenerator { - - @Override - public String generateValue(String param) { - return EncrypKit.md5(param); - } - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuer.java b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuer.java deleted file mode 100644 index 62fac8e4f..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuer.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * - */ - -package com.blade.oauth2.issuer; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public interface OAuthIssuer { - - public String accessToken(); - - public String authorizationCode(); - - public String refreshToken(); -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuerKit.java b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuerKit.java deleted file mode 100644 index ee3284352..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/OAuthIssuerKit.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * - */ - -package com.blade.oauth2.issuer; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class OAuthIssuerKit implements OAuthIssuer { - - private ValueGenerator vg; - - public OAuthIssuerKit(ValueGenerator vg) { - this.vg = vg; - } - - public String accessToken() { - return vg.generateValue(); - } - - public String refreshToken() { - return vg.generateValue(); - } - - public String authorizationCode() { - return vg.generateValue(); - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/UUIDValueGenerator.java b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/UUIDValueGenerator.java deleted file mode 100644 index f66fdc1cd..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/UUIDValueGenerator.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * - */ - -package com.blade.oauth2.issuer; - -import java.util.UUID; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class UUIDValueGenerator extends ValueGenerator { - - @Override - public String generateValue(String param) { - return UUID.fromString(UUID.nameUUIDFromBytes(param.getBytes()).toString()).toString(); - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/ValueGenerator.java b/blade-oauth2/src/main/java/com/blade/oauth2/issuer/ValueGenerator.java deleted file mode 100644 index 29be7c77c..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/issuer/ValueGenerator.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * - */ -package com.blade.oauth2.issuer; - -import java.util.UUID; - - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public abstract class ValueGenerator { - - public String generateValue() { - return generateValue(UUID.randomUUID().toString()); - } - - public abstract String generateValue(String param); -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java b/blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java deleted file mode 100644 index 7e5e1df56..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/kit/OAuthKit.java +++ /dev/null @@ -1,408 +0,0 @@ -/** - * - */ - -package com.blade.oauth2.kit; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import blade.kit.Base64; -import blade.kit.StringKit; - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.OAuthError; -import com.blade.oauth2.exception.OAuthProblemException; -import com.blade.web.http.Request; - -/** - * Common OAuth Utils class. - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public final class OAuthKit { - - private static final String ENCODING = "UTF-8"; - private static final String PARAMETER_SEPARATOR = "&"; - private static final String NAME_VALUE_SEPARATOR = "="; - - public static final String AUTH_SCHEME = OAuth.OAUTH_HEADER_NAME; - - private static final Pattern OAUTH_HEADER = Pattern.compile("\\s*(\\w*)\\s+(.*)"); - private static final Pattern NVP = Pattern.compile("(\\S*)\\s*\\=\\s*\"([^\"]*)\""); - - public static final String MULTIPART = "multipart/"; - - private static final String DEFAULT_CONTENT_CHARSET = ENCODING; - - /** - * Translates parameters into application/x-www-form-urlencoded String - * - * @param parameters parameters to encode - * @param encoding The name of a supported - * character - * encoding. - * @return Translated string - */ - public static String format( - final Collection> parameters, - final String encoding) { - final StringBuilder result = new StringBuilder(); - for (final Map.Entry parameter : parameters) { - String value = parameter.getValue() == null? null : String.valueOf(parameter.getValue()); - if (StringKit.isNotBlank(parameter.getKey()) - && StringKit.isNotBlank(value)) { - final String encodedName = encode(parameter.getKey(), encoding); - final String encodedValue = value != null ? encode(value, encoding) : ""; - if (result.length() > 0) { - result.append(PARAMETER_SEPARATOR); - } - result.append(encodedName); - result.append(NAME_VALUE_SEPARATOR); - result.append(encodedValue); - } - } - return result.toString(); - } - - private static String encode(final String content, final String encoding) { - try { - return URLEncoder.encode(content, - encoding != null ? encoding : "UTF-8"); - } catch (UnsupportedEncodingException problem) { - throw new IllegalArgumentException(problem); - } - } - - /** - * Read data from Input Stream and save it as a String. - * - * @param is InputStream to be read - * @return String that was read from the stream - */ - public static String saveStreamAsString(InputStream is) throws IOException { - return toString(is, ENCODING); - } - - /** - * Get the entity content as a String, using the provided default character set - * if none is found in the entity. - * If defaultCharset is null, the default "UTF-8" is used. - * - * @param is input stream to be saved as string - * @param defaultCharset character set to be applied if none found in the entity - * @return the entity content as a String - * @throws IllegalArgumentException if entity is null or if content length > Integer.MAX_VALUE - * @throws IOException if an error occurs reading the input stream - */ - public static String toString( - final InputStream is, final String defaultCharset) throws IOException { - if (is == null) { - throw new IllegalArgumentException("InputStream may not be null"); - } - - String charset = defaultCharset; - if (charset == null) { - charset = DEFAULT_CONTENT_CHARSET; - } - Reader reader = new InputStreamReader(is, charset); - StringBuilder sb = new StringBuilder(); - int l; - try { - char[] tmp = new char[4096]; - while ((l = reader.read(tmp)) != -1) { - sb.append(tmp, 0, l); - } - } finally { - reader.close(); - } - return sb.toString(); - } - - /** - * Creates invalid_request exception with given message - * - * @param message error message - * @return OAuthException - */ - public static OAuthProblemException handleOAuthProblemException(String message) { - return OAuthProblemException.error(OAuthError.TokenResponse.INVALID_REQUEST) - .description(message); - } - - /** - * Creates OAuthProblemException that contains set of missing oauth parameters - * - * @param missingParams missing oauth parameters - * @return OAuthProblemException with user friendly message about missing oauth parameters - */ - public static OAuthProblemException handleMissingParameters(Set missingParams) { - StringBuffer sb = new StringBuffer("Missing parameters: "); - if (!OAuthKit.isEmpty(missingParams)) { - for (String missingParam : missingParams) { - sb.append(missingParam).append(" "); - } - } - return handleOAuthProblemException(sb.toString().trim()); - } - - public static OAuthProblemException handleBadContentTypeException(String expectedContentType) { - StringBuilder errorMsg = new StringBuilder("Bad request content type. Expecting: ").append( - expectedContentType); - return handleOAuthProblemException(errorMsg.toString()); - } - - public static OAuthProblemException handleNotAllowedParametersOAuthException( - List notAllowedParams) { - StringBuffer sb = new StringBuffer("Not allowed parameters: "); - if (notAllowedParams != null) { - for (String notAllowed : notAllowedParams) { - sb.append(notAllowed).append(" "); - } - } - return handleOAuthProblemException(sb.toString().trim()); - } - - /** - * Parse a form-urlencoded document. - */ - public static Map decodeForm(String form) { - Map params = new HashMap(); - if (StringKit.isNotBlank(form)) { - for (String nvp : form.split("\\&")) { - int equals = nvp.indexOf('='); - String name; - String value; - if (equals < 0) { - name = decodePercent(nvp); - value = null; - } else { - name = decodePercent(nvp.substring(0, equals)); - value = decodePercent(nvp.substring(equals + 1)); - } - params.put(name, value); - } - } - return params; - } - - /** - * Return true if the given Content-Type header means FORM_ENCODED. - */ - public static boolean isFormEncoded(String contentType) { - if (contentType == null) { - return false; - } - int semi = contentType.indexOf(";"); - if (semi >= 0) { - contentType = contentType.substring(0, semi); - } - return OAuth.ContentType.URL_ENCODED.equalsIgnoreCase(contentType.trim()); - } - - public static String decodePercent(String s) { - try { - return URLDecoder.decode(s, ENCODING); - // This implements http://oauth.pbwiki.com/FlexibleDecoding - } catch (java.io.UnsupportedEncodingException wow) { - throw new RuntimeException(wow.getMessage(), wow); - } - } - - private static boolean isEmpty(Set missingParams) { - if (missingParams == null || missingParams.size() == 0) { - return true; - } - return false; - } - - public static String getAuthHeaderField(String authHeader) { - - if (authHeader != null) { - Matcher m = OAUTH_HEADER.matcher(authHeader); - if (m.matches()) { - if (AUTH_SCHEME.equalsIgnoreCase(m.group(1))) { - return m.group(2); - } - } - } - return null; - } - - public static Map decodeOAuthHeader(String header) { - Map headerValues = new HashMap(); - if (header != null) { - Matcher m = OAUTH_HEADER.matcher(header); - if (m.matches()) { - if (AUTH_SCHEME.equalsIgnoreCase(m.group(1))) { - for (String nvp : m.group(2).split("\\s*,\\s*")) { - m = NVP.matcher(nvp); - if (m.matches()) { - String name = decodePercent(m.group(1)); - String value = decodePercent(m.group(2)); - headerValues.put(name, value); - } - } - } - } - } - return headerValues; - } - - // todo: implement method to decode header form (with no challenge) - - /** - * Decodes the Basic Authentication header into a username and password - * - * @param authenticationHeader {@link String} containing the encoded header value. - * e.g. "Basic dXNlcm5hbWU6cGFzc3dvcmQ=" - * @return a {@link String[]} if the header could be decoded into a non null username and password or null. - * @throws UnsupportedEncodingException - */ - public static String[] decodeClientAuthenticationHeader(String authenticationHeader) { - if (authenticationHeader == null || "".equals(authenticationHeader)) { - return null; - } - String[] tokens = authenticationHeader.split(" "); - if (tokens == null) { - return null; - } - if (tokens[0] != null && !"".equals(tokens[0])) { - String authType = tokens[0]; - if (!authType.equalsIgnoreCase("basic")) { - return null; - } - } - try { - if (tokens[1] != null && !"".equals(tokens[1])) { - String encodedCreds = tokens[1]; - String decodedCreds = new String(Base64.decoder(encodedCreds)); - if (decodedCreds.contains(":") && decodedCreds.split(":").length == 2) { - String[] creds = decodedCreds.split(":"); - if (StringKit.isNotBlank(creds[0]) && StringKit.isNotBlank(creds[1])) { - return decodedCreds.split(":"); - } - } - } - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return null; - } - - /** - * Construct a WWW-Authenticate header - */ - public static String encodeOAuthHeader(Map entries) { - StringBuffer sb = new StringBuffer(); - sb.append(OAuth.OAUTH_HEADER_NAME).append(" "); - for (Map.Entry entry : entries.entrySet()) { - String value = entry.getValue() == null? null: String.valueOf(entry.getValue()); - if (StringKit.isNotBlank(entry.getKey()) && StringKit.isNotBlank(value)) { - sb.append(entry.getKey()); - sb.append("=\""); - sb.append(value); - sb.append("\","); - } - } - - return sb.substring(0, sb.length() - 1); - } - - /** - * Construct an Authorization Bearer header - */ - public static String encodeAuthorizationBearerHeader(Map entries) { - StringBuffer sb = new StringBuffer(); - sb.append(OAuth.OAUTH_HEADER_NAME).append(" "); - for (Map.Entry entry : entries.entrySet()) { - String value = entry.getValue() == null? null: String.valueOf(entry.getValue()); - if (StringKit.isNotBlank(entry.getKey()) && StringKit.isNotBlank(value)) { - sb.append(value); - } - } - - return sb.toString(); - } - - public static String getAuthzMethod(String header) { - if (header != null) { - Matcher m = OAUTH_HEADER.matcher(header); - if (m.matches()) { - return m.group(1); - - } - } - return null; - } - - public static Set decodeScopes(String s) { - Set scopes = new HashSet(); - if (StringKit.isNotBlank(s)) { - StringTokenizer tokenizer = new StringTokenizer(s, " "); - - while (tokenizer.hasMoreElements()) { - scopes.add(tokenizer.nextToken()); - } - } - return scopes; - - } - - public static String encodeScopes(Set s) { - StringBuffer scopes = new StringBuffer(); - for (String scope : s) { - scopes.append(scope).append(" "); - } - return scopes.toString().trim(); - - } - - public static boolean isMultipart(Request request) { - - if (!"post".equals(request.method().toLowerCase())) { - return false; - } - String contentType = request.contentType(); - if (contentType == null) { - return false; - } - if (contentType.toLowerCase().startsWith(MULTIPART)) { - return true; - } - return false; - } - - - public static boolean hasContentType(String requestContentType, String requiredContentType) { - if (StringKit.isNotBlank(requiredContentType) || StringKit.isNotBlank(requestContentType)) { - return false; - } - StringTokenizer tokenizer = new StringTokenizer(requestContentType, ";"); - while (tokenizer.hasMoreTokens()) { - if (requiredContentType.equals(tokenizer.nextToken())) { - return true; - } - } - - return false; - } - -} - - diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/message/OAuthMessage.java b/blade-oauth2/src/main/java/com/blade/oauth2/message/OAuthMessage.java deleted file mode 100644 index 21b9097ed..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/message/OAuthMessage.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * - */ -package com.blade.oauth2.message; - -import java.util.Map; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public interface OAuthMessage { - - String getLocationUri(); - - void setLocationUri(String uri); - - String getBody(); - - void setBody(String body); - - String getHeader(String name); - - void addHeader(String name, String header); - - Map getHeaders(); - - void setHeaders(Map headers); - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/GrantType.java b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/GrantType.java deleted file mode 100644 index 961041f0d..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/GrantType.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * - */ -package com.blade.oauth2.message.types; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public enum GrantType { - - // NONE("none"), - AUTHORIZATION_CODE("authorization_code"), - PASSWORD("password"), - REFRESH_TOKEN("refresh_token"), - CLIENT_CREDENTIALS("client_credentials"); - - private String grantType; - - GrantType(String grantType) { - this.grantType = grantType; - } - - @Override - public String toString() { - return grantType; - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ParameterStyle.java b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ParameterStyle.java deleted file mode 100644 index 368b89065..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ParameterStyle.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * - */ -package com.blade.oauth2.message.types; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public enum ParameterStyle { - - BODY("body"), - QUERY("query"), - HEADER("header"); - - private String parameterStyle; - - ParameterStyle(String parameterStyle) { - this.parameterStyle = parameterStyle; - } - - @Override - public String toString() { - return parameterStyle; - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ResponseType.java b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ResponseType.java deleted file mode 100644 index fc119ec60..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/ResponseType.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - */ -package com.blade.oauth2.message.types; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public enum ResponseType { - - CODE("code"), - TOKEN("token"); - - private String code; - - ResponseType(String code) { - this.code = code; - } - - @Override - public String toString() { - return code; - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/TokenType.java b/blade-oauth2/src/main/java/com/blade/oauth2/message/types/TokenType.java deleted file mode 100644 index 5c3d1937c..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/message/types/TokenType.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * - */ -package com.blade.oauth2.message.types; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public enum TokenType { - - BEARER("Bearer"), - MAC("MAC"); - - private String tokenType; - - TokenType(String grantType) { - this.tokenType = grantType; - } - - @Override - public String toString() { - return tokenType; - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java b/blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java deleted file mode 100644 index ddfef8fb6..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/parameters/JSONBodyParametersApplier.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * - */ - -package com.blade.oauth2.parameters; - -import java.util.Map; - -import com.blade.oauth2.message.OAuthMessage; - -import blade.kit.json.JSONHelper; - -public class JSONBodyParametersApplier { - - public OAuthMessage applyOAuthParameters(OAuthMessage message, Map params) { - String json = JSONHelper.mapAsJsonObject(params).toString(); - message.setBody(json); - return message; - } - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java b/blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java deleted file mode 100644 index 3a1e2a180..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/request/OAuthGrantRequest.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * - */ - -package com.blade.oauth2.request; - -import com.blade.oauth2.base.request.OAuthTokenBaseRequest; -import com.blade.oauth2.base.validator.OAuthValidator; -import com.blade.oauth2.exception.OAuthProblemException; -import com.blade.oauth2.message.types.GrantType; -import com.blade.oauth2.validator.AuthorizationCodeValidator; -import com.blade.oauth2.validator.ClientCredentialValidator; -import com.blade.oauth2.validator.PasswordCredentialValidator; -import com.blade.oauth2.validator.RefreshTokenValidator; -import com.blade.web.http.Request; - - -/** - * The Default OAuth Authorization Server class that validates whether a given HttpServletRequest is a valid - * OAuth Token request. - *

- * IMPORTANT: This OAuthTokenRequest assumes that a token request requires client authentication. - * Please see section 3.2.1 of the OAuth Specification: http://tools.ietf.org/html/rfc6749#section-3.2.1 - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class OAuthGrantRequest extends OAuthTokenBaseRequest { - - /** - * Create an OAuth Token request from a given HttpSerlvetRequest - * - * @param request the HttpServletRequest that is validated and transformed into the OAuth Token Request - * @throws OAuthProblemException if the request was not a valid Token request this exception is thrown. - */ - public OAuthGrantRequest(Request request) throws OAuthProblemException { - super(request); - } - - @Override - protected OAuthValidator initValidator() throws OAuthProblemException { - validators.put(GrantType.PASSWORD.toString(), PasswordCredentialValidator.class); - validators.put(GrantType.CLIENT_CREDENTIALS.toString(), ClientCredentialValidator.class); - validators.put(GrantType.AUTHORIZATION_CODE.toString(), AuthorizationCodeValidator.class); - validators.put(GrantType.REFRESH_TOKEN.toString(), RefreshTokenValidator.class); - return super.initValidator(); - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/request/RequestType.java b/blade-oauth2/src/main/java/com/blade/oauth2/request/RequestType.java deleted file mode 100644 index 5b582ea55..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/request/RequestType.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * - */ -package com.blade.oauth2.request; - -/** - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public enum RequestType { - - // link OAuthGrantRequst - GRANT_REQUEST("grant_request"), - // link OAuthRequest - CODE_TOKEN_REQUEST("code_token_request"); - - private String parameterStyle; - - RequestType(String parameterStyle) { - this.parameterStyle = parameterStyle; - } - - @Override - public String toString() { - return parameterStyle; - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java b/blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java deleted file mode 100644 index b166502aa..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/response/OAuthASResponse.java +++ /dev/null @@ -1,136 +0,0 @@ -/** - * - */ - -package com.blade.oauth2.response; - - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.OAuthResponse; -import com.blade.oauth2.message.types.TokenType; -import com.blade.web.http.HttpStatus; -import com.blade.web.http.Request; - -/** - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class OAuthASResponse extends OAuthResponse { - - protected OAuthASResponse(String uri, int responseStatus) { - super(uri, responseStatus); - } - - public static OAuthAuthorizationResponseBuilder authorizationResponse(Request request) { - return new OAuthAuthorizationResponseBuilder(request, HttpStatus.OK); - } - - public static OAuthAuthorizationResponseBuilder authorizationResponse(Request request,int code) { - return new OAuthAuthorizationResponseBuilder(request,code); - } - - public static OAuthTokenResponseBuilder tokenResponse() { - return new OAuthTokenResponseBuilder(HttpStatus.OK); - } - - public static OAuthTokenResponseBuilder tokenResponse(int code) { - return new OAuthTokenResponseBuilder(code); - } - - public static class OAuthAuthorizationResponseBuilder extends OAuthResponseBuilder { - - public OAuthAuthorizationResponseBuilder(Request request,int responseCode) { - super(responseCode); - //AMBER-45 - String state = request.query(OAuth.OAUTH_STATE); - if (state!=null){ - this.setState(state); - } - } - - OAuthAuthorizationResponseBuilder setState(String state) { - this.parameters.put(OAuth.OAUTH_STATE, state); - return this; - } - - public OAuthAuthorizationResponseBuilder setCode(String code) { - this.parameters.put(OAuth.OAUTH_CODE, code); - return this; - } - - public OAuthAuthorizationResponseBuilder setAccessToken(String token) { - this.parameters.put(OAuth.OAUTH_ACCESS_TOKEN, token); - return this; - } - - public OAuthAuthorizationResponseBuilder setExpiresIn(String expiresIn) { - this.parameters.put(OAuth.OAUTH_EXPIRES_IN, expiresIn == null ? null : Long.valueOf(expiresIn)); - return this; - } - - public OAuthAuthorizationResponseBuilder setExpiresIn(Long expiresIn) { - this.parameters.put(OAuth.OAUTH_EXPIRES_IN, expiresIn); - return this; - } - - public OAuthAuthorizationResponseBuilder location(String location) { - this.location = location; - return this; - } - - public OAuthAuthorizationResponseBuilder setParam(String key, String value) { - this.parameters.put(key, value); - return this; - } - } - - - public static class OAuthTokenResponseBuilder extends OAuthResponseBuilder { - - public OAuthTokenResponseBuilder(int responseCode) { - super(responseCode); - this.setTokenType(TokenType.BEARER); - } - - public OAuthTokenResponseBuilder setAccessToken(String token) { - this.parameters.put(OAuth.OAUTH_ACCESS_TOKEN, token); - return this; - } - - public OAuthTokenResponseBuilder setExpiresIn(String expiresIn) { - this.parameters.put(OAuth.OAUTH_EXPIRES_IN, expiresIn == null ? null : Long.valueOf(expiresIn)); - return this; - } - - public OAuthTokenResponseBuilder setRefreshToken(String refreshToken) { - this.parameters.put(OAuth.OAUTH_REFRESH_TOKEN, refreshToken); - return this; - } - - public OAuthTokenResponseBuilder setTokenType(String tokenType) { - this.parameters.put(OAuth.OAUTH_TOKEN_TYPE, tokenType); - return this; - } - - public OAuthTokenResponseBuilder setTokenType(TokenType tokenType) { - return this.setTokenType(String.valueOf(tokenType)); - } - - public OAuthTokenResponseBuilder setExampleParamter(String exampleParamter) { - this.parameters.put(OAuth.OAUTH_EXAMPLE_PARAMETER, exampleParamter); - return this; - } - - public OAuthTokenResponseBuilder setParam(String key, String value) { - this.parameters.put(key, value); - return this; - } - - public OAuthTokenResponseBuilder location(String location) { - this.location = location; - return this; - } - } - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java deleted file mode 100644 index 848edf48f..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationCodeValidator.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * - */ -package com.blade.oauth2.validator; - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.base.validator.OAuthBaseValidator; -import com.blade.web.http.Request; - -/** - * Validator that checks for the required fields in an OAuth Token request with the Authorization Code grant type. - * This validator enforces client authentication either through basic authentication or body parameters. - * - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class AuthorizationCodeValidator extends OAuthBaseValidator { - - public AuthorizationCodeValidator() { - //Value MUST be set to "authorization_code". - requiredParams.add(OAuth.OAUTH_GRANT_TYPE); - requiredParams.add(OAuth.OAUTH_CODE); - requiredParams.add(OAuth.OAUTH_REDIRECT_URI); - requiredParams.add(OAuth.OAUTH_CLIENT_ID); - enforceClientAuthentication = true; - } - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java deleted file mode 100644 index 7bcb74ae6..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/AuthorizationValidator.java +++ /dev/null @@ -1,158 +0,0 @@ -/** - * http://www.rfcreader.com/#rfc6749_line1027 - * The authorization code grant type is used to obtain both access - tokens and refresh tokens and is optimized for confidential clients. - Since this is a redirection-based flow, the client must be capable of - interacting with the resource owner's user-agent (typically a web - browser) and capable of receiving incoming requests (via redirection) - from the authorization server. - - +----------+ - | Resource | - | Owner | - | | - +----------+ - ^ - | - (B) - +----|-----+ Client Identifier +---------------+ - | -+----(A)-- & Redirection URI ---->| | - | User- | | Authorization | - | Agent -+----(B)-- User authenticates --->| Server | - | | | | - | -+----(C)-- Authorization Code ---<| | - +-|----|---+ +---------------+ - | | ^ v - (A) (C) | | - | | | | - ^ v | | - +---------+ | | - | |>---(D)-- Authorization Code ---------' | - | Client | & Redirection URI | - | | | - | |<---(E)----- Access Token -------------------' - +---------+ (w/ Optional Refresh Token) - - Note: The lines illustrating steps (A), (B), and (C) are broken into - two parts as they pass through the user-agent. - - Figure 3: Authorization Code Flow - - The flow illustrated in Figure 3 includes the following steps: - - (A) The client initiates the flow by directing the resource owner's - user-agent to the authorization endpoint. The client includes - its client identifier, requested scope, local state, and a - redirection URI to which the authorization server will send the - user-agent back once access is granted (or denied). - - (B) The authorization server authenticates the resource owner (via - the user-agent) and establishes whether the resource owner - grants or denies the client's access request. - - (C) Assuming the resource owner grants access, the authorization - server redirects the user-agent back to the client using the - redirection URI provided earlier (in the request or during - client registration). The redirection URI includes an - authorization code and any local state provided by the client - earlier. - - (D) The client requests an access token from the authorization - server's token endpoint by including the authorization code - received in the previous step. When making the request, the - client authenticates with the authorization server. The client - includes the redirection URI used to obtain the authorization - code for verification. - - (E) The authorization server authenticates the client, validates the - authorization code, and ensures that the redirection URI - received matches the URI used to redirect the client in - step (C). If valid, the authorization server responds back with - an access token and, optionally, a refresh token. - -4.1.1. Authorization Request - - - The client constructs the request URI by adding the following - parameters to the query component of the authorization endpoint URI - using the "application/x-www-form-urlencoded" format, per Appendix B: - - response_type - REQUIRED. Value MUST be set to "code". - - client_id - REQUIRED. The client identifier as described in Section 2.2. - - redirect_uri - OPTIONAL. As described in Section 3.1.2. - - scope - OPTIONAL. The scope of the access request as described by - Section 3.3. - - state - RECOMMENDED. An opaque value used by the client to maintain - state between the request and callback. The authorization - server includes this value when redirecting the user-agent back - to the client. The parameter SHOULD be used for preventing - cross-site request forgery as described in Section 10.12. - - The client directs the resource owner to the constructed URI using an - HTTP redirection response, or by other means available to it via the - user-agent. - - For example, the client directs the user-agent to make the following - HTTP request using TLS (with extra line breaks for display purposes - only): - - GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz - &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 - Host: server.example.com - - The authorization server validates the request to ensure that all - required parameters are present and valid. If the request is valid, - the authorization server authenticates the resource owner and obtains - an authorization decision (by asking the resource owner or by - establishing approval via other means). - - When a decision is established, the authorization server directs the - user-agent to the provided client redirection URI using an HTTP - redirection response, or by other means available to it via the - user-agent. - */ -package com.blade.oauth2.validator; - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.OAuthError; -import com.blade.oauth2.base.validator.OAuthBaseValidator; -import com.blade.oauth2.exception.OAuthProblemException; -import com.blade.web.http.Request; - -/** - * Authorization Code Grant - * Authorization Request - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class AuthorizationValidator extends OAuthBaseValidator { - - public AuthorizationValidator() { - //Value MUST be set to "code". - requiredParams.add(OAuth.OAUTH_RESPONSE_TYPE); - requiredParams.add(OAuth.OAUTH_CLIENT_ID); - } - - @Override - public void validateMethod(Request request) throws OAuthProblemException { - String method = request.method(); - if (!method.equals(OAuth.HttpMethod.GET) && !method.equals(OAuth.HttpMethod.POST)) { - throw OAuthProblemException.error(OAuthError.CodeResponse.INVALID_REQUEST) - .description("Method not correct."); - } - } - - @Override - public void validateContentType(Request request) throws OAuthProblemException { - } -} - diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java deleted file mode 100644 index 62cf8b5a5..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/ClientCredentialValidator.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * http://www.rfcreader.com/#rfc6749 - * 4.4.2. Access Token Request - * - * The client can request an access token using only its client - credentials (or other supported means of authentication) when the - client is requesting access to the protected resources under its - control, or those of another resource owner that have been previously - arranged with the authorization server (the method of which is beyond - the scope of this specification). - - The client credentials grant type MUST only be used by confidential - clients. - - +---------+ +---------------+ - | | | | - | |>--(A)- Client Authentication --->| Authorization | - | Client | | Server | - | |<--(B)---- Access Token ---------<| | - | | | | - +---------+ +---------------+ - - Figure 6: Client Credentials Flow - - The flow illustrated in Figure 6 includes the following steps: - - (A) The client authenticates with the authorization server and - requests an access token from the token endpoint. - - (B) The authorization server authenticates the client, and if valid, - issues an access token. - */ -package com.blade.oauth2.validator; - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.base.validator.OAuthBaseValidator; -import com.blade.web.http.Request; - -/** - * Client Credentials Grant - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class ClientCredentialValidator extends OAuthBaseValidator { - - public ClientCredentialValidator() { - //Value MUST be set to "client_credentials". - requiredParams.add(OAuth.OAUTH_GRANT_TYPE); - enforceClientAuthentication = true; - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java deleted file mode 100644 index f61596412..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/ImplicitCodeValidator.java +++ /dev/null @@ -1,188 +0,0 @@ -/** - * http://www.rfcreader.com/#rfc6749_line1439 - * 4.2. Implicit Grant - * - * The implicit grant type is used to obtain access tokens (it does not - support the issuance of refresh tokens) and is optimized for public - clients known to operate a particular redirection URI. These clients - are typically implemented in a browser using a scripting language - such as JavaScript. - - Since this is a redirection-based flow, the client must be capable of - interacting with the resource owner's user-agent (typically a web - browser) and capable of receiving incoming requests (via redirection) - from the authorization server. - - Unlike the authorization code grant type, in which the client makes - separate requests for authorization and for an access token, the - client receives the access token as the result of the authorization - request. - - The implicit grant type does not include client authentication, and - relies on the presence of the resource owner and the registration of - the redirection URI. Because the access token is encoded into the - redirection URI, it may be exposed to the resource owner and other - applications residing on the same device. - - +----------+ - | Resource | - | Owner | - | | - +----------+ - ^ - | - (B) - +----|-----+ Client Identifier +---------------+ - | -+----(A)-- & Redirection URI --->| | - | User- | | Authorization | - | Agent -|----(B)-- User authenticates -->| Server | - | | | | - | |<---(C)--- Redirection URI ----<| | - | | with Access Token +---------------+ - | | in Fragment - | | +---------------+ - | |----(D)--- Redirection URI ---->| Web-Hosted | - | | without Fragment | Client | - | | | Resource | - | (F) |<---(E)------- Script ---------<| | - | | +---------------+ - +-|--------+ - | | - (A) (G) Access Token - | | - ^ v - +---------+ - | | - | Client | - | | - +---------+ - - Note: The lines illustrating steps (A) and (B) are broken into two - parts as they pass through the user-agent. - - Figure 4: Implicit Grant Flow - - The flow illustrated in Figure 4 includes the following steps: - - (A) The client initiates the flow by directing the resource owner's - user-agent to the authorization endpoint. The client includes - its client identifier, requested scope, local state, and a - redirection URI to which the authorization server will send the - user-agent back once access is granted (or denied). - - (B) The authorization server authenticates the resource owner (via - the user-agent) and establishes whether the resource owner - grants or denies the client's access request. - - (C) Assuming the resource owner grants access, the authorization - server redirects the user-agent back to the client using the - redirection URI provided earlier. The redirection URI includes - the access token in the URI fragment. - - (D) The user-agent follows the redirection instructions by making a - request to the web-hosted client resource (which does not - include the fragment per [RFC2616]). The user-agent retains the - fragment information locally. - - (E) The web-hosted client resource returns a web page (typically an - HTML document with an embedded script) capable of accessing the - full redirection URI including the fragment retained by the - user-agent, and extracting the access token (and other - parameters) contained in the fragment. - - (F) The user-agent executes the script provided by the web-hosted - client resource locally, which extracts the access token. - - (G) The user-agent passes the access token to the client. - - See Sections 1.3.2 and 9 for background on using the implicit grant. - See Sections 10.3 and 10.16 for important security considerations - when using the implicit grant. - - The client constructs the request URI by adding the following - parameters to the query component of the authorization endpoint URI - using the "application/x-www-form-urlencoded" format, per Appendix B: - - response_type - REQUIRED. Value MUST be set to "token". - - client_id - REQUIRED. The client identifier as described in Section 2.2. - - redirect_uri - OPTIONAL. As described in Section 3.1.2. - - scope - OPTIONAL. The scope of the access request as described by - Section 3.3. - - state - RECOMMENDED. An opaque value used by the client to maintain - state between the request and callback. The authorization - server includes this value when redirecting the user-agent back - to the client. The parameter SHOULD be used for preventing - cross-site request forgery as described in Section 10.12. - - The client directs the resource owner to the constructed URI using an - HTTP redirection response, or by other means available to it via the - user-agent. - - For example, the client directs the user-agent to make the following - HTTP request using TLS (with extra line breaks for display purposes - only): - - GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz - &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 - Host: server.example.com - - The authorization server validates the request to ensure that all - required parameters are present and valid. The authorization server - MUST verify that the redirection URI to which it will redirect the - access token matches a redirection URI registered by the client as - described in Section 3.1.2. - - If the request is valid, the authorization server authenticates the - resource owner and obtains an authorization decision (by asking the - resource owner or by establishing approval via other means). - - When a decision is established, the authorization server directs the - user-agent to the provided client redirection URI using an HTTP - redirection response, or by other means available to it via the - user-agent. - */ - -package com.blade.oauth2.validator; - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.OAuthError; -import com.blade.oauth2.base.validator.OAuthBaseValidator; -import com.blade.oauth2.exception.OAuthProblemException; -import com.blade.web.http.Request; - - -/** - * Implicit Grant - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class ImplicitCodeValidator extends OAuthBaseValidator { - - public ImplicitCodeValidator() { - //Value MUST be set to "token". - requiredParams.add(OAuth.OAUTH_RESPONSE_TYPE); - requiredParams.add(OAuth.OAUTH_CLIENT_ID); - } - - @Override - public void validateMethod(Request request) throws OAuthProblemException { - String method = request.method(); - if (!OAuth.HttpMethod.GET.equals(method) && !OAuth.HttpMethod.POST.equals(method)) { - throw OAuthProblemException.error(OAuthError.CodeResponse.INVALID_REQUEST) - .description("Method not correct."); - } - } - - @Override - public void validateContentType(Request request) throws OAuthProblemException { - } -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java deleted file mode 100644 index c35fea1a2..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/PasswordCredentialValidator.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * http://www.rfcreader.com/#rfc6749 - * 4.3. Resource Owner Password Credentials Grant - * The resource owner password credentials grant type is suitable in - cases where the resource owner has a trust relationship with the - client, such as the device operating system or a highly privileged - - application. The authorization server should take special care when - enabling this grant type and only allow it when other flows are not - viable. - - This grant type is suitable for clients capable of obtaining the - resource owner's credentials (username and password, typically using - an interactive form). It is also used to migrate existing clients - using direct authentication schemes such as HTTP Basic or Digest - authentication to OAuth by converting the stored credentials to an - access token. - - +----------+ - | Resource | - | Owner | - | | - +----------+ - v - | Resource Owner - (A) Password Credentials - | - v - +---------+ +---------------+ - | |>--(B)---- Resource Owner ------->| | - | | Password Credentials | Authorization | - | Client | | Server | - | |<--(C)---- Access Token ---------<| | - | | (w/ Optional Refresh Token) | | - +---------+ +---------------+ - - Figure 5: Resource Owner Password Credentials Flow - - The flow illustrated in Figure 5 includes the following steps: - - (A) The resource owner provides the client with its username and - password. - - (B) The client requests an access token from the authorization - server's token endpoint by including the credentials received - from the resource owner. When making the request, the client - authenticates with the authorization server. - - (C) The authorization server authenticates the client and validates - the resource owner credentials, and if valid, issues an access - token. - - The client makes a request to the token endpoint by adding the - following parameters using the "application/x-www-form-urlencoded" - format per Appendix B with a character encoding of UTF-8 in the HTTP - request entity-body: - - grant_type - REQUIRED. Value MUST be set to "password". - - username - REQUIRED. The resource owner username. - - password - REQUIRED. The resource owner password. - - scope - OPTIONAL. The scope of the access request as described by - Section 3.3. - - If the client type is confidential or the client was issued client - credentials (or assigned other authentication requirements), the - client MUST authenticate with the authorization server as described - in Section 3.2.1. - - For example, the client makes the following HTTP request using - transport-layer security (with extra line breaks for display purposes - only): - - POST /token HTTP/1.1 - Host: server.example.com - Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW - Content-Type: application/x-www-form-urlencoded - - grant_type=password&username=johndoe&password=A3ddj3w - - The authorization server MUST: - - o require client authentication for confidential clients or for any - client that was issued client credentials (or with other - authentication requirements), - - o authenticate the client if client authentication is included, and - - o validate the resource owner password credentials using its - existing password validation algorithm. - - Since this access token request utilizes the resource owner's - password, the authorization server MUST protect the endpoint against - brute force attacks (e.g., using rate-limitation or generating - alerts) - */ -package com.blade.oauth2.validator; - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.base.validator.OAuthBaseValidator; -import com.blade.web.http.Request; - -/** - * Resource Owner Password Credentials Grant - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class PasswordCredentialValidator extends OAuthBaseValidator { - - public PasswordCredentialValidator() { - // Value MUST be set to "password" - requiredParams.add(OAuth.OAUTH_GRANT_TYPE); - requiredParams.add(OAuth.OAUTH_USERNAME); - requiredParams.add(OAuth.OAUTH_PASSWORD); - enforceClientAuthentication = true; - } - -} diff --git a/blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java b/blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java deleted file mode 100644 index e2b403561..000000000 --- a/blade-oauth2/src/main/java/com/blade/oauth2/validator/RefreshTokenValidator.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * http://www.rfcreader.com/#rfc6749 - * 6. Refreshing an Access Token - * If the authorization server issued a refresh token to the client, the - client makes a refresh request to the token endpoint by adding the - following parameters using the "application/x-www-form-urlencoded" - format per Appendix B with a character encoding of UTF-8 in the HTTP - request entity-body: - - grant_type - REQUIRED. Value MUST be set to "refresh_token". - - refresh_token - REQUIRED. The refresh token issued to the client. - - scope - OPTIONAL. The scope of the access request as described by - Section 3.3. The requested scope MUST NOT include any scope - not originally granted by the resource owner, and if omitted is - treated as equal to the scope originally granted by the - resource owner. - - Because refresh tokens are typically long-lasting credentials used to - request additional access tokens, the refresh token is bound to the - client to which it was issued. If the client type is confidential or - the client was issued client credentials (or assigned other - authentication requirements), the client MUST authenticate with the - authorization server as described in Section 3.2.1. - - For example, the client makes the following HTTP request using - transport-layer security (with extra line breaks for display purposes - only): - - POST /token HTTP/1.1 - Host: server.example.com - Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW - Content-Type: application/x-www-form-urlencoded - - grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA - - The authorization server MUST: - - o require client authentication for confidential clients or for any - client that was issued client credentials (or with other - authentication requirements), - - o authenticate the client if client authentication is included and - ensure that the refresh token was issued to the authenticated - client, and - - o validate the refresh token. - - If valid and authorized, the authorization server issues an access - token as described in Section 5.1. If the request failed - verification or is invalid, the authorization server returns an error - response as described in Section 5.2. - - The authorization server MAY issue a new refresh token, in which case - the client MUST discard the old refresh token and replace it with the - new refresh token. The authorization server MAY revoke the old - refresh token after issuing a new refresh token to the client. If a - new refresh token is issued, the refresh token scope MUST be - identical to that of the refresh token included by the client in the - request. - */ -package com.blade.oauth2.validator; - -import com.blade.oauth2.OAuth; -import com.blade.oauth2.base.validator.OAuthBaseValidator; -import com.blade.web.http.Request; - -/** - * Validator that checks for the required fields in an OAuth Token request with the Refresh token grant type. - * This validator enforces client authentication either through basic authentication or body parameters. - * - * http://www.rfcreader.com/#rfc6749 - * 6. Refreshing an Access Token - * @author BruceZCQ [zcq@zhucongqi.cn] - * @version - */ -public class RefreshTokenValidator extends OAuthBaseValidator { - - public RefreshTokenValidator() { - //Value MUST be set to "refresh_token". - requiredParams.add(OAuth.OAUTH_GRANT_TYPE); - requiredParams.add(OAuth.OAUTH_REFRESH_TOKEN); - enforceClientAuthentication = true; - } - -} diff --git a/blade-patchca/README.md b/blade-patchca/README.md deleted file mode 100644 index 4d706a7e7..000000000 --- a/blade-patchca/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# blade-patchca - -基于blade框架 + patchca 的验证码工具包。 - diff --git a/blade-patchca/pom.xml b/blade-patchca/pom.xml deleted file mode 100644 index 4832dbeb1..000000000 --- a/blade-patchca/pom.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - blade-patchca - 1.0.1 - blade-patchca - https://github.com/biezhi/blade/tree/master/blade-patchca - - - - com.bladejava - blade-core - ${blade.version} - - - diff --git a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java b/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java deleted file mode 100644 index bc96521ac..000000000 --- a/blade-patchca/src/main/java/com/blade/patchca/PatchcaService.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.blade.patchca; - -import java.awt.Color; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Random; - -import org.patchca.color.ColorFactory; -import org.patchca.filter.FilterFactory; -import org.patchca.filter.predefined.DiffuseRippleFilterFactory; -import org.patchca.service.ConfigurableCaptchaService; -import org.patchca.utils.encoder.EncoderHelper; -import org.patchca.word.RandomWordFactory; -import org.patchca.word.WordFactory; - -import com.blade.web.http.Response; -import com.blade.web.http.wrapper.Session; - -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - -/** - * PatchcaService - */ -public class PatchcaService { - - private static final Logger LOGGER = LoggerFactory.getLogger(PatchcaService.class); - - private ConfigurableCaptchaService cs = null; - private static Random random = new Random(); - - private PatchcaService() { - cs = new ConfigurableCaptchaService(); - // cs.setColorFactory(new SingleColorFactory(new Color(25, 60, 170))); - cs.setColorFactory(new ColorFactory() { - @Override - public Color getColor(int x) { - int[] c = new int[3]; - int i = random.nextInt(c.length); - for (int fi = 0; fi < c.length; fi++) { - if (fi == i) { - c[fi] = random.nextInt(71); - } else { - c[fi] = random.nextInt(256); - } - } - return new Color(c[0], c[1], c[2]); - } - }); - RandomWordFactory wf = new RandomWordFactory(); - wf.setCharacters("23456789abcdefghigkmnpqrstuvwxyzABCDEFGHIGKLMNPQRSTUVWXYZ"); - wf.setMaxLength(4); - wf.setMinLength(4); - cs.setWordFactory(wf); - cs.setFilterFactory(new DiffuseRippleFilterFactory()); - } - - public static PatchcaService get(){ - return new PatchcaService(); - } - - public PatchcaService color(ColorFactory colorFactory){ - cs.setColorFactory(colorFactory); - return this; - } - - public PatchcaService word(WordFactory wordFactory){ - cs.setWordFactory(wordFactory); - return this; - } - - public PatchcaService filter(FilterFactory filterFactory){ - cs.setFilterFactory(filterFactory); - return this; - } - - public void session(Session session, Response response, String patchca){ - try { - setResponseHeaders(response); - String token = EncoderHelper.getChallangeAndWriteImage(cs, "png", response.outputStream()); - session.attribute(patchca, token); - LOGGER.debug("current sessionid = {}, token = {}", session.id(), token); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void setResponseHeaders(Response response) { - response.contentType("image/png"); - response.header("Cache-Control", "no-cache, no-store"); - response.header("Pragma", "no-cache"); - long time = System.currentTimeMillis(); - response.header("Last-Modified", time + ""); - response.header("Date", time + ""); - response.header("Expires", time + ""); - } - - public String token(String imgType, Response response){ - try { - String token = EncoderHelper.getChallangeAndWriteImage(cs, imgType, response.outputStream()); - return token; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - public String token(Response response){ - try { - String token = EncoderHelper.getChallangeAndWriteImage(cs, "png", response.outputStream()); - return token; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - public File create(String imgPath, String imgType) { - try { - FileOutputStream fos = new FileOutputStream(imgPath); - EncoderHelper.getChallangeAndWriteImage(cs, imgType, fos); - fos.close(); - return new File(imgPath); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } -} diff --git a/blade-patchca/src/main/java/org/patchca/background/BackgroundFactory.java b/blade-patchca/src/main/java/org/patchca/background/BackgroundFactory.java deleted file mode 100644 index 646aaf6cb..000000000 --- a/blade-patchca/src/main/java/org/patchca/background/BackgroundFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ - -package org.patchca.background; - -import java.awt.image.BufferedImage; - -public interface BackgroundFactory { - - void fillBackground(BufferedImage dest); -} diff --git a/blade-patchca/src/main/java/org/patchca/background/SingleColorBackgroundFactory.java b/blade-patchca/src/main/java/org/patchca/background/SingleColorBackgroundFactory.java deleted file mode 100644 index 869af0a7d..000000000 --- a/blade-patchca/src/main/java/org/patchca/background/SingleColorBackgroundFactory.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.background; - -import org.patchca.color.ColorFactory; -import org.patchca.color.SingleColorFactory; - -import java.awt.*; -import java.awt.image.BufferedImage; - - -public class SingleColorBackgroundFactory implements BackgroundFactory { - - private ColorFactory colorFactory; - - public SingleColorBackgroundFactory() { - colorFactory = new SingleColorFactory(Color.WHITE); - } - - public SingleColorBackgroundFactory(Color color) { - colorFactory = new SingleColorFactory(color); - } - - public void setColorFactory(ColorFactory colorFactory) { - this.colorFactory = colorFactory; - } - - @Override - public void fillBackground(BufferedImage dest) { - Graphics g = dest.getGraphics(); - g.setColor(colorFactory.getColor(0)); - g.fillRect(0, 0, dest.getWidth(), dest.getHeight()); - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/color/ColorFactory.java b/blade-patchca/src/main/java/org/patchca/color/ColorFactory.java deleted file mode 100644 index 4a48ec393..000000000 --- a/blade-patchca/src/main/java/org/patchca/color/ColorFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.color; - -import java.awt.*; - -public interface ColorFactory { - - Color getColor(int index); -} diff --git a/blade-patchca/src/main/java/org/patchca/color/GradientColorFactory.java b/blade-patchca/src/main/java/org/patchca/color/GradientColorFactory.java deleted file mode 100644 index badecd70f..000000000 --- a/blade-patchca/src/main/java/org/patchca/color/GradientColorFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.color; - -import java.awt.*; - -public class GradientColorFactory implements ColorFactory { - - private Color start; - private Color step; - - public GradientColorFactory() { - start = new Color(192, 192, 0); - step = new Color(192, 128, 128); - } - - @Override - public Color getColor(int index) { - return new Color((start.getRed() + step.getRed() * index) % 256, - (start.getGreen() + step.getGreen() * index) % 256, - (start.getBlue() + step.getBlue() * index) % 256); - } - - public void setStart(Color start) { - this.start = start; - } - - public void setStep(Color step) { - this.step = step; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/color/RandomColorFactory.java b/blade-patchca/src/main/java/org/patchca/color/RandomColorFactory.java deleted file mode 100644 index 035a41434..000000000 --- a/blade-patchca/src/main/java/org/patchca/color/RandomColorFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.color; - -import java.awt.*; -import java.util.Random; - -public class RandomColorFactory implements ColorFactory { - - private Color min; - private Color max; - private Color color; - - public RandomColorFactory() { - min = new Color(20,40,80); - max = new Color(21,50,140); - } - - public void setMin(Color min) { - this.min = min; - } - - public void setMax(Color max) { - this.max = max; - } - - @Override - public Color getColor(int index) { - if (color == null) { - Random r = new Random(); - color = new Color( min.getRed() + r.nextInt((max.getRed() - min.getRed())), - min.getGreen() + r.nextInt((max.getGreen() - min.getGreen())), - min.getBlue() + r.nextInt((max.getBlue() - min.getBlue()))); - } - return color; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/color/SingleColorFactory.java b/blade-patchca/src/main/java/org/patchca/color/SingleColorFactory.java deleted file mode 100644 index 06ce3be3e..000000000 --- a/blade-patchca/src/main/java/org/patchca/color/SingleColorFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.color; - -import java.awt.*; - -public class SingleColorFactory implements ColorFactory { - - private Color color; - - public SingleColorFactory() { - color = Color.BLACK; - } - - public SingleColorFactory(Color color) { - this.color = color; - } - - @Override - public Color getColor(int index) { - return color; - } - - public void setColor(Color color) { - this.color = color; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/AbstractFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/AbstractFilterFactory.java deleted file mode 100644 index 665b8e178..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/AbstractFilterFactory.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter; - -import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; -import java.util.List; - -public abstract class AbstractFilterFactory implements FilterFactory { - - protected abstract List getFilters(); - - public BufferedImage applyFilters(BufferedImage source) { - BufferedImage dest = source; - for (BufferedImageOp filter : getFilters()) { - dest = filter.filter(dest, null); - } - int x = (source.getWidth() - dest.getWidth()) / 2; - int y = (source.getHeight() - dest.getHeight()) / 2; - source = new BufferedImage(source.getWidth(), source.getHeight(), source.getType()); - source.getGraphics().drawImage(dest, x, y, null); - return source; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/ConfigurableFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/ConfigurableFilterFactory.java deleted file mode 100644 index 9c34991a0..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/ConfigurableFilterFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter; - -import java.awt.image.BufferedImageOp; -import java.util.List; - -public class ConfigurableFilterFactory extends AbstractFilterFactory { - - private List filters; - - @Override - public List getFilters() { - return filters; - } - - public void setFilters(List filters) { - this.filters = filters; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/FilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/FilterFactory.java deleted file mode 100644 index 67ed89309..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/FilterFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter; - -import java.awt.image.BufferedImage; - -public interface FilterFactory { - - BufferedImage applyFilters(BufferedImage source); - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/AbstractConvolveImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/AbstractConvolveImageOp.java deleted file mode 100644 index d89063eee..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/AbstractConvolveImageOp.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - - -public abstract class AbstractConvolveImageOp extends AbstractImageOp { - - private float[][] matrix; - - protected AbstractConvolveImageOp(float[][] matrix) { - this.matrix = matrix; - } - - @Override - protected void filter(int[] inPixels, int[] outPixels, int width, int height) { - long time1 = System.currentTimeMillis(); - int matrixWidth = matrix[0].length; - int matrixHeight = matrix.length; - int mattrixLeft = - matrixWidth / 2; - int matrixTop = - matrixHeight / 2; - for (int y = 0; y < height; y++) { - int ytop = y + matrixTop; - int ybottom = y + matrixTop + matrixHeight; - for (int x = 0; x < width; x++) { - float[] sum = {0.5f, 0.5f, 0.5f, 0.5f}; - int xleft = x + mattrixLeft; - int xright = x + mattrixLeft + matrixWidth; - int matrixY = 0; - for (int my = ytop; my < ybottom; my ++, matrixY++) { - int matrixX = 0; - for (int mx = xleft; mx < xright; mx ++, matrixX ++) { - int pixel = getPixel(inPixels, mx, my, width, height, EDGE_ZERO); - float m = matrix[matrixY][matrixX]; - sum[0] += m * ((pixel >> 24) & 0xff); - sum[1] += m * ((pixel >> 16) & 0xff); - sum[2] += m * ((pixel >> 8) & 0xff); - sum[3] += m * (pixel & 0xff); - } - } - outPixels[x + y * width] = (limitByte((int)sum[0]) << 24) | (limitByte((int)sum[1]) << 16) | (limitByte((int)sum[2]) << 8) | (limitByte((int)sum[3])); - } - } - long time2 = System.currentTimeMillis() - time1; - //System.out.println("AbstractConvolveImageOp " + time2); - - } - - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/AbstractImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/AbstractImageOp.java deleted file mode 100644 index 1f6b70e43..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/AbstractImageOp.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - -import java.awt.*; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; -import java.awt.image.ColorModel; -import java.awt.image.IndexColorModel; - -public abstract class AbstractImageOp implements BufferedImageOp { - - public static final int EDGE_ZERO = 0; - public static final int EDGE_MIRROR = 1; - public static final int EDGE_CLAMP = 2; - - protected int edgeMode; - protected RenderingHints hints; - - public int getEdgeMode() { - return edgeMode; - } - - public void setEdgeMode(int edgeMode) { - this.edgeMode = edgeMode; - } - - protected int getPixel(int pixels[], int x, int y, int width, int height, int edgeMode) { - if (x >= 0 && x < width && y >= 0 && y < height) { - return pixels[x + y * width]; - } else if (edgeMode == EDGE_ZERO) { - return 0; - } else if (edgeMode == EDGE_CLAMP) { - if (x < 0) { - x = 0; - } else if (x >= width) { - x = width - 1; - } - if (y < 0) { - y = 0; - } else if (y >= height) { - y = height - 1; - } - return pixels[x + y * width]; - } else { - if (x < 0) { - x = -x; - } else if (x >= width) { - x = width + width - x - 1; - } - if (y < 0) { - y = -y; - } else if (y > height) { - y = height = height - y - 1; - } - try { - return pixels[x + y * width]; - } catch (Exception e) { - return 0; - } - } - } - - private int linear(int from, int to, int shift, double d) { - return ((int) Math.floor(((from >> shift) & 0xff) + d * (((to >> shift) & 0xff) - ((from >> shift) & 0xff)))) << shift; - } - - private int linear(int from, int to, double d) { - int c = 0; - for (int i = 0; i < 4; i++) { - c += linear(from, to, i * 8, d); - } - return c; - } - - protected int bilinear(int nw, int ne, int sw, int se, double xd, double yd) { - return linear(linear(nw, ne, xd), linear(sw, se, xd), yd); - } - - protected int getPixelBilinear(int pixels[], double x, double y, int width, int height, int edgeMode) { - int xi = (int) Math.floor(x); - int yi = (int) Math.floor(y); - double xd = x - xi; - double yd = y - yi; - int nw = getPixel(pixels, xi, yi, width, height, edgeMode); - int ne = getPixel(pixels, xi + 1, yi, width, height, edgeMode); - int sw = getPixel(pixels, xi, yi + 1, width, height, edgeMode); - int se = getPixel(pixels, xi + 1, yi + 1, width, height, edgeMode); - return bilinear(nw, ne, sw, se, xd, yd); - } - - protected int limit(int v, int min, int max) { - if (v < min) { - v = min; - } else if (v > max) { - v = max; - } - return v; - } - - protected int limitByte(int v) { - return limit(v, 0, 255); - } - - protected void filter(int[] inPixels, int[] outPixels, int width, int height) { - - } - - @Override - public BufferedImage filter(BufferedImage src, BufferedImage dest) { - if (dest == null) { - dest = createCompatibleDestImage(src, null); - } - int width = src.getWidth(); - int height = src.getHeight(); - int[] inPixels = new int[width * height]; - int[] outPixels = new int[width * height]; - src.getRaster().getDataElements(0, 0, width, height, inPixels); - filter(inPixels, outPixels, width, height); - dest.getRaster().setDataElements(0, 0, width, height, outPixels); - return dest; - } - - @Override - public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) { - if (destCM == null) { - destCM = src.getColorModel(); - if (destCM instanceof IndexColorModel) { - destCM = ColorModel.getRGBdefault(); - } - } - return new BufferedImage(destCM, destCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), destCM.isAlphaPremultiplied(), null); - } - - @Override - public Rectangle2D getBounds2D(BufferedImage src) { - return src.getRaster().getBounds(); - } - - @Override - public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) { - if (dstPt == null) { - dstPt = new Point2D.Float(); - } - dstPt.setLocation(srcPt.getX(), srcPt.getY()); - return dstPt; - } - - @Override - public RenderingHints getRenderingHints() { - return hints; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/AbstractTransformImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/AbstractTransformImageOp.java deleted file mode 100644 index be2174942..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/AbstractTransformImageOp.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - - -public abstract class AbstractTransformImageOp extends AbstractImageOp { - - protected abstract void transform(int x, int y, double[] t); - - protected void init() { - } - - private boolean initialized; - - public AbstractTransformImageOp() { - setEdgeMode(EDGE_CLAMP); - } - - @Override - protected void filter(int[] inPixels, int[] outPixels, int width, int height) { - if (!initialized) { - init(); - initialized = true; - } - long time1 = System.currentTimeMillis(); - double[]t = new double[2]; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - transform(x, y, t); - int pixel = getPixelBilinear(inPixels, t[0], t[1], width, height, getEdgeMode()); - outPixels[x + y * width] = pixel; - } - } - long time2 = System.currentTimeMillis() - time1; - //System.out.println("AbstractTransformImageOp " + time2); - } - -} - diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/BlurImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/BlurImageOp.java deleted file mode 100644 index 950e9379d..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/BlurImageOp.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - -public class BlurImageOp extends AbstractConvolveImageOp { - - private static final float[][] matrix = { { 1 / 16f, 2 / 16f, 1 / 16f }, - { 2 / 16f, 4 / 16f, 2 / 16f }, { 1 / 16f, 2 / 16f, 1 / 16f } }; - - public BlurImageOp() { - super(matrix); - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/CurvesImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/CurvesImageOp.java deleted file mode 100644 index 3a66d20f7..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/CurvesImageOp.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - -import org.patchca.color.ColorFactory; -import org.patchca.color.SingleColorFactory; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.util.Random; - - -public class CurvesImageOp extends AbstractImageOp { - - private float strokeMin; - private float strokeMax; - private ColorFactory colorFactory = new SingleColorFactory(); - - public float getStrokeMin() { - return strokeMin; - } - - public void setStrokeMin(float strokeMin) { - this.strokeMin = strokeMin; - } - - public float getStrokeMax() { - return strokeMax; - } - - - public void setStrokeMax(float strokeMax) { - this.strokeMax = strokeMax; - } - public ColorFactory getColorFactory() { - return colorFactory; - } - - public void setColorFactory(ColorFactory colorFactory) { - this.colorFactory = colorFactory; - } - - private double hermiteSpline(double x1, double a1, double x2, double a2, double t) { - double t2=t*t; - double t3=t2*t; - double b=-a2-2.0*a1-3.0*x1+3.0*x2; - double a=a2+a1+2.0*x1-2.0*x2; - return a*t3+b*t2+a1*t+x1; - } - - private double catmullRomSpline(double x0, double x1, double x2, double x3, double t) { - double a1 = (x2 - x0) / 2; - double a2 = (x3 - x1) / 2; - return hermiteSpline(x1, a1, x2, a2, t); - } - - @Override - public BufferedImage filter(BufferedImage src, BufferedImage dest) { - if (dest == null) { - dest = createCompatibleDestImage(src, null); - } - double width = dest.getWidth(); - double height = dest.getHeight(); - Graphics2D g2 = (Graphics2D) src.getGraphics(); - g2.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); - Random r = new Random(); - int cp = 4 + r.nextInt(3); - int[] xPoints = new int[cp]; - int[] yPoints = new int[cp]; - width -= 10; - for (int i = 0; i < cp; i++) { - xPoints[i] = (int) ((int) 5 + (i * width) / (cp - 1)); - yPoints[i] = (int) (height * (r.nextDouble() * 0.5 + 0.2)); - } - int subsections = 6; - int[] xPointsSpline = new int[(cp - 1)*subsections]; - int[] yPointsSpline = new int[(cp - 1)*subsections]; - for (int i = 0; i < cp - 1; i++) { - double x0 = i > 0 ? xPoints[i - 1] : 2 * xPoints[i] - xPoints[i + 1]; - double x1 = xPoints[i]; - double x2 = xPoints[i + 1]; - double x3 = (i + 2 < cp) ? xPoints[i + 2] : 2 * xPoints[i + 1] - xPoints[i]; - double y0 = i > 0 ? yPoints[i - 1] : 2 * yPoints[i] - yPoints[i + 1]; - double y1 = yPoints[i]; - double y2 = yPoints[i + 1]; - double y3 = (i + 2 < cp) ? yPoints[i + 2] : 2 * yPoints[i + 1] - yPoints[i]; - for (int j = 0; j < subsections; j++) { - xPointsSpline[i * subsections + j] = (int) catmullRomSpline(x0, x1, x2, x3, 1.0 / subsections * j); - yPointsSpline[i * subsections + j] = (int) catmullRomSpline(y0, y1, y2, y3, 1.0 / subsections * j); - } - } - for (int i = 0; i < xPointsSpline.length - 1; i++) { - g2.setColor(colorFactory.getColor(i)); - g2.setStroke(new BasicStroke(2 + 2 * r.nextFloat())); - g2.drawLine(xPointsSpline[i], yPointsSpline[i], xPointsSpline[i + 1], yPointsSpline[i + 1]); - } - return src; - } -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/DiffuseImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/DiffuseImageOp.java deleted file mode 100644 index 42a0f0166..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/DiffuseImageOp.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - -import java.util.Random; - -public class DiffuseImageOp extends AbstractTransformImageOp { - - double[] tx; - double[] ty; - double amount; - - public DiffuseImageOp() { - amount = 1.6; - } - - public double getAmount() { - return amount; - } - - public void setAmount(double amount) { - this.amount = amount; - } - - @Override - protected synchronized void init() { - tx = new double[256]; - ty = new double[256]; - for (int i = 0; i < 256; i++) { - double angle = 2 * Math.PI * i / 256; - tx[i] = amount * Math.sin(angle); - ty[i] = amount * Math.cos(angle); - } - } - - @Override - protected void transform(int x, int y, double[] t) { - Random r = new Random(); - int angle = (int) (r.nextFloat() * 255); - t[0] = x + tx[angle]; - t[1] = y + ty[angle]; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/DoubleRippleImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/DoubleRippleImageOp.java deleted file mode 100644 index 73fb17c63..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/DoubleRippleImageOp.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - -public class DoubleRippleImageOp extends RippleImageOp { - - @Override - protected void transform(int x, int y, double[] t) { - double tx = Math.sin((double) y / yWavelength + yRandom) + 1.3 * Math.sin((double) 0.6 * y / yWavelength + yRandom); - double ty = Math.cos((double) x / xWavelength + xRandom) + 1.3 * Math.cos((double) 0.6 * x / xWavelength + xRandom); - t[0] = x + xAmplitude * tx; - t[1] = y + yAmplitude * ty; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/MarbleImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/MarbleImageOp.java deleted file mode 100644 index 5e47eb2ae..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/MarbleImageOp.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - -public class MarbleImageOp extends AbstractTransformImageOp { - - double scale; - double amount; - double turbulence; - double[] tx; - double[] ty; - double randomX; - double randomY; - - public MarbleImageOp() { - scale = 15; - amount = 1.1; - turbulence = 6.2; - randomX = 256 * Math.random(); - randomY = 256 * Math.random(); - } - - public double getScale() { - return scale; - } - - public void setScale(double scale) { - this.scale = scale; - } - - public double getAmount() { - return amount; - } - - public void setAmount(double amount) { - this.amount = amount; - } - - public double getTurbulence() { - return turbulence; - } - - public void setTurbulence(double turbulence) { - this.turbulence = turbulence; - } - - @Override - protected synchronized void init() { - tx = new double[256]; - ty = new double[256]; - for (int i = 0; i < 256; i++) { - double angle = 2 * Math.PI * i * turbulence / 256; - tx[i] = amount * Math.sin(angle); - ty[i] = amount * Math.cos(angle); - } - } - - @Override - protected void transform(int x, int y, double[] t) { - int d = limitByte((int) (127 * (1 + PerlinNoise.noise2D(((double)x) / scale + randomX, ((double)y) / scale + randomY)))); - t[0] = x + tx[d]; - t[1] = y + ty[d]; - } - - protected void filter2(int[] inPixels, int[] outPixels, int width, int height) { - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int pixel = limitByte((int) (127 * (1 + PerlinNoise.noise2D(((double)x) / scale + randomX, ((double)y) / scale + randomY)))); - outPixels[x + y * width] = (limitByte((int)255) << 24) | (limitByte((int)pixel) << 16) | (limitByte((int)pixel) << 8) | (limitByte((int)pixel)); - } - } - } - - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/PerlinNoise.java b/blade-patchca/src/main/java/org/patchca/filter/library/PerlinNoise.java deleted file mode 100644 index 8a0e80bf8..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/PerlinNoise.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - -public class PerlinNoise { - - static int p[] = { 151, 160, 137, 91, 90, 15, - 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, - 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, - 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, - 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, - 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, - 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, - 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, - 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, - 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, - 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, - 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, - 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, - 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, - 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, - 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, - 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, - 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, - 61, 156, 180, 151, 160, 137, 91, 90, 15, - 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, - 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, - 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, - 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, - 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, - 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, - 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, - 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, - 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, - 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, - 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, - 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, - 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, - 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, - 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, - 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, - 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, - 61, 156, 180 }; - - public static double noise2D(double x, double y) { - double fx = Math.floor(x); - double fy = Math.floor(y); - double u, v; - int ix = ((int) fx) & 0xFF; - int iy = ((int) fy) & 0xFF; - x -= fx; - y -= fy; - int i = p[ix]; - int j = p[ix + 1]; - u = fade(x); - v = fade(y); - double grad1 = grad(p[i + iy], x, y); - double grad2 = grad(p[j + iy], x - 1, y); - double grad3 = grad(p[i + iy + 1], x, y - 1); - double grad4 = grad(p[j + iy + 1], x - 1, y - 1); - return lerp(v, lerp(u, grad1, grad2), lerp(u, grad3, grad4)); - } - - static double fade(double t) { - return t * t * t * (t * (t * 6 - 15) + 10); - } - - static double grad(int hash, double x, double y) { - int h = hash & 3; - double u = (h & 1) == 0 ? x : -x; - double v = (h & 2) == 0 ? y : -y; - return u + v; - } - - public static double lerp(double t, double a, double b) { - return a + t * (b - a); - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/RippleImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/RippleImageOp.java deleted file mode 100644 index 3d014fb25..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/RippleImageOp.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - - -public class RippleImageOp extends AbstractTransformImageOp { - - protected double xWavelength; - protected double yWavelength; - protected double xAmplitude; - protected double yAmplitude; - protected double xRandom; - protected double yRandom; - - public RippleImageOp() { - xWavelength = 20; - yWavelength = 10; - xAmplitude = 5; - yAmplitude = 5; - xRandom = 5 * Math.random(); - yRandom = 5 * Math.random(); - } - - public double getxWavelength() { - return xWavelength; - } - - public void setxWavelength(double xWavelength) { - this.xWavelength = xWavelength; - } - - public double getyWavelength() { - return yWavelength; - } - - public void setyWavelength(double yWavelength) { - this.yWavelength = yWavelength; - } - - public double getxAmplitude() { - return xAmplitude; - } - - public void setxAmplitude(double xAmplitude) { - this.xAmplitude = xAmplitude; - } - - public double getyAmplitude() { - return yAmplitude; - } - - public void setyAmplitude(double yAmplitude) { - this.yAmplitude = yAmplitude; - } - - @Override - protected void transform(int x, int y, double[] t) { - double tx = Math.sin((double) y / yWavelength + yRandom); - double ty = Math.cos((double) x / xWavelength + xRandom); - t[0] = x + xAmplitude * tx; - t[1] = y + yAmplitude * ty; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/SoftenImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/SoftenImageOp.java deleted file mode 100644 index 1eb39b0a2..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/SoftenImageOp.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - -public class SoftenImageOp extends AbstractConvolveImageOp { - - private static final float[][] matrix = { { 0 / 16f, 1 / 16f, 0 / 16f }, - { 1 / 16f, 12 / 16f, 1 / 16f }, { 0 / 16f, 1 / 16f, 0 / 16f } }; - - public SoftenImageOp() { - super(matrix); - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/library/WobbleImageOp.java b/blade-patchca/src/main/java/org/patchca/filter/library/WobbleImageOp.java deleted file mode 100644 index 590b4e81c..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/library/WobbleImageOp.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.library; - - -public class WobbleImageOp extends AbstractTransformImageOp { - - private double xWavelength; - private double yWavelength; - private double xAmplitude; - private double yAmplitude; - private double xRandom; - private double yRandom; - private double xScale; - private double yScale; - - public WobbleImageOp() { - xWavelength = 15; - yWavelength = 15; - xAmplitude = 4.0; - yAmplitude = 3.0; - xScale = 1.0; - yScale = 1.0; - xRandom = 3 * Math.random(); - yRandom = 10 * Math.random(); - } - - public double getxWavelength() { - return xWavelength; - } - - public void setxWavelength(double xWavelength) { - this.xWavelength = xWavelength; - } - - public double getyWavelength() { - return yWavelength; - } - - public void setyWavelength(double yWavelength) { - this.yWavelength = yWavelength; - } - - public double getxAmplitude() { - return xAmplitude; - } - - public void setxAmplitude(double xAmplitude) { - this.xAmplitude = xAmplitude; - } - - public double getyAmplitude() { - return yAmplitude; - } - - public void setyAmplitude(double yAmplitude) { - this.yAmplitude = yAmplitude; - } - - public double getxScale() { - return xScale; - } - - public void setxScale(double xScale) { - this.xScale = xScale; - } - - public double getyScale() { - return yScale; - } - - public void setyScale(double yScale) { - this.yScale = yScale; - } - - @Override - protected void transform(int x, int y, double[] t) { - double tx = Math.cos((double) (xScale * x + y) / xWavelength + xRandom); - double ty = Math.sin((double) (yScale * y + x) / yWavelength + yRandom); - t[0] = x + xAmplitude * tx; - t[1] = y + yAmplitude * ty; - - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/CurvesRippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/CurvesRippleFilterFactory.java deleted file mode 100644 index 996181fa6..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/predefined/CurvesRippleFilterFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.predefined; - -import org.patchca.color.ColorFactory; -import org.patchca.filter.library.CurvesImageOp; - -import java.awt.image.BufferedImageOp; -import java.util.ArrayList; -import java.util.List; - -public class CurvesRippleFilterFactory extends RippleFilterFactory { - - protected CurvesImageOp curves = new CurvesImageOp(); - - public CurvesRippleFilterFactory() { - } - - public CurvesRippleFilterFactory(ColorFactory colorFactory) { - setColorFactory(colorFactory); - } - - @Override - protected List getPreRippleFilters() { - List list = new ArrayList(); - list.add(curves); - return list; - } - - public void setStrokeMin(float strokeMin) { - curves.setStrokeMin(strokeMin); - } - - public void setStrokeMax(float strokeMax) { - curves.setStrokeMax(strokeMax); - } - - public void setColorFactory(ColorFactory colorFactory) { - curves.setColorFactory(colorFactory); - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/DiffuseRippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/DiffuseRippleFilterFactory.java deleted file mode 100644 index e668e745c..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/predefined/DiffuseRippleFilterFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.predefined; - -import org.patchca.filter.library.DiffuseImageOp; - -import java.awt.image.BufferedImageOp; -import java.util.ArrayList; -import java.util.List; - - -public class DiffuseRippleFilterFactory extends RippleFilterFactory { - - protected DiffuseImageOp diffuse = new DiffuseImageOp(); - - @Override - protected List getPreRippleFilters() { - List list = new ArrayList(); - list.add(diffuse); - return list; - } -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/DoubleRippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/DoubleRippleFilterFactory.java deleted file mode 100644 index 52ddaf52e..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/predefined/DoubleRippleFilterFactory.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.predefined; - -import org.patchca.filter.AbstractFilterFactory; -import org.patchca.filter.library.DoubleRippleImageOp; - -import java.awt.image.BufferedImageOp; -import java.util.ArrayList; -import java.util.List; - - -public class DoubleRippleFilterFactory extends AbstractFilterFactory { - - protected List filters; - protected DoubleRippleImageOp ripple; - - public DoubleRippleFilterFactory() { - ripple = new DoubleRippleImageOp(); - } - - @Override - public List getFilters() { - if (filters == null) { - filters = new ArrayList(); - filters.add(ripple); - } - return filters; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/MarbleRippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/MarbleRippleFilterFactory.java deleted file mode 100644 index 99f7f1177..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/predefined/MarbleRippleFilterFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.predefined; - -import org.patchca.filter.library.MarbleImageOp; - -import java.awt.image.BufferedImageOp; -import java.util.ArrayList; -import java.util.List; - - -public class MarbleRippleFilterFactory extends RippleFilterFactory { - - protected MarbleImageOp marble = new MarbleImageOp(); - - @Override - protected List getPreRippleFilters() { - List list = new ArrayList(); - list.add(marble); - return list; - } - -} - diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/RippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/RippleFilterFactory.java deleted file mode 100644 index 3bf2c2334..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/predefined/RippleFilterFactory.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.predefined; - -import org.patchca.filter.AbstractFilterFactory; -import org.patchca.filter.library.RippleImageOp; - -import java.awt.image.BufferedImageOp; -import java.util.ArrayList; -import java.util.List; - - -public class RippleFilterFactory extends AbstractFilterFactory { - - protected List filters; - protected RippleImageOp ripple; - - public RippleFilterFactory() { - ripple = new RippleImageOp(); - } - - protected List getPreRippleFilters() { - return new ArrayList(); - } - - protected List getPostRippleFilters() { - return new ArrayList(); - - } - - @Override - public List getFilters() { - if (filters == null) { - filters = new ArrayList(); - filters.addAll(getPreRippleFilters()); - filters.add(ripple); - filters.addAll(getPostRippleFilters()); - } - return filters; - } - - -} diff --git a/blade-patchca/src/main/java/org/patchca/filter/predefined/WobbleRippleFilterFactory.java b/blade-patchca/src/main/java/org/patchca/filter/predefined/WobbleRippleFilterFactory.java deleted file mode 100644 index 3b5094e32..000000000 --- a/blade-patchca/src/main/java/org/patchca/filter/predefined/WobbleRippleFilterFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.filter.predefined; - -import org.patchca.filter.library.WobbleImageOp; - -import java.awt.image.BufferedImageOp; -import java.util.ArrayList; -import java.util.List; - - -public class WobbleRippleFilterFactory extends RippleFilterFactory { - - protected WobbleImageOp wobble; - - public WobbleRippleFilterFactory() { - wobble = new WobbleImageOp(); - } - @Override - protected List getPreRippleFilters() { - List list = new ArrayList(); - list.add(wobble); - return list; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/font/FontFactory.java b/blade-patchca/src/main/java/org/patchca/font/FontFactory.java deleted file mode 100644 index 6438406c8..000000000 --- a/blade-patchca/src/main/java/org/patchca/font/FontFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.font; - -import java.awt.*; - -public interface FontFactory { - Font getFont(int index); -} diff --git a/blade-patchca/src/main/java/org/patchca/font/RandomFontFactory.java b/blade-patchca/src/main/java/org/patchca/font/RandomFontFactory.java deleted file mode 100644 index 80547d856..000000000 --- a/blade-patchca/src/main/java/org/patchca/font/RandomFontFactory.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.font; - -import java.awt.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; - -public class RandomFontFactory implements FontFactory { - - protected List families; - protected int minSize; - protected int maxSize; - protected boolean randomStyle; - - public RandomFontFactory() { - families = new ArrayList(); - families.add("Verdana"); - families.add("Tahoma"); - minSize = 45; - maxSize = 45; - } - - public RandomFontFactory(List families) { - this(); - this.families = families; - } - - public RandomFontFactory(String[] families) { - this(); - this.families = Arrays.asList(families); - } - - public RandomFontFactory(int size, List families) { - this(families); - minSize = maxSize = size; - } - - public RandomFontFactory(int size, String[] families) { - this(families); - minSize = maxSize = size; - } - - public void setFamilies(List families) { - this.families = families; - } - - public void setMinSize(int minSize) { - this.minSize = minSize; - } - - public void setMaxSize(int maxSize) { - this.maxSize = maxSize; - } - - public void setRandomStyle(boolean randomStyle) { - this.randomStyle = randomStyle; - } - - @Override - public Font getFont(int index) { - Random r = new Random(); - String family = families.get(r.nextInt(families.size())); - boolean bold = r.nextBoolean() && randomStyle; - int size = minSize; - if (maxSize - minSize > 0) { - size += r.nextInt(maxSize - minSize); - } - return new Font(family, bold ? Font.BOLD : Font.PLAIN, size); - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/service/AbstractCaptchaService.java b/blade-patchca/src/main/java/org/patchca/service/AbstractCaptchaService.java deleted file mode 100644 index d7a723fe6..000000000 --- a/blade-patchca/src/main/java/org/patchca/service/AbstractCaptchaService.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.service; - -import org.patchca.background.BackgroundFactory; -import org.patchca.color.ColorFactory; -import org.patchca.filter.FilterFactory; -import org.patchca.font.FontFactory; -import org.patchca.text.renderer.TextRenderer; -import org.patchca.word.WordFactory; - -import java.awt.image.BufferedImage; - -public abstract class AbstractCaptchaService implements CaptchaService { - - protected FontFactory fontFactory; - protected WordFactory wordFactory; - protected ColorFactory colorFactory; - protected BackgroundFactory backgroundFactory; - protected TextRenderer textRenderer; - protected FilterFactory filterFactory; - protected int width; - protected int height; - - public void setFontFactory(FontFactory fontFactory) { - this.fontFactory = fontFactory; - } - - public void setWordFactory(WordFactory wordFactory) { - this.wordFactory = wordFactory; - } - - public void setColorFactory(ColorFactory colorFactory) { - this.colorFactory = colorFactory; - } - - public void setBackgroundFactory(BackgroundFactory backgroundFactory) { - this.backgroundFactory = backgroundFactory; - } - - public void setTextRenderer(TextRenderer textRenderer) { - this.textRenderer = textRenderer; - } - - public void setFilterFactory(FilterFactory filterFactory) { - this.filterFactory = filterFactory; - } - - public FontFactory getFontFactory() { - return fontFactory; - } - - public WordFactory getWordFactory() { - return wordFactory; - } - - public ColorFactory getColorFactory() { - return colorFactory; - } - - public BackgroundFactory getBackgroundFactory() { - return backgroundFactory; - } - - public TextRenderer getTextRenderer() { - return textRenderer; - } - - public FilterFactory getFilterFactory() { - return filterFactory; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public void setWidth(int width) { - this.width = width; - } - - public void setHeight(int height) { - this.height = height; - } - - @Override - public Captcha getCaptcha() { - BufferedImage bufImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - backgroundFactory.fillBackground(bufImage); - String word = wordFactory.getNextWord(); - textRenderer.draw(word, bufImage, fontFactory, colorFactory); - bufImage = filterFactory.applyFilters(bufImage); - return new Captcha(word, bufImage); - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/service/Captcha.java b/blade-patchca/src/main/java/org/patchca/service/Captcha.java deleted file mode 100644 index c80ccad9b..000000000 --- a/blade-patchca/src/main/java/org/patchca/service/Captcha.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.service; - -import java.awt.image.BufferedImage; - -public class Captcha { - - private String challenge; - private BufferedImage image; - - public Captcha(String challenge, BufferedImage image) { - this.challenge = challenge; - this.image = image; - } - - public String getChallenge() { - return challenge; - } - - public void setChallenge(String challenge) { - this.challenge = challenge; - } - - public BufferedImage getImage() { - return image; - } - - public void setImage(BufferedImage image) { - this.image = image; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/service/CaptchaService.java b/blade-patchca/src/main/java/org/patchca/service/CaptchaService.java deleted file mode 100644 index b26f6d6da..000000000 --- a/blade-patchca/src/main/java/org/patchca/service/CaptchaService.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.service; - -public interface CaptchaService { - - Captcha getCaptcha(); -} diff --git a/blade-patchca/src/main/java/org/patchca/service/ConfigurableCaptchaService.java b/blade-patchca/src/main/java/org/patchca/service/ConfigurableCaptchaService.java deleted file mode 100644 index eeb9500f7..000000000 --- a/blade-patchca/src/main/java/org/patchca/service/ConfigurableCaptchaService.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.service; - -import org.patchca.background.SingleColorBackgroundFactory; -import org.patchca.color.SingleColorFactory; -import org.patchca.filter.predefined.CurvesRippleFilterFactory; -import org.patchca.font.RandomFontFactory; -import org.patchca.text.renderer.BestFitTextRenderer; -import org.patchca.word.AdaptiveRandomWordFactory; - -public class ConfigurableCaptchaService extends AbstractCaptchaService { - - public ConfigurableCaptchaService() { - backgroundFactory = new SingleColorBackgroundFactory(); - wordFactory = new AdaptiveRandomWordFactory(); - fontFactory = new RandomFontFactory(); - textRenderer = new BestFitTextRenderer(); - colorFactory = new SingleColorFactory(); - filterFactory = new CurvesRippleFilterFactory(colorFactory); - textRenderer.setLeftMargin(10); - textRenderer.setRightMargin(10); - width = 160; - height = 70; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/service/SimpleCaptchaService.java b/blade-patchca/src/main/java/org/patchca/service/SimpleCaptchaService.java deleted file mode 100644 index 55311a6c5..000000000 --- a/blade-patchca/src/main/java/org/patchca/service/SimpleCaptchaService.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.service; - -import org.patchca.background.SingleColorBackgroundFactory; -import org.patchca.color.SingleColorFactory; -import org.patchca.filter.FilterFactory; -import org.patchca.font.RandomFontFactory; -import org.patchca.text.renderer.BestFitTextRenderer; -import org.patchca.word.AdaptiveRandomWordFactory; - -import java.awt.*; - -public class SimpleCaptchaService extends AbstractCaptchaService { - - public SimpleCaptchaService(int width, int height, Color textColor, Color backgroundColor, int fontSize, FilterFactory ff) { - backgroundFactory = new SingleColorBackgroundFactory(backgroundColor); - wordFactory = new AdaptiveRandomWordFactory(); - fontFactory = new RandomFontFactory(); - textRenderer = new BestFitTextRenderer(); - colorFactory = new SingleColorFactory(textColor); - filterFactory = ff; - this.width = width; - this.height = height; - } - - public SimpleCaptchaService(int width, int height, Color textColor, Color backgroundColor, int fontSize, String[]fontNames, FilterFactory ff) { - backgroundFactory = new SingleColorBackgroundFactory(backgroundColor); - wordFactory = new AdaptiveRandomWordFactory(); - fontFactory = new RandomFontFactory(fontNames); - textRenderer = new BestFitTextRenderer(); - colorFactory = new SingleColorFactory(textColor); - filterFactory = ff; - this.width = width; - this.height = height; - } - - @Override - public Captcha getCaptcha() { - return null; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/AbstractTextRenderer.java b/blade-patchca/src/main/java/org/patchca/text/renderer/AbstractTextRenderer.java deleted file mode 100644 index 95044db75..000000000 --- a/blade-patchca/src/main/java/org/patchca/text/renderer/AbstractTextRenderer.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.text.renderer; - -import org.patchca.color.ColorFactory; -import org.patchca.font.FontFactory; - -import java.awt.*; -import java.awt.font.FontRenderContext; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; - -public abstract class AbstractTextRenderer implements TextRenderer { - - protected int leftMargin; - protected int rightMargin; - protected int topMargin; - protected int bottomMargin; - - protected abstract void arrangeCharacters(int width, int height, TextString ts); - - public AbstractTextRenderer() { - leftMargin = rightMargin = 5; - topMargin = bottomMargin = 5; - } - - @Override - public void setLeftMargin(int leftMargin) { - this.leftMargin = leftMargin; - } - - @Override - public void setRightMargin(int rightMargin) { - this.rightMargin = rightMargin; - } - - @Override - public void setTopMargin(int topMargin) { - this.topMargin = topMargin; - } - - @Override - public void setBottomMargin(int bottomMargin) { - this.bottomMargin = bottomMargin; - } - - @Override - public void draw(String text, BufferedImage canvas, FontFactory fontFactory, ColorFactory colorFactory) { - Graphics2D g = (Graphics2D) canvas.getGraphics(); - TextString ts = convertToCharacters(text, g, fontFactory, colorFactory); - arrangeCharacters(canvas.getWidth(), canvas.getHeight(), ts); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - for (TextCharacter tc : ts.getCharacters()) { - g.setColor(tc.getColor()); - g.drawString(tc.iterator(), (float) tc.getX(), (float) tc.getY()); - } - } - - protected TextString convertToCharacters(String text, Graphics2D g, FontFactory fontFactory, ColorFactory colorFactory) { - TextString characters = new TextString(); - FontRenderContext frc = g.getFontRenderContext(); - double lastx = 0; - for (int i = 0; i < text.length(); i++) { - Font font = fontFactory.getFont(i); - char c = text.charAt(i); - FontMetrics fm = g.getFontMetrics(font); - Rectangle2D bounds = font.getStringBounds(String.valueOf(c), frc); - TextCharacter tc = new TextCharacter(); - tc.setCharacter(c); - tc.setFont(font); - tc.setWidth(fm.charWidth(c)); - tc.setHeight(fm.getAscent() + fm.getDescent()); - tc.setAscent(fm.getAscent()); - tc.setDescent(fm.getDescent()); - tc.setX(lastx); - tc.setY(0); - tc.setFont(font); - tc.setColor(colorFactory.getColor(i)); - lastx += bounds.getWidth(); - characters.addCharacter(tc); - } - return characters; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/BestFitTextRenderer.java b/blade-patchca/src/main/java/org/patchca/text/renderer/BestFitTextRenderer.java deleted file mode 100644 index 60762edcd..000000000 --- a/blade-patchca/src/main/java/org/patchca/text/renderer/BestFitTextRenderer.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.text.renderer; - -public class BestFitTextRenderer extends AbstractTextRenderer { - - @Override - protected void arrangeCharacters(int width, int height, TextString ts) { - double widthRemaining = (width - ts.getWidth() - leftMargin - rightMargin) / ts.getCharacters().size(); - double x = leftMargin + widthRemaining / 2; - height -= topMargin + bottomMargin; - for (TextCharacter tc : ts.getCharacters()) { - double y = topMargin + (height + tc.getAscent() * 0.7) / 2; - tc.setX(x); - tc.setY(y); - x += tc.getWidth() + widthRemaining; - } - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/RandomYBestFitTextRenderer.java b/blade-patchca/src/main/java/org/patchca/text/renderer/RandomYBestFitTextRenderer.java deleted file mode 100644 index b6a4250a4..000000000 --- a/blade-patchca/src/main/java/org/patchca/text/renderer/RandomYBestFitTextRenderer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.text.renderer; - -import java.util.Random; - -public class RandomYBestFitTextRenderer extends AbstractTextRenderer { - - @Override - protected void arrangeCharacters(int width, int height, TextString ts) { - double widthRemaining = (width - ts.getWidth() - leftMargin - rightMargin) / ts.getCharacters().size(); - double vmiddle = height / 2; - double x = leftMargin + widthRemaining / 2; - Random r = new Random(); - height -= topMargin + bottomMargin; - for (TextCharacter tc : ts.getCharacters()) { - double heightRemaining = height - tc.getHeight(); - double y = vmiddle + 0.35 * tc.getAscent() + (1 - 2 * r.nextDouble()) * heightRemaining; - tc.setX(x); - tc.setY(y); - x += tc.getWidth() + widthRemaining; - } - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/SimpleTextRenderer.java b/blade-patchca/src/main/java/org/patchca/text/renderer/SimpleTextRenderer.java deleted file mode 100644 index dc68afc35..000000000 --- a/blade-patchca/src/main/java/org/patchca/text/renderer/SimpleTextRenderer.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.text.renderer; - -public class SimpleTextRenderer extends AbstractTextRenderer { - - @Override - protected void arrangeCharacters(int width, int height, TextString ts) { - double x = leftMargin; - for (TextCharacter tc : ts.getCharacters()) { - double y = topMargin + (height + tc.getAscent() * 0.7) / 2; - tc.setX(x); - tc.setY(y); - x += tc.getWidth(); - } - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/TextCharacter.java b/blade-patchca/src/main/java/org/patchca/text/renderer/TextCharacter.java deleted file mode 100644 index 4e0e025f2..000000000 --- a/blade-patchca/src/main/java/org/patchca/text/renderer/TextCharacter.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.text.renderer; - -import java.awt.*; -import java.awt.font.TextAttribute; -import java.text.AttributedCharacterIterator; -import java.text.AttributedString; - -public class TextCharacter { - - private double x; - private double y; - private double width; - private double height; - private double ascent; - private double descent; - private char character; - private Font font; - private Color color; - - public double getX() { - return x; - } - - public void setX(double x) { - this.x = x; - } - - public double getY() { - return y; - } - - public void setY(double y) { - this.y = y; - } - - public double getWidth() { - return width; - } - - public void setWidth(double width) { - this.width = width; - } - - public double getHeight() { - return height; - } - - public void setHeight(double height) { - this.height = height; - } - - public char getCharacter() { - return character; - } - - public void setCharacter(char character) { - this.character = character; - } - - public Font getFont() { - return font; - } - - public void setFont(Font font) { - this.font = font; - } - - public Color getColor() { - return color; - } - - public void setColor(Color color) { - this.color = color; - } - - public double getAscent() { - return ascent; - } - - public void setAscent(double ascent) { - this.ascent = ascent; - } - - public double getDescent() { - return descent; - } - - public void setDescent(double descent) { - this.descent = descent; - } - - public AttributedCharacterIterator iterator() { - AttributedString aString = new AttributedString(String - .valueOf(character)); - aString.addAttribute(TextAttribute.FONT, font, 0, 1); - return aString.getIterator(); - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/TextRenderer.java b/blade-patchca/src/main/java/org/patchca/text/renderer/TextRenderer.java deleted file mode 100644 index 24caf7e37..000000000 --- a/blade-patchca/src/main/java/org/patchca/text/renderer/TextRenderer.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.text.renderer; - -import org.patchca.color.ColorFactory; -import org.patchca.font.FontFactory; - -import java.awt.image.BufferedImage; - -public interface TextRenderer { - - void setLeftMargin(int leftMargin); - - void setRightMargin(int rightMargin); - - void setTopMargin(int topMargin); - - void setBottomMargin(int bottomMargin); - - void draw(String text, BufferedImage canvas, FontFactory fontFactory, ColorFactory colorFactory); - -} diff --git a/blade-patchca/src/main/java/org/patchca/text/renderer/TextString.java b/blade-patchca/src/main/java/org/patchca/text/renderer/TextString.java deleted file mode 100644 index 903324fcd..000000000 --- a/blade-patchca/src/main/java/org/patchca/text/renderer/TextString.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.text.renderer; - -import java.util.ArrayList; - -public class TextString { - - private ArrayList characters = new ArrayList(); - - public void clear() { - characters.clear(); - } - - public void addCharacter(TextCharacter tc) { - characters.add(tc); - } - - public ArrayList getCharacters() { - return characters; - } - - public double getWidth() { - double minx = 0; - double maxx = 0; - boolean first = true; - for (TextCharacter tc : characters) { - if (first) { - minx = tc.getX(); - maxx = tc.getX() + tc.getWidth(); - first = false; - } else { - if (minx > tc.getX()) { - minx = tc.getX(); - } - if (maxx < tc.getX() + tc.getWidth()) { - maxx = tc.getX() + tc.getWidth(); - } - } - - } - return maxx - minx; - } - - public double getHeight() { - double miny = 0; - double maxy = 0; - boolean first = true; - for (TextCharacter tc : characters) { - if (first) { - miny = tc.getY(); - maxy = tc.getY() + tc.getHeight(); - first = false; - } else { - if (miny > tc.getY()) { - miny = tc.getY(); - } - if (maxy < tc.getY() + tc.getHeight()) { - maxy = tc.getY() + tc.getHeight(); - } - } - - } - return maxy - miny; - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/utils/encoder/EncoderHelper.java b/blade-patchca/src/main/java/org/patchca/utils/encoder/EncoderHelper.java deleted file mode 100644 index d34af1e7a..000000000 --- a/blade-patchca/src/main/java/org/patchca/utils/encoder/EncoderHelper.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.utils.encoder; - -import org.patchca.service.Captcha; -import org.patchca.service.CaptchaService; - -import javax.imageio.ImageIO; -import java.io.IOException; -import java.io.OutputStream; - -public class EncoderHelper { - - public static String getChallangeAndWriteImage(CaptchaService service, String format, OutputStream os) throws IOException { - Captcha captcha = service.getCaptcha(); - ImageIO.write(captcha.getImage(), format, os); - return captcha.getChallenge(); - } - -} - diff --git a/blade-patchca/src/main/java/org/patchca/word/AdaptiveRandomWordFactory.java b/blade-patchca/src/main/java/org/patchca/word/AdaptiveRandomWordFactory.java deleted file mode 100644 index c0de231a4..000000000 --- a/blade-patchca/src/main/java/org/patchca/word/AdaptiveRandomWordFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.word; - -import java.util.Random; - -public class AdaptiveRandomWordFactory extends RandomWordFactory { - - protected String wideCharacters; - - public void setWideCharacters(String wideCharacters) { - this.wideCharacters = wideCharacters; - } - - public AdaptiveRandomWordFactory() { - characters = "absdegkmnopwx23456789"; - wideCharacters = "mw"; - } - - @Override - public String getNextWord() { - Random rnd = new Random(); - StringBuffer sb = new StringBuffer(); - StringBuffer chars = new StringBuffer(characters); - int l = minLength + (maxLength > minLength ? rnd.nextInt(maxLength - minLength) : 0); - for (int i = 0; i < l; i++) { - int j = rnd.nextInt(chars.length()); - char c = chars.charAt(j); - if (wideCharacters.indexOf(c) != -1) { - for (int k = 0; k < wideCharacters.length(); k++) { - int idx = chars.indexOf(String.valueOf(wideCharacters.charAt(k))); - if (idx != -1) { - chars.deleteCharAt(idx); - } - } - } - sb.append(c); - } - return sb.toString(); - } - -} diff --git a/blade-patchca/src/main/java/org/patchca/word/RandomWordFactory.java b/blade-patchca/src/main/java/org/patchca/word/RandomWordFactory.java deleted file mode 100644 index f1848fbf8..000000000 --- a/blade-patchca/src/main/java/org/patchca/word/RandomWordFactory.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.word; - -import java.util.Random; - -public class RandomWordFactory implements WordFactory { - - protected String characters; - protected int minLength; - protected int maxLength; - - public void setCharacters(String characters) { - this.characters = characters; - } - - public void setMinLength(int minLength) { - this.minLength = minLength; - } - - public void setMaxLength(int maxLength) { - this.maxLength = maxLength; - } - - public RandomWordFactory() { - characters = "absdegkmnopwx23456789"; - minLength = 6; - maxLength = 6; - } - - @Override - public String getNextWord() { - Random rnd = new Random(); - StringBuffer sb = new StringBuffer(); - int l = minLength + (maxLength > minLength ? rnd.nextInt(maxLength - minLength) : 0); - for (int i = 0; i < l; i++) { - int j = rnd.nextInt(characters.length()); - sb.append(characters.charAt(j)); - } - return sb.toString(); - } - - -} diff --git a/blade-patchca/src/main/java/org/patchca/word/WordFactory.java b/blade-patchca/src/main/java/org/patchca/word/WordFactory.java deleted file mode 100644 index d410bfc60..000000000 --- a/blade-patchca/src/main/java/org/patchca/word/WordFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2009 Piotr Piastucki - * - * This file is part of Patchca CAPTCHA library. - * - * Patchca is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Patchca is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Patchca. If not, see . - */ -package org.patchca.word; - -public interface WordFactory { - - String getNextWord(); -} diff --git a/blade-patchca/src/test/java/org/blade/patchca/AppTest.java b/blade-patchca/src/test/java/org/blade/patchca/AppTest.java deleted file mode 100644 index 011975764..000000000 --- a/blade-patchca/src/test/java/org/blade/patchca/AppTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.blade.patchca; - -import java.io.IOException; - -import com.blade.patchca.PatchcaService; - -public class AppTest { - - public static void main(String[] args) throws IOException { - - PatchcaService service = PatchcaService.get(); - // 生成一个验证码到本地 - service.create("F:/aaa.png", "png"); - } -} diff --git a/blade-redis/README.md b/blade-redis/README.md deleted file mode 100644 index ec29a7327..000000000 --- a/blade-redis/README.md +++ /dev/null @@ -1,158 +0,0 @@ -# Blade-Redis - -在java中更方便的操作redis数据库,基于`blade`框架继承,支持多数据库集群配置。 - -##使用 - -```java -// 配置 -RedisPlugin redisPlugin = RedisPlugin.me(); -redisPlugin.host("127.0.0.1", 6379); -redisPlugin.run(); -``` - -* 使用redis -```java -JedisCache jedisCache = new JedisCache(); - -//基础操作,更多请查看源代码 -public String set(final String key, final String value) { - return super.setString(key, value); -} - -public String set(final String key, final Serializable value) { - return super.setObject(key, value); -} - -public String set(final String key, final String value, final int timeout) { - return super.setString(key, value, timeout); -} - -public Long hset(final String key, final String field, final String value) { - return super.hashSet(key, field, value); -} - -public Long hset(final String key, final String field, final String value, final int timeout) { - return super.hashSet(key, field, value, timeout); -} - -public String hset(final String key, final Map map) { - return super.hashMultipleSet(key, map); -} - -public String hset(final String key, Map map, final int timeout) { - return super.hashMultipleSet(key, map, timeout); -} - -public Long hset(final String key, final String field, final Serializable value) { - return super.hset(key, field, value); -} - -public Long hset(final String key, final String field, final Serializable value, int timeout) { - return super.hset(key, field, value, timeout); -} - -public boolean exists(final String key, final String field) { - return super.exists(key, field); -} - -public boolean exists(final String key) { - return super.exists(key); -} - -public Long del(final String key) { - return super.delKey(key); -} - -public Long del(final String key, final String field) { - return super.delKey(key, field); -} - -public T get(final String key) { - return super.get(key); -} - -public String get(final String key, final String field) { - return super.hashGet(key, field); -} - -public Map getAllHash(final String key) { - return super.hashGetAll(key); -} - -public Serializable getModel(final String key, final String field) { - return SerializeKit.unserialize(super.hashGet(key, field).getBytes()); -} - -public List getSet(final String key, final Integer start, final Integer end) { - return super.listRange(key, start, end); -} - -public Set getKeys(final String pattern) { - return super.getKeyLike(pattern); -} - -public Long delLike(final String patten) { - return super.delKeysLike(patten); -} - -public String hget(final String key, final String field) { - return super.hashGet(key, field); -} - -public String hget(final String key, final String field, final int timeout) { - return super.hashGet(key, field, timeout); -} - -public String hget(String key, Map map) { - return super.hashMultipleSet(key, map); -} - -public Long hcount(String key) { - return super.hashLen(key); -} - -public Long sadd(String key, String... members) { - return super.sadd(key, members); -} - -public Long srem(String key, String... members) { - return super.srem(key, members); -} - -public Set sunion(String... keys) { - return super.sunion(keys); -} - -public Set sdiff(String... keys) { - return super.sdiff(keys); -} - -public Long scard(String key) { - return super.scard(key); -} - -public Long lpush(String key, String... values) { - return super.listPushHead(key, values); -} - -public Long rpush(String key, String... values) { - return super.listPushTail(key, values); -} - -public Long lpushTrim(String key, String value, long size) { - return super.listPushHeadAndTrim(key, value, size); -} - -public Long ldel(String key, String value) { - return super.listDel(key, value, -1); -} - -public Long llength(String key) { - return super.listLen(key); -} - -public T hgetModel(String key, String field) { - return super.hgetObj(key, field); -} -``` diff --git a/blade-redis/pom.xml b/blade-redis/pom.xml deleted file mode 100644 index fbbbfc706..000000000 --- a/blade-redis/pom.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-redis - jar - 1.4.0-alpha - blade-redis - https://github.com/biezhi/blade/blade-redis - - - - com.bladejava - blade-core - ${blade.version} - provided - - - redis.clients - jedis - 2.7.3 - - - diff --git a/blade-redis/src/main/java/blade/plugin/redis/JedisCache.java b/blade-redis/src/main/java/blade/plugin/redis/JedisCache.java deleted file mode 100644 index a122cba1c..000000000 --- a/blade-redis/src/main/java/blade/plugin/redis/JedisCache.java +++ /dev/null @@ -1,157 +0,0 @@ -package blade.plugin.redis; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import blade.kit.SerializeKit; - -/** - * jedis tool - * @author:biezhi - * @version:1.0 - */ -public class JedisCache extends RedisExecutor { - - public String set(final String key, final String value) { - return super.setString(key, value); - } - - public String set(final String key, final Serializable value) { - return super.setObject(key, value); - } - - public String set(final String key, final String value, final int timeout) { - return super.setString(key, value, timeout); - } - - public Long hset(final String key, final String field, final String value) { - return super.hashSet(key, field, value); - } - - public Long hset(final String key, final String field, final String value, final int timeout) { - return super.hashSet(key, field, value, timeout); - } - - public String hset(final String key, final Map map) { - return super.hashMultipleSet(key, map); - } - - public String hset(final String key, Map map, final int timeout) { - return super.hashMultipleSet(key, map, timeout); - } - - public Long hset(final String key, final String field, final Serializable value) { - return super.hset(key, field, value); - } - - public Long hset(final String key, final String field, final Serializable value, int timeout) { - return super.hset(key, field, value, timeout); - } - - public boolean exists(final String key, final String field) { - return super.exists(key, field); - } - - public boolean exists(final String key) { - return super.exists(key); - } - - public Long del(final String key) { - return super.delKey(key); - } - - public Long del(final String key, final String field) { - return super.delKey(key, field); - } - - public T get(final String key) { - return super.get(key); - } - - public String get(final String key, final String field) { - return super.hashGet(key, field); - } - - public Map getAllHash(final String key) { - return super.hashGetAll(key); - } - - public Serializable getModel(final String key, final String field) { - return SerializeKit.unserialize(super.hashGet(key, field).getBytes()); - } - - public List getSet(final String key, final Integer start, final Integer end) { - return super.listRange(key, start, end); - } - - public Set getKeys(final String pattern) { - return super.getKeyLike(pattern); - } - - public Long delLike(final String patten) { - return super.delKeysLike(patten); - } - - public String hget(final String key, final String field) { - return super.hashGet(key, field); - } - - public String hget(final String key, final String field, final int timeout) { - return super.hashGet(key, field, timeout); - } - - public String hget(String key, Map map) { - return super.hashMultipleSet(key, map); - } - - public Long hcount(String key) { - return super.hashLen(key); - } - - public Long sadd(String key, String... members) { - return super.sadd(key, members); - } - - public Long srem(String key, String... members) { - return super.srem(key, members); - } - - public Set sunion(String... keys) { - return super.sunion(keys); - } - - public Set sdiff(String... keys) { - return super.sdiff(keys); - } - - public Long scard(String key) { - return super.scard(key); - } - - public Long lpush(String key, String... values) { - return super.listPushHead(key, values); - } - - public Long rpush(String key, String... values) { - return super.listPushTail(key, values); - } - - public Long lpushTrim(String key, String value, long size) { - return super.listPushHeadAndTrim(key, value, size); - } - - public Long ldel(String key, String value) { - return super.listDel(key, value, -1); - } - - public Long llength(String key) { - return super.listLen(key); - } - - public T hgetModel(String key, String field) { - return super.hgetObj(key, field); - } - -} diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java b/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java deleted file mode 100644 index fc4d89cfc..000000000 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisExecutor.java +++ /dev/null @@ -1,1459 +0,0 @@ -package blade.plugin.redis; - -import java.io.Serializable; -import java.util.*; - -import redis.clients.jedis.*; -import redis.clients.util.SafeEncoder; -import blade.kit.SerializeKit; - -/** - * Redis的辅助类,负责对内存数据库的所有操作 - * - * @author biezhi - * @since 1.0 - */ -public class RedisExecutor { - - // 数据源 - private static ShardedJedisPool shardedJedisPool; - - private static RedisPoolConfig redisPoolConfig = RedisPlugin.me().redisPoolConfig(); - - static void init(){ - // 根据配置文件,创建shared池实例 - shardedJedisPool = new ShardedJedisPool(redisPoolConfig, RedisPlugin.me().shards()); - } - - /** - * 执行器, 它保证在执行操作之后释放数据源returnResource(jedis) - */ - abstract class Executor { - - ShardedJedis jedis; - - ShardedJedisPool shardedJedisPool; - - public Executor(ShardedJedisPool shardedJedisPool) { - this.shardedJedisPool = shardedJedisPool; - jedis = this.shardedJedisPool.getResource(); - } - - /** - * 回调 - * - * @return 执行结果 - */ - abstract T execute(); - - /** - * 调用{@link #execute()}并返回执行结果 它保证在执行{@link #execute()}之后释放数据源returnResource(jedis) - * - * @return 执行结果 - */ - public T getResult() { - T result = null; - try { - result = execute(); - } catch (Throwable e) { - if (null != jedis) { - jedis.close(); - } - throw new RuntimeException("Redis execute exception", e); - } finally { - if (null != jedis) { - jedis.close(); - } - } - return result; - } - } - - /** - * @return 返回ShardedJedis实例 - */ - public ShardedJedis getShardedJedis(){ - return RedisExecutor.shardedJedisPool.getResource(); - } - - /** - * 获取模糊匹配的key - * - * @param likeKey 模糊匹配的key - * @return 匹配key的集合 - */ - public Set getKeyLike(final String likeKey) { - return new Executor>(shardedJedisPool) { - final String pattern = likeKey + "*"; - - @Override - Set execute() { - Collection jedisC = jedis.getAllShards(); - Iterator iter = jedisC.iterator(); - Set keys = new HashSet(); - while (iter.hasNext()) { - Jedis _jedis = iter.next(); - String cursor = "0"; - while (true) { - ScanResult result = _jedis.scan(cursor, new ScanParams().match(pattern)); - keys.addAll(result.getResult()); - cursor = result.getStringCursor(); - if ("0".equals(cursor)) { - break; - } - } - } - return keys; - } - }.getResult(); - } - - /** - * 删除模糊匹配的key - * - * @param likeKey 模糊匹配的key - * @return 删除成功的条数 - */ - public long delKeysLike(final String likeKey) { - final String pattern = likeKey + "*"; - - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - Collection jedisC = jedis.getAllShards(); - Iterator iter = jedisC.iterator(); - long count = 0; - while (iter.hasNext()) { - Jedis _jedis = iter.next(); - Set keys = new HashSet(); - String cursor = "0"; - while (true) { - ScanResult result = _jedis.scan(cursor, new ScanParams().match(pattern)); - keys.addAll(result.getResult()); - cursor = result.getStringCursor(); - if ("0".equals(cursor)) { - break; - } - } - count += _jedis.del(keys.toArray(new String[keys.size()])); - } - return count; - } - }.getResult(); - } - - /** - * 删除 - * - * @param key 匹配的key - * @return 删除成功的条数 - */ - public Long delKey(final String key) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.del(key); - } - }.getResult(); - } - - /** - * 排序 - * @param key - * @return - */ - public List sort(final String key) { - return new Executor>(shardedJedisPool) { - - @Override - List execute() { - return jedis.sort(key); - } - }.getResult(); - } - - /** - * 删除 - * - * @param key 匹配的key - * @return 删除成功的条数 - */ - public Long delKey(final String key, final String... fileds) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.hdel(key, fileds); - } - }.getResult(); - } - - /** - * 删除 - * - * @param keys 匹配的key的集合 - * @return 删除成功的条数 - */ - public Long delKeys(final String[] keys) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - Collection jedisC = jedis.getAllShards(); - Iterator iter = jedisC.iterator(); - long count = 0; - while (iter.hasNext()) { - Jedis _jedis = iter.next(); - count += _jedis.del(keys); - } - return count; - } - }.getResult(); - } - - /** - * 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。 在 Redis 中,带有生存时间的 key 被称为『可挥发』(volatile)的。 - * - * @param key key - * @param expire 生命周期,单位为秒 - * @return 1: 设置成功 0: 已经超时或key不存在 - */ - public Long expire(final String key, final int expire) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.expire(key, expire); - } - }.getResult(); - } - - /** - * 一个跨jvm的id生成器,利用了redis原子性操作的特点 - * - * @param key id的key - * @return 返回生成的Id - */ - public long makeId(final String key) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - long id = jedis.incr(key); - if ((id + 75807) >= Long.MAX_VALUE) { - // 避免溢出,重置,getSet命令之前允许incr插队,75807就是预留的插队空间 - jedis.getSet(key, "0"); - } - return id; - } - }.getResult(); - } - - public boolean exists(final String key) { - return new Executor(shardedJedisPool) { - - @Override - Boolean execute() { - return jedis.exists(key); - } - }.getResult(); - } - - public boolean exists(final String key, final String field) { - return new Executor(shardedJedisPool) { - - @Override - Boolean execute() { - return jedis.hexists(key, field); - } - }.getResult(); - } - - /* ======================================Strings====================================== */ - - /** - * 将字符串值 value 关联到 key 。 如果 key 已经持有其他值, setString 就覆写旧值,无视类型。 对于某个原本带有生存时间(TTL)的键来说, 当 setString 成功在这个键上执行时, 这个键原有的 TTL 将被清除。 时间复杂度:O(1) - * - * @param key key - * @param value string value - * @return 在设置操作成功完成时,才返回 OK 。 - */ - public String setString(final String key, final String value) { - return new Executor(shardedJedisPool) { - - @Override - String execute() { - return jedis.set(key, value); - } - }.getResult(); - } - - /** - * 将值 value 关联到 key ,并将 key 的生存时间设为 expire (以秒为单位)。 如果 key 已经存在, 将覆写旧值。 类似于以下两个命令: SET key value EXPIRE key expire # 设置生存时间 - * 不同之处是这个方法是一个原子性(atomic)操作,关联值和设置生存时间两个动作会在同一时间内完成,在 Redis 用作缓存时,非常实用。 时间复杂度:O(1) - * - * @param key key - * @param value string value - * @param expire 生命周期 - * @return 设置成功时返回 OK 。当 expire 参数不合法时,返回一个错误。 - */ - public String setString(final String key, final String value, final int expire) { - return new Executor(shardedJedisPool) { - - @Override - String execute() { - return jedis.setex(key, expire, value); - } - }.getResult(); - } - - /** - * 将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 setStringIfNotExists 不做任何动作。 时间复杂度:O(1) - * - * @param key key - * @param value string value - * @return 设置成功,返回 1 。设置失败,返回 0 。 - */ - public Long setStringIfNotExists(final String key, final String value) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.setnx(key, value); - } - }.getResult(); - } - - /** - * //TODO 将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 setStringIfNotExists 不做任何动作。 时间复杂度:O(1) - * - * @param key - * @param value - * @return - */ - public String setObject(final String key, final Serializable value) { - return new Executor(shardedJedisPool) { - - @Override - String execute() { - return jedis.set(SafeEncoder.encode(key), SerializeKit.serialize(value)); - } - }.getResult(); - } - - /** - * //TODO 将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 setStringIfNotExists 不做任何动作。 时间复杂度:O(1) - * - * @param key - * @param value - * @param expire - * @return - */ - public String setObject(final String key, final Serializable value, final int expire) { - return new Executor(shardedJedisPool) { - - @Override - String execute() { - return jedis.setex(key.getBytes(), expire, SerializeKit.serialize(value)); - } - }.getResult(); - } - - /** - * //TODO 添加方法功能描述 - * - * @param key - * @param field - * @param value - * @return - */ - public Long hset(final String key, final String field, final Serializable value) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.hset(key.getBytes(), field.getBytes(), SerializeKit.serialize(value)); - } - }.getResult(); - } - - public Long hset(final String key, final String field, final Serializable value, final int expire) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - Pipeline pipeline = jedis.getShard(key).pipelined(); - Response result = pipeline.hset(key.getBytes(), field.getBytes(), SerializeKit.serialize(value)); - pipeline.expire(key, expire); - pipeline.sync(); - return result.get(); - } - }.getResult(); - } - - /** - * 返回 key 所关联的字符串值。如果 key 不存在那么返回特殊值 nil 。 假如 key 储存的值不是字符串类型,返回一个错误,因为 getString 只能用于处理字符串值。 时间复杂度: O(1) - * - * @param key key - * @return 当 key 不存在时,返回 nil ,否则,返回 key 的值。如果 key 不是字符串类型,那么返回一个错误。 - */ - public String getString(final String key) { - return new Executor(shardedJedisPool) { - - @Override - String execute() { - return jedis.get(key); - } - }.getResult(); - } - - public T get(final String key) { - return new Executor(shardedJedisPool) { - - @SuppressWarnings("unchecked") - @Override - T execute() { - Object result = null; - byte[] retVal = jedis.get(SafeEncoder.encode(key)); - if (null != retVal) { - try { - result = SerializeKit.unserialize(retVal); - } catch (Exception e) { - result = SafeEncoder.encode(retVal); - } - } - return (T) result; - } - }.getResult(); - } - - /** - * 批量的 {@link #setString(String, String)} - * - * @param pairs 键值对数组{数组第一个元素为key,第二个元素为value} - * @return 操作状态的集合 - */ - public List batchSetString(final List> pairs) { - return new Executor>(shardedJedisPool) { - - @Override - List execute() { - ShardedJedisPipeline pipeline = jedis.pipelined(); - for (Pair pair : pairs) { - pipeline.set(pair.getKey(), pair.getValue()); - } - return pipeline.syncAndReturnAll(); - } - }.getResult(); - } - - /** - * 批量的 {@link #getString(String)} - * - * @param keys key数组 - * @return value的集合 - */ - public List batchGetString(final String[] keys) { - return new Executor>(shardedJedisPool) { - - @Override - List execute() { - ShardedJedisPipeline pipeline = jedis.pipelined(); - List result = new ArrayList(keys.length); - List> responses = new ArrayList>(keys.length); - for (String key : keys) { - responses.add(pipeline.get(key)); - } - pipeline.sync(); - for (Response resp : responses) { - result.add(resp.get()); - } - return result; - } - }.getResult(); - } - - /* ======================================Hashes====================================== */ - - /** - * 将哈希表 key 中的域 field 的值设为 value 。 如果 key 不存在,一个新的哈希表被创建并进行 hashSet 操作。 如果域 field 已经存在于哈希表中,旧值将被覆盖。 时间复杂度: O(1) - * - * @param key key - * @param field 域 - * @param value string value - * @return 如果 field 是哈希表中的一个新建域,并且值设置成功,返回 1 。如果哈希表中域 field 已经存在且旧值已被新值覆盖,返回 0 。 - */ - public Long hashSet(final String key, final String field, final String value) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.hset(key, field, value); - } - }.getResult(); - } - - /** - * 将哈希表 key 中的域 field 的值设为 value 。 如果 key 不存在,一个新的哈希表被创建并进行 hashSet 操作。 如果域 field 已经存在于哈希表中,旧值将被覆盖。 - * - * @param key key - * @param field 域 - * @param value string value - * @param expire 生命周期,单位为秒 - * @return 如果 field 是哈希表中的一个新建域,并且值设置成功,返回 1 。如果哈希表中域 field 已经存在且旧值已被新值覆盖,返回 0 。 - */ - public Long hashSet(final String key, final String field, final String value, final int expire) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - Pipeline pipeline = jedis.getShard(key).pipelined(); - Response result = pipeline.hset(key, field, value); - pipeline.expire(key, expire); - pipeline.sync(); - return result.get(); - } - }.getResult(); - } - - /** - * 返回哈希表 key 中给定域 field 的值。 时间复杂度:O(1) - * - * @param key key - * @param field 域 - * @return 给定域的值。当给定域不存在或是给定 key 不存在时,返回 nil 。 - */ - public String hashGet(final String key, final String field) { - return new Executor(shardedJedisPool) { - - @Override - String execute() { - return jedis.hget(key, field); - } - }.getResult(); - } - - /** - * 返回哈希表 key 中给定域 field 的值。 如果哈希表 key 存在,同时设置这个 key 的生存时间 - * - * @param key key - * @param field 域 - * @param expire 生命周期,单位为秒 - * @return 给定域的值。当给定域不存在或是给定 key 不存在时,返回 nil 。 - */ - public String hashGet(final String key, final String field, final int expire) { - return new Executor(shardedJedisPool) { - - @Override - String execute() { - Pipeline pipeline = jedis.getShard(key).pipelined(); - Response result = pipeline.hget(key, field); - pipeline.expire(key, expire); - pipeline.sync(); - return result.get(); - } - }.getResult(); - } - - /** - * 同时将多个 field-value (域-值)对设置到哈希表 key 中。 时间复杂度: O(N) (N为fields的数量) - * - * @param key key - * @param hash field-value的map - * @return 如果命令执行成功,返回 OK 。当 key 不是哈希表(hash)类型时,返回一个错误。 - */ - public String hashMultipleSet(final String key, final Map hash) { - return new Executor(shardedJedisPool) { - - @Override - String execute() { - return jedis.hmset(key, hash); - } - }.getResult(); - } - - /** - * 同时将多个 field-value (域-值)对设置到哈希表 key 中。同时设置这个 key 的生存时间 - * - * @param key key - * @param hash field-value的map - * @param expire 生命周期,单位为秒 - * @return 如果命令执行成功,返回 OK 。当 key 不是哈希表(hash)类型时,返回一个错误。 - */ - public String hashMultipleSet(final String key, final Map hash, final int expire) { - return new Executor(shardedJedisPool) { - - @Override - String execute() { - Pipeline pipeline = jedis.getShard(key).pipelined(); - Response result = pipeline.hmset(key, hash); - pipeline.expire(key, expire); - pipeline.sync(); - return result.get(); - } - }.getResult(); - } - - /** - * 返回哈希表 key 中,一个或多个给定域的值。如果给定的域不存在于哈希表,那么返回一个 nil 值。 时间复杂度: O(N) (N为fields的数量) - * - * @param key key - * @param fields field的数组 - * @return 一个包含多个给定域的关联值的表,表值的排列顺序和给定域参数的请求顺序一样。 - */ - public List hashMultipleGet(final String key, final String... fields) { - return new Executor>(shardedJedisPool) { - - @Override - List execute() { - return jedis.hmget(key, fields); - } - }.getResult(); - } - - /** - * 返回哈希表 key 中,一个或多个给定域的值。如果给定的域不存在于哈希表,那么返回一个 nil 值。 同时设置这个 key 的生存时间 - * - * @param key key - * @param fields field的数组 - * @param expire 生命周期,单位为秒 - * @return 一个包含多个给定域的关联值的表,表值的排列顺序和给定域参数的请求顺序一样。 - */ - public List hashMultipleGet(final String key, final int expire, final String... fields) { - return new Executor>(shardedJedisPool) { - - @Override - List execute() { - Pipeline pipeline = jedis.getShard(key).pipelined(); - Response> result = pipeline.hmget(key, fields); - pipeline.expire(key, expire); - pipeline.sync(); - return result.get(); - } - }.getResult(); - } - - /** - * 批量的{@link #hashMultipleSet(String, Map)},在管道中执行 - * - * @param pairs 多个hash的多个field - * @return 操作状态的集合 - */ - public List batchHashMultipleSet(final List>> pairs) { - return new Executor>(shardedJedisPool) { - - @Override - List execute() { - ShardedJedisPipeline pipeline = jedis.pipelined(); - for (Pair> pair : pairs) { - pipeline.hmset(pair.getKey(), pair.getValue()); - } - return pipeline.syncAndReturnAll(); - } - }.getResult(); - } - - /** - * 批量的{@link #hashMultipleSet(String, Map)},在管道中执行 - * - * @param data Map>格式的数据 - * @return 操作状态的集合 - */ - public List batchHashMultipleSet(final Map> data) { - return new Executor>(shardedJedisPool) { - - @Override - List execute() { - ShardedJedisPipeline pipeline = jedis.pipelined(); - for (Map.Entry> iter : data.entrySet()) { - pipeline.hmset(iter.getKey(), iter.getValue()); - } - return pipeline.syncAndReturnAll(); - } - }.getResult(); - } - - /** - * 批量的{@link #hashMultipleGet(String, String...)},在管道中执行 - * - * @param pairs 多个hash的多个field - * @return 执行结果的集合 - */ - public List> batchHashMultipleGet(final List> pairs) { - return new Executor>>(shardedJedisPool) { - - @Override - List> execute() { - ShardedJedisPipeline pipeline = jedis.pipelined(); - List> result = new ArrayList>(pairs.size()); - List>> responses = new ArrayList>>(pairs.size()); - for (Pair pair : pairs) { - responses.add(pipeline.hmget(pair.getKey(), pair.getValue())); - } - pipeline.sync(); - for (Response> resp : responses) { - result.add(resp.get()); - } - return result; - } - }.getResult(); - - } - - /** - * 返回哈希表 key 中,所有的域和值。在返回值里,紧跟每个域名(field name)之后是域的值(value),所以返回值的长度是哈希表大小的两倍。 时间复杂度: O(N) - * - * @param key key - * @return 以列表形式返回哈希表的域和域的值。若 key 不存在,返回空列表。 - */ - public Map hashGetAll(final String key) { - return new Executor>(shardedJedisPool) { - - @Override - Map execute() { - return jedis.hgetAll(key); - } - }.getResult(); - } - - /** - * 返回哈希表 key 中,所有的域和值。在返回值里,紧跟每个域名(field name)之后是域的值(value),所以返回值的长度是哈希表大小的两倍。 同时设置这个 key 的生存时间 - * - * @param key key - * @param expire 生命周期,单位为秒 - * @return 以列表形式返回哈希表的域和域的值。若 key 不存在,返回空列表。 - */ - public Map hashGetAll(final String key, final int expire) { - return new Executor>(shardedJedisPool) { - - @Override - Map execute() { - Pipeline pipeline = jedis.getShard(key).pipelined(); - Response> result = pipeline.hgetAll(key); - pipeline.expire(key, expire); - pipeline.sync(); - return result.get(); - } - }.getResult(); - } - - /** - * 获取hash的field数量 - * - * @param key - * @return - */ - public Long hashLen(final String key) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.hlen(key); - } - }.getResult(); - } - - /** - * 获取hash的field数量 - * - * @param key - * @return - */ - public Long hashLen(final String key, final int expire) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - Pipeline pipeline = jedis.getShard(key).pipelined(); - Response result = pipeline.hlen(key); - pipeline.expire(key, expire); - pipeline.sync(); - return result.get(); - } - }.getResult(); - } - - /** - * 返回 hash 的所有 field - * - * @param key - * @return - */ - public Set hashKeys(final String key) { - return new Executor>(shardedJedisPool) { - - @Override - Set execute() { - return jedis.hkeys(key); - } - }.getResult(); - } - - /** - * 返回 hash 的所有 field - * - * @param key - * @return - */ - public Set hashKeys(final String key, final int expire) { - return new Executor>(shardedJedisPool) { - - @Override - Set execute() { - Pipeline pipeline = jedis.getShard(key).pipelined(); - Response> result = pipeline.hkeys(key); - pipeline.expire(key, expire); - pipeline.sync(); - return result.get(); - } - }.getResult(); - } - - /** - * 批量的{@link #hashGetAll(String)} - * - * @param keys key的数组 - * @return 执行结果的集合 - */ - public List> batchHashGetAll(final String... keys) { - return new Executor>>(shardedJedisPool) { - - @Override - List> execute() { - ShardedJedisPipeline pipeline = jedis.pipelined(); - List> result = new ArrayList>(keys.length); - List>> responses = new ArrayList>>(keys.length); - for (String key : keys) { - responses.add(pipeline.hgetAll(key)); - } - pipeline.sync(); - for (Response> resp : responses) { - result.add(resp.get()); - } - return result; - } - }.getResult(); - } - - /** - * 批量的{@link #hashMultipleGet(String, String...)},与{@link #batchHashGetAll(String...)}不同的是,返回值为Map类型 - * - * @param keys key的数组 - * @return 多个hash的所有filed和value - */ - public Map> batchHashGetAllForMap(final String... keys) { - return new Executor>>(shardedJedisPool) { - - @Override - Map> execute() { - ShardedJedisPipeline pipeline = jedis.pipelined(); - - // 设置map容量防止rehash - int capacity = 1; - while ((int) (capacity * 0.75) <= keys.length) { - capacity <<= 1; - } - Map> result = new HashMap>(capacity); - List>> responses = new ArrayList>>(keys.length); - for (String key : keys) { - responses.add(pipeline.hgetAll(key)); - } - pipeline.sync(); - for (int i = 0; i < keys.length; ++i) { - result.put(keys[i], responses.get(i).get()); - } - return result; - } - }.getResult(); - } - - /* ======================================List====================================== */ - - /** - * 将一个或多个值 value 插入到列表 key 的表尾(最右边)。 - * - * @param key key - * @param values value的数组 - * @return 执行 listPushTail 操作后,表的长度 - */ - public Long listPushTail(final String key, final String... values) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.rpush(key, values); - } - }.getResult(); - } - - /** - * 将一个或多个值 value 插入到列表 key 的表头 - * - * @param key key - * @param values string value - * @return 执行 listPushHead 命令后,列表的长度。 - */ - public Long listPushHead(final String key, final String... values) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.lpush(key, values); - } - }.getResult(); - } - - /** - * list长度 - * - * @param key - * @return - */ - public Long listLen(final String key) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.llen(key); - } - }.getResult(); - } - - /** - * 将一个或多个值 value 插入到列表 key 的表头, 当列表大于指定长度是就对列表进行修剪(trim) - * - * @param key key - * @param value string value - * @param size 链表超过这个长度就修剪元素 - * @return 执行 listPushHeadAndTrim 命令后,列表的长度。 - */ - public Long listPushHeadAndTrim(final String key, final String value, final long size) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - Pipeline pipeline = jedis.getShard(key).pipelined(); - Response result = pipeline.lpush(key, value); - // 修剪列表元素, 如果 size - 1 比 end 下标还要大,Redis将 size 的值设置为 end 。 - pipeline.ltrim(key, 0, size - 1); - pipeline.sync(); - return result.get(); - } - }.getResult(); - } - - /** - * 移除从表尾到表头,第一个 value - * - * @param key - * @param value - * @return - */ - public Long listDel(final String key, final String value, final int index) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.lrem(key, index, value); - } - }.getResult(); - } - - /** - * 批量的{@link #listPushTail(String, String...)},以锁的方式实现 - * - * @param key key - * @param values value的数组 - * @param delOld 如果key存在,是否删除它。true 删除;false: 不删除,只是在行尾追加 - */ - public void batchListPushTail(final String key, final String[] values, final boolean delOld) { - new Executor(shardedJedisPool) { - - @Override - Object execute() { - if (delOld) { - RedisLock lock = new RedisLock(key, shardedJedisPool); - lock.lock(); - try { - Pipeline pipeline = jedis.getShard(key).pipelined(); - pipeline.del(key); - for (String value : values) { - pipeline.rpush(key, value); - } - pipeline.sync(); - } finally { - lock.unlock(); - } - } else { - jedis.rpush(key, values); - } - return null; - } - }.getResult(); - } - - /** - * 同{@link #batchListPushTail(String, String[], boolean)},不同的是利用redis的事务特性来实现 - * - * @param key key - * @param values value的数组 - * @return null - */ - public Object updateListInTransaction(final String key, final List values) { - return new Executor(shardedJedisPool) { - - @Override - Object execute() { - Transaction transaction = jedis.getShard(key).multi(); - transaction.del(key); - for (String value : values) { - transaction.rpush(key, value); - } - transaction.exec(); - return null; - } - }.getResult(); - } - - /** - * 在key对应list的尾部部添加字符串元素,如果key存在,什么也不做 - * - * @param key key - * @param values value的数组 - * @return 执行insertListIfNotExists后,表的长度 - */ - public Long insertListIfNotExists(final String key, final String[] values) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - RedisLock lock = new RedisLock(key, shardedJedisPool); - lock.lock(); - try { - if (!jedis.exists(key)) { - return jedis.rpush(key, values); - } - } finally { - lock.unlock(); - } - return 0L; - } - }.getResult(); - } - - /** - * 返回list所有元素,下标从0开始,负值表示从后面计算,-1表示倒数第一个元素,key不存在返回空列表 - * - * @param key key - * @return list所有元素 - */ - public List listGetAll(final String key) { - return new Executor>(shardedJedisPool) { - - @Override - List execute() { - return jedis.lrange(key, 0, -1); - } - }.getResult(); - } - - /** - * 返回指定区间内的元素,下标从0开始,负值表示从后面计算,-1表示倒数第一个元素,key不存在返回空列表 - * - * @param key key - * @param beginIndex 下标开始索引(包含) - * @param endIndex 下标结束索引(不包含) - * @return 指定区间内的元素 - */ - public List listRange(final String key, final long beginIndex, final long endIndex) { - return new Executor>(shardedJedisPool) { - - @Override - List execute() { - return jedis.lrange(key, beginIndex, endIndex - 1); - } - }.getResult(); - } - - /** - * 一次获得多个链表的数据 - * - * @param keys key的数组 - * @return 执行结果 - */ - public Map> batchGetAllList(final List keys) { - return new Executor>>(shardedJedisPool) { - - @Override - Map> execute() { - ShardedJedisPipeline pipeline = jedis.pipelined(); - Map> result = new HashMap>(); - List>> responses = new ArrayList>>(keys.size()); - for (String key : keys) { - responses.add(pipeline.lrange(key, 0, -1)); - } - pipeline.sync(); - for (int i = 0; i < keys.size(); ++i) { - result.put(keys.get(i), responses.get(i).get()); - } - return result; - } - }.getResult(); - } - - /* ======================================Pub/Sub====================================== */ - - /** - * 将信息 message 发送到指定的频道 channel。 时间复杂度:O(N+M),其中 N 是频道 channel 的订阅者数量,而 M 则是使用模式订阅(subscribed patterns)的客户端的数量。 - * - * @param channel 频道 - * @param message 信息 - * @return 接收到信息 message 的订阅者数量。 - */ - public Long publish(final String channel, final String message) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - Jedis _jedis = jedis.getShard(channel); - return _jedis.publish(channel, message); - } - - }.getResult(); - } - - /** - * 订阅给定的一个频道的信息。 - * - * @param jedisPubSub 监听器 - * @param channel 频道 - */ - public void subscribe(final JedisPubSub jedisPubSub, final String channel) { - new Executor(shardedJedisPool) { - - @Override - Object execute() { - Jedis _jedis = jedis.getShard(channel); - // 注意subscribe是一个阻塞操作,因为当前线程要轮询Redis的响应然后调用subscribe - _jedis.subscribe(jedisPubSub, channel); - return null; - } - }.getResult(); - } - - /** - * 取消订阅 - * - * @param jedisPubSub 监听器 - */ - public void unSubscribe(final JedisPubSub jedisPubSub) { - jedisPubSub.unsubscribe(); - } - - /* ======================================Sorted set================================= */ - - /** - * sadd添加一个元素 - * - * @param key - * @param members - * @return - */ - public Long sadd(final String key, final String... members) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.sadd(key, members); - } - }.getResult(); - } - - public Long sadd(final String key, final byte[]... members) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.sadd(key.getBytes(), members); - } - }.getResult(); - } - - /** - * 获取key的集合 - * - * @param key - * @return - */ - public Set smembers(final String key) { - return new Executor>(shardedJedisPool) { - - @Override - Set execute() { - return jedis.smembers(key); - } - }.getResult(); - } - - /** - * 移除set元素 - * - * @param key - * @param members - * @return - */ - public Long srem(final String key, final String... members) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.srem(key, members); - } - }.getResult(); - } - - /** - * 统计key的value重复合集(共同关注) - * - * @param keys - * @return - */ - public Set sinter(final String... keys) { - return new Executor>(shardedJedisPool) { - - @Override - Set execute() { - Jedis _jedis = jedis.getShard(keys[0]); - return _jedis.sinter(keys); - } - }.getResult(); - } - - /** - * 并集 - * - * @param keys - * @return - */ - public Set sunion(final String... keys) { - return new Executor>(shardedJedisPool) { - - @Override - Set execute() { - Jedis _jedis = jedis.getShard(keys[0]); - return _jedis.sunion(keys); - } - }.getResult(); - } - - /** - * 差集 - * - * @param keys - * @return - */ - public Set sdiff(final String... keys) { - return new Executor>(shardedJedisPool) { - - @Override - Set execute() { - Jedis _jedis = jedis.getShard(keys[0]); - return _jedis.sdiff(keys); - } - }.getResult(); - } - - /** - * 判断元素是否存在 - * - * @param key - * @param member - * @return - */ - public Boolean sismember(final String key, final String member) { - return new Executor(shardedJedisPool) { - - @Override - Boolean execute() { - return jedis.sismember(key, member); - } - }.getResult(); - } - - /** - * 统计列表集合 - * - * @param key - * @return - */ - public Long scard(final String key) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.scard(key); - } - }.getResult(); - } - - /** - * 将一个 member 元素及其 score 值加入到有序集 key 当中。 - * - * @param key key - * @param score score 值可以是整数值或双精度浮点数。 - * @param member 有序集的成员 - * @return 被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。 - */ - public Long addWithSortedSet(final String key, final double score, final String member) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.zadd(key, score, member); - } - }.getResult(); - } - - /** - * 将多个 member 元素及其 score 值加入到有序集 key 当中。 - * - * @param key key - * @param scoreMembers score、member的pair - * @return 被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。 - */ - public Long addWithSortedSet(final String key, final Map scoreMembers) { - return new Executor(shardedJedisPool) { - - @Override - Long execute() { - return jedis.zadd(key, scoreMembers); - } - }.getResult(); - } - - /** - * 返回有序集 key 中,指定区间内的成员。 按照从小到大排序 - * - * @param key - * @param start - * @param end - * @return - */ - public Set rangeSortSet(final String key, final int start, final int end) { - return new Executor>(shardedJedisPool) { - - @Override - Set execute() { - return jedis.zrange(key, start, end); - } - }.getResult(); - } - - /** - * 返回有序集 key 中,指定区间内的成员。 按照从大到小排序 - * @param key - * @param start - * @param end - * @return - */ - public Set revrangeSortSet(final String key, final int start, final int end) { - return new Executor>(shardedJedisPool) { - - @Override - Set execute() { - return jedis.zrevrange(key, start, end); - } - }.getResult(); - } - - /** - * 返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。 有序集成员按 score 值递减(从大到小)的次序排列。 - * - * @param key key - * @param max score最大值 - * @param min score最小值 - * @return 指定区间内,带有 score 值(可选)的有序集成员的列表 - */ - public Set revrangeByScoreWithSortedSet(final String key, final double max, final double min) { - return new Executor>(shardedJedisPool) { - - @Override - Set execute() { - return jedis.zrevrangeByScore(key, max, min); - } - }.getResult(); - } - - /* ======================================Other====================================== */ - - /** - * 构造Pair键值对 - * - * @param key key - * @param value value - * @return 键值对 - */ - public Pair makePair(K key, V value) { - return new Pair(key, value); - } - - /** - * 键值对 - * - * @version V1.0 - * @author fengjc - * @param key - * @param value - */ - public class Pair { - - private K key; - - private V value; - - public Pair(K key, V value) { - this.key = key; - this.value = value; - } - - public K getKey() { - return key; - } - - public void setKey(K key) { - this.key = key; - } - - public V getValue() { - return value; - } - - public void setValue(V value) { - this.value = value; - } - } - - public T hgetObj(final String key, final String field) { - return new Executor(shardedJedisPool) { - - @SuppressWarnings("unchecked") - @Override - T execute() { - Object result = null; - - byte[] retVal = jedis.hget(SafeEncoder.encode(key), SafeEncoder.encode(field)); - if (null != retVal) { - try { - result = SerializeKit.unserialize(retVal); - } catch (Exception e) { - result = SafeEncoder.encode(retVal); - } - } - return (T) result; - } - }.getResult(); - } - -} diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisLock.java b/blade-redis/src/main/java/blade/plugin/redis/RedisLock.java deleted file mode 100644 index 7abe9b188..000000000 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisLock.java +++ /dev/null @@ -1,120 +0,0 @@ -package blade.plugin.redis; - -import java.util.Random; - -import redis.clients.jedis.ShardedJedis; -import redis.clients.jedis.ShardedJedisPool; - -/** - * redis lock - * - * @author biezhi - * @since 1.0 - */ -public class RedisLock { - - /** 加锁标志 */ - public static final String LOCKED = "TRUE"; - - /** 毫秒与毫微秒的换算单位 1毫秒 = 1000000毫微秒 */ - public static final long MILLI_NANO_CONVERSION = 1000 * 1000L; - - /** 默认超时时间(毫秒) */ - public static final long DEFAULT_TIME_OUT = 1000; - - public static final Random RANDOM = new Random(); - - /** 锁的超时时间(秒),过期删除 */ - public static final int EXPIRE = 3 * 60; - - private ShardedJedisPool shardedJedisPool; - - private ShardedJedis jedis; - - private String key; - - // 锁状态标志 - private boolean locked = false; - - /** - * This creates a RedisLock - */ - public RedisLock(String key, ShardedJedisPool shardedJedisPool) { - this.key = key + "_lock"; - this.shardedJedisPool = shardedJedisPool; - this.jedis = this.shardedJedisPool.getResource(); - } - - /** - * 加锁 应该以: lock(); try { doSomething(); } finally { unlock(); } 的方式调用 - * @param timeout 超时时间 - * @return 成功或失败标志 - */ - public boolean lock(long timeout) { - long nano = System.nanoTime(); - timeout *= MILLI_NANO_CONVERSION; - try { - while ((System.nanoTime() - nano) < timeout) { - if (this.jedis.setnx(this.key, LOCKED) == 1) { - this.jedis.expire(this.key, EXPIRE); - this.locked = true; - return this.locked; - } - // 短暂休眠,避免出现活锁 - Thread.sleep(3, RANDOM.nextInt(500)); - } - } catch (Exception e) { - throw new RuntimeException("Locking error", e); - } - return false; - } - - /** - * 加锁 应该以: lock(); try { doSomething(); } finally { unlock(); } 的方式调用 - * - * @param timeout 超时时间 - * @param expire 锁的超时时间(秒),过期删除 - * @return 成功或失败标志 - */ - public boolean lock(long timeout, int expire) { - long nano = System.nanoTime(); - timeout *= MILLI_NANO_CONVERSION; - try { - while ((System.nanoTime() - nano) < timeout) { - if (this.jedis.setnx(this.key, LOCKED) == 1) { - this.jedis.expire(this.key, expire); - this.locked = true; - return this.locked; - } - // 短暂休眠,避免出现活锁 - Thread.sleep(3, RANDOM.nextInt(500)); - } - } catch (Exception e) { - throw new RuntimeException("Locking error", e); - } - return false; - } - - /** - * 加锁 应该以: lock(); try { doSomething(); } finally { unlock(); } 的方式调用 - * - * @return 成功或失败标志 - */ - public boolean lock() { - return lock(DEFAULT_TIME_OUT); - } - - /** - * 解锁 无论是否加锁成功,都需要调用unlock 应该以: lock(); try { doSomething(); } finally { unlock(); } 的方式调用 - */ - public void unlock() { - try { - if (this.locked) { - this.jedis.del(this.key); - } - } finally { - this.shardedJedisPool.close(); -// this.shardedJedisPool.returnResourceObject(this.jedis); - } - } -} diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java b/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java deleted file mode 100644 index 7bc4dd852..000000000 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisPlugin.java +++ /dev/null @@ -1,84 +0,0 @@ -package blade.plugin.redis; - -import java.util.ArrayList; -import java.util.List; - -import com.blade.plugin.Plugin; - -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; -import redis.clients.jedis.JedisShardInfo; - -/** - * redis插件 - * - * @author biezhi - * @since 1.0 - */ -public enum RedisPlugin implements Plugin { - - INSTANCE; - - private final Logger LOGGER = LoggerFactory.getLogger(RedisPlugin.class); - - private RedisPlugin() { - redisPoolConfig = new RedisPoolConfig(); - shards = new ArrayList(); - } - - public static RedisPlugin me(){ - return INSTANCE; - } - - /** - * redis连接池配置 - */ - private RedisPoolConfig redisPoolConfig; - - /** - * 所有redis实例,多台redis主机时可以做集群 - */ - private List shards; - - public RedisPoolConfig redisPoolConfig() { - return redisPoolConfig; - } - - public RedisPlugin host(String host, int port) { - shards.add(new JedisShardInfo(host, port)); - return this; - } - - public RedisPlugin host(String host, int port, String auth) { - JedisShardInfo jedisShardInfo = new JedisShardInfo(host, port); - jedisShardInfo.setPassword(auth); - shards.add(jedisShardInfo); - return this; - } - - public RedisPlugin host(JedisShardInfo jedisShardInfo) { - shards.add(jedisShardInfo); - return this; - } - - public RedisPlugin host(String host) { - shards.add(new JedisShardInfo(host)); - return this; - } - - public List shards() { - return this.shards; - } - - @Override - public void run() { - RedisExecutor.init(); - LOGGER.info("redis plugin config success!"); - } - - @Override - public void destroy() { - shards.clear(); - } - -} diff --git a/blade-redis/src/main/java/blade/plugin/redis/RedisPoolConfig.java b/blade-redis/src/main/java/blade/plugin/redis/RedisPoolConfig.java deleted file mode 100644 index 94ca8beea..000000000 --- a/blade-redis/src/main/java/blade/plugin/redis/RedisPoolConfig.java +++ /dev/null @@ -1,21 +0,0 @@ -package blade.plugin.redis; - -import org.apache.commons.pool2.impl.GenericObjectPoolConfig; - -public class RedisPoolConfig extends GenericObjectPoolConfig { - - public RedisPoolConfig() { - // defaults to make your life with connection pool easier :) - - setMinEvictableIdleTimeMillis(60000); - setTimeBetweenEvictionRunsMillis(60000); - setNumTestsPerEvictionRun(-1); - setTestOnBorrow(true); - setTestOnReturn(true); - setTestWhileIdle(true); - setMaxWaitMillis(3000); - setMaxTotal(10); - setMaxIdle(5); - } - -} diff --git a/pom.xml b/pom.xml index 41e997b1c..dd2800d28 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,7 @@ blade-kit blade-core - blade-cache - blade-redis blade-startup - blade-oauth2 - blade-patchca @@ -55,6 +51,7 @@ org.slf4j slf4j-api ${slf4j-api.version} + provided From 9d9fb806e0cb0a16410932e54c02447991ebe841 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 18 Feb 2016 17:08:04 +0800 Subject: [PATCH 428/545] update readme --- README.md | 29 +++++++++++------------------ README_CN.md | 31 ++++++++++++------------------- 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 7f9f35d60..dd4aa8c2f 100644 --- a/README.md +++ b/README.md @@ -161,32 +161,25 @@ public static void main(String[] args) { ## DSL DB Operation ```java +// query +List posts = + AR.find("where title like ? order by id desc limit ?,?", title, page, count).list(Post.class); + // save -public boolean save(Integer cid, Integer tid, Integer fuid, Integer tuid) { - return model.insert().param("cid", cid) - .param("tid", tid) - .param("fuid", fuid) - .param("tuid", tuid) - .param("addtime", new Date()) - .param("ntype", 0).executeAndCommit() > 0; -} +String insertSql = "insert into t_post (title, content, view_count, create_time) values (?,?,?,?)"; +AR.update(insertSql, title, content, 0, new Date()).commit(); -// signin -public User signin(String username, String password) { - String pwd = EncrypKit.md5(username + password); - return model.select().eq("username", username) - .eq("password", pwd).fetchOne(); -} +// update +AR.update("update t_post set title = ? and content = ? where id = ?",title, content, id).commit(); -// search count -public Long getUserCount(String email){ - return model.count().eq("email", email).fetchCount(); -} +// delete +AR.update("delete from t_post where id = ?",id).commit() ``` You may refer to these examples for additional guidance: + [Hello Blade](https://github.com/blade-samples/hello) ++ [Blog Example](https://github.com/blade-samples/blog) + [API Doc](http://bladejava.com/apidocs) + [User Guide](http://bladejava.com/docs) + [Version Changes](LAST_VERSION.md) diff --git a/README_CN.md b/README_CN.md index a194ae9e8..678a9b059 100644 --- a/README_CN.md +++ b/README_CN.md @@ -160,32 +160,25 @@ public static void main(String[] args) { ## DSL数据库操作 ```java -// 保存操作 -public boolean save(Integer cid, Integer tid, Integer fuid, Integer tuid) { - return model.insert().param("cid", cid) - .param("tid", tid) - .param("fuid", fuid) - .param("tuid", tuid) - .param("addtime", new Date()) - .param("ntype", 0).executeAndCommit() > 0; -} +// query +List posts = + AR.find("where title like ? order by id desc limit ?,?", title, page, count).list(Post.class); -// 登录操作 -public User signin(String username, String password) { - String pwd = EncrypKit.md5(username + password); - return model.select().eq("username", username) - .eq("password", pwd).fetchOne(); -} +// save +String insertSql = "insert into t_post (title, content, view_count, create_time) values (?,?,?,?)"; +AR.update(insertSql, title, content, 0, new Date()).commit(); -// 查询条数 -public Long getUserCount(String email){ - return model.count().eq("email", email).fetchCount(); -} +// update +AR.update("update t_post set title = ? and content = ? where id = ?",title, content, id).commit(); + +// delete +AR.update("delete from t_post where id = ?",id).commit() ``` OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: + [hello工程](https://github.com/blade-samples/hello) ++ [博客例子](https://github.com/blade-samples/blog) + [API文档](http://bladejava.com/apidocs) + [使用指南](http://bladejava.com/docs) + [相关案例](https://github.com/blade-samples) From ab175763795fe364c94a8f84a6ca043b6d690866 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 24 Feb 2016 15:20:04 +0800 Subject: [PATCH 429/545] add blade.basepackage config --- blade-core/src/main/java/com/blade/loader/Configurator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/blade-core/src/main/java/com/blade/loader/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java index 07c23b460..318011aeb 100644 --- a/blade-core/src/main/java/com/blade/loader/Configurator.java +++ b/blade-core/src/main/java/com/blade/loader/Configurator.java @@ -38,6 +38,7 @@ public static void init(BladeConfig bladeConfig, Config config) { String httpEncoding = config.getString("blade.http.encoding"); String httpFilters = config.getString("blade.http.filters"); + String basePackage = config.getString("blade.basepackage"); if(null != dev){ bladeConfig.setDev(dev); @@ -58,6 +59,10 @@ public static void init(BladeConfig bladeConfig, Config config) { if(StringKit.isNotBlank(httpFilters)){ bladeConfig.setStaticFolders(httpFilters.split(",")); } + + if(StringKit.isNotBlank(basePackage)){ + bladeConfig.setBasePackage(basePackage); + } } } \ No newline at end of file From 546acf76176f54eb28b10d2644c2f4bf3991efa7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 24 Feb 2016 15:51:11 +0800 Subject: [PATCH 430/545] fix ioc not store the interceptor --- .../com/blade/interceptor/Interceptor.java | 21 +++++++++++++++++++ .../java/com/blade/route/RouteBuilder.java | 21 +++++++------------ .../blade/view/handle/RouteViewHandler.java | 15 ++++++++++++- .../java/com/blade/web/DispatcherHandler.java | 7 ++++--- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/blade-core/src/main/java/com/blade/interceptor/Interceptor.java b/blade-core/src/main/java/com/blade/interceptor/Interceptor.java index 08f48b2ff..67a7be4fd 100644 --- a/blade-core/src/main/java/com/blade/interceptor/Interceptor.java +++ b/blade-core/src/main/java/com/blade/interceptor/Interceptor.java @@ -1,8 +1,29 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.interceptor; import com.blade.web.http.Request; import com.blade.web.http.Response; +/** + * Interceptor, In the routing block before and after the execution. + * + * @author biezhi + * @since 1.0 + */ public interface Interceptor { boolean before(Request request, Response response); diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index 2f908297f..6d6ce3d4d 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -21,7 +21,6 @@ import com.blade.Blade; import com.blade.interceptor.Interceptor; import com.blade.interceptor.annotation.Intercept; -import com.blade.ioc.Ioc; import com.blade.route.annotation.Path; import com.blade.route.annotation.Route; import com.blade.web.http.HttpMethod; @@ -46,19 +45,16 @@ public class RouteBuilder { */ private ClassReader classReader; - /** - * IOC container, storage route to IOC - */ - private Ioc ioc; + private Routers routers; - private Blade blade; + private String[] routePackages; - private Routers routers; + private String interceptorPackage; public RouteBuilder(Blade blade) { - this.blade = blade; this.routers = blade.routers(); - this.ioc = blade.ioc(); + this.routePackages = blade.routePackages(); + this.interceptorPackage = blade.interceptorPackage(); this.classReader = new ClassPathClassReader(); } @@ -68,13 +64,11 @@ public RouteBuilder(Blade blade) { public void building() { // Route - String[] routePackages = blade.routePackages(); if(null != routePackages && routePackages.length > 0){ this.buildRoute(routePackages); } // Inteceptor - String interceptorPackage = blade.interceptorPackage(); if(StringKit.isNotBlank(interceptorPackage)){ this.buildInterceptor(interceptorPackage); } @@ -103,8 +97,7 @@ private void buildInterceptor(String... interceptorPackages){ // Scan all Interceptor classes = classReader.getClass(packageName, Interceptor.class, recursive); -// classes = classReader.getClassByAnnotation(packageName, Intercept.class, recursive); - + if(null != classes && classes.size() > 0){ for(Class interceptorClazz : classes){ parseInterceptor(interceptorClazz); @@ -155,7 +148,7 @@ private void parseInterceptor(final Class interceptor){ return; } - ioc.addBean(interceptor); +// ioc.addBean(interceptor); Intercept intercept = interceptor.getAnnotation(Intercept.class); String partten = "/.*"; diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 3672a5e7b..871b6ec34 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -2,6 +2,7 @@ import java.lang.reflect.Method; +import com.blade.ioc.Ioc; import com.blade.route.Route; import com.blade.view.template.ModelAndView; import com.blade.web.DispatchKit; @@ -14,7 +15,13 @@ import blade.kit.reflect.ReflectKit; public class RouteViewHandler { - + + private Ioc ioc; + + public RouteViewHandler(Ioc ioc) { + this.ioc = ioc; + } + /** * Parameters in the method * @@ -82,6 +89,12 @@ public boolean intercept(Request request, Response response, Route route){ Method actionMethod = route.getAction(); Object target = route.getTarget(); + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + // execute int len = actionMethod.getParameterTypes().length; actionMethod.setAccessible(true); diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java index ae7f3b1e4..5134889e6 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -70,7 +70,7 @@ public DispatcherHandler(ServletContext servletContext, Routers routers) { this.ioc = blade.ioc(); this.routeMatcher = new RouteMatcher(routers); this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); - this.routeViewHandler = new RouteViewHandler(); + this.routeViewHandler = new RouteViewHandler(this.ioc); } public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ @@ -108,11 +108,12 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo // If find it if (route != null) { request.setRoute(route); - boolean result = false; + // before inteceptor List befores = routeMatcher.getBefore(uri); - result = invokeInterceptor(request, response, befores); + boolean result = invokeInterceptor(request, response, befores); if(result){ + // execute this.routeHandle(request, response, route); if(!request.isAbort()){ From d70beb52d7644e1d79813d0a2e474aa3fcfd7691 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 24 Feb 2016 18:45:16 +0800 Subject: [PATCH 431/545] add service annotation --- .../src/main/java/com/blade/ioc/Ioc.java | 3 ++ .../main/java/com/blade/ioc/SampleIoc.java | 17 ++++++++- .../com/blade/ioc/annotation/Component.java | 1 - .../com/blade/ioc/annotation/Service.java | 36 +++++++++++++++++++ .../blade/ioc/loader/IocAnnotationLoader.java | 4 +-- .../java/com/blade/web/DispatcherServlet.java | 4 +-- 6 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/ioc/annotation/Service.java diff --git a/blade-core/src/main/java/com/blade/ioc/Ioc.java b/blade-core/src/main/java/com/blade/ioc/Ioc.java index 358a47f34..dc028eea5 100644 --- a/blade-core/src/main/java/com/blade/ioc/Ioc.java +++ b/blade-core/src/main/java/com/blade/ioc/Ioc.java @@ -36,6 +36,8 @@ public interface Ioc { void addBean(String name, Object bean); + void setBean(Class type, Object proxyBean); + Object getBean(String name); T getBean(Class type); @@ -45,4 +47,5 @@ public interface Ioc { Set getBeanNames(); void clearAll(); + } diff --git a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java index fa7848670..91ccdddb9 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SampleIoc.java @@ -81,7 +81,22 @@ public void addBean(String name, Object bean) { } } } - + + /** + * Update BeanDefine + */ + public void setBean(Class type, Object proxyBean) { + Assert.notNull(proxyBean); + + BeanDefine beanDefine = pool.get(type.getName()); + if(beanDefine != null){ + beanDefine.setBean(proxyBean); + } else { + beanDefine = new BeanDefine(proxyBean, type); + } + pool.put(type.getName(), beanDefine); + } + /** * Add user-defined objects */ diff --git a/blade-core/src/main/java/com/blade/ioc/annotation/Component.java b/blade-core/src/main/java/com/blade/ioc/annotation/Component.java index 3118c2e48..5c0e50fbf 100644 --- a/blade-core/src/main/java/com/blade/ioc/annotation/Component.java +++ b/blade-core/src/main/java/com/blade/ioc/annotation/Component.java @@ -33,5 +33,4 @@ String value() default ""; - boolean singleton() default true; } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/annotation/Service.java b/blade-core/src/main/java/com/blade/ioc/annotation/Service.java new file mode 100644 index 000000000..9a69d551d --- /dev/null +++ b/blade-core/src/main/java/com/blade/ioc/annotation/Service.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Bean annotations can be injected + * + * @author biezhi + * @since 1.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Service{ + + String value() default ""; + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java index 30a9ec184..be98ca2eb 100644 --- a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java @@ -52,14 +52,14 @@ private Collection> finder(List packageNames, List> classes) { this.classes = classes; } - + @Override public void load(SampleIoc ioc) { for (Class cls : classes) { Component anno = cls.getAnnotation(Component.class); if (anno != null) { String name = anno.value().equals("") ? cls.getName() : anno.value(); - ioc.addBean(name, cls, anno.singleton()); + ioc.addBean(name, cls, true); } } // free diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 31c41aa03..82cdd9b18 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -111,10 +111,10 @@ public void init(Blade blade) { iocApplication.init(); + blade.init(); + this.bootstrap.contextInitialized(blade); - blade.init(); - dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); new BladeBanner().print(); From 93fae47dae6ee1af0c25ff05a337b048f1af8aa9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 25 Feb 2016 15:16:12 +0800 Subject: [PATCH 432/545] fix contextpath not is "/" --- .../blade/web/http/wrapper/ServletRequest.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index b3e73bc1c..b03970ace 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -125,14 +125,17 @@ public void initPathParams(String routePath) { List variables = getPathParam(routePath); String regexPath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); - - Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(uri()); - matcher.matches(); - // start index at 1 as group(0) always stands for the entire expression - for (int i=1; i <= variables.size(); i++) { - String value = matcher.group(i); - pathParams.put(variables.get(i-1), value); + String uri = Path.getRelativePath(uri(), contextPath()); + + Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(uri); + + if(matcher.matches()){ + // start index at 1 as group(0) always stands for the entire expression + for (int i=1, len = variables.size(); i <= len; i++) { + String value = matcher.group(i); + pathParams.put(variables.get(i-1), value); + } } } From ccacac5a341673966146548bdd5dd86ff5c9d255 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 25 Feb 2016 17:14:49 +0800 Subject: [PATCH 433/545] fix logger arg is null and upgrade blade to 1.6.0-beta1 --- LAST_VERSION.md | 4 +- blade-core/pom.xml | 9 ++++- blade-core/src/main/java/com/blade/Const.java | 2 +- blade-kit/pom.xml | 2 +- .../java/blade/kit/logging/SimpleLogger.java | 15 ++++--- .../java/blade/kit/reflect/ReflectKit.java | 40 +++++++++++++++++++ pom.xml | 2 +- 7 files changed, 62 insertions(+), 12 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 6fbfb6452..52b253e8b 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -24,7 +24,7 @@     com.bladejava     blade-kit -    1.2.9-alpha +    1.2.9-beta ``` @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.6.0-alpha +    1.6.0-beta1 ``` diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 884d894f9..9703e4907 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -25,14 +25,21 @@ com.bladejava blade-kit - 1.2.9-alpha + 1.2.9-beta + javax.servlet javax.servlet-api 3.1.0 provided + org.eclipse.jetty jetty-server diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 2c60a9183..dd6504da7 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * Current version */ - String BLADE_VERSION = "1.6.0-alpha"; + String BLADE_VERSION = "1.6.0-beta1"; /** * Server 500 error HTML diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index 41e6a0a15..f6d0d13d0 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - 1.2.9-alpha + 1.2.9-beta blade-kit https://github.com/biezhi/blade/tree/master/blade-kit diff --git a/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java b/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java index 5a217252f..d746c9119 100644 --- a/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java +++ b/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java @@ -212,12 +212,15 @@ protected String format(String message, Object... args) { String msg = String.format(message, args); if(msg.indexOf("{}") != -1){ for(Object arg : args){ - String arg_str = arg.toString(); - if(arg_str.indexOf("\\") != -1){ - arg_str = arg_str.replaceAll("\\\\","/"); - } - if(arg_str.indexOf("$") != -1){ - arg_str = arg_str.replaceAll("\\$","_"); + String arg_str = ""; + if(null != arg){ + arg_str = arg.toString(); + if(arg_str.indexOf("\\") != -1){ + arg_str = arg_str.replaceAll("\\\\","/"); + } + if(arg_str.indexOf("$") != -1){ + arg_str = arg_str.replaceAll("\\$","_"); + } } msg = msg.replaceFirst("\\{\\}", arg_str); } diff --git a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java index c636094fc..0edc5c9b7 100644 --- a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java @@ -73,6 +73,46 @@ public static Object newInstance(Class clazz) throws InstantiationException, return clazz.newInstance(); } + /** + * 根据类名获取Class对象 + * + * @param className 类名称 + * @return 返回Class对象 + */ + public static Class newClass(String className){ + try { + return Class.forName(className); + } catch (ClassNotFoundException e) { + } + return null; + } + + /** + * 获取包是否存在 + * + * @param packageName 包名称 + * @return 返回包是否存在 + */ + public static boolean isPackage(String packageName){ + if(StringKit.isNotBlank(packageName)){ + Package temp = Package.getPackage(packageName); + return null != temp; + } + return false; + } + + public static boolean isClass(String className){ + if(StringKit.isNotBlank(className)){ + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException e) { + } + } + return false; + } + + /** * 创建一个实例对象 * @param clazz class对象 diff --git a/pom.xml b/pom.xml index dd2800d28..d158229e3 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.6.0-alpha + 1.6.0-beta1 4.12 1.7.16 From e60c1fefd6b9ab6662a14763f589786180c2c855 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 25 Feb 2016 17:24:11 +0800 Subject: [PATCH 434/545] update readme and log --- README.md | 4 ++-- README_CN.md | 4 ++-- UPDATE_LOG.md | 12 ++++++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index dd4aa8c2f..78781067d 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.0-alpha + 1.6.0-beta1 com.bladejava @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.0-alpha' +compile 'com.bladejava:blade-core:1.6.0-beta1' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/README_CN.md b/README_CN.md index 678a9b059..9499da9ba 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,7 +38,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.6.0-alpha + 1.6.0-beta1 com.bladejava @@ -50,7 +50,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 或者 `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.0-alpha' +compile 'com.bladejava:blade-core:1.6.0-beta1' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 9e01d9eff..6e266399c 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,5 +1,17 @@ # Blade 更新日志 +### v1.6.0 + 1. 更简化的配置(提供默认配置) + 2. 支持非web应用开发 + 3. 优化代码 + 4. 重构数据库操作 + 5. 内置数据库连接池 + 6. 更灵活的路由操作 + 7. 重新修订官网文档 + 8. 暂时去除servlet3x异步 + 9. 去除多余繁杂的配置,追求精简实用 + 10. 提供易扩展的IOC,路由接口 + ### v1.5.1 1. 修复webRoot是null 2. 修复模板引擎路径错误 From abcbf3f3f3584354ca015c9fa7f2ef69649b5754 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 26 Feb 2016 17:54:56 +0800 Subject: [PATCH 435/545] fix log print error --- .../java/blade/kit/logging/SimpleLogger.java | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java b/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java index d746c9119..33fe2c878 100644 --- a/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java +++ b/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java @@ -207,25 +207,15 @@ protected String format(String message, Object... args) { return null; } if (args == null || args.length == 0){ + if(message.indexOf("{}") != -1){ + message = message.replaceAll("\\{\\}", ""); + } return message.toString(); } else { - String msg = String.format(message, args); - if(msg.indexOf("{}") != -1){ - for(Object arg : args){ - String arg_str = ""; - if(null != arg){ - arg_str = arg.toString(); - if(arg_str.indexOf("\\") != -1){ - arg_str = arg_str.replaceAll("\\\\","/"); - } - if(arg_str.indexOf("$") != -1){ - arg_str = arg_str.replaceAll("\\$","_"); - } - } - msg = msg.replaceFirst("\\{\\}", arg_str); - } + if(message.indexOf("{}") != -1){ + message = message.replaceAll("\\{\\}", "%s"); } - return msg; + return String.format(message.toString(), args); } } From 5a75a02d53ef720c4fc31907e95228d19bf05042 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 29 Feb 2016 11:02:37 +0800 Subject: [PATCH 436/545] update routepackage method name to addRoutePackage --- blade-core/src/main/java/com/blade/Blade.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 0e45af1ab..244f9e1a8 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -180,7 +180,18 @@ public Blade setAppConf(String confName){ * @param packages route package path, is your package name * @return return blade */ - public Blade routes(String...packages){ + public Blade addRoutePackage(String packageName){ + return this.addRoutePackages(packageName); + } + + /** + * Setting route package,e.g:com.baldejava.route + * Can be introduced into multiple packages, all of which are in the package. + * + * @param packages route package path, is your package name + * @return return blade + */ + public Blade addRoutePackages(String...packages){ Assert.notNull(packages); bladeConfig.addRoutePackages(packages); return this; From 7cc8ff98e6441877fdbfa22f001fd015a568bbc8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 29 Feb 2016 11:03:03 +0800 Subject: [PATCH 437/545] add set ServletContext method --- .../src/main/java/com/blade/context/BladeWebContext.java | 6 ++++++ .../src/main/java/com/blade/web/DispatcherServlet.java | 3 +++ 2 files changed, 9 insertions(+) diff --git a/blade-core/src/main/java/com/blade/context/BladeWebContext.java b/blade-core/src/main/java/com/blade/context/BladeWebContext.java index b3900e7ac..7d3247622 100644 --- a/blade-core/src/main/java/com/blade/context/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/context/BladeWebContext.java @@ -55,6 +55,12 @@ public static BladeWebContext me(){ return ctx.get(); } + public static void setContext(ServletContext context) { + BladeWebContext bladeWebContext = new BladeWebContext(); + bladeWebContext.context = context; + ctx.set(bladeWebContext); + } + public static void setContext(ServletContext context, Request request, Response response) { BladeWebContext bladeWebContext = new BladeWebContext(); bladeWebContext.context = context; diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 82cdd9b18..53a339c26 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -26,6 +26,7 @@ import com.blade.Blade; import com.blade.Bootstrap; +import com.blade.context.BladeWebContext; import com.blade.ioc.IocApplication; import com.blade.route.RouteBuilder; @@ -80,6 +81,8 @@ public void init(ServletConfig config) throws ServletException { blade.webRoot(DispatchKit.getWebroot(servletContext).getPath()); + BladeWebContext.setContext(servletContext); + LOGGER.info("blade.webroot = {}", blade.webRoot()); blade.config().init(); From 90bcb6033fb03733cb6944d7e142f014dbd40e16 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 29 Feb 2016 11:03:41 +0800 Subject: [PATCH 438/545] fix controller recursive bug. --- .../java/com/blade/route/RouteBuilder.java | 28 ++++--------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index 6d6ce3d4d..f025435a4 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -27,6 +27,7 @@ import com.blade.web.http.Request; import com.blade.web.http.Response; +import blade.kit.CollectionKit; import blade.kit.StringKit; import blade.kit.reflect.ReflectKit; import blade.kit.resource.ClassPathClassReader; @@ -88,17 +89,9 @@ private void buildInterceptor(String... interceptorPackages){ // Traversal Interceptor for(String packageName : interceptorPackages){ - boolean recursive = false; - - if (packageName.endsWith(".*")) { - packageName = packageName.substring(0, packageName.length() - 2); - recursive = true; - } - // Scan all Interceptor - classes = classReader.getClass(packageName, Interceptor.class, recursive); - - if(null != classes && classes.size() > 0){ + classes = classReader.getClass(packageName, Interceptor.class, false); + if(CollectionKit.isNotEmpty(classes)){ for(Class interceptorClazz : classes){ parseInterceptor(interceptorClazz); } @@ -115,18 +108,9 @@ private void buildRoute(String... routePackages){ Set> classes = null; // Traverse route for(String packageName : routePackages){ - - boolean recursive = false; - - if (packageName.endsWith(".*")) { - packageName = packageName.substring(0, packageName.length() - 2); - recursive = true; - } - - // Scan all Controoler - classes = classReader.getClassByAnnotation(packageName, Path.class, recursive); - - if(null != classes && classes.size() > 0){ + // Scan all Controoler + classes = classReader.getClassByAnnotation(packageName, Path.class, true); + if(CollectionKit.isNotEmpty(classes)){ for(Class pathClazz : classes){ parseRouter(pathClazz); } From cd656f2abe8661491c438bb42b94ea960e25a26a Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 29 Feb 2016 11:59:42 +0800 Subject: [PATCH 439/545] fix basepackage not add route and interceptor --- blade-core/src/main/java/com/blade/loader/Configurator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/blade-core/src/main/java/com/blade/loader/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java index 318011aeb..96cbf3168 100644 --- a/blade-core/src/main/java/com/blade/loader/Configurator.java +++ b/blade-core/src/main/java/com/blade/loader/Configurator.java @@ -62,6 +62,9 @@ public static void init(BladeConfig bladeConfig, Config config) { if(StringKit.isNotBlank(basePackage)){ bladeConfig.setBasePackage(basePackage); + bladeConfig.addIocPackages(basePackage + ".service.*"); + bladeConfig.addRoutePackages(basePackage + ".controller"); + bladeConfig.setInterceptorPackage(basePackage + ".interceptor"); } } From ca090d813e3a7f65627c8c280578339342f53907 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 29 Feb 2016 17:20:02 +0800 Subject: [PATCH 440/545] update blade-core to 1.6.0M1 --- LAST_VERSION.md | 6 +++--- README.md | 4 ++-- README_CN.md | 4 ++-- blade-core/src/main/java/com/blade/Blade.java | 5 +++++ blade-core/src/main/java/com/blade/Const.java | 2 +- pom.xml | 2 +- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 52b253e8b..adc3e46e3 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.6.0-beta1 +    1.6.0M1 ``` @@ -42,7 +42,7 @@     com.bladejava     blade-jdbc -    0.0.1 +    0.0.2 ``` @@ -78,7 +78,7 @@     com.bladejava     blade-patchca -    1.0.1 +    1.0.2 ``` diff --git a/README.md b/README.md index 78781067d..a6280fde0 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.0-beta1 + 1.6.0M1 com.bladejava @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.0-beta1' +compile 'com.bladejava:blade-core:1.6.0M1' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/README_CN.md b/README_CN.md index 9499da9ba..131d550e9 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,7 +38,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.6.0-beta1 + 1.6.0M1 com.bladejava @@ -50,7 +50,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 或者 `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.0-beta1' +compile 'com.bladejava:blade-core:1.6.0M1' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 244f9e1a8..00ba15006 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -197,6 +197,11 @@ public Blade addRoutePackages(String...packages){ return this; } + /** + * + * @param basePackage + * @return + */ public Blade basePackage(String basePackage){ Assert.notBlank(basePackage); bladeConfig.setBasePackage(basePackage); diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index dd6504da7..cd0a8969c 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * Current version */ - String BLADE_VERSION = "1.6.0-beta1"; + String BLADE_VERSION = "1.6.0M1"; /** * Server 500 error HTML diff --git a/pom.xml b/pom.xml index d158229e3..fccb9e0f5 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.6.0-beta1 + 1.6.0-beta2 4.12 1.7.16 From 5413263604c4d7678a909ffb16c589204c5e99ab Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 1 Mar 2016 15:14:24 +0800 Subject: [PATCH 441/545] update ioc implement class name --- blade-core/src/main/java/com/blade/Blade.java | 4 ++-- .../java/com/blade/ioc/{SampleIoc.java => SimpleIoc.java} | 2 +- .../main/java/com/blade/ioc/loader/IocAnnotationLoader.java | 4 ++-- blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java | 4 ++-- blade-core/src/test/java/com/blade/ioc/test/IocTest.java | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) rename blade-core/src/main/java/com/blade/ioc/{SampleIoc.java => SimpleIoc.java} (95%) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 00ba15006..174ea4dce 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -22,7 +22,7 @@ import java.util.Set; import com.blade.ioc.Ioc; -import com.blade.ioc.SampleIoc; +import com.blade.ioc.SimpleIoc; import com.blade.loader.BladeConfig; import com.blade.loader.Configurator; import com.blade.plugin.Plugin; @@ -98,7 +98,7 @@ public class Blade { private Blade() { this.bladeConfig = new BladeConfig(); - this.ioc = new SampleIoc(); + this.ioc = new SimpleIoc(); this.routers = new Routers(); this.templateEngine = new JspEngine(); this.plugins = new HashSet>(); diff --git a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java similarity index 95% rename from blade-core/src/main/java/com/blade/ioc/SampleIoc.java rename to blade-core/src/main/java/com/blade/ioc/SimpleIoc.java index 91ccdddb9..65b37c336 100644 --- a/blade-core/src/main/java/com/blade/ioc/SampleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java @@ -34,7 +34,7 @@ * @author biezhi * @since 1.0 */ -public class SampleIoc implements Ioc { +public class SimpleIoc implements Ioc { private static final Logger LOGGER = LoggerFactory.getLogger(Ioc.class); diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java index be98ca2eb..abd140aad 100644 --- a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java @@ -21,7 +21,7 @@ import java.util.Collection; import java.util.List; -import com.blade.ioc.SampleIoc; +import com.blade.ioc.SimpleIoc; import com.blade.ioc.annotation.Component; import blade.kit.resource.ClassPathClassReader; @@ -54,7 +54,7 @@ public IocAnnotationLoader(Collection> classes) { } @Override - public void load(SampleIoc ioc) { + public void load(SimpleIoc ioc) { for (Class cls : classes) { Component anno = cls.getAnnotation(Component.class); if (anno != null) { diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java index b5f8747c2..f07aefbce 100644 --- a/blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java @@ -15,10 +15,10 @@ */ package com.blade.ioc.loader; -import com.blade.ioc.SampleIoc; +import com.blade.ioc.SimpleIoc; public interface IocLoader { - void load(SampleIoc ioc); + void load(SimpleIoc ioc); } \ No newline at end of file diff --git a/blade-core/src/test/java/com/blade/ioc/test/IocTest.java b/blade-core/src/test/java/com/blade/ioc/test/IocTest.java index dbb1111fe..f908ad89f 100644 --- a/blade-core/src/test/java/com/blade/ioc/test/IocTest.java +++ b/blade-core/src/test/java/com/blade/ioc/test/IocTest.java @@ -6,7 +6,7 @@ import org.junit.Test; import com.blade.ioc.Ioc; -import com.blade.ioc.SampleIoc; +import com.blade.ioc.SimpleIoc; import com.blade.ioc.loader.IocAnnotationLoader; import com.blade.ioc.service.test.UserService; import com.blade.ioc.service.test.UserServiceImpl; @@ -17,7 +17,7 @@ public class IocTest { @Before public void before(){ - ioc = new SampleIoc(); + ioc = new SimpleIoc(); } @Test From 310fa07160081cebd9c58a34c89fbe09401e19c3 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 5 Mar 2016 17:56:02 +0800 Subject: [PATCH 442/545] add PathVariable and RequestParam. --- .../src/main/java/com/blade/route/C.java | 2 +- .../java/com/blade/route/RouteBuilder.java | 2 - .../main/java/com/blade/route/Routers.java | 15 --- .../blade/route/annotation/PathVariable.java | 16 +++ .../blade/route/annotation/RequestParam.java | 20 +++ .../view/{template => }/ModelAndView.java | 2 +- .../main/java/com/blade/view/ModelMap.java | 30 +++++ .../blade/view/handle/RouteViewHandler.java | 126 ++++++++++++++---- .../com/blade/view/template/JspEngine.java | 1 + .../blade/view/template/TemplateEngine.java | 2 + .../java/com/blade/web/DispatcherHandler.java | 2 +- .../java/com/blade/web/http/Response.java | 2 +- .../web/http/wrapper/ServletResponse.java | 2 +- 13 files changed, 177 insertions(+), 45 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/route/annotation/PathVariable.java create mode 100644 blade-core/src/main/java/com/blade/route/annotation/RequestParam.java rename blade-core/src/main/java/com/blade/view/{template => }/ModelAndView.java (98%) create mode 100644 blade-core/src/main/java/com/blade/view/ModelMap.java diff --git a/blade-core/src/main/java/com/blade/route/C.java b/blade-core/src/main/java/com/blade/route/C.java index 4166f4ce9..e540a3767 100644 --- a/blade-core/src/main/java/com/blade/route/C.java +++ b/blade-core/src/main/java/com/blade/route/C.java @@ -2,7 +2,7 @@ import java.util.Map; -import com.blade.view.template.ModelAndView; +import com.blade.view.ModelAndView; public class C { diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index f025435a4..c92d8addf 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -165,8 +165,6 @@ private void parseRouter(final Class router){ return; } -// ioc.addBean(router); - final String nameSpace = router.getAnnotation(Path.class).value(); final String suffix = router.getAnnotation(Path.class).suffix(); diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 6143d29c9..9c30e8a38 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -132,21 +132,6 @@ public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) { } } - public void route(String path, Object target, String methodName) { - try { - Assert.notNull(path, "Route path not is null!"); - Assert.notNull(target, "Target Controller not is null!"); - Assert.notNull(methodName, "Method name not is null"); - - Method method = target.getClass().getMethod(methodName, Request.class, Response.class); - addRoute(HttpMethod.ALL, path, target, target.getClass(), method); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - } - public void route(String path, Class clazz, String methodName) { Assert.notNull(path, "Route path not is null!"); diff --git a/blade-core/src/main/java/com/blade/route/annotation/PathVariable.java b/blade-core/src/main/java/com/blade/route/annotation/PathVariable.java new file mode 100644 index 000000000..f9915b5a8 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/annotation/PathVariable.java @@ -0,0 +1,16 @@ +package com.blade.route.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface PathVariable { + + String value() default ""; + +} diff --git a/blade-core/src/main/java/com/blade/route/annotation/RequestParam.java b/blade-core/src/main/java/com/blade/route/annotation/RequestParam.java new file mode 100644 index 000000000..1707790c9 --- /dev/null +++ b/blade-core/src/main/java/com/blade/route/annotation/RequestParam.java @@ -0,0 +1,20 @@ +package com.blade.route.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RequestParam { + + String value() default ""; + + boolean required() default true; + + String defaultValue() default ""; + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/view/template/ModelAndView.java b/blade-core/src/main/java/com/blade/view/ModelAndView.java similarity index 98% rename from blade-core/src/main/java/com/blade/view/template/ModelAndView.java rename to blade-core/src/main/java/com/blade/view/ModelAndView.java index 77ad65924..a3985bbc6 100644 --- a/blade-core/src/main/java/com/blade/view/template/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/view/ModelAndView.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view.template; +package com.blade.view; import java.util.Map; diff --git a/blade-core/src/main/java/com/blade/view/ModelMap.java b/blade-core/src/main/java/com/blade/view/ModelMap.java new file mode 100644 index 000000000..4b631e2f0 --- /dev/null +++ b/blade-core/src/main/java/com/blade/view/ModelMap.java @@ -0,0 +1,30 @@ +package com.blade.view; + +import com.blade.web.http.Request; +import blade.kit.Assert; + +public class ModelMap { + + private Request request; + + public ModelMap(Request request) { + this.request = request; + } + + public void addAttribute(String name, Object value) { + Assert.notNull(name, "Model attribute name must not be null"); + request.attribute(name, value); + } + + public void attribute(String name, Object value) { + addAttribute(name, value); + } + + public void attr(String name, Object value) { + addAttribute(name, value); + } + + public void put(String name, Object value) { + addAttribute(name, value); + } +} diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 871b6ec34..68c22bd52 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -1,17 +1,23 @@ package com.blade.view.handle; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + import com.blade.ioc.Ioc; import com.blade.route.Route; -import com.blade.view.template.ModelAndView; +import com.blade.route.annotation.PathVariable; +import com.blade.route.annotation.RequestParam; +import com.blade.view.ModelAndView; +import com.blade.view.ModelMap; import com.blade.web.DispatchKit; import com.blade.web.http.Request; import com.blade.web.http.Response; +import com.blade.web.http.wrapper.Session; -import blade.kit.json.JSONHelper; -import blade.kit.json.JSONValue; -import blade.kit.reflect.ConvertKit; import blade.kit.reflect.ReflectKit; public class RouteViewHandler { @@ -22,26 +28,107 @@ public RouteViewHandler(Ioc ioc) { this.ioc = ioc; } + private Object getPathParam(Class parameterType, String val, Request request){ + Object result = null; + if(parameterType.equals(String.class)){ + result = request.param(val); + } else if(parameterType.equals(Integer.class) || parameterType.equals(int.class)){ + result = request.paramAsInt(val); + } else if(parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)){ + result = request.paramAsBool(val); + } else if(parameterType.equals(Long.class) || parameterType.equals(long.class)){ + result = request.paramAsLong(val); + } + return result; + } + + private Object getRequestParam(Class parameterType, String val, String defaultValue, Request request){ + Object result = null; + if(parameterType.equals(String.class)){ + String value = request.query(val); + if(null == value){ + result = defaultValue; + } else { + result = value; + } + } else if(parameterType.equals(Integer.class) || parameterType.equals(int.class)){ + Integer value = request.queryAsInt(val); + if(null == value){ + result = Integer.valueOf(defaultValue); + } else { + result = value; + } + } else if(parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)){ + Boolean value = request.queryAsBool(val); + if(null == value){ + result = Boolean.valueOf(defaultValue); + } else { + result = value; + } + } else if(parameterType.equals(Long.class) || parameterType.equals(long.class)){ + Long value = request.queryAsLong(val); + if(null == value){ + result = Long.valueOf(defaultValue); + } else { + result = value; + } + } + return result; + } + /** * Parameters in the method * * @param request Request object for injection to the method parameter list * @param response Response object for injection to the method parameter list - * @param params Params parameter list + * @param actionMethod Execute method * @return Return the generated array of parameters */ - public Object[] getArgs(Request request, Response response, Class[] params){ - - int len = params.length; + public Object[] getArgs(Request request, Response response, Method actionMethod){ + Annotation[][] parameterAnnotations = actionMethod.getParameterAnnotations(); + Class[] parameterTypes = actionMethod.getParameterTypes(); + int len = parameterTypes.length; Object[] args = new Object[len]; + actionMethod.setAccessible(true); - for(int i=0; i paramTypeClazz = params[i]; - if(paramTypeClazz.getName().equals(Request.class.getName())){ - args[i] = request; + int i = 0; + if(parameterAnnotations.length > 0){ + for (Annotation[] annotations : parameterAnnotations) { + Class parameterType = parameterTypes[i]; + for (Annotation annotation : annotations) { + Class anType = annotation.annotationType(); + if(anType.equals(PathVariable.class)){ + PathVariable pathVariable = (PathVariable) annotation; + String val = pathVariable.value(); + Object value = getPathParam(parameterType, val, request); + args[i] = value; + } else if(anType.equals(RequestParam.class)) { + RequestParam requestParam = (RequestParam) annotation; + String val = requestParam.value(); + Object value = getRequestParam(parameterType, val, requestParam.defaultValue(), request); + args[i] = value; + } + } + i++; } - if(paramTypeClazz.getName().equals(Response.class.getName())){ + } + + for(i=0; i paramTypeClazz = parameterTypes[i]; + if(paramTypeClazz.equals(Request.class)){ + args[i] = request; + } else if(paramTypeClazz.equals(Response.class)){ args[i] = response; + } else if(paramTypeClazz.equals(Session.class)){ + args[i] = request.session(); + } else if(paramTypeClazz.equals(ModelMap.class)){ + args[i] = new ModelMap(request); + } else if(paramTypeClazz.equals(HttpServletRequest.class)){ + args[i] = request.raw(); + } else if(paramTypeClazz.equals(HttpServletResponse.class)){ + args[i] = response.raw(); + } else if(paramTypeClazz.equals(HttpSession.class)){ + args[i] = request.raw().getSession(); } } return args; @@ -53,11 +140,10 @@ public void handle(Request request, Response response, Route route){ // execute int len = actionMethod.getParameterTypes().length; - actionMethod.setAccessible(true); try { Object returnParam = null; if(len > 0){ - Object[] args = getArgs(request, response, actionMethod.getParameterTypes()); + Object[] args = getArgs(request, response, actionMethod); returnParam = ReflectKit.invokeMehod(target, actionMethod, args); } else { returnParam = ReflectKit.invokeMehod(target, actionMethod); @@ -66,16 +152,10 @@ public void handle(Request request, Response response, Route route){ if(null != returnParam){ Class returnType = returnParam.getClass(); if(returnType == String.class){ - response.text(returnParam.toString()); + response.render( returnParam.toString() ); } else if(returnType == ModelAndView.class){ ModelAndView modelAndView = (ModelAndView) returnParam; response.render( modelAndView ); - } else if(ConvertKit.isBasicType(returnType)){ - response.text(returnParam.toString()); - } else { - JSONValue jsonValue = JSONHelper.objectAsJsonValue(returnParam); - String json = jsonValue.toString(); - response.json(json); } } } catch (Exception e) { @@ -101,7 +181,7 @@ public boolean intercept(Request request, Response response, Route route){ try { Object returnParam = null; if(len > 0){ - Object[] args = getArgs(request, response, actionMethod.getParameterTypes()); + Object[] args = getArgs(request, response, actionMethod); returnParam = ReflectKit.invokeMehod(target, actionMethod, args); } else { returnParam = ReflectKit.invokeMehod(target, actionMethod); diff --git a/blade-core/src/main/java/com/blade/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/view/template/JspEngine.java index 34e2d2c67..609d6ab9e 100644 --- a/blade-core/src/main/java/com/blade/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/JspEngine.java @@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletResponse; import com.blade.context.BladeWebContext; +import com.blade.view.ModelAndView; import blade.kit.logging.Logger; import blade.kit.logging.LoggerFactory; diff --git a/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java b/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java index 38ac929b6..465fd438e 100644 --- a/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java @@ -17,6 +17,8 @@ import java.io.Writer; +import com.blade.view.ModelAndView; + /** * TemplateEngine Interface, For view layer to display data * diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java index 5134889e6..c3d674f97 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -29,8 +29,8 @@ import com.blade.route.RouteHandler; import com.blade.route.RouteMatcher; import com.blade.route.Routers; +import com.blade.view.ModelAndView; import com.blade.view.handle.RouteViewHandler; -import com.blade.view.template.ModelAndView; import com.blade.web.http.HttpStatus; import com.blade.web.http.Path; import com.blade.web.http.Request; diff --git a/blade-core/src/main/java/com/blade/web/http/Response.java b/blade-core/src/main/java/com/blade/web/http/Response.java index 9445ee868..738187b71 100644 --- a/blade-core/src/main/java/com/blade/web/http/Response.java +++ b/blade-core/src/main/java/com/blade/web/http/Response.java @@ -21,7 +21,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; -import com.blade.view.template.ModelAndView; +import com.blade.view.ModelAndView; /** * HTTP Response diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index 6ee07fb5c..0f6dc5409 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletResponse; import com.blade.context.BladeWebContext; -import com.blade.view.template.ModelAndView; +import com.blade.view.ModelAndView; import com.blade.view.template.TemplateEngine; import com.blade.web.http.HttpStatus; import com.blade.web.http.Path; From f36ea4443e202967ff9cee7bedde14aa55110be7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 5 Mar 2016 18:06:20 +0800 Subject: [PATCH 443/545] add fileItem Param --- .../main/java/com/blade/view/handle/RouteViewHandler.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 68c22bd52..3711e3649 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -17,6 +17,7 @@ import com.blade.web.http.Request; import com.blade.web.http.Response; import com.blade.web.http.wrapper.Session; +import com.blade.web.multipart.FileItem; import blade.kit.reflect.ReflectKit; @@ -129,6 +130,11 @@ public Object[] getArgs(Request request, Response response, Method actionMethod) args[i] = response.raw(); } else if(paramTypeClazz.equals(HttpSession.class)){ args[i] = request.raw().getSession(); + } else if(paramTypeClazz.equals(FileItem.class)){ + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + args[i] = fileItems[0]; + } } } return args; From 7164cd761a30f8fa2768b19b8cf47df93478daf7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 9 Mar 2016 14:30:13 +0800 Subject: [PATCH 444/545] update blade-core version to 1.6.0M2 --- LAST_VERSION.md | 2 +- README.md | 4 ++-- README_CN.md | 4 ++-- blade-core/src/main/java/com/blade/Const.java | 2 +- pom.xml | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index adc3e46e3..345dd14d3 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.6.0M1 +    1.6.0M2 ``` diff --git a/README.md b/README.md index a6280fde0..1447916c2 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.0M1 + 1.6.0M2 com.bladejava @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.0M1' +compile 'com.bladejava:blade-core:1.6.0M2' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/README_CN.md b/README_CN.md index 131d550e9..83fa7f3fa 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,7 +38,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.6.0M1 + 1.6.0M2 com.bladejava @@ -50,7 +50,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 或者 `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.0M1' +compile 'com.bladejava:blade-core:1.6.0M2' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index cd0a8969c..80baf60e9 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * Current version */ - String BLADE_VERSION = "1.6.0M1"; + String BLADE_VERSION = "1.6.0M2"; /** * Server 500 error HTML diff --git a/pom.xml b/pom.xml index fccb9e0f5..23622e884 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.6.0-beta2 + 1.6.0M2 4.12 1.7.16 From 7e45149cada1ea2ea3e022fd9b092ca5376a4e19 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Mar 2016 11:04:14 +0800 Subject: [PATCH 445/545] fix blade config load is null and ioc injection error. --- blade-core/src/main/java/com/blade/Const.java | 2 +- .../src/main/java/com/blade/ioc/IocApplication.java | 13 +++++++++---- .../main/java/com/blade/loader/Configurator.java | 8 ++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 80baf60e9..748a6e6c8 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -26,7 +26,7 @@ public interface Const { /** * Current version */ - String BLADE_VERSION = "1.6.0M2"; + String BLADE_VERSION = "1.6.0"; /** * Server 500 error HTML diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index e827d9559..01c7b51c8 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -15,6 +15,7 @@ */ package com.blade.ioc; +import java.lang.reflect.Modifier; import java.util.Collection; import java.util.List; import java.util.Map; @@ -23,6 +24,7 @@ import com.blade.Blade; import com.blade.Bootstrap; import com.blade.ioc.annotation.Component; +import com.blade.ioc.annotation.Service; import com.blade.plugin.Plugin; import com.blade.route.Route; import com.blade.route.RouteHandler; @@ -149,10 +151,13 @@ private void registerBean(String packageName) { // Scan package all class Set> classes = classReader.getClass(packageName, recursive); for (Class clazz : classes) { - Component component = clazz.getAnnotation(Component.class); - if(null != component){ - // Register classes - ioc.addBean(clazz); + if(!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())){ + Component component = clazz.getAnnotation(Component.class); + Service service = clazz.getAnnotation(Service.class); + if(null != component || null != service){ + // Register classes + ioc.addBean(clazz); + } } } } diff --git a/blade-core/src/main/java/com/blade/loader/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java index 96cbf3168..031952d6d 100644 --- a/blade-core/src/main/java/com/blade/loader/Configurator.java +++ b/blade-core/src/main/java/com/blade/loader/Configurator.java @@ -15,7 +15,10 @@ */ package com.blade.loader; +import java.util.Map; + import blade.kit.Assert; +import blade.kit.CollectionKit; import blade.kit.StringKit; import blade.kit.config.Config; @@ -66,6 +69,11 @@ public static void init(BladeConfig bladeConfig, Config config) { bladeConfig.addRoutePackages(basePackage + ".controller"); bladeConfig.setInterceptorPackage(basePackage + ".interceptor"); } + + Map configMap = config.getConfigMap(); + if(CollectionKit.isNotEmpty(configMap)){ + bladeConfig.setConfigMap(configMap); + } } } \ No newline at end of file From 2e1701901a0ef24e6a038b8c2997c2e5a2bf8867 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 11 Mar 2016 11:04:31 +0800 Subject: [PATCH 446/545] upgrade blade-core to 1.6.0 release. --- LAST_VERSION.md | 2 +- README.md | 4 ++-- README_CN.md | 4 ++-- pom.xml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 345dd14d3..a8c7a5753 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.6.0M2 +    1.6.0 ``` diff --git a/README.md b/README.md index 1447916c2..944a5a64b 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.0M2 + 1.6.0 com.bladejava @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.0M2' +compile 'com.bladejava:blade-core:1.6.0' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/README_CN.md b/README_CN.md index 83fa7f3fa..f1130fe78 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,7 +38,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.6.0M2 + 1.6.0 com.bladejava @@ -50,7 +50,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 或者 `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.0M2' +compile 'com.bladejava:blade-core:1.6.0' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/pom.xml b/pom.xml index 23622e884..5dd2ea9c3 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.6.0M2 + 1.6.0 4.12 1.7.16 From 7ea44873e195e9a9387bee9f180bba648d9362ed Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Mar 2016 10:10:20 +0800 Subject: [PATCH 447/545] remove mail kit --- blade-kit/pom.xml | 8 +- .../src/main/java/blade/kit/DateKit.java | 37 +- .../src/main/java/blade/kit/MailKit.java | 354 ------------------ .../src/main/java/blade/kit/StringKit.java | 127 +++++++ .../main/java/blade/kit/mail/EmailHandle.java | 287 -------------- .../java/blade/kit/mail/MailTemplate.java | 155 -------- .../java/blade/kit/mail/package-info.java | 4 - .../src/test/java/com/blade/kit/MailTest.java | 36 -- 8 files changed, 159 insertions(+), 849 deletions(-) delete mode 100644 blade-kit/src/main/java/blade/kit/MailKit.java delete mode 100644 blade-kit/src/main/java/blade/kit/mail/EmailHandle.java delete mode 100644 blade-kit/src/main/java/blade/kit/mail/MailTemplate.java delete mode 100644 blade-kit/src/main/java/blade/kit/mail/package-info.java delete mode 100644 blade-kit/src/test/java/com/blade/kit/MailTest.java diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index f6d0d13d0..f32cc097b 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -11,7 +11,7 @@ blade-kit jar - 1.2.9-beta + 1.2.9 blade-kit https://github.com/biezhi/blade/tree/master/blade-kit @@ -35,12 +35,6 @@ 1.2.17 provided - - javax.mail - mail - 1.5.0-b01 - provided - dom4j dom4j diff --git a/blade-kit/src/main/java/blade/kit/DateKit.java b/blade-kit/src/main/java/blade/kit/DateKit.java index 75374b39f..a5c0556cc 100644 --- a/blade-kit/src/main/java/blade/kit/DateKit.java +++ b/blade-kit/src/main/java/blade/kit/DateKit.java @@ -630,6 +630,10 @@ public static Date getDateByUnixTime(int unixTime) { return new Date(unixTime * 1000L); } + public static long getUnixTimeLong() { + return getUnixTimeByDate(new Date()); + } + public static int getCurrentUnixTime() { return getUnixTimeByDate(new Date()); } @@ -644,12 +648,9 @@ public static int getCurrentUnixTime() { public static int getUnixTimeByDate(Date date) { return (int) (date.getTime() / 1000); } - - public static void main(String[] args) { - Date date1 = dateFormat("1981-01-01 00:00:00"); - Date date2 = dateFormat("1900-12-31 00:00:00"); - System.out.println(birthdayFormat(date1)); - System.out.println(birthdayFormat(date2)); + + public static long getUnixTimeLong(Date date) { + return (date.getTime() / 1000); } public static Date getNextDay(Date date) { @@ -830,4 +831,28 @@ public static Date convertToDate(String input) { return date; } + public static Long getTodayTime() { + Calendar today = Calendar.getInstance(); + today.set(Calendar.HOUR_OF_DAY, 0); + today.set(Calendar.MINUTE, 0); + today.set(Calendar.SECOND, 0); + return Long.valueOf(String.valueOf(today.getTimeInMillis()).substring(0, 10)); + } + + public static Long getYesterdayTime() { + Calendar today = Calendar.getInstance(); + today.set(Calendar.HOUR_OF_DAY, -24); + today.set(Calendar.MINUTE, 0); + today.set(Calendar.SECOND, 0); + return Long.valueOf(String.valueOf(today.getTimeInMillis()).substring(0, 10)); + } + + public static Long getTomorrowTime() { + Calendar tomorrow = Calendar.getInstance(); + tomorrow.set(Calendar.HOUR_OF_DAY, 24); + tomorrow.set(Calendar.MINUTE, 0); + tomorrow.set(Calendar.SECOND, 0); + return Long.valueOf(String.valueOf(tomorrow.getTimeInMillis()).substring(0, 10)); + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/MailKit.java b/blade-kit/src/main/java/blade/kit/MailKit.java deleted file mode 100644 index 937f0f93c..000000000 --- a/blade-kit/src/main/java/blade/kit/MailKit.java +++ /dev/null @@ -1,354 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import blade.kit.mail.EmailHandle; -import blade.kit.mail.MailTemplate; - -/** - * 邮件发送类 - * - * @author biezhi - * @since 1.0 - */ -public class MailKit { - -// private static final Logger LOGGER = Logger.getLogger(MailKit.class); - - /**常见的邮件发送协议地址**/ - public static final String SMTP_QQ = "smtp.qq.com"; - public static final String SMTP_163 = "smtp.163.com"; - public static final String SMTP_126 = "smtp.126.com"; - public static final String SMTP_SINA = "smtp.sina.com"; - public static final String SMTP_GMAIL = "smtp.gmail.com"; - - private static String CFG_SMTP = SMTP_QQ; - private static String SEND_USER = ""; - private static String SEND_PASSWORD = ""; - - /** - * 配置邮件协议和账户 - * @param smtp smtp协议 - * @param user 发送人邮件 - * @param password 发送人密码 - */ - public static void config(String smtp, String user, String password){ - if(StringKit.isNotBlank(smtp)){ - CFG_SMTP = smtp; - } - if(StringKit.isNotBlank(user)){ - SEND_USER = user; - } - if(StringKit.isNotBlank(password)){ - SEND_PASSWORD = password; - } - } - - /** - * 根据模板发送 - * @param mailTemplate - * @param subject - * @return - */ - public static boolean send(MailTemplate mailTemplate, String subject){ - if(null != mailTemplate && StringKit.isNotBlank(subject)){ - return sendProcess(CFG_SMTP, SEND_USER, SEND_PASSWORD, - mailTemplate.getToMail(), mailTemplate.getCcMail(), - subject, mailTemplate.toString(), mailTemplate.getFileList()); - } - return false; - } - - /** - * 发送邮件 - * @param toMail 收件人地址 - * @param subject 发送主题 - * @param content 发送内容 - * @throws Exception - * @return 成功返回true,失败返回false - */ - public static boolean send(String toMail, String subject, String content){ - return sendProcess(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, null, subject, content, null); - } - - - /** - * 发送邮件并发送附件 - * @param toMail 收件人地址 - * @param subject 发送主题 - * @param content 发送内容 - * @param files 附件列表 - * @throws Exception - * @return 成功返回true,失败返回false - */ - public static boolean send(String toMail, String subject, String content, String ...files){ - return sendProcess(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, null, subject, content, Arrays.asList(files)); - } - - /** - * 发送邮件并发送附件 - * @param toMail 收件人地址 - * @param subject 发送主题 - * @param content 发送内容 - * @param files 附件列表 - * @throws Exception - * @return 成功返回true,失败返回false - */ - public static boolean send(String toMail, String subject, String content, List files){ - return sendProcess(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, null, subject, content, files); - } - - /** - * 发送并抄送 - * @param toMail 收件人地址 - * @param ccMail 抄送地址 - * @param subject 发送主题 - * @param content 发送内容 - * @return 成功返回true,失败返回false - */ - public static boolean sendAndCc(String toMail, String ccMail, String subject, String content){ - return sendProcess(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, ccMail, subject, content, null); - } - - /** - * 发送邮件并抄送,带附件 - * @param toMail - * @param ccMail - * @param subject - * @param content - * @param files - * @return - */ - public static boolean sendAndCc(String toMail, String ccMail, String subject, String content, String ...files){ - return sendProcess(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, ccMail, subject, content, Arrays.asList(files)); - } - - /** - * 发送邮件并抄送,带附件 - * @param toMail - * @param ccMail - * @param subject - * @param content - * @param files - * @return - */ - public static boolean sendAndCc(String toMail, String ccMail, String subject, String content, List files){ - return sendProcess(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, ccMail, subject, content, files); - } - - /** - * 发送邮件 - * @param smtp 邮件协议 - * @param fromAddress 发送人地址 - * @param fromPass 发送人密码 - * @param toAddress 收件人地址 - * @param ccAdress 抄送人地址 - * @param subject 发送主题 - * @param content 发送内容 - * @throws Exception - */ - public static boolean sendProcess(String smtp,String fromAddress,String fromPass,String toMailList, - String ccAdress,String subject, String content,List fileList){ - try{ - EmailHandle emailHandle = new EmailHandle(smtp); - emailHandle.setFrom(fromAddress); - emailHandle.setNeedAuth(true); - emailHandle.setSubject(subject); - emailHandle.setBody(content); - emailHandle.setToList(toMailList); - - /**添加抄送**/ - if(StringKit.isNotEmpty(ccAdress)){ - emailHandle.setCopyToList(ccAdress); - } - - emailHandle.setFrom(fromAddress); - emailHandle.setNamePass(fromAddress, fromPass); - - if(null != fileList && fileList.size() > 0){ - /** 附件文件路径 **/ - for(String file : fileList){ - emailHandle.addFileAffix(file); - } - } - return emailHandle.sendEmail(); - }catch(Exception e){ - e.printStackTrace(); - } - return false; - } - - - - /*********************************************异步发送:S*******************************************/ - - /** - * 根据模板发送 - * @param mailTemplate - * @param subject - * @return - */ - public static void asynSend(MailTemplate mailTemplate, String subject){ - if(null != mailTemplate && StringKit.isNotBlank(subject)){ - asynSend(CFG_SMTP, SEND_USER, SEND_PASSWORD, mailTemplate.getToMail(), mailTemplate.getCcMail(), - subject, mailTemplate.toString(), mailTemplate.getFileList()); - } - } - - /** - * 异步发送邮件 - * @param toMail - * @param subject - * @param content - * @return - */ - public static void asynSend(final String toMail, final String subject, final String content){ - asynSend(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, null, subject, content, null); - } - - /** - * 异步发送并抄送 - * @param toMail - * @param ccMail - * @param subject - * @param content - */ - public static void asynSendAndCc(final String toMail, final String ccMail, final String subject, final String content){ - asynSend(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, ccMail, subject, content, null); - } - - /** - * 异步发送邮件并发送附件 - * @param toMail - * @param subject - * @param content - * @return - */ - public static void asynSend(final String toMail, final String subject, final String content, final String ...files){ - asynSend(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, null, subject, content, Arrays.asList(files)); - } - - /** - * 异步发送邮件并发送附件 - * @param toMail - * @param subject - * @param content - * @return - */ - public static void asynSend(final String toMail, final String subject, final String content, final List files){ - asynSend(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, null, subject, content, files); - } - - - /** - * 异步发送邮件并抄送,带附件 - * @param toMail - * @param ccMail - * @param subject - * @param content - * @param files - * @return - */ - public static void asynSendAndCc(final String toMail, final String ccMail, final String subject, final String content, final String ...files){ - asynSend(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, ccMail, subject, content, Arrays.asList(files)); - } - - /** - * 异步发送邮件并抄送,带附件 - * @param toMail - * @param ccMail - * @param subject - * @param content - * @param files - * @return - */ - public static void asynSendAndCc(final String toMail, final String ccMail, final String subject, final String content, final List files){ - asynSend(CFG_SMTP, SEND_USER, SEND_PASSWORD, toMail, ccMail, subject, content, files); - } - - /** - * 发送邮件 - * @param smtp 邮件协议 - * @param fromAddress 发送人地址 - * @param fromPass 发送人密码 - * @param toAddress 收件人地址 - * @param ccAdress 抄送人地址 - * @param subject 发送主题 - * @param content 发送内容 - * @throws Exception - */ - public static boolean asynSend(final String smtp,final String fromAddress,final String fromPass,final String toAddress, - final String ccAdress,final String subject, final String content,final List fileList){ - Boolean flag = Boolean.FALSE; - FutureTask futureTask = null; - ExecutorService excutorService = Executors.newCachedThreadPool(); - // 执行任务 - futureTask = new FutureTask(new Callable() { - @Override - public Boolean call() throws Exception { - EmailHandle emailHandle = new EmailHandle(smtp); - emailHandle.setFrom(fromAddress); - emailHandle.setNeedAuth(true); - emailHandle.setSubject(subject); - emailHandle.setBody(content); - emailHandle.setToList(toAddress); - /**添加抄送**/ - if(StringKit.isNotEmpty(ccAdress)){ - emailHandle.setCopyToList(ccAdress); - } - emailHandle.setFrom(fromAddress); - emailHandle.setNamePass(fromAddress, fromPass); - if(null != fileList && fileList.size() > 0){ - /** 附件文件路径 **/ - for(String file : fileList){ - emailHandle.addFileAffix(file); - } - } - return emailHandle.sendEmail(); - } - }); - excutorService.submit(futureTask); - - try { - // 任务没超时说明发送成功 - flag = futureTask.get(5L, TimeUnit.SECONDS); - } catch (InterruptedException e) { - futureTask.cancel(true); - e.printStackTrace(); - } catch (ExecutionException e) { - futureTask.cancel(true); - e.printStackTrace(); - } catch (TimeoutException e) { - futureTask.cancel(true); - e.printStackTrace(); - } finally { - excutorService.shutdown(); - } - return flag; - } - /*********************************************异步发送:E*******************************************/ - -} diff --git a/blade-kit/src/main/java/blade/kit/StringKit.java b/blade-kit/src/main/java/blade/kit/StringKit.java index 12629c2d9..c66b93ea8 100644 --- a/blade-kit/src/main/java/blade/kit/StringKit.java +++ b/blade-kit/src/main/java/blade/kit/StringKit.java @@ -20,6 +20,7 @@ import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; @@ -2560,6 +2561,132 @@ public static String[] split(String str, String separatorChars, int max) { return list.toArray(new String[list.size()]); } + /** + * Convenience method to return a String array as a CSV String. + * E.g. useful for {@code toString()} implementations. + * @param arr the array to display + * @return the delimited String + */ + public static String arrayToCommaDelimitedString(Object[] arr) { + return arrayToDelimitedString(arr, ","); + } + + /** + * Convenience method to return a String array as a delimited (e.g. CSV) + * String. E.g. useful for {@code toString()} implementations. + * @param arr the array to display + * @param delim the delimiter to use (probably a ",") + * @return the delimited String + */ + public static String arrayToDelimitedString(Object[] arr, String delim) { + if (arr == null || arr.length == 0) { + return ""; + } + + if (arr.length == 1) { + return nullSafeToString(arr[0]); + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < arr.length; i++) { + if (i > 0) { + sb.append(delim); + } + sb.append(arr[i]); + } + return sb.toString(); + } + + /** + * Determine if the given objects are equal, returning {@code true} + * if both are {@code null} or {@code false} if only one is + * {@code null}. + *

Compares arrays with {@code Arrays.equals}, performing an equality + * check based on the array elements rather than the array reference. + * @param o1 first Object to compare + * @param o2 second Object to compare + * @return whether the given objects are equal + * @see java.util.Arrays#equals + */ + public static boolean nullSafeEquals(Object o1, Object o2) { + if (o1 == o2) { + return true; + } + if (o1 == null || o2 == null) { + return false; + } + if (o1.equals(o2)) { + return true; + } + if (o1.getClass().isArray() && o2.getClass().isArray()) { + if (o1 instanceof Object[] && o2 instanceof Object[]) { + return Arrays.equals((Object[]) o1, (Object[]) o2); + } + if (o1 instanceof boolean[] && o2 instanceof boolean[]) { + return Arrays.equals((boolean[]) o1, (boolean[]) o2); + } + if (o1 instanceof byte[] && o2 instanceof byte[]) { + return Arrays.equals((byte[]) o1, (byte[]) o2); + } + if (o1 instanceof char[] && o2 instanceof char[]) { + return Arrays.equals((char[]) o1, (char[]) o2); + } + if (o1 instanceof double[] && o2 instanceof double[]) { + return Arrays.equals((double[]) o1, (double[]) o2); + } + if (o1 instanceof float[] && o2 instanceof float[]) { + return Arrays.equals((float[]) o1, (float[]) o2); + } + if (o1 instanceof int[] && o2 instanceof int[]) { + return Arrays.equals((int[]) o1, (int[]) o2); + } + if (o1 instanceof long[] && o2 instanceof long[]) { + return Arrays.equals((long[]) o1, (long[]) o2); + } + if (o1 instanceof short[] && o2 instanceof short[]) { + return Arrays.equals((short[]) o1, (short[]) o2); + } + } + return false; + } + + public static String nullSafeToString(Object obj) { + if (obj == null) { + return "null"; + } + if (obj instanceof String) { + return (String) obj; + } + if (obj instanceof Object[]) { + return nullSafeToString((Object[]) obj); + } + if (obj instanceof boolean[]) { + return nullSafeToString((boolean[]) obj); + } + if (obj instanceof byte[]) { + return nullSafeToString((byte[]) obj); + } + if (obj instanceof char[]) { + return nullSafeToString((char[]) obj); + } + if (obj instanceof double[]) { + return nullSafeToString((double[]) obj); + } + if (obj instanceof float[]) { + return nullSafeToString((float[]) obj); + } + if (obj instanceof int[]) { + return nullSafeToString((int[]) obj); + } + if (obj instanceof long[]) { + return nullSafeToString((long[]) obj); + } + if (obj instanceof short[]) { + return nullSafeToString((short[]) obj); + } + String str = obj.toString(); + return (str != null ? str : ""); + } + /** * 将字符串List转化为字符串,以分隔符间隔. * diff --git a/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java b/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java deleted file mode 100644 index 9529a9b7b..000000000 --- a/blade-kit/src/main/java/blade/kit/mail/EmailHandle.java +++ /dev/null @@ -1,287 +0,0 @@ -package blade.kit.mail; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Properties; - -import javax.activation.DataHandler; -import javax.activation.FileDataSource; -import javax.mail.BodyPart; -import javax.mail.Message; -import javax.mail.Multipart; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; -import javax.mail.internet.MimeUtility; - -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - -/** - * 邮件发送处理工具类 - * @author jiang.li - * @date 2013-12-19 14:08 - */ -public class EmailHandle { - - private static final Logger LOGGER = LoggerFactory.getLogger(EmailHandle.class); - - /** 邮件对象 **/ - private MimeMessage mimeMsg; - - /** 发送邮件的Session会话 **/ - private Session session; - - /** 邮件发送时的一些配置信息的一个属性对象 **/ - private Properties props; - - /** 发件人的用户名 **/ - private String sendUserName; - - /** 发件人密码 **/ - private String sendUserPass; - - /** 附件添加的组件 **/ - private Multipart mp; - - /** 存放附件文件 **/ - private List files = new LinkedList(); - - - public EmailHandle(String smtp) { - sendUserName = ""; - sendUserPass = ""; - setSmtpHost(smtp); - createMimeMessage(); - } - - private void setSmtpHost(String hostName) { - if (props == null){ - props = System.getProperties(); - } - props.put("mail.smtp.host", hostName); - } - - public boolean createMimeMessage() { - try { - /**用props对象来创建并初始化session对象**/ - session = Session.getDefaultInstance(props, null); - /**用session对象来创建并初始化邮件对象**/ - mimeMsg = new MimeMessage(session); - /**生成附件组件的实例**/ - mp = new MimeMultipart(); - return true; - } catch (Exception e) { - System.err.println("获取邮件会话对象时发生错误!" + e); - return false; - } - - } - - /** - * 设置SMTP的身份认证 - */ - public void setNeedAuth(boolean need) { - if (props == null){ props = System.getProperties();} - if (need){ - props.put("mail.smtp.auth", "true"); - }else{ - props.put("mail.smtp.auth", "false"); - } - - } - - /** - * 进行用户身份验证时,设置用户名和密码 - */ - public void setNamePass(String name, String pass) { - sendUserName = name; - sendUserPass = pass; - } - - /** - * 设置邮件主题 - * - * @param mailSubject - * @return - */ - public boolean setSubject(String mailSubject) { - try { - mimeMsg.setSubject(mailSubject); - return true; - } catch (Exception e) { - return false; - } - - } - - /** - * 设置邮件内容,并设置其为文本格式或HTML文件格式,编码方式为UTF-8 - * @param mailBody - * @return - */ - public boolean setBody(String mailBody) { - try { - BodyPart bp = new MimeBodyPart(); - bp.setContent("" + mailBody, "text/html;charset=UTF-8"); - /**在组件上添加邮件文本**/ - mp.addBodyPart(bp); - } catch (Exception e) { - System.err.println("设置邮件正文时发生错误!" + e); - return false; - } - return true; - } - - /** - * 增加发送附件 - * @param filename 邮件附件的地址,只能是本机地址而不能是网络地址,否则抛出异常 - * @return - */ - public boolean addFileAffix(String filename) { - try { - BodyPart bp = new MimeBodyPart(); - FileDataSource fileds = new FileDataSource(filename); - bp.setDataHandler(new DataHandler(fileds)); - /**解决附件名称乱码**/ - bp.setFileName(MimeUtility.encodeText(fileds.getName(), "UTF-8",null)); - /**添加附件**/ - mp.addBodyPart(bp); - files.add(fileds); - return true; - } catch (Exception e) { - System.err.println("增加邮件附件<" + filename + ">时发生错误:" + e); - return false; - } - - } - - /** - * 删除添加的附件 - * @return - */ - public boolean delFileAffix() { - try { - FileDataSource fileds = null; - for (Iterator it = files.iterator(); it.hasNext();) { - fileds = it.next(); - if (fileds != null && fileds.getFile() != null) { - fileds.getFile().delete(); - } - } - return true; - } catch (Exception e) { - System.err.println("删除邮件附件发生错误:" + e); - return false; - } - - } - - /** - * 设置发件人地址 - * @param from 发件人地址 - * @return - */ - public boolean setFrom(String from) { - try { - mimeMsg.setFrom(new InternetAddress(from)); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * 设置收件人地址 - * @param to收件人的地址 - * @return - */ - public boolean setTo(String to) { - try { - if (to == null) - return false; - - mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * 设置收件人地址 - * @param toList 收件人的地址列表 - * @return - */ - public boolean setToList(String toList) { - try { - if (toList == null) - return false; - InternetAddress[] iaToList = InternetAddress.parse(toList); - mimeMsg.setRecipients(Message.RecipientType.TO, iaToList); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * 发送抄送 - * @param copyto - * @return - */ - public boolean setCopyTo(String copyto) { - try { - if (copyto == null) - return false; - mimeMsg.setRecipients(javax.mail.Message.RecipientType.CC,InternetAddress.parse(copyto)); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * 发送抄送 - * @param copyto - * @return - */ - public boolean setCopyToList(String copytoList) { - try { - if (copytoList == null) - return false; - InternetAddress[] iacopytoList = InternetAddress.parse(copytoList); - mimeMsg.setRecipients(javax.mail.Message.RecipientType.CC, iacopytoList); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * 发送邮件 - * @return - */ - public boolean sendEmail() throws Exception { - LOGGER.debug("Sending mail ..."); - - mimeMsg.setContent(mp); - mimeMsg.saveChanges(); - Session mailSession = Session.getInstance(props, null); - Transport transport = mailSession.getTransport("smtp"); - - /** 连接邮件服务器并进行身份验证 **/ - transport.connect((String) props.get("mail.smtp.host"), sendUserName, sendUserPass); - - /** 发送邮件 **/ - transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.TO)); - transport.close(); - LOGGER.debug("Send mail success."); - return true; - } - -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/mail/MailTemplate.java b/blade-kit/src/main/java/blade/kit/mail/MailTemplate.java deleted file mode 100644 index e83ded523..000000000 --- a/blade-kit/src/main/java/blade/kit/mail/MailTemplate.java +++ /dev/null @@ -1,155 +0,0 @@ -package blade.kit.mail; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -import blade.kit.FileKit; -import blade.kit.PatternKit; -import blade.kit.StringKit; - -/** - * 邮件发送模板 - * - * @author biezhi - * @since 1.0 - */ -public class MailTemplate { - - private String templateBody; - private List ccMails = new ArrayList(); - private List toMails = new ArrayList(); - private List fileList = new ArrayList(); - - public MailTemplate() { - } - - public MailTemplate(String templetPath, String toMail, String ccMail) throws IOException { - - loadTemplet(templetPath); - - if(PatternKit.isEmail(toMail)){ - this.toMails.add(toMail); - } - - if(PatternKit.isEmail(ccMail)){ - this.ccMails.add(ccMail); - } - } - - /** - * 添加附件 - * @param filePath - * @return - */ - public MailTemplate addFile(String filePath){ - if(FileKit.isFile(filePath)){ - this.fileList.add(filePath); - } - return this; - } - - /** - * 添加附件列表 - * @param filePath - * @return - */ - public MailTemplate addFiles(List files){ - if(null != files && files.size() > 0){ - this.fileList.addAll(files); - } - return this; - } - - /** - * 发送给谁 - * @param toMail - * @return - */ - public MailTemplate toMail(String ... toMails){ - if(null != toMails && toMails.length > 0){ - for(String toMail : toMails){ - if(PatternKit.isEmail(toMail)){ - this.toMails.add(toMail); - } - } - } - return this; - } - - public MailTemplate ccMail(String... ccMails){ - if(null != ccMails && ccMails.length > 0){ - for(String ccMail : ccMails){ - if(PatternKit.isEmail(ccMail)){ - this.ccMails.add(ccMail); - } - } - } - return this; - } - - /** - * 加载模板 - * @param templetPath - * @return - * @throws IOException - */ - public MailTemplate loadTemplet(String templetPath) throws IOException { - InputStream input = null; - InputStreamReader read = null; - BufferedReader reader = null; - - if (!new File(templetPath).exists()) { - templateBody = ""; - } - try { - input = new FileInputStream(templetPath); - read = new InputStreamReader(input, "UTF-8"); - reader = new BufferedReader(read); - String line; - String result = ""; - while ((line = reader.readLine()) != null) { - result += line + "\n"; - } - templateBody = result.substring(result.indexOf("")); - } catch (Exception e) { - e.printStackTrace(); - templateBody = ""; - } finally { - reader.close(); - read.close(); - input.close(); - } - - return this; - } - - @Override - public String toString() { - return this.templateBody; - } - - public String getToMail() { - if(null != toMails && toMails.size() > 0){ - StringKit.join(toMails, ",").substring(1); - } - return null; - } - - public String getCcMail() { - if(null != ccMails && ccMails.size() > 0){ - StringKit.join(ccMails, ",").substring(1); - } - return null; - } - - public List getFileList() { - return fileList; - } - -} diff --git a/blade-kit/src/main/java/blade/kit/mail/package-info.java b/blade-kit/src/main/java/blade/kit/mail/package-info.java deleted file mode 100644 index a487957c4..000000000 --- a/blade-kit/src/main/java/blade/kit/mail/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 邮件发送包 - */ -package blade.kit.mail; \ No newline at end of file diff --git a/blade-kit/src/test/java/com/blade/kit/MailTest.java b/blade-kit/src/test/java/com/blade/kit/MailTest.java deleted file mode 100644 index 3edd7ff7f..000000000 --- a/blade-kit/src/test/java/com/blade/kit/MailTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.blade.kit; - -import java.io.IOException; - -import blade.kit.MailKit; -import blade.kit.mail.MailTemplate; - -public class MailTest { - - public static void main(String[] args) { - // 发送方配置,邮箱帐号和密码 - MailKit.config(MailKit.SMTP_QQ, "921293209@qq.com", "helloworld"); - - // 测试给【xxx@qq.com】发送邮件 - MailKit.send("xxx@qq.com", "测试发送邮件", "hello"); - - // 测试异步发送邮件 - MailKit.asynSend("xxx", "测试异步发送邮件", "hello"); - - // 测试给【xxx@qq.com】发送邮件并抄送给xoxo@qq.com - MailKit.sendAndCc("xxx@qq.com", "xoxo@qq.com", "测试发送邮件", "hello"); - - // 测试给【xxx@qq.com】发送邮件并带一个附件 - MailKit.send("xxx@qq.com", "测试发送邮件", "hello", "F:/aa.txt"); - - // 使用模板给【xxx@qq.com】发送邮件并带一个附件 - try { - MailTemplate template = new MailTemplate("F:/a.html", "xxx@qq.com", null); - MailKit.send(template, "新主题"); - } catch (IOException e) { - e.printStackTrace(); - } - - } - -} From 12629bc96d45c0f5abd318fdac45440a0f4aebfb Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 24 Mar 2016 18:03:17 +0800 Subject: [PATCH 448/545] upgrade blade-core to 1.6.1M1 --- README.md | 4 +-- README_CN.md | 2 +- blade-core/pom.xml | 2 +- blade-core/src/main/java/com/blade/Const.java | 2 +- .../src/main/java/com/blade/ioc/Ioc.java | 2 ++ .../java/com/blade/ioc/IocApplication.java | 6 +++++ .../src/main/java/com/blade/ioc/IocKit.java | 25 +++++++++++++++++-- .../main/java/com/blade/ioc/SimpleIoc.java | 7 +++++- .../com/blade/ioc/injector/FieldInjector.java | 7 ------ .../blade/route/annotation/PathVariable.java | 2 +- .../blade/route/annotation/RequestParam.java | 2 +- pom.xml | 2 +- 12 files changed, 45 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 944a5a64b..7611e27da 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.0 + 1.6.1M1 com.bladejava @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.0' +compile 'com.bladejava:blade-core:1.6.1M1' compile 'com.bladejava:blade-startup:1.0.1' ``` diff --git a/README_CN.md b/README_CN.md index f1130fe78..59413ee2c 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,7 +38,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.6.0 + 1.6.1M1 com.bladejava diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 9703e4907..d1e07f027 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -25,7 +25,7 @@ com.bladejava blade-kit - 1.2.9-beta + 1.2.9 Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map - private static Map bean2map(Object obj) { - if (obj == null) { - return null; - } - Map map = new HashMap(); - try { - BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()); - PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); - for (PropertyDescriptor property : propertyDescriptors) { - String key = property.getName(); - // 过滤class属性 - if (!key.equals("class")) { - // 得到property对应的getter方法 - Method getter = property.getReadMethod(); - Object value = getter.invoke(obj); - map.put(key, value); - } - } - } catch (Exception e) { - System.out.println("transBean2Map Error " + e); - } - return map; - } - - // Map --> Bean 1: 利用Introspector,PropertyDescriptor实现 Map --> Bean - private static T map2bean(Map map, Class type) { - T obj = null; - try { - obj = type.getConstructor().newInstance(); - BeanInfo beanInfo = Introspector.getBeanInfo(type); - PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); - for (PropertyDescriptor property : propertyDescriptors) { - String key = property.getName(); - if (map.containsKey(key)) { - Object value = map.get(key); - // 得到property对应的setter方法 - Method setter = property.getWriteMethod(); - setter.invoke(obj, value); - } - } - } catch (Exception e) { - System.out.println("transMap2Bean Error " + e); - } - return obj; - } - - public static T parse(JSONObject jsonObject, Class type) { - Map map = parseToMap(jsonObject); - return map2bean(map, type); - } - - /** - * 对象转换为JsonValue对象 - * - * @param bean - * @return - */ - public static JSONObject parse(Object bean) { - JSONObject json = new JSONObject(); - Class klass = bean.getClass(); - boolean includeSuperClass = klass.getClassLoader() != null; - - Method[] methods = includeSuperClass ? klass.getMethods() : klass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i += 1) { - try { - Method method = methods[i]; - if (Modifier.isPublic(method.getModifiers())) { - String name = method.getName(); - String key = ""; - if (name.startsWith("get")) { - if ("getClass".equals(name) || "getDeclaringClass".equals(name)) { - key = ""; - } else { - key = name.substring(3); - } - } else if (name.startsWith("is")) { - key = name.substring(2); - } - if (key.length() > 0 && Character.isUpperCase(key.charAt(0)) - && method.getParameterTypes().length == 0) { - if (key.length() == 1) { - key = key.toLowerCase(); - } else if (!Character.isUpperCase(key.charAt(1))) { - key = key.substring(0, 1).toLowerCase() + key.substring(1); - } - - Object result = method.invoke(bean, (Object[]) null); - if (result != null) { - json.put(name, result); - } - } - } - } catch (Exception ignore) { - } - } - return json; - } - - @SuppressWarnings("unchecked") - public static JSONObject parse(Map map) { - if (map != null && !map.isEmpty()) { - JSONObject jsonObject = new JSONObject(); - Iterator iterator = map.entrySet().iterator(); - while (iterator.hasNext()) { - Map.Entry entry = (Map.Entry) iterator.next(); - String key = entry.getKey(); - Object val = entry.getValue(); - jsonObject.put(key, val); - } - return jsonObject; - } - return null; - } - +package blade.kit.json; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import blade.kit.StringKit; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; + +public class JSONHelper { + + private static final Logger LOGGER = LoggerFactory.getLogger(JSONHelper.class); + + public static Object toJSONObject(JSONValue value) { + if(value.isBoolean()) + return value.asBoolean(); + else if(value.isNumber()) + return value.asInt(); + else if(value.isString()) + return value.asString(); + else if(value.isArray()) + return jsonArrayAsList(value.asArray()); + else if(value.isObject()) + return jsonObjectAsMap(value.asJSONObject()); + else if(value.isBean()) + return jsonObjectAsMap(value.asJSONObject()); + else return null; + } + + public static T toBean(String json, Class clazz) { + JSONObject jsonObject = JSON.parse(json).asJSONObject(); + if(null == jsonObject){ + return null; + } + + T object = null; + try { + object = clazz.newInstance(); + + /*Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + if(field.getModifiers() == 2){ + String key = field.getName(); + if (jsonObject.contains(key)) { + JSONValue value = jsonObject.get(key); + if(null != value){ + field.setAccessible(true); + field.set(object, value.asString()); + } + } + } + }*/ + + BeanInfo beanInfo = Introspector.getBeanInfo(clazz); + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + for (PropertyDescriptor property : propertyDescriptors) { + String name = property.getName(); + if (jsonObject.contains(name)) { + Object value = getValue(property.getPropertyType(), jsonObject, name); + if(null != value){ + // 得到property对应的setter方法 + Method setter = property.getWriteMethod(); + setter.invoke(object, value); + } + } + } + } catch (Exception e) { + LOGGER.error("jsonobject covert to bean error", e); + } + return object; + } + + private static Object getValue(Class type, JSONObject jsonObject, String name){ + if(null != type && null != jsonObject && StringKit.isNotBlank(name)){ + if(type.equals(String.class)){ + return jsonObject.getString(name); + } + if(type.equals(Long.class) || type.equals(long.class)){ + return jsonObject.getLong(name); + } + if(type.equals(Double.class) || type.equals(double.class)){ + return jsonObject.getDouble(name); + } + if(type.equals(Boolean.class) || type.equals(boolean.class)){ + return jsonObject.getBoolean(name); + } + } + return null; + } + + public static Set jsonArrayAsSet(JSONArray array) { + Set set = new HashSet(); + for(JSONValue value:array) + set.add(toJSONObject(value)); + return set; + } + + public static List jsonArrayAsList(JSONArray array) { + List list = new ArrayList(array.size()); + for(JSONValue element:array) + list.add(toJSONObject(element)); + return list; + } + + public static Map jsonObjectAsMap(JSONObject object) { + Map map = new HashMap(object.size(), 1.f); + for(JSONObject.Member member:object) + map.put(member.getName(), toJSONObject(member.getValue())); + return map; + } + + public static JSONValue toJSONValue(Object object) { + if (object == null) + return JSON.NULL; + else if (object instanceof Boolean) + return JSON.value((Boolean) object); + else if (object instanceof Integer) + return JSON.value((Integer) object); + else if (object instanceof Long) + return JSON.value((Long) object); + else if (object instanceof Float) + return JSON.value((Float) object); + else if (object instanceof Double) + return JSON.value((Double) object); + else if (object instanceof String) + return JSON.value((String) object); + else if (object instanceof Byte) + return JSON.value((Byte) object); + else if (object instanceof Collection) + return toJSONArray((Collection) object); + else if (object instanceof Map) + return mapAsJsonObject((Map) object); + else if (object instanceof JSONObject) + return ((JSONObject)object); + else if (object instanceof JSONArray) + return ((JSONArray)object); + else + return toJSONObject(object); + } + + public static JSONArray toJSONArray(Collection collection) { + JSONArray array = new JSONArray(); + for(Object element:collection) + array.add(toJSONValue(element)); + return array; + } + + public static JSONObject mapAsJsonObject(Map map) { + JSONObject object = new JSONObject(); + for(Entry entry:map.entrySet()) { + object.put(String.valueOf(entry.getKey()), toJSONValue(entry.getValue())); + } + return object; + } + + public static JSONObject toJSONObject(Object bean) { + + Class klass = bean.getClass(); + + // If klass is a System class then set includeSuperClass to false. + boolean includeSuperClass = klass.getClassLoader() != null; + Method[] methods = includeSuperClass ? klass.getMethods() : klass.getDeclaredMethods(); + + if(null == methods || methods.length == 0){ + return null; + } + + Map map = new HashMap(); + + for (int i = 0, len = methods.length; i < len; i ++) { + try { + Method method = methods[i]; + if (Modifier.isPublic(method.getModifiers())) { + String name = method.getName(); + String key = ""; + if (name.startsWith("get")) { + if ("getClass".equals(name) || "getDeclaringClass".equals(name)) { + key = ""; + } else { + key = name.substring(3); + } + } else if (name.startsWith("is")) { + key = name.substring(2); + } + if (key.length() > 0 && Character.isUpperCase(key.charAt(0)) && method.getParameterTypes().length == 0) { + if (key.length() == 1) { + key = key.toLowerCase(); + } else if (!Character.isUpperCase(key.charAt(1))) { + key = key.substring(0, 1).toLowerCase() + key.substring(1); + } + Object result = method.invoke(bean, (Object[]) null); + if(null != result){ + map.put(key, wrap(result)); + } + } + } + } catch (Exception ignore) { + } + } + return mapAsJsonObject(map); + } + + public static Object wrap(Object object) { + try { + if (object == null) { + return null; + } + if (object instanceof JSONObject || object instanceof JSONArray + || JSON.NULL.equals(object) || object instanceof JSONString + || object instanceof Byte || object instanceof Character + || object instanceof Short || object instanceof Integer + || object instanceof Long || object instanceof Boolean + || object instanceof Float || object instanceof Double + || object instanceof String || object instanceof BigInteger + || object instanceof BigDecimal) { + return object; + } + + if (object instanceof Collection) { + Collection coll = (Collection) object; + return toJSONArray(coll); + } + + if (object instanceof Map) { + Map map = (Map) object; + return mapAsJsonObject(map); + } + + Package objectPackage = object.getClass().getPackage(); + String objectPackageName = objectPackage != null ? objectPackage.getName() : ""; + if (objectPackageName.startsWith("java.") + || objectPackageName.startsWith("javax.") + || object.getClass().getClassLoader() == null) { + return object.toString(); + } + return toJSONObject(object); + } catch (Exception exception) { + return null; + } + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/JSONKit.java b/blade-kit/src/main/java/blade/kit/json/JSONKit.java index 49c3b8d79..6680d43d6 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONKit.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONKit.java @@ -1,49 +1,38 @@ -package blade.kit.json; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -public class JSONKit { - - public static Map toMap(String json){ - return JSONHelper.parseToMap(json); - } - - public static Map toMap(JSONObject jsonObject){ - return JSONHelper.parseToMap(jsonObject); - } - - public static T parse(JSONObject jsonObject, Class type){ - return JSONHelper.parse(jsonObject, type); - } - - public static String toJSONString(Object bean){ - return JSONHelper.parse(bean).toString(); - } - - public static String toJSONString(Map map){ - return JSONHelper.mapAsJsonObject(map).toString(); - } - - public static String toJSONString(List list){ - if(null != list && list.size() > 0){ - JSONArray jsonArray = new JSONArray(); - for(T oT : list){ - jsonArray.add(JSONHelper.parse(oT)); - } - return jsonArray.toString(); - } - return null; - } - - public static JSONValue parse(String json) { - try { - return new JSONParser(json).parse(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - -} +package blade.kit.json; + +import blade.kit.StringKit; + +public final class JSONKit { + + private JSONKit() {} + + public static String toJSONString(Object object){ + if(null == object){ + return null; + } + return JSONHelper.toJSONValue(object).toString(); + } + + public static String toJSONString(Object object, boolean flag){ + if(!flag){ + return toJSONString(object); + } + if(null == object){ + return null; + } + return JSONHelper.toJSONValue(object).toString(WriterConfig.PRETTY_PRINT); + } + + public static T parse(String json, Class clazz) { + if(StringKit.isBlank(json) || null == clazz){ + return null; + } + return JSONHelper.toBean(json, clazz); + } + + public static JSONObject parseObject(String json) { + return JSON.parse(json).asJSONObject(); + } + + +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/JSONLiteral.java b/blade-kit/src/main/java/blade/kit/json/JSONLiteral.java index 6267fe81e..bb1abc645 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONLiteral.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONLiteral.java @@ -1,97 +1,97 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; - - -@SuppressWarnings("serial") // use default serial UID -class JSONLiteral extends JSONValue { - - private final String value; - private final boolean isNull; - private final boolean isTrue; - private final boolean isFalse; - - JSONLiteral(String value) { - this.value = value; - isNull = "null".equals(value); - isTrue = "true".equals(value); - isFalse = "false".equals(value); - } - - @Override - void write(JSONWriter writer) throws IOException { - writer.writeLiteral(value); - } - - @Override - public String toString() { - return value; - } - - @Override - public int hashCode() { - return value.hashCode(); - } - - @Override - public boolean isNull() { - return isNull; - } - - @Override - public boolean isTrue() { - return isTrue; - } - - @Override - public boolean isFalse() { - return isFalse; - } - - @Override - public boolean isBoolean() { - return isTrue || isFalse; - } - - @Override - public boolean asBoolean() { - return isNull ? super.asBoolean() : isTrue; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JSONLiteral other = (JSONLiteral)object; - return value.equals(other.value); - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; + + +@SuppressWarnings("serial") // use default serial UID +class JSONLiteral extends JSONValue { + + private final String value; + private final boolean isNull; + private final boolean isTrue; + private final boolean isFalse; + + JSONLiteral(String value) { + this.value = value; + isNull = "null".equals(value); + isTrue = "true".equals(value); + isFalse = "false".equals(value); + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeLiteral(value); + } + + @Override + public String toString() { + return value; + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public boolean isNull() { + return isNull; + } + + @Override + public boolean isTrue() { + return isTrue; + } + + @Override + public boolean isFalse() { + return isFalse; + } + + @Override + public boolean isBoolean() { + return isTrue || isFalse; + } + + @Override + public Boolean asBoolean() { + return isNull ? super.asBoolean() : isTrue; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONLiteral other = (JSONLiteral)object; + return value.equals(other.value); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONNumber.java b/blade-kit/src/main/java/blade/kit/json/JSONNumber.java index feca2639f..63c958da2 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONNumber.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONNumber.java @@ -1,94 +1,97 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; - - -@SuppressWarnings("serial") // use default serial UID -class JSONNumber extends JSONValue { - - private final String string; - - JSONNumber(String string) { - if (string == null) { - throw new NullPointerException("string is null"); - } - this.string = string; - } - - @Override - public String toString() { - return string; - } - - @Override - void write(JSONWriter writer) throws IOException { - writer.writeNumber(string); - } - - @Override - public boolean isNumber() { - return true; - } - - @Override - public int asInt() { - return Integer.parseInt(string, 10); - } - - @Override - public long asLong() { - return Long.parseLong(string, 10); - } - - @Override - public float asFloat() { - return Float.parseFloat(string); - } - - @Override - public double asDouble() { - return Double.parseDouble(string); - } - - @Override - public int hashCode() { - return string.hashCode(); - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JSONNumber other = (JSONNumber)object; - return string.equals(other.string); - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; + +@SuppressWarnings("serial") // use default serial UID +class JSONNumber extends JSONValue { + + private final String string; + + JSONNumber(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + this.string = string; + } + + @Override + public String toString() { + return string; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeNumber(string); + } + + @Override + public boolean isNumber() { + return true; + } + + @Override + public Integer asInt() { + return Integer.parseInt(string, 10); + } + + @Override + public Long asLong() { + return Long.parseLong(string, 10); + } + + @Override + public Float asFloat() { + return Float.parseFloat(string); + } + + @Override + public Double asDouble() { + return Double.parseDouble(string); + } + + public Byte asByte() { + return Byte.parseByte(string); + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONNumber other = (JSONNumber) object; + return string.equals(other.string); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONObject.java b/blade-kit/src/main/java/blade/kit/json/JSONObject.java index 310614b1b..064d69e08 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONObject.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONObject.java @@ -1,1026 +1,947 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Reader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import blade.kit.json.JSONObject.Member; - -/** - * Represents a JSON object, a set of name/value pairs, where the names are - * strings and the values are JSON values. - *

- * Members can be added using the add(String, ...) methods which - * accept instances of {@link JSONValue}, strings, primitive numbers, and - * boolean values. To modify certain values of an object, use the - * set(String, ...) methods. Please note that the add - * methods are faster than set as they do not search for existing - * members. On the other hand, the add methods do not prevent - * adding multiple members with the same name. Duplicate names are discouraged - * but not prohibited by JSON. - *

- *

- * Members can be accessed by their name using {@link #get(String)}. A list of - * all names can be obtained from the method {@link #names()}. This class also - * supports iterating over the members in document order using an - * {@link #iterator()} or an enhanced for loop: - *

- * - *
- * for (Member member : jsonObject) {
- *   String name = member.getName();
- *   JsonValue value = member.getValue();
- *   ...
- * }
- * 
- *

- * Even though JSON objects are unordered by definition, instances of this class - * preserve the order of members to allow processing in document order and to - * guarantee a predictable output. - *

- *

- * Note that this class is not thread-safe. If multiple threads - * access a JsonObject instance concurrently, while at least one of - * these threads modifies the contents of this object, access to the instance - * must be synchronized externally. Failure to do so may lead to an inconsistent - * state. - *

- *

- * This class is not supposed to be extended by clients. - *

- */ -@SuppressWarnings("serial") // use default serial UID -public class JSONObject extends JSONValue implements Iterable { - - private final List names; - private final List values; - private transient HashIndexTable table; - - /** - * Creates a new empty JsonObject. - */ - public JSONObject() { - names = new ArrayList(); - values = new ArrayList(); - table = new HashIndexTable(); - } - - /** - * Creates a new JsonObject, initialized with the contents of the specified - * JSON object. - * - * @param object - * the JSON object to get the initial contents from, must not be - * null - */ - public JSONObject(JSONObject object) { - this(object, false); - } - - private JSONObject(JSONObject object, boolean unmodifiable) { - if (object == null) { - throw new NullPointerException("object is null"); - } - if (unmodifiable) { - names = Collections.unmodifiableList(object.names); - values = Collections.unmodifiableList(object.values); - } else { - names = new ArrayList(object.names); - values = new ArrayList(object.values); - } - table = new HashIndexTable(); - updateHashIndex(); - } - - /** - * Reads a JSON object from the given reader. - *

- * Characters are read in chunks and buffered internally, therefore wrapping - * an existing reader in an additional BufferedReader does - * not improve reading performance. - *

- * - * @param reader - * the reader to read the JSON object from - * @return the JSON object that has been read - * @throws IOException - * if an I/O error occurs in the reader - * @throws ParseException - * if the input is not valid JSON - * @throws UnsupportedOperationException - * if the input does not contain a JSON object - * @deprecated Use {@link JSON#parse(Reader)}{@link JSONValue#asObject() - * .asObject()} instead - */ - @Deprecated - public static JSONObject readFrom(Reader reader) throws IOException { - return JSONValue.readFrom(reader).asObject(); - } - - /** - * Reads a JSON object from the given string. - * - * @param string - * the string that contains the JSON object - * @return the JSON object that has been read - * @throws ParseException - * if the input is not valid JSON - * @throws UnsupportedOperationException - * if the input does not contain a JSON object - * @deprecated Use {@link JSON#parse(String)}{@link JSONValue#asObject() - * .asObject()} instead - */ - @Deprecated - public static JSONObject readFrom(String string) { - return JSONValue.readFrom(string).asObject(); - } - - /** - * Returns an unmodifiable JsonObject for the specified one. This method - * allows to provide read-only access to a JsonObject. - *

- * The returned JsonObject is backed by the given object and reflect changes - * that happen to it. Attempts to modify the returned JsonObject result in - * an UnsupportedOperationException. - *

- * - * @param object - * the JsonObject for which an unmodifiable JsonObject is to be - * returned - * @return an unmodifiable view of the specified JsonObject - */ - public static JSONObject unmodifiableObject(JSONObject object) { - return new JSONObject(object, true); - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified int value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, int value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified long value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, long value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified float value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, float value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified double value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, double value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified boolean value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, boolean value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified string. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, String value) { - put(name, JSON.value(value)); - return this; - } - - public JSONObject put(String name, Object value) { - if (value instanceof String) { - put(name, JSON.value((String) value)); - } - - if (value instanceof Integer) { - put(name, JSON.value((Integer) value)); - } - - if (value instanceof Long) { - put(name, JSON.value((Long) value)); - } - - if (value instanceof JSONValue) { - put(name, (JSONValue) value); - } - - if (value instanceof JSONObject) { - put(name, (JSONObject) value); - } - - if (value instanceof JSONArray) { - put(name, (JSONArray) value); - } - - if (value instanceof Boolean) { - put(name, JSON.value((Boolean) value)); - } - - if (value instanceof Byte) { - put(name, JSON.value((Byte) value)); - } - - if (value instanceof Character) { - put(name, JSON.value((Character) value)); - } - - if (value instanceof Short) { - put(name, JSON.value((Short) value)); - } - - if (value instanceof Float) { - put(name, JSON.value((Float) value)); - } - - if (value instanceof Double) { - put(name, JSON.value((Double) value)); - } - - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the specified JSON value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add, must not be null - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, JSONValue value) { - if (name == null) { - throw new NullPointerException("name is null"); - } - if (value == null) { - throw new NullPointerException("value is null"); - } - table.add(name, names.size()); - names.add(name); - values.add(value); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified int value. If this object - * does not contain a member with this name, a new member is added at the - * end of the object. If this object contains multiple members with this - * name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to replace - * @param value - * the value to set to the member - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, int value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified long value. If this object - * does not contain a member with this name, a new member is added at the - * end of the object. If this object contains multiple members with this - * name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to replace - * @param value - * the value to set to the member - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, long value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified float value. If this object - * does not contain a member with this name, a new member is added at the - * end of the object. If this object contains multiple members with this - * name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, float value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified double value. If this object - * does not contain a member with this name, a new member is added at the - * end of the object. If this object contains multiple members with this - * name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, double value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified boolean value. If this - * object does not contain a member with this name, a new member is added at - * the end of the object. If this object contains multiple members with this - * name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, boolean value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified string. If this object does not contain a - * member with this name, a new member is added at the end of the object. If - * this object contains multiple members with this name, only the last one - * is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, String value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the specified - * JSON value. If this object does not contain a member with this name, a - * new member is added at the end of the object. If this object contains - * multiple members with this name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add, must not be null - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, JSONValue value) { - if (name == null) { - throw new NullPointerException("name is null"); - } - if (value == null) { - throw new NullPointerException("value is null"); - } - int index = indexOf(name); - if (index != -1) { - values.set(index, value); - } else { - table.add(name, names.size()); - names.add(name); - values.add(value); - } - return this; - } - - /** - * Removes a member with the specified name from this object. If this object - * contains multiple members with the given name, only the last one is - * removed. If this object does not contain a member with the specified - * name, the object is not modified. - * - * @param name - * the name of the member to remove - * @return the object itself, to enable method chaining - */ - public JSONObject remove(String name) { - if (name == null) { - throw new NullPointerException("name is null"); - } - int index = indexOf(name); - if (index != -1) { - table.remove(index); - names.remove(index); - values.remove(index); - } - return this; - } - - /** - * Copies all members of the specified object into this object. When the - * specified object contains members with names that also exist in this - * object, the existing values in this object will be replaced by the - * corresponding values in the specified object. - * - * @param object - * the object to merge - * @return the object itself, to enable method chaining - */ - public JSONObject merge(JSONObject object) { - if (object == null) { - throw new NullPointerException("object is null"); - } - for (Member member : object) { - this.set(member.name, member.value); - } - return this; - } - - /** - * Returns the value of the member with the specified name in this object. - * If this object contains multiple members with the given name, this method - * will return the last one. - * - * @param name - * the name of the member whose value is to be returned - * @return the value of the last member with the specified name, or - * null if this object does not contain a member with - * that name - */ - public JSONValue get(String name) { - if (name == null) { - throw new NullPointerException("name is null"); - } - int index = indexOf(name); - return index != -1 ? values.get(index) : null; - } - - public JSONObject getJSONObject(String name) { - JSONValue jsonValue = this.get(name); - if(null != jsonValue){ - return jsonValue.asObject(); - } - return null; - } - - public JSONArray getJSONArray(String name) { - JSONValue jsonValue = this.get(name); - if(null != jsonValue){ - return jsonValue.asArray(); - } - return null; - } - - /** - * Returns the int value of the member with the specified name - * in this object. If this object does not contain a member with this name, - * the given default value is returned. If this object contains multiple - * members with the given name, the last one will be picked. If this - * member's value does not represent a JSON number or if it cannot be - * interpreted as Java int, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public int getInt(String name, int defaultValue) { - JSONValue value = get(name); - return value != null ? value.asInt() : defaultValue; - } - - /** - * Returns the long value of the member with the specified name - * in this object. If this object does not contain a member with this name, - * the given default value is returned. If this object contains multiple - * members with the given name, the last one will be picked. If this - * member's value does not represent a JSON number or if it cannot be - * interpreted as Java long, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public long getLong(String name, long defaultValue) { - JSONValue value = get(name); - return value != null ? value.asLong() : defaultValue; - } - - /** - * Returns the float value of the member with the specified - * name in this object. If this object does not contain a member with this - * name, the given default value is returned. If this object contains - * multiple members with the given name, the last one will be picked. If - * this member's value does not represent a JSON number or if it cannot be - * interpreted as Java float, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public float getFloat(String name, float defaultValue) { - JSONValue value = get(name); - return value != null ? value.asFloat() : defaultValue; - } - - /** - * Returns the double value of the member with the specified - * name in this object. If this object does not contain a member with this - * name, the given default value is returned. If this object contains - * multiple members with the given name, the last one will be picked. If - * this member's value does not represent a JSON number or if it cannot be - * interpreted as Java double, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public double getDouble(String name, double defaultValue) { - JSONValue value = get(name); - return value != null ? value.asDouble() : defaultValue; - } - - /** - * Returns the boolean value of the member with the specified - * name in this object. If this object does not contain a member with this - * name, the given default value is returned. If this object contains - * multiple members with the given name, the last one will be picked. If - * this member's value does not represent a JSON true or - * false value, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public boolean getBoolean(String name, boolean defaultValue) { - JSONValue value = get(name); - return value != null ? value.asBoolean() : defaultValue; - } - - /** - * Returns the String value of the member with the specified - * name in this object. If this object does not contain a member with this - * name, the given default value is returned. If this object contains - * multiple members with the given name, the last one is picked. If this - * member's value does not represent a JSON string, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public String getString(String name, String defaultValue) { - JSONValue value = get(name); - return value != null ? value.asString() : defaultValue; - } - - public String getString(String name) { - JSONValue value = get(name); - return value != null ? value.asString() : null; - } - - /** - * Returns the number of members (name/value pairs) in this object. - * - * @return the number of members in this object - */ - public int size() { - return names.size(); - } - - /** - * Returns true if this object contains no members. - * - * @return true if this object contains no members - */ - public boolean isEmpty() { - return names.isEmpty(); - } - - /** - * Returns a list of the names in this object in document order. The - * returned list is backed by this object and will reflect subsequent - * changes. It cannot be used to modify this object. Attempts to modify the - * returned list will result in an exception. - * - * @return a list of the names in this object - */ - public List names() { - return Collections.unmodifiableList(names); - } - - /** - * Returns an iterator over the members of this object in document order. - * The returned iterator cannot be used to modify this object. - * - * @return an iterator over the members of this object - */ - public Iterator iterator() { - final Iterator namesIterator = names.iterator(); - final Iterator valuesIterator = values.iterator(); - return new Iterator() { - - public boolean hasNext() { - return namesIterator.hasNext(); - } - - public Member next() { - String name = namesIterator.next(); - JSONValue value = valuesIterator.next(); - return new Member(name, value); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } - - @Override - void write(JSONWriter writer) throws IOException { - writer.writeObjectOpen(); - Iterator namesIterator = names.iterator(); - Iterator valuesIterator = values.iterator(); - boolean first = true; - while (namesIterator.hasNext()) { - if (!first) { - writer.writeObjectSeparator(); - } - writer.writeMemberName(namesIterator.next()); - writer.writeMemberSeparator(); - valuesIterator.next().write(writer); - first = false; - } - writer.writeObjectClose(); - } - - @Override - public boolean isObject() { - return true; - } - - @Override - public JSONObject asObject() { - return this; - } - - @Override - public int hashCode() { - int result = 1; - result = 31 * result + names.hashCode(); - result = 31 * result + values.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - JSONObject other = (JSONObject) obj; - return names.equals(other.names) && values.equals(other.values); - } - - int indexOf(String name) { - int index = table.get(name); - if (index != -1 && name.equals(names.get(index))) { - return index; - } - return names.lastIndexOf(name); - } - - private synchronized void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { - inputStream.defaultReadObject(); - table = new HashIndexTable(); - updateHashIndex(); - } - - private void updateHashIndex() { - int size = names.size(); - for (int i = 0; i < size; i++) { - table.add(names.get(i), i); - } - } - - /** - * Represents a member of a JSON object, a pair of a name and a value. - */ - public static class Member { - - private final String name; - private final JSONValue value; - - Member(String name, JSONValue value) { - this.name = name; - this.value = value; - } - - /** - * Returns the name of this member. - * - * @return the name of this member, never null - */ - public String getName() { - return name; - } - - /** - * Returns the value of this member. - * - * @return the value of this member, never null - */ - public JSONValue getValue() { - return value; - } - - @Override - public int hashCode() { - int result = 1; - result = 31 * result + name.hashCode(); - result = 31 * result + value.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Member other = (Member) obj; - return name.equals(other.name) && value.equals(other.value); - } - - } - - static class HashIndexTable { - - private final byte[] hashTable = new byte[32]; // must be a power of two - - public HashIndexTable() { - } - - public HashIndexTable(HashIndexTable original) { - System.arraycopy(original.hashTable, 0, hashTable, 0, hashTable.length); - } - - void add(String name, int index) { - int slot = hashSlotFor(name); - if (index < 0xff) { - // increment by 1, 0 stands for empty - hashTable[slot] = (byte) (index + 1); - } else { - hashTable[slot] = 0; - } - } - - void remove(int index) { - for (int i = 0; i < hashTable.length; i++) { - if (hashTable[i] == index + 1) { - hashTable[i] = 0; - } else if (hashTable[i] > index + 1) { - hashTable[i]--; - } - } - } - - int get(Object name) { - int slot = hashSlotFor(name); - // subtract 1, 0 stands for empty - return (hashTable[slot] & 0xff) - 1; - } - - private int hashSlotFor(Object element) { - return element.hashCode() & hashTable.length - 1; - } - - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import blade.kit.json.JSONObject.Member; + +/** + * Represents a JSON object, a set of name/value pairs, where the names are + * strings and the values are JSON values. + *

+ * Members can be added using the add(String, ...) methods which + * accept instances of {@link JSONValue}, strings, primitive numbers, and + * boolean values. To modify certain values of an object, use the + * set(String, ...) methods. Please note that the add + * methods are faster than set as they do not search for existing + * members. On the other hand, the add methods do not prevent + * adding multiple members with the same name. Duplicate names are discouraged + * but not prohibited by JSON. + *

+ *

+ * Members can be accessed by their name using {@link #get(String)}. A list of + * all names can be obtained from the method {@link #names()}. This class also + * supports iterating over the members in document order using an + * {@link #iterator()} or an enhanced for loop: + *

+ * + *
+ * for (Member member : jsonObject) {
+ *   String name = member.getName();
+ *   JsonValue value = member.getValue();
+ *   ...
+ * }
+ * 
+ *

+ * Even though JSON objects are unordered by definition, instances of this class + * preserve the order of members to allow processing in document order and to + * guarantee a predictable output. + *

+ *

+ * Note that this class is not thread-safe. If multiple threads + * access a JsonObject instance concurrently, while at least one of + * these threads modifies the contents of this object, access to the instance + * must be synchronized externally. Failure to do so may lead to an inconsistent + * state. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public class JSONObject extends JSONValue implements Iterable { + + private final List names; + private final List values; + private transient HashIndexTable table; + + /** + * Creates a new empty JsonObject. + */ + public JSONObject() { + names = new ArrayList(); + values = new ArrayList(); + table = new HashIndexTable(); + } + + /** + * Creates a new JsonObject, initialized with the contents of the specified + * JSON object. + * + * @param object + * the JSON object to get the initial contents from, must not be + * null + */ + public JSONObject(JSONObject object) { + this(object, false); + } + + private JSONObject(JSONObject object, boolean unmodifiable) { + if (object == null) { + throw new NullPointerException("object is null"); + } + if (unmodifiable) { + names = Collections.unmodifiableList(object.names); + values = Collections.unmodifiableList(object.values); + } else { + names = new ArrayList(object.names); + values = new ArrayList(object.values); + } + table = new HashIndexTable(); + updateHashIndex(); + } + + /** + * Returns an unmodifiable JsonObject for the specified one. This method + * allows to provide read-only access to a JsonObject. + *

+ * The returned JsonObject is backed by the given object and reflect changes + * that happen to it. Attempts to modify the returned JsonObject result in + * an UnsupportedOperationException. + *

+ * + * @param object + * the JsonObject for which an unmodifiable JsonObject is to be + * returned + * @return an unmodifiable view of the specified JsonObject + */ + public static JSONObject unmodifiableObject(JSONObject object) { + return new JSONObject(object, true); + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified int value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, int value) { + put(name, JSON.value(value)); + return this; + } + + public JSONObject put(String name, Object value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified long value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, long value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified float value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, float value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified double value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, double value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified boolean value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, boolean value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified string. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, String value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the specified JSON value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add, must not be null + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, JSONValue value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + table.add(name, names.size()); + names.add(name); + values.add(value); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified int value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to replace + * @param value + * the value to set to the member + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, int value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified long value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to replace + * @param value + * the value to set to the member + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, long value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified float value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, float value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified double value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, double value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified boolean value. If this + * object does not contain a member with this name, a new member is added at + * the end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, boolean value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified string. If this object does not contain a + * member with this name, a new member is added at the end of the object. If + * this object contains multiple members with this name, only the last one + * is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, String value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the specified + * JSON value. If this object does not contain a member with this name, a + * new member is added at the end of the object. If this object contains + * multiple members with this name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add, must not be null + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, JSONValue value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + int index = indexOf(name); + if (index != -1) { + values.set(index, value); + } else { + table.add(name, names.size()); + names.add(name); + values.add(value); + } + return this; + } + + /** + * Removes a member with the specified name from this object. If this object + * contains multiple members with the given name, only the last one is + * removed. If this object does not contain a member with the specified + * name, the object is not modified. + * + * @param name + * the name of the member to remove + * @return the object itself, to enable method chaining + */ + public JSONObject remove(String name) { + if (name == null) { + throw new NullPointerException("name is null"); + } + int index = indexOf(name); + if (index != -1) { + table.remove(index); + names.remove(index); + values.remove(index); + } + return this; + } + + /** + * Copies all members of the specified object into this object. When the + * specified object contains members with names that also exist in this + * object, the existing values in this object will be replaced by the + * corresponding values in the specified object. + * + * @param object + * the object to merge + * @return the object itself, to enable method chaining + */ + public JSONObject merge(JSONObject object) { + if (object == null) { + throw new NullPointerException("object is null"); + } + for (Member member : object) { + this.set(member.name, member.value); + } + return this; + } + + /** + * Returns the value of the member with the specified name in this object. + * If this object contains multiple members with the given name, this method + * will return the last one. + * + * @param name + * the name of the member whose value is to be returned + * @return the value of the last member with the specified name, or + * null if this object does not contain a member with + * that name + */ + public JSONValue get(String name) { + if (name == null) { + throw new NullPointerException("name is null"); + } + int index = indexOf(name); + return index != -1 ? values.get(index) : null; + } + + public boolean contains(String name) { + if (name == null) { + throw new NullPointerException("name is null"); + } + int index = indexOf(name); + return index != -1; + } + + + /** + * Returns the int value of the member with the specified name + * in this object. If this object does not contain a member with this name, + * the given default value is returned. If this object contains multiple + * members with the given name, the last one will be picked. If this + * member's value does not represent a JSON number or if it cannot be + * interpreted as Java int, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public Integer getInt(String name, Integer defaultValue) { + JSONValue value = get(name); + return value != null ? value.asInt() : defaultValue; + } + + public Integer getInt(String name) { + return getInt(name, null); + } + + /** + * Returns the long value of the member with the specified name + * in this object. If this object does not contain a member with this name, + * the given default value is returned. If this object contains multiple + * members with the given name, the last one will be picked. If this + * member's value does not represent a JSON number or if it cannot be + * interpreted as Java long, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public Long getLong(String name, Long defaultValue) { + JSONValue value = get(name); + return value != null ? value.asLong() : defaultValue; + } + + public Long getLong(String name) { + return getLong(name, null); + } + + /** + * Returns the float value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one will be picked. If + * this member's value does not represent a JSON number or if it cannot be + * interpreted as Java float, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public Float getFloat(String name, Float defaultValue) { + JSONValue value = get(name); + return value != null ? value.asFloat() : defaultValue; + } + + public Float getFloat(String name) { + return getFloat(name, null); + } + + /** + * Returns the double value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one will be picked. If + * this member's value does not represent a JSON number or if it cannot be + * interpreted as Java double, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public Double getDouble(String name, Double defaultValue) { + JSONValue value = get(name); + return value != null ? value.asDouble() : defaultValue; + } + + public Double getDouble(String name) { + return getDouble(name, null); + } + + /** + * Returns the boolean value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one will be picked. If + * this member's value does not represent a JSON true or + * false value, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public Boolean getBoolean(String name, Boolean defaultValue) { + JSONValue value = get(name); + return value != null ? value.asBoolean() : defaultValue; + } + + public boolean getBoolean(String name) { + return getBoolean(name, null); + } + + /** + * Returns the String value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one is picked. If this + * member's value does not represent a JSON string, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public String getString(String name, String defaultValue) { + JSONValue value = get(name); + return value != null ? value.asString() : defaultValue; + } + + public String getString(String name) { + return getString(name, null); + } + + /** + * Returns the number of members (name/value pairs) in this object. + * + * @return the number of members in this object + */ + public int size() { + return names.size(); + } + + /** + * Returns true if this object contains no members. + * + * @return true if this object contains no members + */ + public boolean isEmpty() { + return names.isEmpty(); + } + + /** + * Returns a list of the names in this object in document order. The + * returned list is backed by this object and will reflect subsequent + * changes. It cannot be used to modify this object. Attempts to modify the + * returned list will result in an exception. + * + * @return a list of the names in this object + */ + public List names() { + return Collections.unmodifiableList(names); + } + + /** + * Returns an iterator over the members of this object in document order. + * The returned iterator cannot be used to modify this object. + * + * @return an iterator over the members of this object + */ + public Iterator iterator() { + final Iterator namesIterator = names.iterator(); + final Iterator valuesIterator = values.iterator(); + return new Iterator() { + + public boolean hasNext() { + return namesIterator.hasNext(); + } + + public Member next() { + String name = namesIterator.next(); + JSONValue value = valuesIterator.next(); + return new Member(name, value); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + }; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeObjectOpen(); + Iterator namesIterator = names.iterator(); + Iterator valuesIterator = values.iterator(); + boolean first = true; + while (namesIterator.hasNext()) { + if (!first) { + writer.writeObjectSeparator(); + } + writer.writeMemberName(namesIterator.next()); + writer.writeMemberSeparator(); + valuesIterator.next().write(writer); + first = false; + } + writer.writeObjectClose(); + } + + @Override + public boolean isObject() { + return true; + } + + @Override + public JSONObject asJSONObject() { + return this; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + names.hashCode(); + result = 31 * result + values.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + JSONObject other = (JSONObject) obj; + return names.equals(other.names) && values.equals(other.values); + } + + int indexOf(String name) { + int index = table.get(name); + if (index != -1 && name.equals(names.get(index))) { + return index; + } + return names.lastIndexOf(name); + } + + private synchronized void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { + inputStream.defaultReadObject(); + table = new HashIndexTable(); + updateHashIndex(); + } + + private void updateHashIndex() { + int size = names.size(); + for (int i = 0; i < size; i++) { + table.add(names.get(i), i); + } + } + + /** + * Represents a member of a JSON object, a pair of a name and a value. + */ + public static class Member { + + private final String name; + private final JSONValue value; + + Member(String name, JSONValue value) { + this.name = name; + this.value = value; + } + + /** + * Returns the name of this member. + * + * @return the name of this member, never null + */ + public String getName() { + return name; + } + + /** + * Returns the value of this member. + * + * @return the value of this member, never null + */ + public JSONValue getValue() { + return value; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + name.hashCode(); + result = 31 * result + value.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Member other = (Member) obj; + return name.equals(other.name) && value.equals(other.value); + } + + } + + static class HashIndexTable { + + private final byte[] hashTable = new byte[32]; // must be a power of two + + public HashIndexTable() { + } + + public HashIndexTable(HashIndexTable original) { + System.arraycopy(original.hashTable, 0, hashTable, 0, hashTable.length); + } + + void add(String name, int index) { + int slot = hashSlotFor(name); + if (index < 0xff) { + // increment by 1, 0 stands for empty + hashTable[slot] = (byte) (index + 1); + } else { + hashTable[slot] = 0; + } + } + + void remove(int index) { + for (int i = 0; i < hashTable.length; i++) { + if (hashTable[i] == index + 1) { + hashTable[i] = 0; + } else if (hashTable[i] > index + 1) { + hashTable[i]--; + } + } + } + + int get(Object name) { + int slot = hashSlotFor(name); + // subtract 1, 0 stands for empty + return (hashTable[slot] & 0xff) - 1; + } + + private int hashSlotFor(Object element) { + return element.hashCode() & hashTable.length - 1; + } + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONParser.java b/blade-kit/src/main/java/blade/kit/json/JSONParser.java index fd7509083..8626a65a3 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONParser.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONParser.java @@ -1,412 +1,511 @@ -/******************************************************************************* - * Copyright (c) 2013, 2016 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; - - -class JSONParser { - - private static final int MAX_NESTING_LEVEL = 1000; - private static final int MIN_BUFFER_SIZE = 10; - private static final int DEFAULT_BUFFER_SIZE = 1024; - - private final Reader reader; - private final char[] buffer; - private int bufferOffset; - private int index; - private int fill; - private int line; - private int lineOffset; - private int current; - private StringBuilder captureBuffer; - private int captureStart; - private int nestingLevel; - - /* - * | bufferOffset - * v - * [a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t] < input - * [l|m|n|o|p|q|r|s|t|?|?] < buffer - * ^ ^ - * | index fill - */ - - JSONParser(String string) { - this(new StringReader(string), - Math.max(MIN_BUFFER_SIZE, Math.min(DEFAULT_BUFFER_SIZE, string.length()))); - } - - JSONParser(Reader reader) { - this(reader, DEFAULT_BUFFER_SIZE); - } - - JSONParser(Reader reader, int buffersize) { - this.reader = reader; - buffer = new char[buffersize]; - line = 1; - captureStart = -1; - } - - JSONValue parse() throws IOException { - read(); - skipWhiteSpace(); - JSONValue result = readValue(); - skipWhiteSpace(); - if (!isEndOfText()) { - throw error("Unexpected character"); - } - return result; - } - - private JSONValue readValue() throws IOException { - switch (current) { - case 'n': - return readNull(); - case 't': - return readTrue(); - case 'f': - return readFalse(); - case '"': - return readString(); - case '[': - return readArray(); - case '{': - return readObject(); - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return readNumber(); - default: - throw expected("value"); - } - } - - private JSONArray readArray() throws IOException { - read(); - if (nestingLevel++ >= MAX_NESTING_LEVEL) { - throw error("Nesting too deep"); - } - JSONArray array = new JSONArray(); - skipWhiteSpace(); - if (readChar(']')) { - nestingLevel--; - return array; - } - do { - skipWhiteSpace(); - array.add(readValue()); - skipWhiteSpace(); - } while (readChar(',')); - if (!readChar(']')) { - throw expected("',' or ']'"); - } - nestingLevel--; - return array; - } - - private JSONObject readObject() throws IOException { - read(); - if (nestingLevel++ >= 1000) { - throw error("Nesting too deep"); - } - JSONObject object = new JSONObject(); - skipWhiteSpace(); - if (readChar('}')) { - nestingLevel--; - return object; - } - do { - skipWhiteSpace(); - String name = readName(); - skipWhiteSpace(); - if (!readChar(':')) { - throw expected("':'"); - } - skipWhiteSpace(); - object.put(name, readValue()); - skipWhiteSpace(); - } while (readChar(',')); - if (!readChar('}')) { - throw expected("',' or '}'"); - } - nestingLevel--; - return object; - } - - private String readName() throws IOException { - if (current != '"') { - throw expected("name"); - } - return readStringInternal(); - } - - private JSONValue readNull() throws IOException { - read(); - readRequiredChar('u'); - readRequiredChar('l'); - readRequiredChar('l'); - return JSON.NULL; - } - - private JSONValue readTrue() throws IOException { - read(); - readRequiredChar('r'); - readRequiredChar('u'); - readRequiredChar('e'); - return JSON.TRUE; - } - - private JSONValue readFalse() throws IOException { - read(); - readRequiredChar('a'); - readRequiredChar('l'); - readRequiredChar('s'); - readRequiredChar('e'); - return JSON.FALSE; - } - - private void readRequiredChar(char ch) throws IOException { - if (!readChar(ch)) { - throw expected("'" + ch + "'"); - } - } - - private JSONValue readString() throws IOException { - return new JSONString(readStringInternal()); - } - - private String readStringInternal() throws IOException { - read(); - startCapture(); - while (current != '"') { - if (current == '\\') { - pauseCapture(); - readEscape(); - startCapture(); - } else if (current < 0x20) { - throw expected("valid string character"); - } else { - read(); - } - } - String string = endCapture(); - read(); - return string; - } - - private void readEscape() throws IOException { - read(); - switch (current) { - case '"': - case '/': - case '\\': - captureBuffer.append((char)current); - break; - case 'b': - captureBuffer.append('\b'); - break; - case 'f': - captureBuffer.append('\f'); - break; - case 'n': - captureBuffer.append('\n'); - break; - case 'r': - captureBuffer.append('\r'); - break; - case 't': - captureBuffer.append('\t'); - break; - case 'u': - char[] hexChars = new char[4]; - for (int i = 0; i < 4; i++) { - read(); - if (!isHexDigit()) { - throw expected("hexadecimal digit"); - } - hexChars[i] = (char)current; - } - captureBuffer.append((char)Integer.parseInt(new String(hexChars), 16)); - break; - default: - throw expected("valid escape sequence"); - } - read(); - } - - private JSONValue readNumber() throws IOException { - startCapture(); - readChar('-'); - int firstDigit = current; - if (!readDigit()) { - throw expected("digit"); - } - if (firstDigit != '0') { - while (readDigit()) { - } - } - readFraction(); - readExponent(); - return new JSONNumber(endCapture()); - } - - private boolean readFraction() throws IOException { - if (!readChar('.')) { - return false; - } - if (!readDigit()) { - throw expected("digit"); - } - while (readDigit()) { - } - return true; - } - - private boolean readExponent() throws IOException { - if (!readChar('e') && !readChar('E')) { - return false; - } - if (!readChar('+')) { - readChar('-'); - } - if (!readDigit()) { - throw expected("digit"); - } - while (readDigit()) { - } - return true; - } - - private boolean readChar(char ch) throws IOException { - if (current != ch) { - return false; - } - read(); - return true; - } - - private boolean readDigit() throws IOException { - if (!isDigit()) { - return false; - } - read(); - return true; - } - - private void skipWhiteSpace() throws IOException { - while (isWhiteSpace()) { - read(); - } - } - - private void read() throws IOException { - if (index == fill) { - if (captureStart != -1) { - captureBuffer.append(buffer, captureStart, fill - captureStart); - captureStart = 0; - } - bufferOffset += fill; - fill = reader.read(buffer, 0, buffer.length); - index = 0; - if (fill == -1) { - current = -1; - return; - } - } - if (current == '\n') { - line++; - lineOffset = bufferOffset + index; - } - current = buffer[index++]; - } - - private void startCapture() { - if (captureBuffer == null) { - captureBuffer = new StringBuilder(); - } - captureStart = index - 1; - } - - private void pauseCapture() { - int end = current == -1 ? index : index - 1; - captureBuffer.append(buffer, captureStart, end - captureStart); - captureStart = -1; - } - - private String endCapture() { - int end = current == -1 ? index : index - 1; - String captured; - if (captureBuffer.length() > 0) { - captureBuffer.append(buffer, captureStart, end - captureStart); - captured = captureBuffer.toString(); - captureBuffer.setLength(0); - } else { - captured = new String(buffer, captureStart, end - captureStart); - } - captureStart = -1; - return captured; - } - - private ParseException expected(String expected) { - if (isEndOfText()) { - return error("Unexpected end of input"); - } - return error("Expected " + expected); - } - - private ParseException error(String message) { - int absIndex = bufferOffset + index; - int column = absIndex - lineOffset; - int offset = isEndOfText() ? absIndex : absIndex - 1; - return new ParseException(message, offset, line, column - 1); - } - - private boolean isWhiteSpace() { - return current == ' ' || current == '\t' || current == '\n' || current == '\r'; - } - - private boolean isDigit() { - return current >= '0' && current <= '9'; - } - - private boolean isHexDigit() { - return current >= '0' && current <= '9' - || current >= 'a' && current <= 'f' - || current >= 'A' && current <= 'F'; - } - - private boolean isEndOfText() { - return current == -1; - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + + +/** + * A streaming parser for JSON text. The parser reports all events to a given handler. + */ +public class JSONParser { + + private static final int MAX_NESTING_LEVEL = 1000; + private static final int MIN_BUFFER_SIZE = 10; + private static final int DEFAULT_BUFFER_SIZE = 1024; + + private final JSONHandler handler; + private Reader reader; + private char[] buffer; + private int bufferOffset; + private int index; + private int fill; + private int line; + private int lineOffset; + private int current; + private StringBuilder captureBuffer; + private int captureStart; + private int nestingLevel; + + /* + * | bufferOffset + * v + * [a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t] < input + * [l|m|n|o|p|q|r|s|t|?|?] < buffer + * ^ ^ + * | index fill + */ + + /** + * Creates a new JsonParser with the given handler. The parser will report all parser events to + * this handler. + * + * @param handler + * the handler to process parser events + */ + @SuppressWarnings("unchecked") + public JSONParser(JSONHandler handler) { + if (handler == null) { + throw new NullPointerException("handler is null"); + } + this.handler = (JSONHandler)handler; + handler.parser = this; + } + + /** + * Parses the given input string. The input must contain a valid JSON value, optionally padded + * with whitespace. + * + * @param string + * the input string, must be valid JSON + * @throws ParseException + * if the input is not valid JSON + */ + public void parse(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + int bufferSize = Math.max(MIN_BUFFER_SIZE, Math.min(DEFAULT_BUFFER_SIZE, string.length())); + try { + parse(new StringReader(string), bufferSize); + } catch (IOException exception) { + // StringReader does not throw IOException + throw new RuntimeException(exception); + } + } + + /** + * Reads the entire input from the given reader and parses it as JSON. The input must contain a + * valid JSON value, optionally padded with whitespace. + *

+ * Characters are read in chunks into a default-sized input buffer. Hence, wrapping a reader in an + * additional BufferedReader likely won't improve reading performance. + *

+ * + * @param reader + * the reader to read the input from + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + */ + public void parse(Reader reader) throws IOException { + parse(reader, DEFAULT_BUFFER_SIZE); + } + + /** + * Reads the entire input from the given reader and parses it as JSON. The input must contain a + * valid JSON value, optionally padded with whitespace. + *

+ * Characters are read in chunks into an input buffer of the given size. Hence, wrapping a reader + * in an additional BufferedReader likely won't improve reading performance. + *

+ * + * @param reader + * the reader to read the input from + * @param buffersize + * the size of the input buffer in chars + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + */ + public void parse(Reader reader, int buffersize) throws IOException { + if (reader == null) { + throw new NullPointerException("reader is null"); + } + if (buffersize <= 0) { + throw new IllegalArgumentException("buffersize is zero or negative"); + } + this.reader = reader; + buffer = new char[buffersize]; + bufferOffset = 0; + index = 0; + fill = 0; + line = 1; + lineOffset = 0; + current = 0; + captureStart = -1; + read(); + skipWhiteSpace(); + readValue(); + skipWhiteSpace(); + if (!isEndOfText()) { + throw error("Unexpected character"); + } + } + + private void readValue() throws IOException { + switch (current) { + case 'n': + readNull(); + break; + case 't': + readTrue(); + break; + case 'f': + readFalse(); + break; + case '"': + readString(); + break; + case '[': + readArray(); + break; + case '{': + readObject(); + break; + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + readNumber(); + break; + default: + throw expected("value"); + } + } + + private void readArray() throws IOException { + Object array = handler.startArray(); + read(); + if (++nestingLevel > MAX_NESTING_LEVEL) { + throw error("Nesting too deep"); + } + skipWhiteSpace(); + if (readChar(']')) { + nestingLevel--; + handler.endArray(array); + return; + } + do { + skipWhiteSpace(); + handler.startArrayValue(array); + readValue(); + handler.endArrayValue(array); + skipWhiteSpace(); + } while (readChar(',')); + if (!readChar(']')) { + throw expected("',' or ']'"); + } + nestingLevel--; + handler.endArray(array); + } + + private void readObject() throws IOException { + Object object = handler.startObject(); + read(); + if (++nestingLevel > MAX_NESTING_LEVEL) { + throw error("Nesting too deep"); + } + skipWhiteSpace(); + if (readChar('}')) { + nestingLevel--; + handler.endObject(object); + return; + } + do { + skipWhiteSpace(); + handler.startObjectName(object); + String name = readName(); + handler.endObjectName(object, name); + skipWhiteSpace(); + if (!readChar(':')) { + throw expected("':'"); + } + skipWhiteSpace(); + handler.startObjectValue(object, name); + readValue(); + handler.endObjectValue(object, name); + skipWhiteSpace(); + } while (readChar(',')); + if (!readChar('}')) { + throw expected("',' or '}'"); + } + nestingLevel--; + handler.endObject(object); + } + + private String readName() throws IOException { + if (current != '"') { + throw expected("name"); + } + return readStringInternal(); + } + + private void readNull() throws IOException { + handler.startNull(); + read(); + readRequiredChar('u'); + readRequiredChar('l'); + readRequiredChar('l'); + handler.endNull(); + } + + private void readTrue() throws IOException { + handler.startBoolean(); + read(); + readRequiredChar('r'); + readRequiredChar('u'); + readRequiredChar('e'); + handler.endBoolean(true); + } + + private void readFalse() throws IOException { + handler.startBoolean(); + read(); + readRequiredChar('a'); + readRequiredChar('l'); + readRequiredChar('s'); + readRequiredChar('e'); + handler.endBoolean(false); + } + + private void readRequiredChar(char ch) throws IOException { + if (!readChar(ch)) { + throw expected("'" + ch + "'"); + } + } + + private void readString() throws IOException { + handler.startString(); + handler.endString(readStringInternal()); + } + + private String readStringInternal() throws IOException { + read(); + startCapture(); + while (current != '"') { + if (current == '\\') { + pauseCapture(); + readEscape(); + startCapture(); + } else if (current < 0x20) { + throw expected("valid string character"); + } else { + read(); + } + } + String string = endCapture(); + read(); + return string; + } + + private void readEscape() throws IOException { + read(); + switch (current) { + case '"': + case '/': + case '\\': + captureBuffer.append((char)current); + break; + case 'b': + captureBuffer.append('\b'); + break; + case 'f': + captureBuffer.append('\f'); + break; + case 'n': + captureBuffer.append('\n'); + break; + case 'r': + captureBuffer.append('\r'); + break; + case 't': + captureBuffer.append('\t'); + break; + case 'u': + char[] hexChars = new char[4]; + for (int i = 0; i < 4; i++) { + read(); + if (!isHexDigit()) { + throw expected("hexadecimal digit"); + } + hexChars[i] = (char)current; + } + captureBuffer.append((char)Integer.parseInt(new String(hexChars), 16)); + break; + default: + throw expected("valid escape sequence"); + } + read(); + } + + private void readNumber() throws IOException { + handler.startNumber(); + startCapture(); + readChar('-'); + int firstDigit = current; + if (!readDigit()) { + throw expected("digit"); + } + if (firstDigit != '0') { + while (readDigit()) { + } + } + readFraction(); + readExponent(); + handler.endNumber(endCapture()); + } + + private boolean readFraction() throws IOException { + if (!readChar('.')) { + return false; + } + if (!readDigit()) { + throw expected("digit"); + } + while (readDigit()) { + } + return true; + } + + private boolean readExponent() throws IOException { + if (!readChar('e') && !readChar('E')) { + return false; + } + if (!readChar('+')) { + readChar('-'); + } + if (!readDigit()) { + throw expected("digit"); + } + while (readDigit()) { + } + return true; + } + + private boolean readChar(char ch) throws IOException { + if (current != ch) { + return false; + } + read(); + return true; + } + + private boolean readDigit() throws IOException { + if (!isDigit()) { + return false; + } + read(); + return true; + } + + private void skipWhiteSpace() throws IOException { + while (isWhiteSpace()) { + read(); + } + } + + private void read() throws IOException { + if (index == fill) { + if (captureStart != -1) { + captureBuffer.append(buffer, captureStart, fill - captureStart); + captureStart = 0; + } + bufferOffset += fill; + fill = reader.read(buffer, 0, buffer.length); + index = 0; + if (fill == -1) { + current = -1; + index++; + return; + } + } + if (current == '\n') { + line++; + lineOffset = bufferOffset + index; + } + current = buffer[index++]; + } + + private void startCapture() { + if (captureBuffer == null) { + captureBuffer = new StringBuilder(); + } + captureStart = index - 1; + } + + private void pauseCapture() { + int end = current == -1 ? index : index - 1; + captureBuffer.append(buffer, captureStart, end - captureStart); + captureStart = -1; + } + + private String endCapture() { + int start = captureStart; + int end = index - 1; + captureStart = -1; + if (captureBuffer.length() > 0) { + captureBuffer.append(buffer, start, end - start); + String captured = captureBuffer.toString(); + captureBuffer.setLength(0); + return captured; + } + return new String(buffer, start, end - start); + } + + Location getLocation() { + int offset = bufferOffset + index - 1; + int column = offset - lineOffset + 1; + return new Location(offset, line, column); + } + + private ParseException expected(String expected) { + if (isEndOfText()) { + return error("Unexpected end of input"); + } + return error("Expected " + expected); + } + + private ParseException error(String message) { + return new ParseException(message, getLocation()); + } + + private boolean isWhiteSpace() { + return current == ' ' || current == '\t' || current == '\n' || current == '\r'; + } + + private boolean isDigit() { + return current >= '0' && current <= '9'; + } + + private boolean isHexDigit() { + return current >= '0' && current <= '9' + || current >= 'a' && current <= 'f' + || current >= 'A' && current <= 'F'; + } + + private boolean isEndOfText() { + return current == -1; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONString.java b/blade-kit/src/main/java/blade/kit/json/JSONString.java index 886271320..7751b2b96 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONString.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONString.java @@ -1,74 +1,74 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; - - -@SuppressWarnings("serial") // use default serial UID -class JSONString extends JSONValue { - - private final String string; - - JSONString(String string) { - if (string == null) { - throw new NullPointerException("string is null"); - } - this.string = string; - } - - @Override - void write(JSONWriter writer) throws IOException { - writer.writeString(string); - } - - @Override - public boolean isString() { - return true; - } - - @Override - public String asString() { - return string; - } - - @Override - public int hashCode() { - return string.hashCode(); - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JSONString other = (JSONString)object; - return string.equals(other.string); - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; + + +@SuppressWarnings("serial") // use default serial UID +class JSONString extends JSONValue { + + private final String string; + + JSONString(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + this.string = string; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeString(string); + } + + @Override + public boolean isString() { + return true; + } + + @Override + public String asString() { + return string; + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONString other = (JSONString)object; + return string.equals(other.string); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONValue.java b/blade-kit/src/main/java/blade/kit/json/JSONValue.java index 123acc889..c6312c6cd 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONValue.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONValue.java @@ -1,500 +1,391 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Reader; -import java.io.Serializable; -import java.io.StringWriter; -import java.io.Writer; - - -/** - * Represents a JSON value. This can be a JSON object, an array, - * a number, a string, or one of the literals - * true, false, and null. - *

- * The literals true, false, and null are - * represented by the constants {@link #TRUE}, {@link #FALSE}, and {@link #NULL}. - *

- *

- * JSON objects and arrays are represented by the subtypes - * {@link JSONObject} and {@link JSONArray}. Instances of these types can be created using the - * public constructors of these classes. - *

- *

- * Instances that represent JSON numbers, strings and - * boolean values can be created using the static factory methods - * {@link #valueOf(String)}, {@link #valueOf(long)}, {@link #valueOf(double)}, etc. - *

- *

- * In order to find out whether an instance of this class is of a certain type, the methods - * {@link #isObject()}, {@link #isArray()}, {@link #isString()}, {@link #isNumber()} etc. can be - * used. - *

- *

- * If the type of a JSON value is known, the methods {@link #asObject()}, {@link #asArray()}, - * {@link #asString()}, {@link #asInt()}, etc. can be used to get this value directly in the - * appropriate target type. - *

- *

- * This class is not supposed to be extended by clients. - *

- */ -@SuppressWarnings("serial") // use default serial UID -public abstract class JSONValue implements Serializable { - - /** - * Represents the JSON literal true. - * @deprecated Use Json.TRUE instead - */ - @Deprecated - public static final JSONValue TRUE = new JSONLiteral("true"); - - /** - * Represents the JSON literal false. - * @deprecated Use Json.FALSE instead - */ - @Deprecated - public static final JSONValue FALSE = new JSONLiteral("false"); - - /** - * Represents the JSON literal null. - * @deprecated Use Json.NULL instead - */ - @Deprecated - public static final JSONValue NULL = new JSONLiteral("null"); - - JSONValue() { - // prevent subclasses outside of this package - } - - /** - * Reads a JSON value from the given reader. - *

- * Characters are read in chunks and buffered internally, therefore wrapping an existing reader in - * an additional BufferedReader does not improve reading - * performance. - *

- * - * @param reader - * the reader to read the JSON value from - * @return the JSON value that has been read - * @throws IOException - * if an I/O error occurs in the reader - * @throws ParseException - * if the input is not valid JSON - * @deprecated Use {@link JSON#parse(Reader)} instead - */ - @Deprecated - public static JSONValue readFrom(Reader reader) throws IOException { - return new JSONParser(reader).parse(); - } - - /** - * Reads a JSON value from the given string. - * - * @param text - * the string that contains the JSON value - * @return the JSON value that has been read - * @throws ParseException - * if the input is not valid JSON - * @deprecated Use {@link JSON#parse(String)} instead - */ - @Deprecated - public static JSONValue readFrom(String text) { - try { - return new JSONParser(text).parse(); - } catch (IOException exception) { - // JsonParser does not throw IOException for String - throw new RuntimeException(exception); - } - } - - /** - * Returns a JsonValue instance that represents the given int value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JSONValue valueOf(int value) { - return JSON.value(value); - } - - /** - * Returns a JsonValue instance that represents the given long value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JSONValue valueOf(long value) { - return JSON.value(value); - } - - /** - * Returns a JsonValue instance that represents the given float value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JSONValue valueOf(float value) { - return JSON.value(value); - } - - /** - * Returns a JsonValue instance that represents the given double value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JSONValue valueOf(double value) { - return JSON.value(value); - } - - /** - * Returns a JsonValue instance that represents the given string. - * - * @param string - * the string to get a JSON representation for - * @return a JSON value that represents the given string - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JSONValue valueOf(String string) { - return JSON.value(string); - } - - /** - * Returns a JsonValue instance that represents the given boolean value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - * @deprecated Use Json.value() instead - */ - @Deprecated - public static JSONValue valueOf(boolean value) { - return JSON.value(value); - } - - /** - * Detects whether this value represents a JSON object. If this is the case, this value is an - * instance of {@link JSONObject}. - * - * @return true if this value is an instance of JsonObject - */ - public boolean isObject() { - return false; - } - - /** - * Detects whether this value represents a JSON array. If this is the case, this value is an - * instance of {@link JSONArray}. - * - * @return true if this value is an instance of JsonArray - */ - public boolean isArray() { - return false; - } - - /** - * Detects whether this value represents a JSON number. - * - * @return true if this value represents a JSON number - */ - public boolean isNumber() { - return false; - } - - /** - * Detects whether this value represents a JSON string. - * - * @return true if this value represents a JSON string - */ - public boolean isString() { - return false; - } - - /** - * Detects whether this value represents a boolean value. - * - * @return true if this value represents either the JSON literal true or - * false - */ - public boolean isBoolean() { - return false; - } - - /** - * Detects whether this value represents the JSON literal true. - * - * @return true if this value represents the JSON literal true - */ - public boolean isTrue() { - return false; - } - - /** - * Detects whether this value represents the JSON literal false. - * - * @return true if this value represents the JSON literal false - */ - public boolean isFalse() { - return false; - } - - /** - * Detects whether this value represents the JSON literal null. - * - * @return true if this value represents the JSON literal null - */ - public boolean isNull() { - return false; - } - - /** - * Returns this JSON value as {@link JSONObject}, assuming that this value represents a JSON - * object. If this is not the case, an exception is thrown. - * - * @return a JSONObject for this value - * @throws UnsupportedOperationException - * if this value is not a JSON object - */ - public JSONObject asObject() { - throw new UnsupportedOperationException("Not an object: " + toString()); - } - - /** - * Returns this JSON value as {@link JSONArray}, assuming that this value represents a JSON array. - * If this is not the case, an exception is thrown. - * - * @return a JSONArray for this value - * @throws UnsupportedOperationException - * if this value is not a JSON array - */ - public JSONArray asArray() { - throw new UnsupportedOperationException("Not an array: " + toString()); - } - - /** - * Returns this JSON value as an int value, assuming that this value represents a - * JSON number that can be interpreted as Java int. If this is not the case, an - * exception is thrown. - *

- * To be interpreted as Java int, the JSON number must neither contain an exponent - * nor a fraction part. Moreover, the number must be in the Integer range. - *

- * - * @return this value as int - * @throws UnsupportedOperationException - * if this value is not a JSON number - * @throws NumberFormatException - * if this JSON number can not be interpreted as int value - */ - public int asInt() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as a long value, assuming that this value represents a - * JSON number that can be interpreted as Java long. If this is not the case, an - * exception is thrown. - *

- * To be interpreted as Java long, the JSON number must neither contain an exponent - * nor a fraction part. Moreover, the number must be in the Long range. - *

- * - * @return this value as long - * @throws UnsupportedOperationException - * if this value is not a JSON number - * @throws NumberFormatException - * if this JSON number can not be interpreted as long value - */ - public long asLong() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as a float value, assuming that this value represents a - * JSON number. If this is not the case, an exception is thrown. - *

- * If the JSON number is out of the Float range, {@link Float#POSITIVE_INFINITY} or - * {@link Float#NEGATIVE_INFINITY} is returned. - *

- * - * @return this value as float - * @throws UnsupportedOperationException - * if this value is not a JSON number - */ - public float asFloat() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as a double value, assuming that this value represents a - * JSON number. If this is not the case, an exception is thrown. - *

- * If the JSON number is out of the Double range, {@link Double#POSITIVE_INFINITY} or - * {@link Double#NEGATIVE_INFINITY} is returned. - *

- * - * @return this value as double - * @throws UnsupportedOperationException - * if this value is not a JSON number - */ - public double asDouble() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as String, assuming that this value represents a JSON string. If this - * is not the case, an exception is thrown. - * - * @return the string represented by this value - * @throws UnsupportedOperationException - * if this value is not a JSON string - */ - public String asString() { - throw new UnsupportedOperationException("Not a string: " + toString()); - } - - /** - * Returns this JSON value as a boolean value, assuming that this value is either - * true or false. If this is not the case, an exception is thrown. - * - * @return this value as boolean - * @throws UnsupportedOperationException - * if this value is neither true or false - */ - public boolean asBoolean() { - throw new UnsupportedOperationException("Not a boolean: " + toString()); - } - - /** - * Writes the JSON representation of this value to the given writer in its minimal form, without - * any additional whitespace. - *

- * Writing performance can be improved by using a {@link java.io.BufferedWriter BufferedWriter}. - *

- * - * @param writer - * the writer to write this value to - * @throws IOException - * if an I/O error occurs in the writer - */ - public void writeTo(Writer writer) throws IOException { - writeTo(writer, WriterConfig.MINIMAL); - } - - /** - * Writes the JSON representation of this value to the given writer using the given formatting. - *

- * Writing performance can be improved by using a {@link java.io.BufferedWriter BufferedWriter}. - *

- * - * @param writer - * the writer to write this value to - * @param config - * a configuration that controls the formatting or null for the minimal form - * @throws IOException - * if an I/O error occurs in the writer - */ - public void writeTo(Writer writer, WriterConfig config) throws IOException { - if (writer == null) { - throw new NullPointerException("writer is null"); - } - if (config == null) { - throw new NullPointerException("config is null"); - } - WritingBuffer buffer = new WritingBuffer(writer, 128); - write(config.createWriter(buffer)); - buffer.flush(); - } - - /** - * Returns the JSON string for this value in its minimal form, without any additional whitespace. - * The result is guaranteed to be a valid input for the method {@link #readFrom(String)} and to - * create a value that is equal to this object. - * - * @return a JSON string that represents this value - */ - @Override - public String toString() { - return toString(WriterConfig.MINIMAL); - } - - /** - * Returns the JSON string for this value using the given formatting. - * - * @param config - * a configuration that controls the formatting or null for the minimal form - * @return a JSON string that represents this value - */ - public String toString(WriterConfig config) { - StringWriter writer = new StringWriter(); - try { - writeTo(writer, config); - } catch (IOException exception) { - // StringWriter does not throw IOExceptions - throw new RuntimeException(exception); - } - return writer.toString(); - } - - /** - * Indicates whether some other object is "equal to" this one according to the contract specified - * in {@link Object#equals(Object)}. - *

- * Two JsonValues are considered equal if and only if they represent the same JSON text. As a - * consequence, two given JsonObjects may be different even though they contain the same set of - * names with the same values, but in a different order. - *

- * - * @param object - * the reference object with which to compare - * @return true if this object is the same as the object argument; false otherwise - */ - @Override - public boolean equals(Object object) { - return super.equals(object); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - abstract void write(JSONWriter writer) throws IOException; - -} +/******************************************************************************* + * Copyright (c) 2013, 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Serializable; +import java.io.StringWriter; +import java.io.Writer; + +/** + * Represents a JSON value. This can be a JSON object, an + * array, a number, a string + * , or one of the literals true, false, and + * null. + *

+ * The literals true, false, and + * null are represented by the constants {@link #TRUE}, + * {@link #FALSE}, and {@link #NULL}. + *

+ *

+ * JSON objects and arrays are represented by + * the subtypes {@link JSONObject} and {@link JSONArray}. Instances of these + * types can be created using the public constructors of these classes. + *

+ *

+ * Instances that represent JSON numbers, + * strings and boolean values can be created + * using the static factory methods {@link #valueOf(String)}, + * {@link #valueOf(long)}, {@link #valueOf(double)}, etc. + *

+ *

+ * In order to find out whether an instance of this class is of a certain type, + * the methods {@link #isObject()}, {@link #isArray()}, {@link #isString()}, + * {@link #isNumber()} etc. can be used. + *

+ *

+ * If the type of a JSON value is known, the methods {@link #asObject()}, + * {@link #asArray()}, {@link #asString()}, {@link #asInt()}, etc. can be used + * to get this value directly in the appropriate target type. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public abstract class JSONValue implements Serializable { + + JSONValue() { + // prevent subclasses outside of this package + } + + /** + * Detects whether this value represents a JSON object. If this is the case, + * this value is an instance of {@link JSONObject}. + * + * @return true if this value is an instance of JsonObject + */ + public boolean isObject() { + return false; + } + + public boolean isBean() { + return false; + } + + /** + * Detects whether this value represents a JSON array. If this is the case, + * this value is an instance of {@link JSONArray}. + * + * @return true if this value is an instance of JsonArray + */ + public boolean isArray() { + return false; + } + + /** + * Detects whether this value represents a JSON number. + * + * @return true if this value represents a JSON number + */ + public boolean isNumber() { + return false; + } + + /** + * Detects whether this value represents a JSON string. + * + * @return true if this value represents a JSON string + */ + public boolean isString() { + return false; + } + + public boolean isLong(){ + return false; + } + + /** + * Detects whether this value represents a boolean value. + * + * @return true if this value represents either the JSON + * literal true or false + */ + public boolean isBoolean() { + return false; + } + + /** + * Detects whether this value represents the JSON literal true. + * + * @return true if this value represents the JSON literal + * true + */ + public boolean isTrue() { + return false; + } + + /** + * Detects whether this value represents the JSON literal false + * . + * + * @return true if this value represents the JSON literal + * false + */ + public boolean isFalse() { + return false; + } + + /** + * Detects whether this value represents the JSON literal null. + * + * @return true if this value represents the JSON literal + * null + */ + public boolean isNull() { + return false; + } + + /** + * Returns this JSON value as {@link JSONObject}, assuming that this value + * represents a JSON object. If this is not the case, an exception is + * thrown. + * + * @return a JSONObject for this value + * @throws UnsupportedOperationException + * if this value is not a JSON object + */ + public JSONObject asJSONObject() { + throw new UnsupportedOperationException("Not an JSONObject: " + toString()); + } + + /** + * Returns this JSON value as {@link JSONArray}, assuming that this value + * represents a JSON array. If this is not the case, an exception is thrown. + * + * @return a JSONArray for this value + * @throws UnsupportedOperationException + * if this value is not a JSON array + */ + public JSONArray asArray() { + throw new UnsupportedOperationException("Not an array: " + toString()); + } + + /** + * Returns this JSON value as an int value, assuming that this + * value represents a JSON number that can be interpreted as Java + * int. If this is not the case, an exception is thrown. + *

+ * To be interpreted as Java int, the JSON number must neither + * contain an exponent nor a fraction part. Moreover, the number must be in + * the Integer range. + *

+ * + * @return this value as int + * @throws UnsupportedOperationException + * if this value is not a JSON number + * @throws NumberFormatException + * if this JSON number can not be interpreted as + * int value + */ + public Integer asInt() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a long value, assuming that this + * value represents a JSON number that can be interpreted as Java + * long. If this is not the case, an exception is thrown. + *

+ * To be interpreted as Java long, the JSON number must neither + * contain an exponent nor a fraction part. Moreover, the number must be in + * the Long range. + *

+ * + * @return this value as long + * @throws UnsupportedOperationException + * if this value is not a JSON number + * @throws NumberFormatException + * if this JSON number can not be interpreted as + * long value + */ + public Long asLong() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a float value, assuming that this + * value represents a JSON number. If this is not the case, an exception is + * thrown. + *

+ * If the JSON number is out of the Float range, + * {@link Float#POSITIVE_INFINITY} or {@link Float#NEGATIVE_INFINITY} is + * returned. + *

+ * + * @return this value as float + * @throws UnsupportedOperationException + * if this value is not a JSON number + */ + public Float asFloat() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a double value, assuming that + * this value represents a JSON number. If this is not the case, an + * exception is thrown. + *

+ * If the JSON number is out of the Double range, + * {@link Double#POSITIVE_INFINITY} or {@link Double#NEGATIVE_INFINITY} is + * returned. + *

+ * + * @return this value as double + * @throws UnsupportedOperationException + * if this value is not a JSON number + */ + public Double asDouble() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as String, assuming that this value represents a + * JSON string. If this is not the case, an exception is thrown. + * + * @return the string represented by this value + * @throws UnsupportedOperationException + * if this value is not a JSON string + */ + public String asString() { + throw new UnsupportedOperationException("Not a string: " + toString()); + } + + /** + * Returns this JSON value as a boolean value, assuming that + * this value is either true or false. If this is + * not the case, an exception is thrown. + * + * @return this value as boolean + * @throws UnsupportedOperationException + * if this value is neither true or + * false + */ + public Boolean asBoolean() { + throw new UnsupportedOperationException("Not a boolean: " + toString()); + } + + /** + * Writes the JSON representation of this value to the given writer in its + * minimal form, without any additional whitespace. + *

+ * Writing performance can be improved by using a + * {@link java.io.BufferedWriter BufferedWriter}. + *

+ * + * @param writer + * the writer to write this value to + * @throws IOException + * if an I/O error occurs in the writer + */ + public void writeTo(Writer writer) throws IOException { + writeTo(writer, WriterConfig.MINIMAL); + } + + /** + * Writes the JSON representation of this value to the given writer using + * the given formatting. + *

+ * Writing performance can be improved by using a + * {@link java.io.BufferedWriter BufferedWriter}. + *

+ * + * @param writer + * the writer to write this value to + * @param config + * a configuration that controls the formatting or + * null for the minimal form + * @throws IOException + * if an I/O error occurs in the writer + */ + public void writeTo(Writer writer, WriterConfig config) throws IOException { + if (writer == null) { + throw new NullPointerException("writer is null"); + } + if (config == null) { + throw new NullPointerException("config is null"); + } + WritingBuffer buffer = new WritingBuffer(writer, 128); + write(config.createWriter(buffer)); + buffer.flush(); + } + + /** + * Returns the JSON string for this value in its minimal form, without any + * additional whitespace. The result is guaranteed to be a valid input for + * the method {@link #readFrom(String)} and to create a value that is + * equal to this object. + * + * @return a JSON string that represents this value + */ + @Override + public String toString() { + return toString(WriterConfig.MINIMAL); + } + + /** + * Returns the JSON string for this value using the given formatting. + * + * @param config + * a configuration that controls the formatting or + * null for the minimal form + * @return a JSON string that represents this value + */ + public String toString(WriterConfig config) { + StringWriter writer = new StringWriter(); + try { + writeTo(writer, config); + } catch (IOException exception) { + // StringWriter does not throw IOExceptions + throw new RuntimeException(exception); + } + return writer.toString(); + } + + /** + * Indicates whether some other object is "equal to" this one according to + * the contract specified in {@link Object#equals(Object)}. + *

+ * Two JsonValues are considered equal if and only if they represent the + * same JSON text. As a consequence, two given JsonObjects may be different + * even though they contain the same set of names with the same values, but + * in a different order. + *

+ * + * @param object + * the reference object with which to compare + * @return true if this object is the same as the object argument; false + * otherwise + */ + @Override + public boolean equals(Object object) { + return super.equals(object); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + abstract void write(JSONWriter writer) throws IOException; + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONWriter.java b/blade-kit/src/main/java/blade/kit/json/JSONWriter.java index f628bdf52..2e2b53e49 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONWriter.java +++ b/blade-kit/src/main/java/blade/kit/json/JSONWriter.java @@ -1,145 +1,145 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; - - -class JSONWriter { - - private static final int CONTROL_CHARACTERS_END = 0x001f; - - private static final char[] QUOT_CHARS = {'\\', '"'}; - private static final char[] BS_CHARS = {'\\', '\\'}; - private static final char[] LF_CHARS = {'\\', 'n'}; - private static final char[] CR_CHARS = {'\\', 'r'}; - private static final char[] TAB_CHARS = {'\\', 't'}; - // In JavaScript, U+2028 and U+2029 characters count as line endings and must be encoded. - // http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character - private static final char[] UNICODE_2028_CHARS = {'\\', 'u', '2', '0', '2', '8'}; - private static final char[] UNICODE_2029_CHARS = {'\\', 'u', '2', '0', '2', '9'}; - private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f'}; - - protected final Writer writer; - - JSONWriter(Writer writer) { - this.writer = writer; - } - - protected void writeLiteral(String value) throws IOException { - writer.write(value); - } - - protected void writeNumber(String string) throws IOException { - writer.write(string); - } - - protected void writeString(String string) throws IOException { - writer.write('"'); - writeJsonString(string); - writer.write('"'); - } - - protected void writeArrayOpen() throws IOException { - writer.write('['); - } - - protected void writeArrayClose() throws IOException { - writer.write(']'); - } - - protected void writeArraySeparator() throws IOException { - writer.write(','); - } - - protected void writeObjectOpen() throws IOException { - writer.write('{'); - } - - protected void writeObjectClose() throws IOException { - writer.write('}'); - } - - protected void writeMemberName(String name) throws IOException { - writer.write('"'); - writeJsonString(name); - writer.write('"'); - } - - protected void writeMemberSeparator() throws IOException { - writer.write(':'); - } - - protected void writeObjectSeparator() throws IOException { - writer.write(','); - } - - protected void writeJsonString(String string) throws IOException { - int length = string.length(); - int start = 0; - for (int index = 0; index < length; index++) { - char[] replacement = getReplacementChars(string.charAt(index)); - if (replacement != null) { - writer.write(string, start, index - start); - writer.write(replacement); - start = index + 1; - } - } - writer.write(string, start, length - start); - } - - private static char[] getReplacementChars(char ch) { - if (ch > '\\') { - if (ch < '\u2028' || ch > '\u2029') { - // The lower range contains 'a' .. 'z'. Only 2 checks required. - return null; - } - return ch == '\u2028' ? UNICODE_2028_CHARS : UNICODE_2029_CHARS; - } - if (ch == '\\') { - return BS_CHARS; - } - if (ch > '"') { - // This range contains '0' .. '9' and 'A' .. 'Z'. Need 3 checks to get here. - return null; - } - if (ch == '"') { - return QUOT_CHARS; - } - if (ch > CONTROL_CHARACTERS_END) { - return null; - } - if (ch == '\n') { - return LF_CHARS; - } - if (ch == '\r') { - return CR_CHARS; - } - if (ch == '\t') { - return TAB_CHARS; - } - return new char[] {'\\', 'u', '0', '0', HEX_DIGITS[ch >> 4 & 0x000f], HEX_DIGITS[ch & 0x000f]}; - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; + + +class JSONWriter { + + private static final int CONTROL_CHARACTERS_END = 0x001f; + + private static final char[] QUOT_CHARS = {'\\', '"'}; + private static final char[] BS_CHARS = {'\\', '\\'}; + private static final char[] LF_CHARS = {'\\', 'n'}; + private static final char[] CR_CHARS = {'\\', 'r'}; + private static final char[] TAB_CHARS = {'\\', 't'}; + // In JavaScript, U+2028 and U+2029 characters count as line endings and must be encoded. + // http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character + private static final char[] UNICODE_2028_CHARS = {'\\', 'u', '2', '0', '2', '8'}; + private static final char[] UNICODE_2029_CHARS = {'\\', 'u', '2', '0', '2', '9'}; + private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; + + protected final Writer writer; + + JSONWriter(Writer writer) { + this.writer = writer; + } + + protected void writeLiteral(String value) throws IOException { + writer.write(value); + } + + protected void writeNumber(String string) throws IOException { + writer.write(string); + } + + protected void writeString(String string) throws IOException { + writer.write('"'); + writeJsonString(string); + writer.write('"'); + } + + protected void writeArrayOpen() throws IOException { + writer.write('['); + } + + protected void writeArrayClose() throws IOException { + writer.write(']'); + } + + protected void writeArraySeparator() throws IOException { + writer.write(','); + } + + protected void writeObjectOpen() throws IOException { + writer.write('{'); + } + + protected void writeObjectClose() throws IOException { + writer.write('}'); + } + + protected void writeMemberName(String name) throws IOException { + writer.write('"'); + writeJsonString(name); + writer.write('"'); + } + + protected void writeMemberSeparator() throws IOException { + writer.write(':'); + } + + protected void writeObjectSeparator() throws IOException { + writer.write(','); + } + + protected void writeJsonString(String string) throws IOException { + int length = string.length(); + int start = 0; + for (int index = 0; index < length; index++) { + char[] replacement = getReplacementChars(string.charAt(index)); + if (replacement != null) { + writer.write(string, start, index - start); + writer.write(replacement); + start = index + 1; + } + } + writer.write(string, start, length - start); + } + + private static char[] getReplacementChars(char ch) { + if (ch > '\\') { + if (ch < '\u2028' || ch > '\u2029') { + // The lower range contains 'a' .. 'z'. Only 2 checks required. + return null; + } + return ch == '\u2028' ? UNICODE_2028_CHARS : UNICODE_2029_CHARS; + } + if (ch == '\\') { + return BS_CHARS; + } + if (ch > '"') { + // This range contains '0' .. '9' and 'A' .. 'Z'. Need 3 checks to get here. + return null; + } + if (ch == '"') { + return QUOT_CHARS; + } + if (ch > CONTROL_CHARACTERS_END) { + return null; + } + if (ch == '\n') { + return LF_CHARS; + } + if (ch == '\r') { + return CR_CHARS; + } + if (ch == '\t') { + return TAB_CHARS; + } + return new char[] {'\\', 'u', '0', '0', HEX_DIGITS[ch >> 4 & 0x000f], HEX_DIGITS[ch & 0x000f]}; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/Location.java b/blade-kit/src/main/java/blade/kit/json/Location.java new file mode 100644 index 000000000..fb2cb62f6 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/json/Location.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + + +/** + * An immutable object that represents a location in the parsed text. + */ +public class Location { + + /** + * The absolute character index, starting at 0. + */ + public final int offset; + + /** + * The line number, starting at 1. + */ + public final int line; + + /** + * The column number, starting at 1. + */ + public final int column; + + Location(int offset, int line, int column) { + this.offset = offset; + this.column = column; + this.line = line; + } + + @Override + public String toString() { + return line + ":" + column; + } + + @Override + public int hashCode() { + return offset; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Location other = (Location)obj; + return offset == other.offset && column == other.column && line == other.line; + } + +} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/ParseException.java b/blade-kit/src/main/java/blade/kit/json/ParseException.java index 623eb6d50..045d686c6 100644 --- a/blade-kit/src/main/java/blade/kit/json/ParseException.java +++ b/blade-kit/src/main/java/blade/kit/json/ParseException.java @@ -1,70 +1,81 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -/** - * An unchecked exception to indicate that an input does not qualify as valid JSON. - */ -@SuppressWarnings("serial") // use default serial UID -public class ParseException extends RuntimeException { - - private final int offset; - private final int line; - private final int column; - - ParseException(String message, int offset, int line, int column) { - super(message + " at " + line + ":" + column); - this.offset = offset; - this.line = line; - this.column = column; - } - - /** - * Returns the absolute index of the character at which the error occurred. The index of the first - * character of a document is 0. - * - * @return the character offset at which the error occurred, will be >= 0 - */ - public int getOffset() { - return offset; - } - - /** - * Returns the number of the line in which the error occurred. The first line counts as 1. - * - * @return the line in which the error occurred, will be >= 1 - */ - public int getLine() { - return line; - } - - /** - * Returns the index of the character at which the error occurred, relative to the line. The index - * of the first character of a line is 0. - * - * @return the column in which the error occurred, will be >= 0 - */ - public int getColumn() { - return column; - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +/** + * An unchecked exception to indicate that an input does not qualify as valid JSON. + */ +@SuppressWarnings("serial") // use default serial UID +public class ParseException extends RuntimeException { + + private final Location location; + + ParseException(String message, Location location) { + super(message + " at " + location); + this.location = location; + } + + /** + * Returns the location at which the error occurred. + * + * @return the error location + */ + public Location getLocation() { + return location; + } + + /** + * Returns the absolute character index at which the error occurred. The offset of the first + * character of a document is 0. + * + * @return the character offset at which the error occurred, will be >= 0 + * @deprecated Use {@link #getLocation()} instead + */ + @Deprecated + public int getOffset() { + return location.offset; + } + + /** + * Returns the line number in which the error occurred. The number of the first line is 1. + * + * @return the line in which the error occurred, will be >= 1 + * @deprecated Use {@link #getLocation()} instead + */ + @Deprecated + public int getLine() { + return location.line; + } + + /** + * Returns the column number at which the error occurred, i.e. the number of the character in its + * line. The number of the first character of a line is 1. + * + * @return the column in which the error occurred, will be >= 1 + * @deprecated Use {@link #getLocation()} instead + */ + @Deprecated + public int getColumn() { + return location.column; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java b/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java index c78cb0475..a14a10328 100644 --- a/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java +++ b/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java @@ -1,157 +1,157 @@ -/******************************************************************************* - * Copyright (c) 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; -import java.util.Arrays; - - -/** - * Enables human readable JSON output by inserting whitespace between values.after commas and - * colons. Example: - * - *
- * jsonValue.writeTo(writer, PrettyPrint.singleLine());
- * 
- */ -public class PrettyPrint extends WriterConfig { - - private final char[] indentChars; - - protected PrettyPrint(char[] indentChars) { - this.indentChars = indentChars; - } - - /** - * Print every value on a separate line. Use tabs (\t) for indentation. - * - * @return A PrettyPrint instance for wrapped mode with tab indentation - */ - public static PrettyPrint singleLine() { - return new PrettyPrint(null); - } - - /** - * Print every value on a separate line. Use the given number of spaces for indentation. - * - * @param number - * the number of spaces to use - * @return A PrettyPrint instance for wrapped mode with spaces indentation - */ - public static PrettyPrint indentWithSpaces(int number) { - if (number < 0) { - throw new IllegalArgumentException("number is negative"); - } - char[] chars = new char[number]; - Arrays.fill(chars, ' '); - return new PrettyPrint(chars); - } - - /** - * Do not break lines, but still insert whitespace between values. - * - * @return A PrettyPrint instance for single-line mode - */ - public static PrettyPrint indentWithTabs() { - return new PrettyPrint(new char[] {'\t'}); - } - - @Override - protected JSONWriter createWriter(Writer writer) { - return new PrettyPrintWriter(writer, indentChars); - } - - private static class PrettyPrintWriter extends JSONWriter { - - private final char[] indentChars; - private int indent; - - private PrettyPrintWriter(Writer writer, char[] indentChars) { - super(writer); - this.indentChars = indentChars; - } - - @Override - protected void writeArrayOpen() throws IOException { - indent++; - writer.write('['); - writeNewLine(); - } - - @Override - protected void writeArrayClose() throws IOException { - indent--; - writeNewLine(); - writer.write(']'); - } - - @Override - protected void writeArraySeparator() throws IOException { - writer.write(','); - if (!writeNewLine()) { - writer.write(' '); - } - } - - @Override - protected void writeObjectOpen() throws IOException { - indent++; - writer.write('{'); - writeNewLine(); - } - - @Override - protected void writeObjectClose() throws IOException { - indent--; - writeNewLine(); - writer.write('}'); - } - - @Override - protected void writeMemberSeparator() throws IOException { - writer.write(':'); - writer.write(' '); - } - - @Override - protected void writeObjectSeparator() throws IOException { - writer.write(','); - if (!writeNewLine()) { - writer.write(' '); - } - } - - private boolean writeNewLine() throws IOException { - if (indentChars == null) { - return false; - } - writer.write('\n'); - for (int i = 0; i < indent; i++) { - writer.write(indentChars); - } - return true; - } - - } - -} +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; +import java.util.Arrays; + + +/** + * Enables human readable JSON output by inserting whitespace between values.after commas and + * colons. Example: + * + *
+ * jsonValue.writeTo(writer, PrettyPrint.singleLine());
+ * 
+ */ +public class PrettyPrint extends WriterConfig { + + private final char[] indentChars; + + protected PrettyPrint(char[] indentChars) { + this.indentChars = indentChars; + } + + /** + * Print every value on a separate line. Use tabs (\t) for indentation. + * + * @return A PrettyPrint instance for wrapped mode with tab indentation + */ + public static PrettyPrint singleLine() { + return new PrettyPrint(null); + } + + /** + * Print every value on a separate line. Use the given number of spaces for indentation. + * + * @param number + * the number of spaces to use + * @return A PrettyPrint instance for wrapped mode with spaces indentation + */ + public static PrettyPrint indentWithSpaces(int number) { + if (number < 0) { + throw new IllegalArgumentException("number is negative"); + } + char[] chars = new char[number]; + Arrays.fill(chars, ' '); + return new PrettyPrint(chars); + } + + /** + * Do not break lines, but still insert whitespace between values. + * + * @return A PrettyPrint instance for single-line mode + */ + public static PrettyPrint indentWithTabs() { + return new PrettyPrint(new char[] {'\t'}); + } + + @Override + protected JSONWriter createWriter(Writer writer) { + return new PrettyPrintWriter(writer, indentChars); + } + + private static class PrettyPrintWriter extends JSONWriter { + + private final char[] indentChars; + private int indent; + + private PrettyPrintWriter(Writer writer, char[] indentChars) { + super(writer); + this.indentChars = indentChars; + } + + @Override + protected void writeArrayOpen() throws IOException { + indent++; + writer.write('['); + writeNewLine(); + } + + @Override + protected void writeArrayClose() throws IOException { + indent--; + writeNewLine(); + writer.write(']'); + } + + @Override + protected void writeArraySeparator() throws IOException { + writer.write(','); + if (!writeNewLine()) { + writer.write(' '); + } + } + + @Override + protected void writeObjectOpen() throws IOException { + indent++; + writer.write('{'); + writeNewLine(); + } + + @Override + protected void writeObjectClose() throws IOException { + indent--; + writeNewLine(); + writer.write('}'); + } + + @Override + protected void writeMemberSeparator() throws IOException { + writer.write(':'); + writer.write(' '); + } + + @Override + protected void writeObjectSeparator() throws IOException { + writer.write(','); + if (!writeNewLine()) { + writer.write(' '); + } + } + + private boolean writeNewLine() throws IOException { + if (indentChars == null) { + return false; + } + writer.write('\n'); + for (int i = 0; i < indent; i++) { + writer.write(indentChars); + } + return true; + } + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/WriterConfig.java b/blade-kit/src/main/java/blade/kit/json/WriterConfig.java index 59869517b..6573c80d2 100644 --- a/blade-kit/src/main/java/blade/kit/json/WriterConfig.java +++ b/blade-kit/src/main/java/blade/kit/json/WriterConfig.java @@ -1,50 +1,50 @@ -/******************************************************************************* - * Copyright (c) 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.Writer; - - -/** - * Controls the formatting of the JSON output. Use one of the available constants. - */ -public abstract class WriterConfig { - - /** - * Write JSON in its minimal form, without any additional whitespace. This is the default. - */ - public static WriterConfig MINIMAL = new WriterConfig() { - @Override - JSONWriter createWriter(Writer writer) { - return new JSONWriter(writer); - } - }; - - /** - * Write JSON in pretty-print, with each value on a separate line and an indentation of two - * spaces. - */ - public static WriterConfig PRETTY_PRINT = PrettyPrint.indentWithSpaces(2); - - abstract JSONWriter createWriter(Writer writer); - -} +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.Writer; + + +/** + * Controls the formatting of the JSON output. Use one of the available constants. + */ +public abstract class WriterConfig { + + /** + * Write JSON in its minimal form, without any additional whitespace. This is the default. + */ + public static WriterConfig MINIMAL = new WriterConfig() { + @Override + JSONWriter createWriter(Writer writer) { + return new JSONWriter(writer); + } + }; + + /** + * Write JSON in pretty-print, with each value on a separate line and an indentation of two + * spaces. + */ + public static WriterConfig PRETTY_PRINT = PrettyPrint.indentWithSpaces(2); + + abstract JSONWriter createWriter(Writer writer); + +} diff --git a/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java b/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java index a6bba01ee..58a779b0c 100644 --- a/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java +++ b/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java @@ -1,99 +1,99 @@ -/******************************************************************************* - * Copyright (c) 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; - - -/** - * A lightweight writing buffer to reduce the amount of write operations to be performed on the - * underlying writer. This implementation is not thread-safe. It deliberately deviates from the - * contract of Writer. In particular, it does not flush or close the wrapped writer nor does it - * ensure that the wrapped writer is open. - */ -class WritingBuffer extends Writer { - - private final Writer writer; - private final char[] buffer; - private int fill = 0; - - WritingBuffer(Writer writer) { - this(writer, 16); - } - - WritingBuffer(Writer writer, int bufferSize) { - this.writer = writer; - buffer = new char[bufferSize]; - } - - @Override - public void write(int c) throws IOException { - if (fill > buffer.length - 1) { - flush(); - } - buffer[fill++] = (char)c; - } - - @Override - public void write(char[] cbuf, int off, int len) throws IOException { - if (fill > buffer.length - len) { - flush(); - if (len > buffer.length) { - writer.write(cbuf, off, len); - return; - } - } - System.arraycopy(cbuf, off, buffer, fill, len); - fill += len; - } - - @Override - public void write(String str, int off, int len) throws IOException { - if (fill > buffer.length - len) { - flush(); - if (len > buffer.length) { - writer.write(str, off, len); - return; - } - } - str.getChars(off, off + len, buffer, fill); - fill += len; - } - - /** - * Flushes the internal buffer but does not flush the wrapped writer. - */ - @Override - public void flush() throws IOException { - writer.write(buffer, 0, fill); - fill = 0; - } - - /** - * Does not close or flush the wrapped writer. - */ - @Override - public void close() throws IOException { - } - -} +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package blade.kit.json; + +import java.io.IOException; +import java.io.Writer; + + +/** + * A lightweight writing buffer to reduce the amount of write operations to be performed on the + * underlying writer. This implementation is not thread-safe. It deliberately deviates from the + * contract of Writer. In particular, it does not flush or close the wrapped writer nor does it + * ensure that the wrapped writer is open. + */ +class WritingBuffer extends Writer { + + private final Writer writer; + private final char[] buffer; + private int fill = 0; + + WritingBuffer(Writer writer) { + this(writer, 16); + } + + WritingBuffer(Writer writer, int bufferSize) { + this.writer = writer; + buffer = new char[bufferSize]; + } + + @Override + public void write(int c) throws IOException { + if (fill > buffer.length - 1) { + flush(); + } + buffer[fill++] = (char)c; + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + if (fill > buffer.length - len) { + flush(); + if (len > buffer.length) { + writer.write(cbuf, off, len); + return; + } + } + System.arraycopy(cbuf, off, buffer, fill, len); + fill += len; + } + + @Override + public void write(String str, int off, int len) throws IOException { + if (fill > buffer.length - len) { + flush(); + if (len > buffer.length) { + writer.write(str, off, len); + return; + } + } + str.getChars(off, off + len, buffer, fill); + fill += len; + } + + /** + * Flushes the internal buffer but does not flush the wrapped writer. + */ + @Override + public void flush() throws IOException { + writer.write(buffer, 0, fill); + fill = 0; + } + + /** + * Does not close or flush the wrapped writer. + */ + @Override + public void close() throws IOException { + } + +} diff --git a/blade-kit/src/test/java/com/blade/kit/JSONTest.java b/blade-kit/src/test/java/com/blade/kit/JSONTest.java index 464a8db5c..84972fdd8 100644 --- a/blade-kit/src/test/java/com/blade/kit/JSONTest.java +++ b/blade-kit/src/test/java/com/blade/kit/JSONTest.java @@ -1,58 +1,59 @@ -package com.blade.kit; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import blade.kit.json.JSONArray; -import blade.kit.json.JSONKit; -import blade.kit.json.JSONObject; -import blade.kit.json.JSONValue; - -public class JSONTest { - - public static void main(String[] args) { - //[{"text": "首页","href": "/"},{"text": "博客","href": "blog"},{"text": "关于","href": "about"},{"text": "联系","href": "contact"}] - String json = "[{\"text\": \"博客\",\"href\": \"blog\"}]"; - - // 下面构造两个map、一个list和一个Employee对象 - Map map1 = new HashMap(); - map1.put("name", "Alexia"); - map1.put("sex", "female"); - map1.put("age", "23"); - - List> list = new ArrayList>(); - Map map = new HashMap(); - - map.put("abc", "123456"); - map.put("def", "hmm"); - list.add(map); - - String string = JSONKit.toJSONString(list); - System.out.println(string); - - List list2 = JSONKit.parse(json).asArray().values(); - System.out.println(list2); - - JSONObject obj1 = new JSONObject(); - obj1.put("name", "jack"); - - System.out.println(obj1); - - JSONArray obj2 = new JSONArray(); - obj2.add("123"); - - System.out.println(obj2); - - User u1 = new User(); - u1.setAge(22); - u1.setName("rose"); - - System.out.println(JSONKit.toJSONString(u1)); - -// User u = JSONKit.parse("{\"name\":\"jack\",\"age\":20}", User.class); -// System.out.println(u); - } - -} +package com.blade.kit; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import blade.kit.json.JSON; +import blade.kit.json.JSONArray; +import blade.kit.json.JSONHelper; +import blade.kit.json.JSONKit; +import blade.kit.json.JSONObject; +import blade.kit.json.JSONValue; + +public class JSONTest { + + public static void main(String[] args) { + //[{"text": "首页","href": "/"},{"text": "博客","href": "blog"},{"text": "关于","href": "about"},{"text": "联系","href": "contact"}] + String json = "[{\"text\": \"博客\",\"href\": \"blog\"}]"; + + // 下面构造两个map、一个list和一个Employee对象 + Map map1 = new HashMap(); + map1.put("name", "Alexia"); + map1.put("sex", "female"); + map1.put("age", "23"); + + List> list = new ArrayList>(); + Map map = new HashMap(); + + map.put("abc", "123456"); + map.put("def", "hmm"); + list.add(map); + + String string = JSONKit.toJSONString(list); + System.out.println(string); + + List list2 = JSON.parse(json).asArray().values(); + System.out.println(list2); + + JSONObject obj1 = new JSONObject(); + obj1.put("name", "jack"); + + System.out.println(obj1); + + JSONArray obj2 = new JSONArray(); + obj2.add("123"); + + System.out.println(obj2); + + User u1 = new User(); + u1.setAge(22); +// u1.setName("rose"); + + System.out.println(JSONHelper.toJSONValue(u1).toString()); + +// System.out.println(JSONKit.toJSONString(u1)); + } + +} diff --git a/blade-kit/src/test/java/com/blade/kit/User.java b/blade-kit/src/test/java/com/blade/kit/User.java index d2ce61c2b..7dfc118d4 100644 --- a/blade-kit/src/test/java/com/blade/kit/User.java +++ b/blade-kit/src/test/java/com/blade/kit/User.java @@ -1,32 +1,28 @@ -package com.blade.kit; - -public class User { - - private String name; - private long age; - - public User() { - // TODO Auto-generated constructor stub - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public long getAge() { - return age; - } - - public void setAge(long age) { - this.age = age; - } - - @Override - public String toString() { - return "User [name=" + name + ", age=" + age + "]"; - } +package com.blade.kit; + +public class User { + + private String name; + private long age; + + public User() { + // TODO Auto-generated constructor stub + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getAge() { + return age; + } + + public void setAge(long age) { + this.age = age; + } + } \ No newline at end of file From 452ddc176fd0f54718ef68db0c91bca401e614ab Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 11 Apr 2016 18:49:27 +0800 Subject: [PATCH 452/545] update readme --- LAST_VERSION.md | 184 +++++++++---------- README.md | 438 ++++++++++++++++++++++---------------------- README_CN.md | 440 ++++++++++++++++++++++----------------------- blade-core/pom.xml | 2 +- blade-kit/pom.xml | 116 ++++++------ pom.xml | 2 +- 6 files changed, 591 insertions(+), 591 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index a8c7a5753..94c988a0e 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -1,92 +1,92 @@ -# blade last version - -如果在maven仓库中下载不到最新版本的依赖,请添加maven snapshots仓库 - -```xml - - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - -``` -和`dependencies`相同级别 - - -## [blade-kit](http://search.maven.org/#search%7Cga%7C1%7Cblade-kit) -```xml - -    com.bladejava -    blade-kit -    1.2.9-beta - -``` - -## [blade-core](http://search.maven.org/#search%7Cga%7C1%7Cblade-core) -```xml - -    com.bladejava -    blade-core -    1.6.0 - -``` - -## [blade-jdbc](http://search.maven.org/#search%7Cga%7C1%7Cblade-jdbc) -```xml - -    com.bladejava -    blade-jdbc -    0.0.2 - -``` - -## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache) -```xml - -    com.bladejava -    blade-cache -    1.2.3 - -``` - -## [blade-redis](http://search.maven.org/#search%7Cga%7C1%7Cblade-redis) -```xml - -    com.bladejava -    blade-redis -    1.2.3 - -``` - -## [blade-startup](http://search.maven.org/#search%7Cga%7C1%7Cblade-startup) -```xml - -    com.bladejava -    blade-startup -    1.0.1 - -``` - -## [blade-patchca](http://search.maven.org/#search%7Cga%7C1%7Cblade-patchca) -```xml - -    com.bladejava -    blade-patchca -    1.0.2 - -``` - -## [blade-oauth2](http://search.maven.org/#search%7Cga%7C1%7Cblade-oauth2) -```xml - -    com.bladejava -    blade-oauth2 -    1.0.2 - -``` +# blade last version + +如果在maven仓库中下载不到最新版本的依赖,请添加maven snapshots仓库 + +```xml + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + +``` +和`dependencies`相同级别 + + +## [blade-kit](http://search.maven.org/#search%7Cga%7C1%7Cblade-kit) +```xml + +    com.bladejava +    blade-kit +    1.3.0M1 + +``` + +## [blade-core](http://search.maven.org/#search%7Cga%7C1%7Cblade-core) +```xml + +    com.bladejava +    blade-core +    1.6.1M2 + +``` + +## [blade-jdbc](http://search.maven.org/#search%7Cga%7C1%7Cblade-jdbc) +```xml + +    com.bladejava +    blade-jdbc +    0.0.7 + +``` + +## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache) +```xml + +    com.bladejava +    blade-cache +    1.2.3 + +``` + +## [blade-redis](http://search.maven.org/#search%7Cga%7C1%7Cblade-redis) +```xml + +    com.bladejava +    blade-redis +    1.2.3 + +``` + +## [blade-startup](http://search.maven.org/#search%7Cga%7C1%7Cblade-startup) +```xml + +    com.bladejava +    blade-startup +    1.0.1 + +``` + +## [blade-patchca](http://search.maven.org/#search%7Cga%7C1%7Cblade-patchca) +```xml + +    com.bladejava +    blade-patchca +    1.0.2 + +``` + +## [blade-oauth2](http://search.maven.org/#search%7Cga%7C1%7Cblade-oauth2) +```xml + +    com.bladejava +    blade-oauth2 +    1.0.2 + +``` diff --git a/README.md b/README.md index 7611e27da..1c9c418fe 100644 --- a/README.md +++ b/README.md @@ -1,219 +1,219 @@ - -[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) - -[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - -[中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) - -## What Is Blade? - -Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. -If you like it, please [star and fork it](https://github.com/biezhi/blade). Thank you! - -## Features - -* [x] Lightweight: the code is simple and the structure is clear -* [x] Modular (you can choose which components to use) -* [x] Supports plug-in extension mechanism -* [x] RESTful style routing interface -* [x] Supports multiple configuration files (currently properties, json and coding) -* [x] Embedded jetty server and template engine support -* [x] Supports JDK 1.6 and up - -## Overview - -* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. -* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. - -## Get Start - -To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : - -Grab via `Maven`: - -```xml - - com.bladejava - blade-core - 1.6.1M1 - - - com.bladejava - blade-startup - 1.0.1 - -``` -or `Gradle`: -```sh -compile 'com.bladejava:blade-core:1.6.1M1' -compile 'com.bladejava:blade-startup:1.0.1' -``` - -Create `Main` method like this: - -```java -public class App { - - public static void main(String[] args) { - Blade blade = me(); - blade.get("/", (request, response) -> { - response.html("

Hello blade!

"); - }); - blade.listen(9001).start(); - } -} -``` - -Run it and point your browser to [http://localhost:9001](http://localhost:9001). There you go, you've just created your first Blade app! - -## API Example - -```java -public static void main(String[] args) { - Blade blade = me(); - blade.get("/user/21", getxxx); - blade.post("/save", postxxx); - blade.delete("/del/21", deletexxx); - blade.put("/put", putxxx); - blade.listen(9001).start(); -} -``` - -## REST URL Parameters - -```java -public static void main(String[] args) { - Blade blade = me(); - blade.get("/user/:uid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - response.text("uid : " + uid); - }); - - blade.get("/users/:uid/post/:pid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - Integer pid = request.paramAsInt("pid"); - String msg = "uid = " + uid + ", pid = " + pid; - response.text(msg); - }); - - blade.listen(9001).start(); -} -``` - -## Form URL Parameters - -```java -public static void main(String[] args) { - Blade blade = me(); - blade.get("/user", (request, response) -> { - Integer uid = request.queryAsInt("uid"); - response.text("uid : " + uid); - }); - blade.listen(9001).start(); -} -``` - -## Upload File - -```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; - File file = fileItem.getFile(); - - String fileRealPath = "your upload file path!"; - - nioTransferCopy(file, fileRealPath); - } -} -``` - -## Route Config File - -`route.conf` - -```sh -GET / IndexRoute.home -GET /signin IndexRoute.show_signin -POST /signin IndexRoute.signin -GET /signout IndexRoute.signout -POST /upload_img UploadRoute.upload_img -``` - -## Route Intercept - -```java -public static void main(String[] args) { - Blade blade = me(); - blade.before("/.*", (request, response) -> { - System.out.println("before..."); - }); - blade.listen(9001).start(); -} -``` - -## DSL DB Operation - -```java -// query -List posts = - AR.find("where title like ? order by id desc limit ?,?", title, page, count).list(Post.class); - -// save -String insertSql = "insert into t_post (title, content, view_count, create_time) values (?,?,?,?)"; -AR.update(insertSql, title, content, 0, new Date()).commit(); - -// update -AR.update("update t_post set title = ? and content = ? where id = ?",title, content, id).commit(); - -// delete -AR.update("delete from t_post where id = ?",id).commit() -``` - -You may refer to these examples for additional guidance: - -+ [Hello Blade](https://github.com/blade-samples/hello) -+ [Blog Example](https://github.com/blade-samples/blog) -+ [API Doc](http://bladejava.com/apidocs) -+ [User Guide](http://bladejava.com/docs) -+ [Version Changes](LAST_VERSION.md) -+ [Examples](https://github.com/blade-samples) - -## Plan - -- 1. Add the test code -- 2. Optimize the code base -- 3. Optimization of concurrent ability - -## Update - -[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## Contact - -- Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me@gmail.com - -## Contributor - -Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! - -- [mfarid](https://github.com/mfarid) -- [daimajia](https://github.com/daimajia) -- [shenjie1993](https://github.com/shenjie1993) -- [sumory](https://github.com/sumory) -- [udaykadaboina](https://github.com/udaykadaboina) -- [SyedWasiHaider](https://github.com/SyedWasiHaider) -- [Awakens](https://github.com/Awakens) -- [shellac](https://github.com/shellac) -- [SudarAbisheck](https://github.com/SudarAbisheck) - -## Licenses - -Please see [Apache License](LICENSE) + +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) + +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + +[中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) + +## What Is Blade? + +Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. +If you like it, please [star and fork it](https://github.com/biezhi/blade). Thank you! + +## Features + +* [x] Lightweight: the code is simple and the structure is clear +* [x] Modular (you can choose which components to use) +* [x] Supports plug-in extension mechanism +* [x] RESTful style routing interface +* [x] Supports multiple configuration files (currently properties, json and coding) +* [x] Embedded jetty server and template engine support +* [x] Supports JDK 1.6 and up + +## Overview + +* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. +* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. + +## Get Start + +To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : + +Grab via `Maven`: + +```xml + + com.bladejava + blade-core + 1.6.1M2 + + + com.bladejava + blade-startup + 1.0.1 + +``` +or `Gradle`: +```sh +compile 'com.bladejava:blade-core:1.6.1M2' +compile 'com.bladejava:blade-startup:1.0.1' +``` + +Create `Main` method like this: + +```java +public class App { + + public static void main(String[] args) { + Blade blade = me(); + blade.get("/", (request, response) -> { + response.html("

Hello blade!

"); + }); + blade.listen(9001).start(); + } +} +``` + +Run it and point your browser to [http://localhost:9001](http://localhost:9001). There you go, you've just created your first Blade app! + +## API Example + +```java +public static void main(String[] args) { + Blade blade = me(); + blade.get("/user/21", getxxx); + blade.post("/save", postxxx); + blade.delete("/del/21", deletexxx); + blade.put("/put", putxxx); + blade.listen(9001).start(); +} +``` + +## REST URL Parameters + +```java +public static void main(String[] args) { + Blade blade = me(); + blade.get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + blade.get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + blade.listen(9001).start(); +} +``` + +## Form URL Parameters + +```java +public static void main(String[] args) { + Blade blade = me(); + blade.get("/user", (request, response) -> { + Integer uid = request.queryAsInt("uid"); + response.text("uid : " + uid); + }); + blade.listen(9001).start(); +} +``` + +## Upload File + +```java +public void upload_img(Request request, Response response){ + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## Route Config File + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## Route Intercept + +```java +public static void main(String[] args) { + Blade blade = me(); + blade.before("/.*", (request, response) -> { + System.out.println("before..."); + }); + blade.listen(9001).start(); +} +``` + +## DSL DB Operation + +```java +// query +List posts = + AR.find("where title like ? order by id desc limit ?,?", title, page, count).list(Post.class); + +// save +String insertSql = "insert into t_post (title, content, view_count, create_time) values (?,?,?,?)"; +AR.update(insertSql, title, content, 0, new Date()).commit(); + +// update +AR.update("update t_post set title = ? and content = ? where id = ?",title, content, id).commit(); + +// delete +AR.update("delete from t_post where id = ?",id).commit() +``` + +You may refer to these examples for additional guidance: + ++ [Hello Blade](https://github.com/blade-samples/hello) ++ [Blog Example](https://github.com/blade-samples/blog) ++ [API Doc](http://bladejava.com/apidocs) ++ [User Guide](http://bladejava.com/docs) ++ [Version Changes](LAST_VERSION.md) ++ [Examples](https://github.com/blade-samples) + +## Plan + +- 1. Add the test code +- 2. Optimize the code base +- 3. Optimization of concurrent ability + +## Update + +[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## Contact + +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me@gmail.com + +## Contributor + +Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! + +- [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) + +## Licenses + +Please see [Apache License](LICENSE) diff --git a/README_CN.md b/README_CN.md index 59413ee2c..b7ba69f7d 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,220 +1,220 @@ - -[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) - -[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) - -[English](https://github.com/biezhi/blade/blob/master/README.md) - -## Blade是什么? - -Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计。 -如果你喜欢,欢迎 [Star and Fork](https://github.com/biezhi/blade), 谢谢! - -## 特性 - -* [x] 轻量级。代码简洁,结构清晰,更容易开发 -* [x] 模块化(你可以选择使用哪些组件) -* [x] 插件扩展机制 -* [x] Restful风格的路由接口 -* [x] 多种配置文件支持(当前支持properties、json和硬编码) -* [x] 内置Jetty服务,模板引擎支持 -* [x] 支持JDK1.6或者更高版本 - -## 概述 - -* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 -* 优雅的:`blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 - -## 快速入门 - -开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : - -`Maven` 配置: - -```xml - - com.bladejava - blade-core - 1.6.1M1 - - - com.bladejava - blade-startup - 1.0.1 - -``` - -或者 `Gradle`: - -```sh -compile 'com.bladejava:blade-core:1.6.0' -compile 'com.bladejava:blade-startup:1.0.1' -``` - -编写 `Main`函数: - -```java -public static void main(String[] args) { - Blade blade = me(); - blade.get("/", (request, response) -> { - response.html("

Hello blade!

"); - }); - blade.listen(9001).start(); -} -``` - -用浏览器打开 http://localhost:9001 这样就可以看到第一个Blade应用了! - -## API示例 - -```java -public static void main(String[] args) { - Blade blade = me(); - blade.get("/user/21", getxxx); - blade.post("/save", postxxx); - blade.delete("/del/21", deletexxx); - blade.put("/put", putxxx); - blade.listen(9001).start(); -} -``` - -## REST URL参数获取 - -```java -public static void main(String[] args) { - Blade blade = me(); - blade.get("/user/:uid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - response.text("uid : " + uid); - }); - - blade.get("/users/:uid/post/:pid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - Integer pid = request.paramAsInt("pid"); - String msg = "uid = " + uid + ", pid = " + pid; - response.text(msg); - }); - - blade.listen(9001).start(); -} -``` - -## 表单参数获取 - -```java -public static void main(String[] args) { - Blade blade = me(); - blade.get("/user", (request, response) -> { - Integer uid = request.queryAsInt("uid"); - response.text("uid : " + uid); - }); - blade.listen(9001).start(); -} -``` - -## 上传文件 - -```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; - File file = fileItem.getFile(); - - String fileRealPath = "your upload file path!"; - - nioTransferCopy(file, fileRealPath); - } -} -``` - -## 配置文件路由 - -`route.conf` - -```sh -GET / IndexRoute.home -GET /signin IndexRoute.show_signin -POST /signin IndexRoute.signin -GET /signout IndexRoute.signout -POST /upload_img UploadRoute.upload_img -``` - -## 路由拦截 - -```java -public static void main(String[] args) { - Blade blade = me(); - blade.before("/.*", (request, response) -> { - System.out.println("before..."); - }); - blade.listen(9001).start(); -} -``` - -## DSL数据库操作 - -```java -// query -List posts = - AR.find("where title like ? order by id desc limit ?,?", title, page, count).list(Post.class); - -// save -String insertSql = "insert into t_post (title, content, view_count, create_time) values (?,?,?,?)"; -AR.update(insertSql, title, content, 0, new Date()).commit(); - -// update -AR.update("update t_post set title = ? and content = ? where id = ?",title, content, id).commit(); - -// delete -AR.update("delete from t_post where id = ?",id).commit() -``` - -OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: - -+ [hello工程](https://github.com/blade-samples/hello) -+ [博客例子](https://github.com/blade-samples/blog) -+ [API文档](http://bladejava.com/apidocs) -+ [使用指南](http://bladejava.com/docs) -+ [相关案例](https://github.com/blade-samples) -+ [版本查询](LAST_VERSION.md) - -### 计划 - -- 1. 添加测试代码 -- 2. 优化基础代码 -- 3. 优化并发能力 - -## 更新日志 - -[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## 联系我 - -- Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me#gmail.com -- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) - -## 贡献 - -非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! - -- [mfarid](https://github.com/mfarid) -- [daimajia](https://github.com/daimajia) -- [shenjie1993](https://github.com/shenjie1993) -- [sumory](https://github.com/sumory) -- [udaykadaboina](https://github.com/udaykadaboina) -- [SyedWasiHaider](https://github.com/SyedWasiHaider) -- [Awakens](https://github.com/Awakens) -- [shellac](https://github.com/shellac) -- [SudarAbisheck](https://github.com/SudarAbisheck) - -## 开源协议 - -请查看 [Apache License](LICENSE) - + +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) + +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) + +[English](https://github.com/biezhi/blade/blob/master/README.md) + +## Blade是什么? + +Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计。 +如果你喜欢,欢迎 [Star and Fork](https://github.com/biezhi/blade), 谢谢! + +## 特性 + +* [x] 轻量级。代码简洁,结构清晰,更容易开发 +* [x] 模块化(你可以选择使用哪些组件) +* [x] 插件扩展机制 +* [x] Restful风格的路由接口 +* [x] 多种配置文件支持(当前支持properties、json和硬编码) +* [x] 内置Jetty服务,模板引擎支持 +* [x] 支持JDK1.6或者更高版本 + +## 概述 + +* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 +* 优雅的:`blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 + +## 快速入门 + +开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : + +`Maven` 配置: + +```xml + + com.bladejava + blade-core + 1.6.1M2 + + + com.bladejava + blade-startup + 1.0.1 + +``` + +或者 `Gradle`: + +```sh +compile 'com.bladejava:blade-core:1.6.1M2' +compile 'com.bladejava:blade-startup:1.0.1' +``` + +编写 `Main`函数: + +```java +public static void main(String[] args) { + Blade blade = me(); + blade.get("/", (request, response) -> { + response.html("

Hello blade!

"); + }); + blade.listen(9001).start(); +} +``` + +用浏览器打开 http://localhost:9001 这样就可以看到第一个Blade应用了! + +## API示例 + +```java +public static void main(String[] args) { + Blade blade = me(); + blade.get("/user/21", getxxx); + blade.post("/save", postxxx); + blade.delete("/del/21", deletexxx); + blade.put("/put", putxxx); + blade.listen(9001).start(); +} +``` + +## REST URL参数获取 + +```java +public static void main(String[] args) { + Blade blade = me(); + blade.get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + blade.get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + blade.listen(9001).start(); +} +``` + +## 表单参数获取 + +```java +public static void main(String[] args) { + Blade blade = me(); + blade.get("/user", (request, response) -> { + Integer uid = request.queryAsInt("uid"); + response.text("uid : " + uid); + }); + blade.listen(9001).start(); +} +``` + +## 上传文件 + +```java +public void upload_img(Request request, Response response){ + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## 配置文件路由 + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## 路由拦截 + +```java +public static void main(String[] args) { + Blade blade = me(); + blade.before("/.*", (request, response) -> { + System.out.println("before..."); + }); + blade.listen(9001).start(); +} +``` + +## DSL数据库操作 + +```java +// query +List posts = + AR.find("where title like ? order by id desc limit ?,?", title, page, count).list(Post.class); + +// save +String insertSql = "insert into t_post (title, content, view_count, create_time) values (?,?,?,?)"; +AR.update(insertSql, title, content, 0, new Date()).commit(); + +// update +AR.update("update t_post set title = ? and content = ? where id = ?",title, content, id).commit(); + +// delete +AR.update("delete from t_post where id = ?",id).commit() +``` + +OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: + ++ [hello工程](https://github.com/blade-samples/hello) ++ [博客例子](https://github.com/blade-samples/blog) ++ [API文档](http://bladejava.com/apidocs) ++ [使用指南](http://bladejava.com/docs) ++ [相关案例](https://github.com/blade-samples) ++ [版本查询](LAST_VERSION.md) + +### 计划 + +- 1. 添加测试代码 +- 2. 优化基础代码 +- 3. 优化并发能力 + +## 更新日志 + +[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## 联系我 + +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me#gmail.com +- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) + +## 贡献 + +非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! + +- [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) + +## 开源协议 + +请查看 [Apache License](LICENSE) + diff --git a/blade-core/pom.xml b/blade-core/pom.xml index d1e07f027..d76462064 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -25,7 +25,7 @@ com.bladejava blade-kit - 1.2.9 + 1.3.0M1 - - javax.servlet - javax.servlet-api - 3.1.0 - provided - - - - org.eclipse.jetty - jetty-server - ${jetty.version} - provided - - - org.eclipse.jetty - jetty-webapp - ${jetty.version} - provided - - - junit - junit - test - - - - + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + + blade-core + jar + ${blade.version} + blade-core + https://github.com/biezhi/blade/blade-core + + + + com.bladejava + blade-kit + 1.3.0 + + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + + junit + junit + test + + + + diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 9ca3e007f..960f203c3 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -1,729 +1,669 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.io.InputStream; -import java.text.ParseException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.blade.ioc.Ioc; -import com.blade.ioc.SimpleIoc; -import com.blade.loader.BladeConfig; -import com.blade.loader.Configurator; -import com.blade.plugin.Plugin; -import com.blade.route.Route; -import com.blade.route.RouteException; -import com.blade.route.RouteGroup; -import com.blade.route.RouteHandler; -import com.blade.route.Routers; -import com.blade.route.loader.ClassPathRouteLoader; -import com.blade.server.Server; -import com.blade.view.template.JspEngine; -import com.blade.view.template.TemplateEngine; -import com.blade.web.http.HttpMethod; -import com.blade.web.verify.Xss; - -import blade.kit.Assert; -import blade.kit.config.loader.ConfigLoader; -import blade.kit.reflect.ReflectKit; - -/** - * Blade Core Class - * - * @author biezhi - * @since 1.0 - */ -public class Blade { - - /** - * Blade initialize - */ - private boolean isInit = false; - - /** - * Servlet asynchronous - */ - private boolean isAsyn = false; - - /** - * Blade initialize config class - */ - private Bootstrap bootstrap = null; - - /** - * Global configuration Object - */ - private BladeConfig bladeConfig = null; - - /** - * IOC Container, save javabean - */ - private Ioc ioc = null; - - /** - * default render is jspRender - */ - private TemplateEngine templateEngine = null; - - /** - * manage route - */ - private Routers routers = null; - - /** - * jetty start port - */ - private int port = Const.DEFAULT_PORT; - - /** - * jetty server - */ - private Server bladeServer; - - /** - * Xss defense - */ - private Xss xss; - - private Set> plugins; - - private Blade() { - this.bladeConfig = new BladeConfig(); - this.ioc = new SimpleIoc(); - this.routers = new Routers(); - this.templateEngine = new JspEngine(); - this.xss = new Xss(); - this.plugins = new HashSet>(); - } - - static final class BladeHolder { - private static final Blade ME = new Blade(); - } - - /** - * @return Single case method returns Blade object - */ - public static final Blade me(){ - return BladeHolder.ME; - } - - /** - * Set Blade initialize - * @param isInit initialize - */ - public void init() { - if(!this.isInit){ - this.isInit = true; - } - } - - /** - * create a jetty server - * @param port server port - * @return return server object - */ - public Server createServer(int port){ - return new Server(port, isAsyn); - } - - /** - * @return return route manager - */ - public Routers routers() { - return routers; - } - - /** - * @return return blade ioc container - */ - public Ioc ioc(){ - return ioc; - } - - /** - * Setting a ioc container - * @param container ioc object - * @return return blade - */ - public Blade container(Ioc ioc){ - Assert.notNull(ioc); - this.ioc = ioc; - return this; - } - - /** - * Setting Properties configuration file - * File path based on classpath - * - * @param confName properties file name - * @return return blade - */ - public Blade setAppConf(String confName){ - Assert.notBlank(confName); - blade.kit.config.Config config = ConfigLoader.load(confName); - Configurator.init(bladeConfig, config); - return this; - } - - /** - * Setting route package,e.g:com.baldejava.route - * Can be introduced into multiple packages, all of which are in the package. - * - * @param packages route package path, is your package name - * @return return blade - */ - public Blade addRoutePackage(String packageName){ - return this.addRoutePackages(packageName); - } - - /** - * Setting route package,e.g:com.baldejava.route - * Can be introduced into multiple packages, all of which are in the package. - * - * @param packages route package path, is your package name - * @return return blade - */ - public Blade addRoutePackages(String...packages){ - Assert.notNull(packages); - bladeConfig.addRoutePackages(packages); - return this; - } - - /** - * - * @param basePackage - * @return - */ - public Blade basePackage(String basePackage){ - Assert.notBlank(basePackage); - bladeConfig.setBasePackage(basePackage); - bladeConfig.addIocPackages(basePackage + ".service.*"); - bladeConfig.addRoutePackages(basePackage + ".controller"); - bladeConfig.setInterceptorPackage(basePackage + ".interceptor"); - return this; - } - - /** - * Setting the path where the interceptor, e.g:com.bladejava.interceptor - * - * @param packageName interceptor packagename - * @return return blade - */ - public Blade interceptor(String packageName) { - Assert.notBlank(packageName); - bladeConfig.setInterceptorPackage(packageName); - return this; - } - - /** - * Setting Ioc packages, e.g:com.bladejava.service - * - * @param packages All need to do into the package, can be introduced into a number of - * @return return blade - */ - public Blade ioc(String...packages){ - Assert.notNull(packages); - bladeConfig.addIocPackages(packages); - return this; - } - - /** - * Add a route - * - * @param path route path - * @param target Target object for routing - * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @return return blade - */ - public Blade route(String path, Class clazz, String method){ - routers.route(path, clazz, method); - return this; - } - - /** - * Register a functional route - * - * @param path route url - * @param clazz route processing class - * @param method route processing method name - * @param httpMethod HttpMethod Type, GET/POST/... - * @return Blade return blade - */ - public Blade route(String path, Class clazz, String method, HttpMethod httpMethod){ - routers.route(path, clazz, method, httpMethod); - return this; - } - - /** - * Add a route list - * @param routes route list - * @return return blade - */ - public Blade routes(List routes){ - Assert.notEmpty(routes, "Routes not is empty!"); - routers.addRoutes(routes); - return this; - } - - /** - * Register a GET request route - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade get(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.GET); - return this; - } - - /** - * Register a POST request route - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade post(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.POST); - return this; - } - - /** - * Register a DELETE request route - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade delete(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.DELETE); - return this; - } - - /** - * Register a PUT request route - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade put(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.PUT); - return this; - } - - /** - * Register for any request routing - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade all(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Register for any request routing - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade any(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Route Group. e.g blade.group('/users').get().post() - * @param g - * @return return blade - */ - public RouteGroup group(String prefix){ - Assert.notNull(prefix, "Route group prefix not is null"); - return new RouteGroup(this, prefix); - } - - /** - * Setting default xss filter - * @param xss xss filter implement - * @return return blade - */ - public Blade xss(final Xss xss){ - Assert.notNull(xss); - this.xss = xss; - return this; - } - - public Xss xss(){ - return this.xss; - } - - /** - * Register a pre routing request interceptor - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade before(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.BEFORE); - return this; - } - - /** - * Register a after routing request interceptor - * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade - */ - public Blade after(String path, RouteHandler handler){ - routers.route(path, handler, HttpMethod.AFTER); - return this; - } - - /** - * Setting Render Engin, Default is JspRender - * - * @param templateEngine Render engine object - * @return return blade - */ - public Blade viewEngin(TemplateEngine templateEngine) { - Assert.notNull(templateEngine); - this.templateEngine = templateEngine; - return this; - } - - /** - * Setting the frame static file folder - * - * @param folders List of directories to filter, e.g: "/public,/static,/images" - * @return return blade - */ - public Blade staticFolder(final String ... folders) { - Assert.notNull(folders); - bladeConfig.setStaticFolders(folders); - return this; - } - - /** - * Setting XSS is enable - * - * @param enableXSS enable XSS, default is false - * @return return blade - */ - public Blade enableXSS(boolean httpXss){ - bladeConfig.setHttpXss(httpXss); - return this; - } - - /** - * Dynamically set the global initialization class, the embedded Jetty boot - * - * @param bootstrap global initialization config class - * @return return blade - */ - public Blade app(Bootstrap bootstrap){ - Assert.notNull(bootstrap); - this.bootstrap = bootstrap; - return this; - } - - /** - * Dynamically set global initialization class - * - * @param bootstrap global initialization config class - * @return return blade - */ - public Blade app(Class bootstrap){ - Assert.notNull(bootstrap); - try { - ioc.addBean(Bootstrap.class.getName(), ReflectKit.newInstance(bootstrap)); - } catch (Exception e) { - e.printStackTrace(); - } - return this; - } - - /** - * Setting 404 view page - * - * @param view404 404 view page - * @return return blade - */ - public Blade view404(final String view404){ - Assert.notBlank(view404); - bladeConfig.setView404(view404); - return this; - } - - /** - * Setting 500 view page - * - * @param view500 500 view page - * @return return blade - */ - public Blade view500(final String view500){ - Assert.notBlank(view500); - bladeConfig.setView500(view500); - return this; - } - - /** - * Setting blade web root path - * - * @param webRoot web root path - * @return return blade - */ - public Blade webRoot(final String webRoot){ - Assert.notBlank(webRoot); - bladeConfig.setWebRoot(webRoot); - return this; - } - - /** - * Setting blade run mode - * - * @param isDev is dev mode - * @return return blade - */ - public Blade isDev(boolean isDev){ - bladeConfig.setDev(isDev); - return this; - } - - /** - * Setting jetty listen port - * - * @param port port, default is 9000 - * @return return blade - */ - public Blade listen(int port){ - this.port = port; - return this; - } - - /** - * Setting servlet asynchronous - * @param isAsyn is asynchronous - * @return return blade - */ - public Blade isAsyn(boolean isAsyn){ - this.isAsyn = isAsyn; - return this; - } - - /** - * Setting jetty context - * - * @param contextPath context path, default is / - */ - public void start(String contextPath) { - try { - Assert.notBlank(contextPath); - bladeServer = new Server(this.port, this.isAsyn); - bladeServer.start(contextPath); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Start jetty server - */ - public void start() { - this.start("/"); - } - - /** - * Jetty sever shutdown - */ - public void stop() { - try { - bladeServer.stop(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Join in server - * - * @throws InterruptedException join exception - */ - public void join() throws InterruptedException { - bladeServer.join(); - } - - /** - * @return Return blade config object - */ - public BladeConfig config(){ - return bladeConfig; - } - - /** - * @return Return route packages - */ - public String[] routePackages(){ - return bladeConfig.getRoutePackages(); - } - - /** - * @return Return ioc packages - */ - public String[] iocs(){ - return bladeConfig.getIocPackages(); - } - - /** - * @return Returns the interceptor array, only one element here use String[] - */ - public String interceptorPackage(){ - return bladeConfig.getInterceptorPackage(); - } - - /** - * @return Return blade encoding, default is UTF-8 - */ - public String encoding(){ - return bladeConfig.getEncoding(); - } - - /** - * @return Return 404 view - */ - public String view404(){ - return bladeConfig.getView404(); - } - - /** - * @return Return 500 view - */ - public String view500(){ - return bladeConfig.getView500(); - } - - /** - * @return Return blade web root path - */ - public String webRoot(){ - return bladeConfig.getWebRoot(); - } - - /** - * @return Return is dev mode - */ - public boolean isDev(){ - return bladeConfig.isDev(); - } - - /** - * @return Return static resource directory - */ - public Set staticFolder(){ - return bladeConfig.getStaticFolders(); - } - - /** - * @return Return bootstrap object - */ - public Bootstrap bootstrap(){ - return this.bootstrap; - } - - /** - * @return Return current templateEngine - */ - public TemplateEngine templateEngine() { - return this.templateEngine; - } - - /** - * @return Return XSS is enabled - */ - public boolean enableXSS(){ - return bladeConfig.isHttpXss(); - } - - /** - * return register plugin object - * - * @param plugin plugin class - * @return return blade - */ - public Blade plugin(Class plugin){ - Assert.notNull(plugin); - plugins.add(plugin); - return this; - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage controller package name - * @return return blade - */ - public Blade routeConf(String basePackage) { - return routeConf(basePackage, "route.conf"); - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage controller package name - * @param conf Configuration file path, the configuration file must be in classpath - * @return return blade - */ - public Blade routeConf(String basePackage, String conf) { - try { - Assert.notBlank(basePackage); - Assert.notBlank(conf); - InputStream ins = Blade.class.getResourceAsStream("/" + conf); - ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); - routesLoader.setBasePackage(basePackage); - List routes = routesLoader.load(); - routers.addRoutes(routes); - } catch (RouteException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - return this; - } - - /** - * @return Return blade is initialize - */ - public boolean isInit() { - return isInit; - } - - public boolean httpCache() { - return bladeConfig.isHttpCache(); - } - - public Set> plugins() { - return this.plugins; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +import java.io.InputStream; +import java.text.ParseException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.blade.context.BladeConfig; +import com.blade.embedd.EmbedServer; +import com.blade.ioc.Ioc; +import com.blade.ioc.SimpleIoc; +import com.blade.plugin.Plugin; +import com.blade.route.Route; +import com.blade.route.RouteException; +import com.blade.route.RouteGroup; +import com.blade.route.RouteHandler; +import com.blade.route.Routers; +import com.blade.route.loader.ClassPathRouteLoader; +import com.blade.view.template.JspEngine; +import com.blade.view.template.TemplateEngine; +import com.blade.web.http.HttpMethod; +import com.blade.web.verify.Xss; + +import blade.kit.Assert; +import blade.kit.Environment; +import blade.kit.reflect.ReflectKit; + +/** + * Blade Core Class + * + * @author biezhi + * @since 1.0 + */ +public class Blade { + + // Blade initialize + private boolean isInit = false; + + // Blade initialize config class + private Bootstrap bootstrap = null; + + // Global configuration Object + private BladeConfig bladeConfig = null; + + // IOC Container + private Ioc ioc = null; + + // default render is jspRender + private TemplateEngine templateEngine = null; + + // routes + private Routers routers = null; + + // jetty start port + private int port = Const.DEFAULT_PORT; + + // default context path + private String contextPath = Const.DEFAULT_CONTEXTPATH; + + // Xss defense + private Xss xss; + + private Set> plugins; + + private Blade() { + this.bladeConfig = new BladeConfig(); + this.ioc = new SimpleIoc(); + this.routers = new Routers(); + this.templateEngine = new JspEngine(); + this.xss = new Xss(); + this.plugins = new HashSet>(); + } + + static final class BladeHolder { + private static final Blade ME = new Blade(); + } + + /** + * @return Single case method returns Blade object + */ + public static final Blade me(){ + return BladeHolder.ME; + } + + /** + * + * @param appConf + * @return + */ + public static final Blade me(String appConf){ + Blade blade = BladeHolder.ME; + blade.bladeConfig.load(appConf); + return blade; + } + + /** + * Set Blade initialize + * @param isInit initialize + */ + public void init() { + if(!this.isInit){ + this.isInit = true; + } + } + + /** + * @return return route manager + */ + public Routers routers() { + return routers; + } + + /** + * @return return blade ioc container + */ + public Ioc ioc(){ + return ioc; + } + + /** + * Setting a ioc container + * @param container ioc object + * @return return blade + */ + public Blade container(Ioc ioc){ + Assert.notNull(ioc); + this.ioc = ioc; + return this; + } + + /** + * Setting Properties configuration file + * File path based on classpath + * + * @param confName properties file name + * @return return blade + */ + public Blade loadAppConf(String confName){ + Assert.notBlank(confName); + bladeConfig.load(confName); + return this; + } + + /** + * Setting route package,e.g:com.baldejava.route + * Can be introduced into multiple packages, all of which are in the package. + * + * @param packages route package path, is your package name + * @return return blade + */ + public Blade addRoutePackage(String packageName){ + return this.addRoutePackages(packageName); + } + + /** + * Setting route package,e.g:com.baldejava.route + * Can be introduced into multiple packages, all of which are in the package. + * + * @param packages route package path, is your package name + * @return return blade + */ + public Blade addRoutePackages(String...packages){ + Assert.notNull(packages); + bladeConfig.addRoutePackages(packages); + return this; + } + + /** + * + * @param basePackage + * @return + */ + public Blade basePackage(String basePackage){ + Assert.notBlank(basePackage); + bladeConfig.setBasePackage(basePackage); + bladeConfig.addIocPackages(basePackage + ".service.*"); + bladeConfig.addRoutePackages(basePackage + ".controller"); + bladeConfig.setInterceptorPackage(basePackage + ".interceptor"); + return this; + } + + /** + * Setting the path where the interceptor, e.g:com.bladejava.interceptor + * + * @param packageName interceptor packagename + * @return return blade + */ + public Blade interceptor(String packageName) { + Assert.notBlank(packageName); + bladeConfig.setInterceptorPackage(packageName); + return this; + } + + /** + * Setting Ioc packages, e.g:com.bladejava.service + * + * @param packages All need to do into the package, can be introduced into a number of + * @return return blade + */ + public Blade ioc(String...packages){ + Assert.notNull(packages); + bladeConfig.addIocPackages(packages); + return this; + } + + /** + * Add a route + * + * @param path route path + * @param target Target object for routing + * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade + */ + public Blade route(String path, Class clazz, String method){ + routers.route(path, clazz, method); + return this; + } + + /** + * Register a functional route + * + * @param path route url + * @param clazz route processing class + * @param method route processing method name + * @param httpMethod HttpMethod Type, GET/POST/... + * @return Blade return blade + */ + public Blade route(String path, Class clazz, String method, HttpMethod httpMethod){ + routers.route(path, clazz, method, httpMethod); + return this; + } + + /** + * Add a route list + * @param routes route list + * @return return blade + */ + public Blade routes(List routes){ + Assert.notEmpty(routes, "Routes not is empty!"); + routers.addRoutes(routes); + return this; + } + + /** + * Register a GET request route + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade get(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.GET); + return this; + } + + /** + * Register a POST request route + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade post(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.POST); + return this; + } + + /** + * Register a DELETE request route + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade delete(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.DELETE); + return this; + } + + /** + * Register a PUT request route + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade put(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.PUT); + return this; + } + + /** + * Register for any request routing + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade all(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Register for any request routing + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade any(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Route Group. e.g blade.group('/users').get().post() + * @param g + * @return return blade + */ + public RouteGroup group(String prefix){ + Assert.notNull(prefix, "Route group prefix not is null"); + return new RouteGroup(this, prefix); + } + + /** + * Setting default xss filter + * @param xss xss filter implement + * @return return blade + */ + public Blade xss(final Xss xss){ + Assert.notNull(xss); + this.xss = xss; + return this; + } + + public Xss xss(){ + return this.xss; + } + + /** + * Register a pre routing request interceptor + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade before(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.BEFORE); + return this; + } + + /** + * Register a after routing request interceptor + * + * @param path route path, request url + * @param handler execute route Handle + * @return return blade + */ + public Blade after(String path, RouteHandler handler){ + routers.route(path, handler, HttpMethod.AFTER); + return this; + } + + /** + * Setting Render Engin, Default is JspRender + * + * @param templateEngine Render engine object + * @return return blade + */ + public Blade viewEngin(TemplateEngine templateEngine) { + Assert.notNull(templateEngine); + this.templateEngine = templateEngine; + return this; + } + + /** + * Setting the frame static file folder + * + * @param folders List of directories to filter, e.g: "/public,/static,/images" + * @return return blade + */ + public Blade staticFolder(final String ... folders) { + Assert.notNull(folders); + bladeConfig.setStaticFolders(folders); + return this; + } + + /** + * Setting XSS is enable + * + * @param enableXSS enable XSS, default is false + * @return return blade + */ + public Blade enableXSS(boolean httpXss){ + bladeConfig.setHttpXss(httpXss); + return this; + } + + /** + * Dynamically set the global initialization class, the embedded Jetty boot + * + * @param bootstrap global initialization config class + * @return return blade + */ + public Blade app(Bootstrap bootstrap){ + Assert.notNull(bootstrap); + this.bootstrap = bootstrap; + return this; + } + + /** + * Dynamically set global initialization class + * + * @param bootstrap global initialization config class + * @return return blade + */ + public Blade app(Class bootstrap){ + Assert.notNull(bootstrap); + try { + ioc.addBean(Bootstrap.class.getName(), ReflectKit.newInstance(bootstrap)); + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + /** + * Setting 404 view page + * + * @param view404 404 view page + * @return return blade + */ + public Blade view404(final String view404){ + Assert.notBlank(view404); + bladeConfig.setView404(view404); + return this; + } + + /** + * Setting 500 view page + * + * @param view500 500 view page + * @return return blade + */ + public Blade view500(final String view500){ + Assert.notBlank(view500); + bladeConfig.setView500(view500); + return this; + } + + /** + * Setting blade web root path + * + * @param webRoot web root path + * @return return blade + */ + public Blade webRoot(final String webRoot){ + Assert.notBlank(webRoot); + bladeConfig.setWebRoot(webRoot); + return this; + } + + /** + * Setting blade run mode + * + * @param isDev is dev mode + * @return return blade + */ + public Blade isDev(boolean isDev){ + bladeConfig.setDev(isDev); + return this; + } + + /** + * Setting jetty listen port + * + * @param port port, default is 9000 + * @return return blade + */ + public Blade listen(int port){ + this.port = port; + return this; + } + + /** + * @return Return blade config object + */ + public BladeConfig config(){ + return bladeConfig; + } + + /** + * @return Return Blade Environment + */ + public Environment environment(){ + return bladeConfig.environment(); + } + + /** + * @return Return route packages + */ + public String[] routePackages(){ + return bladeConfig.getRoutePackages(); + } + + /** + * @return Return ioc packages + */ + public String[] iocs(){ + return bladeConfig.getIocPackages(); + } + + /** + * @return Returns the interceptor array, only one element here use String[] + */ + public String interceptorPackage(){ + return bladeConfig.getInterceptorPackage(); + } + + /** + * @return Return blade encoding, default is UTF-8 + */ + public String encoding(){ + return bladeConfig.getEncoding(); + } + + /** + * @return Return 404 view + */ + public String view404(){ + return bladeConfig.getView404(); + } + + /** + * @return Return 500 view + */ + public String view500(){ + return bladeConfig.getView500(); + } + + /** + * @return Return blade web root path + */ + public String webRoot(){ + return bladeConfig.getWebRoot(); + } + + /** + * @return Return is dev mode + */ + public boolean isDev(){ + return bladeConfig.isDev(); + } + + /** + * @return Return static resource directory + */ + public Set staticFolder(){ + return bladeConfig.getStaticFolders(); + } + + /** + * @return Return bootstrap object + */ + public Bootstrap bootstrap(){ + return this.bootstrap; + } + + /** + * @return Return current templateEngine + */ + public TemplateEngine templateEngine() { + return this.templateEngine; + } + + /** + * @return Return XSS is enabled + */ + public boolean enableXSS(){ + return bladeConfig.isHttpXss(); + } + + /** + * return register plugin object + * + * @param plugin plugin class + * @return return blade + */ + public Blade plugin(Class plugin){ + Assert.notNull(plugin); + plugins.add(plugin); + return this; + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage controller package name + * @return return blade + */ + public Blade routeConf(String basePackage) { + return routeConf(basePackage, "route.conf"); + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage controller package name + * @param conf Configuration file path, the configuration file must be in classpath + * @return return blade + */ + public Blade routeConf(String basePackage, String conf) { + try { + Assert.notBlank(basePackage); + Assert.notBlank(conf); + InputStream ins = Blade.class.getResourceAsStream("/" + conf); + ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); + routesLoader.setBasePackage(basePackage); + List routes = routesLoader.load(); + routers.addRoutes(routes); + } catch (RouteException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return this; + } + + /** + * @return Return blade is initialize + */ + public boolean isInit() { + return isInit; + } + + public boolean httpCache() { + return bladeConfig.isHttpCache(); + } + + public Set> plugins() { + return this.plugins; + } + + public void start(Class embedServer) throws Exception { + embedServer.newInstance().startup(port, contextPath); + } + + public void start(EmbedServer embedServer) throws Exception { + embedServer.startup(port, contextPath); + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 8eaa0e9f7..fbd3f9eb2 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -1,59 +1,53 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -/** - * Const Interface - * - * @author biezhi - * @since 1.0 - */ -public interface Const { - - /** - * Current version - */ - String BLADE_VERSION = "1.6.2"; - - /** - * Server 500 error HTML - */ - String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " - + BLADE_VERSION +"
"; - - /** - * Server 404 error HTML - */ - String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " - + BLADE_VERSION +"
"; - - /** - * Default jetty server port - */ - int DEFAULT_PORT = 9000; - - /** - * Request ThreadPoll context key - */ - String BLADE_EXECUTOR = "blade-req-executor"; - - String BLADE_ROUTE = "blade.route"; - String BLADE_IOC = "blade.ioc"; - String BLADE_VIEW_404 = "blade.view404"; - String BLADE_VIEW_500 = "blade.view500"; - String BLADE_DEV = "blade.dev"; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +/** + * Const Interface + * + * @author biezhi + * @since 1.0 + */ +public interface Const { + + // current blade version + String BLADE_VERSION = "1.6.3"; + + // default embedd server context path + String DEFAULT_CONTEXTPATH = "/"; + + // Server 500 error HTML + String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; + + // Server 404 error HTML + String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; + + // Default jetty server port + int DEFAULT_PORT = 9000; + + // Request ThreadPoll context key + String BLADE_EXECUTOR = "blade-req-executor"; + + /**************** + * blade properties + * **************/ + String BLADE_ROUTE = "blade.route"; + String BLADE_IOC = "blade.ioc"; + String BLADE_VIEW_404 = "blade.view404"; + String BLADE_VIEW_500 = "blade.view500"; + String BLADE_DEV = "blade.dev"; + +} diff --git a/blade-core/src/main/java/com/blade/route/annotation/Path.java b/blade-core/src/main/java/com/blade/annotation/Controller.java similarity index 92% rename from blade-core/src/main/java/com/blade/route/annotation/Path.java rename to blade-core/src/main/java/com/blade/annotation/Controller.java index 1cd5c480d..947ff8ca1 100644 --- a/blade-core/src/main/java/com/blade/route/annotation/Path.java +++ b/blade-core/src/main/java/com/blade/annotation/Controller.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route.annotation; +package com.blade.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -29,7 +29,7 @@ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -public @interface Path{ +public @interface Controller{ /** * @return namespace diff --git a/blade-core/src/main/java/com/blade/interceptor/annotation/Intercept.java b/blade-core/src/main/java/com/blade/annotation/Intercept.java similarity index 93% rename from blade-core/src/main/java/com/blade/interceptor/annotation/Intercept.java rename to blade-core/src/main/java/com/blade/annotation/Intercept.java index 4e210581d..f4f7afde7 100644 --- a/blade-core/src/main/java/com/blade/interceptor/annotation/Intercept.java +++ b/blade-core/src/main/java/com/blade/annotation/Intercept.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.interceptor.annotation; +package com.blade.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/route/annotation/PathVariable.java b/blade-core/src/main/java/com/blade/annotation/PathVariable.java similarity index 86% rename from blade-core/src/main/java/com/blade/route/annotation/PathVariable.java rename to blade-core/src/main/java/com/blade/annotation/PathVariable.java index 15e964b90..3edb7e5b8 100644 --- a/blade-core/src/main/java/com/blade/route/annotation/PathVariable.java +++ b/blade-core/src/main/java/com/blade/annotation/PathVariable.java @@ -1,4 +1,4 @@ -package com.blade.route.annotation; +package com.blade.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/blade-core/src/main/java/com/blade/route/annotation/RequestParam.java b/blade-core/src/main/java/com/blade/annotation/RequestParam.java similarity index 88% rename from blade-core/src/main/java/com/blade/route/annotation/RequestParam.java rename to blade-core/src/main/java/com/blade/annotation/RequestParam.java index 15a32ee50..af3fc8cbf 100644 --- a/blade-core/src/main/java/com/blade/route/annotation/RequestParam.java +++ b/blade-core/src/main/java/com/blade/annotation/RequestParam.java @@ -1,4 +1,4 @@ -package com.blade.route.annotation; +package com.blade.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/blade-core/src/main/java/com/blade/route/annotation/Route.java b/blade-core/src/main/java/com/blade/annotation/Route.java similarity index 95% rename from blade-core/src/main/java/com/blade/route/annotation/Route.java rename to blade-core/src/main/java/com/blade/annotation/Route.java index cba2887cb..395fc3277 100644 --- a/blade-core/src/main/java/com/blade/route/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/annotation/Route.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route.annotation; +package com.blade.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/annotation/package-info.java b/blade-core/src/main/java/com/blade/annotation/package-info.java new file mode 100644 index 000000000..31e0066ee --- /dev/null +++ b/blade-core/src/main/java/com/blade/annotation/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade Annotation + */ +package com.blade.annotation; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/loader/BladeConfig.java b/blade-core/src/main/java/com/blade/context/BladeConfig.java similarity index 69% rename from blade-core/src/main/java/com/blade/loader/BladeConfig.java rename to blade-core/src/main/java/com/blade/context/BladeConfig.java index 5b835d81d..db6bbb0ab 100644 --- a/blade-core/src/main/java/com/blade/loader/BladeConfig.java +++ b/blade-core/src/main/java/com/blade/context/BladeConfig.java @@ -1,248 +1,226 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.loader; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import blade.kit.PatternKit; -import blade.kit.config.Config; -import blade.kit.config.loader.ConfigLoader; - -/** - * Blade Config Class - * - * @author biezhi - * @since 1.0 - * - */ -public class BladeConfig { - - // Store all variables - private Map configMap; - - // Storage of all routing packets - private Set routePackages = new HashSet(); - - // Store all IOC packages - private Set iocPackages = new HashSet(); - - // Store all filter directories - private Set staticFolders = new HashSet(); - - // Base package - private String basePackage; - - // Interceptor package - private String interceptorPackage; - - // Encoding - private String encoding = "utf-8"; - - // web root path - private String webRoot; - - // 404 view page - private String view404; - - // 500 view page - private String view500; - - // Is dev mode - private boolean isDev = true; - - // Enabled XSS - private boolean httpXss = false; - - private boolean httpCache = false; - - private boolean configInit = false; - - public BladeConfig() { - staticFolders.add("/public"); - staticFolders.add("/assets"); - staticFolders.add("/static"); - } - - public void init(){ - if(!configInit){ - try { - Config config = ConfigLoader.load("blade.properties"); - if(null != config){ - Configurator.init(this, config); - } - } catch (Exception e) { - } - } - } - - public Map getConfigMap() { - return configMap; - } - - public void setConfigMap(Map configMap) { - this.configMap = configMap; - } - - public String get(String key){ - return configMap.get(key); - } - - public Integer getAsInt(String key){ - String val = get(key); - if(null != val && PatternKit.isNumber(val)){ - return Integer.valueOf(val); - } - return null; - } - - public Long getAsLong(String key){ - String val = get(key); - if(null != val && PatternKit.isNumber(val)){ - return Long.valueOf(val); - } - return null; - } - - public Boolean getAsBoolean(String key){ - String val = get(key); - if(null != val){ - return Boolean.valueOf(val); - } - return null; - } - - public Double getAsDouble(String key){ - String val = get(key); - if(null != val){ - return Double.valueOf(val); - } - return null; - } - - public Float getAsFloat(String key){ - String val = get(key); - if(null != val){ - return Float.valueOf(val); - } - return null; - } - - public String[] getRoutePackages() { - String[] routeArr = new String[routePackages.size()]; - return routePackages.toArray(routeArr); - } - - public void addRoutePackages(String ... packages) { - if(null != packages && packages.length > 0){ - routePackages.addAll(Arrays.asList(packages)); - } - } - - public String getBasePackage() { - return basePackage; - } - - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - } - - public String[] getIocPackages() { - String[] iocArr = new String[iocPackages.size()]; - return iocPackages.toArray(iocArr); - } - - public void addIocPackages(String ... packages) { - if(null != packages && packages.length > 0){ - iocPackages.addAll(Arrays.asList(packages)); - } - } - - public String getInterceptorPackage() { - return interceptorPackage; - } - - public void setInterceptorPackage(String interceptorPackage) { - this.interceptorPackage = interceptorPackage; - } - - public Set getStaticFolders() { - return staticFolders; - } - - public void setStaticFolders(String ... packages) { - staticFolders.addAll(Arrays.asList(packages)); - } - - public String getView404() { - return view404; - } - - public void setView404(String view404) { - this.view404 = view404; - } - - public String getView500() { - return view500; - } - - public void setView500(String view500) { - this.view500 = view500; - } - - public String getWebRoot() { - return webRoot; - } - - public void setWebRoot(String webRoot) { - this.webRoot = webRoot; - } - - public boolean isDev() { - return isDev; - } - - public void setDev(boolean isDev) { - this.isDev = isDev; - } - - public String getEncoding() { - return encoding; - } - - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - public boolean isHttpXss() { - return httpXss; - } - - public void setHttpXss(boolean httpXss) { - this.httpXss = httpXss; - } - - public boolean isHttpCache() { - return httpCache; - } - - public void setHttpCache(boolean httpCache) { - this.httpCache = httpCache; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import com.blade.Blade; + +import blade.kit.Environment; +import blade.kit.StringKit; + +/** + * Blade Config Class + * + * @author biezhi + * @since 1.0 + * + */ +public class BladeConfig { + + // Storage of all routing packets + private Set routePackages = new HashSet(); + + // Store all IOC packages + private Set iocPackages = new HashSet(); + + // Store all filter directories + private Set staticFolders = new HashSet(); + + // Base package + private String basePackage; + + // Interceptor package + private String interceptorPackage; + + // Encoding + private String encoding = "utf-8"; + + // web root path + private String webRoot; + + // 404 view page + private String view404; + + // 500 view page + private String view500; + + // Is dev mode + private boolean isDev = true; + + // Enabled XSS + private boolean httpXss = false; + + private boolean httpCache = false; + + private boolean configInit = false; + + private Environment environment; + + public BladeConfig() { + staticFolders.add("/public"); + staticFolders.add("/assets"); + staticFolders.add("/static"); + } + + public void load(String confPath){ + if(!configInit){ + try { + Environment environment = Environment.load(confPath); + if(null != environment){ + this.environment = environment; + this.isDev = environment.getBoolean("app.dev", true); + this.httpCache = environment.getBoolean("http.cache", false); + this.httpXss = environment.getBoolean("http.xss", false); + this.encoding = environment.getString("http.encoding", "UTF-8"); + this.addIocPackages(environment.getString("app.ioc")); + this.view500 = environment.getString("app.view.500"); + this.view404 = environment.getString("app.view.404"); + + String httpFilters = environment.getString("http.filters"); + String basePackage = environment.getString("app.base-package"); + Integer port = environment.getInt("server.port"); + + if(null != port){ + Blade.me().listen(port); + } + + if(StringKit.isNotBlank(httpFilters)){ + this.setStaticFolders(httpFilters.split(",")); + } + + if(StringKit.isNotBlank(basePackage)){ + this.setBasePackage(basePackage); + this.addIocPackages(basePackage + ".service.*"); + this.addRoutePackages(basePackage + ".controller"); + this.setInterceptorPackage(basePackage + ".interceptor"); + } + + } + } catch (Exception e) { + } + } + } + + public Environment environment(){ + return this.environment; + } + + public String[] getRoutePackages() { + String[] routeArr = new String[routePackages.size()]; + return routePackages.toArray(routeArr); + } + + public void addRoutePackages(String ... packages) { + if(null != packages && packages.length > 0){ + routePackages.addAll(Arrays.asList(packages)); + } + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } + + public String[] getIocPackages() { + String[] iocArr = new String[iocPackages.size()]; + return iocPackages.toArray(iocArr); + } + + public void addIocPackages(String ... packages) { + if(null != packages && packages.length > 0){ + iocPackages.addAll(Arrays.asList(packages)); + } + } + + public String getInterceptorPackage() { + return interceptorPackage; + } + + public void setInterceptorPackage(String interceptorPackage) { + this.interceptorPackage = interceptorPackage; + } + + public Set getStaticFolders() { + return staticFolders; + } + + public void setStaticFolders(String ... packages) { + staticFolders.addAll(Arrays.asList(packages)); + } + + public String getView404() { + return view404; + } + + public void setView404(String view404) { + this.view404 = view404; + } + + public String getView500() { + return view500; + } + + public void setView500(String view500) { + this.view500 = view500; + } + + public String getWebRoot() { + return webRoot; + } + + public void setWebRoot(String webRoot) { + this.webRoot = webRoot; + } + + public boolean isDev() { + return isDev; + } + + public void setDev(boolean isDev) { + this.isDev = isDev; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public boolean isHttpXss() { + return httpXss; + } + + public void setHttpXss(boolean httpXss) { + this.httpXss = httpXss; + } + + public boolean isHttpCache() { + return httpCache; + } + + public void setHttpCache(boolean httpCache) { + this.httpCache = httpCache; + } + +} diff --git a/blade-core/src/main/java/com/blade/embedd/EmbedServer.java b/blade-core/src/main/java/com/blade/embedd/EmbedServer.java new file mode 100644 index 000000000..64891ddc3 --- /dev/null +++ b/blade-core/src/main/java/com/blade/embedd/EmbedServer.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.embedd; + +/** + * Jetty Server + * + * @author biezhi + * @since 1.0 + */ +public interface EmbedServer { + + void startup(int port) throws Exception; + + void startup(int port, String contextPath) throws Exception; + + void startup(int port, String contextPath, String webRoot) throws Exception; + + void stop() throws Exception; + +} diff --git a/blade-core/src/main/java/com/blade/embedd/package-info.java b/blade-core/src/main/java/com/blade/embedd/package-info.java new file mode 100644 index 000000000..96aacd1f9 --- /dev/null +++ b/blade-core/src/main/java/com/blade/embedd/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade Jetty Ext + */ +package com.blade.embedd; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 88c4412d8..6aa424ab2 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -31,10 +31,11 @@ import com.blade.route.Routers; import blade.kit.CollectionKit; +import blade.kit.StringKit; import blade.kit.logging.Logger; import blade.kit.logging.LoggerFactory; -import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; +import blade.kit.resource.DynamicClassReader; /** * IOC container, used to initialize the IOC object @@ -70,7 +71,7 @@ public class IocApplication { public IocApplication(Blade blade) { this.blade = blade; - this.classReader = new ClassPathClassReader(); + this.classReader = DynamicClassReader.getClassReader(); this.plugins = CollectionKit.newArrayList(); this.pluginTypes = blade.plugins(); this.ioc = blade.ioc(); @@ -146,7 +147,9 @@ public void init(){ * @param packageName package name */ private void registerBean(String packageName) { - + if(StringKit.isBlank(packageName)){ + return; + } // Recursive scan boolean recursive = false; if (packageName.endsWith(".*")) { diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java index abd140aad..9ad544519 100644 --- a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java @@ -24,14 +24,14 @@ import com.blade.ioc.SimpleIoc; import com.blade.ioc.annotation.Component; -import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; +import blade.kit.resource.DynamicClassReader; public final class IocAnnotationLoader implements IocLoader { private Collection> classes; - private ClassReader classReader = new ClassPathClassReader(); + private ClassReader classReader = DynamicClassReader.getClassReader(); public IocAnnotationLoader(String... packageNames) { List> annotations = new ArrayList>(1); diff --git a/blade-core/src/main/java/com/blade/loader/Configurator.java b/blade-core/src/main/java/com/blade/loader/Configurator.java deleted file mode 100644 index 58660aca5..000000000 --- a/blade-core/src/main/java/com/blade/loader/Configurator.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.loader; - -import java.util.Map; - -import blade.kit.Assert; -import blade.kit.CollectionKit; -import blade.kit.StringKit; -import blade.kit.config.Config; - -/** - * Blade configuration - * - * @author biezhi - * @since 1.0 - */ -public final class Configurator { - - public static void init(BladeConfig bladeConfig, Config config) { - - Assert.notNull(bladeConfig); - Assert.notNull(config); - - Boolean dev = config.getBoolean("blade.dev"); - Boolean httpCache = config.getBoolean("blade.http.cache"); - Boolean httpXss = config.getBoolean("blade.http.xss"); - - String httpEncoding = config.getString("blade.http.encoding"); - String httpFilters = config.getString("blade.http.filters"); - String basePackage = config.getString("blade.basepackage"); - String iocPackage = config.getString("blade.ioc"); - String view500 = config.getString("blade.view.500"); - String view404 = config.getString("blade.view.404"); - - if(null != dev){ - bladeConfig.setDev(dev); - } - - if(null != httpCache){ - bladeConfig.setHttpCache(httpCache); - } - - if(StringKit.isNotBlank(httpEncoding)){ - bladeConfig.setEncoding(httpEncoding); - } - - if(StringKit.isNotBlank(iocPackage)){ - bladeConfig.addIocPackages(iocPackage); - } - - if(null != httpXss){ - bladeConfig.setHttpXss(httpXss); - } - - if(StringKit.isNotBlank(httpFilters)){ - bladeConfig.setStaticFolders(httpFilters.split(",")); - } - - if(StringKit.isNotBlank(view404)){ - bladeConfig.setView404(view404); - } - - if(StringKit.isNotBlank(view500)){ - bladeConfig.setView500(view500); - } - - if(StringKit.isNotBlank(basePackage)){ - bladeConfig.setBasePackage(basePackage); - bladeConfig.addIocPackages(basePackage + ".service.*"); - bladeConfig.addRoutePackages(basePackage + ".controller"); - bladeConfig.setInterceptorPackage(basePackage + ".interceptor"); - } - - Map configMap = config.getConfigMap(); - if(CollectionKit.isNotEmpty(configMap)){ - bladeConfig.setConfigMap(configMap); - } - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/loader/package-info.java b/blade-core/src/main/java/com/blade/loader/package-info.java deleted file mode 100644 index bfbefb4f8..000000000 --- a/blade-core/src/main/java/com/blade/loader/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Blade Config And Loader - */ -package com.blade.loader; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/C.java b/blade-core/src/main/java/com/blade/route/C.java deleted file mode 100644 index e540a3767..000000000 --- a/blade-core/src/main/java/com/blade/route/C.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.blade.route; - -import java.util.Map; - -import com.blade.view.ModelAndView; - -public class C { - - public ModelAndView render(String view){ - return new ModelAndView(view); - } - - public ModelAndView render(Map model, String view){ - return new ModelAndView(model, view); - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index c92d8addf..19e0dca3d 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -19,10 +19,10 @@ import java.util.Set; import com.blade.Blade; +import com.blade.annotation.Intercept; +import com.blade.annotation.Controller; +import com.blade.annotation.Route; import com.blade.interceptor.Interceptor; -import com.blade.interceptor.annotation.Intercept; -import com.blade.route.annotation.Path; -import com.blade.route.annotation.Route; import com.blade.web.http.HttpMethod; import com.blade.web.http.Request; import com.blade.web.http.Response; @@ -30,8 +30,8 @@ import blade.kit.CollectionKit; import blade.kit.StringKit; import blade.kit.reflect.ReflectKit; -import blade.kit.resource.ClassPathClassReader; import blade.kit.resource.ClassReader; +import blade.kit.resource.DynamicClassReader; /** * Route builder @@ -56,7 +56,7 @@ public RouteBuilder(Blade blade) { this.routers = blade.routers(); this.routePackages = blade.routePackages(); this.interceptorPackage = blade.interceptorPackage(); - this.classReader = new ClassPathClassReader(); + this.classReader = DynamicClassReader.getClassReader(); } /** @@ -109,7 +109,7 @@ private void buildRoute(String... routePackages){ // Traverse route for(String packageName : routePackages){ // Scan all Controoler - classes = classReader.getClassByAnnotation(packageName, Path.class, true); + classes = classReader.getClassByAnnotation(packageName, Controller.class, true); if(CollectionKit.isNotEmpty(classes)){ for(Class pathClazz : classes){ parseRouter(pathClazz); @@ -165,9 +165,9 @@ private void parseRouter(final Class router){ return; } - final String nameSpace = router.getAnnotation(Path.class).value(); + final String nameSpace = router.getAnnotation(Controller.class).value(); - final String suffix = router.getAnnotation(Path.class).suffix(); + final String suffix = router.getAnnotation(Controller.class).suffix(); for (Method method : methods) { diff --git a/blade-core/src/main/java/com/blade/route/annotation/package-info.java b/blade-core/src/main/java/com/blade/route/annotation/package-info.java deleted file mode 100644 index 615d80887..000000000 --- a/blade-core/src/main/java/com/blade/route/annotation/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Blade Annotation - */ -package com.blade.route.annotation; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/server/Server.java b/blade-core/src/main/java/com/blade/server/Server.java deleted file mode 100644 index 2a7e86503..000000000 --- a/blade-core/src/main/java/com/blade/server/Server.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.server; - -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; - -import com.blade.web.DispatcherServlet; - -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - -/** - * Jetty Server - * - * @author biezhi - * @since 1.0 - */ -public class Server { - - private static final Logger LOGGER = LoggerFactory.getLogger(Server.class); - - private int port = 9000; - - private org.eclipse.jetty.server.Server server; - - private ServletContextHandler context; - - public Server(int port, boolean async) { - this.port = port; - } - - public void setPort(int port){ - this.port = port; - } - - public void start(String contextPath) throws Exception{ - - server = new org.eclipse.jetty.server.Server(this.port); - // 设置在JVM退出时关闭Jetty的钩子。 - server.setStopAtShutdown(true); - - context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath(contextPath); - - context.setResourceBase(Thread.currentThread().getContextClassLoader() - .getResource("").getPath()); - - ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); - servletHolder.setAsyncSupported(false); - servletHolder.setInitOrder(1); - - context.addServlet(servletHolder, "/"); - server.setHandler(this.context); - server.start(); - -// server.dump(System.err); - LOGGER.info("Blade Server Listen on http://127.0.0.1:{}", this.port); - } - - public void join() throws InterruptedException { - server.join(); - } - - public void stop() throws Exception{ - context.stop(); - server.stop(); - } -} diff --git a/blade-core/src/main/java/com/blade/server/package-info.java b/blade-core/src/main/java/com/blade/server/package-info.java deleted file mode 100644 index 928775bd0..000000000 --- a/blade-core/src/main/java/com/blade/server/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Blade Jetty Ext - */ -package com.blade.server; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 9be611186..506bb0189 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -1,212 +1,212 @@ -package com.blade.view.handle; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import com.blade.ioc.Ioc; -import com.blade.route.Route; -import com.blade.route.annotation.PathVariable; -import com.blade.route.annotation.RequestParam; -import com.blade.view.ModelAndView; -import com.blade.view.ModelMap; -import com.blade.web.DispatchKit; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.wrapper.Session; -import com.blade.web.multipart.FileItem; - -import blade.kit.reflect.ReflectKit; - -public class RouteViewHandler { - - private Ioc ioc; - - public RouteViewHandler(Ioc ioc) { - this.ioc = ioc; - } - - private Object getPathParam(Class parameterType, String val, Request request){ - Object result = null; - if(parameterType.equals(String.class)){ - result = request.param(val); - } else if(parameterType.equals(Integer.class) || parameterType.equals(int.class)){ - result = request.paramAsInt(val); - } else if(parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)){ - result = request.paramAsBool(val); - } else if(parameterType.equals(Long.class) || parameterType.equals(long.class)){ - result = request.paramAsLong(val); - } - return result; - } - - private Object getRequestParam(Class parameterType, String val, String defaultValue, Request request){ - Object result = null; - if(parameterType.equals(String.class)){ - String value = request.query(val); - if(null == value){ - result = defaultValue; - } else { - result = value; - } - } else if(parameterType.equals(Integer.class) || parameterType.equals(int.class)){ - Integer value = request.queryAsInt(val); - if(null == value){ - result = Integer.valueOf(defaultValue); - } else { - result = value; - } - } else if(parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)){ - Boolean value = request.queryAsBool(val); - if(null == value){ - result = Boolean.valueOf(defaultValue); - } else { - result = value; - } - } else if(parameterType.equals(Long.class) || parameterType.equals(long.class)){ - Long value = request.queryAsLong(val); - if(null == value){ - result = Long.valueOf(defaultValue); - } else { - result = value; - } - } - return result; - } - - /** - * Parameters in the method - * - * @param request Request object for injection to the method parameter list - * @param response Response object for injection to the method parameter list - * @param actionMethod Execute method - * @return Return the generated array of parameters - */ - public Object[] getArgs(Request request, Response response, Method actionMethod){ - Annotation[][] parameterAnnotations = actionMethod.getParameterAnnotations(); - Class[] parameterTypes = actionMethod.getParameterTypes(); - int len = parameterTypes.length; - Object[] args = new Object[len]; - actionMethod.setAccessible(true); - - int i = 0; - if(parameterAnnotations.length > 0){ - for (Annotation[] annotations : parameterAnnotations) { - Class parameterType = parameterTypes[i]; - for (Annotation annotation : annotations) { - Class anType = annotation.annotationType(); - if(anType.equals(PathVariable.class)){ - PathVariable pathVariable = (PathVariable) annotation; - String val = pathVariable.value(); - Object value = getPathParam(parameterType, val, request); - args[i] = value; - } else if(anType.equals(RequestParam.class)) { - RequestParam requestParam = (RequestParam) annotation; - String val = requestParam.value(); - Object value = getRequestParam(parameterType, val, requestParam.defaultValue(), request); - args[i] = value; - } - } - i++; - } - } - - for(i=0; i paramTypeClazz = parameterTypes[i]; - if(paramTypeClazz.equals(Request.class)){ - args[i] = request; - } else if(paramTypeClazz.equals(Response.class)){ - args[i] = response; - } else if(paramTypeClazz.equals(Session.class)){ - args[i] = request.session(); - } else if(paramTypeClazz.equals(ModelMap.class)){ - args[i] = new ModelMap(request); - } else if(paramTypeClazz.equals(HttpServletRequest.class)){ - args[i] = request.raw(); - } else if(paramTypeClazz.equals(HttpServletResponse.class)){ - args[i] = response.raw(); - } else if(paramTypeClazz.equals(HttpSession.class)){ - args[i] = request.raw().getSession(); - } else if(paramTypeClazz.equals(FileItem.class)){ - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - args[i] = fileItems[0]; - } - } - } - return args; - } - - public void handle(Request request, Response response, Route route){ - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - // execute - - int len = actionMethod.getParameterTypes().length; - try { - Object returnParam = null; - if(len > 0){ - Object[] args = getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if(null != returnParam){ - Class returnType = returnParam.getClass(); - if(returnType == String.class){ - response.render( returnParam.toString() ); - } else if(returnType == ModelAndView.class){ - ModelAndView modelAndView = (ModelAndView) returnParam; - response.render( modelAndView ); - } - } - } catch (Exception e) { - request.abort(); - DispatchKit.printError(e, 500, response); - } - - } - - public boolean intercept(Request request, Response response, Route route){ - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - - if(null == target){ - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - - // execute - int len = actionMethod.getParameterTypes().length; - actionMethod.setAccessible(true); - try { - Object returnParam = null; - if(len > 0){ - Object[] args = getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if(null != returnParam){ - Class returnType = returnParam.getClass(); - if(returnType == Boolean.class || returnType == boolean.class){ - return (Boolean) returnParam; - } - } - - return true; - - } catch (Exception e) { - request.abort(); - DispatchKit.printError(e, 500, response); - } - return false; - } - -} +package com.blade.view.handle; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import com.blade.annotation.PathVariable; +import com.blade.annotation.RequestParam; +import com.blade.ioc.Ioc; +import com.blade.route.Route; +import com.blade.view.ModelAndView; +import com.blade.view.ModelMap; +import com.blade.web.DispatchKit; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.Session; +import com.blade.web.multipart.FileItem; + +import blade.kit.reflect.ReflectKit; + +public class RouteViewHandler { + + private Ioc ioc; + + public RouteViewHandler(Ioc ioc) { + this.ioc = ioc; + } + + private Object getPathParam(Class parameterType, String val, Request request){ + Object result = null; + if(parameterType.equals(String.class)){ + result = request.param(val); + } else if(parameterType.equals(Integer.class) || parameterType.equals(int.class)){ + result = request.paramAsInt(val); + } else if(parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)){ + result = request.paramAsBool(val); + } else if(parameterType.equals(Long.class) || parameterType.equals(long.class)){ + result = request.paramAsLong(val); + } + return result; + } + + private Object getRequestParam(Class parameterType, String val, String defaultValue, Request request){ + Object result = null; + if(parameterType.equals(String.class)){ + String value = request.query(val); + if(null == value){ + result = defaultValue; + } else { + result = value; + } + } else if(parameterType.equals(Integer.class) || parameterType.equals(int.class)){ + Integer value = request.queryAsInt(val); + if(null == value){ + result = Integer.valueOf(defaultValue); + } else { + result = value; + } + } else if(parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)){ + Boolean value = request.queryAsBool(val); + if(null == value){ + result = Boolean.valueOf(defaultValue); + } else { + result = value; + } + } else if(parameterType.equals(Long.class) || parameterType.equals(long.class)){ + Long value = request.queryAsLong(val); + if(null == value){ + result = Long.valueOf(defaultValue); + } else { + result = value; + } + } + return result; + } + + /** + * Parameters in the method + * + * @param request Request object for injection to the method parameter list + * @param response Response object for injection to the method parameter list + * @param actionMethod Execute method + * @return Return the generated array of parameters + */ + public Object[] getArgs(Request request, Response response, Method actionMethod){ + Annotation[][] parameterAnnotations = actionMethod.getParameterAnnotations(); + Class[] parameterTypes = actionMethod.getParameterTypes(); + int len = parameterTypes.length; + Object[] args = new Object[len]; + actionMethod.setAccessible(true); + + int i = 0; + if(parameterAnnotations.length > 0){ + for (Annotation[] annotations : parameterAnnotations) { + Class parameterType = parameterTypes[i]; + for (Annotation annotation : annotations) { + Class anType = annotation.annotationType(); + if(anType.equals(PathVariable.class)){ + PathVariable pathVariable = (PathVariable) annotation; + String val = pathVariable.value(); + Object value = getPathParam(parameterType, val, request); + args[i] = value; + } else if(anType.equals(RequestParam.class)) { + RequestParam requestParam = (RequestParam) annotation; + String val = requestParam.value(); + Object value = getRequestParam(parameterType, val, requestParam.defaultValue(), request); + args[i] = value; + } + } + i++; + } + } + + for(i=0; i paramTypeClazz = parameterTypes[i]; + if(paramTypeClazz.equals(Request.class)){ + args[i] = request; + } else if(paramTypeClazz.equals(Response.class)){ + args[i] = response; + } else if(paramTypeClazz.equals(Session.class)){ + args[i] = request.session(); + } else if(paramTypeClazz.equals(ModelMap.class)){ + args[i] = new ModelMap(request); + } else if(paramTypeClazz.equals(HttpServletRequest.class)){ + args[i] = request.raw(); + } else if(paramTypeClazz.equals(HttpServletResponse.class)){ + args[i] = response.raw(); + } else if(paramTypeClazz.equals(HttpSession.class)){ + args[i] = request.raw().getSession(); + } else if(paramTypeClazz.equals(FileItem.class)){ + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + args[i] = fileItems[0]; + } + } + } + return args; + } + + public void handle(Request request, Response response, Route route){ + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + // execute + + int len = actionMethod.getParameterTypes().length; + try { + Object returnParam = null; + if(len > 0){ + Object[] args = getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if(null != returnParam){ + Class returnType = returnParam.getClass(); + if(returnType == String.class){ + response.render( returnParam.toString() ); + } else if(returnType == ModelAndView.class){ + ModelAndView modelAndView = (ModelAndView) returnParam; + response.render( modelAndView ); + } + } + } catch (Exception e) { + request.abort(); + DispatchKit.printError(e, 500, response); + } + + } + + public boolean intercept(Request request, Response response, Route route){ + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + + // execute + int len = actionMethod.getParameterTypes().length; + actionMethod.setAccessible(true); + try { + Object returnParam = null; + if(len > 0){ + Object[] args = getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if(null != returnParam){ + Class returnType = returnParam.getClass(); + if(returnType == Boolean.class || returnType == boolean.class){ + return (Boolean) returnParam; + } + } + + return true; + + } catch (Exception e) { + request.abort(); + DispatchKit.printError(e, 500, response); + } + return false; + } + +} diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 53a339c26..e08cc1c29 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -34,6 +34,7 @@ import blade.kit.SystemKit; import blade.kit.logging.Logger; import blade.kit.logging.LoggerFactory; +import blade.kit.resource.DynamicClassReader; /** * Blade Core DispatcherServlet @@ -77,6 +78,8 @@ public void init(ServletConfig config) throws ServletException { LOGGER.info("user.timezone = {}", System.getProperty("user.timezone")); LOGGER.info("file.encoding = {}", System.getProperty("file.encoding")); + DynamicClassReader.init(); + long initStart = System.currentTimeMillis(); blade.webRoot(DispatchKit.getWebroot(servletContext).getPath()); @@ -85,8 +88,6 @@ public void init(ServletConfig config) throws ServletException { LOGGER.info("blade.webroot = {}", blade.webRoot()); - blade.config().init(); - this.bootstrap = blade.bootstrap(); if(null == bootstrap){ String bootStrapClassName = config.getInitParameter("bootstrap"); @@ -122,7 +123,9 @@ public void init(Blade blade) { new BladeBanner().print(); - LOGGER.info("DispatcherServlet initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); + String appName = blade.environment().getString("app.name", "Blade"); + + LOGGER.info(appName + " initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); } } diff --git a/blade-startup/pom.xml b/blade-embed-jetty/pom.xml similarity index 59% rename from blade-startup/pom.xml rename to blade-embed-jetty/pom.xml index bf54bc750..4f4357fd7 100644 --- a/blade-startup/pom.xml +++ b/blade-embed-jetty/pom.xml @@ -1,57 +1,49 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-startup - 1.0.1 - blade-startup - - https://github.com/biezhi/blade/blade-startup - - - UTF-8 - 9.2.12.v20150709 - 3.1.0 - - - - - com.bladejava - blade-core - ${blade.version} - - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - - org.eclipse.jetty - jetty-server - ${jetty.version} - - - org.eclipse.jetty - jetty-webapp - ${jetty.version} - - - - - - - + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + blade-embed-jetty + 0.0.1 + blade-embed-jetty + http://maven.apache.org + + + UTF-8 + 3.1.0 + 9.2.12.v20150709 + + + + + + com.bladejava + blade-core + ${blade.version} + + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + + + + diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java new file mode 100644 index 000000000..3ecfabb96 --- /dev/null +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -0,0 +1,109 @@ +package com.blade.embedd; + +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.thread.QueuedThreadPool; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.web.DispatcherServlet; + +import blade.kit.Environment; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; + +public class EmbedJettyServer implements EmbedServer { + + private static final Logger LOGGER = LoggerFactory.getLogger(EmbedJettyServer.class); + + private int port = Const.DEFAULT_PORT; + + private org.eclipse.jetty.server.Server server; + + private ServletContextHandler context; + + private Environment environment = Blade.me().environment().add("jetty.properties"); + + public EmbedJettyServer() { + } + + @Override + public void startup(int port) throws Exception { + this.startup(port, Const.DEFAULT_CONTEXTPATH, null); + } + + @Override + public void startup(int port, String contextPath) throws Exception { + this.startup(port, contextPath, null); + } + + @Override + public void startup(int port, String contextPath, String webRoot) throws Exception { + this.port = port; + + // Setup Threadpool + QueuedThreadPool threadPool = new QueuedThreadPool(); + + int maxThreads = environment.getInt("server.jetty.max-threads", 100); + + threadPool.setMaxThreads(maxThreads); + + server = new org.eclipse.jetty.server.Server(threadPool); + // 设置在JVM退出时关闭Jetty的钩子。 + server.setStopAtShutdown(true); + + context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath(contextPath); + + /*if(StringKit.isNotBlank(webRoot)){ + context.setResourceBase(webRoot); + } else{ + context.setResourceBase(getClass().getResource("").getPath()); + }*/ + context.setResourceBase("."); + + int securePort = environment.getInt("server.jetty.http.secure-port", 8443); + int outputBufferSize = environment.getInt("server.jetty.http.output-buffersize", 32768); + int requestHeaderSize = environment.getInt("server.jetty.http.request-headersize", 8192); + int responseHeaderSize = environment.getInt("server.jetty.http.response-headersize", 8192); + + // HTTP Configuration + HttpConfiguration http_config = new HttpConfiguration(); + http_config.setSecurePort(securePort); + http_config.setOutputBufferSize(outputBufferSize); + http_config.setRequestHeaderSize(requestHeaderSize); + http_config.setResponseHeaderSize(responseHeaderSize); + http_config.setSendServerVersion(true); + http_config.setSendDateHeader(false); + + long idleTimeout = environment.getLong("server.jetty.http.idle-timeout", 30000L); + + ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(http_config)); + http.setPort(this.port); + http.setIdleTimeout(idleTimeout); + server.addConnector(http); + + ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); + servletHolder.setAsyncSupported(false); + servletHolder.setInitOrder(1); + + context.addServlet(servletHolder, "/"); + server.setHandler(this.context); + + server.start(); + LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); + server.join(); + } + + public void stop() throws Exception { + server.stop(); + } + + public void waitForInterrupt() throws InterruptedException { + server.join(); + } + +} \ No newline at end of file diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index a92b488f5..7aa038445 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -1,58 +1,58 @@ - - - 4.0.0 - - com.bladejava - blade-root - 1.0 - - - blade-kit - jar - 1.3.0M1 - blade-kit - https://github.com/biezhi/blade/tree/master/blade-kit - - - 3.0.1 - - - - - junit - junit - - - org.slf4j - slf4j-api - provided - - - log4j - log4j - 1.2.17 - provided - - - dom4j - dom4j - 1.6.1 - provided - - - jaxen - jaxen - 1.1.6 - provided - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - - + + + 4.0.0 + + com.bladejava + blade-root + 1.0 + + + blade-kit + jar + 1.3.0 + blade-kit + https://github.com/biezhi/blade/tree/master/blade-kit + + + 3.0.1 + + + + + junit + junit + + + org.slf4j + slf4j-api + provided + + + log4j + log4j + 1.2.17 + provided + + + dom4j + dom4j + 1.6.1 + provided + + + jaxen + jaxen + 1.1.6 + provided + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + + diff --git a/blade-kit/src/main/java/blade/kit/ClassLoaderKit.java b/blade-kit/src/main/java/blade/kit/ClassLoaderKit.java index b6127de90..0c5671151 100644 --- a/blade-kit/src/main/java/blade/kit/ClassLoaderKit.java +++ b/blade-kit/src/main/java/blade/kit/ClassLoaderKit.java @@ -15,7 +15,7 @@ public class ClassLoaderKit { public static ClassLoader getDefault() { ClassLoader loader = null; try { - loader = Thread.currentThread().getContextClassLoader(); + loader = ClassLoader.class.getClassLoader(); } catch (Exception e) { } if (loader == null) { diff --git a/blade-kit/src/main/java/blade/kit/Environment.java b/blade-kit/src/main/java/blade/kit/Environment.java new file mode 100644 index 000000000..666839c46 --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/Environment.java @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; + +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; + +/** + * Environment + * + * @author biezhi + * @since 1.0 + */ +public class Environment { + + private static final Logger LOGGER = LoggerFactory.getLogger(Environment.class); + + private Map envMap = new HashMap(20); + + public Environment(String confPath){ + this.envMap = loadMap(confPath); + } + + private Map loadMap(String confPath){ + Map envMap = new HashMap(20); + Properties config = new Properties(); + confPath = confPath.startsWith("/") ? confPath : "/" + confPath; + InputStream in = this.getClass().getResourceAsStream(confPath); + try { + if(null != in){ + config.load(in); + // parse properties file + Set> set = config.entrySet(); + if(CollectionKit.isNotEmpty(set)){ + Iterator> it = set.iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + String key = entry.getKey().toString(); + String value = entry.getValue().toString(); + String fuKey = getWildcard(value); + if(null != fuKey && null != config.get(fuKey)){ + String fuValue = config.get(fuKey).toString(); + value = value.replaceAll("\\$\\{" + fuKey + "\\}", fuValue); + } + envMap.put(key, value); + } + LOGGER.info("load environment config [classpath:" + confPath + "]"); + } + } + } catch (IOException e) { + LOGGER.error("load environment config error", e); + } finally { + IOKit.closeQuietly(in); + } + return envMap; + } + + public static Environment load(String confPath) { + return new Environment(confPath); + } + + public Environment add(String confPath){ + this.envMap.putAll(loadMap(confPath)); + return this; + } + + private static String getWildcard(String str) { + if (null != str && str.indexOf("${") != -1) { + int start = str.indexOf("${"); + int end = str.indexOf("}"); + if (start != -1 && end != -1) { + return str.substring(start + 2, end); + } + } + return null; + } + + public Map getEnvMap(){ + return envMap; + } + + public String getString(String key) { + return envMap.get(key); + } + + public String getString(String key, String defaultValue) { + return null != envMap.get(key) ? envMap.get(key) : defaultValue; + } + + public Integer getInt(String key) { + String value = getString(key); + if (StringKit.isNotBlank(value)) { + return Integer.valueOf(value); + } + return null; + } + + public Integer getInt(String key, Integer defaultValue) { + return null != getInt(key) ? getInt(key) : defaultValue; + } + + public Long getLong(String key) { + String value = getString(key); + if (StringKit.isNotBlank(value)) { + return Long.valueOf(value); + } + return null; + } + + public Long getLong(String key, Long defaultValue) { + return null != getLong(key) ? getLong(key) : defaultValue; + } + + public Boolean getBoolean(String key) { + String value = getString(key); + if (StringKit.isNotBlank(value)) { + return Boolean.valueOf(value); + } + return null; + } + + public Boolean getBoolean(String key, boolean defaultValue) { + return null != getBoolean(key) ? getBoolean(key) : defaultValue; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/config/Config.java b/blade-kit/src/main/java/blade/kit/config/Config.java deleted file mode 100644 index 789ee38db..000000000 --- a/blade-kit/src/main/java/blade/kit/config/Config.java +++ /dev/null @@ -1,60 +0,0 @@ -package blade.kit.config; - -import java.util.Map; - -/** - * 配置文件顶层接口,用于获取配置文件的真实数据 - * - */ -public interface Config { - - /** - * 获取一个String类型的值 - * - * @param key 要获取的key - * @return 返回string - */ - String getString(String key); - - /** - * 获取一个Integer类型的值 - * - * @param key 要获取的key - * @return 返回int或者null - */ - Integer getInt(String key); - - /** - * 获取一个Long类型的值 - * - * @param key 要获取的key - * @return 返回long或者null - */ - Long getLong(String key); - - /** - * 获取一个Boolean类型的值 - * - * @param key 要获取的key - * @return 返回boolean或者null - */ - Boolean getBoolean(String key); - - /** - * 获取一个Double类型的值 - * - * @param key 要获取的key - * @return 返回double或者null - */ - Double getDouble(String key); - - Map getConfigMap(); - - /** - * 将获取到的配置文件转换成一个接口 - * - * @param type 接口类型 - * @return 返回接口对象 - */ - T get(Class type); -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/config/adapter/ConfigAdapter.java b/blade-kit/src/main/java/blade/kit/config/adapter/ConfigAdapter.java deleted file mode 100644 index fce3e1edf..000000000 --- a/blade-kit/src/main/java/blade/kit/config/adapter/ConfigAdapter.java +++ /dev/null @@ -1,104 +0,0 @@ -package blade.kit.config.adapter; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.HashMap; -import java.util.Map; - -import blade.kit.config.Config; - -/** - * 配置适配器,用于适配各种配置文件,解析成Config接口 - * 实现类需要完成的就是向configMap内赋值 - */ -public abstract class ConfigAdapter implements Config { - - /** - * 存储配置数据 - */ - protected Map configMap = new HashMap(); - - public String getString(String key) { - Object object = configMap.get(key); - if(null != object){ - return object.toString(); - } - return null; - } - - public Integer getInt(String key) { - String value = this.getString(key); - if(null != value){ - return Integer.parseInt(value); - } - return null; - } - - public Long getLong(String key) { - String value = this.getString(key); - if(null != value){ - return Long.parseLong(value); - } - return null; - } - - public Boolean getBoolean(String key) { - String value = this.getString(key); - if(null != value){ - return Boolean.parseBoolean(value); - } - return null; - } - - public Double getDouble(String key) { - String value = this.getString(key); - if(null != value){ - return Double.parseDouble(value); - } - return null; - } - - public T get(Class t) { - try { - @SuppressWarnings("unchecked") - T tobj = (T) Proxy.newProxyInstance(t.getClassLoader(), - new Class[] { t }, new InvocationHandler() { - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - - String method_name = method.getName(); - Class returnClazz = method.getReturnType(); - - if(returnClazz == String.class){ - return ConfigAdapter.this.getString(method_name); - } - - if (returnClazz == Integer.class || returnClazz == int.class) { - return ConfigAdapter.this.getInt(method_name); - } - - if(returnClazz == Long.class || returnClazz == long.class){ - return ConfigAdapter.this.getLong(method_name); - } - - if(returnClazz == Double.class || returnClazz == double.class){ - return ConfigAdapter.this.getDouble(method_name); - } - - if(returnClazz == Boolean.class || returnClazz == boolean.class){ - return ConfigAdapter.this.getBoolean(method_name); - } - return null; - } - }); - return tobj; - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } - return null; - } - - public abstract Config read(String conf); - -} diff --git a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java b/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java deleted file mode 100644 index 2815f1f6c..000000000 --- a/blade-kit/src/main/java/blade/kit/config/adapter/PropConfigAdapter.java +++ /dev/null @@ -1,77 +0,0 @@ -package blade.kit.config.adapter; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Set; - -import blade.kit.CollectionKit; -import blade.kit.IOKit; -import blade.kit.config.Config; -import blade.kit.config.exception.ConfigAdapterException; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - -/** - * 解析Properties配置文件 - * - */ -public class PropConfigAdapter extends ConfigAdapter { - - private static final Logger LOGGER = LoggerFactory.getLogger(PropConfigAdapter.class); - - @Override - public Config read(String prop_file) { - Properties props = new Properties(); - InputStream in = null; - try { - in = Thread.currentThread().getContextClassLoader().getResourceAsStream(prop_file); - if (in != null) { - props.load(in); - // 解析properties文件 - Set> set = props.entrySet(); - if(CollectionKit.isNotEmpty(set)){ - Iterator> it = set.iterator(); - while (it.hasNext()) { - Entry entry = it.next(); - String key = entry.getKey().toString(); - String value = entry.getValue().toString(); - String fuKey = getWildcard(value); - if(null != fuKey && null != props.get(fuKey)){ - String fuValue = props.get(fuKey).toString(); - value = value.replaceAll("\\$\\{" + fuKey + "\\}", fuValue); - } - configMap.put(key, value); - } - LOGGER.info("Loading config file [classpath:/" + prop_file + "]"); - return this; - } - } - return null; - } catch (IOException e) { - throw new ConfigAdapterException("load properties file error!"); - } finally { - IOKit.closeQuietly(in); - } - } - - private String getWildcard(String str){ - if(null != str && str.indexOf("${") != -1){ - int start = str.indexOf("${"); - int end = str.indexOf("}"); - if(start != -1 && end != -1){ - return str.substring(start + 2, end); - } - } - return null; - } - - @Override - public Map getConfigMap() { - return configMap; - } - -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/config/exception/ConfigAdapterException.java b/blade-kit/src/main/java/blade/kit/config/exception/ConfigAdapterException.java deleted file mode 100644 index 9b21b75a2..000000000 --- a/blade-kit/src/main/java/blade/kit/config/exception/ConfigAdapterException.java +++ /dev/null @@ -1,18 +0,0 @@ -package blade.kit.config.exception; - -/** - * 配置适配异常 - */ -public class ConfigAdapterException extends RuntimeException { - - private static final long serialVersionUID = 6118361499832602075L; - - public ConfigAdapterException(String msg){ - super(msg); - } - - public ConfigAdapterException(Throwable t){ - super(t); - } - -} diff --git a/blade-kit/src/main/java/blade/kit/config/exception/LoadException.java b/blade-kit/src/main/java/blade/kit/config/exception/LoadException.java deleted file mode 100644 index b082aeb8c..000000000 --- a/blade-kit/src/main/java/blade/kit/config/exception/LoadException.java +++ /dev/null @@ -1,18 +0,0 @@ -package blade.kit.config.exception; - -/** - * 配置加载异常 - */ -public class LoadException extends RuntimeException { - - private static final long serialVersionUID = 713951618562461059L; - - public LoadException(String msg){ - super(msg); - } - - public LoadException(Throwable t){ - super(t); - } - -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/config/loader/ConfigLoader.java b/blade-kit/src/main/java/blade/kit/config/loader/ConfigLoader.java deleted file mode 100644 index baa7a41f0..000000000 --- a/blade-kit/src/main/java/blade/kit/config/loader/ConfigLoader.java +++ /dev/null @@ -1,32 +0,0 @@ -package blade.kit.config.loader; - -import blade.kit.config.Config; -import blade.kit.config.adapter.ConfigAdapter; -import blade.kit.config.adapter.PropConfigAdapter; -import blade.kit.config.exception.LoadException; -import blade.kit.reflect.ReflectKit; - -/** - * 配置加载器,用于加载配置文件 - */ -public class ConfigLoader { - - public static Config load(String conf){ - return load(conf, PropConfigAdapter.class); - } - - public static Config load(String conf, Class adapter){ - - if(null == conf || conf.equals("")){ - throw new LoadException("the config file name is null"); - } - - if(null == adapter){ - throw new LoadException("the config adapter class is null"); - } - - ConfigAdapter configAdapter = ReflectKit.newBean(adapter); - - return configAdapter.read(conf); - } -} diff --git a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java index 0edc5c9b7..280ce38d6 100644 --- a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java +++ b/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java @@ -276,7 +276,7 @@ public static boolean isNot(Object obj, Object... mybe) { public static List scanPackageClass(String rootPackageName) { List classNames = new ArrayList(); try { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); + ClassLoader loader = ReflectKit.class.getClassLoader(); URL url = loader.getResource(rootPackageName.replace('.', '/')); ExceptionKit.makeRunTimeWhen(url == null, "package[%s] not found!", rootPackageName); diff --git a/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java b/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java index eb7a51843..2185c1324 100644 --- a/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java +++ b/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java @@ -144,7 +144,7 @@ public Set> getClassByAnnotation(String packageName, Class parent, C // 定义一个枚举的集合 并进行循环来处理这个目录下的URL Enumeration dirs; try { - dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); + dirs = getClass().getClassLoader().getResources(packageDirName); // 循环迭代下去 while (dirs.hasMoreElements()) { // 获取下一个元素 diff --git a/blade-kit/src/main/java/blade/kit/resource/DynamicClassReader.java b/blade-kit/src/main/java/blade/kit/resource/DynamicClassReader.java new file mode 100644 index 000000000..36acca3ca --- /dev/null +++ b/blade-kit/src/main/java/blade/kit/resource/DynamicClassReader.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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 blade.kit.resource; + +/** + * 动态根据环境获取ClassReader + * + * @author biezhi + * @since 1.0 + */ +public class DynamicClassReader { + + private static boolean IS_JAR_CONTEXT = false; + + private DynamicClassReader() { + } + + public static void init(){ + String rs = DynamicClassReader.class.getResource("").toString(); + if(rs.indexOf(".jar!") != -1){ + IS_JAR_CONTEXT = true; + } + } + + public static ClassReader getClassReader(){ + if(IS_JAR_CONTEXT){ + return new JarReaderImpl(); + } + return new ClassPathClassReader(); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java b/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java index f932bfc15..5f3318478 100644 --- a/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java +++ b/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java @@ -64,7 +64,7 @@ public Set> getClassByAnnotation(String packageName, Class parent, C // 定义一个枚举的集合 并进行循环来处理这个目录下的URL Enumeration dirs; try { - dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); + dirs = getClass().getClassLoader().getResources(packageDirName); // 循环迭代下去 while (dirs.hasMoreElements()) { // 获取下一个元素 @@ -91,7 +91,7 @@ private Set> getClasses(final URL url, final String packageDirName, Str // 从此jar包 得到一个枚举类 Enumeration eje = jarFile.entries( ); - // 同样的进行循环迭代 + // 同样的进行循环迭代 while (eje.hasMoreElements()) { // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 JarEntry entry = eje.nextElement(); diff --git a/pom.xml b/pom.xml index 1d640870a..ce2c89fdd 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 1.6 UTF-8 3.0.1 - 1.6.2 + 1.6.3 4.12 1.7.16 @@ -23,8 +23,8 @@ blade-kit blade-core - blade-startup - + blade-embed-jetty + From ea81f2dc1a6103ce3201b6e2f5b2f91eaa2b555c Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 23 Aug 2016 18:59:29 +0800 Subject: [PATCH 456/545] fix env is null --- LAST_VERSION.md | 18 +++++++++--------- .../java/com/blade/web/DispatcherServlet.java | 7 ++++++- .../com/blade/embedd/EmbedJettyServer.java | 8 +++++++- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index eacc47ac4..119cdada3 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -37,6 +37,15 @@ ``` +## [blade-embed-jetty](http://search.maven.org/#search%7Cga%7C1%7Cblade-embed-jetty) +```xml + +    com.bladejava +    blade-embed-jetty +    0.0.1 + +``` + ## [blade-jdbc](http://search.maven.org/#search%7Cga%7C1%7Cblade-jdbc) ```xml @@ -64,15 +73,6 @@ ``` -## [blade-startup](http://search.maven.org/#search%7Cga%7C1%7Cblade-startup) -```xml - -    com.bladejava -    blade-startup -    1.0.1 - -``` - ## [blade-patchca](http://search.maven.org/#search%7Cga%7C1%7Cblade-patchca) ```xml diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index e08cc1c29..560077ea3 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -30,6 +30,7 @@ import com.blade.ioc.IocApplication; import com.blade.route.RouteBuilder; +import blade.kit.Environment; import blade.kit.StringKit; import blade.kit.SystemKit; import blade.kit.logging.Logger; @@ -123,7 +124,11 @@ public void init(Blade blade) { new BladeBanner().print(); - String appName = blade.environment().getString("app.name", "Blade"); + Environment environment = blade.environment(); + String appName = "Blade"; + if(null != environment){ + appName = environment.getString("app.name", "Blade"); + } LOGGER.info(appName + " initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); } diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index 3ecfabb96..7f56c5c8e 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -25,9 +25,15 @@ public class EmbedJettyServer implements EmbedServer { private ServletContextHandler context; - private Environment environment = Blade.me().environment().add("jetty.properties"); + private Environment environment = null; public EmbedJettyServer() { + Environment bladeEnv = Blade.me().environment(); + if(null != bladeEnv){ + environment = bladeEnv.add("jetty.properties"); + } else{ + environment = Environment.load("jetty.properties"); + } } @Override From 4778313de36e0b2cbbf79f134d3d4f532da7ef33 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 23 Aug 2016 20:51:47 +0800 Subject: [PATCH 457/545] fix web env resources file not found --- blade-core/src/main/java/com/blade/Blade.java | 14 + .../main/java/com/blade/web/DispatchKit.java | 351 ++++++++-------- .../java/com/blade/web/DispatcherHandler.java | 395 +++++++++--------- .../java/com/blade/web/DispatcherServlet.java | 2 +- 4 files changed, 392 insertions(+), 370 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 960f203c3..aa082a5f9 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -76,6 +76,9 @@ public class Blade { // Xss defense private Xss xss; + // enableServer + private boolean enableServer = false; + private Set> plugins; private Blade() { @@ -650,6 +653,15 @@ public boolean isInit() { return isInit; } + public Blade enableServer(boolean enableServer) { + this.enableServer = enableServer; + return this; + } + + public boolean enableServer() { + return this.enableServer; + } + public boolean httpCache() { return bladeConfig.isHttpCache(); } @@ -660,10 +672,12 @@ public Set> plugins() { public void start(Class embedServer) throws Exception { embedServer.newInstance().startup(port, contextPath); + this.enableServer = true; } public void start(EmbedServer embedServer) throws Exception { embedServer.startup(port, contextPath); } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/DispatchKit.java b/blade-core/src/main/java/com/blade/web/DispatchKit.java index 09faa9ef8..9436dac86 100644 --- a/blade-core/src/main/java/com/blade/web/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/web/DispatchKit.java @@ -1,171 +1,180 @@ -package com.blade.web; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLDecoder; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletResponse; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.web.http.HttpException; -import com.blade.web.http.Response; - -import blade.kit.FileKit; -import blade.kit.StreamKit; -import blade.kit.StringKit; - -public class DispatchKit { - - public static File getWebroot(ServletContext sc) { - String dir = sc.getRealPath("/"); - if (dir == null) { - try { - URL url = sc.getResource("/"); - if (url != null && "file".equals(url.getProtocol())) { - dir = URLDecoder.decode(url.getFile(), "utf-8"); - } else { - throw new IllegalStateException("Can't get webroot dir, url = " + url); - } - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - return new File(dir); - } - - public static void setNoCache(HttpServletResponse response) { - // Http 1.0 header - response.setHeader("Buffer", "false"); - response.setHeader("Pragma", "no-cache"); - response.setDateHeader("Expires", 1L); - // Http 1.1 header - response.setHeader("Cache-Control", "no-cache, no-store, max-age=0"); - } - - public static void setFileDownloadHeader(HttpServletResponse response, String fileName, String contentType) { - if (contentType == null) { - contentType = "application/x-download"; - } - response.setContentType(contentType); - // 中文文件名支持 - try { - String encodedfileName = new String(fileName.getBytes(), "ISO8859-1"); - response.setHeader("Content-Disposition", "attachment; filename=" + encodedfileName); - } catch (UnsupportedEncodingException e) { - } - } - - private static Boolean isDev = null; - - /** - * Print Error Message - * @param err - * @param code - * @param response - */ - public static void printError(Throwable err, int code, Response response){ - if(null == isDev){ - isDev = Blade.me().isDev(); - } - err.printStackTrace(); - try { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final PrintWriter writer = new PrintWriter(baos); - - // If the developer mode, the error output to the page - if(isDev){ - writer.println(String.format(HTML, err.getClass() + " : " + err.getMessage())); - writer.println(); - err.printStackTrace(writer); - writer.println(END); - } else { - if(code == 404){ - String view404 = Blade.me().view404(); - if(StringKit.isNotBlank(view404)){ - response.render(view404); - return; - } else { - writer.write(err.getMessage()); - } - } else { - String view500 = Blade.me().view500(); - if(StringKit.isNotBlank(view500)){ - response.render(view500); - return; - } else { - writer.write(Const.INTERNAL_ERROR); - } - } - } - writer.close(); - response.status(code); - InputStream body = new ByteArrayInputStream(baos.toByteArray()); - print(body, response.outputStream()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Print - * @param body - * @param out - * @throws IOException - */ - public static void print(InputStream body, OutputStream out) throws IOException { - StreamKit.io(body, out, true, true); - /* - try { - int size = in.available(); - byte[] content = new byte[size]; - in.read(content); - out.write(content); - } finally { - in.close(); - out.close(); - }*/ - } - - - /** - * Print static file - * @param uri - * @param realpath - * @param httpResponse - */ - public static void printStatic(String uri, String realpath, Response response) { - try { - File file = new File(realpath); - if(FileKit.exist(file)){ - FileInputStream in = new FileInputStream(file); - print(in, response.outputStream()); - } else { - HttpException httpException = new HttpException(404, uri + " not found"); - DispatchKit.printError(httpException, 404, response); - } - } catch (FileNotFoundException e) { - DispatchKit.printError(e, 404, response); - } catch (IOException e) { - DispatchKit.printError(e, 500, response); - } - } - - private static final String HTML = "Blade Framework Error Page" - + "" - + "

%s

";
-	
-	
-	private static final String END = "
Blade-" + Const.BLADE_VERSION + "(Blade Framework
"; - -} +package com.blade.web; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.web.http.HttpException; +import com.blade.web.http.Response; + +import blade.kit.FileKit; +import blade.kit.StreamKit; +import blade.kit.StringKit; + +public class DispatchKit { + + static final boolean isWeb = Blade.me().enableServer(); + + private static Boolean isDev = null; + + public static File getWebRoot(ServletContext sc) { + String dir = sc.getRealPath("/"); + if (dir == null) { + try { + URL url = sc.getResource("/"); + if (url != null && "file".equals(url.getProtocol())) { + dir = URLDecoder.decode(url.getFile(), "utf-8"); + } else { + throw new IllegalStateException("Can't get webroot dir, url = " + url); + } + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + return new File(dir); + } + + public static void setNoCache(HttpServletResponse response) { + // Http 1.0 header + response.setHeader("Buffer", "false"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 1L); + // Http 1.1 header + response.setHeader("Cache-Control", "no-cache, no-store, max-age=0"); + } + + public static void setFileDownloadHeader(HttpServletResponse response, String fileName, String contentType) { + if (contentType == null) { + contentType = "application/x-download"; + } + response.setContentType(contentType); + // 中文文件名支持 + try { + String encodedfileName = new String(fileName.getBytes(), "ISO8859-1"); + response.setHeader("Content-Disposition", "attachment; filename=" + encodedfileName); + } catch (UnsupportedEncodingException e) { + } + } + + /** + * Print Error Message + * @param err + * @param code + * @param response + */ + public static void printError(Throwable err, int code, Response response){ + if(null == isDev){ + isDev = Blade.me().isDev(); + } + err.printStackTrace(); + try { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final PrintWriter writer = new PrintWriter(baos); + + // If the developer mode, the error output to the page + if(isDev){ + writer.println(String.format(HTML, err.getClass() + " : " + err.getMessage())); + writer.println(); + err.printStackTrace(writer); + writer.println(END); + } else { + if(code == 404){ + String view404 = Blade.me().view404(); + if(StringKit.isNotBlank(view404)){ + response.render(view404); + return; + } else { + writer.write(err.getMessage()); + } + } else { + String view500 = Blade.me().view500(); + if(StringKit.isNotBlank(view500)){ + response.render(view500); + return; + } else { + writer.write(Const.INTERNAL_ERROR); + } + } + } + writer.close(); + response.status(code); + InputStream body = new ByteArrayInputStream(baos.toByteArray()); + print(body, response.outputStream()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Print + * @param body + * @param out + * @throws IOException + */ + public static void print(InputStream body, OutputStream out) throws IOException { + StreamKit.io(body, out, true, true); + /* + try { + int size = in.available(); + byte[] content = new byte[size]; + in.read(content); + out.write(content); + } finally { + in.close(); + out.close(); + }*/ + } + + /** + * Print static file + * @param uri + * @param realpath + * @param httpResponse + */ + public static void printStatic(String uri, HttpServletRequest request, Response response) { + try { + String realpath = ""; + if(isWeb){ + realpath = request.getServletContext().getRealPath(uri); + } else{ + realpath = DispatchKit.class.getResource(uri).getPath(); + } + + File file = new File(realpath); + if(FileKit.exist(file)){ + FileInputStream in = new FileInputStream(file); + print(in, response.outputStream()); + } else { + HttpException httpException = new HttpException(404, uri + " not found"); + DispatchKit.printError(httpException, 404, response); + } + } catch (FileNotFoundException e) { + DispatchKit.printError(e, 404, response); + } catch (IOException e) { + DispatchKit.printError(e, 500, response); + } + } + + private static final String HTML = "Blade Framework Error Page" + + "" + + "

%s

";
+	
+	
+	private static final String END = "
Blade-" + Const.BLADE_VERSION + "(Blade Framework
"; + +} diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java index 2c7de88b5..07057483f 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -1,199 +1,198 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; - -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.context.BladeWebContext; -import com.blade.ioc.Ioc; -import com.blade.route.Route; -import com.blade.route.RouteHandler; -import com.blade.route.RouteMatcher; -import com.blade.route.Routers; -import com.blade.view.ModelAndView; -import com.blade.view.handle.RouteViewHandler; -import com.blade.web.http.HttpStatus; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.wrapper.ServletRequest; -import com.blade.web.http.wrapper.ServletResponse; - -import blade.kit.StringKit; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - -/** - * Synchronous request processor - * - * @author biezhi - * @since 1.0 - */ -public class DispatcherHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); - - private Ioc ioc; - - private Blade blade; - - private ServletContext servletContext; - - private RouteMatcher routeMatcher; - - private StaticFileFilter staticFileFilter; - - private RouteViewHandler routeViewHandler; - - public DispatcherHandler(ServletContext servletContext, Routers routers) { - this.servletContext = servletContext; - this.blade = Blade.me(); - this.ioc = blade.ioc(); - this.routeMatcher = new RouteMatcher(routers); - this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); - this.routeViewHandler = new RouteViewHandler(this.ioc); - } - - public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ - - // http method, GET/POST ... - String method = httpRequest.getMethod(); - - // reuqest uri - String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - - // Create Response - Response response = new ServletResponse(httpResponse, blade.templateEngine());; - - // If it is static, the resource is handed over to the filter - if(staticFileFilter.isStatic(uri)){ - LOGGER.debug("Request : {}\t{}", method, uri); - String realpath = httpRequest.getServletContext().getRealPath(uri); - DispatchKit.printStatic(uri, realpath, response); - return; - } - - LOGGER.info("Request : {}\t{}", method, uri); - - try { - - // Create Request - Request request = new ServletRequest(httpRequest); - - // Init Context - BladeWebContext.setContext(servletContext, request, response); - - Route route = routeMatcher.getRoute(method, uri); - - // If find it - if (route != null) { - request.setRoute(route); - - // before inteceptor - List befores = routeMatcher.getBefore(uri); - boolean result = invokeInterceptor(request, response, befores); - if(result){ - - // execute - this.routeHandle(request, response, route); - if(!request.isAbort()){ - // after inteceptor - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - } - } - } else { - // Not found - render404(response, uri); - } - return; - } catch (Exception e) { - DispatchKit.printError(e, 500, response); - } - return; - } - - /** - * 404 view render - * - * @param response response object - * @param uri 404 uri - */ - private void render404(Response response, String uri) { - String view404 = blade.view404(); - if(StringKit.isNotBlank(view404)){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", uri); - response.render( modelAndView ); - } else { - response.status(HttpStatus.NOT_FOUND); - response.html(String.format(Const.VIEW_NOTFOUND, uri)); - } - } - - /** - * Methods to perform the interceptor - * - * @param request request object - * @param response response object - * @param interceptors execute the interceptor list - * @return Return execute is ok - */ - private boolean invokeInterceptor(Request request, Response response, List interceptors) { - for(Route route : interceptors){ - boolean flag = routeViewHandler.intercept(request, response, route); - if(!flag){ - return false; - } - } - return true; - } - - /** - * Actual routing method execution - * - * @param request request object - * @param response response object - * @param route route object - */ - private void routeHandle(Request request, Response response, Route route){ - - Object target = route.getTarget(); - if(null == target){ - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - - request.initPathParams(route.getPath()); - - // Init context - BladeWebContext.setContext(servletContext, request, response); - if(route.getTargetType() == RouteHandler.class){ - RouteHandler routeHandler = (RouteHandler) target; - routeHandler.handle(request, response); - } else { - routeViewHandler.handle(request, response, route); - } - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; + +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.context.BladeWebContext; +import com.blade.ioc.Ioc; +import com.blade.route.Route; +import com.blade.route.RouteHandler; +import com.blade.route.RouteMatcher; +import com.blade.route.Routers; +import com.blade.view.ModelAndView; +import com.blade.view.handle.RouteViewHandler; +import com.blade.web.http.HttpStatus; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.ServletRequest; +import com.blade.web.http.wrapper.ServletResponse; + +import blade.kit.StringKit; +import blade.kit.logging.Logger; +import blade.kit.logging.LoggerFactory; + +/** + * Synchronous request processor + * + * @author biezhi + * @since 1.0 + */ +public class DispatcherHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); + + private Ioc ioc; + + private Blade blade; + + private ServletContext servletContext; + + private RouteMatcher routeMatcher; + + private StaticFileFilter staticFileFilter; + + private RouteViewHandler routeViewHandler; + + public DispatcherHandler(ServletContext servletContext, Routers routers) { + this.servletContext = servletContext; + this.blade = Blade.me(); + this.ioc = blade.ioc(); + this.routeMatcher = new RouteMatcher(routers); + this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); + this.routeViewHandler = new RouteViewHandler(this.ioc); + } + + public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ + + // http method, GET/POST ... + String method = httpRequest.getMethod(); + + // reuqest uri + String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); + + // Create Response + Response response = new ServletResponse(httpResponse, blade.templateEngine());; + + // If it is static, the resource is handed over to the filter + if(staticFileFilter.isStatic(uri)){ + LOGGER.debug("Request : {}\t{}", method, uri); + DispatchKit.printStatic(uri, httpRequest, response); + return; + } + + LOGGER.info("Request : {}\t{}", method, uri); + + try { + + // Create Request + Request request = new ServletRequest(httpRequest); + + // Init Context + BladeWebContext.setContext(servletContext, request, response); + + Route route = routeMatcher.getRoute(method, uri); + + // If find it + if (route != null) { + request.setRoute(route); + + // before inteceptor + List befores = routeMatcher.getBefore(uri); + boolean result = invokeInterceptor(request, response, befores); + if(result){ + + // execute + this.routeHandle(request, response, route); + if(!request.isAbort()){ + // after inteceptor + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + } + } + } else { + // Not found + render404(response, uri); + } + return; + } catch (Exception e) { + DispatchKit.printError(e, 500, response); + } + return; + } + + /** + * 404 view render + * + * @param response response object + * @param uri 404 uri + */ + private void render404(Response response, String uri) { + String view404 = blade.view404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(Const.VIEW_NOTFOUND, uri)); + } + } + + /** + * Methods to perform the interceptor + * + * @param request request object + * @param response response object + * @param interceptors execute the interceptor list + * @return Return execute is ok + */ + private boolean invokeInterceptor(Request request, Response response, List interceptors) { + for(Route route : interceptors){ + boolean flag = routeViewHandler.intercept(request, response, route); + if(!flag){ + return false; + } + } + return true; + } + + /** + * Actual routing method execution + * + * @param request request object + * @param response response object + * @param route route object + */ + private void routeHandle(Request request, Response response, Route route){ + + Object target = route.getTarget(); + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + + request.initPathParams(route.getPath()); + + // Init context + BladeWebContext.setContext(servletContext, request, response); + if(route.getTargetType() == RouteHandler.class){ + RouteHandler routeHandler = (RouteHandler) target; + routeHandler.handle(request, response); + } else { + routeViewHandler.handle(request, response, route); + } + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 560077ea3..8a18d6172 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -83,7 +83,7 @@ public void init(ServletConfig config) throws ServletException { long initStart = System.currentTimeMillis(); - blade.webRoot(DispatchKit.getWebroot(servletContext).getPath()); + blade.webRoot(DispatchKit.getWebRoot(servletContext).getPath()); BladeWebContext.setContext(servletContext); From 330f335030e1030d562db4a44487c81962200ed7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 24 Aug 2016 15:50:08 +0800 Subject: [PATCH 458/545] fix bug and upgrade blade to 1.6.4 --- LAST_VERSION.md | 16 +- README.md | 8 +- README_CN.md | 4 +- blade-auth/pom.xml | 40 + .../main/java/com/blade/auth}/CSRFConfig.java | 2 +- .../com/blade/auth}/CSRFTokenManager.java | 396 +- .../src/main/java/com/blade/auth}/Xss.java | 22 +- .../java/com/blade/auth}/package-info.java | 8 +- .../src/test/java/com/blade/auth/AppTest.java | 38 + blade-core/pom.xml | 19 +- blade-core/src/main/java/com/blade/Blade.java | 27 +- blade-core/src/main/java/com/blade/Const.java | 2 +- .../java/com/blade/context/BladeConfig.java | 5 +- .../java/com/blade/ioc/IocApplication.java | 14 +- .../src/main/java/com/blade/ioc/IocKit.java | 3 +- .../main/java/com/blade/ioc/SimpleIoc.java | 8 +- .../blade/ioc/loader/IocAnnotationLoader.java | 5 +- .../java/com/blade/route/RouteBuilder.java | 13 +- .../main/java/com/blade/route/Routers.java | 8 +- .../route/loader/AbstractFileRouteLoader.java | 3 +- .../java/com/blade/view/ModelAndView.java | 236 +- .../main/java/com/blade/view/ModelMap.java | 2 +- .../blade/view/handle/RouteViewHandler.java | 3 +- .../com/blade/view/template/JspEngine.java | 155 +- .../main/java/com/blade/web/BladeBanner.java | 6 +- .../main/java/com/blade/web/DispatchKit.java | 36 +- .../java/com/blade/web/DispatcherHandler.java | 8 +- .../java/com/blade/web/DispatcherServlet.java | 15 +- .../main/java/com/blade/web/http/Path.java | 4 +- .../web/http/wrapper/ServletRequest.java | 1174 ++-- .../web/http/wrapper/ServletResponse.java | 3 +- .../com/blade/web/multipart/Multipart.java | 2 +- blade-embed-jetty/pom.xml | 19 +- .../com/blade/embedd/EmbedJettyServer.java | 8 +- blade-kit/pom.xml | 29 +- .../main/java/blade/kit/io/package-info.java | 4 - .../blade/kit/logging/FeatureDetector.java | 65 - .../main/java/blade/kit/logging/Level.java | 22 - .../java/blade/kit/logging/Log4jLogger.java | 55 - .../main/java/blade/kit/logging/Logger.java | 25 - .../java/blade/kit/logging/LoggerFactory.java | 18 - .../java/blade/kit/logging/SimpleLogger.java | 222 - .../java/blade/kit/logging/Slf4jLogger.java | 58 - .../java/blade/kit/resource/package-info.java | 4 - .../java/blade/kit/timw/package-info.java | 4 - .../main/java/{ => com}/blade/kit/AES.java | 114 +- .../main/java/{ => com}/blade/kit/Assert.java | 2 +- .../main/java/{ => com}/blade/kit/Base64.java | 2 +- .../java/{ => com}/blade/kit/BeanKit.java | 2 +- .../java/{ => com}/blade/kit/CharKit.java | 2 +- .../{ => com}/blade/kit/ClassLoaderKit.java | 2 +- .../java/{ => com}/blade/kit/CloneKit.java | 2 +- .../{ => com}/blade/kit/CollectionKit.java | 2 +- .../java/{ => com}/blade/kit/DateKit.java | 2 +- .../main/java/{ => com}/blade/kit/Emptys.java | 2 +- .../java/{ => com}/blade/kit/EncrypKit.java | 2 +- .../java/{ => com}/blade/kit/Environment.java | 7 +- .../{ => com}/blade/kit/ExceptionKit.java | 2 +- .../java/{ => com}/blade/kit/FileKit.java | 4 +- .../java/{ => com}/blade/kit/HashidKit.java | 2 +- .../main/java/{ => com}/blade/kit/IOKit.java | 546 +- .../main/java/{ => com}/blade/kit/IpKit.java | 2 +- .../java/{ => com}/blade/kit/MimeParse.java | 456 +- .../java/{ => com}/blade/kit/ObjectKit.java | 6 +- .../java/{ => com}/blade/kit/PatternKit.java | 2 +- .../{ => com}/blade/kit/SerializeKit.java | 2 +- .../java/{ => com}/blade/kit/ShellKit.java | 2 +- .../java/{ => com}/blade/kit/StreamKit.java | 8 +- .../java/{ => com}/blade/kit/StringKit.java | 5740 ++++++++--------- .../java/{ => com}/blade/kit/SystemKit.java | 2 +- .../java/{ => com}/blade/kit/TaskKit.java | 6 +- .../java/{ => com}/blade/kit/TimeKit.java | 2 +- .../java/{ => com}/blade/kit/TimwKit.java | 7 +- .../main/java/{ => com}/blade/kit/XmlKit.java | 2 +- .../blade/kit/base/ThrowableKit.java | 410 +- .../kit/exception/ClassReaderException.java | 2 +- .../kit/exception/IllegalPathException.java | 2 +- .../blade/kit/exception/ReflectException.java | 2 +- .../blade/kit/http/ConnectionFactory.java | 2 +- .../java/{ => com}/blade/kit/http/Header.java | 2 +- .../{ => com}/blade/kit/http/HttpRequest.java | 6 +- .../blade/kit/http/HttpRequestException.java | 2 +- .../{ => com}/blade/kit/http/MethodType.java | 2 +- .../blade/kit/http/RequestOutputStream.java | 2 +- .../{ => com}/blade/kit/http/TokenQueue.java | 4 +- .../blade/kit/http/UploadProgress.java | 2 +- .../blade/kit/http/package-info.java | 8 +- .../blade/kit/io/AppendableWriter.java | 5 +- .../{ => com}/blade/kit/io/ByteArray.java | 4 +- .../blade/kit/io/ByteArrayOutputStream.java | 4 +- .../{ => com}/blade/kit/io/CharStreams.java | 10 +- .../kit/io/FastByteArrayOutputStream.java | 2 +- .../blade/kit/io/FastByteBuffer.java | 4 +- .../{ => com}/blade/kit/io/LineBuffer.java | 2 +- .../{ => com}/blade/kit/io/LineProcessor.java | 2 +- .../{ => com}/blade/kit/io/LineReader.java | 5 +- .../blade/kit/io/StringBuilderWriter.java | 2 +- .../java/com/blade/kit/io/package-info.java | 4 + .../java/{ => com}/blade/kit/json/JSON.java | 818 +-- .../{ => com}/blade/kit/json/JSONArray.java | 944 +-- .../{ => com}/blade/kit/json/JSONHandler.java | 526 +- .../{ => com}/blade/kit/json/JSONHelper.java | 509 +- .../{ => com}/blade/kit/json/JSONKit.java | 74 +- .../{ => com}/blade/kit/json/JSONLiteral.java | 194 +- .../{ => com}/blade/kit/json/JSONNumber.java | 194 +- .../{ => com}/blade/kit/json/JSONObject.java | 1894 +++--- .../{ => com}/blade/kit/json/JSONParser.java | 1022 +-- .../{ => com}/blade/kit/json/JSONString.java | 148 +- .../{ => com}/blade/kit/json/JSONValue.java | 782 +-- .../{ => com}/blade/kit/json/JSONWriter.java | 290 +- .../{ => com}/blade/kit/json/Location.java | 150 +- .../blade/kit/json/ParseException.java | 162 +- .../{ => com}/blade/kit/json/PrettyPrint.java | 314 +- .../blade/kit/json/WriterConfig.java | 100 +- .../blade/kit/json/WritingBuffer.java | 198 +- .../{ => com}/blade/kit/package-info.java | 8 +- .../blade/kit/reflect/ClassDefine.java | 2 +- .../blade/kit/reflect/ConvertKit.java | 2 +- .../blade/kit/reflect/ReflectKit.java | 15 +- .../kit/resource/AbstractClassReader.java | 11 +- .../kit/resource/ClassPathClassReader.java | 2 +- .../blade/kit/resource/ClassReader.java | 2 +- .../kit/resource/DynamicClassReader.java | 2 +- .../blade/kit/resource/JarReaderImpl.java | 13 +- .../com/blade/kit/resource/package-info.java | 4 + .../{ => com}/blade/kit/text/HTMLFilter.java | 2 +- .../{ => com}/blade/kit/timw/TimwCounter.java | 2 +- .../{ => com}/blade/kit/timw/TimwManager.java | 2 +- .../{ => com}/blade/kit/timw/TimwMonitor.java | 4 +- .../java/com/blade/kit/timw/package-info.java | 4 + .../java/com/blade/kit/HttpRequestTest.java | 2 +- .../src/test/java/com/blade/kit/JSONTest.java | 118 +- .../test/java/com/blade/kit/StringTest.java | 2 +- .../src/test/java/com/blade/kit/TaskTest.java | 2 +- pom.xml | 34 +- 135 files changed, 9190 insertions(+), 9602 deletions(-) create mode 100644 blade-auth/pom.xml rename {blade-core/src/main/java/com/blade/web/verify => blade-auth/src/main/java/com/blade/auth}/CSRFConfig.java (95%) rename {blade-core/src/main/java/com/blade/web/verify => blade-auth/src/main/java/com/blade/auth}/CSRFTokenManager.java (94%) rename {blade-core/src/main/java/com/blade/web/verify => blade-auth/src/main/java/com/blade/auth}/Xss.java (59%) rename {blade-core/src/main/java/com/blade/web/verify => blade-auth/src/main/java/com/blade/auth}/package-info.java (57%) create mode 100644 blade-auth/src/test/java/com/blade/auth/AppTest.java delete mode 100644 blade-kit/src/main/java/blade/kit/io/package-info.java delete mode 100644 blade-kit/src/main/java/blade/kit/logging/FeatureDetector.java delete mode 100644 blade-kit/src/main/java/blade/kit/logging/Level.java delete mode 100644 blade-kit/src/main/java/blade/kit/logging/Log4jLogger.java delete mode 100644 blade-kit/src/main/java/blade/kit/logging/Logger.java delete mode 100644 blade-kit/src/main/java/blade/kit/logging/LoggerFactory.java delete mode 100644 blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java delete mode 100644 blade-kit/src/main/java/blade/kit/logging/Slf4jLogger.java delete mode 100644 blade-kit/src/main/java/blade/kit/resource/package-info.java delete mode 100644 blade-kit/src/main/java/blade/kit/timw/package-info.java rename blade-kit/src/main/java/{ => com}/blade/kit/AES.java (94%) rename blade-kit/src/main/java/{ => com}/blade/kit/Assert.java (97%) rename blade-kit/src/main/java/{ => com}/blade/kit/Base64.java (97%) rename blade-kit/src/main/java/{ => com}/blade/kit/BeanKit.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/CharKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/ClassLoaderKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/CloneKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/CollectionKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/DateKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/Emptys.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/EncrypKit.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/Environment.java (94%) rename blade-kit/src/main/java/{ => com}/blade/kit/ExceptionKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/FileKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/HashidKit.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/IOKit.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/IpKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/MimeParse.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/ObjectKit.java (90%) rename blade-kit/src/main/java/{ => com}/blade/kit/PatternKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/SerializeKit.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/ShellKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/StreamKit.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/StringKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/SystemKit.java (97%) rename blade-kit/src/main/java/{ => com}/blade/kit/TaskKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/TimeKit.java (94%) rename blade-kit/src/main/java/{ => com}/blade/kit/TimwKit.java (91%) rename blade-kit/src/main/java/{ => com}/blade/kit/XmlKit.java (93%) rename blade-kit/src/main/java/{ => com}/blade/kit/base/ThrowableKit.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/exception/ClassReaderException.java (89%) rename blade-kit/src/main/java/{ => com}/blade/kit/exception/IllegalPathException.java (90%) rename blade-kit/src/main/java/{ => com}/blade/kit/exception/ReflectException.java (86%) rename blade-kit/src/main/java/{ => com}/blade/kit/http/ConnectionFactory.java (93%) rename blade-kit/src/main/java/{ => com}/blade/kit/http/Header.java (94%) rename blade-kit/src/main/java/{ => com}/blade/kit/http/HttpRequest.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/http/HttpRequestException.java (89%) rename blade-kit/src/main/java/{ => com}/blade/kit/http/MethodType.java (91%) rename blade-kit/src/main/java/{ => com}/blade/kit/http/RequestOutputStream.java (93%) rename blade-kit/src/main/java/{ => com}/blade/kit/http/TokenQueue.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/http/UploadProgress.java (90%) rename blade-kit/src/main/java/{ => com}/blade/kit/http/package-info.java (50%) rename blade-kit/src/main/java/{ => com}/blade/kit/io/AppendableWriter.java (93%) rename blade-kit/src/main/java/{ => com}/blade/kit/io/ByteArray.java (92%) rename blade-kit/src/main/java/{ => com}/blade/kit/io/ByteArrayOutputStream.java (94%) rename blade-kit/src/main/java/{ => com}/blade/kit/io/CharStreams.java (94%) rename blade-kit/src/main/java/{ => com}/blade/kit/io/FastByteArrayOutputStream.java (94%) rename blade-kit/src/main/java/{ => com}/blade/kit/io/FastByteBuffer.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/io/LineBuffer.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/io/LineProcessor.java (92%) rename blade-kit/src/main/java/{ => com}/blade/kit/io/LineReader.java (93%) rename blade-kit/src/main/java/{ => com}/blade/kit/io/StringBuilderWriter.java (96%) create mode 100644 blade-kit/src/main/java/com/blade/kit/io/package-info.java rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSON.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONArray.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONHandler.java (97%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONHelper.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONKit.java (88%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONLiteral.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONNumber.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONObject.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONParser.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONString.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONValue.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/JSONWriter.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/Location.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/ParseException.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/PrettyPrint.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/WriterConfig.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/json/WritingBuffer.java (96%) rename blade-kit/src/main/java/{ => com}/blade/kit/package-info.java (60%) rename blade-kit/src/main/java/{ => com}/blade/kit/reflect/ClassDefine.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/reflect/ConvertKit.java (92%) rename blade-kit/src/main/java/{ => com}/blade/kit/reflect/ReflectKit.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/resource/AbstractClassReader.java (95%) rename blade-kit/src/main/java/{ => com}/blade/kit/resource/ClassPathClassReader.java (93%) rename blade-kit/src/main/java/{ => com}/blade/kit/resource/ClassReader.java (94%) rename blade-kit/src/main/java/{ => com}/blade/kit/resource/DynamicClassReader.java (93%) rename blade-kit/src/main/java/{ => com}/blade/kit/resource/JarReaderImpl.java (94%) create mode 100644 blade-kit/src/main/java/com/blade/kit/resource/package-info.java rename blade-kit/src/main/java/{ => com}/blade/kit/text/HTMLFilter.java (97%) rename blade-kit/src/main/java/{ => com}/blade/kit/timw/TimwCounter.java (94%) rename blade-kit/src/main/java/{ => com}/blade/kit/timw/TimwManager.java (93%) rename blade-kit/src/main/java/{ => com}/blade/kit/timw/TimwMonitor.java (91%) create mode 100644 blade-kit/src/main/java/com/blade/kit/timw/package-info.java diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 119cdada3..05580996a 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -24,7 +24,7 @@     com.bladejava     blade-kit -    1.3.0 +    1.3.1 ``` @@ -33,7 +33,7 @@     com.bladejava     blade-core -    1.6.2 +    1.6.4 ``` @@ -42,7 +42,7 @@     com.bladejava     blade-embed-jetty -    0.0.1 +    0.0.2 ``` @@ -51,7 +51,7 @@     com.bladejava     blade-jdbc -    0.0.8 +    0.1.2 ``` @@ -82,11 +82,3 @@
``` -## [blade-oauth2](http://search.maven.org/#search%7Cga%7C1%7Cblade-oauth2) -```xml - -    com.bladejava -    blade-oauth2 -    1.0.2 - -``` diff --git a/README.md b/README.md index 6fd1f3486..33625c937 100644 --- a/README.md +++ b/README.md @@ -38,18 +38,18 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.3 + 1.6.4 com.bladejava blade-embed-jetty - 0.0.1 + 0.0.2 ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.3' -compile 'com.bladejava:blade-embed-jetty:0.0.1' +compile 'com.bladejava:blade-core:1.6.4' +compile 'com.bladejava:blade-embed-jetty:0.0.2' ``` Create `Main` method like this: diff --git a/README_CN.md b/README_CN.md index 89cddede7..5f73f0156 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,12 +38,12 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.6.3 + 1.6.4 com.bladejava blade-embed-jetty - 0.0.1 + 0.0.2 ``` diff --git a/blade-auth/pom.xml b/blade-auth/pom.xml new file mode 100644 index 000000000..fcf6e9319 --- /dev/null +++ b/blade-auth/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + com.bladejava + blade + 1.0 + + + blade-auth + 0.0.1 + blade-auth + http://maven.apache.org + + + + org.slf4j + slf4j-api + + + com.bladejava + blade-core + ${blade-core.version} + + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + junit + junit + test + + + diff --git a/blade-core/src/main/java/com/blade/web/verify/CSRFConfig.java b/blade-auth/src/main/java/com/blade/auth/CSRFConfig.java similarity index 95% rename from blade-core/src/main/java/com/blade/web/verify/CSRFConfig.java rename to blade-auth/src/main/java/com/blade/auth/CSRFConfig.java index e2afe8908..142383c68 100644 --- a/blade-core/src/main/java/com/blade/web/verify/CSRFConfig.java +++ b/blade-auth/src/main/java/com/blade/auth/CSRFConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.verify; +package com.blade.auth; /** * CSRF Config diff --git a/blade-core/src/main/java/com/blade/web/verify/CSRFTokenManager.java b/blade-auth/src/main/java/com/blade/auth/CSRFTokenManager.java similarity index 94% rename from blade-core/src/main/java/com/blade/web/verify/CSRFTokenManager.java rename to blade-auth/src/main/java/com/blade/auth/CSRFTokenManager.java index ee7a2f048..fa609c17c 100644 --- a/blade-core/src/main/java/com/blade/web/verify/CSRFTokenManager.java +++ b/blade-auth/src/main/java/com/blade/auth/CSRFTokenManager.java @@ -1,198 +1,198 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.verify; - -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.wrapper.Session; - -import blade.kit.HashidKit; -import blade.kit.StringKit; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - -/** - * CSRF token Manager - * - * @author biezhi - * @since 1.0 - */ -public class CSRFTokenManager { - - private static Logger LOGGER = LoggerFactory.getLogger(CSRFTokenManager.class); - - private static CSRFConfig config = new CSRFConfig(); - - private static HashidKit HASHID = new HashidKit(config.secret, config.length); - - private CSRFTokenManager() { - } - - public static void config(CSRFConfig config){ - CSRFTokenManager.config = config; - HASHID = new HashidKit(config.secret, config.length); - } - - /** - * Create a token - * - * @param request request object - * @param response response object - * @return return token - */ - public static String createToken(Request request, Response response) { - String token = null; - synchronized (request) { - Session session = request.session(); - String objToken = session.attribute(config.session); - - if(StringKit.isBlank(objToken)){ - token = createNewToken(request, response); - LOGGER.debug("create csrf_token:{}", token); - } else { - token = objToken; - session.attribute(config.session, token); - } - } - return token; - } - - /** - * Create a token - * - * @param request request object - * @param response response object - * @return return token - */ - public static String createNewToken(Request request, Response response) { - String token = null; - synchronized (request) { - Session session = request.session(); - session.removeAttribute(config.session); - token = HASHID.encode( System.currentTimeMillis() ); - session.attribute(config.session, token); - if(config.setHeader){ - response.header(config.header, token); - } - if(config.setCookie){ - response.cookie(config.cookiePath, config.cookie, token, config.expire, config.secured); - } - LOGGER.debug("create csrf_token:{}", token); - } - return token; - } - - public static boolean verify(Request request, Response response) { - // csrftoken attribute from session - String sToken = request.session().attribute(config.session); - if (sToken == null) { - // Generate new token into session - sToken = CSRFTokenManager.createToken(request, response); - return true; - } else { - String pToken = request.query(config.form); - if(config.setHeader){ - pToken = request.header(config.form); - } - if(config.setCookie){ - pToken = request.cookie(config.form); - } - if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { - return true; - } - } - - return false; - } - - /** - * According to form parameter verification - * - * @param request request object - * @param response response object - * @return return verify is success - */ - public static boolean verifyAsForm(Request request, Response response) { - // csrftoken attribute from session - String sToken = request.session().attribute(config.session); - if (sToken == null) { - // Generate new token into session - sToken = CSRFTokenManager.createToken(request, response); - return true; - } else { - String pToken = request.query(config.form); - if(config.setHeader){ - pToken = request.header(config.form); - } - if(config.setCookie){ - pToken = request.cookie(config.form); - } - if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { - return true; - } - } - - return false; - } - - /** - * According to header information verification - * - * @param request request object - * @param response response object - * @return return verify is success - */ - public static boolean verifyAsHeader(Request request, Response response) { - // csrftoken attribute from session - String sToken = request.session().attribute(config.session); - if (sToken == null) { - // Generate new token into session - sToken = CSRFTokenManager.createToken(request, response); - return true; - } else { - String pToken = request.header(config.header); - if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { - return true; - } - } - - return false; - } - - /** - * According to cookie verification - * - * @param request request object - * @param response response object - * @return return verify is success - */ - public static boolean verifyAsCookie(Request request, Response response) { - // csrftoken attribute from session - String sToken = request.session().attribute(config.session); - if (sToken == null) { - // Generate new token into session - sToken = CSRFTokenManager.createToken(request, response); - return true; - } else { - String pToken = request.cookie(config.cookie); - if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { - return true; - } - } - return false; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.auth; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.HashidKit; +import com.blade.kit.StringKit; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.Session; + +/** + * CSRF token Manager + * + * @author biezhi + * @since 1.0 + */ +public class CSRFTokenManager { + + private static Logger LOGGER = LoggerFactory.getLogger(CSRFTokenManager.class); + + private static CSRFConfig config = new CSRFConfig(); + + private static HashidKit HASHID = new HashidKit(config.secret, config.length); + + private CSRFTokenManager() { + } + + public static void config(CSRFConfig config){ + CSRFTokenManager.config = config; + HASHID = new HashidKit(config.secret, config.length); + } + + /** + * Create a token + * + * @param request request object + * @param response response object + * @return return token + */ + public static String createToken(Request request, Response response) { + String token = null; + synchronized (request) { + Session session = request.session(); + String objToken = session.attribute(config.session); + + if(StringKit.isBlank(objToken)){ + token = createNewToken(request, response); + LOGGER.debug("create csrf_token:{}", token); + } else { + token = objToken; + session.attribute(config.session, token); + } + } + return token; + } + + /** + * Create a token + * + * @param request request object + * @param response response object + * @return return token + */ + public static String createNewToken(Request request, Response response) { + String token = null; + synchronized (request) { + Session session = request.session(); + session.removeAttribute(config.session); + token = HASHID.encode( System.currentTimeMillis() ); + session.attribute(config.session, token); + if(config.setHeader){ + response.header(config.header, token); + } + if(config.setCookie){ + response.cookie(config.cookiePath, config.cookie, token, config.expire, config.secured); + } + LOGGER.debug("create csrf_token:{}", token); + } + return token; + } + + public static boolean verify(Request request, Response response) { + // csrftoken attribute from session + String sToken = request.session().attribute(config.session); + if (sToken == null) { + // Generate new token into session + sToken = CSRFTokenManager.createToken(request, response); + return true; + } else { + String pToken = request.query(config.form); + if(config.setHeader){ + pToken = request.header(config.form); + } + if(config.setCookie){ + pToken = request.cookie(config.form); + } + if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { + return true; + } + } + + return false; + } + + /** + * According to form parameter verification + * + * @param request request object + * @param response response object + * @return return verify is success + */ + public static boolean verifyAsForm(Request request, Response response) { + // csrftoken attribute from session + String sToken = request.session().attribute(config.session); + if (sToken == null) { + // Generate new token into session + sToken = CSRFTokenManager.createToken(request, response); + return true; + } else { + String pToken = request.query(config.form); + if(config.setHeader){ + pToken = request.header(config.form); + } + if(config.setCookie){ + pToken = request.cookie(config.form); + } + if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { + return true; + } + } + + return false; + } + + /** + * According to header information verification + * + * @param request request object + * @param response response object + * @return return verify is success + */ + public static boolean verifyAsHeader(Request request, Response response) { + // csrftoken attribute from session + String sToken = request.session().attribute(config.session); + if (sToken == null) { + // Generate new token into session + sToken = CSRFTokenManager.createToken(request, response); + return true; + } else { + String pToken = request.header(config.header); + if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { + return true; + } + } + + return false; + } + + /** + * According to cookie verification + * + * @param request request object + * @param response response object + * @return return verify is success + */ + public static boolean verifyAsCookie(Request request, Response response) { + // csrftoken attribute from session + String sToken = request.session().attribute(config.session); + if (sToken == null) { + // Generate new token into session + sToken = CSRFTokenManager.createToken(request, response); + return true; + } else { + String pToken = request.cookie(config.cookie); + if (StringKit.isNotBlank(pToken) && sToken.equals(pToken)) { + return true; + } + } + return false; + } + +} diff --git a/blade-core/src/main/java/com/blade/web/verify/Xss.java b/blade-auth/src/main/java/com/blade/auth/Xss.java similarity index 59% rename from blade-core/src/main/java/com/blade/web/verify/Xss.java rename to blade-auth/src/main/java/com/blade/auth/Xss.java index 7f8c1d59d..1b79074d4 100644 --- a/blade-core/src/main/java/com/blade/web/verify/Xss.java +++ b/blade-auth/src/main/java/com/blade/auth/Xss.java @@ -1,11 +1,11 @@ -package com.blade.web.verify; - -import blade.kit.text.HTMLFilter; - -public class Xss { - - public String filter(String str){ - return HTMLFilter.htmlSpecialChars(str); - } - -} +package com.blade.auth; + +import com.blade.kit.text.HTMLFilter; + +public class Xss { + + public String filter(String str){ + return HTMLFilter.htmlSpecialChars(str); + } + +} diff --git a/blade-core/src/main/java/com/blade/web/verify/package-info.java b/blade-auth/src/main/java/com/blade/auth/package-info.java similarity index 57% rename from blade-core/src/main/java/com/blade/web/verify/package-info.java rename to blade-auth/src/main/java/com/blade/auth/package-info.java index 23bd98799..8cc06e0e8 100644 --- a/blade-core/src/main/java/com/blade/web/verify/package-info.java +++ b/blade-auth/src/main/java/com/blade/auth/package-info.java @@ -1,4 +1,4 @@ -/** - * Authentication And Security - */ -package com.blade.web.verify; \ No newline at end of file +/** + * Authentication And Security + */ +package com.blade.auth; \ No newline at end of file diff --git a/blade-auth/src/test/java/com/blade/auth/AppTest.java b/blade-auth/src/test/java/com/blade/auth/AppTest.java new file mode 100644 index 000000000..45f271d54 --- /dev/null +++ b/blade-auth/src/test/java/com/blade/auth/AppTest.java @@ -0,0 +1,38 @@ +package com.blade.auth; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 350ae9e55..d6e84d747 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -3,25 +3,36 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 + com.bladejava - blade-root + blade 1.0 blade-core jar - ${blade.version} + ${blade-core.version} blade-core https://github.com/biezhi/blade/blade-core + + org.slf4j + slf4j-api + + + + org.slf4j + slf4j-log4j12 + + com.bladejava blade-kit - 1.3.0 + ${blade-kit.version} - + javax.servlet javax.servlet-api diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index aa082a5f9..90bb0388f 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -25,6 +25,9 @@ import com.blade.embedd.EmbedServer; import com.blade.ioc.Ioc; import com.blade.ioc.SimpleIoc; +import com.blade.kit.Assert; +import com.blade.kit.Environment; +import com.blade.kit.reflect.ReflectKit; import com.blade.plugin.Plugin; import com.blade.route.Route; import com.blade.route.RouteException; @@ -35,11 +38,6 @@ import com.blade.view.template.JspEngine; import com.blade.view.template.TemplateEngine; import com.blade.web.http.HttpMethod; -import com.blade.web.verify.Xss; - -import blade.kit.Assert; -import blade.kit.Environment; -import blade.kit.reflect.ReflectKit; /** * Blade Core Class @@ -73,9 +71,6 @@ public class Blade { // default context path private String contextPath = Const.DEFAULT_CONTEXTPATH; - // Xss defense - private Xss xss; - // enableServer private boolean enableServer = false; @@ -86,7 +81,6 @@ private Blade() { this.ioc = new SimpleIoc(); this.routers = new Routers(); this.templateEngine = new JspEngine(); - this.xss = new Xss(); this.plugins = new HashSet>(); } @@ -342,21 +336,6 @@ public RouteGroup group(String prefix){ return new RouteGroup(this, prefix); } - /** - * Setting default xss filter - * @param xss xss filter implement - * @return return blade - */ - public Blade xss(final Xss xss){ - Assert.notNull(xss); - this.xss = xss; - return this; - } - - public Xss xss(){ - return this.xss; - } - /** * Register a pre routing request interceptor * diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index fbd3f9eb2..b4249cd93 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -24,7 +24,7 @@ public interface Const { // current blade version - String BLADE_VERSION = "1.6.3"; + String BLADE_VERSION = "1.6.4"; // default embedd server context path String DEFAULT_CONTEXTPATH = "/"; diff --git a/blade-core/src/main/java/com/blade/context/BladeConfig.java b/blade-core/src/main/java/com/blade/context/BladeConfig.java index db6bbb0ab..695d67076 100644 --- a/blade-core/src/main/java/com/blade/context/BladeConfig.java +++ b/blade-core/src/main/java/com/blade/context/BladeConfig.java @@ -20,9 +20,8 @@ import java.util.Set; import com.blade.Blade; - -import blade.kit.Environment; -import blade.kit.StringKit; +import com.blade.kit.Environment; +import com.blade.kit.StringKit; /** * Blade Config Class diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 6aa424ab2..a423f439a 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -21,22 +21,22 @@ import java.util.Map; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.Blade; import com.blade.Bootstrap; import com.blade.ioc.annotation.Component; import com.blade.ioc.annotation.Service; +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; +import com.blade.kit.resource.ClassReader; +import com.blade.kit.resource.DynamicClassReader; import com.blade.plugin.Plugin; import com.blade.route.Route; import com.blade.route.RouteHandler; import com.blade.route.Routers; -import blade.kit.CollectionKit; -import blade.kit.StringKit; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; -import blade.kit.resource.ClassReader; -import blade.kit.resource.DynamicClassReader; - /** * IOC container, used to initialize the IOC object * diff --git a/blade-core/src/main/java/com/blade/ioc/IocKit.java b/blade-core/src/main/java/com/blade/ioc/IocKit.java index 459849517..fffc46a6f 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocKit.java +++ b/blade-core/src/main/java/com/blade/ioc/IocKit.java @@ -23,8 +23,7 @@ import com.blade.ioc.annotation.InjectWith; import com.blade.ioc.injector.FieldInjector; - -import blade.kit.reflect.ClassDefine; +import com.blade.kit.reflect.ClassDefine; /** * IocKit, get Bean diff --git a/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java index f5c04661a..2f67ac541 100644 --- a/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java @@ -22,11 +22,11 @@ import java.util.Map; import java.util.Set; -import com.blade.ioc.loader.IocLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import blade.kit.Assert; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; +import com.blade.ioc.loader.IocLoader; +import com.blade.kit.Assert; /** * The default IOC container implementation diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java index 9ad544519..7479617ea 100644 --- a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java @@ -23,9 +23,8 @@ import com.blade.ioc.SimpleIoc; import com.blade.ioc.annotation.Component; - -import blade.kit.resource.ClassReader; -import blade.kit.resource.DynamicClassReader; +import com.blade.kit.resource.ClassReader; +import com.blade.kit.resource.DynamicClassReader; public final class IocAnnotationLoader implements IocLoader { diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index 19e0dca3d..ba937c87c 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -19,20 +19,19 @@ import java.util.Set; import com.blade.Blade; -import com.blade.annotation.Intercept; import com.blade.annotation.Controller; +import com.blade.annotation.Intercept; import com.blade.annotation.Route; import com.blade.interceptor.Interceptor; +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassReader; +import com.blade.kit.resource.DynamicClassReader; import com.blade.web.http.HttpMethod; import com.blade.web.http.Request; import com.blade.web.http.Response; -import blade.kit.CollectionKit; -import blade.kit.StringKit; -import blade.kit.reflect.ReflectKit; -import blade.kit.resource.ClassReader; -import blade.kit.resource.DynamicClassReader; - /** * Route builder * diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 9c30e8a38..88c5f43a1 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -20,14 +20,14 @@ import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; import com.blade.web.http.HttpMethod; import com.blade.web.http.Request; import com.blade.web.http.Response; -import blade.kit.Assert; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - /** * Registration, management route * diff --git a/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java index 22f8269df..403d50151 100644 --- a/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java @@ -25,14 +25,13 @@ import java.util.List; import java.util.StringTokenizer; +import com.blade.kit.IOKit; import com.blade.route.Route; import com.blade.route.RouteException; import com.blade.web.http.HttpMethod; import com.blade.web.http.Request; import com.blade.web.http.Response; -import blade.kit.IOKit; - /** * Abstract loader implementation * diff --git a/blade-core/src/main/java/com/blade/view/ModelAndView.java b/blade-core/src/main/java/com/blade/view/ModelAndView.java index a3985bbc6..a2e8ca20c 100644 --- a/blade-core/src/main/java/com/blade/view/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/view/ModelAndView.java @@ -1,119 +1,119 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view; - -import java.util.Map; - -import blade.kit.CollectionKit; - -/** - * ModelAndView, Using templates and data - * - * @author biezhi - * @since 1.0 - */ -public class ModelAndView { - - /** - * Data object, the object is placed in the attribute httprequest - */ - private Map model; - - /** - * View Page - */ - private String view; - - /** - * Create an empty view - * - * @param view view page - */ - public ModelAndView(String view) { - super(); - this.model = CollectionKit.newHashMap(); - this.view = view; - } - - /** - * Create a model view object with data - * - * @param model model data - * @param view view page - */ - public ModelAndView(Map model, String view) { - super(); - this.model = model; - this.view = view; - } - - /** - * Add data to model - * - * @param key key - * @param value value - */ - public void add(String key, Object value){ - this.model.put(key, value); - } - - /** - * Remove model data - * - * @param key key - */ - public void remove(String key){ - this.model.remove(key); - } - - /** - * - * @return Return view page - */ - public String getView() { - return view; - } - - /** - * Setting view page - * - * @param view view page - */ - public void setView(String view) { - this.view = view; - } - - /** - * @return Return model map - */ - public Map getModel() { - return model; - } - - /** - * Setting model - * - * @param model Storage data map - */ - public void setModel(Map model) { - this.model = model; - } - - @Override - public String toString() { - return "view = " + view + ", model = " + model; - } +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view; + +import java.util.Map; + +import com.blade.kit.CollectionKit; + +/** + * ModelAndView, Using templates and data + * + * @author biezhi + * @since 1.0 + */ +public class ModelAndView { + + /** + * Data object, the object is placed in the attribute httprequest + */ + private Map model; + + /** + * View Page + */ + private String view; + + /** + * Create an empty view + * + * @param view view page + */ + public ModelAndView(String view) { + super(); + this.model = CollectionKit.newHashMap(); + this.view = view; + } + + /** + * Create a model view object with data + * + * @param model model data + * @param view view page + */ + public ModelAndView(Map model, String view) { + super(); + this.model = model; + this.view = view; + } + + /** + * Add data to model + * + * @param key key + * @param value value + */ + public void add(String key, Object value){ + this.model.put(key, value); + } + + /** + * Remove model data + * + * @param key key + */ + public void remove(String key){ + this.model.remove(key); + } + + /** + * + * @return Return view page + */ + public String getView() { + return view; + } + + /** + * Setting view page + * + * @param view view page + */ + public void setView(String view) { + this.view = view; + } + + /** + * @return Return model map + */ + public Map getModel() { + return model; + } + + /** + * Setting model + * + * @param model Storage data map + */ + public void setModel(Map model) { + this.model = model; + } + + @Override + public String toString() { + return "view = " + view + ", model = " + model; + } } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/view/ModelMap.java b/blade-core/src/main/java/com/blade/view/ModelMap.java index 4b631e2f0..a5a009551 100644 --- a/blade-core/src/main/java/com/blade/view/ModelMap.java +++ b/blade-core/src/main/java/com/blade/view/ModelMap.java @@ -1,7 +1,7 @@ package com.blade.view; +import com.blade.kit.Assert; import com.blade.web.http.Request; -import blade.kit.Assert; public class ModelMap { diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 506bb0189..f595d660f 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -10,6 +10,7 @@ import com.blade.annotation.PathVariable; import com.blade.annotation.RequestParam; import com.blade.ioc.Ioc; +import com.blade.kit.reflect.ReflectKit; import com.blade.route.Route; import com.blade.view.ModelAndView; import com.blade.view.ModelMap; @@ -19,8 +20,6 @@ import com.blade.web.http.wrapper.Session; import com.blade.web.multipart.FileItem; -import blade.kit.reflect.ReflectKit; - public class RouteViewHandler { private Ioc ioc; diff --git a/blade-core/src/main/java/com/blade/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/view/template/JspEngine.java index 609d6ab9e..6173395f3 100644 --- a/blade-core/src/main/java/com/blade/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/JspEngine.java @@ -1,77 +1,78 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; - -import java.io.IOException; -import java.io.Writer; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.blade.context.BladeWebContext; -import com.blade.view.ModelAndView; - -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - -/** - * JSP Render, Default Render - * - * @author biezhi - * @since 1.0 - */ -public final class JspEngine implements TemplateEngine { - - private static final Logger LOGGER = LoggerFactory.getLogger(JspEngine.class); - - private String viewPath = "/WEB-INF/"; - - public JspEngine() { - } - - public JspEngine(String viewPath) { - this.viewPath = viewPath; - } - - @Override - public void render(ModelAndView modelAndView, Writer writer) { - HttpServletRequest servletRequest = BladeWebContext.request().raw(); - HttpServletResponse servletResponse = BladeWebContext.response().raw(); - - try { - Map model = modelAndView.getModel(); - String realPath = viewPath + modelAndView.getView(); - - if (null != model && !model.isEmpty()) { - Set keys = model.keySet(); - for (String key : keys) { - servletRequest.setAttribute(key, model.get(key)); - } - } - servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); - } catch (ServletException e) { - e.printStackTrace(); - LOGGER.error("", e); - } catch (IOException e) { - e.printStackTrace(); - LOGGER.error("", e); - } - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.BladeWebContext; +import com.blade.view.ModelAndView; + + +/** + * JSP Render, Default Render + * + * @author biezhi + * @since 1.0 + */ +public final class JspEngine implements TemplateEngine { + + private static final Logger LOGGER = LoggerFactory.getLogger(JspEngine.class); + + private String viewPath = "/WEB-INF/"; + + public JspEngine() { + } + + public JspEngine(String viewPath) { + this.viewPath = viewPath; + } + + @Override + public void render(ModelAndView modelAndView, Writer writer) { + HttpServletRequest servletRequest = BladeWebContext.request().raw(); + HttpServletResponse servletResponse = BladeWebContext.response().raw(); + + try { + Map model = modelAndView.getModel(); + String realPath = viewPath + modelAndView.getView(); + + if (null != model && !model.isEmpty()) { + Set keys = model.keySet(); + for (String key : keys) { + servletRequest.setAttribute(key, model.get(key)); + } + } + servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); + } catch (ServletException e) { + e.printStackTrace(); + LOGGER.error("", e); + } catch (IOException e) { + e.printStackTrace(); + LOGGER.error("", e); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/web/BladeBanner.java b/blade-core/src/main/java/com/blade/web/BladeBanner.java index ce219b564..868a83733 100644 --- a/blade-core/src/main/java/com/blade/web/BladeBanner.java +++ b/blade-core/src/main/java/com/blade/web/BladeBanner.java @@ -1,9 +1,9 @@ package com.blade.web; -import com.blade.Const; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; +import com.blade.Const; public class BladeBanner { diff --git a/blade-core/src/main/java/com/blade/web/DispatchKit.java b/blade-core/src/main/java/com/blade/web/DispatchKit.java index 9436dac86..39a676423 100644 --- a/blade-core/src/main/java/com/blade/web/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/web/DispatchKit.java @@ -17,17 +17,21 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.Blade; import com.blade.Const; +import com.blade.kit.FileKit; +import com.blade.kit.StreamKit; +import com.blade.kit.StringKit; import com.blade.web.http.HttpException; import com.blade.web.http.Response; -import blade.kit.FileKit; -import blade.kit.StreamKit; -import blade.kit.StringKit; - public class DispatchKit { + private static final Logger LOGGER = LoggerFactory.getLogger(DispatchKit.class); + static final boolean isWeb = Blade.me().enableServer(); private static Boolean isDev = null; @@ -128,16 +132,6 @@ public static void printError(Throwable err, int code, Response response){ */ public static void print(InputStream body, OutputStream out) throws IOException { StreamKit.io(body, out, true, true); - /* - try { - int size = in.available(); - byte[] content = new byte[size]; - in.read(content); - out.write(content); - } finally { - in.close(); - out.close(); - }*/ } /** @@ -149,17 +143,21 @@ public static void print(InputStream body, OutputStream out) throws IOException public static void printStatic(String uri, HttpServletRequest request, Response response) { try { String realpath = ""; + InputStream ins = null; if(isWeb){ realpath = request.getServletContext().getRealPath(uri); + File file = new File(realpath); + if(FileKit.exist(file)){ + ins = new FileInputStream(file); + } } else{ - realpath = DispatchKit.class.getResource(uri).getPath(); + ins = DispatchKit.class.getResourceAsStream(uri); } - File file = new File(realpath); - if(FileKit.exist(file)){ - FileInputStream in = new FileInputStream(file); - print(in, response.outputStream()); + if(null != ins){ + print(ins, response.outputStream()); } else { + LOGGER.debug("request realpath is [{}]", realpath); HttpException httpException = new HttpException(404, uri + " not found"); DispatchKit.printError(httpException, 404, response); } diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java index 07057483f..4ddacc808 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -21,10 +21,14 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.Blade; import com.blade.Const; import com.blade.context.BladeWebContext; import com.blade.ioc.Ioc; +import com.blade.kit.StringKit; import com.blade.route.Route; import com.blade.route.RouteHandler; import com.blade.route.RouteMatcher; @@ -38,10 +42,6 @@ import com.blade.web.http.wrapper.ServletRequest; import com.blade.web.http.wrapper.ServletResponse; -import blade.kit.StringKit; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - /** * Synchronous request processor * diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 8a18d6172..92223099a 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -24,19 +24,19 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.Blade; import com.blade.Bootstrap; import com.blade.context.BladeWebContext; import com.blade.ioc.IocApplication; +import com.blade.kit.Environment; +import com.blade.kit.StringKit; +import com.blade.kit.SystemKit; +import com.blade.kit.resource.DynamicClassReader; import com.blade.route.RouteBuilder; -import blade.kit.Environment; -import blade.kit.StringKit; -import blade.kit.SystemKit; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; -import blade.kit.resource.DynamicClassReader; - /** * Blade Core DispatcherServlet * @@ -113,7 +113,6 @@ public void init(Blade blade) { // initialization ioc iocApplication = new IocApplication(blade); - iocApplication.init(); blade.init(); diff --git a/blade-core/src/main/java/com/blade/web/http/Path.java b/blade-core/src/main/java/com/blade/web/http/Path.java index 7f8ee06ef..fe28a2690 100644 --- a/blade-core/src/main/java/com/blade/web/http/Path.java +++ b/blade-core/src/main/java/com/blade/web/http/Path.java @@ -19,8 +19,8 @@ import java.net.URLDecoder; import java.util.List; -import blade.kit.CollectionKit; -import blade.kit.StringKit; +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; /** * Path URL diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index 4b54c3ab0..7329bd031 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -1,597 +1,579 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http.wrapper; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.ServletContext; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import com.blade.Blade; -import com.blade.route.Route; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.multipart.FileItem; -import com.blade.web.multipart.Multipart; -import com.blade.web.multipart.MultipartException; -import com.blade.web.multipart.MultipartHandler; - -import blade.kit.IOKit; -import blade.kit.ObjectKit; -import blade.kit.StringKit; - -/** - * ServletRequest - * - * @author biezhi - * @since 1.0 - */ -public class ServletRequest implements Request { - - private static final String USER_AGENT = "user-agent"; - - protected Route route; - - private HttpServletRequest request; - - protected Map pathParams = null; - - private Map multipartParams = null; - - private List files = null; - - private Session session = null; - - private Blade blade = null; - - private boolean isAbort = false; - - public ServletRequest(HttpServletRequest request) throws MultipartException, IOException { - this.request = request; - this.pathParams = new HashMap(); - this.multipartParams = new HashMap(); - this.files = new ArrayList(); - this.blade = Blade.me(); - init(); - } - - public ServletRequest init() throws IOException, MultipartException { - // retrieve multipart/form-data parameters - if (Multipart.isMultipartContent(request)) { - Multipart multipart = new Multipart(); - multipart.parse(request, new MultipartHandler() { - - @Override - public void handleFormItem(String name, String value) { - multipartParams.put( name, value ); - } - - @Override - public void handleFileItem(String name, FileItem fileItem) { - files.add(fileItem); - } - - }); - } - return this; - } - - private String join(String[] arr) { - String ret = ""; - for (String item : arr) { - ret += "," + item; - } - if (ret.length() > 0) { - ret = ret.substring(1); - } - return ret; - } - - @Override - public void initPathParams(String routePath) { - pathParams.clear(); - - List variables = getPathParam(routePath); - String regexPath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); - - String uri = Path.getRelativePath(uri(), contextPath()); - - Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(uri); - - if(matcher.matches()){ - // start index at 1 as group(0) always stands for the entire expression - for (int i=1, len = variables.size(); i <= len; i++) { - String value = matcher.group(i); - pathParams.put(variables.get(i-1), value); - } - } - } - - private List getPathParam(String routePath) { - List variables = new ArrayList(); - Matcher matcher = Pattern.compile(Path.VAR_REGEXP).matcher(routePath); - while (matcher.find()) { - variables.add(matcher.group(1)); - } - return variables; - } - - @Override - public HttpServletRequest raw() { - return request; - } - - @Override - public String host() { - return request.getServerName(); - } - - @Override - public String url() { - return request.getRequestURL().toString(); - } - - @Override - public String uri() { - return Path.fixPath(request.getRequestURI()); - } - - @Override - public String userAgent() { - return request.getHeader(USER_AGENT); - } - - @Override - public String pathInfo() { - return request.getPathInfo(); - } - - @Override - public String protocol() { - return request.getProtocol(); - } - - @Override - public String servletPath() { - return request.getServletPath(); - } - - @Override - public String contextPath() { - return request.getContextPath(); - } - - @Override - public ServletContext context() { - return request.getServletContext(); - } - - @Override - public Map pathParams() { - return pathParams; - } - - @Override - public String param(String name) { - String val = pathParams.get(name); - if(null != val && blade.enableXSS()){ - return blade.xss().filter(val); - } - return val; - } - - @Override - public String param(String name, String defaultValue) { - String val = pathParams.get(name); - if(null == val){ - val = defaultValue; - } - if (null != val && blade.enableXSS()) { - return blade.xss().filter(val); - } - return val; - } - - @Override - public Integer paramAsInt(String name) { - String value = param(name); - if (StringKit.isNotBlank(value)) { - return Integer.parseInt(value); - } - return null; - } - - @Override - public Long paramAsLong(String name) { - String value = param(name); - if (StringKit.isNotBlank(value)) { - return Long.parseLong(value); - } - return null; - } - - @Override - public Boolean paramAsBool(String name) { - String value = param(name); - if (StringKit.isNotBlank(value)) { - return Boolean.parseBoolean(value); - } - return null; - } - - @Override - public String queryString() { - return request.getQueryString(); - } - - @Override - public Map querys() { - Map params = new HashMap(); - - Map requestParams = request.getParameterMap(); - for (Map.Entry entry : requestParams.entrySet()) { - params.put( entry.getKey(), join(entry.getValue()) ); - } - params.putAll(multipartParams); - return Collections.unmodifiableMap(params); - } - - @Override - public String query(String name) { - String[] param = request.getParameterValues(name); - String val = null; - if (param != null) { - val = join(param); - } else { - val = multipartParams.get(name); - } - if(null != val && blade.enableXSS()){ - return blade.xss().filter(val); - } - return val; - } - - @Override - public String query(String name, String defaultValue) { - String[] param = request.getParameterValues(name); - String val = null; - if (param != null) { - val = join(param); - } else { - val = multipartParams.get(name); - } - if(null == val){ - val = defaultValue; - } - if(blade.enableXSS()){ - return blade.xss().filter(val); - } - return val; - } - - @Override - public Integer queryAsInt(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { - return Integer.parseInt(value); - } - return null; - } - - @Override - public Long queryAsLong(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { - return Long.parseLong(value); - } - return null; - } - - @Override - public Boolean queryAsBool(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isBoolean(value)) { - return Boolean.parseBoolean(value); - } - return null; - } - - @Override - public Float queryAsFloat(String name) { - String value = query(name); - if (StringKit.isNotBlank(value)) { - try { - return Float.parseFloat(value); - } catch (NumberFormatException e) { - } - } - return null; - } - - @Override - public Double queryAsDouble(String name) { - String value = query(name); - if (StringKit.isNotBlank(value)) { - try { - return Double.parseDouble(value); - } catch (NumberFormatException e) { - } - } - return null; - } - - @Override - public String method() { - return request.getMethod(); - } - - @Override - public HttpMethod httpMethod() { - return HttpMethod.valueOf(request.getMethod().toUpperCase()); - } - - @Override - public String address() { - return request.getRemoteAddr(); - } - - @Override - public Session session() { - if (session == null) { - session = new Session(request.getSession()); - } - return session; - } - - @Override - public Session session(boolean create) { - if (session == null) { - HttpSession httpSession = request.getSession(create); - if (httpSession != null) { - session = new Session(httpSession); - } - } - return session; - } - - @Override - public void attribute(String name, Object value) { - request.setAttribute(name, value); - } - - @SuppressWarnings("unchecked") - @Override - public T attribute(String name) { - Object object = request.getAttribute(name); - if(null != object){ - return (T) object; - } - return null; - } - - @Override - public Set attributes() { - Set attrList = new HashSet(); - Enumeration attributes = (Enumeration) request.getAttributeNames(); - while (attributes.hasMoreElements()) { - attrList.add(attributes.nextElement()); - } - return attrList; - } - - @Override - public String contentType() { - return request.getContentType(); - } - - @Override - public int port() { - return request.getServerPort(); - } - - @Override - public boolean isSecure() { - return request.isSecure(); - } - - @Override - public boolean isAjax() { - if (request.getHeader("x-requested-with") == null) { - return false; - } - return "XMLHttpRequest".equals(request.getHeader("x-requested-with")); - } - - @Override - public Map cookies() { - javax.servlet.http.Cookie[] servletCookies = request.getCookies(); - - Map cookies = new HashMap(); - for (javax.servlet.http.Cookie c : servletCookies) { - cookies.put( c.getName(), map(c) ); - } - - return Collections.unmodifiableMap(cookies); - } - - private Cookie map(Cookie servletCookie) { - Cookie cookie = new Cookie(servletCookie.getName(), servletCookie.getValue()); - cookie.setMaxAge(servletCookie.getMaxAge()); - cookie.setHttpOnly(servletCookie.isHttpOnly()); - String path = servletCookie.getPath(); - if(null != path){ - cookie.setPath(path); - } - String domain = servletCookie.getDomain(); - if(null != domain){ - cookie.setDomain(domain); - } - cookie.setSecure(servletCookie.getSecure()); - return cookie; - } - - @Override - public String cookie(String name) { - Cookie cookie = cookieRaw(name); - if(null != cookie){ - return cookie.getValue(); - } - return null; - } - - @Override - public Cookie cookieRaw(String name) { - javax.servlet.http.Cookie[] servletCookies = request.getCookies(); - - if (servletCookies == null) { - return null; - } - - for (javax.servlet.http.Cookie c : servletCookies) { - if (c.getName().equals(name)) { - return map(c); - } - } - return null; - } - - @Override - public Map headers() { - Enumeration servletHeaders = request.getHeaderNames(); - Map headers = new HashMap(); - while(servletHeaders.hasMoreElements()) { - String headerName = servletHeaders.nextElement(); - headers.put(headerName, request.getHeader(headerName)); - } - return headers; - } - - @Override - public String header(String name) { - return request.getHeader(name); - } - - @Override - public void encoding(String encoding) { - try { - request.setCharacterEncoding(encoding); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - - @Override - public void setRoute(Route route) { - this.route = route; - initPathParams(route.getPath()); - } - - @Override - public Route route() { - return this.route; - } - - @Override - public void abort() { - this.isAbort = true; - } - - @Override - public boolean isAbort() { - return this.isAbort; - } - - @Override - public T model(String slug, Class clazz) { - if(StringKit.isNotBlank(slug) && null != clazz){ - return ObjectKit.model(slug, clazz, querys()); - } - return null; - } - - @Override - public FileItem[] files() { - FileItem[] fileParts = new FileItem[files.size()]; - for (int i=0; i < files.size(); i++) { - fileParts[i] = files.get(i); - } - return fileParts; - } - - @Override - public BodyParser body() { - return new BodyParser() { - @Override - public String asString() { - try { - BufferedReader reader = new BufferedReader( new InputStreamReader(request.getInputStream()) ); - StringBuilder sb = new StringBuilder(); - String line = reader.readLine(); - while (line != null) { - sb.append(line + "\n"); - line = reader.readLine(); - } - reader.close(); - String data = sb.toString(); - - return data; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public InputStream asInputStream() { - try { - return request.getInputStream(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public byte[] asByte() { - try { - return IOKit.toByteArray(request.getInputStream()); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - }; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http.wrapper; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.ServletContext; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import com.blade.kit.IOKit; +import com.blade.kit.ObjectKit; +import com.blade.kit.StringKit; +import com.blade.route.Route; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.multipart.FileItem; +import com.blade.web.multipart.Multipart; +import com.blade.web.multipart.MultipartException; +import com.blade.web.multipart.MultipartHandler; + +/** + * ServletRequest + * + * @author biezhi + * @since 1.0 + */ +public class ServletRequest implements Request { + + private static final String USER_AGENT = "user-agent"; + + protected Route route; + + private HttpServletRequest request; + + protected Map pathParams = null; + + private Map multipartParams = null; + + private List files = null; + + private Session session = null; + + private boolean isAbort = false; + + public ServletRequest(HttpServletRequest request) throws MultipartException, IOException { + this.request = request; + this.pathParams = new HashMap(); + this.multipartParams = new HashMap(); + this.files = new ArrayList(); + init(); + } + + public ServletRequest init() throws IOException, MultipartException { + // retrieve multipart/form-data parameters + if (Multipart.isMultipartContent(request)) { + Multipart multipart = new Multipart(); + multipart.parse(request, new MultipartHandler() { + + @Override + public void handleFormItem(String name, String value) { + multipartParams.put( name, value ); + } + + @Override + public void handleFileItem(String name, FileItem fileItem) { + files.add(fileItem); + } + + }); + } + return this; + } + + private String join(String[] arr) { + String ret = ""; + for (String item : arr) { + ret += "," + item; + } + if (ret.length() > 0) { + ret = ret.substring(1); + } + return ret; + } + + @Override + public void initPathParams(String routePath) { + pathParams.clear(); + + List variables = getPathParam(routePath); + String regexPath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); + + String uri = Path.getRelativePath(uri(), contextPath()); + + Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(uri); + + if(matcher.matches()){ + // start index at 1 as group(0) always stands for the entire expression + for (int i=1, len = variables.size(); i <= len; i++) { + String value = matcher.group(i); + pathParams.put(variables.get(i-1), value); + } + } + } + + private List getPathParam(String routePath) { + List variables = new ArrayList(); + Matcher matcher = Pattern.compile(Path.VAR_REGEXP).matcher(routePath); + while (matcher.find()) { + variables.add(matcher.group(1)); + } + return variables; + } + + @Override + public HttpServletRequest raw() { + return request; + } + + @Override + public String host() { + return request.getServerName(); + } + + @Override + public String url() { + return request.getRequestURL().toString(); + } + + @Override + public String uri() { + return Path.fixPath(request.getRequestURI()); + } + + @Override + public String userAgent() { + return request.getHeader(USER_AGENT); + } + + @Override + public String pathInfo() { + return request.getPathInfo(); + } + + @Override + public String protocol() { + return request.getProtocol(); + } + + @Override + public String servletPath() { + return request.getServletPath(); + } + + @Override + public String contextPath() { + return request.getContextPath(); + } + + @Override + public ServletContext context() { + return request.getServletContext(); + } + + @Override + public Map pathParams() { + return pathParams; + } + + @Override + public String param(String name) { + return pathParams.get(name); + } + + @Override + public String param(String name, String defaultValue) { + String val = pathParams.get(name); + if(null == val){ + val = defaultValue; + } + return val; + } + + @Override + public Integer paramAsInt(String name) { + String value = param(name); + if (StringKit.isNotBlank(value)) { + return Integer.parseInt(value); + } + return null; + } + + @Override + public Long paramAsLong(String name) { + String value = param(name); + if (StringKit.isNotBlank(value)) { + return Long.parseLong(value); + } + return null; + } + + @Override + public Boolean paramAsBool(String name) { + String value = param(name); + if (StringKit.isNotBlank(value)) { + return Boolean.parseBoolean(value); + } + return null; + } + + @Override + public String queryString() { + return request.getQueryString(); + } + + @Override + public Map querys() { + Map params = new HashMap(); + + Map requestParams = request.getParameterMap(); + for (Map.Entry entry : requestParams.entrySet()) { + params.put( entry.getKey(), join(entry.getValue()) ); + } + params.putAll(multipartParams); + return Collections.unmodifiableMap(params); + } + + @Override + public String query(String name) { + String[] param = request.getParameterValues(name); + String val = null; + if (param != null) { + val = join(param); + } else { + val = multipartParams.get(name); + } + return val; + } + + @Override + public String query(String name, String defaultValue) { + String[] param = request.getParameterValues(name); + String val = null; + if (param != null) { + val = join(param); + } else { + val = multipartParams.get(name); + } + if(null == val){ + val = defaultValue; + } + return val; + } + + @Override + public Integer queryAsInt(String name) { + String value = query(name); + if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { + return Integer.parseInt(value); + } + return null; + } + + @Override + public Long queryAsLong(String name) { + String value = query(name); + if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { + return Long.parseLong(value); + } + return null; + } + + @Override + public Boolean queryAsBool(String name) { + String value = query(name); + if (StringKit.isNotBlank(value) && StringKit.isBoolean(value)) { + return Boolean.parseBoolean(value); + } + return null; + } + + @Override + public Float queryAsFloat(String name) { + String value = query(name); + if (StringKit.isNotBlank(value)) { + try { + return Float.parseFloat(value); + } catch (NumberFormatException e) { + } + } + return null; + } + + @Override + public Double queryAsDouble(String name) { + String value = query(name); + if (StringKit.isNotBlank(value)) { + try { + return Double.parseDouble(value); + } catch (NumberFormatException e) { + } + } + return null; + } + + @Override + public String method() { + return request.getMethod(); + } + + @Override + public HttpMethod httpMethod() { + return HttpMethod.valueOf(request.getMethod().toUpperCase()); + } + + @Override + public String address() { + return request.getRemoteAddr(); + } + + @Override + public Session session() { + if (session == null) { + session = new Session(request.getSession()); + } + return session; + } + + @Override + public Session session(boolean create) { + if (session == null) { + HttpSession httpSession = request.getSession(create); + if (httpSession != null) { + session = new Session(httpSession); + } + } + return session; + } + + @Override + public void attribute(String name, Object value) { + request.setAttribute(name, value); + } + + @SuppressWarnings("unchecked") + @Override + public T attribute(String name) { + Object object = request.getAttribute(name); + if(null != object){ + return (T) object; + } + return null; + } + + @Override + public Set attributes() { + Set attrList = new HashSet(); + Enumeration attributes = (Enumeration) request.getAttributeNames(); + while (attributes.hasMoreElements()) { + attrList.add(attributes.nextElement()); + } + return attrList; + } + + @Override + public String contentType() { + return request.getContentType(); + } + + @Override + public int port() { + return request.getServerPort(); + } + + @Override + public boolean isSecure() { + return request.isSecure(); + } + + @Override + public boolean isAjax() { + if (request.getHeader("x-requested-with") == null) { + return false; + } + return "XMLHttpRequest".equals(request.getHeader("x-requested-with")); + } + + @Override + public Map cookies() { + javax.servlet.http.Cookie[] servletCookies = request.getCookies(); + + Map cookies = new HashMap(); + for (javax.servlet.http.Cookie c : servletCookies) { + cookies.put( c.getName(), map(c) ); + } + + return Collections.unmodifiableMap(cookies); + } + + private Cookie map(Cookie servletCookie) { + Cookie cookie = new Cookie(servletCookie.getName(), servletCookie.getValue()); + cookie.setMaxAge(servletCookie.getMaxAge()); + cookie.setHttpOnly(servletCookie.isHttpOnly()); + String path = servletCookie.getPath(); + if(null != path){ + cookie.setPath(path); + } + String domain = servletCookie.getDomain(); + if(null != domain){ + cookie.setDomain(domain); + } + cookie.setSecure(servletCookie.getSecure()); + return cookie; + } + + @Override + public String cookie(String name) { + Cookie cookie = cookieRaw(name); + if(null != cookie){ + return cookie.getValue(); + } + return null; + } + + @Override + public Cookie cookieRaw(String name) { + javax.servlet.http.Cookie[] servletCookies = request.getCookies(); + + if (servletCookies == null) { + return null; + } + + for (javax.servlet.http.Cookie c : servletCookies) { + if (c.getName().equals(name)) { + return map(c); + } + } + return null; + } + + @Override + public Map headers() { + Enumeration servletHeaders = request.getHeaderNames(); + Map headers = new HashMap(); + while(servletHeaders.hasMoreElements()) { + String headerName = servletHeaders.nextElement(); + headers.put(headerName, request.getHeader(headerName)); + } + return headers; + } + + @Override + public String header(String name) { + return request.getHeader(name); + } + + @Override + public void encoding(String encoding) { + try { + request.setCharacterEncoding(encoding); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + @Override + public void setRoute(Route route) { + this.route = route; + initPathParams(route.getPath()); + } + + @Override + public Route route() { + return this.route; + } + + @Override + public void abort() { + this.isAbort = true; + } + + @Override + public boolean isAbort() { + return this.isAbort; + } + + @Override + public T model(String slug, Class clazz) { + if(StringKit.isNotBlank(slug) && null != clazz){ + return ObjectKit.model(slug, clazz, querys()); + } + return null; + } + + @Override + public FileItem[] files() { + FileItem[] fileParts = new FileItem[files.size()]; + for (int i=0; i < files.size(); i++) { + fileParts[i] = files.get(i); + } + return fileParts; + } + + @Override + public BodyParser body() { + return new BodyParser() { + @Override + public String asString() { + try { + BufferedReader reader = new BufferedReader( new InputStreamReader(request.getInputStream()) ); + StringBuilder sb = new StringBuilder(); + String line = reader.readLine(); + while (line != null) { + sb.append(line + "\n"); + line = reader.readLine(); + } + reader.close(); + String data = sb.toString(); + + return data; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public InputStream asInputStream() { + try { + return request.getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public byte[] asByte() { + try { + return IOKit.toByteArray(request.getInputStream()); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + }; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index 0f6dc5409..ce26212e5 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletResponse; import com.blade.context.BladeWebContext; +import com.blade.kit.Assert; import com.blade.view.ModelAndView; import com.blade.view.template.TemplateEngine; import com.blade.web.http.HttpStatus; @@ -31,8 +32,6 @@ import com.blade.web.http.Request; import com.blade.web.http.Response; -import blade.kit.Assert; - /** * ServletResponse * diff --git a/blade-core/src/main/java/com/blade/web/multipart/Multipart.java b/blade-core/src/main/java/com/blade/web/multipart/Multipart.java index f6d56cd98..3e33c72f3 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/Multipart.java +++ b/blade-core/src/main/java/com/blade/web/multipart/Multipart.java @@ -26,7 +26,7 @@ import javax.servlet.http.HttpServletRequest; -import blade.kit.IOKit; +import com.blade.kit.IOKit; /** * Multipart diff --git a/blade-embed-jetty/pom.xml b/blade-embed-jetty/pom.xml index 4f4357fd7..63543267a 100644 --- a/blade-embed-jetty/pom.xml +++ b/blade-embed-jetty/pom.xml @@ -5,26 +5,30 @@ 4.0.0 com.bladejava - blade-root + blade 1.0 + blade-embed-jetty - 0.0.1 + ${blade-embed-jetty.version} blade-embed-jetty http://maven.apache.org - UTF-8 - 3.1.0 9.2.12.v20150709 - + - + + + org.slf4j + slf4j-api + + com.bladejava blade-core - ${blade.version} + ${blade-core.version} @@ -44,6 +48,7 @@ jetty-webapp ${jetty.version} + diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index 7f56c5c8e..03bf8b0e7 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -6,15 +6,14 @@ import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.blade.Blade; import com.blade.Const; +import com.blade.kit.Environment; import com.blade.web.DispatcherServlet; -import blade.kit.Environment; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - public class EmbedJettyServer implements EmbedServer { private static final Logger LOGGER = LoggerFactory.getLogger(EmbedJettyServer.class); @@ -34,6 +33,7 @@ public EmbedJettyServer() { } else{ environment = Environment.load("jetty.properties"); } + Blade.me().enableServer(true); } @Override diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index 7aa038445..bc2d4bab8 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -5,54 +5,49 @@ 4.0.0 com.bladejava - blade-root + blade 1.0 - + blade-kit jar - 1.3.0 + ${blade-kit.version} blade-kit https://github.com/biezhi/blade/tree/master/blade-kit - - - 3.0.1 - - + - - junit - junit - + org.slf4j slf4j-api - provided + - log4j - log4j - 1.2.17 - provided + junit + junit + dom4j dom4j 1.6.1 provided + jaxen jaxen 1.1.6 provided + javax.servlet javax.servlet-api ${servlet.version} provided + diff --git a/blade-kit/src/main/java/blade/kit/io/package-info.java b/blade-kit/src/main/java/blade/kit/io/package-info.java deleted file mode 100644 index d227577ed..000000000 --- a/blade-kit/src/main/java/blade/kit/io/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * IO操作包 - */ -package blade.kit.io; \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/FeatureDetector.java b/blade-kit/src/main/java/blade/kit/logging/FeatureDetector.java deleted file mode 100644 index e233cc1fe..000000000 --- a/blade-kit/src/main/java/blade/kit/logging/FeatureDetector.java +++ /dev/null @@ -1,65 +0,0 @@ -package blade.kit.logging; - -public final class FeatureDetector { - - private FeatureDetector() { - } - - static { - setCacheUnderscoreToCamelcaseEnabled(true); // enabled by default - } - - private static Boolean jodaTimeAvailable; - private static Boolean slf4jAvailable; - private static Boolean log4jAvailable; - private static Boolean oracleAvailable; - private static boolean cacheUnderscoreToCamelcaseEnabled; - - public static boolean isPresent(String className) { - try { - // what's wrong with old plain Class.forName - // this code supposed to work everywhere including containers - Class.forName(className); - // getClassLoader().loadClass(className); - return true; - } catch (Throwable ex) { - return false; - } - } - - public static boolean isJodaTimeAvailable() { - if (jodaTimeAvailable == null) { - jodaTimeAvailable = isPresent("org.joda.time.DateTime"); - } - return jodaTimeAvailable; - } - - public static boolean isSlf4jAvailable() { - if (slf4jAvailable == null) { - slf4jAvailable = isPresent("org.slf4j.Logger"); - } - return slf4jAvailable; - } - - public static boolean isLog4jAvailable() { - if (log4jAvailable == null) { - log4jAvailable = isPresent("org.apache.log4j.Logger"); - } - return log4jAvailable; - } - - public static boolean isOracleAvailable() { - if (oracleAvailable == null) { - oracleAvailable = isPresent("oracle.sql.TIMESTAMP"); - } - return oracleAvailable; - } - - public static boolean isCacheUnderscoreToCamelcaseEnabled() { - return cacheUnderscoreToCamelcaseEnabled; - } - - public static void setCacheUnderscoreToCamelcaseEnabled(boolean cacheUnderscoreToCamelcaseEnabled) { - FeatureDetector.cacheUnderscoreToCamelcaseEnabled = cacheUnderscoreToCamelcaseEnabled; - } -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/Level.java b/blade-kit/src/main/java/blade/kit/logging/Level.java deleted file mode 100644 index 5e3dcbe63..000000000 --- a/blade-kit/src/main/java/blade/kit/logging/Level.java +++ /dev/null @@ -1,22 +0,0 @@ -package blade.kit.logging; - -/** - * 日志级别 - * @author biezhi - * - */ -public final class Level { - - public static final int TRACE = 100; - - public static final int DEBUG = 200; - - public static final int INFO = 300; - - public static final int WARN = 400; - - public static final int ERROR = 500; - - public static final int FATAL = 600; - -} diff --git a/blade-kit/src/main/java/blade/kit/logging/Log4jLogger.java b/blade-kit/src/main/java/blade/kit/logging/Log4jLogger.java deleted file mode 100644 index 166dc584c..000000000 --- a/blade-kit/src/main/java/blade/kit/logging/Log4jLogger.java +++ /dev/null @@ -1,55 +0,0 @@ -package blade.kit.logging; - -public class Log4jLogger implements Logger { - - private final org.apache.log4j.Logger logger; - - public Log4jLogger(org.apache.log4j.Logger logger) { - this.logger = logger; - } - - @Override - public void debug(String msg) { - logger.debug(msg); - } - - @Override - public void debug(String msg, Object... args) { - } - - public void warn(String msg) { - logger.warn(msg); - } - - public void warn(String msg, Throwable t) { - logger.warn(msg, t); - } - - @Override - public void info(String msg) { - logger.info(msg); - } - - @Override - public void info(String msg, Object... args) { - } - - @Override - public void error(String msg) { - logger.error(msg); - } - - @Override - public void error(String msg, Object... args) { - } - - @Override - public void error(String msg, Throwable t) { - logger.error(msg, t); - } - - @Override - public void warn(String msg, Object... args) { - } - -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/Logger.java b/blade-kit/src/main/java/blade/kit/logging/Logger.java deleted file mode 100644 index 80f65dd0b..000000000 --- a/blade-kit/src/main/java/blade/kit/logging/Logger.java +++ /dev/null @@ -1,25 +0,0 @@ -package blade.kit.logging; - -public interface Logger { - - public void debug(String msg); - - public void debug(String msg, Object... args); - - public void info(String msg); - - public void info(String msg, Object... args); - - public void warn(String msg); - - public void warn(String msg, Object ...args); - - public void warn(String msg, Throwable exception); - - public void error(String msg); - - public void error(String msg, Object...args); - - public void error(String msg, Throwable t); - -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/LoggerFactory.java b/blade-kit/src/main/java/blade/kit/logging/LoggerFactory.java deleted file mode 100644 index d6aaf1a13..000000000 --- a/blade-kit/src/main/java/blade/kit/logging/LoggerFactory.java +++ /dev/null @@ -1,18 +0,0 @@ -package blade.kit.logging; - -public class LoggerFactory { - - private static final boolean slf4jAvailable = FeatureDetector.isSlf4jAvailable(); - private static final boolean log4jAvailable = FeatureDetector.isLog4jAvailable(); - - public static Logger getLogger(Class clazz) { - if(slf4jAvailable){ - return new Slf4jLogger(org.slf4j.LoggerFactory.getLogger(clazz)); - } - if(log4jAvailable){ - return new Log4jLogger(org.apache.log4j.Logger.getLogger(clazz)); - } - return new SimpleLogger(clazz); - } - -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java b/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java deleted file mode 100644 index 33fe2c878..000000000 --- a/blade-kit/src/main/java/blade/kit/logging/SimpleLogger.java +++ /dev/null @@ -1,222 +0,0 @@ -package blade.kit.logging; - -import java.io.PrintStream; -import java.text.SimpleDateFormat; -import java.util.Date; - -public class SimpleLogger implements Logger { - - private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"); - - private static PrintStream outprint = System.out; - - private int level = Level.DEBUG; - - protected String name; - - public SimpleLogger() { - String currentClassName = Thread.currentThread().getStackTrace()[2].getClassName(); - this.name = currentClassName; - } - - public SimpleLogger(Class type) { - this.name = type.getName(); - } - - private String getLevel(int level){ - if(level <= Level.TRACE){ - return "TRACE"; - } - if(level <= Level.DEBUG){ - return "DEBUG"; - } - if(level <= Level.INFO){ - return "INFO"; - } - if(level <= Level.WARN){ - return "WARN"; - } - if(level <= Level.ERROR){ - outprint = System.err; - return "ERROR"; - } - if(level <= Level.FATAL){ - return "FATAL"; - } - return "DEBUG"; - } - - private String now() { - return sdf.format(new Date()); - } - - public void trace(String message) { - if (level <= Level.TRACE) - log(Level.TRACE, message); - } - - public void trace(String message, Object... args) { - if (level <= Level.TRACE) - log(Level.TRACE, message, args); - } - - public void trace(String message, Throwable t) { - if (level <= Level.TRACE) - log(Level.TRACE, message, t); - } - - - public void trace(String message, Throwable t, Object... args) { - if (level <= Level.TRACE) - log(Level.TRACE, message, t, args); - } - - - public void debug(String message) { - if (level <= Level.DEBUG) - log(Level.DEBUG, message); - } - - - public void debug(String message, Object... args) { - if (level <= Level.DEBUG) - log(Level.DEBUG, message, args); - } - - - public void debug(String message, Throwable t) { - if (level <= Level.DEBUG) - log(Level.DEBUG, message, t); - } - - - public void debug(String message, Throwable t, Object... args) { - if (level <= Level.DEBUG) - log(Level.DEBUG, message, t, args); - } - - - public void info(String message) { - if (level <= Level.INFO) - log(Level.INFO, message); - } - - - public void info(String message, Object... args) { - if (level <= Level.INFO) - log(Level.INFO, message, args); - } - - - public void info(String message, Throwable t) { - if (level <= Level.INFO) - log(Level.INFO, message, t); - } - - - public void info(String message, Throwable t, Object... args) { - if (level <= Level.INFO) - log(Level.INFO, message, t, args); - } - - - public void warn(String message) { - if (level <= Level.WARN) - log(Level.WARN, message); - } - - - public void warn(String message, Object... args) { - if (level <= Level.WARN) - log(Level.WARN, message, args); - } - - - public void warn(String message, Throwable t) { - if (level <= Level.WARN) - log(Level.WARN, message, t); - } - - - public void warn(String message, Throwable t, Object... args) { - if (level <= Level.WARN) - log(Level.WARN, message, t, args); - } - - - public void error(String message) { - if (level <= Level.ERROR) - log(Level.ERROR, message); - } - - - public void error(String message, Object... args) { - if (level <= Level.ERROR) - log(Level.ERROR, message, args); - } - - - public void error(String message, Throwable t) { - if (level <= Level.ERROR) - log(Level.ERROR, message, t); - } - - - public void error(String message, Throwable t, Object... args) { - if (level <= Level.ERROR) - log(Level.ERROR, message, t, args); - } - - public boolean isDebugEnabled() { - return level <= Level.DEBUG; - } - - public boolean isErrorEnabled() { - return level <= Level.ERROR; - } - - public boolean isInfoEnabled() { - return level <= Level.INFO; - } - - public boolean isWarnEnabled() { - return level <= Level.WARN; - } - - public void log(int level, String message, Object... args) { - log(level, message, null, args); - } - - public void log(int level, String message, Throwable t, Object... args) { - - StringBuilder sb = new StringBuilder(now()); - sb.append(" ").append(getLevel(level)).append(" "); - sb.append("[").append(Thread.currentThread().getName()).append("]").append(" "); - sb.append(this.name).append(" | "); - sb.append(format(message, args)); - - outprint.println(sb.toString()); - if (t != null) { - t.printStackTrace(System.err); - System.err.flush(); - } - } - - protected String format(String message, Object... args) { - if (message == null) { - return null; - } - if (args == null || args.length == 0){ - if(message.indexOf("{}") != -1){ - message = message.replaceAll("\\{\\}", ""); - } - return message.toString(); - } else { - if(message.indexOf("{}") != -1){ - message = message.replaceAll("\\{\\}", "%s"); - } - return String.format(message.toString(), args); - } - } - -} \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/logging/Slf4jLogger.java b/blade-kit/src/main/java/blade/kit/logging/Slf4jLogger.java deleted file mode 100644 index 996c1d321..000000000 --- a/blade-kit/src/main/java/blade/kit/logging/Slf4jLogger.java +++ /dev/null @@ -1,58 +0,0 @@ -package blade.kit.logging; - -public class Slf4jLogger implements Logger { - - private final org.slf4j.Logger logger; - - public Slf4jLogger(org.slf4j.Logger logger) { - this.logger = logger; - } - - @Override - public void debug(String msg, Object... args) { - logger.debug(msg, args); - } - - @Override - public void debug(String msg) { - logger.debug(msg); - } - - public void warn(String msg) { - logger.warn(msg); - } - - public void warn(String msg, Throwable t) { - logger.warn(msg, t); - } - - @Override - public void info(String msg) { - logger.info(msg); - } - - @Override - public void info(String msg, Object... args) { - logger.info(msg, args); - } - - @Override - public void error(String msg) { - logger.error(msg); - } - - @Override - public void error(String msg, Object... args) { - logger.error(msg, args); - } - - @Override - public void error(String msg, Throwable t) { - logger.error(msg, t); - } - - @Override - public void warn(String msg, Object... args) { - logger.warn(msg, args); - } -} diff --git a/blade-kit/src/main/java/blade/kit/resource/package-info.java b/blade-kit/src/main/java/blade/kit/resource/package-info.java deleted file mode 100644 index 7e091b6f7..000000000 --- a/blade-kit/src/main/java/blade/kit/resource/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 资源搜索包 - */ -package blade.kit.resource; \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/timw/package-info.java b/blade-kit/src/main/java/blade/kit/timw/package-info.java deleted file mode 100644 index c7efc5c84..000000000 --- a/blade-kit/src/main/java/blade/kit/timw/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 计时器包 - */ -package blade.kit.timw; \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/AES.java b/blade-kit/src/main/java/com/blade/kit/AES.java similarity index 94% rename from blade-kit/src/main/java/blade/kit/AES.java rename to blade-kit/src/main/java/com/blade/kit/AES.java index ddf404e7b..906d4adcd 100644 --- a/blade-kit/src/main/java/blade/kit/AES.java +++ b/blade-kit/src/main/java/com/blade/kit/AES.java @@ -1,58 +1,58 @@ -package blade.kit; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; - -/** - * Aes encryption - */ -public class AES { - - private static SecretKeySpec secretKey; - private static byte[] key; - - public static void setKey(String myKey) { - MessageDigest sha = null; - try { - key = myKey.getBytes("UTF-8"); - sha = MessageDigest.getInstance("SHA-1"); - key = sha.digest(key); - key = Arrays.copyOf(key, 16); // use only first 128 bit - secretKey = new SecretKeySpec(key, "AES"); - - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - - public static String encrypt(String strToEncrypt) { - try { - Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); - cipher.init(Cipher.ENCRYPT_MODE, secretKey); - return Base64.encodeBytes(cipher.doFinal(strToEncrypt.getBytes("UTF-8"))); - } catch (Exception e) { - System.out.println("Error while encrypting: " + e.toString()); - } - return null; - } - - public static String decrypt(String strToDecrypt) { - try { - Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); - - cipher.init(Cipher.DECRYPT_MODE, secretKey); - return new String(cipher.doFinal(Base64.decode(strToDecrypt))); - - } catch (Exception e) { - System.out.println("Error while decrypting: " + e.toString()); - } - return null; - } - +package com.blade.kit; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; + +/** + * Aes encryption + */ +public class AES { + + private static SecretKeySpec secretKey; + private static byte[] key; + + public static void setKey(String myKey) { + MessageDigest sha = null; + try { + key = myKey.getBytes("UTF-8"); + sha = MessageDigest.getInstance("SHA-1"); + key = sha.digest(key); + key = Arrays.copyOf(key, 16); // use only first 128 bit + secretKey = new SecretKeySpec(key, "AES"); + + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + public static String encrypt(String strToEncrypt) { + try { + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + return Base64.encodeBytes(cipher.doFinal(strToEncrypt.getBytes("UTF-8"))); + } catch (Exception e) { + System.out.println("Error while encrypting: " + e.toString()); + } + return null; + } + + public static String decrypt(String strToDecrypt) { + try { + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); + + cipher.init(Cipher.DECRYPT_MODE, secretKey); + return new String(cipher.doFinal(Base64.decode(strToDecrypt))); + + } catch (Exception e) { + System.out.println("Error while decrypting: " + e.toString()); + } + return null; + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/Assert.java b/blade-kit/src/main/java/com/blade/kit/Assert.java similarity index 97% rename from blade-kit/src/main/java/blade/kit/Assert.java rename to blade-kit/src/main/java/com/blade/kit/Assert.java index fcacaa458..8556169cb 100644 --- a/blade-kit/src/main/java/blade/kit/Assert.java +++ b/blade-kit/src/main/java/com/blade/kit/Assert.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.util.Collection; import java.util.Map; diff --git a/blade-kit/src/main/java/blade/kit/Base64.java b/blade-kit/src/main/java/com/blade/kit/Base64.java similarity index 97% rename from blade-kit/src/main/java/blade/kit/Base64.java rename to blade-kit/src/main/java/com/blade/kit/Base64.java index ca9042aec..69cd26e7d 100644 --- a/blade-kit/src/main/java/blade/kit/Base64.java +++ b/blade-kit/src/main/java/com/blade/kit/Base64.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.io.UnsupportedEncodingException; diff --git a/blade-kit/src/main/java/blade/kit/BeanKit.java b/blade-kit/src/main/java/com/blade/kit/BeanKit.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/BeanKit.java rename to blade-kit/src/main/java/com/blade/kit/BeanKit.java index 40a57ea8c..a283ee3f0 100644 --- a/blade-kit/src/main/java/blade/kit/BeanKit.java +++ b/blade-kit/src/main/java/com/blade/kit/BeanKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.beans.BeanInfo; import java.beans.Introspector; diff --git a/blade-kit/src/main/java/blade/kit/CharKit.java b/blade-kit/src/main/java/com/blade/kit/CharKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/CharKit.java rename to blade-kit/src/main/java/com/blade/kit/CharKit.java index 85f1898b9..d911bf872 100644 --- a/blade-kit/src/main/java/blade/kit/CharKit.java +++ b/blade-kit/src/main/java/com/blade/kit/CharKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.io.UnsupportedEncodingException; diff --git a/blade-kit/src/main/java/blade/kit/ClassLoaderKit.java b/blade-kit/src/main/java/com/blade/kit/ClassLoaderKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/ClassLoaderKit.java rename to blade-kit/src/main/java/com/blade/kit/ClassLoaderKit.java index 0c5671151..60bf386e2 100644 --- a/blade-kit/src/main/java/blade/kit/ClassLoaderKit.java +++ b/blade-kit/src/main/java/com/blade/kit/ClassLoaderKit.java @@ -1,4 +1,4 @@ -package blade.kit; +package com.blade.kit; import java.io.IOException; import java.io.InputStream; diff --git a/blade-kit/src/main/java/blade/kit/CloneKit.java b/blade-kit/src/main/java/com/blade/kit/CloneKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/CloneKit.java rename to blade-kit/src/main/java/com/blade/kit/CloneKit.java index 4afb3a7db..00a0ee76d 100644 --- a/blade-kit/src/main/java/blade/kit/CloneKit.java +++ b/blade-kit/src/main/java/com/blade/kit/CloneKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; diff --git a/blade-kit/src/main/java/blade/kit/CollectionKit.java b/blade-kit/src/main/java/com/blade/kit/CollectionKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/CollectionKit.java rename to blade-kit/src/main/java/com/blade/kit/CollectionKit.java index 8a6494e4b..9fadf39d3 100644 --- a/blade-kit/src/main/java/blade/kit/CollectionKit.java +++ b/blade-kit/src/main/java/com/blade/kit/CollectionKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.util.ArrayDeque; import java.util.ArrayList; diff --git a/blade-kit/src/main/java/blade/kit/DateKit.java b/blade-kit/src/main/java/com/blade/kit/DateKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/DateKit.java rename to blade-kit/src/main/java/com/blade/kit/DateKit.java index a5c0556cc..32b72c4ad 100644 --- a/blade-kit/src/main/java/blade/kit/DateKit.java +++ b/blade-kit/src/main/java/com/blade/kit/DateKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.text.DateFormat; import java.text.ParseException; diff --git a/blade-kit/src/main/java/blade/kit/Emptys.java b/blade-kit/src/main/java/com/blade/kit/Emptys.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/Emptys.java rename to blade-kit/src/main/java/com/blade/kit/Emptys.java index 520f66f01..85a207f52 100644 --- a/blade-kit/src/main/java/blade/kit/Emptys.java +++ b/blade-kit/src/main/java/com/blade/kit/Emptys.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.io.Serializable; diff --git a/blade-kit/src/main/java/blade/kit/EncrypKit.java b/blade-kit/src/main/java/com/blade/kit/EncrypKit.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/EncrypKit.java rename to blade-kit/src/main/java/com/blade/kit/EncrypKit.java index 58698febe..7b27a3cec 100644 --- a/blade-kit/src/main/java/blade/kit/EncrypKit.java +++ b/blade-kit/src/main/java/com/blade/kit/EncrypKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.security.MessageDigest; diff --git a/blade-kit/src/main/java/blade/kit/Environment.java b/blade-kit/src/main/java/com/blade/kit/Environment.java similarity index 94% rename from blade-kit/src/main/java/blade/kit/Environment.java rename to blade-kit/src/main/java/com/blade/kit/Environment.java index 666839c46..28947d7a7 100644 --- a/blade-kit/src/main/java/blade/kit/Environment.java +++ b/blade-kit/src/main/java/com/blade/kit/Environment.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.io.IOException; import java.io.InputStream; @@ -24,8 +24,9 @@ import java.util.Properties; import java.util.Set; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Environment diff --git a/blade-kit/src/main/java/blade/kit/ExceptionKit.java b/blade-kit/src/main/java/com/blade/kit/ExceptionKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/ExceptionKit.java rename to blade-kit/src/main/java/com/blade/kit/ExceptionKit.java index 258a11719..08f727cf9 100644 --- a/blade-kit/src/main/java/blade/kit/ExceptionKit.java +++ b/blade-kit/src/main/java/com/blade/kit/ExceptionKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.io.PrintWriter; import java.io.StringWriter; diff --git a/blade-kit/src/main/java/blade/kit/FileKit.java b/blade-kit/src/main/java/com/blade/kit/FileKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/FileKit.java rename to blade-kit/src/main/java/com/blade/kit/FileKit.java index 3f1409f4a..c6e68c241 100644 --- a/blade-kit/src/main/java/blade/kit/FileKit.java +++ b/blade-kit/src/main/java/com/blade/kit/FileKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.io.File; import java.io.FileFilter; @@ -29,7 +29,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import blade.kit.exception.IllegalPathException; +import com.blade.kit.exception.IllegalPathException; /** * 有关文件处理的工具类。 diff --git a/blade-kit/src/main/java/blade/kit/HashidKit.java b/blade-kit/src/main/java/com/blade/kit/HashidKit.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/HashidKit.java rename to blade-kit/src/main/java/com/blade/kit/HashidKit.java index cd8c4f761..7846d636a 100644 --- a/blade-kit/src/main/java/blade/kit/HashidKit.java +++ b/blade-kit/src/main/java/com/blade/kit/HashidKit.java @@ -1,4 +1,4 @@ -package blade.kit; +package com.blade.kit; import java.util.*; import java.util.regex.Matcher; diff --git a/blade-kit/src/main/java/blade/kit/IOKit.java b/blade-kit/src/main/java/com/blade/kit/IOKit.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/IOKit.java rename to blade-kit/src/main/java/com/blade/kit/IOKit.java index d96ed74b5..8bf36d76c 100644 --- a/blade-kit/src/main/java/blade/kit/IOKit.java +++ b/blade-kit/src/main/java/com/blade/kit/IOKit.java @@ -1,273 +1,273 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; - -import java.io.BufferedReader; -import java.io.Closeable; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; -import java.net.HttpURLConnection; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.URLConnection; -import java.nio.channels.Selector; -import java.nio.charset.Charset; -import java.util.zip.ZipFile; - -import blade.kit.io.FastByteArrayOutputStream; - -/** - * IO工具类 - * - * @author biezhi - * @since 1.0 - */ -public final class IOKit { - - public static final String LINE_SEPARATOR; - - private static final int EOF = -1; - - static { - // avoid security issues - StringWriter buf = new StringWriter(4); // NOSONAR - PrintWriter out = new PrintWriter(buf); - out.println(); - LINE_SEPARATOR = buf.toString(); - } - - /** - * The default buffer size to use. - */ - public static final int DEFAULT_BUFFER_SIZE = 0x1000; - - private IOKit() { - } - - public static String toString(InputStream input) throws IOException { - StringWriter sw = new StringWriter(); - copy(input, sw); - return sw.toString(); - } - - public static String toString(File file) throws IOException { - try { - BufferedReader reader = new BufferedReader(new FileReader(file)); - StringBuilder data = readFromBufferedReader(reader); - reader.close(); - return new String(data.toString().getBytes(), "utf-8"); - } catch (IOException ex) { - throw new RuntimeException("File " + file + " not found."); - } - } - - private static StringBuilder readFromBufferedReader(BufferedReader reader) throws IOException { - StringBuilder builder = new StringBuilder(); - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - int numRead = 0; - while((numRead = reader.read(buffer)) != EOF) { - builder.append(String.valueOf(buffer, 0, numRead)); - buffer = new char[DEFAULT_BUFFER_SIZE]; - } - return builder; - } - - public static byte[] toByteArray(InputStream input) throws IOException { - @SuppressWarnings("resource") - FastByteArrayOutputStream os = new FastByteArrayOutputStream(); - byte[] buf = new byte[1024]; - for (int n = input.read(buf); n != EOF; n = input.read(buf)) { - os.write(buf, 0, n); - } - return os.toByteArray(); - } - - - - public static long copyLarge(final InputStream input, final OutputStream output) - throws IOException { - byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; - long count = 0L; - int n = 0; - while (EOF != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; - } - - public static void copy(InputStream input, Writer output) - throws IOException { - InputStreamReader in = new InputStreamReader(input); // NOSONAR - copy(in, output); - } - - public static long copyLarge(Reader input, Writer output) throws IOException { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - long count = 0L; - int n = 0; - while (EOF != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; - } - - public static void write(byte[] data, File file) { - OutputStream os = null; - try { - os = new FileOutputStream(file); - os.write(data); - } catch (IOException e) { - throw new IllegalStateException(e); - } finally { - closeQuietly(os); - } - } - - public static void write(char[] data, File file, String charsetName) { - write(data, file, Charset.forName(charsetName)); - } - - public static void write(char[] data, File file, Charset charset) { - OutputStream os = null; - try { - os = new FileOutputStream(file); - os.write(new String(data).getBytes(charset)); - } catch (IOException e) { - throw new IllegalStateException(e); - } finally { - closeQuietly(os); - } - } - - public static void write(String data, File file, String charsetName) { - write(data, file, Charset.forName(charsetName)); - } - - public static void write(String data, File file, Charset charset) { - OutputStream os = null; - try { - os = new FileOutputStream(file); - os.write(data.getBytes(charset)); - } catch (IOException e) { - throw new IllegalStateException(e); - } finally { - closeQuietly(os); - } - } - - public static int copy(InputStream input, OutputStream output) - throws IOException { - long count = copyLarge(input, output); - if (count > Integer.MAX_VALUE) { - return -1; - } - return (int) count; - } - - public static int copy(InputStream input, Writer output, String charsetName) - throws IOException { - return copy(new InputStreamReader(input, Charset.forName(charsetName)), - output); - } - - public static int copy(InputStream input, Writer output, Charset charset) - throws IOException { - return copy(new InputStreamReader(input, charset), output); - } - - public static int copy(Reader input, Writer output) throws IOException { - long count = copyLarge(input, output); - if (count > Integer.MAX_VALUE) { - return -1; - } - return (int) count; - } - - public static void closeQuietly(ZipFile obj) { - try { - if (obj != null) { - obj.close(); - } - } catch (IOException e) { - } - } - - public static void closeQuietly(Socket socket) { - try { - if (socket != null) { - socket.close(); - } - } catch (IOException e) { - } - } - - public static void closeQuietly(ServerSocket socket) { - try { - if (socket != null) { - socket.close(); - } - } catch (IOException e) { - } - } - - public static void closeQuietly(Selector selector) { - try { - if (selector != null) { - selector.close(); - } - } catch (IOException e) { - } - } - - public static void closeQuietly(URLConnection conn) { - if (conn != null) { - if (conn instanceof HttpURLConnection) { - ((HttpURLConnection) conn).disconnect(); - } - } - } - - public static void closeQuietly(Closeable closeable) { - if (null != closeable) { - try { - closeable.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - public static String toString(Reader input) throws IOException { - StringBuilder output = new StringBuilder(); - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - int n; - while (EOF != (n = input.read(buffer))) { - output.append(buffer, 0, n); - } - return output.toString(); - } -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; + +import java.io.BufferedReader; +import java.io.Closeable; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.StringWriter; +import java.io.Writer; +import java.net.HttpURLConnection; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URLConnection; +import java.nio.channels.Selector; +import java.nio.charset.Charset; +import java.util.zip.ZipFile; + +import com.blade.kit.io.FastByteArrayOutputStream; + +/** + * IO工具类 + * + * @author biezhi + * @since 1.0 + */ +public final class IOKit { + + public static final String LINE_SEPARATOR; + + private static final int EOF = -1; + + static { + // avoid security issues + StringWriter buf = new StringWriter(4); // NOSONAR + PrintWriter out = new PrintWriter(buf); + out.println(); + LINE_SEPARATOR = buf.toString(); + } + + /** + * The default buffer size to use. + */ + public static final int DEFAULT_BUFFER_SIZE = 0x1000; + + private IOKit() { + } + + public static String toString(InputStream input) throws IOException { + StringWriter sw = new StringWriter(); + copy(input, sw); + return sw.toString(); + } + + public static String toString(File file) throws IOException { + try { + BufferedReader reader = new BufferedReader(new FileReader(file)); + StringBuilder data = readFromBufferedReader(reader); + reader.close(); + return new String(data.toString().getBytes(), "utf-8"); + } catch (IOException ex) { + throw new RuntimeException("File " + file + " not found."); + } + } + + private static StringBuilder readFromBufferedReader(BufferedReader reader) throws IOException { + StringBuilder builder = new StringBuilder(); + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + int numRead = 0; + while((numRead = reader.read(buffer)) != EOF) { + builder.append(String.valueOf(buffer, 0, numRead)); + buffer = new char[DEFAULT_BUFFER_SIZE]; + } + return builder; + } + + public static byte[] toByteArray(InputStream input) throws IOException { + @SuppressWarnings("resource") + FastByteArrayOutputStream os = new FastByteArrayOutputStream(); + byte[] buf = new byte[1024]; + for (int n = input.read(buf); n != EOF; n = input.read(buf)) { + os.write(buf, 0, n); + } + return os.toByteArray(); + } + + + + public static long copyLarge(final InputStream input, final OutputStream output) + throws IOException { + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + long count = 0L; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + public static void copy(InputStream input, Writer output) + throws IOException { + InputStreamReader in = new InputStreamReader(input); // NOSONAR + copy(in, output); + } + + public static long copyLarge(Reader input, Writer output) throws IOException { + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + long count = 0L; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + public static void write(byte[] data, File file) { + OutputStream os = null; + try { + os = new FileOutputStream(file); + os.write(data); + } catch (IOException e) { + throw new IllegalStateException(e); + } finally { + closeQuietly(os); + } + } + + public static void write(char[] data, File file, String charsetName) { + write(data, file, Charset.forName(charsetName)); + } + + public static void write(char[] data, File file, Charset charset) { + OutputStream os = null; + try { + os = new FileOutputStream(file); + os.write(new String(data).getBytes(charset)); + } catch (IOException e) { + throw new IllegalStateException(e); + } finally { + closeQuietly(os); + } + } + + public static void write(String data, File file, String charsetName) { + write(data, file, Charset.forName(charsetName)); + } + + public static void write(String data, File file, Charset charset) { + OutputStream os = null; + try { + os = new FileOutputStream(file); + os.write(data.getBytes(charset)); + } catch (IOException e) { + throw new IllegalStateException(e); + } finally { + closeQuietly(os); + } + } + + public static int copy(InputStream input, OutputStream output) + throws IOException { + long count = copyLarge(input, output); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; + } + + public static int copy(InputStream input, Writer output, String charsetName) + throws IOException { + return copy(new InputStreamReader(input, Charset.forName(charsetName)), + output); + } + + public static int copy(InputStream input, Writer output, Charset charset) + throws IOException { + return copy(new InputStreamReader(input, charset), output); + } + + public static int copy(Reader input, Writer output) throws IOException { + long count = copyLarge(input, output); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; + } + + public static void closeQuietly(ZipFile obj) { + try { + if (obj != null) { + obj.close(); + } + } catch (IOException e) { + } + } + + public static void closeQuietly(Socket socket) { + try { + if (socket != null) { + socket.close(); + } + } catch (IOException e) { + } + } + + public static void closeQuietly(ServerSocket socket) { + try { + if (socket != null) { + socket.close(); + } + } catch (IOException e) { + } + } + + public static void closeQuietly(Selector selector) { + try { + if (selector != null) { + selector.close(); + } + } catch (IOException e) { + } + } + + public static void closeQuietly(URLConnection conn) { + if (conn != null) { + if (conn instanceof HttpURLConnection) { + ((HttpURLConnection) conn).disconnect(); + } + } + } + + public static void closeQuietly(Closeable closeable) { + if (null != closeable) { + try { + closeable.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static String toString(Reader input) throws IOException { + StringBuilder output = new StringBuilder(); + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + int n; + while (EOF != (n = input.read(buffer))) { + output.append(buffer, 0, n); + } + return output.toString(); + } +} diff --git a/blade-kit/src/main/java/blade/kit/IpKit.java b/blade-kit/src/main/java/com/blade/kit/IpKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/IpKit.java rename to blade-kit/src/main/java/com/blade/kit/IpKit.java index 7554c2f01..0a51426ee 100644 --- a/blade-kit/src/main/java/blade/kit/IpKit.java +++ b/blade-kit/src/main/java/com/blade/kit/IpKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.net.InetAddress; import java.net.NetworkInterface; diff --git a/blade-kit/src/main/java/blade/kit/MimeParse.java b/blade-kit/src/main/java/com/blade/kit/MimeParse.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/MimeParse.java rename to blade-kit/src/main/java/com/blade/kit/MimeParse.java index d942e1c36..3686964e8 100644 --- a/blade-kit/src/main/java/blade/kit/MimeParse.java +++ b/blade-kit/src/main/java/com/blade/kit/MimeParse.java @@ -1,228 +1,228 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * MIME-Type解析类 - * - * @author biezhi - * @since 1.0 - */ -public class MimeParse { - - /** - * Constant for no mime type - */ - public static final String NO_MIME_TYPE = ""; - - /** - * Parse results container - */ - private static class ParseResults { - String type; - - String subType; - - // !a dictionary of all the parameters for the media range - Map params; - - @Override - public String toString() { - StringBuffer s = new StringBuffer("('" + type + "', '" + subType + "', {"); - for (String k : params.keySet()) { - s.append("'" + k + "':'" + params.get(k) + "',"); - } - return s.append("})").toString(); - } - } - - /** - * Carves up a mime-type and returns a ParseResults object - * For example, the media range 'application/xhtml;q=0.5' would get parsed - * into: - * ('application', 'xhtml', {'q', '0.5'}) - */ - private static ParseResults parseMimeType(String mimeType) { - String[] parts = StringKit.split(mimeType, ";"); - ParseResults results = new ParseResults(); - results.params = new HashMap(); - - for (int i = 1; i < parts.length; ++i) { - String p = parts[i]; - String[] subParts = StringKit.split(p, "="); - if (subParts.length == 2) { - results.params.put(subParts[0].trim(), subParts[1].trim()); - } - } - String fullType = parts[0].trim(); - - // Java URLConnection class sends an Accept header that includes a - // single "*" - Turn it into a legal wildcard. - if (fullType.equals("*")) { - fullType = "*/*"; - } - - int slashIndex = fullType.indexOf('/'); - if (slashIndex != -1) { - results.type = fullType.substring(0, slashIndex); - results.subType = fullType.substring(slashIndex + 1); - } else { - //If the type is invalid, attempt to turn into a wildcard - results.type = fullType; - results.subType = "*"; - } - - return results; - } - - /** - * Carves up a media range and returns a ParseResults. - * For example, the media range 'application/*;q=0.5' would get parsed into: - * ('application', '*', {'q', '0.5'}) - * In addition this function also guarantees that there is a value for 'q' - * in the params dictionary, filling it in with a proper default if - * necessary. - * - * @param range - */ - private static ParseResults parseMediaRange(String range) { - ParseResults results = parseMimeType(range); - String q = results.params.get("q"); - float f = toFloat(q, 1); - if (isBlank(q) || f < 0 || f > 1) { - results.params.put("q", "1"); - } - return results; - } - - /** - * Structure for holding a fitness/quality combo - */ - private static class FitnessAndQuality implements Comparable { - int fitness; - - float quality; - - String mimeType; // optionally used - - private FitnessAndQuality(int fitness, float quality) { - this.fitness = fitness; - this.quality = quality; - } - - public int compareTo(FitnessAndQuality o) { - if (fitness == o.fitness) { - if (quality == o.quality) { - return 0; - } else { - return quality < o.quality ? -1 : 1; - } - } else { - return fitness < o.fitness ? -1 : 1; - } - } - } - - /** - * Find the best match for a given mimeType against a list of media_ranges - * that have already been parsed by MimeParse.parseMediaRange(). Returns a - * tuple of the fitness value and the value of the 'q' quality parameter of - * the best match, or (-1, 0) if no match was found. Just as for - * quality_parsed(), 'parsed_ranges' must be a list of parsed media ranges. - * - * @param mimeType - * @param parsedRanges - */ - private static FitnessAndQuality fitnessAndQualityParsed(String mimeType, Collection parsedRanges) { - int bestFitness = -1; - float bestFitQ = 0; - ParseResults target = parseMediaRange(mimeType); - - for (ParseResults range : parsedRanges) { - if ((target.type.equals(range.type) || range.type.equals("*") || target.type.equals("*")) - && (target.subType.equals(range.subType) || range.subType.equals("*") - || target.subType.equals("*"))) { - for (String k : target.params.keySet()) { - int paramMatches = 0; - if (!k.equals("q") && range.params.containsKey(k) - && target.params.get(k).equals(range.params.get(k))) { - paramMatches++; - } - int fitness = (range.type.equals(target.type)) ? 100 : 0; - fitness += (range.subType.equals(target.subType)) ? 10 : 0; - fitness += paramMatches; - if (fitness > bestFitness) { - bestFitness = fitness; - bestFitQ = toFloat(range.params.get("q"), 0); - } - } - } - } - return new FitnessAndQuality(bestFitness, bestFitQ); - } - - /** - * Finds best match - * - * @param supported the supported types - * @param header the header - * @return the best match - */ - public static String bestMatch(Collection supported, String header) { - List parseResults = new LinkedList(); - List weightedMatches = new LinkedList(); - String[] headers = StringKit.split(header, ","); - for (String r : headers) { - parseResults.add(parseMediaRange(r)); - } - - for (String s : supported) { - FitnessAndQuality fitnessAndQuality = fitnessAndQualityParsed(s, parseResults); - fitnessAndQuality.mimeType = s; - weightedMatches.add(fitnessAndQuality); - } - Collections.sort(weightedMatches); - - FitnessAndQuality lastOne = weightedMatches.get(weightedMatches.size() - 1); - return Float.compare(lastOne.quality, 0) != 0 ? lastOne.mimeType : NO_MIME_TYPE; - } - - private static boolean isBlank(String s) { - return s == null || "".equals(s.trim()); - } - - private static float toFloat(final String str, final float defaultValue) { - if (str == null) { - return defaultValue; - } - try { - return Float.parseFloat(str); - } catch (final NumberFormatException nfe) { - return defaultValue; - } - } - - private MimeParse() { - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * MIME-Type解析类 + * + * @author biezhi + * @since 1.0 + */ +public class MimeParse { + + /** + * Constant for no mime type + */ + public static final String NO_MIME_TYPE = ""; + + /** + * Parse results container + */ + private static class ParseResults { + String type; + + String subType; + + // !a dictionary of all the parameters for the media range + Map params; + + @Override + public String toString() { + StringBuffer s = new StringBuffer("('" + type + "', '" + subType + "', {"); + for (String k : params.keySet()) { + s.append("'" + k + "':'" + params.get(k) + "',"); + } + return s.append("})").toString(); + } + } + + /** + * Carves up a mime-type and returns a ParseResults object + * For example, the media range 'application/xhtml;q=0.5' would get parsed + * into: + * ('application', 'xhtml', {'q', '0.5'}) + */ + private static ParseResults parseMimeType(String mimeType) { + String[] parts = StringKit.split(mimeType, ";"); + ParseResults results = new ParseResults(); + results.params = new HashMap(); + + for (int i = 1; i < parts.length; ++i) { + String p = parts[i]; + String[] subParts = StringKit.split(p, "="); + if (subParts.length == 2) { + results.params.put(subParts[0].trim(), subParts[1].trim()); + } + } + String fullType = parts[0].trim(); + + // Java URLConnection class sends an Accept header that includes a + // single "*" - Turn it into a legal wildcard. + if (fullType.equals("*")) { + fullType = "*/*"; + } + + int slashIndex = fullType.indexOf('/'); + if (slashIndex != -1) { + results.type = fullType.substring(0, slashIndex); + results.subType = fullType.substring(slashIndex + 1); + } else { + //If the type is invalid, attempt to turn into a wildcard + results.type = fullType; + results.subType = "*"; + } + + return results; + } + + /** + * Carves up a media range and returns a ParseResults. + * For example, the media range 'application/*;q=0.5' would get parsed into: + * ('application', '*', {'q', '0.5'}) + * In addition this function also guarantees that there is a value for 'q' + * in the params dictionary, filling it in with a proper default if + * necessary. + * + * @param range + */ + private static ParseResults parseMediaRange(String range) { + ParseResults results = parseMimeType(range); + String q = results.params.get("q"); + float f = toFloat(q, 1); + if (isBlank(q) || f < 0 || f > 1) { + results.params.put("q", "1"); + } + return results; + } + + /** + * Structure for holding a fitness/quality combo + */ + private static class FitnessAndQuality implements Comparable { + int fitness; + + float quality; + + String mimeType; // optionally used + + private FitnessAndQuality(int fitness, float quality) { + this.fitness = fitness; + this.quality = quality; + } + + public int compareTo(FitnessAndQuality o) { + if (fitness == o.fitness) { + if (quality == o.quality) { + return 0; + } else { + return quality < o.quality ? -1 : 1; + } + } else { + return fitness < o.fitness ? -1 : 1; + } + } + } + + /** + * Find the best match for a given mimeType against a list of media_ranges + * that have already been parsed by MimeParse.parseMediaRange(). Returns a + * tuple of the fitness value and the value of the 'q' quality parameter of + * the best match, or (-1, 0) if no match was found. Just as for + * quality_parsed(), 'parsed_ranges' must be a list of parsed media ranges. + * + * @param mimeType + * @param parsedRanges + */ + private static FitnessAndQuality fitnessAndQualityParsed(String mimeType, Collection parsedRanges) { + int bestFitness = -1; + float bestFitQ = 0; + ParseResults target = parseMediaRange(mimeType); + + for (ParseResults range : parsedRanges) { + if ((target.type.equals(range.type) || range.type.equals("*") || target.type.equals("*")) + && (target.subType.equals(range.subType) || range.subType.equals("*") + || target.subType.equals("*"))) { + for (String k : target.params.keySet()) { + int paramMatches = 0; + if (!k.equals("q") && range.params.containsKey(k) + && target.params.get(k).equals(range.params.get(k))) { + paramMatches++; + } + int fitness = (range.type.equals(target.type)) ? 100 : 0; + fitness += (range.subType.equals(target.subType)) ? 10 : 0; + fitness += paramMatches; + if (fitness > bestFitness) { + bestFitness = fitness; + bestFitQ = toFloat(range.params.get("q"), 0); + } + } + } + } + return new FitnessAndQuality(bestFitness, bestFitQ); + } + + /** + * Finds best match + * + * @param supported the supported types + * @param header the header + * @return the best match + */ + public static String bestMatch(Collection supported, String header) { + List parseResults = new LinkedList(); + List weightedMatches = new LinkedList(); + String[] headers = StringKit.split(header, ","); + for (String r : headers) { + parseResults.add(parseMediaRange(r)); + } + + for (String s : supported) { + FitnessAndQuality fitnessAndQuality = fitnessAndQualityParsed(s, parseResults); + fitnessAndQuality.mimeType = s; + weightedMatches.add(fitnessAndQuality); + } + Collections.sort(weightedMatches); + + FitnessAndQuality lastOne = weightedMatches.get(weightedMatches.size() - 1); + return Float.compare(lastOne.quality, 0) != 0 ? lastOne.mimeType : NO_MIME_TYPE; + } + + private static boolean isBlank(String s) { + return s == null || "".equals(s.trim()); + } + + private static float toFloat(final String str, final float defaultValue) { + if (str == null) { + return defaultValue; + } + try { + return Float.parseFloat(str); + } catch (final NumberFormatException nfe) { + return defaultValue; + } + } + + private MimeParse() { + } + +} diff --git a/blade-kit/src/main/java/blade/kit/ObjectKit.java b/blade-kit/src/main/java/com/blade/kit/ObjectKit.java similarity index 90% rename from blade-kit/src/main/java/blade/kit/ObjectKit.java rename to blade-kit/src/main/java/com/blade/kit/ObjectKit.java index 2fadab960..f2051aec2 100644 --- a/blade-kit/src/main/java/blade/kit/ObjectKit.java +++ b/blade-kit/src/main/java/com/blade/kit/ObjectKit.java @@ -1,11 +1,11 @@ -package blade.kit; +package com.blade.kit; import java.lang.reflect.Field; import java.util.Date; import java.util.Map; -import blade.kit.exception.ReflectException; -import blade.kit.reflect.ReflectKit; +import com.blade.kit.exception.ReflectException; +import com.blade.kit.reflect.ReflectKit; public final class ObjectKit { diff --git a/blade-kit/src/main/java/blade/kit/PatternKit.java b/blade-kit/src/main/java/com/blade/kit/PatternKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/PatternKit.java rename to blade-kit/src/main/java/com/blade/kit/PatternKit.java index 1f307dbee..20cf42f50 100644 --- a/blade-kit/src/main/java/blade/kit/PatternKit.java +++ b/blade-kit/src/main/java/com/blade/kit/PatternKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.util.regex.Pattern; diff --git a/blade-kit/src/main/java/blade/kit/SerializeKit.java b/blade-kit/src/main/java/com/blade/kit/SerializeKit.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/SerializeKit.java rename to blade-kit/src/main/java/com/blade/kit/SerializeKit.java index 140547c00..705fa5021 100644 --- a/blade-kit/src/main/java/blade/kit/SerializeKit.java +++ b/blade-kit/src/main/java/com/blade/kit/SerializeKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; diff --git a/blade-kit/src/main/java/blade/kit/ShellKit.java b/blade-kit/src/main/java/com/blade/kit/ShellKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/ShellKit.java rename to blade-kit/src/main/java/com/blade/kit/ShellKit.java index a37b70f58..8ebc179ee 100644 --- a/blade-kit/src/main/java/blade/kit/ShellKit.java +++ b/blade-kit/src/main/java/com/blade/kit/ShellKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.io.BufferedReader; import java.io.DataOutputStream; diff --git a/blade-kit/src/main/java/blade/kit/StreamKit.java b/blade-kit/src/main/java/com/blade/kit/StreamKit.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/StreamKit.java rename to blade-kit/src/main/java/com/blade/kit/StreamKit.java index b25ebcec5..5b41cbebe 100644 --- a/blade-kit/src/main/java/blade/kit/StreamKit.java +++ b/blade-kit/src/main/java/com/blade/kit/StreamKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.io.Closeable; import java.io.File; @@ -29,9 +29,9 @@ import java.io.StringWriter; import java.io.Writer; -import blade.kit.io.ByteArray; -import blade.kit.io.ByteArrayOutputStream; -import blade.kit.io.FastByteArrayOutputStream; +import com.blade.kit.io.ByteArray; +import com.blade.kit.io.ByteArrayOutputStream; +import com.blade.kit.io.FastByteArrayOutputStream; /** * 基于流的工具类 diff --git a/blade-kit/src/main/java/blade/kit/StringKit.java b/blade-kit/src/main/java/com/blade/kit/StringKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/StringKit.java rename to blade-kit/src/main/java/com/blade/kit/StringKit.java index 3108882d0..4b8026916 100644 --- a/blade-kit/src/main/java/blade/kit/StringKit.java +++ b/blade-kit/src/main/java/com/blade/kit/StringKit.java @@ -1,2870 +1,2870 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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 blade.kit; - -import java.io.UnsupportedEncodingException; -import java.math.BigDecimal; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Random; -import java.util.UUID; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * 有关字符串处理的工具类。 - * - * @author biezhi - * @since 1.0 - */ -public abstract class StringKit { - - private static final String FOLDER_SEPARATOR = "/"; - private static final String WINDOWS_FOLDER_SEPARATOR = "\\"; - private static final String TOP_PATH = ".."; - private static final String CURRENT_PATH = "."; - public static String[] NUMBER = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "百", "千", "万", "亿" }; - public static final String CREATE = "create"; - public static final String DELETE = "delete"; - public static final String SAVE = "save"; - public static final String UPDATE = "update"; - public static final String QUERY = "query"; - public static final String ERROR = "error"; - public static final String SUCCESS = "success"; - public static final String FAILED = "failed"; - public static final String IP = "strIp"; - public static final String ANSWER = "strAnswer"; - public static final String LOGIN = "login"; - public static final String INDEX = "index"; - public static final String HOME = "home"; - public static final String NORIGHT = "noRight"; - public static final String BOSSIP = "strBOSSIp"; - public static final String BOSSIPS = "BOSSIPS";// 配置文件参数 - public static final String BOSSANSWER = "BOSSANSWER";// 配置文件参数 - private static final String RANDOM_CHAR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - - /** - * 检查字符串是否为null或空字符串""。 - * - *
-     * StringUtil.isEmpty(null)      = true
-     * StringUtil.isEmpty("")        = true
-     * StringUtil.isEmpty(" ")       = false
-     * StringUtil.isEmpty("bob")     = false
-     * StringUtil.isEmpty("  bob  ") = false
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果为空, 则返回true - */ - public static boolean isEmpty(String str) { - return (str == null || str.length() == 0) ? true : false; - } - - public static boolean isAnyEmpty(String...strings) { - if (strings == null) { - return true; - } - for (String string : strings) { - if (isEmpty(string)) { - return true; - } - } - return false; - } - - /** - * 检查字符串是否不是null和空字符串""。 - * - *
-     * StringUtil.isEmpty(null)      = false
-     * StringUtil.isEmpty("")        = false
-     * StringUtil.isEmpty(" ")       = true
-     * StringUtil.isEmpty("bob")     = true
-     * StringUtil.isEmpty("  bob  ") = true
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果不为空, 则返回true - */ - public static boolean isNotEmpty(String str) { - return !isEmpty(str); - } - - /** - * 检查字符串是否是空白:null、空字符串""或只有空白字符。 - * - *
-     * StringUtil.isBlank(null)      = true
-     * StringUtil.isBlank("")        = true
-     * StringUtil.isBlank(" ")       = true
-     * StringUtil.isBlank("bob")     = false
-     * StringUtil.isBlank("  bob  ") = false
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果为空白, 则返回true - */ - public static boolean isBlank(String str) { - int length; - - if ((str == null) || ((length = str.length()) == 0)) { - return true; - } - - for (int i = 0; i < length; i++) { - if (!Character.isWhitespace(str.charAt(i))) { - return false; - } - } - - return true; - } - - public static boolean isAllBlank(String...strings) { - if (strings == null) { - return true; - } - for (String string : strings) { - if (isNotBlank(string)) { - return false; - } - } - return true; - } - - public static boolean isAnyBlank(String...strings) { - if (strings == null) { - return true; - } - for (String string : strings) { - if (isBlank(string)) { - return true; - } - } - return false; - } - - /** - * 检查字符串是否不是空白:null、空字符串""或只有空白字符。 - * - *
-     * StringUtil.isBlank(null)      = false
-     * StringUtil.isBlank("")        = false
-     * StringUtil.isBlank(" ")       = false
-     * StringUtil.isBlank("bob")     = true
-     * StringUtil.isBlank("  bob  ") = true
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果为空白, 则返回true - */ - public static boolean isNotBlank(String str) { - int length; - - if ((str == null) || ((length = str.length()) == 0)) { - return false; - } - - for (int i = 0; i < length; i++) { - if (!Character.isWhitespace(str.charAt(i))) { - return true; - } - } - - return false; - } - - /** - * 如果字符串是null,则返回指定默认字符串,否则返回字符串本身。 - * - *
-     * StringUtil.defaultIfNull(null, "default")  = "default"
-     * StringUtil.defaultIfNull("", "default")    = ""
-     * StringUtil.defaultIfNull("  ", "default")  = "  "
-     * StringUtil.defaultIfNull("bat", "default") = "bat"
-     * 
- * - * @param str 要转换的字符串 - * @param defaultStr 默认字符串 - * - * @return 字符串本身或指定的默认字符串 - */ - public static String defaultIfNull(String str) { - return (str == null) ? "" : str; - } - - /** - * 如果字符串是null,则返回指定默认字符串,否则返回字符串本身。 - * - *
-     * StringUtil.defaultIfNull(null, "default")  = "default"
-     * StringUtil.defaultIfNull("", "default")    = ""
-     * StringUtil.defaultIfNull("  ", "default")  = "  "
-     * StringUtil.defaultIfNull("bat", "default") = "bat"
-     * 
- * - * @param str 要转换的字符串 - * @param defaultStr 默认字符串 - * - * @return 字符串本身或指定的默认字符串 - */ - public static String defaultIfNull(String str, String defaultStr) { - return (str == null) ? defaultStr : str; - } - - /** - * 除去字符串头尾部的空白,如果字符串是null,依然返回null。 - * - *

- * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 - * - *

-     * StringUtil.trim(null)          = null
-     * StringUtil.trim("")            = ""
-     * StringUtil.trim("     ")       = ""
-     * StringUtil.trim("abc")         = "abc"
-     * StringUtil.trim("    abc    ") = "abc"
-     * 
- * - *

- * - * @param str 要处理的字符串 - * - * @return 除去空白的字符串,如果原字串为null,则返回null - */ - public static String trim(String str) { - return trim(str, null, 0); - } - - /** - * Trims array of strings. null array elements are ignored. - */ - public static void trimAll(String[] strings) { - if (strings == null) { - return; - } - for (int i = 0; i < strings.length; i++) { - String string = strings[i]; - if (string != null) { - strings[i] = trim(string); - } - } - } - - /** - * 除去字符串头尾部的指定字符,如果字符串是null,依然返回null。 - * - *
-     * StringUtil.trim(null, *)          = null
-     * StringUtil.trim("", *)            = ""
-     * StringUtil.trim("abc", null)      = "abc"
-     * StringUtil.trim("  abc", null)    = "abc"
-     * StringUtil.trim("abc  ", null)    = "abc"
-     * StringUtil.trim(" abc ", null)    = "abc"
-     * StringUtil.trim("  abcyx", "xyz") = "  abc"
-     * 
- * - * @param str 要处理的字符串 - * @param stripChars 要除去的字符,如果为null表示除去空白字符 - * - * @return 除去指定字符后的的字符串,如果原字串为null,则返回null - */ - public static String trim(String str, String stripChars) { - return trim(str, stripChars, 0); - } - - /** - * 除去字符串头部的空白,如果字符串是null,则返回null。 - * - *

- * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 - * - *

-     * StringUtil.trimStart(null)         = null
-     * StringUtil.trimStart("")           = ""
-     * StringUtil.trimStart("abc")        = "abc"
-     * StringUtil.trimStart("  abc")      = "abc"
-     * StringUtil.trimStart("abc  ")      = "abc  "
-     * StringUtil.trimStart(" abc ")      = "abc "
-     * 
- * - *

- * - * @param str 要处理的字符串 - * - * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null - */ - public static String trimStart(String str) { - return trim(str, null, -1); - } - - /** - * 除去字符串头部的指定字符,如果字符串是null,依然返回null。 - * - *
-     * StringUtil.trimStart(null, *)          = null
-     * StringUtil.trimStart("", *)            = ""
-     * StringUtil.trimStart("abc", "")        = "abc"
-     * StringUtil.trimStart("abc", null)      = "abc"
-     * StringUtil.trimStart("  abc", null)    = "abc"
-     * StringUtil.trimStart("abc  ", null)    = "abc  "
-     * StringUtil.trimStart(" abc ", null)    = "abc "
-     * StringUtil.trimStart("yxabc  ", "xyz") = "abc  "
-     * 
- * - * @param str 要处理的字符串 - * @param stripChars 要除去的字符,如果为null表示除去空白字符 - * - * @return 除去指定字符后的的字符串,如果原字串为null,则返回null - */ - public static String trimStart(String str, String stripChars) { - return trim(str, stripChars, -1); - } - - /** - * 除去字符串尾部的空白,如果字符串是null,则返回null。 - * - *

- * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 - * - *

-     * StringUtil.trimEnd(null)       = null
-     * StringUtil.trimEnd("")         = ""
-     * StringUtil.trimEnd("abc")      = "abc"
-     * StringUtil.trimEnd("  abc")    = "  abc"
-     * StringUtil.trimEnd("abc  ")    = "abc"
-     * StringUtil.trimEnd(" abc ")    = " abc"
-     * 
- * - *

- * - * @param str 要处理的字符串 - * - * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null - */ - public static String trimEnd(String str) { - return trim(str, null, 1); - } - - /** - * 除去字符串尾部的指定字符,如果字符串是null,依然返回null。 - * - *
-     * StringUtil.trimEnd(null, *)          = null
-     * StringUtil.trimEnd("", *)            = ""
-     * StringUtil.trimEnd("abc", "")        = "abc"
-     * StringUtil.trimEnd("abc", null)      = "abc"
-     * StringUtil.trimEnd("  abc", null)    = "  abc"
-     * StringUtil.trimEnd("abc  ", null)    = "abc"
-     * StringUtil.trimEnd(" abc ", null)    = " abc"
-     * StringUtil.trimEnd("  abcyx", "xyz") = "  abc"
-     * 
- * - * @param str 要处理的字符串 - * @param stripChars 要除去的字符,如果为null表示除去空白字符 - * - * @return 除去指定字符后的的字符串,如果原字串为null,则返回null - */ - public static String trimEnd(String str, String stripChars) { - return trim(str, stripChars, 1); - } - - /** - * 除去字符串头尾部的空白,如果结果字符串是空字符串"",则返回null。 - * - *

- * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 - * - *

-     * StringUtil.trimToNull(null)          = null
-     * StringUtil.trimToNull("")            = null
-     * StringUtil.trimToNull("     ")       = null
-     * StringUtil.trimToNull("abc")         = "abc"
-     * StringUtil.trimToNull("    abc    ") = "abc"
-     * 
- * - *

- * - * @param str 要处理的字符串 - * - * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null - */ - public static String trimToNull(String str) { - return trimToNull(str, null); - } - - /** - * 除去字符串头尾部的空白,如果结果字符串是空字符串"",则返回null。 - * - *

- * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 - * - *

-     * StringUtil.trim(null, *)          = null
-     * StringUtil.trim("", *)            = null
-     * StringUtil.trim("abc", null)      = "abc"
-     * StringUtil.trim("  abc", null)    = "abc"
-     * StringUtil.trim("abc  ", null)    = "abc"
-     * StringUtil.trim(" abc ", null)    = "abc"
-     * StringUtil.trim("  abcyx", "xyz") = "  abc"
-     * 
- * - *

- * - * @param str 要处理的字符串 - * @param stripChars 要除去的字符,如果为null表示除去空白字符 - * - * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null - */ - public static String trimToNull(String str, String stripChars) { - String result = trim(str, stripChars); - - if ((result == null) || (result.length() == 0)) { - return null; - } - - return result; - } - - /** - * 除去字符串头尾部的空白,如果字符串是null,则返回空字符串""。 - * - *

- * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 - * - *

-     * StringUtil.trimToEmpty(null)          = ""
-     * StringUtil.trimToEmpty("")            = ""
-     * StringUtil.trimToEmpty("     ")       = ""
-     * StringUtil.trimToEmpty("abc")         = "abc"
-     * StringUtil.trimToEmpty("    abc    ") = "abc"
-     * 
- * - *

- * - * @param str 要处理的字符串 - * - * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null - */ - public static String trimToEmpty(String str) { - return trimToEmpty(str, null); - } - - /** - * 除去字符串头尾部的空白,如果字符串是null,则返回空字符串""。 - * - *

- * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 - * - *

-     * StringUtil.trim(null, *)          = ""
-     * StringUtil.trim("", *)            = ""
-     * StringUtil.trim("abc", null)      = "abc"
-     * StringUtil.trim("  abc", null)    = "abc"
-     * StringUtil.trim("abc  ", null)    = "abc"
-     * StringUtil.trim(" abc ", null)    = "abc"
-     * StringUtil.trim("  abcyx", "xyz") = "  abc"
-     * 
- * - *

- * - * @param str 要处理的字符串 - * - * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null - */ - public static String trimToEmpty(String str, String stripChars) { - String result = trim(str, stripChars); - - if (result == null) { - return ""; - } - return result; - } - - /** - * 除去字符串头尾部的指定字符,如果字符串是null,依然返回null。 - * - *
-     * StringUtil.trim(null, *)          = null
-     * StringUtil.trim("", *)            = ""
-     * StringUtil.trim("abc", null)      = "abc"
-     * StringUtil.trim("  abc", null)    = "abc"
-     * StringUtil.trim("abc  ", null)    = "abc"
-     * StringUtil.trim(" abc ", null)    = "abc"
-     * StringUtil.trim("  abcyx", "xyz") = "  abc"
-     * 
- * - * @param str 要处理的字符串 - * @param stripChars 要除去的字符,如果为null表示除去空白字符 - * @param mode -1表示trimStart,0表示trim全部, 1表示trimEnd - * - * @return 除去指定字符后的的字符串,如果原字串为null,则返回null - */ - private static String trim(String str, String stripChars, int mode) { - if (str == null) { - return null; - } - - int length = str.length(); - int start = 0; - int end = length; - - // 扫描字符串头部 - if (mode <= 0) { - if (stripChars == null) { - while ((start < end) && (Character.isWhitespace(str.charAt(start)))) { - start++; - } - } else if (stripChars.length() == 0) { - return str; - } else { - while ((start < end) && (str.startsWith(stripChars) && stripChars.indexOf(str.charAt(start)) != -1)) { - start++; - } - } - } - - // 扫描字符串尾部 - if (mode >= 0) { - if (stripChars == null) { - while ((start < end) && (Character.isWhitespace(str.charAt(end - 1)))) { - end--; - } - } else if (stripChars.length() == 0) { - return str; - } else { - while ((start < end) && (str.endsWith(stripChars) && stripChars.indexOf(str.charAt(end - 1)) != -1)) { - end--; - } - } - } - - if ((start > 0) || (end < length)) { - return str.substring(start, end); - } - - return str; - } - - /* - * ========================================================================== == - */ - /* 比较函数。 */ - /* */ - /* 以下方法用来比较两个字符串是否相同。 */ - /* - * ========================================================================== == - */ - - /** - * 比较两个字符串(大小写敏感)。 - * - *
-     * StringUtil.equals(null, null)   = true
-     * StringUtil.equals(null, "abc")  = false
-     * StringUtil.equals("abc", null)  = false
-     * StringUtil.equals("abc", "abc") = true
-     * StringUtil.equals("abc", "ABC") = false
-     * 
- * - * @param str1 要比较的字符串1 - * @param str2 要比较的字符串2 - * - * @return 如果两个字符串相同,或者都是null,则返回true - */ - public static boolean equals(String str1, String str2) { - if (str1 == null) { - return str2 == null; - } - - return str1.equals(str2); - } - - /** - * 比较两个字符串(大小写不敏感)。 - * - *
-     * StringUtil.equalsIgnoreCase(null, null)   = true
-     * StringUtil.equalsIgnoreCase(null, "abc")  = false
-     * StringUtil.equalsIgnoreCase("abc", null)  = false
-     * StringUtil.equalsIgnoreCase("abc", "abc") = true
-     * StringUtil.equalsIgnoreCase("abc", "ABC") = true
-     * 
- * - * @param str1 要比较的字符串1 - * @param str2 要比较的字符串2 - * - * @return 如果两个字符串相同,或者都是null,则返回true - */ - public static boolean equalsIgnoreCase(String str1, String str2) { - if (str1 == null) { - return str2 == null; - } - - return str1.equalsIgnoreCase(str2); - } - - /** - * Compares string with at least one from the provided array. If at least one equal string is found, returns its - * index. Otherwise, -1 is returned. - */ - public static int equalsOne(String src, String[] dest) { - if (src == null || dest == null) { - return -1; - } - - for (int i = 0; i < dest.length; i++) { - if (src.equals(dest[i])) { - return i; - } - } - return -1; - } - - /** - * Compares string with at least one from the provided array, ignoring case. If at least one equal string is found, - * it returns its index. Otherwise, -1 is returned. - */ - public static int equalsOneIgnoreCase(String src, String[] dest) { - if (src == null || dest == null) { - return -1; - } - - for (int i = 0; i < dest.length; i++) { - if (src.equalsIgnoreCase(dest[i])) { - return i; - } - } - return -1; - } - - /** - * Compares two string arrays. - * - * @param as first string array - * @param as1 second string array - * - * @return true if all array elements matches - */ - public static boolean equalsIgnoreCase(String as[], String as1[]) { - if (as == null && as1 == null) { - return true; - } - if (as == null || as1 == null) { - return false; - } - if (as.length != as1.length) { - return false; - } - for (int i = 0; i < as.length; i++) { - if (!as[i].equalsIgnoreCase(as1[i])) { - return false; - } - } - return true; - } - - /* - * ========================================================================== == - */ - /* 字符串类型判定函数。 */ - /* */ - /* 判定字符串的类型是否为:字母、数字、空白等 */ - /* - * ========================================================================== == - */ - - /** - * 判断字符串是否只包含unicode字母。 - * - *

- * null将返回false,空字符串""将返回 true。 - *

- * - *
-     * StringUtil.isAlpha(null)   = false
-     * StringUtil.isAlpha("")     = true
-     * StringUtil.isAlpha("  ")   = false
-     * StringUtil.isAlpha("abc")  = true
-     * StringUtil.isAlpha("ab2c") = false
-     * StringUtil.isAlpha("ab-c") = false
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果字符串非null并且全由unicode字母组成,则返回true - */ - public static boolean isAlpha(String str) { - if (str == null) { - return false; - } - - int length = str.length(); - - for (int i = 0; i < length; i++) { - if (!Character.isLetter(str.charAt(i))) { - return false; - } - } - - return true; - } - - /** - * 判断字符串是否只包含unicode字母和空格' '。 - * - *

- * null将返回false,空字符串""将返回 true。 - *

- * - *
-     * StringUtil.isAlphaSpace(null)   = false
-     * StringUtil.isAlphaSpace("")     = true
-     * StringUtil.isAlphaSpace("  ")   = true
-     * StringUtil.isAlphaSpace("abc")  = true
-     * StringUtil.isAlphaSpace("ab c") = true
-     * StringUtil.isAlphaSpace("ab2c") = false
-     * StringUtil.isAlphaSpace("ab-c") = false
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果字符串非null并且全由unicode字母和空格组成,则返回true - */ - public static boolean isAlphaSpace(String str) { - if (str == null) { - return false; - } - - int length = str.length(); - - for (int i = 0; i < length; i++) { - if (!Character.isLetter(str.charAt(i)) && (str.charAt(i) != ' ')) { - return false; - } - } - - return true; - } - - /** - * 判断字符串是否只包含unicode字母和数字。 - * - *

- * null将返回false,空字符串""将返回 true。 - *

- * - *
-     * StringUtil.isAlphanumeric(null)   = false
-     * StringUtil.isAlphanumeric("")     = true
-     * StringUtil.isAlphanumeric("  ")   = false
-     * StringUtil.isAlphanumeric("abc")  = true
-     * StringUtil.isAlphanumeric("ab c") = false
-     * StringUtil.isAlphanumeric("ab2c") = true
-     * StringUtil.isAlphanumeric("ab-c") = false
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果字符串非null并且全由unicode字母数字组成,则返回true - */ - public static boolean isAlphanumeric(String str) { - if (str == null) { - return false; - } - - int length = str.length(); - - for (int i = 0; i < length; i++) { - if (!Character.isLetterOrDigit(str.charAt(i))) { - return false; - } - } - - return true; - } - - /** - * 判断字符串是否只包含unicode字母数字和空格' '。 - * - *

- * null将返回false,空字符串""将返回 true。 - *

- * - *
-     * StringUtil.isAlphanumericSpace(null)   = false
-     * StringUtil.isAlphanumericSpace("")     = true
-     * StringUtil.isAlphanumericSpace("  ")   = true
-     * StringUtil.isAlphanumericSpace("abc")  = true
-     * StringUtil.isAlphanumericSpace("ab c") = true
-     * StringUtil.isAlphanumericSpace("ab2c") = true
-     * StringUtil.isAlphanumericSpace("ab-c") = false
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果字符串非null并且全由unicode字母数字和空格组成,则返回true - */ - public static boolean isAlphanumericSpace(String str) { - if (str == null) { - return false; - } - - int length = str.length(); - - for (int i = 0; i < length; i++) { - if (!Character.isLetterOrDigit(str.charAt(i)) && (str.charAt(i) != ' ')) { - return false; - } - } - - return true; - } - - /** - * 判断字符串是否只包含unicode数字。 - * - *

- * null将返回false,空字符串""将返回 true。 - *

- * - *
-     * StringUtil.isNumeric(null)   = false
-     * StringUtil.isNumeric("")     = true
-     * StringUtil.isNumeric("  ")   = false
-     * StringUtil.isNumeric("123")  = true
-     * StringUtil.isNumeric("12 3") = false
-     * StringUtil.isNumeric("ab2c") = false
-     * StringUtil.isNumeric("12-3") = false
-     * StringUtil.isNumeric("12.3") = false
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果字符串非null并且全由unicode数字组成,则返回true - */ - public static boolean isNumeric(String str) { - if (str == null) { - return false; - } - - int length = str.length(); - - for (int i = 0; i < length; i++) { - if (!Character.isDigit(str.charAt(i))) { - return false; - } - } - - return true; - } - - /** - * 判断字符串是否只包含unicode数字和空格' '。 - * - *

- * null将返回false,空字符串""将返回 true。 - *

- * - *
-     * StringUtil.isNumericSpace(null)   = false
-     * StringUtil.isNumericSpace("")     = true
-     * StringUtil.isNumericSpace("  ")   = true
-     * StringUtil.isNumericSpace("123")  = true
-     * StringUtil.isNumericSpace("12 3") = true
-     * StringUtil.isNumericSpace("ab2c") = false
-     * StringUtil.isNumericSpace("12-3") = false
-     * StringUtil.isNumericSpace("12.3") = false
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果字符串非null并且全由unicode数字和空格组成,则返回true - */ - public static boolean isNumericSpace(String str) { - if (str == null) { - return false; - } - - int length = str.length(); - - for (int i = 0; i < length; i++) { - if (!Character.isDigit(str.charAt(i)) && (str.charAt(i) != ' ')) { - return false; - } - } - - return true; - } - - /** - * 判断字符串是否只包含unicode空白。 - * - *

- * null将返回false,空字符串""将返回 true。 - *

- * - *
-     * StringUtil.isWhitespace(null)   = false
-     * StringUtil.isWhitespace("")     = true
-     * StringUtil.isWhitespace("  ")   = true
-     * StringUtil.isWhitespace("abc")  = false
-     * StringUtil.isWhitespace("ab2c") = false
-     * StringUtil.isWhitespace("ab-c") = false
-     * 
- * - * @param str 要检查的字符串 - * - * @return 如果字符串非null并且全由unicode空白组成,则返回true - */ - public static boolean isWhitespace(String str) { - if (str == null) { - return false; - } - int length = str.length(); - for (int i = 0; i < length; i++) { - if (!Character.isWhitespace(str.charAt(i))) { - return false; - } - } - return true; - } - - /* - * ========================================================================== == - */ - /* 大小写转换。 */ - /* - * ========================================================================== == - */ - - /** - * 将字符串转换成大写。 - * - *

- * 如果字符串是null则返回null。 - * - *

-     * StringUtil.toUpperCasing(null)  = null
-     * StringUtil.toUpperCasing("")    = ""
-     * StringUtil.toUpperCasing("aBc") = "ABC"
-     * 
- * - *

- * - * @param str 要转换的字符串 - * - * @return 大写字符串,如果原字符串为null,则返回null - */ - public static String toUpperCase(String str) { - if (str == null) { - return null; - } - - return str.toUpperCase(); - } - - /** - * 将字符串转换成小写。 - * - *

- * 如果字符串是null则返回null。 - * - *

-     * StringUtil.toLowerCasing(null)  = null
-     * StringUtil.toLowerCasing("")    = ""
-     * StringUtil.toLowerCasing("aBc") = "abc"
-     * 
- * - *

- * - * @param str 要转换的字符串 - * - * @return 大写字符串,如果原字符串为null,则返回null - */ - public static String toLowerCase(String str) { - if (str == null) { - return null; - } - - return str.toLowerCase(); - } - - /** - * 将字符串的首字符转成大写(Character.toTitleCase),其它字符不变。 - * - *

- * 如果字符串是null则返回null。 - * - *

-     * StringUtil.capitalize(null)  = null
-     * StringUtil.capitalize("")    = ""
-     * StringUtil.capitalize("cat") = "Cat"
-     * StringUtil.capitalize("cAt") = "CAt"
-     * 
- * - *

- * - * @param str 要转换的字符串 - * - * @return 首字符为大写的字符串,如果原字符串为null,则返回null - */ - public static String capitalize(String str) { - int strLen; - - if ((str == null) || ((strLen = str.length()) == 0)) { - return str; - } - - return new StringBuilder(strLen).append(Character.toTitleCase(str.charAt(0))).append(str.substring(1)) - .toString(); - } - - /** - * 将字符串的首字符转成小写,其它字符不变。 - * - *

- * 如果字符串是null则返回null。 - * - *

-     * StringUtil.uncapitalize(null)  = null
-     * StringUtil.uncapitalize("")    = ""
-     * StringUtil.uncapitalize("Cat") = "cat"
-     * StringUtil.uncapitalize("CAT") = "cAT"
-     * 
- * - *

- * - * @param str 要转换的字符串 - * - * @return 首字符为小写的字符串,如果原字符串为null,则返回null - */ - public static String uncapitalize(String str) { - int strLen; - - if ((str == null) || ((strLen = str.length()) == 0)) { - return str; - } - - return new StringBuilder(strLen).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)) - .toString(); - } - - /** - * 与 {@link #uncapitalize(String)}不同,连续大写字符将不做改变 - * - *

- * 如果字符串是null则返回null。 - * - *

-     * StringUtil.uncapitalize(null)  = null
-     * StringUtil.uncapitalize("")    = ""
-     * StringUtil.uncapitalize("Cat") = "cat"
-     * StringUtil.uncapitalize("CAT") = "CAT"
-     * 
- * - *

- * - * @param str 要转换的字符串 - * - * @return 首字符为小写的字符串,如果原字符串为null,则返回null - */ - public static String decapitalize(String str) { - if ((str == null) || str.length() == 0) { - return str; - } - if (str.length() > 1 && Character.isUpperCase(str.charAt(1)) && Character.isUpperCase(str.charAt(0))) { - return str; - } - - char chars[] = str.toCharArray(); - char c = chars[0]; - char modifiedChar = Character.toLowerCase(c); - if (modifiedChar == c) { - return str; - } - chars[0] = modifiedChar; - return new String(chars); - } - - /** - * 反转字符串的大小写。 - * - *

- * 如果字符串是null则返回null。 - * - *

-     * StringUtil.swapCasing(null)                 = null
-     * StringUtil.swapCasing("")                   = ""
-     * StringUtil.swapCasing("The dog has a BONE") = "tHE DOG HAS A bone"
-     * 
- * - *

- * - * @param str 要转换的字符串 - * - * @return 大小写被反转的字符串,如果原字符串为null,则返回null - */ - public static String swapCase(String str) { - int strLen; - - if ((str == null) || ((strLen = str.length()) == 0)) { - return str; - } - - StringBuilder builder = new StringBuilder(strLen); - - char ch = 0; - - for (int i = 0; i < strLen; i++) { - ch = str.charAt(i); - - if (Character.isUpperCase(ch)) { - ch = Character.toLowerCase(ch); - } else if (Character.isTitleCase(ch)) { - ch = Character.toLowerCase(ch); - } else if (Character.isLowerCase(ch)) { - ch = Character.toUpperCase(ch); - } - - builder.append(ch); - } - - return builder.toString(); - } - - public static String fromCamelCase(String str, char separator) { - int strLen; - - if ((str == null) || ((strLen = str.length()) == 0)) { - return str; - } - StringBuilder result = new StringBuilder(strLen * 2); - int resultLength = 0; - boolean prevTranslated = false; - for (int i = 0; i < strLen; i++) { - char c = str.charAt(i); - if (i > 0 || c != separator) {// skip first starting separator - if (Character.isUpperCase(c)) { - if (!prevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != separator) { - result.append(separator); - resultLength++; - } - c = Character.toLowerCase(c); - prevTranslated = true; - } else { - prevTranslated = false; - } - result.append(c); - resultLength++; - } - } - return resultLength > 0 ? result.toString() : str; - } - - /** - * String2Short - * - * @param s - * @param def - * @return - */ - public static short toShort(String s, short def) { - try { - return (isEmpty(s)) ? def : Short.parseShort(s); - } catch (NumberFormatException e) { - return def; - } - } - - /** - * String2Int - * - * @param s - * @param def - * @return - */ - public static int toInt(String s, int def) { - try { - return (isEmpty(s)) ? def : Integer.parseInt(s); - } catch (NumberFormatException e) { - return def; - } - } - - /** - * String2Long - * - * @param s - * @param def - * @return - */ - public static long toLong(String s, long def) { - try { - return (isEmpty(s)) ? def : Long.parseLong(s); - } catch (NumberFormatException e) { - return def; - } - } - - /** - * String2Float - * - * @param s - * @param def - * @return - */ - public static float toFloat(String s, float def) { - try { - return (isEmpty(s)) ? def : Float.parseFloat(s); - } catch (NumberFormatException e) { - return def; - } - } - - /** - * String2Double - * - * @param s - * @param def - * @return - */ - public static double toDouble(String s, double def) { - try { - return (isEmpty(s)) ? def : Double.parseDouble(s); - } catch (NumberFormatException e) { - return def; - } - } - - /** - * String2Boolean - * - * @param s - * @param def - * @return - */ - public static boolean toBoolean(String s, boolean def) { - if (isEmpty(s)) - return def; - else { - return "true".equalsIgnoreCase(s); - } - } - - // ----------- 字符串截取 ----------- // - /** - * 截取 float/double 类型 一位小数 - * - * @param f - * @return - */ - public static String getDelFormat(Object f) { - DecimalFormat df = new DecimalFormat("0.0"); - return df.format(f); - } - - /** - * 截取 float/double 类型 两位小数 - * - * @param f - * @return - */ - public static String getDelFormat2(Object f) { - DecimalFormat df = new DecimalFormat("0.00"); - return df.format(f); - } - - /** - * 截取三位 - * - * @param f - * @return - */ - public static String getDelFormat3(Object f) { - DecimalFormat df = new DecimalFormat("0.000"); - return df.format(f); - } - - /** - * 截取字符串 先是一定的长多 多余... - * - * @param source - * 元字符串 - * @param len - * 显示长多 - * @return - */ - public static String getStringsubstr(String source, int len) { - if (null == source || "".equals(source)) { - return ""; - } - if (source.length() > len) { - return source.substring(0, len) + "..."; - } - - return source; - } - - // ----------- 随机数 ----------- // - /** - * 获得0-max的随机数 - * - * @param length - * @return String - */ - public static String getRandomNumber(int length, int max) { - Random random = new Random(); - StringBuffer buffer = new StringBuffer(); - - for (int i = 0; i < length; i++) { - buffer.append(random.nextInt(max)); - } - return buffer.toString(); - } - - /** - * 获取指定长度的随机数字组成的字符串 - * - * @param size - * @return - */ - public static String getRandomNumber(int size) { - String num = ""; - for (int i = 0; i < size; i++) { - double a = Math.random() * 9; - a = Math.ceil(a); - int randomNum = new Double(a).intValue(); - num += randomNum; - } - return num; - } - - /** - * 获取随机字符 - * - * @param size - * @return - */ - public static String getRandomChar(int size) { - String sRand = ""; - Random random = new Random();// 创建一个随机类 - for (int i = 0; i < size; i++) { - String ch = String.valueOf(RANDOM_CHAR.charAt(random.nextInt(RANDOM_CHAR.length()))); - sRand += ch; - } - return sRand; - } - - // ----------- 验证 ----------- // - /** - * 判断字符串是否为数字和有正确的值 - * - * @param str - * @return - */ - public static boolean isNumber(String str) { - // Pattern pattern=Pattern.compile("[0-9]*"); - // return pattern.matcher(str).matches(); - if (null != str && 0 != str.trim().length() && str.matches("\\d*")) { - return true; - } - - return false; - } - - public static boolean isBoolean(String value) { - if(null != value){ - String val = value.toLowerCase(); - if(val.equals("true") || val.equals("false")){ - return true; - } - } - return false; - } - - /** - * 将阿拉伯数字转为中文数字 - * - * @return - */ - public static String toChineseNumber(int number, int depth) { - if (depth < 0) - depth = 0; - if (number <= 0 && depth == 0) - return NUMBER[0]; - - String chinese = ""; - String src = number + ""; - if (src.charAt(src.length() - 1) == 'l' || src.charAt(src.length() - 1) == 'L') { - src = src.substring(0, src.length() - 1); - } - - if (src.length() > 4) - chinese = toChineseNumber(Integer.parseInt(src.substring(0, src.length() - 4)), depth + 1) - + toChineseNumber(Integer.parseInt(src.substring(src.length() - 4, src.length())), depth - 1); - else { - char prv = 0; - for (int i = 0; i < src.length(); i++) { - switch (src.charAt(i)) { - case '0': - if (prv != '0') - chinese = chinese + NUMBER[0]; - break; - case '1': - chinese = chinese + NUMBER[1]; - break; - case '2': - chinese = chinese + NUMBER[2]; - break; - case '3': - chinese = chinese + NUMBER[3]; - break; - case '4': - chinese = chinese + NUMBER[4]; - break; - case '5': - chinese = chinese + NUMBER[5]; - break; - case '6': - chinese = chinese + NUMBER[6]; - break; - case '7': - chinese = chinese + NUMBER[7]; - break; - case '8': - chinese = chinese + NUMBER[8]; - break; - case '9': - chinese = chinese + NUMBER[9]; - break; - } - prv = src.charAt(i); - - switch (src.length() - 1 - i) { - case 1:// 十 - if (prv != '0') - chinese = chinese + NUMBER[10]; - break; - case 2:// 百 - if (prv != '0') - chinese = chinese + NUMBER[11]; - break; - case 3:// 千 - if (prv != '0') - chinese = chinese + NUMBER[12]; - break; - } - } - } - while (chinese.length() > 0 && chinese.lastIndexOf(NUMBER[0]) == chinese.length() - 1) - chinese = chinese.substring(0, chinese.length() - 1); - if (depth == 1) - chinese += NUMBER[13]; - if (depth == 2) - chinese += NUMBER[14]; - return chinese; - } - - /** - * 验证字符串是否含有特殊字符和中文 - * - * @param - * - * @return - */ - public static boolean checkIsEnglish(String s) { - String Letters = "(){}[]\",.<>\\/~!@#$%^&*;': "; - int i; - int c; - - if (s.charAt(0) == '-') { - return false; - } - if (s.charAt(s.length() - 1) == '-') { - return false; - } - - for (i = 0; i < s.length(); i++) { - c = s.charAt(i); - if (Letters.indexOf(c) > -1) { - return false; - } - } - - // 验证是否刚好匹配 - boolean yesorno = isChineseStr(s); - if (yesorno) { - return false; - } - return true; - } - - public static boolean isChineseStr(String pValue) { - for (int i = 0; i < pValue.length(); i++) { - if ((int) pValue.charAt(i) > 256) - return true; - } - return false; - } - - /** - * 判断一个字符是Ascill字符还是其它字符(如汉,日,韩文字符) - * - * @param char c, 需要判断的字符 - * @return boolean, 返回true,Ascill字符 - */ - public static boolean isLetter(char c) { - int k = 0x80; - return c / k == 0 ? true : false; - } - - - // ----------- 格式化 ---------- // - /** - * 格式化数据 - * - * @param decima - * l3453454 - * @return 3,453,454 - */ - public final static String FormatDecimalString(String decimal) { - double dValue = Double.valueOf(decimal).doubleValue(); - DecimalFormat df = new DecimalFormat(); - String positivePattern = " ,000"; - String negativePattern = " ,000"; - if (dValue < 0) { - df.applyPattern(negativePattern); - return df.format(dValue).replace(',', ','); - } else { - df.applyPattern(positivePattern); - return df.format(dValue).replace(',', ','); - } - } - - /** - * 格式化数据 - * - * @param source - * 3453454 - * @return 3,453,454 - */ - public static String getNumberFormat(long source) { - NumberFormat usFormat = NumberFormat.getIntegerInstance(Locale.US); - return usFormat.format(source); - } - - // ----------- 过滤 ---------- // - /** - * 过滤字符串里的的特殊字符 - * - * @param str - * 要过滤的字符串 - * @return 过滤后的字符串 - */ - public static String stringFilter(String str) { - // 过滤通过页面表单提交的字符 - String[][] FilterChars = { { "<", "<" }, { ">", ">" }, { " ", " " }, { "\"", """ }, { "&", "&" }, - { "/", "/" }, { "\\", "\" }, { "'", "\\'" }, { "%", "%" } }; - - String[] str_arr = stringSpilit(str, ""); - - for (int i = 0; i < str_arr.length; i++) { - for (int j = 0; j < FilterChars.length; j++) { - if (FilterChars[j][0].equals(str_arr[i])) - str_arr[i] = FilterChars[j][1]; - } - } - return (stringConnect(str_arr, "")).trim(); - } - - // 关健字过滤 - public static String stringKeyWorldFilter(String str) { - // 过滤通过页面表单提交的字符 - String[][] FilterChars = { { "<", "" }, { ">", "" }, { "\"", "" }, { "&", "" }, { "/", "" }, { "\\", "" }, { "'", "" }, - { "%", "" } }; - - String[] str_arr = stringSpilit(str, ""); - - for (int i = 0; i < str_arr.length; i++) { - for (int j = 0; j < FilterChars.length; j++) { - if (FilterChars[j][0].equals(str_arr[i])) - str_arr[i] = FilterChars[j][1]; - } - } - return (stringConnect(str_arr, "")).trim(); - } - - public static String escapeJavaScript(String value) { - return escapeJava(value); - } - - public static String unescapeJavaScript(String value) { - return unescapeJava(value); - } - - public static String escapeJava(String value) { - if (value == null || value.length() == 0) { - return value; - } - int len = value.length(); - StringBuilder buf = null; - for (int i = 0; i < len; i++) { - char ch = value.charAt(i); - String rep; - switch (ch) { - case '\\': - rep = "\\\\"; - break; - case '\"': - rep = "\\\""; - break; - case '\'': - rep = "\\\'"; - break; - case '\t': - rep = "\\t"; - break; - case '\n': - rep = "\\n"; - break; - case '\r': - rep = "\\r"; - break; - case '\b': - rep = "\\b"; - break; - case '\f': - rep = "\\f"; - break; - default: - rep = null; - break; - } - if (rep != null) { - if (buf == null) { - buf = new StringBuilder(len * 2); - if (i > 0) { - buf.append(value.substring(0, i)); - } - } - buf.append(rep); - } else { - if (buf != null) { - buf.append(ch); - } - } - } - if (buf != null) { - return buf.toString(); - } - return value; - } - - public static String unescapeJava(String value) { - if (value == null || value.length() == 0) { - return value; - } - StringBuilder buf = null; - int len = value.length(); - int len1 = len - 1; - for (int i = 0; i < len; i++) { - char ch = value.charAt(i); - if (ch == '\\' && i < len1) { - int j = i; - i++; - ch = value.charAt(i); - switch (ch) { - case '\\': - ch = '\\'; - break; - case '\"': - ch = '\"'; - break; - case '\'': - ch = '\''; - break; - case 't': - ch = '\t'; - break; - case 'n': - ch = '\n'; - break; - case 'r': - ch = '\r'; - break; - case 'b': - ch = '\b'; - break; - case 'f': - ch = '\f'; - break; - case 'u': - ch = (char) Integer.parseInt(value.substring(i + 1, i + 5), 16); - i = i + 4; - break; - default: - j--; - } - if (buf == null) { - buf = new StringBuilder(len); - if (j > 0) { - buf.append(value.substring(0, j)); - } - } - buf.append(ch); - } else if (buf != null) { - buf.append(ch); - } - } - if (buf != null) { - return buf.toString(); - } - return value; - } - - // ----------- 切割合并 ---------- // - /** - * 分割字符串 - * - * @param str - * 要分割的字符串 - * @param spilit_sign - * 字符串的分割标志 - * @return 分割后得到的字符串数组 - */ - public static String[] stringSpilit(String str, String spilit_sign) { - String[] spilit_string = str.split(spilit_sign); - if (spilit_string[0].equals("")) { - String[] new_string = new String[spilit_string.length - 1]; - for (int i = 1; i < spilit_string.length; i++) - new_string[i - 1] = spilit_string[i]; - return new_string; - } else - return spilit_string; - } - - /** - * 用特殊的字符连接字符串 - * - * @param strings - * 要连接的字符串数组 - * @param spilit_sign - * 连接字符 - * @return 连接字符串 - */ - public static String stringConnect(String[] strings, String spilit_sign) { - StringBuffer str = new StringBuffer(""); - for (int i = 0; i < strings.length; i++) { - str.append(strings[i]).append(spilit_sign); - } - return str.toString(); - } - - /** - * 四舍五入 返回int类型 - * - * @param dSource - * 2342.45 - * @return 2342 - */ - public static int getRound(double dSource) { - int iRound; - // BigDecimal的构造函数参数类型是double - BigDecimal deSource = new BigDecimal(dSource); - // deSource.setScale(0,BigDecimal.ROUND_HALF_UP) 返回值类型 BigDecimal - // intValue() 方法将BigDecimal转化为int - iRound = deSource.setScale(0, BigDecimal.ROUND_HALF_UP).intValue(); - return iRound; - } - - /** - * 提供小数位四舍五入处理。 - * - * @param s - * 需要四舍五入的数字 - * @return 四舍五入后的结果 - */ - public static double round(double s) { - BigDecimal b = new BigDecimal(Double.toString(s)); - BigDecimal one = new BigDecimal("1"); - return b.divide(one, BigDecimal.ROUND_HALF_UP).doubleValue(); - } - - /** - * 提供小数位四舍五入处理。 - * - * @param s - * 需要四舍五入的数字 - * @return 四舍五入后的结果 - */ - public static long roundlong(double s) { - BigDecimal b = new BigDecimal(Double.toString(s)); - BigDecimal one = new BigDecimal("1"); - return b.divide(one, BigDecimal.ROUND_HALF_UP).longValue(); - } - - /** - * 得到一个字符串的长度,显示的长度,一个汉字或日韩文长度为2,英文字符长度为1 - * - * @param String - * s ,需要得到长度的字符串 - * @return int, 得到的字符串长度 - */ - public static int length(String s) { - if (s == null) - return 0; - char[] c = s.toCharArray(); - int len = 0; - for (int i = 0; i < c.length; i++) { - len++; - if (!isLetter(c[i])) { - len++; - } - } - return len; - } - - /** - * 功能:获得配置文件中指定编码字符串 - * - * @param str - * 解码字符串 charset 指定编码 - * - */ - public static String getStrByCharset(String str, String charset) throws UnsupportedEncodingException { - return new String(str.getBytes("ISO-8859-1"), charset); - } - - /** - * 提取字符串中的中文字符 - * - * @param str - * @return - */ - public static String getChineseByStr(String str) { - - StringBuilder resultStr = new StringBuilder(""); - - Pattern pcn = Pattern.compile("[\u4e00-\u9fa5]"); - Matcher m = pcn.matcher(str); - while (m.find()) { - resultStr.append(m.group().toString()); - } - - return resultStr.toString(); - } - - // 将两位小数的字符串*100 - public static String parseStrInt(String strDouble) { - String fen = ""; - int dotIndex = strDouble.lastIndexOf("."); - if (dotIndex >= 0) {// 有小数点字符串 - String zs = strDouble.substring(0, dotIndex); - if (!isNumber(zs)) { - return null; - } - fen = zs; - if (strDouble.substring(dotIndex).length() > 1) {// 有小数部分 - String xs = strDouble.substring(dotIndex).substring(1); - if (!isNumber(xs)) { - return null; - } - if (xs.length() >= 3) {// 截取后面部分 - xs = xs.substring(0, 2); - } else { - if (xs.length() < 2) { - xs = xs + "0"; - } - } - fen = zs + xs; - } else {// 没有小数 - return null; - } - - } else {// 无小数点字符串 - fen = strDouble + "00"; - } - return fen; - } - - /** - * 检查浮点数 - * - * @param num - * @param type - * "0+":非负浮点数 "+":正浮点数 "-0":非正浮点数 "-":负浮点数 "":浮点数 - * @return - */ - public static boolean checkFloat(String num, String type) { - String eL = ""; - if (type.equals("0+")) - eL = "^\\d+(\\.\\d+)?$";// 非负浮点数 - else if (type.equals("+")) - eL = "^((\\d+\\.\\d*[1-9]\\d*)|(\\d*[1-9]\\d*\\.\\d+)|(\\d*[1-9]\\d*))$";// 正浮点数 - else if (type.equals("-0")) - eL = "^((-\\d+(\\.\\d+)?)|(0+(\\.0+)?))$";// 非正浮点数 - else if (type.equals("-")) - eL = "^(-((\\d+\\.\\d*[1-9]\\d*)|(\\d*[1-9]\\d*\\.\\d+)|(\\d*[1-9]\\d*)))$";// 负浮点数 - else - eL = "^(-?\\d+)(\\.\\d+)?$";// 浮点数 - Pattern p = Pattern.compile(eL); - Matcher m = p.matcher(num); - boolean b = m.matches(); - return b; - } - - /** - * 替换字符串 - * - * @param inString - * @param oldPattern - * @param newPattern - * @return - */ - public static String replace(String inString, String oldPattern, String newPattern) { - if (isEmpty(inString) || isEmpty(oldPattern) || newPattern == null) { - return inString; - } - StringBuilder sb = new StringBuilder(); - int pos = 0; // our position in the old string - int index = inString.indexOf(oldPattern); - // the index of an occurrence we've found, or -1 - int patLen = oldPattern.length(); - while (index >= 0) { - sb.append(inString.substring(pos, index)); - sb.append(newPattern); - pos = index + patLen; - index = inString.indexOf(oldPattern, pos); - } - sb.append(inString.substring(pos)); - // remember to append any characters to the right of a match - return sb.toString(); - } - - public static String deleteAny(String inString, String charsToDelete) { - if (isEmpty(inString) || isEmpty(charsToDelete)) { - return inString; - } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < inString.length(); i++) { - char c = inString.charAt(i); - if (charsToDelete.indexOf(c) == -1) { - sb.append(c); - } - } - return sb.toString(); - } - - /** - * 获取文件名称 - * - * @param path - * @return - */ - public static String getFilename(String path) { - if (path == null) { - return null; - } - int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); - return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path); - } - - public static String applyRelativePath(String path, String relativePath) { - int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); - if (separatorIndex != -1) { - String newPath = path.substring(0, separatorIndex); - if (!relativePath.startsWith(FOLDER_SEPARATOR)) { - newPath += FOLDER_SEPARATOR; - } - return newPath + relativePath; - } else { - return relativePath; - } - } - - public static String cleanPath(String path) { - if (path == null) { - return null; - } - String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR); - - // Strip prefix from path to analyze, to not treat it as part of the - // first path element. This is necessary to correctly parse paths like - // "file:core/../core/io/Resource.class", where the ".." should just - // strip the first "core" directory while keeping the "file:" prefix. - int prefixIndex = pathToUse.indexOf(":"); - String prefix = ""; - if (prefixIndex != -1) { - prefix = pathToUse.substring(0, prefixIndex + 1); - pathToUse = pathToUse.substring(prefixIndex + 1); - } - if (pathToUse.startsWith(FOLDER_SEPARATOR)) { - prefix = prefix + FOLDER_SEPARATOR; - pathToUse = pathToUse.substring(1); - } - - String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR); - List pathElements = new LinkedList(); - int tops = 0; - - for (int i = pathArray.length - 1; i >= 0; i--) { - String element = pathArray[i]; - if (CURRENT_PATH.equals(element)) { - // Points to current directory - drop it. - } else if (TOP_PATH.equals(element)) { - // Registering top path found. - tops++; - } else { - if (tops > 0) { - // Merging path element with element corresponding to top path. - tops--; - } else { - // Normal path element found. - pathElements.add(0, element); - } - } - } - - // Remaining top paths need to be retained. - for (int i = 0; i < tops; i++) { - pathElements.add(0, TOP_PATH); - } - - return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); - } - - public static String[] toStringArray(Collection collection) { - if (collection == null) { - return null; - } - return collection.toArray(new String[collection.size()]); - } - - public static String[] delimitedListToStringArray(String str, String delimiter) { - return delimitedListToStringArray(str, delimiter, null); - } - - public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) { - if (str == null) { - return new String[0]; - } - if (delimiter == null) { - return new String[] {str}; - } - List result = new ArrayList(); - if ("".equals(delimiter)) { - for (int i = 0; i < str.length(); i++) { - result.add(deleteAny(str.substring(i, i + 1), charsToDelete)); - } - } else { - int pos = 0; - int delPos; - while ((delPos = str.indexOf(delimiter, pos)) != -1) { - result.add(deleteAny(str.substring(pos, delPos), charsToDelete)); - pos = delPos + delimiter.length(); - } - if (str.length() > 0 && pos <= str.length()) { - // Add rest of String, but not in case of empty input. - result.add(deleteAny(str.substring(pos), charsToDelete)); - } - } - return toStringArray(result); - } - - public static String collectionToDelimitedString(Collection coll, String delim, String prefix, String suffix) { - if (CollectionKit.isEmpty(coll)) { - return ""; - } - StringBuilder sb = new StringBuilder(); - Iterator it = coll.iterator(); - while (it.hasNext()) { - sb.append(prefix).append(it.next()).append(suffix); - if (it.hasNext()) { - sb.append(delim); - } - } - return sb.toString(); - } - - public static String collectionToDelimitedString(Collection coll, String delim) { - return collectionToDelimitedString(coll, delim, "", ""); - } - - public static String firstUpperCase(String str) { - return str.substring(0, 1).toUpperCase() + str.substring(1); - } - - public static String join(final String[] array, final String separator) { - if (array == null) { - return null; - } - final int noOfItems = array.length; - if (noOfItems <= 0) { - return null; - } - if (noOfItems == 1) { - return array[0].toString(); - } - final StringBuilder buf = new StringBuilder(noOfItems * 16); - for (int i = 0; i < noOfItems; i++) { - buf.append(separator); - if (array[i] != null) { - buf.append(array[i]); - } - } - return buf.toString(); - } - - public static String join(final Object[] array, final String separator) { - if (array == null) { - return null; - } - final int noOfItems = array.length; - if (noOfItems <= 0) { - return null; - } - if (noOfItems == 1) { - return array[0].toString(); - } - final StringBuilder buf = new StringBuilder(noOfItems * 16); - for (int i = 0; i < noOfItems; i++) { - buf.append(separator); - if (array[i] != null) { - buf.append(array[i]); - } - } - return buf.toString(); - } - - public static String join(final List array, final String separator) { - if (array == null) { - return null; - } - final int noOfItems = array.size(); - if (noOfItems <= 0) { - return null; - } - if (noOfItems == 1) { - return array.get(0).toString(); - } - final StringBuilder buf = new StringBuilder(noOfItems * 16); - for (int i = 0; i < noOfItems; i++) { - buf.append(separator); - if (array.get(i) != null) { - buf.append(array.get(i)); - } - } - return buf.toString(); - } - - public static String join(String... parts) { - StringBuilder sb = new StringBuilder(parts.length); - for (String part : parts) { - sb.append(part); - } - return sb.toString(); - } - - public static String join(Iterable elements, String separator) { - if (elements == null) { - return ""; - } - return join(elements.iterator(), separator); - } - - public static String join(Iterator elements, String separator) { - if (elements == null) { - return ""; - } - StringBuilder sb = new StringBuilder(); - while (elements.hasNext()) { - Object o = elements.next(); - if (sb.length() > 0 && separator != null) { - sb.append(separator); - } - sb.append(o); - } - return sb.toString(); - } - - /** - * 随机获取UUID字符串(无中划线) - * - * @return UUID字符串 - */ - public static String getUUID() { - String uuid = UUID.randomUUID().toString(); - return uuid.substring(0, 8) + uuid.substring(9, 13) + uuid.substring(14, 18) + uuid.substring(19, 23) - + uuid.substring(24); - } - - /** - * 随机获取字符串 - * - * @param length 随机字符串长度 - * @return 随机字符串 - */ - public static String random(int length) { - if (length <= 0) { - return ""; - } - char[] randomChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', - 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm' }; - Random random = new Random(); - StringBuffer stringBuffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - stringBuffer.append(randomChar[Math.abs(random.nextInt()) % randomChar.length]); - } - return stringBuffer.toString(); - } - - /** - * 根据指定长度 分隔字符串 - * - * @param str 需要处理的字符串 - * @param length 分隔长度 - * @return 字符串集合 - */ - public static List split(String str, int length) { - List list = new ArrayList(); - for (int i = 0; i < str.length(); i += length) { - int endIndex = i + length; - if (endIndex <= str.length()) { - list.add(str.substring(i, i + length)); - } else { - list.add(str.substring(i, str.length() - 1)); - } - } - return list; - } - - /** - * 将字符串按空白字符分割。 - * - *

- * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为null,则返回null。 - * - *

-     * StringUtil.split(null)       = null
-     * StringUtil.split("")         = []
-     * StringUtil.split("abc def")  = ["abc", "def"]
-     * StringUtil.split("abc  def") = ["abc", "def"]
-     * StringUtil.split(" abc ")    = ["abc"]
-     * 
- * - *

- * - * @param str 要分割的字符串 - * - * @return 分割后的字符串数组,如果原字符串为null,则返回null - */ - public static String[] split(String str) { - return split(str, null, -1); - } - - /** - * 将String to long list - * - * @param source - * @param token - * @return - */ - public static List parseStringToLongList(String source, String token) { - - if (isBlank(source) || isEmpty(token)) { - return null; - } - - List result = new ArrayList(); - String[] units = source.split(token); - for (String unit : units) { - result.add(Long.valueOf(unit)); - } - - return result; - } - - /** - * Splits a string in several parts (tokens) that are separated by delimiter. Delimiter is always surrounded - * by two strings! If there is no content between two delimiters, empty string will be returned for that token. - * Therefore, the length of the returned array will always be: #delimiters + 1. - *

- * Method is much, much faster then regexp String.split(), and a bit faster then - * StringTokenizer. - * - * @param src string to split - * @param delimiter split delimiter - * - * @return array of split strings - */ - public static String[] splitNoCompress(String src, String delimiter) { - if (src == null || delimiter == null) { - return null; - } - int maxparts = (src.length() / delimiter.length()) + 2; // one more for - // the last - int[] positions = new int[maxparts]; - int dellen = delimiter.length(); - - int i, j = 0; - int count = 0; - positions[0] = -dellen; - while ((i = src.indexOf(delimiter, j)) != -1) { - count++; - positions[count] = i; - j = i + dellen; - } - count++; - positions[count] = src.length(); - - String[] result = new String[count]; - - for (i = 0; i < count; i++) { - result[i] = src.substring(positions[i] + dellen, positions[i + 1]); - } - return result; - } - - public static String[] splitc(String src, String d) { - if (isAnyEmpty(src, d)) { - return new String[] { src }; - } - char[] delimiters = d.toCharArray(); - char[] srcc = src.toCharArray(); - - int maxparts = srcc.length + 1; - int[] start = new int[maxparts]; - int[] end = new int[maxparts]; - - int count = 0; - - start[0] = 0; - int s = 0, e; - if (CharKit.equalsOne(srcc[0], delimiters)) { // string starts with - // delimiter - end[0] = 0; - count++; - s = CharKit.findFirstDiff(srcc, 1, delimiters); - if (s == -1) { // nothing after delimiters - return new String[] { "", "" }; - } - start[1] = s; // new start - } - while (true) { - // find new end - e = CharKit.findFirstEqual(srcc, s, delimiters); - if (e == -1) { - end[count] = srcc.length; - break; - } - end[count] = e; - // find new start - count++; - s = CharKit.findFirstDiff(srcc, e, delimiters); - if (s == -1) { - start[count] = end[count] = srcc.length; - break; - } - start[count] = s; - } - count++; - String[] result = new String[count]; - for (int i = 0; i < count; i++) { - result[i] = src.substring(start[i], end[i]); - } - return result; - } - - public static String[] splitc(String src, char delimiter) { - if (isEmpty(src)) { - return new String[] { "" }; - } - char[] srcc = src.toCharArray(); - - int maxparts = srcc.length + 1; - int[] start = new int[maxparts]; - int[] end = new int[maxparts]; - - int count = 0; - - start[0] = 0; - int s = 0, e; - if (srcc[0] == delimiter) { // string starts with delimiter - end[0] = 0; - count++; - s = CharKit.findFirstDiff(srcc, 1, delimiter); - if (s == -1) { // nothing after delimiters - return new String[] { "", "" }; - } - start[1] = s; // new start - } - while (true) { - // find new end - e = CharKit.findFirstEqual(srcc, s, delimiter); - if (e == -1) { - end[count] = srcc.length; - break; - } - end[count] = e; - // find new start - count++; - s = CharKit.findFirstDiff(srcc, e, delimiter); - if (s == -1) { - start[count] = end[count] = srcc.length; - break; - } - start[count] = s; - } - count++; - String[] result = new String[count]; - for (int i = 0; i < count; i++) { - result[i] = src.substring(start[i], end[i]); - } - return result; - } - - public static String[] splitc(String src, char[] delimiters) { - if (isEmpty(src) || null == delimiters || delimiters.length == 0) { - return new String[] { src }; - } - char[] srcc = src.toCharArray(); - - int maxparts = srcc.length + 1; - int[] start = new int[maxparts]; - int[] end = new int[maxparts]; - - int count = 0; - - start[0] = 0; - int s = 0, e; - if (CharKit.equalsOne(srcc[0], delimiters) == true) { // string start - // with - // delimiter - end[0] = 0; - count++; - s = CharKit.findFirstDiff(srcc, 1, delimiters); - if (s == -1) { // nothing after delimiters - return new String[] { "", "" }; - } - start[1] = s; // new start - } - while (true) { - // find new end - e = CharKit.findFirstEqual(srcc, s, delimiters); - if (e == -1) { - end[count] = srcc.length; - break; - } - end[count] = e; - - // find new start - count++; - s = CharKit.findFirstDiff(srcc, e, delimiters); - if (s == -1) { - start[count] = end[count] = srcc.length; - break; - } - start[count] = s; - } - count++; - String[] result = new String[count]; - for (int i = 0; i < count; i++) { - result[i] = src.substring(start[i], end[i]); - } - return result; - } - - /** - * 将字符串按指定字符分割。 - * - *

- * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为null,则返回null。 - * - *

-     * StringUtil.split(null, *)         = null
-     * StringUtil.split("", *)           = []
-     * StringUtil.split("a.b.c", '.')    = ["a", "b", "c"]
-     * StringUtil.split("a..b.c", '.')   = ["a", "b", "c"]
-     * StringUtil.split("a:b:c", '.')    = ["a:b:c"]
-     * StringUtil.split("a b c", ' ')    = ["a", "b", "c"]
-     * 
- * - *

- * - * @param str 要分割的字符串 - * @param separatorChar 分隔符 - * - * @return 分割后的字符串数组,如果原字符串为null,则返回null - */ - public static String[] split(String str, char separatorChar) { - if (str == null) { - return null; - } - - int length = str.length(); - - if (length == 0) { - return Emptys.EMPTY_STRING_ARRAY; - } - - List list = CollectionKit.createArrayList(); - int i = 0; - int start = 0; - boolean match = false; - - while (i < length) { - if (str.charAt(i) == separatorChar) { - if (match) { - list.add(str.substring(start, i)); - match = false; - } - - start = ++i; - continue; - } - - match = true; - i++; - } - - if (match) { - list.add(str.substring(start, i)); - } - - return list.toArray(new String[list.size()]); - } - - /** - * 将字符串按指定字符分割。 - * - *

- * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为null,则返回null。 - * - *

-     * StringUtil.split(null, *)                = null
-     * StringUtil.split("", *)                  = []
-     * StringUtil.split("abc def", null)        = ["abc", "def"]
-     * StringUtil.split("abc def", " ")         = ["abc", "def"]
-     * StringUtil.split("abc  def", " ")        = ["abc", "def"]
-     * StringUtil.split(" ab:  cd::ef  ", ":")  = ["ab", "cd", "ef"]
-     * StringUtil.split("abc.def", "")          = ["abc.def"]
-     * 
- * - *

- * - * @param str 要分割的字符串 - * @param separatorChars 分隔符 - * - * @return 分割后的字符串数组,如果原字符串为null,则返回null - */ - public static String[] split(String str, String separatorChars) { - return split(str, separatorChars, -1); - } - - /** - * 将字符串按指定字符分割。 - * - *

- * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为null,则返回null。 - * - *

-     * StringUtil.split(null, *, *)                 = null
-     * StringUtil.split("", *, *)                   = []
-     * StringUtil.split("ab cd ef", null, 0)        = ["ab", "cd", "ef"]
-     * StringUtil.split("  ab   cd ef  ", null, 0)  = ["ab", "cd", "ef"]
-     * StringUtil.split("ab:cd::ef", ":", 0)        = ["ab", "cd", "ef"]
-     * StringUtil.split("ab:cd:ef", ":", 2)         = ["ab", "cdef"]
-     * StringUtil.split("abc.def", "", 2)           = ["abc.def"]
-     * 
- * - *

- * - * @param str 要分割的字符串 - * @param separatorChars 分隔符 - * @param max 返回的数组的最大个数,如果小于等于0,则表示无限制 - * - * @return 分割后的字符串数组,如果原字符串为null,则返回null - */ - public static String[] split(String str, String separatorChars, int max) { - if (str == null) { - return null; - } - - int length = str.length(); - - if (length == 0) { - return Emptys.EMPTY_STRING_ARRAY; - } - - List list = CollectionKit.createArrayList(); - int sizePlus1 = 1; - int i = 0; - int start = 0; - boolean match = false; - - if (separatorChars == null) { - // null表示使用空白作为分隔符 - while (i < length) { - if (Character.isWhitespace(str.charAt(i))) { - if (match) { - if (sizePlus1++ == max) { - i = length; - } - - list.add(str.substring(start, i)); - match = false; - } - - start = ++i; - continue; - } - - match = true; - i++; - } - } else if (separatorChars.length() == 1) { - // 优化分隔符长度为1的情形 - char sep = separatorChars.charAt(0); - - while (i < length) { - if (str.charAt(i) == sep) { - if (match) { - if (sizePlus1++ == max) { - i = length; - } - - list.add(str.substring(start, i)); - match = false; - } - - start = ++i; - continue; - } - - match = true; - i++; - } - } else { - // 一般情形 - while (i < length) { - if (separatorChars.indexOf(str.charAt(i)) >= 0) { - if (match) { - if (sizePlus1++ == max) { - i = length; - } - - list.add(str.substring(start, i)); - match = false; - } - - start = ++i; - continue; - } - - match = true; - i++; - } - } - - if (match) { - list.add(str.substring(start, i)); - } - - return list.toArray(new String[list.size()]); - } - - /** - * Convenience method to return a String array as a CSV String. - * E.g. useful for {@code toString()} implementations. - * @param arr the array to display - * @return the delimited String - */ - public static String arrayToCommaDelimitedString(Object[] arr) { - return arrayToDelimitedString(arr, ","); - } - - /** - * Convenience method to return a String array as a delimited (e.g. CSV) - * String. E.g. useful for {@code toString()} implementations. - * @param arr the array to display - * @param delim the delimiter to use (probably a ",") - * @return the delimited String - */ - public static String arrayToDelimitedString(Object[] arr, String delim) { - if (arr == null || arr.length == 0) { - return ""; - } - - if (arr.length == 1) { - return nullSafeToString(arr[0]); - } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < arr.length; i++) { - if (i > 0) { - sb.append(delim); - } - sb.append(arr[i]); - } - return sb.toString(); - } - - /** - * Determine if the given objects are equal, returning {@code true} - * if both are {@code null} or {@code false} if only one is - * {@code null}. - *

Compares arrays with {@code Arrays.equals}, performing an equality - * check based on the array elements rather than the array reference. - * @param o1 first Object to compare - * @param o2 second Object to compare - * @return whether the given objects are equal - * @see java.util.Arrays#equals - */ - public static boolean nullSafeEquals(Object o1, Object o2) { - if (o1 == o2) { - return true; - } - if (o1 == null || o2 == null) { - return false; - } - if (o1.equals(o2)) { - return true; - } - if (o1.getClass().isArray() && o2.getClass().isArray()) { - if (o1 instanceof Object[] && o2 instanceof Object[]) { - return Arrays.equals((Object[]) o1, (Object[]) o2); - } - if (o1 instanceof boolean[] && o2 instanceof boolean[]) { - return Arrays.equals((boolean[]) o1, (boolean[]) o2); - } - if (o1 instanceof byte[] && o2 instanceof byte[]) { - return Arrays.equals((byte[]) o1, (byte[]) o2); - } - if (o1 instanceof char[] && o2 instanceof char[]) { - return Arrays.equals((char[]) o1, (char[]) o2); - } - if (o1 instanceof double[] && o2 instanceof double[]) { - return Arrays.equals((double[]) o1, (double[]) o2); - } - if (o1 instanceof float[] && o2 instanceof float[]) { - return Arrays.equals((float[]) o1, (float[]) o2); - } - if (o1 instanceof int[] && o2 instanceof int[]) { - return Arrays.equals((int[]) o1, (int[]) o2); - } - if (o1 instanceof long[] && o2 instanceof long[]) { - return Arrays.equals((long[]) o1, (long[]) o2); - } - if (o1 instanceof short[] && o2 instanceof short[]) { - return Arrays.equals((short[]) o1, (short[]) o2); - } - } - return false; - } - - public static String nullSafeToString(Object obj) { - if (obj == null) { - return "null"; - } - if (obj instanceof String) { - return (String) obj; - } - if (obj instanceof Object[]) { - return nullSafeToString((Object[]) obj); - } - if (obj instanceof boolean[]) { - return nullSafeToString((boolean[]) obj); - } - if (obj instanceof byte[]) { - return nullSafeToString((byte[]) obj); - } - if (obj instanceof char[]) { - return nullSafeToString((char[]) obj); - } - if (obj instanceof double[]) { - return nullSafeToString((double[]) obj); - } - if (obj instanceof float[]) { - return nullSafeToString((float[]) obj); - } - if (obj instanceof int[]) { - return nullSafeToString((int[]) obj); - } - if (obj instanceof long[]) { - return nullSafeToString((long[]) obj); - } - if (obj instanceof short[]) { - return nullSafeToString((short[]) obj); - } - String str = obj.toString(); - return (str != null ? str : ""); - } - - /** - * 将字符串List转化为字符串,以分隔符间隔. - * - * @param list 需要处理的List. - * @param separator 分隔符. - * @return 转化后的字符串 - */ - public static String toString(List list, String separator) { - StringBuffer stringBuffer = new StringBuffer(); - for (String str : list) { - stringBuffer.append(separator + str); - } - stringBuffer.deleteCharAt(0); - return stringBuffer.toString(); - } - - public static String toString(Object value) { - if (value == null) { - return null; - } - return value.toString(); - } - - public static String toString(Collection collection) { - return toString(collection, " "); - } - - public static String toString(Collection collection, String split) { - if (collection == null || split == null) { - return null; - } - - StringBuilder builder = new StringBuilder(); - for (Object object : collection) { - builder.append(object).append(split); - } - - builder.setLength(builder.length() - split.length()); - return builder.toString(); - } - - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; + +import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Random; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 有关字符串处理的工具类。 + * + * @author biezhi + * @since 1.0 + */ +public abstract class StringKit { + + private static final String FOLDER_SEPARATOR = "/"; + private static final String WINDOWS_FOLDER_SEPARATOR = "\\"; + private static final String TOP_PATH = ".."; + private static final String CURRENT_PATH = "."; + public static String[] NUMBER = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "百", "千", "万", "亿" }; + public static final String CREATE = "create"; + public static final String DELETE = "delete"; + public static final String SAVE = "save"; + public static final String UPDATE = "update"; + public static final String QUERY = "query"; + public static final String ERROR = "error"; + public static final String SUCCESS = "success"; + public static final String FAILED = "failed"; + public static final String IP = "strIp"; + public static final String ANSWER = "strAnswer"; + public static final String LOGIN = "login"; + public static final String INDEX = "index"; + public static final String HOME = "home"; + public static final String NORIGHT = "noRight"; + public static final String BOSSIP = "strBOSSIp"; + public static final String BOSSIPS = "BOSSIPS";// 配置文件参数 + public static final String BOSSANSWER = "BOSSANSWER";// 配置文件参数 + private static final String RANDOM_CHAR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + /** + * 检查字符串是否为null或空字符串""。 + * + *

+     * StringUtil.isEmpty(null)      = true
+     * StringUtil.isEmpty("")        = true
+     * StringUtil.isEmpty(" ")       = false
+     * StringUtil.isEmpty("bob")     = false
+     * StringUtil.isEmpty("  bob  ") = false
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果为空, 则返回true + */ + public static boolean isEmpty(String str) { + return (str == null || str.length() == 0) ? true : false; + } + + public static boolean isAnyEmpty(String...strings) { + if (strings == null) { + return true; + } + for (String string : strings) { + if (isEmpty(string)) { + return true; + } + } + return false; + } + + /** + * 检查字符串是否不是null和空字符串""。 + * + *
+     * StringUtil.isEmpty(null)      = false
+     * StringUtil.isEmpty("")        = false
+     * StringUtil.isEmpty(" ")       = true
+     * StringUtil.isEmpty("bob")     = true
+     * StringUtil.isEmpty("  bob  ") = true
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果不为空, 则返回true + */ + public static boolean isNotEmpty(String str) { + return !isEmpty(str); + } + + /** + * 检查字符串是否是空白:null、空字符串""或只有空白字符。 + * + *
+     * StringUtil.isBlank(null)      = true
+     * StringUtil.isBlank("")        = true
+     * StringUtil.isBlank(" ")       = true
+     * StringUtil.isBlank("bob")     = false
+     * StringUtil.isBlank("  bob  ") = false
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果为空白, 则返回true + */ + public static boolean isBlank(String str) { + int length; + + if ((str == null) || ((length = str.length()) == 0)) { + return true; + } + + for (int i = 0; i < length; i++) { + if (!Character.isWhitespace(str.charAt(i))) { + return false; + } + } + + return true; + } + + public static boolean isAllBlank(String...strings) { + if (strings == null) { + return true; + } + for (String string : strings) { + if (isNotBlank(string)) { + return false; + } + } + return true; + } + + public static boolean isAnyBlank(String...strings) { + if (strings == null) { + return true; + } + for (String string : strings) { + if (isBlank(string)) { + return true; + } + } + return false; + } + + /** + * 检查字符串是否不是空白:null、空字符串""或只有空白字符。 + * + *
+     * StringUtil.isBlank(null)      = false
+     * StringUtil.isBlank("")        = false
+     * StringUtil.isBlank(" ")       = false
+     * StringUtil.isBlank("bob")     = true
+     * StringUtil.isBlank("  bob  ") = true
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果为空白, 则返回true + */ + public static boolean isNotBlank(String str) { + int length; + + if ((str == null) || ((length = str.length()) == 0)) { + return false; + } + + for (int i = 0; i < length; i++) { + if (!Character.isWhitespace(str.charAt(i))) { + return true; + } + } + + return false; + } + + /** + * 如果字符串是null,则返回指定默认字符串,否则返回字符串本身。 + * + *
+     * StringUtil.defaultIfNull(null, "default")  = "default"
+     * StringUtil.defaultIfNull("", "default")    = ""
+     * StringUtil.defaultIfNull("  ", "default")  = "  "
+     * StringUtil.defaultIfNull("bat", "default") = "bat"
+     * 
+ * + * @param str 要转换的字符串 + * @param defaultStr 默认字符串 + * + * @return 字符串本身或指定的默认字符串 + */ + public static String defaultIfNull(String str) { + return (str == null) ? "" : str; + } + + /** + * 如果字符串是null,则返回指定默认字符串,否则返回字符串本身。 + * + *
+     * StringUtil.defaultIfNull(null, "default")  = "default"
+     * StringUtil.defaultIfNull("", "default")    = ""
+     * StringUtil.defaultIfNull("  ", "default")  = "  "
+     * StringUtil.defaultIfNull("bat", "default") = "bat"
+     * 
+ * + * @param str 要转换的字符串 + * @param defaultStr 默认字符串 + * + * @return 字符串本身或指定的默认字符串 + */ + public static String defaultIfNull(String str, String defaultStr) { + return (str == null) ? defaultStr : str; + } + + /** + * 除去字符串头尾部的空白,如果字符串是null,依然返回null。 + * + *

+ * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + *

+     * StringUtil.trim(null)          = null
+     * StringUtil.trim("")            = ""
+     * StringUtil.trim("     ")       = ""
+     * StringUtil.trim("abc")         = "abc"
+     * StringUtil.trim("    abc    ") = "abc"
+     * 
+ * + *

+ * + * @param str 要处理的字符串 + * + * @return 除去空白的字符串,如果原字串为null,则返回null + */ + public static String trim(String str) { + return trim(str, null, 0); + } + + /** + * Trims array of strings. null array elements are ignored. + */ + public static void trimAll(String[] strings) { + if (strings == null) { + return; + } + for (int i = 0; i < strings.length; i++) { + String string = strings[i]; + if (string != null) { + strings[i] = trim(string); + } + } + } + + /** + * 除去字符串头尾部的指定字符,如果字符串是null,依然返回null。 + * + *
+     * StringUtil.trim(null, *)          = null
+     * StringUtil.trim("", *)            = ""
+     * StringUtil.trim("abc", null)      = "abc"
+     * StringUtil.trim("  abc", null)    = "abc"
+     * StringUtil.trim("abc  ", null)    = "abc"
+     * StringUtil.trim(" abc ", null)    = "abc"
+     * StringUtil.trim("  abcyx", "xyz") = "  abc"
+     * 
+ * + * @param str 要处理的字符串 + * @param stripChars 要除去的字符,如果为null表示除去空白字符 + * + * @return 除去指定字符后的的字符串,如果原字串为null,则返回null + */ + public static String trim(String str, String stripChars) { + return trim(str, stripChars, 0); + } + + /** + * 除去字符串头部的空白,如果字符串是null,则返回null。 + * + *

+ * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + *

+     * StringUtil.trimStart(null)         = null
+     * StringUtil.trimStart("")           = ""
+     * StringUtil.trimStart("abc")        = "abc"
+     * StringUtil.trimStart("  abc")      = "abc"
+     * StringUtil.trimStart("abc  ")      = "abc  "
+     * StringUtil.trimStart(" abc ")      = "abc "
+     * 
+ * + *

+ * + * @param str 要处理的字符串 + * + * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null + */ + public static String trimStart(String str) { + return trim(str, null, -1); + } + + /** + * 除去字符串头部的指定字符,如果字符串是null,依然返回null。 + * + *
+     * StringUtil.trimStart(null, *)          = null
+     * StringUtil.trimStart("", *)            = ""
+     * StringUtil.trimStart("abc", "")        = "abc"
+     * StringUtil.trimStart("abc", null)      = "abc"
+     * StringUtil.trimStart("  abc", null)    = "abc"
+     * StringUtil.trimStart("abc  ", null)    = "abc  "
+     * StringUtil.trimStart(" abc ", null)    = "abc "
+     * StringUtil.trimStart("yxabc  ", "xyz") = "abc  "
+     * 
+ * + * @param str 要处理的字符串 + * @param stripChars 要除去的字符,如果为null表示除去空白字符 + * + * @return 除去指定字符后的的字符串,如果原字串为null,则返回null + */ + public static String trimStart(String str, String stripChars) { + return trim(str, stripChars, -1); + } + + /** + * 除去字符串尾部的空白,如果字符串是null,则返回null。 + * + *

+ * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + *

+     * StringUtil.trimEnd(null)       = null
+     * StringUtil.trimEnd("")         = ""
+     * StringUtil.trimEnd("abc")      = "abc"
+     * StringUtil.trimEnd("  abc")    = "  abc"
+     * StringUtil.trimEnd("abc  ")    = "abc"
+     * StringUtil.trimEnd(" abc ")    = " abc"
+     * 
+ * + *

+ * + * @param str 要处理的字符串 + * + * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null + */ + public static String trimEnd(String str) { + return trim(str, null, 1); + } + + /** + * 除去字符串尾部的指定字符,如果字符串是null,依然返回null。 + * + *
+     * StringUtil.trimEnd(null, *)          = null
+     * StringUtil.trimEnd("", *)            = ""
+     * StringUtil.trimEnd("abc", "")        = "abc"
+     * StringUtil.trimEnd("abc", null)      = "abc"
+     * StringUtil.trimEnd("  abc", null)    = "  abc"
+     * StringUtil.trimEnd("abc  ", null)    = "abc"
+     * StringUtil.trimEnd(" abc ", null)    = " abc"
+     * StringUtil.trimEnd("  abcyx", "xyz") = "  abc"
+     * 
+ * + * @param str 要处理的字符串 + * @param stripChars 要除去的字符,如果为null表示除去空白字符 + * + * @return 除去指定字符后的的字符串,如果原字串为null,则返回null + */ + public static String trimEnd(String str, String stripChars) { + return trim(str, stripChars, 1); + } + + /** + * 除去字符串头尾部的空白,如果结果字符串是空字符串"",则返回null。 + * + *

+ * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + *

+     * StringUtil.trimToNull(null)          = null
+     * StringUtil.trimToNull("")            = null
+     * StringUtil.trimToNull("     ")       = null
+     * StringUtil.trimToNull("abc")         = "abc"
+     * StringUtil.trimToNull("    abc    ") = "abc"
+     * 
+ * + *

+ * + * @param str 要处理的字符串 + * + * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null + */ + public static String trimToNull(String str) { + return trimToNull(str, null); + } + + /** + * 除去字符串头尾部的空白,如果结果字符串是空字符串"",则返回null。 + * + *

+ * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + *

+     * StringUtil.trim(null, *)          = null
+     * StringUtil.trim("", *)            = null
+     * StringUtil.trim("abc", null)      = "abc"
+     * StringUtil.trim("  abc", null)    = "abc"
+     * StringUtil.trim("abc  ", null)    = "abc"
+     * StringUtil.trim(" abc ", null)    = "abc"
+     * StringUtil.trim("  abcyx", "xyz") = "  abc"
+     * 
+ * + *

+ * + * @param str 要处理的字符串 + * @param stripChars 要除去的字符,如果为null表示除去空白字符 + * + * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null + */ + public static String trimToNull(String str, String stripChars) { + String result = trim(str, stripChars); + + if ((result == null) || (result.length() == 0)) { + return null; + } + + return result; + } + + /** + * 除去字符串头尾部的空白,如果字符串是null,则返回空字符串""。 + * + *

+ * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + *

+     * StringUtil.trimToEmpty(null)          = ""
+     * StringUtil.trimToEmpty("")            = ""
+     * StringUtil.trimToEmpty("     ")       = ""
+     * StringUtil.trimToEmpty("abc")         = "abc"
+     * StringUtil.trimToEmpty("    abc    ") = "abc"
+     * 
+ * + *

+ * + * @param str 要处理的字符串 + * + * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null + */ + public static String trimToEmpty(String str) { + return trimToEmpty(str, null); + } + + /** + * 除去字符串头尾部的空白,如果字符串是null,则返回空字符串""。 + * + *

+ * 注意,和String.trim不同,此方法使用Character.isWhitespace 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + *

+     * StringUtil.trim(null, *)          = ""
+     * StringUtil.trim("", *)            = ""
+     * StringUtil.trim("abc", null)      = "abc"
+     * StringUtil.trim("  abc", null)    = "abc"
+     * StringUtil.trim("abc  ", null)    = "abc"
+     * StringUtil.trim(" abc ", null)    = "abc"
+     * StringUtil.trim("  abcyx", "xyz") = "  abc"
+     * 
+ * + *

+ * + * @param str 要处理的字符串 + * + * @return 除去空白的字符串,如果原字串为null或结果字符串为"",则返回 null + */ + public static String trimToEmpty(String str, String stripChars) { + String result = trim(str, stripChars); + + if (result == null) { + return ""; + } + return result; + } + + /** + * 除去字符串头尾部的指定字符,如果字符串是null,依然返回null。 + * + *
+     * StringUtil.trim(null, *)          = null
+     * StringUtil.trim("", *)            = ""
+     * StringUtil.trim("abc", null)      = "abc"
+     * StringUtil.trim("  abc", null)    = "abc"
+     * StringUtil.trim("abc  ", null)    = "abc"
+     * StringUtil.trim(" abc ", null)    = "abc"
+     * StringUtil.trim("  abcyx", "xyz") = "  abc"
+     * 
+ * + * @param str 要处理的字符串 + * @param stripChars 要除去的字符,如果为null表示除去空白字符 + * @param mode -1表示trimStart,0表示trim全部, 1表示trimEnd + * + * @return 除去指定字符后的的字符串,如果原字串为null,则返回null + */ + private static String trim(String str, String stripChars, int mode) { + if (str == null) { + return null; + } + + int length = str.length(); + int start = 0; + int end = length; + + // 扫描字符串头部 + if (mode <= 0) { + if (stripChars == null) { + while ((start < end) && (Character.isWhitespace(str.charAt(start)))) { + start++; + } + } else if (stripChars.length() == 0) { + return str; + } else { + while ((start < end) && (str.startsWith(stripChars) && stripChars.indexOf(str.charAt(start)) != -1)) { + start++; + } + } + } + + // 扫描字符串尾部 + if (mode >= 0) { + if (stripChars == null) { + while ((start < end) && (Character.isWhitespace(str.charAt(end - 1)))) { + end--; + } + } else if (stripChars.length() == 0) { + return str; + } else { + while ((start < end) && (str.endsWith(stripChars) && stripChars.indexOf(str.charAt(end - 1)) != -1)) { + end--; + } + } + } + + if ((start > 0) || (end < length)) { + return str.substring(start, end); + } + + return str; + } + + /* + * ========================================================================== == + */ + /* 比较函数。 */ + /* */ + /* 以下方法用来比较两个字符串是否相同。 */ + /* + * ========================================================================== == + */ + + /** + * 比较两个字符串(大小写敏感)。 + * + *
+     * StringUtil.equals(null, null)   = true
+     * StringUtil.equals(null, "abc")  = false
+     * StringUtil.equals("abc", null)  = false
+     * StringUtil.equals("abc", "abc") = true
+     * StringUtil.equals("abc", "ABC") = false
+     * 
+ * + * @param str1 要比较的字符串1 + * @param str2 要比较的字符串2 + * + * @return 如果两个字符串相同,或者都是null,则返回true + */ + public static boolean equals(String str1, String str2) { + if (str1 == null) { + return str2 == null; + } + + return str1.equals(str2); + } + + /** + * 比较两个字符串(大小写不敏感)。 + * + *
+     * StringUtil.equalsIgnoreCase(null, null)   = true
+     * StringUtil.equalsIgnoreCase(null, "abc")  = false
+     * StringUtil.equalsIgnoreCase("abc", null)  = false
+     * StringUtil.equalsIgnoreCase("abc", "abc") = true
+     * StringUtil.equalsIgnoreCase("abc", "ABC") = true
+     * 
+ * + * @param str1 要比较的字符串1 + * @param str2 要比较的字符串2 + * + * @return 如果两个字符串相同,或者都是null,则返回true + */ + public static boolean equalsIgnoreCase(String str1, String str2) { + if (str1 == null) { + return str2 == null; + } + + return str1.equalsIgnoreCase(str2); + } + + /** + * Compares string with at least one from the provided array. If at least one equal string is found, returns its + * index. Otherwise, -1 is returned. + */ + public static int equalsOne(String src, String[] dest) { + if (src == null || dest == null) { + return -1; + } + + for (int i = 0; i < dest.length; i++) { + if (src.equals(dest[i])) { + return i; + } + } + return -1; + } + + /** + * Compares string with at least one from the provided array, ignoring case. If at least one equal string is found, + * it returns its index. Otherwise, -1 is returned. + */ + public static int equalsOneIgnoreCase(String src, String[] dest) { + if (src == null || dest == null) { + return -1; + } + + for (int i = 0; i < dest.length; i++) { + if (src.equalsIgnoreCase(dest[i])) { + return i; + } + } + return -1; + } + + /** + * Compares two string arrays. + * + * @param as first string array + * @param as1 second string array + * + * @return true if all array elements matches + */ + public static boolean equalsIgnoreCase(String as[], String as1[]) { + if (as == null && as1 == null) { + return true; + } + if (as == null || as1 == null) { + return false; + } + if (as.length != as1.length) { + return false; + } + for (int i = 0; i < as.length; i++) { + if (!as[i].equalsIgnoreCase(as1[i])) { + return false; + } + } + return true; + } + + /* + * ========================================================================== == + */ + /* 字符串类型判定函数。 */ + /* */ + /* 判定字符串的类型是否为:字母、数字、空白等 */ + /* + * ========================================================================== == + */ + + /** + * 判断字符串是否只包含unicode字母。 + * + *

+ * null将返回false,空字符串""将返回 true。 + *

+ * + *
+     * StringUtil.isAlpha(null)   = false
+     * StringUtil.isAlpha("")     = true
+     * StringUtil.isAlpha("  ")   = false
+     * StringUtil.isAlpha("abc")  = true
+     * StringUtil.isAlpha("ab2c") = false
+     * StringUtil.isAlpha("ab-c") = false
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果字符串非null并且全由unicode字母组成,则返回true + */ + public static boolean isAlpha(String str) { + if (str == null) { + return false; + } + + int length = str.length(); + + for (int i = 0; i < length; i++) { + if (!Character.isLetter(str.charAt(i))) { + return false; + } + } + + return true; + } + + /** + * 判断字符串是否只包含unicode字母和空格' '。 + * + *

+ * null将返回false,空字符串""将返回 true。 + *

+ * + *
+     * StringUtil.isAlphaSpace(null)   = false
+     * StringUtil.isAlphaSpace("")     = true
+     * StringUtil.isAlphaSpace("  ")   = true
+     * StringUtil.isAlphaSpace("abc")  = true
+     * StringUtil.isAlphaSpace("ab c") = true
+     * StringUtil.isAlphaSpace("ab2c") = false
+     * StringUtil.isAlphaSpace("ab-c") = false
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果字符串非null并且全由unicode字母和空格组成,则返回true + */ + public static boolean isAlphaSpace(String str) { + if (str == null) { + return false; + } + + int length = str.length(); + + for (int i = 0; i < length; i++) { + if (!Character.isLetter(str.charAt(i)) && (str.charAt(i) != ' ')) { + return false; + } + } + + return true; + } + + /** + * 判断字符串是否只包含unicode字母和数字。 + * + *

+ * null将返回false,空字符串""将返回 true。 + *

+ * + *
+     * StringUtil.isAlphanumeric(null)   = false
+     * StringUtil.isAlphanumeric("")     = true
+     * StringUtil.isAlphanumeric("  ")   = false
+     * StringUtil.isAlphanumeric("abc")  = true
+     * StringUtil.isAlphanumeric("ab c") = false
+     * StringUtil.isAlphanumeric("ab2c") = true
+     * StringUtil.isAlphanumeric("ab-c") = false
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果字符串非null并且全由unicode字母数字组成,则返回true + */ + public static boolean isAlphanumeric(String str) { + if (str == null) { + return false; + } + + int length = str.length(); + + for (int i = 0; i < length; i++) { + if (!Character.isLetterOrDigit(str.charAt(i))) { + return false; + } + } + + return true; + } + + /** + * 判断字符串是否只包含unicode字母数字和空格' '。 + * + *

+ * null将返回false,空字符串""将返回 true。 + *

+ * + *
+     * StringUtil.isAlphanumericSpace(null)   = false
+     * StringUtil.isAlphanumericSpace("")     = true
+     * StringUtil.isAlphanumericSpace("  ")   = true
+     * StringUtil.isAlphanumericSpace("abc")  = true
+     * StringUtil.isAlphanumericSpace("ab c") = true
+     * StringUtil.isAlphanumericSpace("ab2c") = true
+     * StringUtil.isAlphanumericSpace("ab-c") = false
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果字符串非null并且全由unicode字母数字和空格组成,则返回true + */ + public static boolean isAlphanumericSpace(String str) { + if (str == null) { + return false; + } + + int length = str.length(); + + for (int i = 0; i < length; i++) { + if (!Character.isLetterOrDigit(str.charAt(i)) && (str.charAt(i) != ' ')) { + return false; + } + } + + return true; + } + + /** + * 判断字符串是否只包含unicode数字。 + * + *

+ * null将返回false,空字符串""将返回 true。 + *

+ * + *
+     * StringUtil.isNumeric(null)   = false
+     * StringUtil.isNumeric("")     = true
+     * StringUtil.isNumeric("  ")   = false
+     * StringUtil.isNumeric("123")  = true
+     * StringUtil.isNumeric("12 3") = false
+     * StringUtil.isNumeric("ab2c") = false
+     * StringUtil.isNumeric("12-3") = false
+     * StringUtil.isNumeric("12.3") = false
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果字符串非null并且全由unicode数字组成,则返回true + */ + public static boolean isNumeric(String str) { + if (str == null) { + return false; + } + + int length = str.length(); + + for (int i = 0; i < length; i++) { + if (!Character.isDigit(str.charAt(i))) { + return false; + } + } + + return true; + } + + /** + * 判断字符串是否只包含unicode数字和空格' '。 + * + *

+ * null将返回false,空字符串""将返回 true。 + *

+ * + *
+     * StringUtil.isNumericSpace(null)   = false
+     * StringUtil.isNumericSpace("")     = true
+     * StringUtil.isNumericSpace("  ")   = true
+     * StringUtil.isNumericSpace("123")  = true
+     * StringUtil.isNumericSpace("12 3") = true
+     * StringUtil.isNumericSpace("ab2c") = false
+     * StringUtil.isNumericSpace("12-3") = false
+     * StringUtil.isNumericSpace("12.3") = false
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果字符串非null并且全由unicode数字和空格组成,则返回true + */ + public static boolean isNumericSpace(String str) { + if (str == null) { + return false; + } + + int length = str.length(); + + for (int i = 0; i < length; i++) { + if (!Character.isDigit(str.charAt(i)) && (str.charAt(i) != ' ')) { + return false; + } + } + + return true; + } + + /** + * 判断字符串是否只包含unicode空白。 + * + *

+ * null将返回false,空字符串""将返回 true。 + *

+ * + *
+     * StringUtil.isWhitespace(null)   = false
+     * StringUtil.isWhitespace("")     = true
+     * StringUtil.isWhitespace("  ")   = true
+     * StringUtil.isWhitespace("abc")  = false
+     * StringUtil.isWhitespace("ab2c") = false
+     * StringUtil.isWhitespace("ab-c") = false
+     * 
+ * + * @param str 要检查的字符串 + * + * @return 如果字符串非null并且全由unicode空白组成,则返回true + */ + public static boolean isWhitespace(String str) { + if (str == null) { + return false; + } + int length = str.length(); + for (int i = 0; i < length; i++) { + if (!Character.isWhitespace(str.charAt(i))) { + return false; + } + } + return true; + } + + /* + * ========================================================================== == + */ + /* 大小写转换。 */ + /* + * ========================================================================== == + */ + + /** + * 将字符串转换成大写。 + * + *

+ * 如果字符串是null则返回null。 + * + *

+     * StringUtil.toUpperCasing(null)  = null
+     * StringUtil.toUpperCasing("")    = ""
+     * StringUtil.toUpperCasing("aBc") = "ABC"
+     * 
+ * + *

+ * + * @param str 要转换的字符串 + * + * @return 大写字符串,如果原字符串为null,则返回null + */ + public static String toUpperCase(String str) { + if (str == null) { + return null; + } + + return str.toUpperCase(); + } + + /** + * 将字符串转换成小写。 + * + *

+ * 如果字符串是null则返回null。 + * + *

+     * StringUtil.toLowerCasing(null)  = null
+     * StringUtil.toLowerCasing("")    = ""
+     * StringUtil.toLowerCasing("aBc") = "abc"
+     * 
+ * + *

+ * + * @param str 要转换的字符串 + * + * @return 大写字符串,如果原字符串为null,则返回null + */ + public static String toLowerCase(String str) { + if (str == null) { + return null; + } + + return str.toLowerCase(); + } + + /** + * 将字符串的首字符转成大写(Character.toTitleCase),其它字符不变。 + * + *

+ * 如果字符串是null则返回null。 + * + *

+     * StringUtil.capitalize(null)  = null
+     * StringUtil.capitalize("")    = ""
+     * StringUtil.capitalize("cat") = "Cat"
+     * StringUtil.capitalize("cAt") = "CAt"
+     * 
+ * + *

+ * + * @param str 要转换的字符串 + * + * @return 首字符为大写的字符串,如果原字符串为null,则返回null + */ + public static String capitalize(String str) { + int strLen; + + if ((str == null) || ((strLen = str.length()) == 0)) { + return str; + } + + return new StringBuilder(strLen).append(Character.toTitleCase(str.charAt(0))).append(str.substring(1)) + .toString(); + } + + /** + * 将字符串的首字符转成小写,其它字符不变。 + * + *

+ * 如果字符串是null则返回null。 + * + *

+     * StringUtil.uncapitalize(null)  = null
+     * StringUtil.uncapitalize("")    = ""
+     * StringUtil.uncapitalize("Cat") = "cat"
+     * StringUtil.uncapitalize("CAT") = "cAT"
+     * 
+ * + *

+ * + * @param str 要转换的字符串 + * + * @return 首字符为小写的字符串,如果原字符串为null,则返回null + */ + public static String uncapitalize(String str) { + int strLen; + + if ((str == null) || ((strLen = str.length()) == 0)) { + return str; + } + + return new StringBuilder(strLen).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)) + .toString(); + } + + /** + * 与 {@link #uncapitalize(String)}不同,连续大写字符将不做改变 + * + *

+ * 如果字符串是null则返回null。 + * + *

+     * StringUtil.uncapitalize(null)  = null
+     * StringUtil.uncapitalize("")    = ""
+     * StringUtil.uncapitalize("Cat") = "cat"
+     * StringUtil.uncapitalize("CAT") = "CAT"
+     * 
+ * + *

+ * + * @param str 要转换的字符串 + * + * @return 首字符为小写的字符串,如果原字符串为null,则返回null + */ + public static String decapitalize(String str) { + if ((str == null) || str.length() == 0) { + return str; + } + if (str.length() > 1 && Character.isUpperCase(str.charAt(1)) && Character.isUpperCase(str.charAt(0))) { + return str; + } + + char chars[] = str.toCharArray(); + char c = chars[0]; + char modifiedChar = Character.toLowerCase(c); + if (modifiedChar == c) { + return str; + } + chars[0] = modifiedChar; + return new String(chars); + } + + /** + * 反转字符串的大小写。 + * + *

+ * 如果字符串是null则返回null。 + * + *

+     * StringUtil.swapCasing(null)                 = null
+     * StringUtil.swapCasing("")                   = ""
+     * StringUtil.swapCasing("The dog has a BONE") = "tHE DOG HAS A bone"
+     * 
+ * + *

+ * + * @param str 要转换的字符串 + * + * @return 大小写被反转的字符串,如果原字符串为null,则返回null + */ + public static String swapCase(String str) { + int strLen; + + if ((str == null) || ((strLen = str.length()) == 0)) { + return str; + } + + StringBuilder builder = new StringBuilder(strLen); + + char ch = 0; + + for (int i = 0; i < strLen; i++) { + ch = str.charAt(i); + + if (Character.isUpperCase(ch)) { + ch = Character.toLowerCase(ch); + } else if (Character.isTitleCase(ch)) { + ch = Character.toLowerCase(ch); + } else if (Character.isLowerCase(ch)) { + ch = Character.toUpperCase(ch); + } + + builder.append(ch); + } + + return builder.toString(); + } + + public static String fromCamelCase(String str, char separator) { + int strLen; + + if ((str == null) || ((strLen = str.length()) == 0)) { + return str; + } + StringBuilder result = new StringBuilder(strLen * 2); + int resultLength = 0; + boolean prevTranslated = false; + for (int i = 0; i < strLen; i++) { + char c = str.charAt(i); + if (i > 0 || c != separator) {// skip first starting separator + if (Character.isUpperCase(c)) { + if (!prevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != separator) { + result.append(separator); + resultLength++; + } + c = Character.toLowerCase(c); + prevTranslated = true; + } else { + prevTranslated = false; + } + result.append(c); + resultLength++; + } + } + return resultLength > 0 ? result.toString() : str; + } + + /** + * String2Short + * + * @param s + * @param def + * @return + */ + public static short toShort(String s, short def) { + try { + return (isEmpty(s)) ? def : Short.parseShort(s); + } catch (NumberFormatException e) { + return def; + } + } + + /** + * String2Int + * + * @param s + * @param def + * @return + */ + public static int toInt(String s, int def) { + try { + return (isEmpty(s)) ? def : Integer.parseInt(s); + } catch (NumberFormatException e) { + return def; + } + } + + /** + * String2Long + * + * @param s + * @param def + * @return + */ + public static long toLong(String s, long def) { + try { + return (isEmpty(s)) ? def : Long.parseLong(s); + } catch (NumberFormatException e) { + return def; + } + } + + /** + * String2Float + * + * @param s + * @param def + * @return + */ + public static float toFloat(String s, float def) { + try { + return (isEmpty(s)) ? def : Float.parseFloat(s); + } catch (NumberFormatException e) { + return def; + } + } + + /** + * String2Double + * + * @param s + * @param def + * @return + */ + public static double toDouble(String s, double def) { + try { + return (isEmpty(s)) ? def : Double.parseDouble(s); + } catch (NumberFormatException e) { + return def; + } + } + + /** + * String2Boolean + * + * @param s + * @param def + * @return + */ + public static boolean toBoolean(String s, boolean def) { + if (isEmpty(s)) + return def; + else { + return "true".equalsIgnoreCase(s); + } + } + + // ----------- 字符串截取 ----------- // + /** + * 截取 float/double 类型 一位小数 + * + * @param f + * @return + */ + public static String getDelFormat(Object f) { + DecimalFormat df = new DecimalFormat("0.0"); + return df.format(f); + } + + /** + * 截取 float/double 类型 两位小数 + * + * @param f + * @return + */ + public static String getDelFormat2(Object f) { + DecimalFormat df = new DecimalFormat("0.00"); + return df.format(f); + } + + /** + * 截取三位 + * + * @param f + * @return + */ + public static String getDelFormat3(Object f) { + DecimalFormat df = new DecimalFormat("0.000"); + return df.format(f); + } + + /** + * 截取字符串 先是一定的长多 多余... + * + * @param source + * 元字符串 + * @param len + * 显示长多 + * @return + */ + public static String getStringsubstr(String source, int len) { + if (null == source || "".equals(source)) { + return ""; + } + if (source.length() > len) { + return source.substring(0, len) + "..."; + } + + return source; + } + + // ----------- 随机数 ----------- // + /** + * 获得0-max的随机数 + * + * @param length + * @return String + */ + public static String getRandomNumber(int length, int max) { + Random random = new Random(); + StringBuffer buffer = new StringBuffer(); + + for (int i = 0; i < length; i++) { + buffer.append(random.nextInt(max)); + } + return buffer.toString(); + } + + /** + * 获取指定长度的随机数字组成的字符串 + * + * @param size + * @return + */ + public static String getRandomNumber(int size) { + String num = ""; + for (int i = 0; i < size; i++) { + double a = Math.random() * 9; + a = Math.ceil(a); + int randomNum = new Double(a).intValue(); + num += randomNum; + } + return num; + } + + /** + * 获取随机字符 + * + * @param size + * @return + */ + public static String getRandomChar(int size) { + String sRand = ""; + Random random = new Random();// 创建一个随机类 + for (int i = 0; i < size; i++) { + String ch = String.valueOf(RANDOM_CHAR.charAt(random.nextInt(RANDOM_CHAR.length()))); + sRand += ch; + } + return sRand; + } + + // ----------- 验证 ----------- // + /** + * 判断字符串是否为数字和有正确的值 + * + * @param str + * @return + */ + public static boolean isNumber(String str) { + // Pattern pattern=Pattern.compile("[0-9]*"); + // return pattern.matcher(str).matches(); + if (null != str && 0 != str.trim().length() && str.matches("\\d*")) { + return true; + } + + return false; + } + + public static boolean isBoolean(String value) { + if(null != value){ + String val = value.toLowerCase(); + if(val.equals("true") || val.equals("false")){ + return true; + } + } + return false; + } + + /** + * 将阿拉伯数字转为中文数字 + * + * @return + */ + public static String toChineseNumber(int number, int depth) { + if (depth < 0) + depth = 0; + if (number <= 0 && depth == 0) + return NUMBER[0]; + + String chinese = ""; + String src = number + ""; + if (src.charAt(src.length() - 1) == 'l' || src.charAt(src.length() - 1) == 'L') { + src = src.substring(0, src.length() - 1); + } + + if (src.length() > 4) + chinese = toChineseNumber(Integer.parseInt(src.substring(0, src.length() - 4)), depth + 1) + + toChineseNumber(Integer.parseInt(src.substring(src.length() - 4, src.length())), depth - 1); + else { + char prv = 0; + for (int i = 0; i < src.length(); i++) { + switch (src.charAt(i)) { + case '0': + if (prv != '0') + chinese = chinese + NUMBER[0]; + break; + case '1': + chinese = chinese + NUMBER[1]; + break; + case '2': + chinese = chinese + NUMBER[2]; + break; + case '3': + chinese = chinese + NUMBER[3]; + break; + case '4': + chinese = chinese + NUMBER[4]; + break; + case '5': + chinese = chinese + NUMBER[5]; + break; + case '6': + chinese = chinese + NUMBER[6]; + break; + case '7': + chinese = chinese + NUMBER[7]; + break; + case '8': + chinese = chinese + NUMBER[8]; + break; + case '9': + chinese = chinese + NUMBER[9]; + break; + } + prv = src.charAt(i); + + switch (src.length() - 1 - i) { + case 1:// 十 + if (prv != '0') + chinese = chinese + NUMBER[10]; + break; + case 2:// 百 + if (prv != '0') + chinese = chinese + NUMBER[11]; + break; + case 3:// 千 + if (prv != '0') + chinese = chinese + NUMBER[12]; + break; + } + } + } + while (chinese.length() > 0 && chinese.lastIndexOf(NUMBER[0]) == chinese.length() - 1) + chinese = chinese.substring(0, chinese.length() - 1); + if (depth == 1) + chinese += NUMBER[13]; + if (depth == 2) + chinese += NUMBER[14]; + return chinese; + } + + /** + * 验证字符串是否含有特殊字符和中文 + * + * @param + * + * @return + */ + public static boolean checkIsEnglish(String s) { + String Letters = "(){}[]\",.<>\\/~!@#$%^&*;': "; + int i; + int c; + + if (s.charAt(0) == '-') { + return false; + } + if (s.charAt(s.length() - 1) == '-') { + return false; + } + + for (i = 0; i < s.length(); i++) { + c = s.charAt(i); + if (Letters.indexOf(c) > -1) { + return false; + } + } + + // 验证是否刚好匹配 + boolean yesorno = isChineseStr(s); + if (yesorno) { + return false; + } + return true; + } + + public static boolean isChineseStr(String pValue) { + for (int i = 0; i < pValue.length(); i++) { + if ((int) pValue.charAt(i) > 256) + return true; + } + return false; + } + + /** + * 判断一个字符是Ascill字符还是其它字符(如汉,日,韩文字符) + * + * @param char c, 需要判断的字符 + * @return boolean, 返回true,Ascill字符 + */ + public static boolean isLetter(char c) { + int k = 0x80; + return c / k == 0 ? true : false; + } + + + // ----------- 格式化 ---------- // + /** + * 格式化数据 + * + * @param decima + * l3453454 + * @return 3,453,454 + */ + public final static String FormatDecimalString(String decimal) { + double dValue = Double.valueOf(decimal).doubleValue(); + DecimalFormat df = new DecimalFormat(); + String positivePattern = " ,000"; + String negativePattern = " ,000"; + if (dValue < 0) { + df.applyPattern(negativePattern); + return df.format(dValue).replace(',', ','); + } else { + df.applyPattern(positivePattern); + return df.format(dValue).replace(',', ','); + } + } + + /** + * 格式化数据 + * + * @param source + * 3453454 + * @return 3,453,454 + */ + public static String getNumberFormat(long source) { + NumberFormat usFormat = NumberFormat.getIntegerInstance(Locale.US); + return usFormat.format(source); + } + + // ----------- 过滤 ---------- // + /** + * 过滤字符串里的的特殊字符 + * + * @param str + * 要过滤的字符串 + * @return 过滤后的字符串 + */ + public static String stringFilter(String str) { + // 过滤通过页面表单提交的字符 + String[][] FilterChars = { { "<", "<" }, { ">", ">" }, { " ", " " }, { "\"", """ }, { "&", "&" }, + { "/", "/" }, { "\\", "\" }, { "'", "\\'" }, { "%", "%" } }; + + String[] str_arr = stringSpilit(str, ""); + + for (int i = 0; i < str_arr.length; i++) { + for (int j = 0; j < FilterChars.length; j++) { + if (FilterChars[j][0].equals(str_arr[i])) + str_arr[i] = FilterChars[j][1]; + } + } + return (stringConnect(str_arr, "")).trim(); + } + + // 关健字过滤 + public static String stringKeyWorldFilter(String str) { + // 过滤通过页面表单提交的字符 + String[][] FilterChars = { { "<", "" }, { ">", "" }, { "\"", "" }, { "&", "" }, { "/", "" }, { "\\", "" }, { "'", "" }, + { "%", "" } }; + + String[] str_arr = stringSpilit(str, ""); + + for (int i = 0; i < str_arr.length; i++) { + for (int j = 0; j < FilterChars.length; j++) { + if (FilterChars[j][0].equals(str_arr[i])) + str_arr[i] = FilterChars[j][1]; + } + } + return (stringConnect(str_arr, "")).trim(); + } + + public static String escapeJavaScript(String value) { + return escapeJava(value); + } + + public static String unescapeJavaScript(String value) { + return unescapeJava(value); + } + + public static String escapeJava(String value) { + if (value == null || value.length() == 0) { + return value; + } + int len = value.length(); + StringBuilder buf = null; + for (int i = 0; i < len; i++) { + char ch = value.charAt(i); + String rep; + switch (ch) { + case '\\': + rep = "\\\\"; + break; + case '\"': + rep = "\\\""; + break; + case '\'': + rep = "\\\'"; + break; + case '\t': + rep = "\\t"; + break; + case '\n': + rep = "\\n"; + break; + case '\r': + rep = "\\r"; + break; + case '\b': + rep = "\\b"; + break; + case '\f': + rep = "\\f"; + break; + default: + rep = null; + break; + } + if (rep != null) { + if (buf == null) { + buf = new StringBuilder(len * 2); + if (i > 0) { + buf.append(value.substring(0, i)); + } + } + buf.append(rep); + } else { + if (buf != null) { + buf.append(ch); + } + } + } + if (buf != null) { + return buf.toString(); + } + return value; + } + + public static String unescapeJava(String value) { + if (value == null || value.length() == 0) { + return value; + } + StringBuilder buf = null; + int len = value.length(); + int len1 = len - 1; + for (int i = 0; i < len; i++) { + char ch = value.charAt(i); + if (ch == '\\' && i < len1) { + int j = i; + i++; + ch = value.charAt(i); + switch (ch) { + case '\\': + ch = '\\'; + break; + case '\"': + ch = '\"'; + break; + case '\'': + ch = '\''; + break; + case 't': + ch = '\t'; + break; + case 'n': + ch = '\n'; + break; + case 'r': + ch = '\r'; + break; + case 'b': + ch = '\b'; + break; + case 'f': + ch = '\f'; + break; + case 'u': + ch = (char) Integer.parseInt(value.substring(i + 1, i + 5), 16); + i = i + 4; + break; + default: + j--; + } + if (buf == null) { + buf = new StringBuilder(len); + if (j > 0) { + buf.append(value.substring(0, j)); + } + } + buf.append(ch); + } else if (buf != null) { + buf.append(ch); + } + } + if (buf != null) { + return buf.toString(); + } + return value; + } + + // ----------- 切割合并 ---------- // + /** + * 分割字符串 + * + * @param str + * 要分割的字符串 + * @param spilit_sign + * 字符串的分割标志 + * @return 分割后得到的字符串数组 + */ + public static String[] stringSpilit(String str, String spilit_sign) { + String[] spilit_string = str.split(spilit_sign); + if (spilit_string[0].equals("")) { + String[] new_string = new String[spilit_string.length - 1]; + for (int i = 1; i < spilit_string.length; i++) + new_string[i - 1] = spilit_string[i]; + return new_string; + } else + return spilit_string; + } + + /** + * 用特殊的字符连接字符串 + * + * @param strings + * 要连接的字符串数组 + * @param spilit_sign + * 连接字符 + * @return 连接字符串 + */ + public static String stringConnect(String[] strings, String spilit_sign) { + StringBuffer str = new StringBuffer(""); + for (int i = 0; i < strings.length; i++) { + str.append(strings[i]).append(spilit_sign); + } + return str.toString(); + } + + /** + * 四舍五入 返回int类型 + * + * @param dSource + * 2342.45 + * @return 2342 + */ + public static int getRound(double dSource) { + int iRound; + // BigDecimal的构造函数参数类型是double + BigDecimal deSource = new BigDecimal(dSource); + // deSource.setScale(0,BigDecimal.ROUND_HALF_UP) 返回值类型 BigDecimal + // intValue() 方法将BigDecimal转化为int + iRound = deSource.setScale(0, BigDecimal.ROUND_HALF_UP).intValue(); + return iRound; + } + + /** + * 提供小数位四舍五入处理。 + * + * @param s + * 需要四舍五入的数字 + * @return 四舍五入后的结果 + */ + public static double round(double s) { + BigDecimal b = new BigDecimal(Double.toString(s)); + BigDecimal one = new BigDecimal("1"); + return b.divide(one, BigDecimal.ROUND_HALF_UP).doubleValue(); + } + + /** + * 提供小数位四舍五入处理。 + * + * @param s + * 需要四舍五入的数字 + * @return 四舍五入后的结果 + */ + public static long roundlong(double s) { + BigDecimal b = new BigDecimal(Double.toString(s)); + BigDecimal one = new BigDecimal("1"); + return b.divide(one, BigDecimal.ROUND_HALF_UP).longValue(); + } + + /** + * 得到一个字符串的长度,显示的长度,一个汉字或日韩文长度为2,英文字符长度为1 + * + * @param String + * s ,需要得到长度的字符串 + * @return int, 得到的字符串长度 + */ + public static int length(String s) { + if (s == null) + return 0; + char[] c = s.toCharArray(); + int len = 0; + for (int i = 0; i < c.length; i++) { + len++; + if (!isLetter(c[i])) { + len++; + } + } + return len; + } + + /** + * 功能:获得配置文件中指定编码字符串 + * + * @param str + * 解码字符串 charset 指定编码 + * + */ + public static String getStrByCharset(String str, String charset) throws UnsupportedEncodingException { + return new String(str.getBytes("ISO-8859-1"), charset); + } + + /** + * 提取字符串中的中文字符 + * + * @param str + * @return + */ + public static String getChineseByStr(String str) { + + StringBuilder resultStr = new StringBuilder(""); + + Pattern pcn = Pattern.compile("[\u4e00-\u9fa5]"); + Matcher m = pcn.matcher(str); + while (m.find()) { + resultStr.append(m.group().toString()); + } + + return resultStr.toString(); + } + + // 将两位小数的字符串*100 + public static String parseStrInt(String strDouble) { + String fen = ""; + int dotIndex = strDouble.lastIndexOf("."); + if (dotIndex >= 0) {// 有小数点字符串 + String zs = strDouble.substring(0, dotIndex); + if (!isNumber(zs)) { + return null; + } + fen = zs; + if (strDouble.substring(dotIndex).length() > 1) {// 有小数部分 + String xs = strDouble.substring(dotIndex).substring(1); + if (!isNumber(xs)) { + return null; + } + if (xs.length() >= 3) {// 截取后面部分 + xs = xs.substring(0, 2); + } else { + if (xs.length() < 2) { + xs = xs + "0"; + } + } + fen = zs + xs; + } else {// 没有小数 + return null; + } + + } else {// 无小数点字符串 + fen = strDouble + "00"; + } + return fen; + } + + /** + * 检查浮点数 + * + * @param num + * @param type + * "0+":非负浮点数 "+":正浮点数 "-0":非正浮点数 "-":负浮点数 "":浮点数 + * @return + */ + public static boolean checkFloat(String num, String type) { + String eL = ""; + if (type.equals("0+")) + eL = "^\\d+(\\.\\d+)?$";// 非负浮点数 + else if (type.equals("+")) + eL = "^((\\d+\\.\\d*[1-9]\\d*)|(\\d*[1-9]\\d*\\.\\d+)|(\\d*[1-9]\\d*))$";// 正浮点数 + else if (type.equals("-0")) + eL = "^((-\\d+(\\.\\d+)?)|(0+(\\.0+)?))$";// 非正浮点数 + else if (type.equals("-")) + eL = "^(-((\\d+\\.\\d*[1-9]\\d*)|(\\d*[1-9]\\d*\\.\\d+)|(\\d*[1-9]\\d*)))$";// 负浮点数 + else + eL = "^(-?\\d+)(\\.\\d+)?$";// 浮点数 + Pattern p = Pattern.compile(eL); + Matcher m = p.matcher(num); + boolean b = m.matches(); + return b; + } + + /** + * 替换字符串 + * + * @param inString + * @param oldPattern + * @param newPattern + * @return + */ + public static String replace(String inString, String oldPattern, String newPattern) { + if (isEmpty(inString) || isEmpty(oldPattern) || newPattern == null) { + return inString; + } + StringBuilder sb = new StringBuilder(); + int pos = 0; // our position in the old string + int index = inString.indexOf(oldPattern); + // the index of an occurrence we've found, or -1 + int patLen = oldPattern.length(); + while (index >= 0) { + sb.append(inString.substring(pos, index)); + sb.append(newPattern); + pos = index + patLen; + index = inString.indexOf(oldPattern, pos); + } + sb.append(inString.substring(pos)); + // remember to append any characters to the right of a match + return sb.toString(); + } + + public static String deleteAny(String inString, String charsToDelete) { + if (isEmpty(inString) || isEmpty(charsToDelete)) { + return inString; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < inString.length(); i++) { + char c = inString.charAt(i); + if (charsToDelete.indexOf(c) == -1) { + sb.append(c); + } + } + return sb.toString(); + } + + /** + * 获取文件名称 + * + * @param path + * @return + */ + public static String getFilename(String path) { + if (path == null) { + return null; + } + int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); + return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path); + } + + public static String applyRelativePath(String path, String relativePath) { + int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); + if (separatorIndex != -1) { + String newPath = path.substring(0, separatorIndex); + if (!relativePath.startsWith(FOLDER_SEPARATOR)) { + newPath += FOLDER_SEPARATOR; + } + return newPath + relativePath; + } else { + return relativePath; + } + } + + public static String cleanPath(String path) { + if (path == null) { + return null; + } + String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR); + + // Strip prefix from path to analyze, to not treat it as part of the + // first path element. This is necessary to correctly parse paths like + // "file:core/../core/io/Resource.class", where the ".." should just + // strip the first "core" directory while keeping the "file:" prefix. + int prefixIndex = pathToUse.indexOf(":"); + String prefix = ""; + if (prefixIndex != -1) { + prefix = pathToUse.substring(0, prefixIndex + 1); + pathToUse = pathToUse.substring(prefixIndex + 1); + } + if (pathToUse.startsWith(FOLDER_SEPARATOR)) { + prefix = prefix + FOLDER_SEPARATOR; + pathToUse = pathToUse.substring(1); + } + + String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR); + List pathElements = new LinkedList(); + int tops = 0; + + for (int i = pathArray.length - 1; i >= 0; i--) { + String element = pathArray[i]; + if (CURRENT_PATH.equals(element)) { + // Points to current directory - drop it. + } else if (TOP_PATH.equals(element)) { + // Registering top path found. + tops++; + } else { + if (tops > 0) { + // Merging path element with element corresponding to top path. + tops--; + } else { + // Normal path element found. + pathElements.add(0, element); + } + } + } + + // Remaining top paths need to be retained. + for (int i = 0; i < tops; i++) { + pathElements.add(0, TOP_PATH); + } + + return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); + } + + public static String[] toStringArray(Collection collection) { + if (collection == null) { + return null; + } + return collection.toArray(new String[collection.size()]); + } + + public static String[] delimitedListToStringArray(String str, String delimiter) { + return delimitedListToStringArray(str, delimiter, null); + } + + public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) { + if (str == null) { + return new String[0]; + } + if (delimiter == null) { + return new String[] {str}; + } + List result = new ArrayList(); + if ("".equals(delimiter)) { + for (int i = 0; i < str.length(); i++) { + result.add(deleteAny(str.substring(i, i + 1), charsToDelete)); + } + } else { + int pos = 0; + int delPos; + while ((delPos = str.indexOf(delimiter, pos)) != -1) { + result.add(deleteAny(str.substring(pos, delPos), charsToDelete)); + pos = delPos + delimiter.length(); + } + if (str.length() > 0 && pos <= str.length()) { + // Add rest of String, but not in case of empty input. + result.add(deleteAny(str.substring(pos), charsToDelete)); + } + } + return toStringArray(result); + } + + public static String collectionToDelimitedString(Collection coll, String delim, String prefix, String suffix) { + if (CollectionKit.isEmpty(coll)) { + return ""; + } + StringBuilder sb = new StringBuilder(); + Iterator it = coll.iterator(); + while (it.hasNext()) { + sb.append(prefix).append(it.next()).append(suffix); + if (it.hasNext()) { + sb.append(delim); + } + } + return sb.toString(); + } + + public static String collectionToDelimitedString(Collection coll, String delim) { + return collectionToDelimitedString(coll, delim, "", ""); + } + + public static String firstUpperCase(String str) { + return str.substring(0, 1).toUpperCase() + str.substring(1); + } + + public static String join(final String[] array, final String separator) { + if (array == null) { + return null; + } + final int noOfItems = array.length; + if (noOfItems <= 0) { + return null; + } + if (noOfItems == 1) { + return array[0].toString(); + } + final StringBuilder buf = new StringBuilder(noOfItems * 16); + for (int i = 0; i < noOfItems; i++) { + buf.append(separator); + if (array[i] != null) { + buf.append(array[i]); + } + } + return buf.toString(); + } + + public static String join(final Object[] array, final String separator) { + if (array == null) { + return null; + } + final int noOfItems = array.length; + if (noOfItems <= 0) { + return null; + } + if (noOfItems == 1) { + return array[0].toString(); + } + final StringBuilder buf = new StringBuilder(noOfItems * 16); + for (int i = 0; i < noOfItems; i++) { + buf.append(separator); + if (array[i] != null) { + buf.append(array[i]); + } + } + return buf.toString(); + } + + public static String join(final List array, final String separator) { + if (array == null) { + return null; + } + final int noOfItems = array.size(); + if (noOfItems <= 0) { + return null; + } + if (noOfItems == 1) { + return array.get(0).toString(); + } + final StringBuilder buf = new StringBuilder(noOfItems * 16); + for (int i = 0; i < noOfItems; i++) { + buf.append(separator); + if (array.get(i) != null) { + buf.append(array.get(i)); + } + } + return buf.toString(); + } + + public static String join(String... parts) { + StringBuilder sb = new StringBuilder(parts.length); + for (String part : parts) { + sb.append(part); + } + return sb.toString(); + } + + public static String join(Iterable elements, String separator) { + if (elements == null) { + return ""; + } + return join(elements.iterator(), separator); + } + + public static String join(Iterator elements, String separator) { + if (elements == null) { + return ""; + } + StringBuilder sb = new StringBuilder(); + while (elements.hasNext()) { + Object o = elements.next(); + if (sb.length() > 0 && separator != null) { + sb.append(separator); + } + sb.append(o); + } + return sb.toString(); + } + + /** + * 随机获取UUID字符串(无中划线) + * + * @return UUID字符串 + */ + public static String getUUID() { + String uuid = UUID.randomUUID().toString(); + return uuid.substring(0, 8) + uuid.substring(9, 13) + uuid.substring(14, 18) + uuid.substring(19, 23) + + uuid.substring(24); + } + + /** + * 随机获取字符串 + * + * @param length 随机字符串长度 + * @return 随机字符串 + */ + public static String random(int length) { + if (length <= 0) { + return ""; + } + char[] randomChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm' }; + Random random = new Random(); + StringBuffer stringBuffer = new StringBuffer(); + for (int i = 0; i < length; i++) { + stringBuffer.append(randomChar[Math.abs(random.nextInt()) % randomChar.length]); + } + return stringBuffer.toString(); + } + + /** + * 根据指定长度 分隔字符串 + * + * @param str 需要处理的字符串 + * @param length 分隔长度 + * @return 字符串集合 + */ + public static List split(String str, int length) { + List list = new ArrayList(); + for (int i = 0; i < str.length(); i += length) { + int endIndex = i + length; + if (endIndex <= str.length()) { + list.add(str.substring(i, i + length)); + } else { + list.add(str.substring(i, str.length() - 1)); + } + } + return list; + } + + /** + * 将字符串按空白字符分割。 + * + *

+ * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为null,则返回null。 + * + *

+     * StringUtil.split(null)       = null
+     * StringUtil.split("")         = []
+     * StringUtil.split("abc def")  = ["abc", "def"]
+     * StringUtil.split("abc  def") = ["abc", "def"]
+     * StringUtil.split(" abc ")    = ["abc"]
+     * 
+ * + *

+ * + * @param str 要分割的字符串 + * + * @return 分割后的字符串数组,如果原字符串为null,则返回null + */ + public static String[] split(String str) { + return split(str, null, -1); + } + + /** + * 将String to long list + * + * @param source + * @param token + * @return + */ + public static List parseStringToLongList(String source, String token) { + + if (isBlank(source) || isEmpty(token)) { + return null; + } + + List result = new ArrayList(); + String[] units = source.split(token); + for (String unit : units) { + result.add(Long.valueOf(unit)); + } + + return result; + } + + /** + * Splits a string in several parts (tokens) that are separated by delimiter. Delimiter is always surrounded + * by two strings! If there is no content between two delimiters, empty string will be returned for that token. + * Therefore, the length of the returned array will always be: #delimiters + 1. + *

+ * Method is much, much faster then regexp String.split(), and a bit faster then + * StringTokenizer. + * + * @param src string to split + * @param delimiter split delimiter + * + * @return array of split strings + */ + public static String[] splitNoCompress(String src, String delimiter) { + if (src == null || delimiter == null) { + return null; + } + int maxparts = (src.length() / delimiter.length()) + 2; // one more for + // the last + int[] positions = new int[maxparts]; + int dellen = delimiter.length(); + + int i, j = 0; + int count = 0; + positions[0] = -dellen; + while ((i = src.indexOf(delimiter, j)) != -1) { + count++; + positions[count] = i; + j = i + dellen; + } + count++; + positions[count] = src.length(); + + String[] result = new String[count]; + + for (i = 0; i < count; i++) { + result[i] = src.substring(positions[i] + dellen, positions[i + 1]); + } + return result; + } + + public static String[] splitc(String src, String d) { + if (isAnyEmpty(src, d)) { + return new String[] { src }; + } + char[] delimiters = d.toCharArray(); + char[] srcc = src.toCharArray(); + + int maxparts = srcc.length + 1; + int[] start = new int[maxparts]; + int[] end = new int[maxparts]; + + int count = 0; + + start[0] = 0; + int s = 0, e; + if (CharKit.equalsOne(srcc[0], delimiters)) { // string starts with + // delimiter + end[0] = 0; + count++; + s = CharKit.findFirstDiff(srcc, 1, delimiters); + if (s == -1) { // nothing after delimiters + return new String[] { "", "" }; + } + start[1] = s; // new start + } + while (true) { + // find new end + e = CharKit.findFirstEqual(srcc, s, delimiters); + if (e == -1) { + end[count] = srcc.length; + break; + } + end[count] = e; + // find new start + count++; + s = CharKit.findFirstDiff(srcc, e, delimiters); + if (s == -1) { + start[count] = end[count] = srcc.length; + break; + } + start[count] = s; + } + count++; + String[] result = new String[count]; + for (int i = 0; i < count; i++) { + result[i] = src.substring(start[i], end[i]); + } + return result; + } + + public static String[] splitc(String src, char delimiter) { + if (isEmpty(src)) { + return new String[] { "" }; + } + char[] srcc = src.toCharArray(); + + int maxparts = srcc.length + 1; + int[] start = new int[maxparts]; + int[] end = new int[maxparts]; + + int count = 0; + + start[0] = 0; + int s = 0, e; + if (srcc[0] == delimiter) { // string starts with delimiter + end[0] = 0; + count++; + s = CharKit.findFirstDiff(srcc, 1, delimiter); + if (s == -1) { // nothing after delimiters + return new String[] { "", "" }; + } + start[1] = s; // new start + } + while (true) { + // find new end + e = CharKit.findFirstEqual(srcc, s, delimiter); + if (e == -1) { + end[count] = srcc.length; + break; + } + end[count] = e; + // find new start + count++; + s = CharKit.findFirstDiff(srcc, e, delimiter); + if (s == -1) { + start[count] = end[count] = srcc.length; + break; + } + start[count] = s; + } + count++; + String[] result = new String[count]; + for (int i = 0; i < count; i++) { + result[i] = src.substring(start[i], end[i]); + } + return result; + } + + public static String[] splitc(String src, char[] delimiters) { + if (isEmpty(src) || null == delimiters || delimiters.length == 0) { + return new String[] { src }; + } + char[] srcc = src.toCharArray(); + + int maxparts = srcc.length + 1; + int[] start = new int[maxparts]; + int[] end = new int[maxparts]; + + int count = 0; + + start[0] = 0; + int s = 0, e; + if (CharKit.equalsOne(srcc[0], delimiters) == true) { // string start + // with + // delimiter + end[0] = 0; + count++; + s = CharKit.findFirstDiff(srcc, 1, delimiters); + if (s == -1) { // nothing after delimiters + return new String[] { "", "" }; + } + start[1] = s; // new start + } + while (true) { + // find new end + e = CharKit.findFirstEqual(srcc, s, delimiters); + if (e == -1) { + end[count] = srcc.length; + break; + } + end[count] = e; + + // find new start + count++; + s = CharKit.findFirstDiff(srcc, e, delimiters); + if (s == -1) { + start[count] = end[count] = srcc.length; + break; + } + start[count] = s; + } + count++; + String[] result = new String[count]; + for (int i = 0; i < count; i++) { + result[i] = src.substring(start[i], end[i]); + } + return result; + } + + /** + * 将字符串按指定字符分割。 + * + *

+ * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为null,则返回null。 + * + *

+     * StringUtil.split(null, *)         = null
+     * StringUtil.split("", *)           = []
+     * StringUtil.split("a.b.c", '.')    = ["a", "b", "c"]
+     * StringUtil.split("a..b.c", '.')   = ["a", "b", "c"]
+     * StringUtil.split("a:b:c", '.')    = ["a:b:c"]
+     * StringUtil.split("a b c", ' ')    = ["a", "b", "c"]
+     * 
+ * + *

+ * + * @param str 要分割的字符串 + * @param separatorChar 分隔符 + * + * @return 分割后的字符串数组,如果原字符串为null,则返回null + */ + public static String[] split(String str, char separatorChar) { + if (str == null) { + return null; + } + + int length = str.length(); + + if (length == 0) { + return Emptys.EMPTY_STRING_ARRAY; + } + + List list = CollectionKit.createArrayList(); + int i = 0; + int start = 0; + boolean match = false; + + while (i < length) { + if (str.charAt(i) == separatorChar) { + if (match) { + list.add(str.substring(start, i)); + match = false; + } + + start = ++i; + continue; + } + + match = true; + i++; + } + + if (match) { + list.add(str.substring(start, i)); + } + + return list.toArray(new String[list.size()]); + } + + /** + * 将字符串按指定字符分割。 + * + *

+ * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为null,则返回null。 + * + *

+     * StringUtil.split(null, *)                = null
+     * StringUtil.split("", *)                  = []
+     * StringUtil.split("abc def", null)        = ["abc", "def"]
+     * StringUtil.split("abc def", " ")         = ["abc", "def"]
+     * StringUtil.split("abc  def", " ")        = ["abc", "def"]
+     * StringUtil.split(" ab:  cd::ef  ", ":")  = ["ab", "cd", "ef"]
+     * StringUtil.split("abc.def", "")          = ["abc.def"]
+     * 
+ * + *

+ * + * @param str 要分割的字符串 + * @param separatorChars 分隔符 + * + * @return 分割后的字符串数组,如果原字符串为null,则返回null + */ + public static String[] split(String str, String separatorChars) { + return split(str, separatorChars, -1); + } + + /** + * 将字符串按指定字符分割。 + * + *

+ * 分隔符不会出现在目标数组中,连续的分隔符就被看作一个。如果字符串为null,则返回null。 + * + *

+     * StringUtil.split(null, *, *)                 = null
+     * StringUtil.split("", *, *)                   = []
+     * StringUtil.split("ab cd ef", null, 0)        = ["ab", "cd", "ef"]
+     * StringUtil.split("  ab   cd ef  ", null, 0)  = ["ab", "cd", "ef"]
+     * StringUtil.split("ab:cd::ef", ":", 0)        = ["ab", "cd", "ef"]
+     * StringUtil.split("ab:cd:ef", ":", 2)         = ["ab", "cdef"]
+     * StringUtil.split("abc.def", "", 2)           = ["abc.def"]
+     * 
+ * + *

+ * + * @param str 要分割的字符串 + * @param separatorChars 分隔符 + * @param max 返回的数组的最大个数,如果小于等于0,则表示无限制 + * + * @return 分割后的字符串数组,如果原字符串为null,则返回null + */ + public static String[] split(String str, String separatorChars, int max) { + if (str == null) { + return null; + } + + int length = str.length(); + + if (length == 0) { + return Emptys.EMPTY_STRING_ARRAY; + } + + List list = CollectionKit.createArrayList(); + int sizePlus1 = 1; + int i = 0; + int start = 0; + boolean match = false; + + if (separatorChars == null) { + // null表示使用空白作为分隔符 + while (i < length) { + if (Character.isWhitespace(str.charAt(i))) { + if (match) { + if (sizePlus1++ == max) { + i = length; + } + + list.add(str.substring(start, i)); + match = false; + } + + start = ++i; + continue; + } + + match = true; + i++; + } + } else if (separatorChars.length() == 1) { + // 优化分隔符长度为1的情形 + char sep = separatorChars.charAt(0); + + while (i < length) { + if (str.charAt(i) == sep) { + if (match) { + if (sizePlus1++ == max) { + i = length; + } + + list.add(str.substring(start, i)); + match = false; + } + + start = ++i; + continue; + } + + match = true; + i++; + } + } else { + // 一般情形 + while (i < length) { + if (separatorChars.indexOf(str.charAt(i)) >= 0) { + if (match) { + if (sizePlus1++ == max) { + i = length; + } + + list.add(str.substring(start, i)); + match = false; + } + + start = ++i; + continue; + } + + match = true; + i++; + } + } + + if (match) { + list.add(str.substring(start, i)); + } + + return list.toArray(new String[list.size()]); + } + + /** + * Convenience method to return a String array as a CSV String. + * E.g. useful for {@code toString()} implementations. + * @param arr the array to display + * @return the delimited String + */ + public static String arrayToCommaDelimitedString(Object[] arr) { + return arrayToDelimitedString(arr, ","); + } + + /** + * Convenience method to return a String array as a delimited (e.g. CSV) + * String. E.g. useful for {@code toString()} implementations. + * @param arr the array to display + * @param delim the delimiter to use (probably a ",") + * @return the delimited String + */ + public static String arrayToDelimitedString(Object[] arr, String delim) { + if (arr == null || arr.length == 0) { + return ""; + } + + if (arr.length == 1) { + return nullSafeToString(arr[0]); + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < arr.length; i++) { + if (i > 0) { + sb.append(delim); + } + sb.append(arr[i]); + } + return sb.toString(); + } + + /** + * Determine if the given objects are equal, returning {@code true} + * if both are {@code null} or {@code false} if only one is + * {@code null}. + *

Compares arrays with {@code Arrays.equals}, performing an equality + * check based on the array elements rather than the array reference. + * @param o1 first Object to compare + * @param o2 second Object to compare + * @return whether the given objects are equal + * @see java.util.Arrays#equals + */ + public static boolean nullSafeEquals(Object o1, Object o2) { + if (o1 == o2) { + return true; + } + if (o1 == null || o2 == null) { + return false; + } + if (o1.equals(o2)) { + return true; + } + if (o1.getClass().isArray() && o2.getClass().isArray()) { + if (o1 instanceof Object[] && o2 instanceof Object[]) { + return Arrays.equals((Object[]) o1, (Object[]) o2); + } + if (o1 instanceof boolean[] && o2 instanceof boolean[]) { + return Arrays.equals((boolean[]) o1, (boolean[]) o2); + } + if (o1 instanceof byte[] && o2 instanceof byte[]) { + return Arrays.equals((byte[]) o1, (byte[]) o2); + } + if (o1 instanceof char[] && o2 instanceof char[]) { + return Arrays.equals((char[]) o1, (char[]) o2); + } + if (o1 instanceof double[] && o2 instanceof double[]) { + return Arrays.equals((double[]) o1, (double[]) o2); + } + if (o1 instanceof float[] && o2 instanceof float[]) { + return Arrays.equals((float[]) o1, (float[]) o2); + } + if (o1 instanceof int[] && o2 instanceof int[]) { + return Arrays.equals((int[]) o1, (int[]) o2); + } + if (o1 instanceof long[] && o2 instanceof long[]) { + return Arrays.equals((long[]) o1, (long[]) o2); + } + if (o1 instanceof short[] && o2 instanceof short[]) { + return Arrays.equals((short[]) o1, (short[]) o2); + } + } + return false; + } + + public static String nullSafeToString(Object obj) { + if (obj == null) { + return "null"; + } + if (obj instanceof String) { + return (String) obj; + } + if (obj instanceof Object[]) { + return nullSafeToString((Object[]) obj); + } + if (obj instanceof boolean[]) { + return nullSafeToString((boolean[]) obj); + } + if (obj instanceof byte[]) { + return nullSafeToString((byte[]) obj); + } + if (obj instanceof char[]) { + return nullSafeToString((char[]) obj); + } + if (obj instanceof double[]) { + return nullSafeToString((double[]) obj); + } + if (obj instanceof float[]) { + return nullSafeToString((float[]) obj); + } + if (obj instanceof int[]) { + return nullSafeToString((int[]) obj); + } + if (obj instanceof long[]) { + return nullSafeToString((long[]) obj); + } + if (obj instanceof short[]) { + return nullSafeToString((short[]) obj); + } + String str = obj.toString(); + return (str != null ? str : ""); + } + + /** + * 将字符串List转化为字符串,以分隔符间隔. + * + * @param list 需要处理的List. + * @param separator 分隔符. + * @return 转化后的字符串 + */ + public static String toString(List list, String separator) { + StringBuffer stringBuffer = new StringBuffer(); + for (String str : list) { + stringBuffer.append(separator + str); + } + stringBuffer.deleteCharAt(0); + return stringBuffer.toString(); + } + + public static String toString(Object value) { + if (value == null) { + return null; + } + return value.toString(); + } + + public static String toString(Collection collection) { + return toString(collection, " "); + } + + public static String toString(Collection collection, String split) { + if (collection == null || split == null) { + return null; + } + + StringBuilder builder = new StringBuilder(); + for (Object object : collection) { + builder.append(object).append(split); + } + + builder.setLength(builder.length() - split.length()); + return builder.toString(); + } + + +} diff --git a/blade-kit/src/main/java/blade/kit/SystemKit.java b/blade-kit/src/main/java/com/blade/kit/SystemKit.java similarity index 97% rename from blade-kit/src/main/java/blade/kit/SystemKit.java rename to blade-kit/src/main/java/com/blade/kit/SystemKit.java index e4b41d503..886056b5d 100644 --- a/blade-kit/src/main/java/blade/kit/SystemKit.java +++ b/blade-kit/src/main/java/com/blade/kit/SystemKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.io.PrintWriter; import java.net.InetAddress; diff --git a/blade-kit/src/main/java/blade/kit/TaskKit.java b/blade-kit/src/main/java/com/blade/kit/TaskKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/TaskKit.java rename to blade-kit/src/main/java/com/blade/kit/TaskKit.java index e6fd1fcd0..c2ce77b15 100644 --- a/blade-kit/src/main/java/blade/kit/TaskKit.java +++ b/blade-kit/src/main/java/com/blade/kit/TaskKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.text.ParseException; import java.util.ArrayList; @@ -25,8 +25,8 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * 定时任务 diff --git a/blade-kit/src/main/java/blade/kit/TimeKit.java b/blade-kit/src/main/java/com/blade/kit/TimeKit.java similarity index 94% rename from blade-kit/src/main/java/blade/kit/TimeKit.java rename to blade-kit/src/main/java/com/blade/kit/TimeKit.java index f67dcb33b..cb192dfd5 100644 --- a/blade-kit/src/main/java/blade/kit/TimeKit.java +++ b/blade-kit/src/main/java/com/blade/kit/TimeKit.java @@ -1,4 +1,4 @@ -package blade.kit; +package com.blade.kit; import java.text.SimpleDateFormat; import java.util.Date; diff --git a/blade-kit/src/main/java/blade/kit/TimwKit.java b/blade-kit/src/main/java/com/blade/kit/TimwKit.java similarity index 91% rename from blade-kit/src/main/java/blade/kit/TimwKit.java rename to blade-kit/src/main/java/com/blade/kit/TimwKit.java index 01be0b17f..7e251d324 100644 --- a/blade-kit/src/main/java/blade/kit/TimwKit.java +++ b/blade-kit/src/main/java/com/blade/kit/TimwKit.java @@ -13,14 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit; +package com.blade.kit; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * 计数均衡器 diff --git a/blade-kit/src/main/java/blade/kit/XmlKit.java b/blade-kit/src/main/java/com/blade/kit/XmlKit.java similarity index 93% rename from blade-kit/src/main/java/blade/kit/XmlKit.java rename to blade-kit/src/main/java/com/blade/kit/XmlKit.java index ccb04e6f6..d6ae01b1c 100644 --- a/blade-kit/src/main/java/blade/kit/XmlKit.java +++ b/blade-kit/src/main/java/com/blade/kit/XmlKit.java @@ -1,4 +1,4 @@ -package blade.kit; +package com.blade.kit; import java.io.File; diff --git a/blade-kit/src/main/java/blade/kit/base/ThrowableKit.java b/blade-kit/src/main/java/com/blade/kit/base/ThrowableKit.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/base/ThrowableKit.java rename to blade-kit/src/main/java/com/blade/kit/base/ThrowableKit.java index 12d54babb..364893183 100644 --- a/blade-kit/src/main/java/blade/kit/base/ThrowableKit.java +++ b/blade-kit/src/main/java/com/blade/kit/base/ThrowableKit.java @@ -1,205 +1,205 @@ -/* - * Copyright (C) 2007 The Guava Authors - * - * 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 blade.kit.base; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.reflect.InvocationTargetException; - -import blade.kit.Assert; - -/** - * Static utility methods pertaining to instances of {@link Throwable}. - * - *

- * See the Guava User Guide entry on - * - * Throwables. - * - * @author Kevin Bourrillion - * @author Ben Yu - * @since 1.0 - */ -public final class ThrowableKit { - private ThrowableKit() { - } - - /** - * Propagates {@code throwable} exactly as-is, if and only if it is an - * instance of {@code declaredType}. Example usage: - * - *

-	 * try {
-	 * 	someMethodThatCouldThrowAnything();
-	 * } catch (IKnowWhatToDoWithThisException e) {
-	 * 	handle(e);
-	 * } catch (Throwable t) {
-	 * 	Throwables.propagateIfInstanceOf(t, IOException.class);
-	 * 	Throwables.propagateIfInstanceOf(t, SQLException.class);
-	 * 	throw Throwables.propagate(t);
-	 * }
-	 * 
- */ - public static void propagateIfInstanceOf(Throwable throwable, Class declaredType) - throws X { - // Check for null is needed to avoid frequent JNI calls to isInstance(). - if (throwable != null && declaredType.isInstance(throwable)) { - throw declaredType.cast(throwable); - } - } - - /** - * Propagates {@code throwable} exactly as-is, if and only if it is an - * instance of {@link RuntimeException} or {@link Error}. Example usage: - * - *
-	 * try {
-	 * 	someMethodThatCouldThrowAnything();
-	 * } catch (IKnowWhatToDoWithThisException e) {
-	 * 	handle(e);
-	 * } catch (Throwable t) {
-	 * 	Throwables.propagateIfPossible(t);
-	 * 	throw new RuntimeException("unexpected", t);
-	 * }
-	 * 
- */ - public static void propagateIfPossible(Throwable throwable) { - propagateIfInstanceOf(throwable, Error.class); - propagateIfInstanceOf(throwable, RuntimeException.class); - } - - /** - * Propagates {@code throwable} exactly as-is, if and only if it is an - * instance of {@link RuntimeException}, {@link Error}, or - * {@code declaredType}. Example usage: - * - *
-	 * try {
-	 * 	someMethodThatCouldThrowAnything();
-	 * } catch (IKnowWhatToDoWithThisException e) {
-	 * 	handle(e);
-	 * } catch (Throwable t) {
-	 * 	Throwables.propagateIfPossible(t, OtherException.class);
-	 * 	throw new RuntimeException("unexpected", t);
-	 * }
-	 * 
- * - * @param throwable - * the Throwable to possibly propagate - * @param declaredType - * the single checked exception type declared by the calling - * method - */ - public static void propagateIfPossible(Throwable throwable, Class declaredType) throws X { - propagateIfInstanceOf(throwable, declaredType); - propagateIfPossible(throwable); - } - - /** - * Propagates {@code throwable} exactly as-is, if and only if it is an - * instance of {@link RuntimeException}, {@link Error}, - * {@code declaredType1}, or {@code declaredType2}. In the unlikely case - * that you have three or more declared checked exception types, you can - * handle them all by invoking these methods repeatedly. See usage example - * in {@link #propagateIfPossible(Throwable, Class)}. - * - * @param throwable - * the Throwable to possibly propagate - * @param declaredType1 - * any checked exception type declared by the calling method - * @param declaredType2 - * any other checked exception type declared by the calling - * method - */ - public static void propagateIfPossible(Throwable throwable, - Class declaredType1, Class declaredType2) throws X1, X2 { - Assert.notNull(declaredType2); - propagateIfInstanceOf(throwable, declaredType1); - propagateIfPossible(throwable, declaredType2); - } - - /** - * Propagates {@code throwable} as-is if it is an instance of - * {@link RuntimeException} or {@link Error}, or else as a last resort, - * wraps it in a {@code RuntimeException} then propagates. - *

- * This method always throws an exception. The {@code RuntimeException} - * return type is only for client code to make Java type system happy in - * case a return value is required by the enclosing method. Example usage: - * - *

-	 * T doSomething() {
-	 * 	try {
-	 * 		return someMethodThatCouldThrowAnything();
-	 * 	} catch (IKnowWhatToDoWithThisException e) {
-	 * 		return handle(e);
-	 * 	} catch (Throwable t) {
-	 * 		throw Throwables.propagate(t);
-	 * 	}
-	 * }
-	 * 
- * - * @param throwable - * the Throwable to propagate - * @return nothing will ever be returned; this return type is only for your - * convenience, as illustrated in the example above - */ - public static RuntimeException propagate(Throwable throwable) { - propagateIfPossible(Assert.checkNotNull(throwable)); - throw new RuntimeException(throwable); - } - - /** - * Returns the innermost cause of {@code throwable}. The first throwable in - * a chain provides context from when the error or exception was initially - * detected. Example usage: - * - *
-	 * assertEquals("Unable to assign a customer id", Throwables.getRootCause(e).getMessage());
-	 * 
- */ - public static Throwable getRootCause(Throwable throwable) { - Throwable cause; - while ((cause = throwable.getCause()) != null) { - throwable = cause; - } - return throwable; - } - - /** - * Returns a string containing the result of {@link Throwable#toString() - * toString()}, followed by the full, recursive stack trace of - * {@code throwable}. Note that you probably should not be parsing the - * resulting string; if you need programmatic access to the stack frames, - * you can call {@link Throwable#getStackTrace()}. - */ - public static String getStackTraceAsString(Throwable throwable) { - StringWriter stringWriter = new StringWriter(); - throwable.printStackTrace(new PrintWriter(stringWriter)); - return stringWriter.toString(); - } - - public static RuntimeException unchecked(Throwable e) { - if (e instanceof RuntimeException) { - return (RuntimeException) e; - } - if (e instanceof InvocationTargetException) { - return unchecked(((InvocationTargetException) e).getTargetException()); - } - return new RuntimeException(e); - } -} +/* + * Copyright (C) 2007 The Guava Authors + * + * 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.blade.kit.base; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.InvocationTargetException; + +import com.blade.kit.Assert; + +/** + * Static utility methods pertaining to instances of {@link Throwable}. + * + *

+ * See the Guava User Guide entry on + * + * Throwables. + * + * @author Kevin Bourrillion + * @author Ben Yu + * @since 1.0 + */ +public final class ThrowableKit { + private ThrowableKit() { + } + + /** + * Propagates {@code throwable} exactly as-is, if and only if it is an + * instance of {@code declaredType}. Example usage: + * + *

+	 * try {
+	 * 	someMethodThatCouldThrowAnything();
+	 * } catch (IKnowWhatToDoWithThisException e) {
+	 * 	handle(e);
+	 * } catch (Throwable t) {
+	 * 	Throwables.propagateIfInstanceOf(t, IOException.class);
+	 * 	Throwables.propagateIfInstanceOf(t, SQLException.class);
+	 * 	throw Throwables.propagate(t);
+	 * }
+	 * 
+ */ + public static void propagateIfInstanceOf(Throwable throwable, Class declaredType) + throws X { + // Check for null is needed to avoid frequent JNI calls to isInstance(). + if (throwable != null && declaredType.isInstance(throwable)) { + throw declaredType.cast(throwable); + } + } + + /** + * Propagates {@code throwable} exactly as-is, if and only if it is an + * instance of {@link RuntimeException} or {@link Error}. Example usage: + * + *
+	 * try {
+	 * 	someMethodThatCouldThrowAnything();
+	 * } catch (IKnowWhatToDoWithThisException e) {
+	 * 	handle(e);
+	 * } catch (Throwable t) {
+	 * 	Throwables.propagateIfPossible(t);
+	 * 	throw new RuntimeException("unexpected", t);
+	 * }
+	 * 
+ */ + public static void propagateIfPossible(Throwable throwable) { + propagateIfInstanceOf(throwable, Error.class); + propagateIfInstanceOf(throwable, RuntimeException.class); + } + + /** + * Propagates {@code throwable} exactly as-is, if and only if it is an + * instance of {@link RuntimeException}, {@link Error}, or + * {@code declaredType}. Example usage: + * + *
+	 * try {
+	 * 	someMethodThatCouldThrowAnything();
+	 * } catch (IKnowWhatToDoWithThisException e) {
+	 * 	handle(e);
+	 * } catch (Throwable t) {
+	 * 	Throwables.propagateIfPossible(t, OtherException.class);
+	 * 	throw new RuntimeException("unexpected", t);
+	 * }
+	 * 
+ * + * @param throwable + * the Throwable to possibly propagate + * @param declaredType + * the single checked exception type declared by the calling + * method + */ + public static void propagateIfPossible(Throwable throwable, Class declaredType) throws X { + propagateIfInstanceOf(throwable, declaredType); + propagateIfPossible(throwable); + } + + /** + * Propagates {@code throwable} exactly as-is, if and only if it is an + * instance of {@link RuntimeException}, {@link Error}, + * {@code declaredType1}, or {@code declaredType2}. In the unlikely case + * that you have three or more declared checked exception types, you can + * handle them all by invoking these methods repeatedly. See usage example + * in {@link #propagateIfPossible(Throwable, Class)}. + * + * @param throwable + * the Throwable to possibly propagate + * @param declaredType1 + * any checked exception type declared by the calling method + * @param declaredType2 + * any other checked exception type declared by the calling + * method + */ + public static void propagateIfPossible(Throwable throwable, + Class declaredType1, Class declaredType2) throws X1, X2 { + Assert.notNull(declaredType2); + propagateIfInstanceOf(throwable, declaredType1); + propagateIfPossible(throwable, declaredType2); + } + + /** + * Propagates {@code throwable} as-is if it is an instance of + * {@link RuntimeException} or {@link Error}, or else as a last resort, + * wraps it in a {@code RuntimeException} then propagates. + *

+ * This method always throws an exception. The {@code RuntimeException} + * return type is only for client code to make Java type system happy in + * case a return value is required by the enclosing method. Example usage: + * + *

+	 * T doSomething() {
+	 * 	try {
+	 * 		return someMethodThatCouldThrowAnything();
+	 * 	} catch (IKnowWhatToDoWithThisException e) {
+	 * 		return handle(e);
+	 * 	} catch (Throwable t) {
+	 * 		throw Throwables.propagate(t);
+	 * 	}
+	 * }
+	 * 
+ * + * @param throwable + * the Throwable to propagate + * @return nothing will ever be returned; this return type is only for your + * convenience, as illustrated in the example above + */ + public static RuntimeException propagate(Throwable throwable) { + propagateIfPossible(Assert.checkNotNull(throwable)); + throw new RuntimeException(throwable); + } + + /** + * Returns the innermost cause of {@code throwable}. The first throwable in + * a chain provides context from when the error or exception was initially + * detected. Example usage: + * + *
+	 * assertEquals("Unable to assign a customer id", Throwables.getRootCause(e).getMessage());
+	 * 
+ */ + public static Throwable getRootCause(Throwable throwable) { + Throwable cause; + while ((cause = throwable.getCause()) != null) { + throwable = cause; + } + return throwable; + } + + /** + * Returns a string containing the result of {@link Throwable#toString() + * toString()}, followed by the full, recursive stack trace of + * {@code throwable}. Note that you probably should not be parsing the + * resulting string; if you need programmatic access to the stack frames, + * you can call {@link Throwable#getStackTrace()}. + */ + public static String getStackTraceAsString(Throwable throwable) { + StringWriter stringWriter = new StringWriter(); + throwable.printStackTrace(new PrintWriter(stringWriter)); + return stringWriter.toString(); + } + + public static RuntimeException unchecked(Throwable e) { + if (e instanceof RuntimeException) { + return (RuntimeException) e; + } + if (e instanceof InvocationTargetException) { + return unchecked(((InvocationTargetException) e).getTargetException()); + } + return new RuntimeException(e); + } +} diff --git a/blade-kit/src/main/java/blade/kit/exception/ClassReaderException.java b/blade-kit/src/main/java/com/blade/kit/exception/ClassReaderException.java similarity index 89% rename from blade-kit/src/main/java/blade/kit/exception/ClassReaderException.java rename to blade-kit/src/main/java/com/blade/kit/exception/ClassReaderException.java index 536861e39..6058d1413 100644 --- a/blade-kit/src/main/java/blade/kit/exception/ClassReaderException.java +++ b/blade-kit/src/main/java/com/blade/kit/exception/ClassReaderException.java @@ -1,4 +1,4 @@ -package blade.kit.exception; +package com.blade.kit.exception; /** * 类读取异常 diff --git a/blade-kit/src/main/java/blade/kit/exception/IllegalPathException.java b/blade-kit/src/main/java/com/blade/kit/exception/IllegalPathException.java similarity index 90% rename from blade-kit/src/main/java/blade/kit/exception/IllegalPathException.java rename to blade-kit/src/main/java/com/blade/kit/exception/IllegalPathException.java index aeb57bf78..7f877e79d 100644 --- a/blade-kit/src/main/java/blade/kit/exception/IllegalPathException.java +++ b/blade-kit/src/main/java/com/blade/kit/exception/IllegalPathException.java @@ -1,4 +1,4 @@ -package blade.kit.exception; +package com.blade.kit.exception; /** * 代表非法的路径。 diff --git a/blade-kit/src/main/java/blade/kit/exception/ReflectException.java b/blade-kit/src/main/java/com/blade/kit/exception/ReflectException.java similarity index 86% rename from blade-kit/src/main/java/blade/kit/exception/ReflectException.java rename to blade-kit/src/main/java/com/blade/kit/exception/ReflectException.java index 852d72d2f..0a6faa5fe 100644 --- a/blade-kit/src/main/java/blade/kit/exception/ReflectException.java +++ b/blade-kit/src/main/java/com/blade/kit/exception/ReflectException.java @@ -1,4 +1,4 @@ -package blade.kit.exception; +package com.blade.kit.exception; public class ReflectException extends RuntimeException{ diff --git a/blade-kit/src/main/java/blade/kit/http/ConnectionFactory.java b/blade-kit/src/main/java/com/blade/kit/http/ConnectionFactory.java similarity index 93% rename from blade-kit/src/main/java/blade/kit/http/ConnectionFactory.java rename to blade-kit/src/main/java/com/blade/kit/http/ConnectionFactory.java index c695eff71..e12793b82 100644 --- a/blade-kit/src/main/java/blade/kit/http/ConnectionFactory.java +++ b/blade-kit/src/main/java/com/blade/kit/http/ConnectionFactory.java @@ -1,4 +1,4 @@ -package blade.kit.http; +package com.blade.kit.http; import java.io.IOException; import java.net.HttpURLConnection; diff --git a/blade-kit/src/main/java/blade/kit/http/Header.java b/blade-kit/src/main/java/com/blade/kit/http/Header.java similarity index 94% rename from blade-kit/src/main/java/blade/kit/http/Header.java rename to blade-kit/src/main/java/com/blade/kit/http/Header.java index 3b8eba01f..a375f21ab 100644 --- a/blade-kit/src/main/java/blade/kit/http/Header.java +++ b/blade-kit/src/main/java/com/blade/kit/http/Header.java @@ -1,4 +1,4 @@ -package blade.kit.http; +package com.blade.kit.http; /** * 头信息常量 diff --git a/blade-kit/src/main/java/blade/kit/http/HttpRequest.java b/blade-kit/src/main/java/com/blade/kit/http/HttpRequest.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/http/HttpRequest.java rename to blade-kit/src/main/java/com/blade/kit/http/HttpRequest.java index 407a79540..9228f6691 100644 --- a/blade-kit/src/main/java/blade/kit/http/HttpRequest.java +++ b/blade-kit/src/main/java/com/blade/kit/http/HttpRequest.java @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ -package blade.kit.http; +package com.blade.kit.http; import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; import static java.net.HttpURLConnection.HTTP_CREATED; @@ -85,8 +85,8 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; -import blade.kit.Assert; -import blade.kit.Base64; +import com.blade.kit.Assert; +import com.blade.kit.Base64; /** * Http请求类 diff --git a/blade-kit/src/main/java/blade/kit/http/HttpRequestException.java b/blade-kit/src/main/java/com/blade/kit/http/HttpRequestException.java similarity index 89% rename from blade-kit/src/main/java/blade/kit/http/HttpRequestException.java rename to blade-kit/src/main/java/com/blade/kit/http/HttpRequestException.java index 52a2527c0..7a335ca6e 100644 --- a/blade-kit/src/main/java/blade/kit/http/HttpRequestException.java +++ b/blade-kit/src/main/java/com/blade/kit/http/HttpRequestException.java @@ -1,4 +1,4 @@ -package blade.kit.http; +package com.blade.kit.http; import java.io.IOException; diff --git a/blade-kit/src/main/java/blade/kit/http/MethodType.java b/blade-kit/src/main/java/com/blade/kit/http/MethodType.java similarity index 91% rename from blade-kit/src/main/java/blade/kit/http/MethodType.java rename to blade-kit/src/main/java/com/blade/kit/http/MethodType.java index 1af683374..e647169e9 100644 --- a/blade-kit/src/main/java/blade/kit/http/MethodType.java +++ b/blade-kit/src/main/java/com/blade/kit/http/MethodType.java @@ -1,4 +1,4 @@ -package blade.kit.http; +package com.blade.kit.http; /** * 请求方法类型 diff --git a/blade-kit/src/main/java/blade/kit/http/RequestOutputStream.java b/blade-kit/src/main/java/com/blade/kit/http/RequestOutputStream.java similarity index 93% rename from blade-kit/src/main/java/blade/kit/http/RequestOutputStream.java rename to blade-kit/src/main/java/com/blade/kit/http/RequestOutputStream.java index 61d41238f..7ac4ec9b0 100644 --- a/blade-kit/src/main/java/blade/kit/http/RequestOutputStream.java +++ b/blade-kit/src/main/java/com/blade/kit/http/RequestOutputStream.java @@ -1,4 +1,4 @@ -package blade.kit.http; +package com.blade.kit.http; import java.io.BufferedOutputStream; import java.io.IOException; diff --git a/blade-kit/src/main/java/blade/kit/http/TokenQueue.java b/blade-kit/src/main/java/com/blade/kit/http/TokenQueue.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/http/TokenQueue.java rename to blade-kit/src/main/java/com/blade/kit/http/TokenQueue.java index 2194c3820..bd2694408 100644 --- a/blade-kit/src/main/java/blade/kit/http/TokenQueue.java +++ b/blade-kit/src/main/java/com/blade/kit/http/TokenQueue.java @@ -1,6 +1,6 @@ -package blade.kit.http; +package com.blade.kit.http; -import blade.kit.Assert; +import com.blade.kit.Assert; /** * A character queue with parsing helpers. diff --git a/blade-kit/src/main/java/blade/kit/http/UploadProgress.java b/blade-kit/src/main/java/com/blade/kit/http/UploadProgress.java similarity index 90% rename from blade-kit/src/main/java/blade/kit/http/UploadProgress.java rename to blade-kit/src/main/java/com/blade/kit/http/UploadProgress.java index 403a5dfd0..da9c9a270 100644 --- a/blade-kit/src/main/java/blade/kit/http/UploadProgress.java +++ b/blade-kit/src/main/java/com/blade/kit/http/UploadProgress.java @@ -1,4 +1,4 @@ -package blade.kit.http; +package com.blade.kit.http; /** * 上传进度回调接口 diff --git a/blade-kit/src/main/java/blade/kit/http/package-info.java b/blade-kit/src/main/java/com/blade/kit/http/package-info.java similarity index 50% rename from blade-kit/src/main/java/blade/kit/http/package-info.java rename to blade-kit/src/main/java/com/blade/kit/http/package-info.java index e2311401b..9c5032b49 100644 --- a/blade-kit/src/main/java/blade/kit/http/package-info.java +++ b/blade-kit/src/main/java/com/blade/kit/http/package-info.java @@ -1,4 +1,4 @@ -/** - * http网络请求包 - */ -package blade.kit.http; \ No newline at end of file +/** + * http网络请求包 + */ +package com.blade.kit.http; \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/io/AppendableWriter.java b/blade-kit/src/main/java/com/blade/kit/io/AppendableWriter.java similarity index 93% rename from blade-kit/src/main/java/blade/kit/io/AppendableWriter.java rename to blade-kit/src/main/java/com/blade/kit/io/AppendableWriter.java index 11a721def..253deeaab 100644 --- a/blade-kit/src/main/java/blade/kit/io/AppendableWriter.java +++ b/blade-kit/src/main/java/com/blade/kit/io/AppendableWriter.java @@ -1,10 +1,11 @@ -package blade.kit.io; +package com.blade.kit.io; + +import static com.blade.kit.Assert.checkNotNull; import java.io.Closeable; import java.io.Flushable; import java.io.IOException; import java.io.Writer; -import static blade.kit.Assert.checkNotNull; /** * Writer that places all output on an {@link Appendable} target. If the target diff --git a/blade-kit/src/main/java/blade/kit/io/ByteArray.java b/blade-kit/src/main/java/com/blade/kit/io/ByteArray.java similarity index 92% rename from blade-kit/src/main/java/blade/kit/io/ByteArray.java rename to blade-kit/src/main/java/com/blade/kit/io/ByteArray.java index 5fcc68d3b..86262d73f 100644 --- a/blade-kit/src/main/java/blade/kit/io/ByteArray.java +++ b/blade-kit/src/main/java/com/blade/kit/io/ByteArray.java @@ -1,11 +1,11 @@ -package blade.kit.io; +package com.blade.kit.io; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import blade.kit.Assert; +import com.blade.kit.Assert; /** * 代表一个byte数组。 diff --git a/blade-kit/src/main/java/blade/kit/io/ByteArrayOutputStream.java b/blade-kit/src/main/java/com/blade/kit/io/ByteArrayOutputStream.java similarity index 94% rename from blade-kit/src/main/java/blade/kit/io/ByteArrayOutputStream.java rename to blade-kit/src/main/java/com/blade/kit/io/ByteArrayOutputStream.java index 3feccac35..bf81dff73 100644 --- a/blade-kit/src/main/java/blade/kit/io/ByteArrayOutputStream.java +++ b/blade-kit/src/main/java/com/blade/kit/io/ByteArrayOutputStream.java @@ -1,11 +1,11 @@ -package blade.kit.io; +package com.blade.kit.io; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import blade.kit.IOKit; +import com.blade.kit.IOKit; /** * 非同步的ByteArrayOutputStream替换方案, 执行toByteArray() 方法时返回的是只读的内部字节数组, 避免了没有必要的字节复制. 本代码移植自IBM diff --git a/blade-kit/src/main/java/blade/kit/io/CharStreams.java b/blade-kit/src/main/java/com/blade/kit/io/CharStreams.java similarity index 94% rename from blade-kit/src/main/java/blade/kit/io/CharStreams.java rename to blade-kit/src/main/java/com/blade/kit/io/CharStreams.java index 0d98ffb39..9e7373da1 100644 --- a/blade-kit/src/main/java/blade/kit/io/CharStreams.java +++ b/blade-kit/src/main/java/com/blade/kit/io/CharStreams.java @@ -1,6 +1,9 @@ -package blade.kit.io; +package com.blade.kit.io; +import static com.blade.kit.Assert.checkNotNull; +import static com.blade.kit.Assert.checkPositionIndexes; + import java.io.Closeable; import java.io.EOFException; import java.io.IOException; @@ -10,10 +13,7 @@ import java.util.ArrayList; import java.util.List; -import static blade.kit.Assert.checkNotNull; -import static blade.kit.Assert.checkPositionIndexes; - -import blade.kit.Assert; +import com.blade.kit.Assert; /** * Provides utility methods for working with character streams. diff --git a/blade-kit/src/main/java/blade/kit/io/FastByteArrayOutputStream.java b/blade-kit/src/main/java/com/blade/kit/io/FastByteArrayOutputStream.java similarity index 94% rename from blade-kit/src/main/java/blade/kit/io/FastByteArrayOutputStream.java rename to blade-kit/src/main/java/com/blade/kit/io/FastByteArrayOutputStream.java index 9a935a00e..4e1f1a9c4 100644 --- a/blade-kit/src/main/java/blade/kit/io/FastByteArrayOutputStream.java +++ b/blade-kit/src/main/java/com/blade/kit/io/FastByteArrayOutputStream.java @@ -1,4 +1,4 @@ -package blade.kit.io; +package com.blade.kit.io; import java.io.IOException; import java.io.OutputStream; diff --git a/blade-kit/src/main/java/blade/kit/io/FastByteBuffer.java b/blade-kit/src/main/java/com/blade/kit/io/FastByteBuffer.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/io/FastByteBuffer.java rename to blade-kit/src/main/java/com/blade/kit/io/FastByteBuffer.java index 1c63c0e6d..e28efe1a8 100644 --- a/blade-kit/src/main/java/blade/kit/io/FastByteBuffer.java +++ b/blade-kit/src/main/java/com/blade/kit/io/FastByteBuffer.java @@ -1,6 +1,6 @@ -package blade.kit.io; +package com.blade.kit.io; -import blade.kit.Assert; +import com.blade.kit.Assert; /** * 快速缓冲,将数据存放在缓冲集中,取代以往的单一数组 diff --git a/blade-kit/src/main/java/blade/kit/io/LineBuffer.java b/blade-kit/src/main/java/com/blade/kit/io/LineBuffer.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/io/LineBuffer.java rename to blade-kit/src/main/java/com/blade/kit/io/LineBuffer.java index ac0830c63..c539f4c00 100644 --- a/blade-kit/src/main/java/blade/kit/io/LineBuffer.java +++ b/blade-kit/src/main/java/com/blade/kit/io/LineBuffer.java @@ -1,4 +1,4 @@ -package blade.kit.io; +package com.blade.kit.io; import java.io.IOException; diff --git a/blade-kit/src/main/java/blade/kit/io/LineProcessor.java b/blade-kit/src/main/java/com/blade/kit/io/LineProcessor.java similarity index 92% rename from blade-kit/src/main/java/blade/kit/io/LineProcessor.java rename to blade-kit/src/main/java/com/blade/kit/io/LineProcessor.java index a1c33af44..4c87d9a49 100644 --- a/blade-kit/src/main/java/blade/kit/io/LineProcessor.java +++ b/blade-kit/src/main/java/com/blade/kit/io/LineProcessor.java @@ -1,4 +1,4 @@ -package blade.kit.io; +package com.blade.kit.io; import java.io.IOException; diff --git a/blade-kit/src/main/java/blade/kit/io/LineReader.java b/blade-kit/src/main/java/com/blade/kit/io/LineReader.java similarity index 93% rename from blade-kit/src/main/java/blade/kit/io/LineReader.java rename to blade-kit/src/main/java/com/blade/kit/io/LineReader.java index cb458c88a..b29f68d14 100644 --- a/blade-kit/src/main/java/blade/kit/io/LineReader.java +++ b/blade-kit/src/main/java/com/blade/kit/io/LineReader.java @@ -1,11 +1,12 @@ -package blade.kit.io; +package com.blade.kit.io; + +import static com.blade.kit.Assert.checkNotNull; import java.io.IOException; import java.io.Reader; import java.nio.CharBuffer; import java.util.LinkedList; import java.util.Queue; -import static blade.kit.Assert.checkNotNull; /** * A class for reading lines of text. Provides the same functionality * as {@link java.io.BufferedReader#readLine()} but for all {@link Readable} diff --git a/blade-kit/src/main/java/blade/kit/io/StringBuilderWriter.java b/blade-kit/src/main/java/com/blade/kit/io/StringBuilderWriter.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/io/StringBuilderWriter.java rename to blade-kit/src/main/java/com/blade/kit/io/StringBuilderWriter.java index 666002885..03b58a044 100644 --- a/blade-kit/src/main/java/blade/kit/io/StringBuilderWriter.java +++ b/blade-kit/src/main/java/com/blade/kit/io/StringBuilderWriter.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit.io; +package com.blade.kit.io; import java.io.Serializable; import java.io.Writer; diff --git a/blade-kit/src/main/java/com/blade/kit/io/package-info.java b/blade-kit/src/main/java/com/blade/kit/io/package-info.java new file mode 100644 index 000000000..b1a309d49 --- /dev/null +++ b/blade-kit/src/main/java/com/blade/kit/io/package-info.java @@ -0,0 +1,4 @@ +/** + * IO操作包 + */ +package com.blade.kit.io; \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/JSON.java b/blade-kit/src/main/java/com/blade/kit/json/JSON.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/json/JSON.java rename to blade-kit/src/main/java/com/blade/kit/json/JSON.java index eafa5ca3a..bc4412733 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSON.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSON.java @@ -1,409 +1,409 @@ -/******************************************************************************* - * Copyright (c) 2015, 2016 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Reader; - -/** - * This class serves as the entry point to the minimal-json API. - *

- * To parse a given JSON input, use the parse() - * methods like in this example: - *

- * - *
- * JsonObject object = Json.parse(string).asObject();
- * 
- *

- * To create a JSON data structure to be serialized, use the - * methods value(), array(), and object() - * . For example, the following snippet will produce the JSON string - * {"foo": 23, "bar": true}: - *

- * - *
- * String string = Json.object().add("foo", 23).add("bar", true).toString();
- * 
- *

- * To create a JSON array from a given Java array, you can use one of the - * array() methods with varargs parameters: - *

- * - *
- * String[] names = ...
- * JsonArray array = Json.array(names);
- * 
- */ -public final class JSON { - - private JSON() { - // not meant to be instantiated - } - - /** - * Represents the JSON literal null. - */ - public static final JSONValue NULL = new JSONLiteral("null"); - - /** - * Represents the JSON literal true. - */ - public static final JSONValue TRUE = new JSONLiteral("true"); - - /** - * Represents the JSON literal false. - */ - public static final JSONValue FALSE = new JSONLiteral("false"); - - /** - * Returns a JsonValue instance that represents the given int - * value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - */ - public static JSONValue value(Integer value) { - return new JSONNumber(Integer.toString(value, 10)); - } - - public static JSONValue value(Object value) { - return JSONHelper.toJSONValue(value); - } - - /** - * Returns a JsonValue instance that represents the given long - * value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - */ - public static JSONValue value(Long value) { - return new JSONNumber(Long.toString(value, 10)); - } - - public static JSONValue value(Byte value) { - return new JSONNumber(Byte.toString(value)); - } - - /** - * Returns a JsonValue instance that represents the given float - * value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - */ - public static JSONValue value(Float value) { - if (Float.isInfinite(value) || Float.isNaN(value)) { - throw new IllegalArgumentException("Infinite and NaN values not permitted in JSON"); - } - return new JSONNumber(cutOffPointZero(Float.toString(value))); - } - - /** - * Returns a JsonValue instance that represents the given - * double value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - */ - public static JSONValue value(Double value) { - if (Double.isInfinite(value) || Double.isNaN(value)) { - throw new IllegalArgumentException("Infinite and NaN values not permitted in JSON"); - } - return new JSONNumber(cutOffPointZero(Double.toString(value))); - } - - /** - * Returns a JsonValue instance that represents the given string. - * - * @param string - * the string to get a JSON representation for - * @return a JSON value that represents the given string - */ - public static JSONValue value(String string) { - return string == null ? NULL : new JSONString(string); - } - - /** - * Returns a JsonValue instance that represents the given - * boolean value. - * - * @param value - * the value to get a JSON representation for - * @return a JSON value that represents the given value - */ - public static JSONValue value(Boolean value) { - return value ? TRUE : FALSE; - } - - /** - * Creates a new empty JsonArray. This is equivalent to creating a new - * JsonArray using the constructor. - * - * @return a new empty JSON array - */ - public static JSONValue array() { - return new JSONArray(); - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given int values. - * - * @param values - * the values to be included in the new JSON array - * @return a new JSON array that contains the given values - */ - public static JSONArray array(Integer... values) { - if (values == null) { - throw new NullPointerException("values is null"); - } - JSONArray array = new JSONArray(); - for (int value : values) { - array.add(value); - } - return array; - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given long values. - * - * @param values - * the values to be included in the new JSON array - * @return a new JSON array that contains the given values - */ - public static JSONArray array(Long... values) { - if (values == null) { - throw new NullPointerException("values is null"); - } - JSONArray array = new JSONArray(); - for (long value : values) { - array.add(value); - } - return array; - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given float values. - * - * @param values - * the values to be included in the new JSON array - * @return a new JSON array that contains the given values - */ - public static JSONArray array(Float... values) { - if (values == null) { - throw new NullPointerException("values is null"); - } - JSONArray array = new JSONArray(); - for (float value : values) { - array.add(value); - } - return array; - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given double values. - * - * @param values - * the values to be included in the new JSON array - * @return a new JSON array that contains the given values - */ - public static JSONArray array(Double... values) { - if (values == null) { - throw new NullPointerException("values is null"); - } - JSONArray array = new JSONArray(); - for (double value : values) { - array.add(value); - } - return array; - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given boolean values. - * - * @param values - * the values to be included in the new JSON array - * @return a new JSON array that contains the given values - */ - public static JSONArray array(Boolean... values) { - if (values == null) { - throw new NullPointerException("values is null"); - } - JSONArray array = new JSONArray(); - for (boolean value : values) { - array.add(value); - } - return array; - } - - /** - * Creates a new JsonArray that contains the JSON representations of the - * given strings. - * - * @param strings - * the strings to be included in the new JSON array - * @return a new JSON array that contains the given strings - */ - public static JSONArray array(String... strings) { - if (strings == null) { - throw new NullPointerException("values is null"); - } - JSONArray array = new JSONArray(); - for (String value : strings) { - array.add(value); - } - return array; - } - - /** - * Creates a new empty JsonObject. This is equivalent to creating a new - * JsonObject using the constructor. - * - * @return a new empty JSON object - */ - public static JSONObject create() { - return new JSONObject(); - } - - /** - * Parses the given input string as JSON. The input must contain a valid - * JSON value, optionally padded with whitespace. - * - * @param string - * the input string, must be valid JSON - * @return a value that represents the parsed JSON - * @throws ParseException - * if the input is not valid JSON - */ - public static JSONValue parse(String string) { - if (string == null) { - throw new NullPointerException("string is null"); - } - DefaultHandler handler = new DefaultHandler(); - new JSONParser(handler).parse(string); - return handler.getValue(); - } - - /** - * Reads the entire input from the given reader and parses it as JSON. The - * input must contain a valid JSON value, optionally padded with whitespace. - *

- * Characters are read in chunks into an input buffer. Hence, wrapping a - * reader in an additional BufferedReader likely won't improve - * reading performance. - *

- * - * @param reader - * the reader to read the JSON value from - * @return a value that represents the parsed JSON - * @throws IOException - * if an I/O error occurs in the reader - * @throws ParseException - * if the input is not valid JSON - */ - public static JSONValue parse(Reader reader) throws IOException { - if (reader == null) { - throw new NullPointerException("reader is null"); - } - DefaultHandler handler = new DefaultHandler(); - new JSONParser(handler).parse(reader); - return handler.getValue(); - } - - private static String cutOffPointZero(String string) { - if (string.endsWith(".0")) { - return string.substring(0, string.length() - 2); - } - return string; - } - - static class DefaultHandler extends JSONHandler { - - protected JSONValue value; - - @Override - public JSONArray startArray() { - return new JSONArray(); - } - - @Override - public JSONObject startObject() { - return new JSONObject(); - } - - @Override - public void endNull() { - value = NULL; - } - - @Override - public void endBoolean(boolean bool) { - value = bool ? TRUE : FALSE; - } - - @Override - public void endString(String string) { - value = new JSONString(string); - } - - @Override - public void endNumber(String string) { - value = new JSONNumber(string); - } - - @Override - public void endArray(JSONArray array) { - value = array; - } - - @Override - public void endObject(JSONObject object) { - value = object; - } - - @Override - public void endArrayValue(JSONArray array) { - array.add(value); - } - - @Override - public void endObjectValue(JSONObject object, String name) { - object.put(name, value); - } - - JSONValue getValue() { - return value; - } - - } - -} +/******************************************************************************* + * Copyright (c) 2015, 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; +import java.io.Reader; + +/** + * This class serves as the entry point to the minimal-json API. + *

+ * To parse a given JSON input, use the parse() + * methods like in this example: + *

+ * + *
+ * JsonObject object = Json.parse(string).asObject();
+ * 
+ *

+ * To create a JSON data structure to be serialized, use the + * methods value(), array(), and object() + * . For example, the following snippet will produce the JSON string + * {"foo": 23, "bar": true}: + *

+ * + *
+ * String string = Json.object().add("foo", 23).add("bar", true).toString();
+ * 
+ *

+ * To create a JSON array from a given Java array, you can use one of the + * array() methods with varargs parameters: + *

+ * + *
+ * String[] names = ...
+ * JsonArray array = Json.array(names);
+ * 
+ */ +public final class JSON { + + private JSON() { + // not meant to be instantiated + } + + /** + * Represents the JSON literal null. + */ + public static final JSONValue NULL = new JSONLiteral("null"); + + /** + * Represents the JSON literal true. + */ + public static final JSONValue TRUE = new JSONLiteral("true"); + + /** + * Represents the JSON literal false. + */ + public static final JSONValue FALSE = new JSONLiteral("false"); + + /** + * Returns a JsonValue instance that represents the given int + * value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JSONValue value(Integer value) { + return new JSONNumber(Integer.toString(value, 10)); + } + + public static JSONValue value(Object value) { + return JSONHelper.toJSONValue(value); + } + + /** + * Returns a JsonValue instance that represents the given long + * value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JSONValue value(Long value) { + return new JSONNumber(Long.toString(value, 10)); + } + + public static JSONValue value(Byte value) { + return new JSONNumber(Byte.toString(value)); + } + + /** + * Returns a JsonValue instance that represents the given float + * value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JSONValue value(Float value) { + if (Float.isInfinite(value) || Float.isNaN(value)) { + throw new IllegalArgumentException("Infinite and NaN values not permitted in JSON"); + } + return new JSONNumber(cutOffPointZero(Float.toString(value))); + } + + /** + * Returns a JsonValue instance that represents the given + * double value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JSONValue value(Double value) { + if (Double.isInfinite(value) || Double.isNaN(value)) { + throw new IllegalArgumentException("Infinite and NaN values not permitted in JSON"); + } + return new JSONNumber(cutOffPointZero(Double.toString(value))); + } + + /** + * Returns a JsonValue instance that represents the given string. + * + * @param string + * the string to get a JSON representation for + * @return a JSON value that represents the given string + */ + public static JSONValue value(String string) { + return string == null ? NULL : new JSONString(string); + } + + /** + * Returns a JsonValue instance that represents the given + * boolean value. + * + * @param value + * the value to get a JSON representation for + * @return a JSON value that represents the given value + */ + public static JSONValue value(Boolean value) { + return value ? TRUE : FALSE; + } + + /** + * Creates a new empty JsonArray. This is equivalent to creating a new + * JsonArray using the constructor. + * + * @return a new empty JSON array + */ + public static JSONValue array() { + return new JSONArray(); + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given int values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JSONArray array(Integer... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (int value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given long values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JSONArray array(Long... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (long value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given float values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JSONArray array(Float... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (float value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given double values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JSONArray array(Double... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (double value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given boolean values. + * + * @param values + * the values to be included in the new JSON array + * @return a new JSON array that contains the given values + */ + public static JSONArray array(Boolean... values) { + if (values == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (boolean value : values) { + array.add(value); + } + return array; + } + + /** + * Creates a new JsonArray that contains the JSON representations of the + * given strings. + * + * @param strings + * the strings to be included in the new JSON array + * @return a new JSON array that contains the given strings + */ + public static JSONArray array(String... strings) { + if (strings == null) { + throw new NullPointerException("values is null"); + } + JSONArray array = new JSONArray(); + for (String value : strings) { + array.add(value); + } + return array; + } + + /** + * Creates a new empty JsonObject. This is equivalent to creating a new + * JsonObject using the constructor. + * + * @return a new empty JSON object + */ + public static JSONObject create() { + return new JSONObject(); + } + + /** + * Parses the given input string as JSON. The input must contain a valid + * JSON value, optionally padded with whitespace. + * + * @param string + * the input string, must be valid JSON + * @return a value that represents the parsed JSON + * @throws ParseException + * if the input is not valid JSON + */ + public static JSONValue parse(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + DefaultHandler handler = new DefaultHandler(); + new JSONParser(handler).parse(string); + return handler.getValue(); + } + + /** + * Reads the entire input from the given reader and parses it as JSON. The + * input must contain a valid JSON value, optionally padded with whitespace. + *

+ * Characters are read in chunks into an input buffer. Hence, wrapping a + * reader in an additional BufferedReader likely won't improve + * reading performance. + *

+ * + * @param reader + * the reader to read the JSON value from + * @return a value that represents the parsed JSON + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + */ + public static JSONValue parse(Reader reader) throws IOException { + if (reader == null) { + throw new NullPointerException("reader is null"); + } + DefaultHandler handler = new DefaultHandler(); + new JSONParser(handler).parse(reader); + return handler.getValue(); + } + + private static String cutOffPointZero(String string) { + if (string.endsWith(".0")) { + return string.substring(0, string.length() - 2); + } + return string; + } + + static class DefaultHandler extends JSONHandler { + + protected JSONValue value; + + @Override + public JSONArray startArray() { + return new JSONArray(); + } + + @Override + public JSONObject startObject() { + return new JSONObject(); + } + + @Override + public void endNull() { + value = NULL; + } + + @Override + public void endBoolean(boolean bool) { + value = bool ? TRUE : FALSE; + } + + @Override + public void endString(String string) { + value = new JSONString(string); + } + + @Override + public void endNumber(String string) { + value = new JSONNumber(string); + } + + @Override + public void endArray(JSONArray array) { + value = array; + } + + @Override + public void endObject(JSONObject object) { + value = object; + } + + @Override + public void endArrayValue(JSONArray array) { + array.add(value); + } + + @Override + public void endObjectValue(JSONObject object, String name) { + object.put(name, value); + } + + JSONValue getValue() { + return value; + } + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONArray.java b/blade-kit/src/main/java/com/blade/kit/json/JSONArray.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/json/JSONArray.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONArray.java index 0e4b07918..f4b1217ab 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONArray.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONArray.java @@ -1,472 +1,472 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -/** - * Represents a JSON array, an ordered collection of JSON values. - *

- * Elements can be added using the add(...) methods which accept - * instances of {@link JSONValue}, strings, primitive numbers, and boolean - * values. To replace an element of an array, use the set(int, ...) - * methods. - *

- *

- * Elements can be accessed by their index using {@link #get(int)}. This class - * also supports iterating over the elements in document order using an - * {@link #iterator()} or an enhanced for loop: - *

- * - *
- * for (JsonValue value : jsonArray) {
- *   ...
- * }
- * 
- *

- * An equivalent {@link List} can be obtained from the method {@link #values()}. - *

- *

- * Note that this class is not thread-safe. If multiple threads - * access a JsonArray instance concurrently, while at least one of - * these threads modifies the contents of this array, access to the instance - * must be synchronized externally. Failure to do so may lead to an inconsistent - * state. - *

- *

- * This class is not supposed to be extended by clients. - *

- */ -@SuppressWarnings("serial") // use default serial UID -public class JSONArray extends JSONValue implements Iterable { - - private final List values; - - /** - * Creates a new empty JsonArray. - */ - public JSONArray() { - values = new ArrayList(); - } - - /** - * Creates a new JsonArray with the contents of the specified JSON array. - * - * @param array - * the JsonArray to get the initial contents from, must not be - * null - */ - public JSONArray(JSONArray array) { - this(array, false); - } - - private JSONArray(JSONArray array, boolean unmodifiable) { - if (array == null) { - throw new NullPointerException("array is null"); - } - if (unmodifiable) { - values = Collections.unmodifiableList(array.values); - } else { - values = new ArrayList(array.values); - } - } - - /** - * Returns an unmodifiable wrapper for the specified JsonArray. This method - * allows to provide read-only access to a JsonArray. - *

- * The returned JsonArray is backed by the given array and reflects - * subsequent changes. Attempts to modify the returned JsonArray result in - * an UnsupportedOperationException. - *

- * - * @param array - * the JsonArray for which an unmodifiable JsonArray is to be - * returned - * @return an unmodifiable view of the specified JsonArray - */ - public static JSONArray unmodifiableArray(JSONArray array) { - return new JSONArray(array, true); - } - - /** - * Appends the JSON representation of the specified int value - * to the end of this array. - * - * @param value - * the value to add to the array - * @return the array itself, to enable method chaining - */ - public JSONArray add(int value) { - values.add(JSON.value(value)); - return this; - } - - /** - * Appends the JSON representation of the specified long value - * to the end of this array. - * - * @param value - * the value to add to the array - * @return the array itself, to enable method chaining - */ - public JSONArray add(long value) { - values.add(JSON.value(value)); - return this; - } - - /** - * Appends the JSON representation of the specified float value - * to the end of this array. - * - * @param value - * the value to add to the array - * @return the array itself, to enable method chaining - */ - public JSONArray add(float value) { - values.add(JSON.value(value)); - return this; - } - - /** - * Appends the JSON representation of the specified double - * value to the end of this array. - * - * @param value - * the value to add to the array - * @return the array itself, to enable method chaining - */ - public JSONArray add(double value) { - values.add(JSON.value(value)); - return this; - } - - /** - * Appends the JSON representation of the specified boolean - * value to the end of this array. - * - * @param value - * the value to add to the array - * @return the array itself, to enable method chaining - */ - public JSONArray add(boolean value) { - values.add(JSON.value(value)); - return this; - } - - /** - * Appends the JSON representation of the specified string to the end of - * this array. - * - * @param value - * the string to add to the array - * @return the array itself, to enable method chaining - */ - public JSONArray add(String value) { - values.add(JSON.value(value)); - return this; - } - - public JSONArray add(Object value) { - values.add(JSON.value(value)); - return this; - } - - /** - * Appends the specified JSON value to the end of this array. - * - * @param value - * the JsonValue to add to the array, must not be - * null - * @return the array itself, to enable method chaining - */ - public JSONArray add(JSONValue value) { - if (value == null) { - throw new NullPointerException("value is null"); - } - values.add(value); - return this; - } - - /** - * Replaces the element at the specified position in this array with the - * JSON representation of the specified int value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 - * or index >= size - */ - public JSONArray set(int index, int value) { - values.set(index, JSON.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the - * JSON representation of the specified long value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 - * or index >= size - */ - public JSONArray set(int index, long value) { - values.set(index, JSON.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the - * JSON representation of the specified float value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 - * or index >= size - */ - public JSONArray set(int index, float value) { - values.set(index, JSON.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the - * JSON representation of the specified double value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 - * or index >= size - */ - public JSONArray set(int index, double value) { - values.set(index, JSON.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the - * JSON representation of the specified boolean value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 - * or index >= size - */ - public JSONArray set(int index, boolean value) { - values.set(index, JSON.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the - * JSON representation of the specified string. - * - * @param index - * the index of the array element to replace - * @param value - * the string to be stored at the specified array position - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 - * or index >= size - */ - public JSONArray set(int index, String value) { - values.set(index, JSON.value(value)); - return this; - } - - /** - * Replaces the element at the specified position in this array with the - * specified JSON value. - * - * @param index - * the index of the array element to replace - * @param value - * the value to be stored at the specified array position, must - * not be null - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 - * or index >= size - */ - public JSONArray set(int index, JSONValue value) { - if (value == null) { - throw new NullPointerException("value is null"); - } - values.set(index, value); - return this; - } - - /** - * Removes the element at the specified index from this array. - * - * @param index - * the index of the element to remove - * @return the array itself, to enable method chaining - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 - * or index >= size - */ - public JSONArray remove(int index) { - values.remove(index); - return this; - } - - /** - * Returns the number of elements in this array. - * - * @return the number of elements in this array - */ - public int size() { - return values.size(); - } - - /** - * Returns true if this array contains no elements. - * - * @return true if this array contains no elements - */ - public boolean isEmpty() { - return values.isEmpty(); - } - - /** - * Returns the value of the element at the specified position in this array. - * - * @param index - * the index of the array element to return - * @return the value of the element at the specified position - * @throws IndexOutOfBoundsException - * if the index is out of range, i.e. index < 0 - * or index >= size - */ - public JSONValue get(int index) { - return values.get(index); - } - - /** - * Returns a list of the values in this array in document order. The - * returned list is backed by this array and will reflect subsequent - * changes. It cannot be used to modify this array. Attempts to modify the - * returned list will result in an exception. - * - * @return a list of the values in this array - */ - public List values() { - return Collections.unmodifiableList(values); - } - - /** - * Returns an iterator over the values of this array in document order. The - * returned iterator cannot be used to modify this array. - * - * @return an iterator over the values of this array - */ - public Iterator iterator() { - final Iterator iterator = values.iterator(); - return new Iterator() { - - public boolean hasNext() { - return iterator.hasNext(); - } - - public JSONValue next() { - return iterator.next(); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - void write(JSONWriter writer) throws IOException { - writer.writeArrayOpen(); - Iterator iterator = iterator(); - boolean first = true; - while (iterator.hasNext()) { - if (!first) { - writer.writeArraySeparator(); - } - iterator.next().write(writer); - first = false; - } - writer.writeArrayClose(); - } - - @Override - public boolean isArray() { - return true; - } - - @Override - public JSONArray asArray() { - return this; - } - - @Override - public int hashCode() { - return values.hashCode(); - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JSONArray other = (JSONArray) object; - return values.equals(other.values); - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Represents a JSON array, an ordered collection of JSON values. + *

+ * Elements can be added using the add(...) methods which accept + * instances of {@link JSONValue}, strings, primitive numbers, and boolean + * values. To replace an element of an array, use the set(int, ...) + * methods. + *

+ *

+ * Elements can be accessed by their index using {@link #get(int)}. This class + * also supports iterating over the elements in document order using an + * {@link #iterator()} or an enhanced for loop: + *

+ * + *
+ * for (JsonValue value : jsonArray) {
+ *   ...
+ * }
+ * 
+ *

+ * An equivalent {@link List} can be obtained from the method {@link #values()}. + *

+ *

+ * Note that this class is not thread-safe. If multiple threads + * access a JsonArray instance concurrently, while at least one of + * these threads modifies the contents of this array, access to the instance + * must be synchronized externally. Failure to do so may lead to an inconsistent + * state. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public class JSONArray extends JSONValue implements Iterable { + + private final List values; + + /** + * Creates a new empty JsonArray. + */ + public JSONArray() { + values = new ArrayList(); + } + + /** + * Creates a new JsonArray with the contents of the specified JSON array. + * + * @param array + * the JsonArray to get the initial contents from, must not be + * null + */ + public JSONArray(JSONArray array) { + this(array, false); + } + + private JSONArray(JSONArray array, boolean unmodifiable) { + if (array == null) { + throw new NullPointerException("array is null"); + } + if (unmodifiable) { + values = Collections.unmodifiableList(array.values); + } else { + values = new ArrayList(array.values); + } + } + + /** + * Returns an unmodifiable wrapper for the specified JsonArray. This method + * allows to provide read-only access to a JsonArray. + *

+ * The returned JsonArray is backed by the given array and reflects + * subsequent changes. Attempts to modify the returned JsonArray result in + * an UnsupportedOperationException. + *

+ * + * @param array + * the JsonArray for which an unmodifiable JsonArray is to be + * returned + * @return an unmodifiable view of the specified JsonArray + */ + public static JSONArray unmodifiableArray(JSONArray array) { + return new JSONArray(array, true); + } + + /** + * Appends the JSON representation of the specified int value + * to the end of this array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(int value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified long value + * to the end of this array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(long value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified float value + * to the end of this array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(float value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified double + * value to the end of this array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(double value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified boolean + * value to the end of this array. + * + * @param value + * the value to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(boolean value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the JSON representation of the specified string to the end of + * this array. + * + * @param value + * the string to add to the array + * @return the array itself, to enable method chaining + */ + public JSONArray add(String value) { + values.add(JSON.value(value)); + return this; + } + + public JSONArray add(Object value) { + values.add(JSON.value(value)); + return this; + } + + /** + * Appends the specified JSON value to the end of this array. + * + * @param value + * the JsonValue to add to the array, must not be + * null + * @return the array itself, to enable method chaining + */ + public JSONArray add(JSONValue value) { + if (value == null) { + throw new NullPointerException("value is null"); + } + values.add(value); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified int value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, int value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified long value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, long value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified float value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, float value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified double value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, double value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified boolean value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, boolean value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * JSON representation of the specified string. + * + * @param index + * the index of the array element to replace + * @param value + * the string to be stored at the specified array position + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, String value) { + values.set(index, JSON.value(value)); + return this; + } + + /** + * Replaces the element at the specified position in this array with the + * specified JSON value. + * + * @param index + * the index of the array element to replace + * @param value + * the value to be stored at the specified array position, must + * not be null + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray set(int index, JSONValue value) { + if (value == null) { + throw new NullPointerException("value is null"); + } + values.set(index, value); + return this; + } + + /** + * Removes the element at the specified index from this array. + * + * @param index + * the index of the element to remove + * @return the array itself, to enable method chaining + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONArray remove(int index) { + values.remove(index); + return this; + } + + /** + * Returns the number of elements in this array. + * + * @return the number of elements in this array + */ + public int size() { + return values.size(); + } + + /** + * Returns true if this array contains no elements. + * + * @return true if this array contains no elements + */ + public boolean isEmpty() { + return values.isEmpty(); + } + + /** + * Returns the value of the element at the specified position in this array. + * + * @param index + * the index of the array element to return + * @return the value of the element at the specified position + * @throws IndexOutOfBoundsException + * if the index is out of range, i.e. index < 0 + * or index >= size + */ + public JSONValue get(int index) { + return values.get(index); + } + + /** + * Returns a list of the values in this array in document order. The + * returned list is backed by this array and will reflect subsequent + * changes. It cannot be used to modify this array. Attempts to modify the + * returned list will result in an exception. + * + * @return a list of the values in this array + */ + public List values() { + return Collections.unmodifiableList(values); + } + + /** + * Returns an iterator over the values of this array in document order. The + * returned iterator cannot be used to modify this array. + * + * @return an iterator over the values of this array + */ + public Iterator iterator() { + final Iterator iterator = values.iterator(); + return new Iterator() { + + public boolean hasNext() { + return iterator.hasNext(); + } + + public JSONValue next() { + return iterator.next(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeArrayOpen(); + Iterator iterator = iterator(); + boolean first = true; + while (iterator.hasNext()) { + if (!first) { + writer.writeArraySeparator(); + } + iterator.next().write(writer); + first = false; + } + writer.writeArrayClose(); + } + + @Override + public boolean isArray() { + return true; + } + + @Override + public JSONArray asArray() { + return this; + } + + @Override + public int hashCode() { + return values.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONArray other = (JSONArray) object; + return values.equals(other.values); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONHandler.java b/blade-kit/src/main/java/com/blade/kit/json/JSONHandler.java similarity index 97% rename from blade-kit/src/main/java/blade/kit/json/JSONHandler.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONHandler.java index ebae827b8..9a735ac2b 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONHandler.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONHandler.java @@ -1,263 +1,263 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - - -/** - * A handler for parser events. Instances of this class can be given to a {@link JSONParser}. The - * parser will then call the methods of the given handler while reading the input. - *

- * The default implementations of these methods do nothing. Subclasses may override only those - * methods they are interested in. They can use getLocation() to access the current - * character position of the parser at any point. The start* methods will be called - * while the location points to the first character of the parsed element. The end* - * methods will be called while the location points to the character position that directly follows - * the last character of the parsed element. Example: - *

- * - *
- * ["lorem ipsum"]
- *  ^            ^
- *  startString  endString
- * 
- *

- * Subclasses that build an object representation of the parsed JSON can return arbitrary handler - * objects for JSON arrays and JSON objects in {@link #startArray()} and {@link #startObject()}. - * These handler objects will then be provided in all subsequent parser events for this particular - * array or object. They can be used to keep track the elements of a JSON array or object. - *

- * - * @param - * The type of handlers used for JSON arrays - * @param - * The type of handlers used for JSON objects - * @see JSONParser - */ -public abstract class JSONHandler { - - JSONParser parser; - - /** - * Returns the current parser location. - * - * @return the current parser location - */ - protected Location getLocation() { - return parser.getLocation(); - } - - /** - * Indicates the beginning of a null literal in the JSON input. This method will be - * called when reading the first character of the literal. - */ - public void startNull() { - } - - /** - * Indicates the end of a null literal in the JSON input. This method will be called - * after reading the last character of the literal. - */ - public void endNull() { - } - - /** - * Indicates the beginning of a boolean literal (true or false) in the - * JSON input. This method will be called when reading the first character of the literal. - */ - public void startBoolean() { - } - - /** - * Indicates the end of a boolean literal (true or false) in the JSON - * input. This method will be called after reading the last character of the literal. - * - * @param value - * the parsed boolean value - */ - public void endBoolean(boolean value) { - } - - /** - * Indicates the beginning of a string in the JSON input. This method will be called when reading - * the opening double quote character ('"'). - */ - public void startString() { - } - - /** - * Indicates the end of a string in the JSON input. This method will be called after reading the - * closing double quote character ('"'). - * - * @param string - * the parsed string - */ - public void endString(String string) { - } - - /** - * Indicates the beginning of a number in the JSON input. This method will be called when reading - * the first character of the number. - */ - public void startNumber() { - } - - /** - * Indicates the end of a number in the JSON input. This method will be called after reading the - * last character of the number. - * - * @param string - * the parsed number string - */ - public void endNumber(String string) { - } - - /** - * Indicates the beginning of an array in the JSON input. This method will be called when reading - * the opening square bracket character ('['). - *

- * This method may return an object to handle subsequent parser events for this array. This array - * handler will then be provided in all calls to {@link #startArrayValue(Object) - * startArrayValue()}, {@link #endArrayValue(Object) endArrayValue()}, and - * {@link #endArray(Object) endArray()} for this array. - *

- * - * @return a handler for this array, or null if not needed - */ - public A startArray() { - return null; - } - - /** - * Indicates the end of an array in the JSON input. This method will be called after reading the - * closing square bracket character (']'). - * - * @param array - * the array handler returned from {@link #startArray()}, or null if not - * provided - */ - public void endArray(A array) { - } - - /** - * Indicates the beginning of an array element in the JSON input. This method will be called when - * reading the first character of the element, just before the call to the start - * method for the specific element type ({@link #startString()}, {@link #startNumber()}, etc.). - * - * @param array - * the array handler returned from {@link #startArray()}, or null if not - * provided - */ - public void startArrayValue(A array) { - } - - /** - * Indicates the end of an array element in the JSON input. This method will be called after - * reading the last character of the element value, just after the end method for the - * specific element type (like {@link #endString(String) endString()}, {@link #endNumber(String) - * endNumber()}, etc.). - * - * @param array - * the array handler returned from {@link #startArray()}, or null if not - * provided - */ - public void endArrayValue(A array) { - } - - /** - * Indicates the beginning of an object in the JSON input. This method will be called when reading - * the opening curly bracket character ('{'). - *

- * This method may return an object to handle subsequent parser events for this object. This - * object handler will be provided in all calls to {@link #startObjectName(Object) - * startObjectName()}, {@link #endObjectName(Object, String) endObjectName()}, - * {@link #startObjectValue(Object, String) startObjectValue()}, - * {@link #endObjectValue(Object, String) endObjectValue()}, and {@link #endObject(Object) - * endObject()} for this object. - *

- * - * @return a handler for this object, or null if not needed - */ - public O startObject() { - return null; - } - - /** - * Indicates the end of an object in the JSON input. This method will be called after reading the - * closing curly bracket character ('}'). - * - * @param object - * the object handler returned from {@link #startObject()}, or null if not provided - */ - public void endObject(O object) { - } - - /** - * Indicates the beginning of the name of an object member in the JSON input. This method will be - * called when reading the opening quote character ('"') of the member name. - * - * @param object - * the object handler returned from {@link #startObject()}, or null if not - * provided - */ - public void startObjectName(O object) { - } - - /** - * Indicates the end of an object member name in the JSON input. This method will be called after - * reading the closing quote character ('"') of the member name. - * - * @param object - * the object handler returned from {@link #startObject()}, or null if not provided - * @param name - * the parsed member name - */ - public void endObjectName(O object, String name) { - } - - /** - * Indicates the beginning of the name of an object member in the JSON input. This method will be - * called when reading the opening quote character ('"') of the member name. - * - * @param object - * the object handler returned from {@link #startObject()}, or null if not - * provided - * @param name - * the member name - */ - public void startObjectValue(O object, String name) { - } - - /** - * Indicates the end of an object member value in the JSON input. This method will be called after - * reading the last character of the member value, just after the end method for the - * specific member type (like {@link #endString(String) endString()}, {@link #endNumber(String) - * endNumber()}, etc.). - * - * @param object - * the object handler returned from {@link #startObject()}, or null if not provided - * @param name - * the parsed member name - */ - public void endObjectValue(O object, String name) { - } - -} +/******************************************************************************* + * Copyright (c) 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + + +/** + * A handler for parser events. Instances of this class can be given to a {@link JSONParser}. The + * parser will then call the methods of the given handler while reading the input. + *

+ * The default implementations of these methods do nothing. Subclasses may override only those + * methods they are interested in. They can use getLocation() to access the current + * character position of the parser at any point. The start* methods will be called + * while the location points to the first character of the parsed element. The end* + * methods will be called while the location points to the character position that directly follows + * the last character of the parsed element. Example: + *

+ * + *
+ * ["lorem ipsum"]
+ *  ^            ^
+ *  startString  endString
+ * 
+ *

+ * Subclasses that build an object representation of the parsed JSON can return arbitrary handler + * objects for JSON arrays and JSON objects in {@link #startArray()} and {@link #startObject()}. + * These handler objects will then be provided in all subsequent parser events for this particular + * array or object. They can be used to keep track the elements of a JSON array or object. + *

+ * + * @param
+ * The type of handlers used for JSON arrays + * @param + * The type of handlers used for JSON objects + * @see JSONParser + */ +public abstract class JSONHandler { + + JSONParser parser; + + /** + * Returns the current parser location. + * + * @return the current parser location + */ + protected Location getLocation() { + return parser.getLocation(); + } + + /** + * Indicates the beginning of a null literal in the JSON input. This method will be + * called when reading the first character of the literal. + */ + public void startNull() { + } + + /** + * Indicates the end of a null literal in the JSON input. This method will be called + * after reading the last character of the literal. + */ + public void endNull() { + } + + /** + * Indicates the beginning of a boolean literal (true or false) in the + * JSON input. This method will be called when reading the first character of the literal. + */ + public void startBoolean() { + } + + /** + * Indicates the end of a boolean literal (true or false) in the JSON + * input. This method will be called after reading the last character of the literal. + * + * @param value + * the parsed boolean value + */ + public void endBoolean(boolean value) { + } + + /** + * Indicates the beginning of a string in the JSON input. This method will be called when reading + * the opening double quote character ('"'). + */ + public void startString() { + } + + /** + * Indicates the end of a string in the JSON input. This method will be called after reading the + * closing double quote character ('"'). + * + * @param string + * the parsed string + */ + public void endString(String string) { + } + + /** + * Indicates the beginning of a number in the JSON input. This method will be called when reading + * the first character of the number. + */ + public void startNumber() { + } + + /** + * Indicates the end of a number in the JSON input. This method will be called after reading the + * last character of the number. + * + * @param string + * the parsed number string + */ + public void endNumber(String string) { + } + + /** + * Indicates the beginning of an array in the JSON input. This method will be called when reading + * the opening square bracket character ('['). + *

+ * This method may return an object to handle subsequent parser events for this array. This array + * handler will then be provided in all calls to {@link #startArrayValue(Object) + * startArrayValue()}, {@link #endArrayValue(Object) endArrayValue()}, and + * {@link #endArray(Object) endArray()} for this array. + *

+ * + * @return a handler for this array, or null if not needed + */ + public A startArray() { + return null; + } + + /** + * Indicates the end of an array in the JSON input. This method will be called after reading the + * closing square bracket character (']'). + * + * @param array + * the array handler returned from {@link #startArray()}, or null if not + * provided + */ + public void endArray(A array) { + } + + /** + * Indicates the beginning of an array element in the JSON input. This method will be called when + * reading the first character of the element, just before the call to the start + * method for the specific element type ({@link #startString()}, {@link #startNumber()}, etc.). + * + * @param array + * the array handler returned from {@link #startArray()}, or null if not + * provided + */ + public void startArrayValue(A array) { + } + + /** + * Indicates the end of an array element in the JSON input. This method will be called after + * reading the last character of the element value, just after the end method for the + * specific element type (like {@link #endString(String) endString()}, {@link #endNumber(String) + * endNumber()}, etc.). + * + * @param array + * the array handler returned from {@link #startArray()}, or null if not + * provided + */ + public void endArrayValue(A array) { + } + + /** + * Indicates the beginning of an object in the JSON input. This method will be called when reading + * the opening curly bracket character ('{'). + *

+ * This method may return an object to handle subsequent parser events for this object. This + * object handler will be provided in all calls to {@link #startObjectName(Object) + * startObjectName()}, {@link #endObjectName(Object, String) endObjectName()}, + * {@link #startObjectValue(Object, String) startObjectValue()}, + * {@link #endObjectValue(Object, String) endObjectValue()}, and {@link #endObject(Object) + * endObject()} for this object. + *

+ * + * @return a handler for this object, or null if not needed + */ + public O startObject() { + return null; + } + + /** + * Indicates the end of an object in the JSON input. This method will be called after reading the + * closing curly bracket character ('}'). + * + * @param object + * the object handler returned from {@link #startObject()}, or null if not provided + */ + public void endObject(O object) { + } + + /** + * Indicates the beginning of the name of an object member in the JSON input. This method will be + * called when reading the opening quote character ('"') of the member name. + * + * @param object + * the object handler returned from {@link #startObject()}, or null if not + * provided + */ + public void startObjectName(O object) { + } + + /** + * Indicates the end of an object member name in the JSON input. This method will be called after + * reading the closing quote character ('"') of the member name. + * + * @param object + * the object handler returned from {@link #startObject()}, or null if not provided + * @param name + * the parsed member name + */ + public void endObjectName(O object, String name) { + } + + /** + * Indicates the beginning of the name of an object member in the JSON input. This method will be + * called when reading the opening quote character ('"') of the member name. + * + * @param object + * the object handler returned from {@link #startObject()}, or null if not + * provided + * @param name + * the member name + */ + public void startObjectValue(O object, String name) { + } + + /** + * Indicates the end of an object member value in the JSON input. This method will be called after + * reading the last character of the member value, just after the end method for the + * specific member type (like {@link #endString(String) endString()}, {@link #endNumber(String) + * endNumber()}, etc.). + * + * @param object + * the object handler returned from {@link #startObject()}, or null if not provided + * @param name + * the parsed member name + */ + public void endObjectValue(O object, String name) { + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONHelper.java b/blade-kit/src/main/java/com/blade/kit/json/JSONHelper.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/json/JSONHelper.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONHelper.java index fbe3e521d..883b233a3 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONHelper.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONHelper.java @@ -1,255 +1,256 @@ -package blade.kit.json; - -import java.beans.BeanInfo; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import blade.kit.StringKit; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; - -public class JSONHelper { - - private static final Logger LOGGER = LoggerFactory.getLogger(JSONHelper.class); - - public static Object toJSONObject(JSONValue value) { - if(value.isBoolean()) - return value.asBoolean(); - else if(value.isNumber()) - return value.asInt(); - else if(value.isString()) - return value.asString(); - else if(value.isArray()) - return jsonArrayAsList(value.asArray()); - else if(value.isObject()) - return jsonObjectAsMap(value.asJSONObject()); - else if(value.isBean()) - return jsonObjectAsMap(value.asJSONObject()); - else return null; - } - - public static T toBean(String json, Class clazz) { - JSONObject jsonObject = JSON.parse(json).asJSONObject(); - if(null == jsonObject){ - return null; - } - - T object = null; - try { - object = clazz.newInstance(); - - /*Field[] fields = clazz.getDeclaredFields(); - for (Field field : fields) { - if(field.getModifiers() == 2){ - String key = field.getName(); - if (jsonObject.contains(key)) { - JSONValue value = jsonObject.get(key); - if(null != value){ - field.setAccessible(true); - field.set(object, value.asString()); - } - } - } - }*/ - - BeanInfo beanInfo = Introspector.getBeanInfo(clazz); - PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); - for (PropertyDescriptor property : propertyDescriptors) { - String name = property.getName(); - if (jsonObject.contains(name)) { - Object value = getValue(property.getPropertyType(), jsonObject, name); - if(null != value){ - // 得到property对应的setter方法 - Method setter = property.getWriteMethod(); - setter.invoke(object, value); - } - } - } - } catch (Exception e) { - LOGGER.error("jsonobject covert to bean error", e); - } - return object; - } - - private static Object getValue(Class type, JSONObject jsonObject, String name){ - if(null != type && null != jsonObject && StringKit.isNotBlank(name)){ - if(type.equals(String.class)){ - return jsonObject.getString(name); - } - if(type.equals(Long.class) || type.equals(long.class)){ - return jsonObject.getLong(name); - } - if(type.equals(Double.class) || type.equals(double.class)){ - return jsonObject.getDouble(name); - } - if(type.equals(Boolean.class) || type.equals(boolean.class)){ - return jsonObject.getBoolean(name); - } - } - return null; - } - - public static Set jsonArrayAsSet(JSONArray array) { - Set set = new HashSet(); - for(JSONValue value:array) - set.add(toJSONObject(value)); - return set; - } - - public static List jsonArrayAsList(JSONArray array) { - List list = new ArrayList(array.size()); - for(JSONValue element:array) - list.add(toJSONObject(element)); - return list; - } - - public static Map jsonObjectAsMap(JSONObject object) { - Map map = new HashMap(object.size(), 1.f); - for(JSONObject.Member member:object) - map.put(member.getName(), toJSONObject(member.getValue())); - return map; - } - - public static JSONValue toJSONValue(Object object) { - if (object == null) - return JSON.NULL; - else if (object instanceof Boolean) - return JSON.value((Boolean) object); - else if (object instanceof Integer) - return JSON.value((Integer) object); - else if (object instanceof Long) - return JSON.value((Long) object); - else if (object instanceof Float) - return JSON.value((Float) object); - else if (object instanceof Double) - return JSON.value((Double) object); - else if (object instanceof String) - return JSON.value((String) object); - else if (object instanceof Byte) - return JSON.value((Byte) object); - else if (object instanceof Collection) - return toJSONArray((Collection) object); - else if (object instanceof Map) - return mapAsJsonObject((Map) object); - else if (object instanceof JSONObject) - return ((JSONObject)object); - else if (object instanceof JSONArray) - return ((JSONArray)object); - else - return toJSONObject(object); - } - - public static JSONArray toJSONArray(Collection collection) { - JSONArray array = new JSONArray(); - for(Object element:collection) - array.add(toJSONValue(element)); - return array; - } - - public static JSONObject mapAsJsonObject(Map map) { - JSONObject object = new JSONObject(); - for(Entry entry:map.entrySet()) { - object.put(String.valueOf(entry.getKey()), toJSONValue(entry.getValue())); - } - return object; - } - - public static JSONObject toJSONObject(Object bean) { - - Class klass = bean.getClass(); - - // If klass is a System class then set includeSuperClass to false. - boolean includeSuperClass = klass.getClassLoader() != null; - Method[] methods = includeSuperClass ? klass.getMethods() : klass.getDeclaredMethods(); - - if(null == methods || methods.length == 0){ - return null; - } - - Map map = new HashMap(); - - for (int i = 0, len = methods.length; i < len; i ++) { - try { - Method method = methods[i]; - if (Modifier.isPublic(method.getModifiers())) { - String name = method.getName(); - String key = ""; - if (name.startsWith("get")) { - if ("getClass".equals(name) || "getDeclaringClass".equals(name)) { - key = ""; - } else { - key = name.substring(3); - } - } else if (name.startsWith("is")) { - key = name.substring(2); - } - if (key.length() > 0 && Character.isUpperCase(key.charAt(0)) && method.getParameterTypes().length == 0) { - if (key.length() == 1) { - key = key.toLowerCase(); - } else if (!Character.isUpperCase(key.charAt(1))) { - key = key.substring(0, 1).toLowerCase() + key.substring(1); - } - Object result = method.invoke(bean, (Object[]) null); - if(null != result){ - map.put(key, wrap(result)); - } - } - } - } catch (Exception ignore) { - } - } - return mapAsJsonObject(map); - } - - public static Object wrap(Object object) { - try { - if (object == null) { - return null; - } - if (object instanceof JSONObject || object instanceof JSONArray - || JSON.NULL.equals(object) || object instanceof JSONString - || object instanceof Byte || object instanceof Character - || object instanceof Short || object instanceof Integer - || object instanceof Long || object instanceof Boolean - || object instanceof Float || object instanceof Double - || object instanceof String || object instanceof BigInteger - || object instanceof BigDecimal) { - return object; - } - - if (object instanceof Collection) { - Collection coll = (Collection) object; - return toJSONArray(coll); - } - - if (object instanceof Map) { - Map map = (Map) object; - return mapAsJsonObject(map); - } - - Package objectPackage = object.getClass().getPackage(); - String objectPackageName = objectPackage != null ? objectPackage.getName() : ""; - if (objectPackageName.startsWith("java.") - || objectPackageName.startsWith("javax.") - || object.getClass().getClassLoader() == null) { - return object.toString(); - } - return toJSONObject(object); - } catch (Exception exception) { - return null; - } - } - +package com.blade.kit.json; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.StringKit; + +public class JSONHelper { + + private static final Logger LOGGER = LoggerFactory.getLogger(JSONHelper.class); + + public static Object toJSONObject(JSONValue value) { + if(value.isBoolean()) + return value.asBoolean(); + else if(value.isNumber()) + return value.asInt(); + else if(value.isString()) + return value.asString(); + else if(value.isArray()) + return jsonArrayAsList(value.asArray()); + else if(value.isObject()) + return jsonObjectAsMap(value.asJSONObject()); + else if(value.isBean()) + return jsonObjectAsMap(value.asJSONObject()); + else return null; + } + + public static T toBean(String json, Class clazz) { + JSONObject jsonObject = JSON.parse(json).asJSONObject(); + if(null == jsonObject){ + return null; + } + + T object = null; + try { + object = clazz.newInstance(); + + /*Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + if(field.getModifiers() == 2){ + String key = field.getName(); + if (jsonObject.contains(key)) { + JSONValue value = jsonObject.get(key); + if(null != value){ + field.setAccessible(true); + field.set(object, value.asString()); + } + } + } + }*/ + + BeanInfo beanInfo = Introspector.getBeanInfo(clazz); + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + for (PropertyDescriptor property : propertyDescriptors) { + String name = property.getName(); + if (jsonObject.contains(name)) { + Object value = getValue(property.getPropertyType(), jsonObject, name); + if(null != value){ + // 得到property对应的setter方法 + Method setter = property.getWriteMethod(); + setter.invoke(object, value); + } + } + } + } catch (Exception e) { + LOGGER.error("jsonobject covert to bean error", e); + } + return object; + } + + private static Object getValue(Class type, JSONObject jsonObject, String name){ + if(null != type && null != jsonObject && StringKit.isNotBlank(name)){ + if(type.equals(String.class)){ + return jsonObject.getString(name); + } + if(type.equals(Long.class) || type.equals(long.class)){ + return jsonObject.getLong(name); + } + if(type.equals(Double.class) || type.equals(double.class)){ + return jsonObject.getDouble(name); + } + if(type.equals(Boolean.class) || type.equals(boolean.class)){ + return jsonObject.getBoolean(name); + } + } + return null; + } + + public static Set jsonArrayAsSet(JSONArray array) { + Set set = new HashSet(); + for(JSONValue value:array) + set.add(toJSONObject(value)); + return set; + } + + public static List jsonArrayAsList(JSONArray array) { + List list = new ArrayList(array.size()); + for(JSONValue element:array) + list.add(toJSONObject(element)); + return list; + } + + public static Map jsonObjectAsMap(JSONObject object) { + Map map = new HashMap(object.size(), 1.f); + for(JSONObject.Member member:object) + map.put(member.getName(), toJSONObject(member.getValue())); + return map; + } + + public static JSONValue toJSONValue(Object object) { + if (object == null) + return JSON.NULL; + else if (object instanceof Boolean) + return JSON.value((Boolean) object); + else if (object instanceof Integer) + return JSON.value((Integer) object); + else if (object instanceof Long) + return JSON.value((Long) object); + else if (object instanceof Float) + return JSON.value((Float) object); + else if (object instanceof Double) + return JSON.value((Double) object); + else if (object instanceof String) + return JSON.value((String) object); + else if (object instanceof Byte) + return JSON.value((Byte) object); + else if (object instanceof Collection) + return toJSONArray((Collection) object); + else if (object instanceof Map) + return mapAsJsonObject((Map) object); + else if (object instanceof JSONObject) + return ((JSONObject)object); + else if (object instanceof JSONArray) + return ((JSONArray)object); + else + return toJSONObject(object); + } + + public static JSONArray toJSONArray(Collection collection) { + JSONArray array = new JSONArray(); + for(Object element:collection) + array.add(toJSONValue(element)); + return array; + } + + public static JSONObject mapAsJsonObject(Map map) { + JSONObject object = new JSONObject(); + for(Entry entry:map.entrySet()) { + object.put(String.valueOf(entry.getKey()), toJSONValue(entry.getValue())); + } + return object; + } + + public static JSONObject toJSONObject(Object bean) { + + Class klass = bean.getClass(); + + // If klass is a System class then set includeSuperClass to false. + boolean includeSuperClass = klass.getClassLoader() != null; + Method[] methods = includeSuperClass ? klass.getMethods() : klass.getDeclaredMethods(); + + if(null == methods || methods.length == 0){ + return null; + } + + Map map = new HashMap(); + + for (int i = 0, len = methods.length; i < len; i ++) { + try { + Method method = methods[i]; + if (Modifier.isPublic(method.getModifiers())) { + String name = method.getName(); + String key = ""; + if (name.startsWith("get")) { + if ("getClass".equals(name) || "getDeclaringClass".equals(name)) { + key = ""; + } else { + key = name.substring(3); + } + } else if (name.startsWith("is")) { + key = name.substring(2); + } + if (key.length() > 0 && Character.isUpperCase(key.charAt(0)) && method.getParameterTypes().length == 0) { + if (key.length() == 1) { + key = key.toLowerCase(); + } else if (!Character.isUpperCase(key.charAt(1))) { + key = key.substring(0, 1).toLowerCase() + key.substring(1); + } + Object result = method.invoke(bean, (Object[]) null); + if(null != result){ + map.put(key, wrap(result)); + } + } + } + } catch (Exception ignore) { + } + } + return mapAsJsonObject(map); + } + + public static Object wrap(Object object) { + try { + if (object == null) { + return null; + } + if (object instanceof JSONObject || object instanceof JSONArray + || JSON.NULL.equals(object) || object instanceof JSONString + || object instanceof Byte || object instanceof Character + || object instanceof Short || object instanceof Integer + || object instanceof Long || object instanceof Boolean + || object instanceof Float || object instanceof Double + || object instanceof String || object instanceof BigInteger + || object instanceof BigDecimal) { + return object; + } + + if (object instanceof Collection) { + Collection coll = (Collection) object; + return toJSONArray(coll); + } + + if (object instanceof Map) { + Map map = (Map) object; + return mapAsJsonObject(map); + } + + Package objectPackage = object.getClass().getPackage(); + String objectPackageName = objectPackage != null ? objectPackage.getName() : ""; + if (objectPackageName.startsWith("java.") + || objectPackageName.startsWith("javax.") + || object.getClass().getClassLoader() == null) { + return object.toString(); + } + return toJSONObject(object); + } catch (Exception exception) { + return null; + } + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/JSONKit.java b/blade-kit/src/main/java/com/blade/kit/json/JSONKit.java similarity index 88% rename from blade-kit/src/main/java/blade/kit/json/JSONKit.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONKit.java index 6680d43d6..fd529dc13 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONKit.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONKit.java @@ -1,38 +1,38 @@ -package blade.kit.json; - -import blade.kit.StringKit; - -public final class JSONKit { - - private JSONKit() {} - - public static String toJSONString(Object object){ - if(null == object){ - return null; - } - return JSONHelper.toJSONValue(object).toString(); - } - - public static String toJSONString(Object object, boolean flag){ - if(!flag){ - return toJSONString(object); - } - if(null == object){ - return null; - } - return JSONHelper.toJSONValue(object).toString(WriterConfig.PRETTY_PRINT); - } - - public static T parse(String json, Class clazz) { - if(StringKit.isBlank(json) || null == clazz){ - return null; - } - return JSONHelper.toBean(json, clazz); - } - - public static JSONObject parseObject(String json) { - return JSON.parse(json).asJSONObject(); - } - - +package com.blade.kit.json; + +import com.blade.kit.StringKit; + +public final class JSONKit { + + private JSONKit() {} + + public static String toJSONString(Object object){ + if(null == object){ + return null; + } + return JSONHelper.toJSONValue(object).toString(); + } + + public static String toJSONString(Object object, boolean flag){ + if(!flag){ + return toJSONString(object); + } + if(null == object){ + return null; + } + return JSONHelper.toJSONValue(object).toString(WriterConfig.PRETTY_PRINT); + } + + public static T parse(String json, Class clazz) { + if(StringKit.isBlank(json) || null == clazz){ + return null; + } + return JSONHelper.toBean(json, clazz); + } + + public static JSONObject parseObject(String json) { + return JSON.parse(json).asJSONObject(); + } + + } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/JSONLiteral.java b/blade-kit/src/main/java/com/blade/kit/json/JSONLiteral.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/json/JSONLiteral.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONLiteral.java index bb1abc645..d00acdd70 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONLiteral.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONLiteral.java @@ -1,97 +1,97 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; - - -@SuppressWarnings("serial") // use default serial UID -class JSONLiteral extends JSONValue { - - private final String value; - private final boolean isNull; - private final boolean isTrue; - private final boolean isFalse; - - JSONLiteral(String value) { - this.value = value; - isNull = "null".equals(value); - isTrue = "true".equals(value); - isFalse = "false".equals(value); - } - - @Override - void write(JSONWriter writer) throws IOException { - writer.writeLiteral(value); - } - - @Override - public String toString() { - return value; - } - - @Override - public int hashCode() { - return value.hashCode(); - } - - @Override - public boolean isNull() { - return isNull; - } - - @Override - public boolean isTrue() { - return isTrue; - } - - @Override - public boolean isFalse() { - return isFalse; - } - - @Override - public boolean isBoolean() { - return isTrue || isFalse; - } - - @Override - public Boolean asBoolean() { - return isNull ? super.asBoolean() : isTrue; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JSONLiteral other = (JSONLiteral)object; - return value.equals(other.value); - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; + + +@SuppressWarnings("serial") // use default serial UID +class JSONLiteral extends JSONValue { + + private final String value; + private final boolean isNull; + private final boolean isTrue; + private final boolean isFalse; + + JSONLiteral(String value) { + this.value = value; + isNull = "null".equals(value); + isTrue = "true".equals(value); + isFalse = "false".equals(value); + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeLiteral(value); + } + + @Override + public String toString() { + return value; + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public boolean isNull() { + return isNull; + } + + @Override + public boolean isTrue() { + return isTrue; + } + + @Override + public boolean isFalse() { + return isFalse; + } + + @Override + public boolean isBoolean() { + return isTrue || isFalse; + } + + @Override + public Boolean asBoolean() { + return isNull ? super.asBoolean() : isTrue; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONLiteral other = (JSONLiteral)object; + return value.equals(other.value); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONNumber.java b/blade-kit/src/main/java/com/blade/kit/json/JSONNumber.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/json/JSONNumber.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONNumber.java index 63c958da2..f5c74823f 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONNumber.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONNumber.java @@ -1,97 +1,97 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; - -@SuppressWarnings("serial") // use default serial UID -class JSONNumber extends JSONValue { - - private final String string; - - JSONNumber(String string) { - if (string == null) { - throw new NullPointerException("string is null"); - } - this.string = string; - } - - @Override - public String toString() { - return string; - } - - @Override - void write(JSONWriter writer) throws IOException { - writer.writeNumber(string); - } - - @Override - public boolean isNumber() { - return true; - } - - @Override - public Integer asInt() { - return Integer.parseInt(string, 10); - } - - @Override - public Long asLong() { - return Long.parseLong(string, 10); - } - - @Override - public Float asFloat() { - return Float.parseFloat(string); - } - - @Override - public Double asDouble() { - return Double.parseDouble(string); - } - - public Byte asByte() { - return Byte.parseByte(string); - } - - @Override - public int hashCode() { - return string.hashCode(); - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JSONNumber other = (JSONNumber) object; - return string.equals(other.string); - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; + +@SuppressWarnings("serial") // use default serial UID +class JSONNumber extends JSONValue { + + private final String string; + + JSONNumber(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + this.string = string; + } + + @Override + public String toString() { + return string; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeNumber(string); + } + + @Override + public boolean isNumber() { + return true; + } + + @Override + public Integer asInt() { + return Integer.parseInt(string, 10); + } + + @Override + public Long asLong() { + return Long.parseLong(string, 10); + } + + @Override + public Float asFloat() { + return Float.parseFloat(string); + } + + @Override + public Double asDouble() { + return Double.parseDouble(string); + } + + public Byte asByte() { + return Byte.parseByte(string); + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONNumber other = (JSONNumber) object; + return string.equals(other.string); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONObject.java b/blade-kit/src/main/java/com/blade/kit/json/JSONObject.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/json/JSONObject.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONObject.java index 064d69e08..1b8142c30 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONObject.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONObject.java @@ -1,947 +1,947 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import blade.kit.json.JSONObject.Member; - -/** - * Represents a JSON object, a set of name/value pairs, where the names are - * strings and the values are JSON values. - *

- * Members can be added using the add(String, ...) methods which - * accept instances of {@link JSONValue}, strings, primitive numbers, and - * boolean values. To modify certain values of an object, use the - * set(String, ...) methods. Please note that the add - * methods are faster than set as they do not search for existing - * members. On the other hand, the add methods do not prevent - * adding multiple members with the same name. Duplicate names are discouraged - * but not prohibited by JSON. - *

- *

- * Members can be accessed by their name using {@link #get(String)}. A list of - * all names can be obtained from the method {@link #names()}. This class also - * supports iterating over the members in document order using an - * {@link #iterator()} or an enhanced for loop: - *

- * - *
- * for (Member member : jsonObject) {
- *   String name = member.getName();
- *   JsonValue value = member.getValue();
- *   ...
- * }
- * 
- *

- * Even though JSON objects are unordered by definition, instances of this class - * preserve the order of members to allow processing in document order and to - * guarantee a predictable output. - *

- *

- * Note that this class is not thread-safe. If multiple threads - * access a JsonObject instance concurrently, while at least one of - * these threads modifies the contents of this object, access to the instance - * must be synchronized externally. Failure to do so may lead to an inconsistent - * state. - *

- *

- * This class is not supposed to be extended by clients. - *

- */ -@SuppressWarnings("serial") // use default serial UID -public class JSONObject extends JSONValue implements Iterable { - - private final List names; - private final List values; - private transient HashIndexTable table; - - /** - * Creates a new empty JsonObject. - */ - public JSONObject() { - names = new ArrayList(); - values = new ArrayList(); - table = new HashIndexTable(); - } - - /** - * Creates a new JsonObject, initialized with the contents of the specified - * JSON object. - * - * @param object - * the JSON object to get the initial contents from, must not be - * null - */ - public JSONObject(JSONObject object) { - this(object, false); - } - - private JSONObject(JSONObject object, boolean unmodifiable) { - if (object == null) { - throw new NullPointerException("object is null"); - } - if (unmodifiable) { - names = Collections.unmodifiableList(object.names); - values = Collections.unmodifiableList(object.values); - } else { - names = new ArrayList(object.names); - values = new ArrayList(object.values); - } - table = new HashIndexTable(); - updateHashIndex(); - } - - /** - * Returns an unmodifiable JsonObject for the specified one. This method - * allows to provide read-only access to a JsonObject. - *

- * The returned JsonObject is backed by the given object and reflect changes - * that happen to it. Attempts to modify the returned JsonObject result in - * an UnsupportedOperationException. - *

- * - * @param object - * the JsonObject for which an unmodifiable JsonObject is to be - * returned - * @return an unmodifiable view of the specified JsonObject - */ - public static JSONObject unmodifiableObject(JSONObject object) { - return new JSONObject(object, true); - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified int value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, int value) { - put(name, JSON.value(value)); - return this; - } - - public JSONObject put(String name, Object value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified long value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, long value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified float value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, float value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified double value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, double value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified boolean value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, boolean value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the JSON representation of the specified string. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, String value) { - put(name, JSON.value(value)); - return this; - } - - /** - * Appends a new member to the end of this object, with the specified name - * and the specified JSON value. - *

- * This method does not prevent duplicate names. Calling - * this method with a name that already exists in the object will append - * another member with the same name. In order to replace existing members, - * use the method set(name, value) instead. However, - * add is much faster than set (because it does - * not need to search for existing members). Therefore add should - * be preferred when constructing new objects. - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add, must not be null - * @return the object itself, to enable method chaining - */ - public JSONObject put(String name, JSONValue value) { - if (name == null) { - throw new NullPointerException("name is null"); - } - if (value == null) { - throw new NullPointerException("value is null"); - } - table.add(name, names.size()); - names.add(name); - values.add(value); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified int value. If this object - * does not contain a member with this name, a new member is added at the - * end of the object. If this object contains multiple members with this - * name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to replace - * @param value - * the value to set to the member - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, int value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified long value. If this object - * does not contain a member with this name, a new member is added at the - * end of the object. If this object contains multiple members with this - * name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to replace - * @param value - * the value to set to the member - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, long value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified float value. If this object - * does not contain a member with this name, a new member is added at the - * end of the object. If this object contains multiple members with this - * name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, float value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified double value. If this object - * does not contain a member with this name, a new member is added at the - * end of the object. If this object contains multiple members with this - * name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, double value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified boolean value. If this - * object does not contain a member with this name, a new member is added at - * the end of the object. If this object contains multiple members with this - * name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, boolean value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the JSON - * representation of the specified string. If this object does not contain a - * member with this name, a new member is added at the end of the object. If - * this object contains multiple members with this name, only the last one - * is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, String value) { - set(name, JSON.value(value)); - return this; - } - - /** - * Sets the value of the member with the specified name to the specified - * JSON value. If this object does not contain a member with this name, a - * new member is added at the end of the object. If this object contains - * multiple members with this name, only the last one is changed. - *

- * This method should only be used to modify existing - * objects. To fill a new object with members, the method - * add(name, value) should be preferred which is much faster - * (as it does not need to search for existing members). - *

- * - * @param name - * the name of the member to add - * @param value - * the value of the member to add, must not be null - * @return the object itself, to enable method chaining - */ - public JSONObject set(String name, JSONValue value) { - if (name == null) { - throw new NullPointerException("name is null"); - } - if (value == null) { - throw new NullPointerException("value is null"); - } - int index = indexOf(name); - if (index != -1) { - values.set(index, value); - } else { - table.add(name, names.size()); - names.add(name); - values.add(value); - } - return this; - } - - /** - * Removes a member with the specified name from this object. If this object - * contains multiple members with the given name, only the last one is - * removed. If this object does not contain a member with the specified - * name, the object is not modified. - * - * @param name - * the name of the member to remove - * @return the object itself, to enable method chaining - */ - public JSONObject remove(String name) { - if (name == null) { - throw new NullPointerException("name is null"); - } - int index = indexOf(name); - if (index != -1) { - table.remove(index); - names.remove(index); - values.remove(index); - } - return this; - } - - /** - * Copies all members of the specified object into this object. When the - * specified object contains members with names that also exist in this - * object, the existing values in this object will be replaced by the - * corresponding values in the specified object. - * - * @param object - * the object to merge - * @return the object itself, to enable method chaining - */ - public JSONObject merge(JSONObject object) { - if (object == null) { - throw new NullPointerException("object is null"); - } - for (Member member : object) { - this.set(member.name, member.value); - } - return this; - } - - /** - * Returns the value of the member with the specified name in this object. - * If this object contains multiple members with the given name, this method - * will return the last one. - * - * @param name - * the name of the member whose value is to be returned - * @return the value of the last member with the specified name, or - * null if this object does not contain a member with - * that name - */ - public JSONValue get(String name) { - if (name == null) { - throw new NullPointerException("name is null"); - } - int index = indexOf(name); - return index != -1 ? values.get(index) : null; - } - - public boolean contains(String name) { - if (name == null) { - throw new NullPointerException("name is null"); - } - int index = indexOf(name); - return index != -1; - } - - - /** - * Returns the int value of the member with the specified name - * in this object. If this object does not contain a member with this name, - * the given default value is returned. If this object contains multiple - * members with the given name, the last one will be picked. If this - * member's value does not represent a JSON number or if it cannot be - * interpreted as Java int, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public Integer getInt(String name, Integer defaultValue) { - JSONValue value = get(name); - return value != null ? value.asInt() : defaultValue; - } - - public Integer getInt(String name) { - return getInt(name, null); - } - - /** - * Returns the long value of the member with the specified name - * in this object. If this object does not contain a member with this name, - * the given default value is returned. If this object contains multiple - * members with the given name, the last one will be picked. If this - * member's value does not represent a JSON number or if it cannot be - * interpreted as Java long, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public Long getLong(String name, Long defaultValue) { - JSONValue value = get(name); - return value != null ? value.asLong() : defaultValue; - } - - public Long getLong(String name) { - return getLong(name, null); - } - - /** - * Returns the float value of the member with the specified - * name in this object. If this object does not contain a member with this - * name, the given default value is returned. If this object contains - * multiple members with the given name, the last one will be picked. If - * this member's value does not represent a JSON number or if it cannot be - * interpreted as Java float, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public Float getFloat(String name, Float defaultValue) { - JSONValue value = get(name); - return value != null ? value.asFloat() : defaultValue; - } - - public Float getFloat(String name) { - return getFloat(name, null); - } - - /** - * Returns the double value of the member with the specified - * name in this object. If this object does not contain a member with this - * name, the given default value is returned. If this object contains - * multiple members with the given name, the last one will be picked. If - * this member's value does not represent a JSON number or if it cannot be - * interpreted as Java double, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public Double getDouble(String name, Double defaultValue) { - JSONValue value = get(name); - return value != null ? value.asDouble() : defaultValue; - } - - public Double getDouble(String name) { - return getDouble(name, null); - } - - /** - * Returns the boolean value of the member with the specified - * name in this object. If this object does not contain a member with this - * name, the given default value is returned. If this object contains - * multiple members with the given name, the last one will be picked. If - * this member's value does not represent a JSON true or - * false value, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public Boolean getBoolean(String name, Boolean defaultValue) { - JSONValue value = get(name); - return value != null ? value.asBoolean() : defaultValue; - } - - public boolean getBoolean(String name) { - return getBoolean(name, null); - } - - /** - * Returns the String value of the member with the specified - * name in this object. If this object does not contain a member with this - * name, the given default value is returned. If this object contains - * multiple members with the given name, the last one is picked. If this - * member's value does not represent a JSON string, an exception is thrown. - * - * @param name - * the name of the member whose value is to be returned - * @param defaultValue - * the value to be returned if the requested member is missing - * @return the value of the last member with the specified name, or the - * given default value if this object does not contain a member with - * that name - */ - public String getString(String name, String defaultValue) { - JSONValue value = get(name); - return value != null ? value.asString() : defaultValue; - } - - public String getString(String name) { - return getString(name, null); - } - - /** - * Returns the number of members (name/value pairs) in this object. - * - * @return the number of members in this object - */ - public int size() { - return names.size(); - } - - /** - * Returns true if this object contains no members. - * - * @return true if this object contains no members - */ - public boolean isEmpty() { - return names.isEmpty(); - } - - /** - * Returns a list of the names in this object in document order. The - * returned list is backed by this object and will reflect subsequent - * changes. It cannot be used to modify this object. Attempts to modify the - * returned list will result in an exception. - * - * @return a list of the names in this object - */ - public List names() { - return Collections.unmodifiableList(names); - } - - /** - * Returns an iterator over the members of this object in document order. - * The returned iterator cannot be used to modify this object. - * - * @return an iterator over the members of this object - */ - public Iterator iterator() { - final Iterator namesIterator = names.iterator(); - final Iterator valuesIterator = values.iterator(); - return new Iterator() { - - public boolean hasNext() { - return namesIterator.hasNext(); - } - - public Member next() { - String name = namesIterator.next(); - JSONValue value = valuesIterator.next(); - return new Member(name, value); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } - - @Override - void write(JSONWriter writer) throws IOException { - writer.writeObjectOpen(); - Iterator namesIterator = names.iterator(); - Iterator valuesIterator = values.iterator(); - boolean first = true; - while (namesIterator.hasNext()) { - if (!first) { - writer.writeObjectSeparator(); - } - writer.writeMemberName(namesIterator.next()); - writer.writeMemberSeparator(); - valuesIterator.next().write(writer); - first = false; - } - writer.writeObjectClose(); - } - - @Override - public boolean isObject() { - return true; - } - - @Override - public JSONObject asJSONObject() { - return this; - } - - @Override - public int hashCode() { - int result = 1; - result = 31 * result + names.hashCode(); - result = 31 * result + values.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - JSONObject other = (JSONObject) obj; - return names.equals(other.names) && values.equals(other.values); - } - - int indexOf(String name) { - int index = table.get(name); - if (index != -1 && name.equals(names.get(index))) { - return index; - } - return names.lastIndexOf(name); - } - - private synchronized void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { - inputStream.defaultReadObject(); - table = new HashIndexTable(); - updateHashIndex(); - } - - private void updateHashIndex() { - int size = names.size(); - for (int i = 0; i < size; i++) { - table.add(names.get(i), i); - } - } - - /** - * Represents a member of a JSON object, a pair of a name and a value. - */ - public static class Member { - - private final String name; - private final JSONValue value; - - Member(String name, JSONValue value) { - this.name = name; - this.value = value; - } - - /** - * Returns the name of this member. - * - * @return the name of this member, never null - */ - public String getName() { - return name; - } - - /** - * Returns the value of this member. - * - * @return the value of this member, never null - */ - public JSONValue getValue() { - return value; - } - - @Override - public int hashCode() { - int result = 1; - result = 31 * result + name.hashCode(); - result = 31 * result + value.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Member other = (Member) obj; - return name.equals(other.name) && value.equals(other.value); - } - - } - - static class HashIndexTable { - - private final byte[] hashTable = new byte[32]; // must be a power of two - - public HashIndexTable() { - } - - public HashIndexTable(HashIndexTable original) { - System.arraycopy(original.hashTable, 0, hashTable, 0, hashTable.length); - } - - void add(String name, int index) { - int slot = hashSlotFor(name); - if (index < 0xff) { - // increment by 1, 0 stands for empty - hashTable[slot] = (byte) (index + 1); - } else { - hashTable[slot] = 0; - } - } - - void remove(int index) { - for (int i = 0; i < hashTable.length; i++) { - if (hashTable[i] == index + 1) { - hashTable[i] = 0; - } else if (hashTable[i] > index + 1) { - hashTable[i]--; - } - } - } - - int get(Object name) { - int slot = hashSlotFor(name); - // subtract 1, 0 stands for empty - return (hashTable[slot] & 0xff) - 1; - } - - private int hashSlotFor(Object element) { - return element.hashCode() & hashTable.length - 1; - } - - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import com.blade.kit.json.JSONObject.Member; + +/** + * Represents a JSON object, a set of name/value pairs, where the names are + * strings and the values are JSON values. + *

+ * Members can be added using the add(String, ...) methods which + * accept instances of {@link JSONValue}, strings, primitive numbers, and + * boolean values. To modify certain values of an object, use the + * set(String, ...) methods. Please note that the add + * methods are faster than set as they do not search for existing + * members. On the other hand, the add methods do not prevent + * adding multiple members with the same name. Duplicate names are discouraged + * but not prohibited by JSON. + *

+ *

+ * Members can be accessed by their name using {@link #get(String)}. A list of + * all names can be obtained from the method {@link #names()}. This class also + * supports iterating over the members in document order using an + * {@link #iterator()} or an enhanced for loop: + *

+ * + *
+ * for (Member member : jsonObject) {
+ *   String name = member.getName();
+ *   JsonValue value = member.getValue();
+ *   ...
+ * }
+ * 
+ *

+ * Even though JSON objects are unordered by definition, instances of this class + * preserve the order of members to allow processing in document order and to + * guarantee a predictable output. + *

+ *

+ * Note that this class is not thread-safe. If multiple threads + * access a JsonObject instance concurrently, while at least one of + * these threads modifies the contents of this object, access to the instance + * must be synchronized externally. Failure to do so may lead to an inconsistent + * state. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public class JSONObject extends JSONValue implements Iterable { + + private final List names; + private final List values; + private transient HashIndexTable table; + + /** + * Creates a new empty JsonObject. + */ + public JSONObject() { + names = new ArrayList(); + values = new ArrayList(); + table = new HashIndexTable(); + } + + /** + * Creates a new JsonObject, initialized with the contents of the specified + * JSON object. + * + * @param object + * the JSON object to get the initial contents from, must not be + * null + */ + public JSONObject(JSONObject object) { + this(object, false); + } + + private JSONObject(JSONObject object, boolean unmodifiable) { + if (object == null) { + throw new NullPointerException("object is null"); + } + if (unmodifiable) { + names = Collections.unmodifiableList(object.names); + values = Collections.unmodifiableList(object.values); + } else { + names = new ArrayList(object.names); + values = new ArrayList(object.values); + } + table = new HashIndexTable(); + updateHashIndex(); + } + + /** + * Returns an unmodifiable JsonObject for the specified one. This method + * allows to provide read-only access to a JsonObject. + *

+ * The returned JsonObject is backed by the given object and reflect changes + * that happen to it. Attempts to modify the returned JsonObject result in + * an UnsupportedOperationException. + *

+ * + * @param object + * the JsonObject for which an unmodifiable JsonObject is to be + * returned + * @return an unmodifiable view of the specified JsonObject + */ + public static JSONObject unmodifiableObject(JSONObject object) { + return new JSONObject(object, true); + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified int value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, int value) { + put(name, JSON.value(value)); + return this; + } + + public JSONObject put(String name, Object value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified long value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, long value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified float value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, float value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified double value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, double value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified boolean value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, boolean value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the JSON representation of the specified string. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, String value) { + put(name, JSON.value(value)); + return this; + } + + /** + * Appends a new member to the end of this object, with the specified name + * and the specified JSON value. + *

+ * This method does not prevent duplicate names. Calling + * this method with a name that already exists in the object will append + * another member with the same name. In order to replace existing members, + * use the method set(name, value) instead. However, + * add is much faster than set (because it does + * not need to search for existing members). Therefore add should + * be preferred when constructing new objects. + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add, must not be null + * @return the object itself, to enable method chaining + */ + public JSONObject put(String name, JSONValue value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + table.add(name, names.size()); + names.add(name); + values.add(value); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified int value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to replace + * @param value + * the value to set to the member + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, int value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified long value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to replace + * @param value + * the value to set to the member + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, long value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified float value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, float value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified double value. If this object + * does not contain a member with this name, a new member is added at the + * end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, double value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified boolean value. If this + * object does not contain a member with this name, a new member is added at + * the end of the object. If this object contains multiple members with this + * name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, boolean value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the JSON + * representation of the specified string. If this object does not contain a + * member with this name, a new member is added at the end of the object. If + * this object contains multiple members with this name, only the last one + * is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, String value) { + set(name, JSON.value(value)); + return this; + } + + /** + * Sets the value of the member with the specified name to the specified + * JSON value. If this object does not contain a member with this name, a + * new member is added at the end of the object. If this object contains + * multiple members with this name, only the last one is changed. + *

+ * This method should only be used to modify existing + * objects. To fill a new object with members, the method + * add(name, value) should be preferred which is much faster + * (as it does not need to search for existing members). + *

+ * + * @param name + * the name of the member to add + * @param value + * the value of the member to add, must not be null + * @return the object itself, to enable method chaining + */ + public JSONObject set(String name, JSONValue value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + int index = indexOf(name); + if (index != -1) { + values.set(index, value); + } else { + table.add(name, names.size()); + names.add(name); + values.add(value); + } + return this; + } + + /** + * Removes a member with the specified name from this object. If this object + * contains multiple members with the given name, only the last one is + * removed. If this object does not contain a member with the specified + * name, the object is not modified. + * + * @param name + * the name of the member to remove + * @return the object itself, to enable method chaining + */ + public JSONObject remove(String name) { + if (name == null) { + throw new NullPointerException("name is null"); + } + int index = indexOf(name); + if (index != -1) { + table.remove(index); + names.remove(index); + values.remove(index); + } + return this; + } + + /** + * Copies all members of the specified object into this object. When the + * specified object contains members with names that also exist in this + * object, the existing values in this object will be replaced by the + * corresponding values in the specified object. + * + * @param object + * the object to merge + * @return the object itself, to enable method chaining + */ + public JSONObject merge(JSONObject object) { + if (object == null) { + throw new NullPointerException("object is null"); + } + for (Member member : object) { + this.set(member.name, member.value); + } + return this; + } + + /** + * Returns the value of the member with the specified name in this object. + * If this object contains multiple members with the given name, this method + * will return the last one. + * + * @param name + * the name of the member whose value is to be returned + * @return the value of the last member with the specified name, or + * null if this object does not contain a member with + * that name + */ + public JSONValue get(String name) { + if (name == null) { + throw new NullPointerException("name is null"); + } + int index = indexOf(name); + return index != -1 ? values.get(index) : null; + } + + public boolean contains(String name) { + if (name == null) { + throw new NullPointerException("name is null"); + } + int index = indexOf(name); + return index != -1; + } + + + /** + * Returns the int value of the member with the specified name + * in this object. If this object does not contain a member with this name, + * the given default value is returned. If this object contains multiple + * members with the given name, the last one will be picked. If this + * member's value does not represent a JSON number or if it cannot be + * interpreted as Java int, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public Integer getInt(String name, Integer defaultValue) { + JSONValue value = get(name); + return value != null ? value.asInt() : defaultValue; + } + + public Integer getInt(String name) { + return getInt(name, null); + } + + /** + * Returns the long value of the member with the specified name + * in this object. If this object does not contain a member with this name, + * the given default value is returned. If this object contains multiple + * members with the given name, the last one will be picked. If this + * member's value does not represent a JSON number or if it cannot be + * interpreted as Java long, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public Long getLong(String name, Long defaultValue) { + JSONValue value = get(name); + return value != null ? value.asLong() : defaultValue; + } + + public Long getLong(String name) { + return getLong(name, null); + } + + /** + * Returns the float value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one will be picked. If + * this member's value does not represent a JSON number or if it cannot be + * interpreted as Java float, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public Float getFloat(String name, Float defaultValue) { + JSONValue value = get(name); + return value != null ? value.asFloat() : defaultValue; + } + + public Float getFloat(String name) { + return getFloat(name, null); + } + + /** + * Returns the double value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one will be picked. If + * this member's value does not represent a JSON number or if it cannot be + * interpreted as Java double, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public Double getDouble(String name, Double defaultValue) { + JSONValue value = get(name); + return value != null ? value.asDouble() : defaultValue; + } + + public Double getDouble(String name) { + return getDouble(name, null); + } + + /** + * Returns the boolean value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one will be picked. If + * this member's value does not represent a JSON true or + * false value, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public Boolean getBoolean(String name, Boolean defaultValue) { + JSONValue value = get(name); + return value != null ? value.asBoolean() : defaultValue; + } + + public boolean getBoolean(String name) { + return getBoolean(name, null); + } + + /** + * Returns the String value of the member with the specified + * name in this object. If this object does not contain a member with this + * name, the given default value is returned. If this object contains + * multiple members with the given name, the last one is picked. If this + * member's value does not represent a JSON string, an exception is thrown. + * + * @param name + * the name of the member whose value is to be returned + * @param defaultValue + * the value to be returned if the requested member is missing + * @return the value of the last member with the specified name, or the + * given default value if this object does not contain a member with + * that name + */ + public String getString(String name, String defaultValue) { + JSONValue value = get(name); + return value != null ? value.asString() : defaultValue; + } + + public String getString(String name) { + return getString(name, null); + } + + /** + * Returns the number of members (name/value pairs) in this object. + * + * @return the number of members in this object + */ + public int size() { + return names.size(); + } + + /** + * Returns true if this object contains no members. + * + * @return true if this object contains no members + */ + public boolean isEmpty() { + return names.isEmpty(); + } + + /** + * Returns a list of the names in this object in document order. The + * returned list is backed by this object and will reflect subsequent + * changes. It cannot be used to modify this object. Attempts to modify the + * returned list will result in an exception. + * + * @return a list of the names in this object + */ + public List names() { + return Collections.unmodifiableList(names); + } + + /** + * Returns an iterator over the members of this object in document order. + * The returned iterator cannot be used to modify this object. + * + * @return an iterator over the members of this object + */ + public Iterator iterator() { + final Iterator namesIterator = names.iterator(); + final Iterator valuesIterator = values.iterator(); + return new Iterator() { + + public boolean hasNext() { + return namesIterator.hasNext(); + } + + public Member next() { + String name = namesIterator.next(); + JSONValue value = valuesIterator.next(); + return new Member(name, value); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + }; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeObjectOpen(); + Iterator namesIterator = names.iterator(); + Iterator valuesIterator = values.iterator(); + boolean first = true; + while (namesIterator.hasNext()) { + if (!first) { + writer.writeObjectSeparator(); + } + writer.writeMemberName(namesIterator.next()); + writer.writeMemberSeparator(); + valuesIterator.next().write(writer); + first = false; + } + writer.writeObjectClose(); + } + + @Override + public boolean isObject() { + return true; + } + + @Override + public JSONObject asJSONObject() { + return this; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + names.hashCode(); + result = 31 * result + values.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + JSONObject other = (JSONObject) obj; + return names.equals(other.names) && values.equals(other.values); + } + + int indexOf(String name) { + int index = table.get(name); + if (index != -1 && name.equals(names.get(index))) { + return index; + } + return names.lastIndexOf(name); + } + + private synchronized void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { + inputStream.defaultReadObject(); + table = new HashIndexTable(); + updateHashIndex(); + } + + private void updateHashIndex() { + int size = names.size(); + for (int i = 0; i < size; i++) { + table.add(names.get(i), i); + } + } + + /** + * Represents a member of a JSON object, a pair of a name and a value. + */ + public static class Member { + + private final String name; + private final JSONValue value; + + Member(String name, JSONValue value) { + this.name = name; + this.value = value; + } + + /** + * Returns the name of this member. + * + * @return the name of this member, never null + */ + public String getName() { + return name; + } + + /** + * Returns the value of this member. + * + * @return the value of this member, never null + */ + public JSONValue getValue() { + return value; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + name.hashCode(); + result = 31 * result + value.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Member other = (Member) obj; + return name.equals(other.name) && value.equals(other.value); + } + + } + + static class HashIndexTable { + + private final byte[] hashTable = new byte[32]; // must be a power of two + + public HashIndexTable() { + } + + public HashIndexTable(HashIndexTable original) { + System.arraycopy(original.hashTable, 0, hashTable, 0, hashTable.length); + } + + void add(String name, int index) { + int slot = hashSlotFor(name); + if (index < 0xff) { + // increment by 1, 0 stands for empty + hashTable[slot] = (byte) (index + 1); + } else { + hashTable[slot] = 0; + } + } + + void remove(int index) { + for (int i = 0; i < hashTable.length; i++) { + if (hashTable[i] == index + 1) { + hashTable[i] = 0; + } else if (hashTable[i] > index + 1) { + hashTable[i]--; + } + } + } + + int get(Object name) { + int slot = hashSlotFor(name); + // subtract 1, 0 stands for empty + return (hashTable[slot] & 0xff) - 1; + } + + private int hashSlotFor(Object element) { + return element.hashCode() & hashTable.length - 1; + } + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONParser.java b/blade-kit/src/main/java/com/blade/kit/json/JSONParser.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/json/JSONParser.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONParser.java index 8626a65a3..c118bf5de 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONParser.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONParser.java @@ -1,511 +1,511 @@ -/******************************************************************************* - * Copyright (c) 2013, 2016 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; - - -/** - * A streaming parser for JSON text. The parser reports all events to a given handler. - */ -public class JSONParser { - - private static final int MAX_NESTING_LEVEL = 1000; - private static final int MIN_BUFFER_SIZE = 10; - private static final int DEFAULT_BUFFER_SIZE = 1024; - - private final JSONHandler handler; - private Reader reader; - private char[] buffer; - private int bufferOffset; - private int index; - private int fill; - private int line; - private int lineOffset; - private int current; - private StringBuilder captureBuffer; - private int captureStart; - private int nestingLevel; - - /* - * | bufferOffset - * v - * [a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t] < input - * [l|m|n|o|p|q|r|s|t|?|?] < buffer - * ^ ^ - * | index fill - */ - - /** - * Creates a new JsonParser with the given handler. The parser will report all parser events to - * this handler. - * - * @param handler - * the handler to process parser events - */ - @SuppressWarnings("unchecked") - public JSONParser(JSONHandler handler) { - if (handler == null) { - throw new NullPointerException("handler is null"); - } - this.handler = (JSONHandler)handler; - handler.parser = this; - } - - /** - * Parses the given input string. The input must contain a valid JSON value, optionally padded - * with whitespace. - * - * @param string - * the input string, must be valid JSON - * @throws ParseException - * if the input is not valid JSON - */ - public void parse(String string) { - if (string == null) { - throw new NullPointerException("string is null"); - } - int bufferSize = Math.max(MIN_BUFFER_SIZE, Math.min(DEFAULT_BUFFER_SIZE, string.length())); - try { - parse(new StringReader(string), bufferSize); - } catch (IOException exception) { - // StringReader does not throw IOException - throw new RuntimeException(exception); - } - } - - /** - * Reads the entire input from the given reader and parses it as JSON. The input must contain a - * valid JSON value, optionally padded with whitespace. - *

- * Characters are read in chunks into a default-sized input buffer. Hence, wrapping a reader in an - * additional BufferedReader likely won't improve reading performance. - *

- * - * @param reader - * the reader to read the input from - * @throws IOException - * if an I/O error occurs in the reader - * @throws ParseException - * if the input is not valid JSON - */ - public void parse(Reader reader) throws IOException { - parse(reader, DEFAULT_BUFFER_SIZE); - } - - /** - * Reads the entire input from the given reader and parses it as JSON. The input must contain a - * valid JSON value, optionally padded with whitespace. - *

- * Characters are read in chunks into an input buffer of the given size. Hence, wrapping a reader - * in an additional BufferedReader likely won't improve reading performance. - *

- * - * @param reader - * the reader to read the input from - * @param buffersize - * the size of the input buffer in chars - * @throws IOException - * if an I/O error occurs in the reader - * @throws ParseException - * if the input is not valid JSON - */ - public void parse(Reader reader, int buffersize) throws IOException { - if (reader == null) { - throw new NullPointerException("reader is null"); - } - if (buffersize <= 0) { - throw new IllegalArgumentException("buffersize is zero or negative"); - } - this.reader = reader; - buffer = new char[buffersize]; - bufferOffset = 0; - index = 0; - fill = 0; - line = 1; - lineOffset = 0; - current = 0; - captureStart = -1; - read(); - skipWhiteSpace(); - readValue(); - skipWhiteSpace(); - if (!isEndOfText()) { - throw error("Unexpected character"); - } - } - - private void readValue() throws IOException { - switch (current) { - case 'n': - readNull(); - break; - case 't': - readTrue(); - break; - case 'f': - readFalse(); - break; - case '"': - readString(); - break; - case '[': - readArray(); - break; - case '{': - readObject(); - break; - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - readNumber(); - break; - default: - throw expected("value"); - } - } - - private void readArray() throws IOException { - Object array = handler.startArray(); - read(); - if (++nestingLevel > MAX_NESTING_LEVEL) { - throw error("Nesting too deep"); - } - skipWhiteSpace(); - if (readChar(']')) { - nestingLevel--; - handler.endArray(array); - return; - } - do { - skipWhiteSpace(); - handler.startArrayValue(array); - readValue(); - handler.endArrayValue(array); - skipWhiteSpace(); - } while (readChar(',')); - if (!readChar(']')) { - throw expected("',' or ']'"); - } - nestingLevel--; - handler.endArray(array); - } - - private void readObject() throws IOException { - Object object = handler.startObject(); - read(); - if (++nestingLevel > MAX_NESTING_LEVEL) { - throw error("Nesting too deep"); - } - skipWhiteSpace(); - if (readChar('}')) { - nestingLevel--; - handler.endObject(object); - return; - } - do { - skipWhiteSpace(); - handler.startObjectName(object); - String name = readName(); - handler.endObjectName(object, name); - skipWhiteSpace(); - if (!readChar(':')) { - throw expected("':'"); - } - skipWhiteSpace(); - handler.startObjectValue(object, name); - readValue(); - handler.endObjectValue(object, name); - skipWhiteSpace(); - } while (readChar(',')); - if (!readChar('}')) { - throw expected("',' or '}'"); - } - nestingLevel--; - handler.endObject(object); - } - - private String readName() throws IOException { - if (current != '"') { - throw expected("name"); - } - return readStringInternal(); - } - - private void readNull() throws IOException { - handler.startNull(); - read(); - readRequiredChar('u'); - readRequiredChar('l'); - readRequiredChar('l'); - handler.endNull(); - } - - private void readTrue() throws IOException { - handler.startBoolean(); - read(); - readRequiredChar('r'); - readRequiredChar('u'); - readRequiredChar('e'); - handler.endBoolean(true); - } - - private void readFalse() throws IOException { - handler.startBoolean(); - read(); - readRequiredChar('a'); - readRequiredChar('l'); - readRequiredChar('s'); - readRequiredChar('e'); - handler.endBoolean(false); - } - - private void readRequiredChar(char ch) throws IOException { - if (!readChar(ch)) { - throw expected("'" + ch + "'"); - } - } - - private void readString() throws IOException { - handler.startString(); - handler.endString(readStringInternal()); - } - - private String readStringInternal() throws IOException { - read(); - startCapture(); - while (current != '"') { - if (current == '\\') { - pauseCapture(); - readEscape(); - startCapture(); - } else if (current < 0x20) { - throw expected("valid string character"); - } else { - read(); - } - } - String string = endCapture(); - read(); - return string; - } - - private void readEscape() throws IOException { - read(); - switch (current) { - case '"': - case '/': - case '\\': - captureBuffer.append((char)current); - break; - case 'b': - captureBuffer.append('\b'); - break; - case 'f': - captureBuffer.append('\f'); - break; - case 'n': - captureBuffer.append('\n'); - break; - case 'r': - captureBuffer.append('\r'); - break; - case 't': - captureBuffer.append('\t'); - break; - case 'u': - char[] hexChars = new char[4]; - for (int i = 0; i < 4; i++) { - read(); - if (!isHexDigit()) { - throw expected("hexadecimal digit"); - } - hexChars[i] = (char)current; - } - captureBuffer.append((char)Integer.parseInt(new String(hexChars), 16)); - break; - default: - throw expected("valid escape sequence"); - } - read(); - } - - private void readNumber() throws IOException { - handler.startNumber(); - startCapture(); - readChar('-'); - int firstDigit = current; - if (!readDigit()) { - throw expected("digit"); - } - if (firstDigit != '0') { - while (readDigit()) { - } - } - readFraction(); - readExponent(); - handler.endNumber(endCapture()); - } - - private boolean readFraction() throws IOException { - if (!readChar('.')) { - return false; - } - if (!readDigit()) { - throw expected("digit"); - } - while (readDigit()) { - } - return true; - } - - private boolean readExponent() throws IOException { - if (!readChar('e') && !readChar('E')) { - return false; - } - if (!readChar('+')) { - readChar('-'); - } - if (!readDigit()) { - throw expected("digit"); - } - while (readDigit()) { - } - return true; - } - - private boolean readChar(char ch) throws IOException { - if (current != ch) { - return false; - } - read(); - return true; - } - - private boolean readDigit() throws IOException { - if (!isDigit()) { - return false; - } - read(); - return true; - } - - private void skipWhiteSpace() throws IOException { - while (isWhiteSpace()) { - read(); - } - } - - private void read() throws IOException { - if (index == fill) { - if (captureStart != -1) { - captureBuffer.append(buffer, captureStart, fill - captureStart); - captureStart = 0; - } - bufferOffset += fill; - fill = reader.read(buffer, 0, buffer.length); - index = 0; - if (fill == -1) { - current = -1; - index++; - return; - } - } - if (current == '\n') { - line++; - lineOffset = bufferOffset + index; - } - current = buffer[index++]; - } - - private void startCapture() { - if (captureBuffer == null) { - captureBuffer = new StringBuilder(); - } - captureStart = index - 1; - } - - private void pauseCapture() { - int end = current == -1 ? index : index - 1; - captureBuffer.append(buffer, captureStart, end - captureStart); - captureStart = -1; - } - - private String endCapture() { - int start = captureStart; - int end = index - 1; - captureStart = -1; - if (captureBuffer.length() > 0) { - captureBuffer.append(buffer, start, end - start); - String captured = captureBuffer.toString(); - captureBuffer.setLength(0); - return captured; - } - return new String(buffer, start, end - start); - } - - Location getLocation() { - int offset = bufferOffset + index - 1; - int column = offset - lineOffset + 1; - return new Location(offset, line, column); - } - - private ParseException expected(String expected) { - if (isEndOfText()) { - return error("Unexpected end of input"); - } - return error("Expected " + expected); - } - - private ParseException error(String message) { - return new ParseException(message, getLocation()); - } - - private boolean isWhiteSpace() { - return current == ' ' || current == '\t' || current == '\n' || current == '\r'; - } - - private boolean isDigit() { - return current >= '0' && current <= '9'; - } - - private boolean isHexDigit() { - return current >= '0' && current <= '9' - || current >= 'a' && current <= 'f' - || current >= 'A' && current <= 'F'; - } - - private boolean isEndOfText() { - return current == -1; - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + + +/** + * A streaming parser for JSON text. The parser reports all events to a given handler. + */ +public class JSONParser { + + private static final int MAX_NESTING_LEVEL = 1000; + private static final int MIN_BUFFER_SIZE = 10; + private static final int DEFAULT_BUFFER_SIZE = 1024; + + private final JSONHandler handler; + private Reader reader; + private char[] buffer; + private int bufferOffset; + private int index; + private int fill; + private int line; + private int lineOffset; + private int current; + private StringBuilder captureBuffer; + private int captureStart; + private int nestingLevel; + + /* + * | bufferOffset + * v + * [a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t] < input + * [l|m|n|o|p|q|r|s|t|?|?] < buffer + * ^ ^ + * | index fill + */ + + /** + * Creates a new JsonParser with the given handler. The parser will report all parser events to + * this handler. + * + * @param handler + * the handler to process parser events + */ + @SuppressWarnings("unchecked") + public JSONParser(JSONHandler handler) { + if (handler == null) { + throw new NullPointerException("handler is null"); + } + this.handler = (JSONHandler)handler; + handler.parser = this; + } + + /** + * Parses the given input string. The input must contain a valid JSON value, optionally padded + * with whitespace. + * + * @param string + * the input string, must be valid JSON + * @throws ParseException + * if the input is not valid JSON + */ + public void parse(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + int bufferSize = Math.max(MIN_BUFFER_SIZE, Math.min(DEFAULT_BUFFER_SIZE, string.length())); + try { + parse(new StringReader(string), bufferSize); + } catch (IOException exception) { + // StringReader does not throw IOException + throw new RuntimeException(exception); + } + } + + /** + * Reads the entire input from the given reader and parses it as JSON. The input must contain a + * valid JSON value, optionally padded with whitespace. + *

+ * Characters are read in chunks into a default-sized input buffer. Hence, wrapping a reader in an + * additional BufferedReader likely won't improve reading performance. + *

+ * + * @param reader + * the reader to read the input from + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + */ + public void parse(Reader reader) throws IOException { + parse(reader, DEFAULT_BUFFER_SIZE); + } + + /** + * Reads the entire input from the given reader and parses it as JSON. The input must contain a + * valid JSON value, optionally padded with whitespace. + *

+ * Characters are read in chunks into an input buffer of the given size. Hence, wrapping a reader + * in an additional BufferedReader likely won't improve reading performance. + *

+ * + * @param reader + * the reader to read the input from + * @param buffersize + * the size of the input buffer in chars + * @throws IOException + * if an I/O error occurs in the reader + * @throws ParseException + * if the input is not valid JSON + */ + public void parse(Reader reader, int buffersize) throws IOException { + if (reader == null) { + throw new NullPointerException("reader is null"); + } + if (buffersize <= 0) { + throw new IllegalArgumentException("buffersize is zero or negative"); + } + this.reader = reader; + buffer = new char[buffersize]; + bufferOffset = 0; + index = 0; + fill = 0; + line = 1; + lineOffset = 0; + current = 0; + captureStart = -1; + read(); + skipWhiteSpace(); + readValue(); + skipWhiteSpace(); + if (!isEndOfText()) { + throw error("Unexpected character"); + } + } + + private void readValue() throws IOException { + switch (current) { + case 'n': + readNull(); + break; + case 't': + readTrue(); + break; + case 'f': + readFalse(); + break; + case '"': + readString(); + break; + case '[': + readArray(); + break; + case '{': + readObject(); + break; + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + readNumber(); + break; + default: + throw expected("value"); + } + } + + private void readArray() throws IOException { + Object array = handler.startArray(); + read(); + if (++nestingLevel > MAX_NESTING_LEVEL) { + throw error("Nesting too deep"); + } + skipWhiteSpace(); + if (readChar(']')) { + nestingLevel--; + handler.endArray(array); + return; + } + do { + skipWhiteSpace(); + handler.startArrayValue(array); + readValue(); + handler.endArrayValue(array); + skipWhiteSpace(); + } while (readChar(',')); + if (!readChar(']')) { + throw expected("',' or ']'"); + } + nestingLevel--; + handler.endArray(array); + } + + private void readObject() throws IOException { + Object object = handler.startObject(); + read(); + if (++nestingLevel > MAX_NESTING_LEVEL) { + throw error("Nesting too deep"); + } + skipWhiteSpace(); + if (readChar('}')) { + nestingLevel--; + handler.endObject(object); + return; + } + do { + skipWhiteSpace(); + handler.startObjectName(object); + String name = readName(); + handler.endObjectName(object, name); + skipWhiteSpace(); + if (!readChar(':')) { + throw expected("':'"); + } + skipWhiteSpace(); + handler.startObjectValue(object, name); + readValue(); + handler.endObjectValue(object, name); + skipWhiteSpace(); + } while (readChar(',')); + if (!readChar('}')) { + throw expected("',' or '}'"); + } + nestingLevel--; + handler.endObject(object); + } + + private String readName() throws IOException { + if (current != '"') { + throw expected("name"); + } + return readStringInternal(); + } + + private void readNull() throws IOException { + handler.startNull(); + read(); + readRequiredChar('u'); + readRequiredChar('l'); + readRequiredChar('l'); + handler.endNull(); + } + + private void readTrue() throws IOException { + handler.startBoolean(); + read(); + readRequiredChar('r'); + readRequiredChar('u'); + readRequiredChar('e'); + handler.endBoolean(true); + } + + private void readFalse() throws IOException { + handler.startBoolean(); + read(); + readRequiredChar('a'); + readRequiredChar('l'); + readRequiredChar('s'); + readRequiredChar('e'); + handler.endBoolean(false); + } + + private void readRequiredChar(char ch) throws IOException { + if (!readChar(ch)) { + throw expected("'" + ch + "'"); + } + } + + private void readString() throws IOException { + handler.startString(); + handler.endString(readStringInternal()); + } + + private String readStringInternal() throws IOException { + read(); + startCapture(); + while (current != '"') { + if (current == '\\') { + pauseCapture(); + readEscape(); + startCapture(); + } else if (current < 0x20) { + throw expected("valid string character"); + } else { + read(); + } + } + String string = endCapture(); + read(); + return string; + } + + private void readEscape() throws IOException { + read(); + switch (current) { + case '"': + case '/': + case '\\': + captureBuffer.append((char)current); + break; + case 'b': + captureBuffer.append('\b'); + break; + case 'f': + captureBuffer.append('\f'); + break; + case 'n': + captureBuffer.append('\n'); + break; + case 'r': + captureBuffer.append('\r'); + break; + case 't': + captureBuffer.append('\t'); + break; + case 'u': + char[] hexChars = new char[4]; + for (int i = 0; i < 4; i++) { + read(); + if (!isHexDigit()) { + throw expected("hexadecimal digit"); + } + hexChars[i] = (char)current; + } + captureBuffer.append((char)Integer.parseInt(new String(hexChars), 16)); + break; + default: + throw expected("valid escape sequence"); + } + read(); + } + + private void readNumber() throws IOException { + handler.startNumber(); + startCapture(); + readChar('-'); + int firstDigit = current; + if (!readDigit()) { + throw expected("digit"); + } + if (firstDigit != '0') { + while (readDigit()) { + } + } + readFraction(); + readExponent(); + handler.endNumber(endCapture()); + } + + private boolean readFraction() throws IOException { + if (!readChar('.')) { + return false; + } + if (!readDigit()) { + throw expected("digit"); + } + while (readDigit()) { + } + return true; + } + + private boolean readExponent() throws IOException { + if (!readChar('e') && !readChar('E')) { + return false; + } + if (!readChar('+')) { + readChar('-'); + } + if (!readDigit()) { + throw expected("digit"); + } + while (readDigit()) { + } + return true; + } + + private boolean readChar(char ch) throws IOException { + if (current != ch) { + return false; + } + read(); + return true; + } + + private boolean readDigit() throws IOException { + if (!isDigit()) { + return false; + } + read(); + return true; + } + + private void skipWhiteSpace() throws IOException { + while (isWhiteSpace()) { + read(); + } + } + + private void read() throws IOException { + if (index == fill) { + if (captureStart != -1) { + captureBuffer.append(buffer, captureStart, fill - captureStart); + captureStart = 0; + } + bufferOffset += fill; + fill = reader.read(buffer, 0, buffer.length); + index = 0; + if (fill == -1) { + current = -1; + index++; + return; + } + } + if (current == '\n') { + line++; + lineOffset = bufferOffset + index; + } + current = buffer[index++]; + } + + private void startCapture() { + if (captureBuffer == null) { + captureBuffer = new StringBuilder(); + } + captureStart = index - 1; + } + + private void pauseCapture() { + int end = current == -1 ? index : index - 1; + captureBuffer.append(buffer, captureStart, end - captureStart); + captureStart = -1; + } + + private String endCapture() { + int start = captureStart; + int end = index - 1; + captureStart = -1; + if (captureBuffer.length() > 0) { + captureBuffer.append(buffer, start, end - start); + String captured = captureBuffer.toString(); + captureBuffer.setLength(0); + return captured; + } + return new String(buffer, start, end - start); + } + + Location getLocation() { + int offset = bufferOffset + index - 1; + int column = offset - lineOffset + 1; + return new Location(offset, line, column); + } + + private ParseException expected(String expected) { + if (isEndOfText()) { + return error("Unexpected end of input"); + } + return error("Expected " + expected); + } + + private ParseException error(String message) { + return new ParseException(message, getLocation()); + } + + private boolean isWhiteSpace() { + return current == ' ' || current == '\t' || current == '\n' || current == '\r'; + } + + private boolean isDigit() { + return current >= '0' && current <= '9'; + } + + private boolean isHexDigit() { + return current >= '0' && current <= '9' + || current >= 'a' && current <= 'f' + || current >= 'A' && current <= 'F'; + } + + private boolean isEndOfText() { + return current == -1; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONString.java b/blade-kit/src/main/java/com/blade/kit/json/JSONString.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/json/JSONString.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONString.java index 7751b2b96..c64ec66ab 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONString.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONString.java @@ -1,74 +1,74 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; - - -@SuppressWarnings("serial") // use default serial UID -class JSONString extends JSONValue { - - private final String string; - - JSONString(String string) { - if (string == null) { - throw new NullPointerException("string is null"); - } - this.string = string; - } - - @Override - void write(JSONWriter writer) throws IOException { - writer.writeString(string); - } - - @Override - public boolean isString() { - return true; - } - - @Override - public String asString() { - return string; - } - - @Override - public int hashCode() { - return string.hashCode(); - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null) { - return false; - } - if (getClass() != object.getClass()) { - return false; - } - JSONString other = (JSONString)object; - return string.equals(other.string); - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; + + +@SuppressWarnings("serial") // use default serial UID +class JSONString extends JSONValue { + + private final String string; + + JSONString(String string) { + if (string == null) { + throw new NullPointerException("string is null"); + } + this.string = string; + } + + @Override + void write(JSONWriter writer) throws IOException { + writer.writeString(string); + } + + @Override + public boolean isString() { + return true; + } + + @Override + public String asString() { + return string; + } + + @Override + public int hashCode() { + return string.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (getClass() != object.getClass()) { + return false; + } + JSONString other = (JSONString)object; + return string.equals(other.string); + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONValue.java b/blade-kit/src/main/java/com/blade/kit/json/JSONValue.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/json/JSONValue.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONValue.java index c6312c6cd..7742582bc 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONValue.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONValue.java @@ -1,391 +1,391 @@ -/******************************************************************************* - * Copyright (c) 2013, 2016 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Serializable; -import java.io.StringWriter; -import java.io.Writer; - -/** - * Represents a JSON value. This can be a JSON object, an - * array, a number, a string - * , or one of the literals true, false, and - * null. - *

- * The literals true, false, and - * null are represented by the constants {@link #TRUE}, - * {@link #FALSE}, and {@link #NULL}. - *

- *

- * JSON objects and arrays are represented by - * the subtypes {@link JSONObject} and {@link JSONArray}. Instances of these - * types can be created using the public constructors of these classes. - *

- *

- * Instances that represent JSON numbers, - * strings and boolean values can be created - * using the static factory methods {@link #valueOf(String)}, - * {@link #valueOf(long)}, {@link #valueOf(double)}, etc. - *

- *

- * In order to find out whether an instance of this class is of a certain type, - * the methods {@link #isObject()}, {@link #isArray()}, {@link #isString()}, - * {@link #isNumber()} etc. can be used. - *

- *

- * If the type of a JSON value is known, the methods {@link #asObject()}, - * {@link #asArray()}, {@link #asString()}, {@link #asInt()}, etc. can be used - * to get this value directly in the appropriate target type. - *

- *

- * This class is not supposed to be extended by clients. - *

- */ -@SuppressWarnings("serial") // use default serial UID -public abstract class JSONValue implements Serializable { - - JSONValue() { - // prevent subclasses outside of this package - } - - /** - * Detects whether this value represents a JSON object. If this is the case, - * this value is an instance of {@link JSONObject}. - * - * @return true if this value is an instance of JsonObject - */ - public boolean isObject() { - return false; - } - - public boolean isBean() { - return false; - } - - /** - * Detects whether this value represents a JSON array. If this is the case, - * this value is an instance of {@link JSONArray}. - * - * @return true if this value is an instance of JsonArray - */ - public boolean isArray() { - return false; - } - - /** - * Detects whether this value represents a JSON number. - * - * @return true if this value represents a JSON number - */ - public boolean isNumber() { - return false; - } - - /** - * Detects whether this value represents a JSON string. - * - * @return true if this value represents a JSON string - */ - public boolean isString() { - return false; - } - - public boolean isLong(){ - return false; - } - - /** - * Detects whether this value represents a boolean value. - * - * @return true if this value represents either the JSON - * literal true or false - */ - public boolean isBoolean() { - return false; - } - - /** - * Detects whether this value represents the JSON literal true. - * - * @return true if this value represents the JSON literal - * true - */ - public boolean isTrue() { - return false; - } - - /** - * Detects whether this value represents the JSON literal false - * . - * - * @return true if this value represents the JSON literal - * false - */ - public boolean isFalse() { - return false; - } - - /** - * Detects whether this value represents the JSON literal null. - * - * @return true if this value represents the JSON literal - * null - */ - public boolean isNull() { - return false; - } - - /** - * Returns this JSON value as {@link JSONObject}, assuming that this value - * represents a JSON object. If this is not the case, an exception is - * thrown. - * - * @return a JSONObject for this value - * @throws UnsupportedOperationException - * if this value is not a JSON object - */ - public JSONObject asJSONObject() { - throw new UnsupportedOperationException("Not an JSONObject: " + toString()); - } - - /** - * Returns this JSON value as {@link JSONArray}, assuming that this value - * represents a JSON array. If this is not the case, an exception is thrown. - * - * @return a JSONArray for this value - * @throws UnsupportedOperationException - * if this value is not a JSON array - */ - public JSONArray asArray() { - throw new UnsupportedOperationException("Not an array: " + toString()); - } - - /** - * Returns this JSON value as an int value, assuming that this - * value represents a JSON number that can be interpreted as Java - * int. If this is not the case, an exception is thrown. - *

- * To be interpreted as Java int, the JSON number must neither - * contain an exponent nor a fraction part. Moreover, the number must be in - * the Integer range. - *

- * - * @return this value as int - * @throws UnsupportedOperationException - * if this value is not a JSON number - * @throws NumberFormatException - * if this JSON number can not be interpreted as - * int value - */ - public Integer asInt() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as a long value, assuming that this - * value represents a JSON number that can be interpreted as Java - * long. If this is not the case, an exception is thrown. - *

- * To be interpreted as Java long, the JSON number must neither - * contain an exponent nor a fraction part. Moreover, the number must be in - * the Long range. - *

- * - * @return this value as long - * @throws UnsupportedOperationException - * if this value is not a JSON number - * @throws NumberFormatException - * if this JSON number can not be interpreted as - * long value - */ - public Long asLong() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as a float value, assuming that this - * value represents a JSON number. If this is not the case, an exception is - * thrown. - *

- * If the JSON number is out of the Float range, - * {@link Float#POSITIVE_INFINITY} or {@link Float#NEGATIVE_INFINITY} is - * returned. - *

- * - * @return this value as float - * @throws UnsupportedOperationException - * if this value is not a JSON number - */ - public Float asFloat() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as a double value, assuming that - * this value represents a JSON number. If this is not the case, an - * exception is thrown. - *

- * If the JSON number is out of the Double range, - * {@link Double#POSITIVE_INFINITY} or {@link Double#NEGATIVE_INFINITY} is - * returned. - *

- * - * @return this value as double - * @throws UnsupportedOperationException - * if this value is not a JSON number - */ - public Double asDouble() { - throw new UnsupportedOperationException("Not a number: " + toString()); - } - - /** - * Returns this JSON value as String, assuming that this value represents a - * JSON string. If this is not the case, an exception is thrown. - * - * @return the string represented by this value - * @throws UnsupportedOperationException - * if this value is not a JSON string - */ - public String asString() { - throw new UnsupportedOperationException("Not a string: " + toString()); - } - - /** - * Returns this JSON value as a boolean value, assuming that - * this value is either true or false. If this is - * not the case, an exception is thrown. - * - * @return this value as boolean - * @throws UnsupportedOperationException - * if this value is neither true or - * false - */ - public Boolean asBoolean() { - throw new UnsupportedOperationException("Not a boolean: " + toString()); - } - - /** - * Writes the JSON representation of this value to the given writer in its - * minimal form, without any additional whitespace. - *

- * Writing performance can be improved by using a - * {@link java.io.BufferedWriter BufferedWriter}. - *

- * - * @param writer - * the writer to write this value to - * @throws IOException - * if an I/O error occurs in the writer - */ - public void writeTo(Writer writer) throws IOException { - writeTo(writer, WriterConfig.MINIMAL); - } - - /** - * Writes the JSON representation of this value to the given writer using - * the given formatting. - *

- * Writing performance can be improved by using a - * {@link java.io.BufferedWriter BufferedWriter}. - *

- * - * @param writer - * the writer to write this value to - * @param config - * a configuration that controls the formatting or - * null for the minimal form - * @throws IOException - * if an I/O error occurs in the writer - */ - public void writeTo(Writer writer, WriterConfig config) throws IOException { - if (writer == null) { - throw new NullPointerException("writer is null"); - } - if (config == null) { - throw new NullPointerException("config is null"); - } - WritingBuffer buffer = new WritingBuffer(writer, 128); - write(config.createWriter(buffer)); - buffer.flush(); - } - - /** - * Returns the JSON string for this value in its minimal form, without any - * additional whitespace. The result is guaranteed to be a valid input for - * the method {@link #readFrom(String)} and to create a value that is - * equal to this object. - * - * @return a JSON string that represents this value - */ - @Override - public String toString() { - return toString(WriterConfig.MINIMAL); - } - - /** - * Returns the JSON string for this value using the given formatting. - * - * @param config - * a configuration that controls the formatting or - * null for the minimal form - * @return a JSON string that represents this value - */ - public String toString(WriterConfig config) { - StringWriter writer = new StringWriter(); - try { - writeTo(writer, config); - } catch (IOException exception) { - // StringWriter does not throw IOExceptions - throw new RuntimeException(exception); - } - return writer.toString(); - } - - /** - * Indicates whether some other object is "equal to" this one according to - * the contract specified in {@link Object#equals(Object)}. - *

- * Two JsonValues are considered equal if and only if they represent the - * same JSON text. As a consequence, two given JsonObjects may be different - * even though they contain the same set of names with the same values, but - * in a different order. - *

- * - * @param object - * the reference object with which to compare - * @return true if this object is the same as the object argument; false - * otherwise - */ - @Override - public boolean equals(Object object) { - return super.equals(object); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - abstract void write(JSONWriter writer) throws IOException; - -} +/******************************************************************************* + * Copyright (c) 2013, 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; +import java.io.Serializable; +import java.io.StringWriter; +import java.io.Writer; + +/** + * Represents a JSON value. This can be a JSON object, an + * array, a number, a string + * , or one of the literals true, false, and + * null. + *

+ * The literals true, false, and + * null are represented by the constants {@link #TRUE}, + * {@link #FALSE}, and {@link #NULL}. + *

+ *

+ * JSON objects and arrays are represented by + * the subtypes {@link JSONObject} and {@link JSONArray}. Instances of these + * types can be created using the public constructors of these classes. + *

+ *

+ * Instances that represent JSON numbers, + * strings and boolean values can be created + * using the static factory methods {@link #valueOf(String)}, + * {@link #valueOf(long)}, {@link #valueOf(double)}, etc. + *

+ *

+ * In order to find out whether an instance of this class is of a certain type, + * the methods {@link #isObject()}, {@link #isArray()}, {@link #isString()}, + * {@link #isNumber()} etc. can be used. + *

+ *

+ * If the type of a JSON value is known, the methods {@link #asObject()}, + * {@link #asArray()}, {@link #asString()}, {@link #asInt()}, etc. can be used + * to get this value directly in the appropriate target type. + *

+ *

+ * This class is not supposed to be extended by clients. + *

+ */ +@SuppressWarnings("serial") // use default serial UID +public abstract class JSONValue implements Serializable { + + JSONValue() { + // prevent subclasses outside of this package + } + + /** + * Detects whether this value represents a JSON object. If this is the case, + * this value is an instance of {@link JSONObject}. + * + * @return true if this value is an instance of JsonObject + */ + public boolean isObject() { + return false; + } + + public boolean isBean() { + return false; + } + + /** + * Detects whether this value represents a JSON array. If this is the case, + * this value is an instance of {@link JSONArray}. + * + * @return true if this value is an instance of JsonArray + */ + public boolean isArray() { + return false; + } + + /** + * Detects whether this value represents a JSON number. + * + * @return true if this value represents a JSON number + */ + public boolean isNumber() { + return false; + } + + /** + * Detects whether this value represents a JSON string. + * + * @return true if this value represents a JSON string + */ + public boolean isString() { + return false; + } + + public boolean isLong(){ + return false; + } + + /** + * Detects whether this value represents a boolean value. + * + * @return true if this value represents either the JSON + * literal true or false + */ + public boolean isBoolean() { + return false; + } + + /** + * Detects whether this value represents the JSON literal true. + * + * @return true if this value represents the JSON literal + * true + */ + public boolean isTrue() { + return false; + } + + /** + * Detects whether this value represents the JSON literal false + * . + * + * @return true if this value represents the JSON literal + * false + */ + public boolean isFalse() { + return false; + } + + /** + * Detects whether this value represents the JSON literal null. + * + * @return true if this value represents the JSON literal + * null + */ + public boolean isNull() { + return false; + } + + /** + * Returns this JSON value as {@link JSONObject}, assuming that this value + * represents a JSON object. If this is not the case, an exception is + * thrown. + * + * @return a JSONObject for this value + * @throws UnsupportedOperationException + * if this value is not a JSON object + */ + public JSONObject asJSONObject() { + throw new UnsupportedOperationException("Not an JSONObject: " + toString()); + } + + /** + * Returns this JSON value as {@link JSONArray}, assuming that this value + * represents a JSON array. If this is not the case, an exception is thrown. + * + * @return a JSONArray for this value + * @throws UnsupportedOperationException + * if this value is not a JSON array + */ + public JSONArray asArray() { + throw new UnsupportedOperationException("Not an array: " + toString()); + } + + /** + * Returns this JSON value as an int value, assuming that this + * value represents a JSON number that can be interpreted as Java + * int. If this is not the case, an exception is thrown. + *

+ * To be interpreted as Java int, the JSON number must neither + * contain an exponent nor a fraction part. Moreover, the number must be in + * the Integer range. + *

+ * + * @return this value as int + * @throws UnsupportedOperationException + * if this value is not a JSON number + * @throws NumberFormatException + * if this JSON number can not be interpreted as + * int value + */ + public Integer asInt() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a long value, assuming that this + * value represents a JSON number that can be interpreted as Java + * long. If this is not the case, an exception is thrown. + *

+ * To be interpreted as Java long, the JSON number must neither + * contain an exponent nor a fraction part. Moreover, the number must be in + * the Long range. + *

+ * + * @return this value as long + * @throws UnsupportedOperationException + * if this value is not a JSON number + * @throws NumberFormatException + * if this JSON number can not be interpreted as + * long value + */ + public Long asLong() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a float value, assuming that this + * value represents a JSON number. If this is not the case, an exception is + * thrown. + *

+ * If the JSON number is out of the Float range, + * {@link Float#POSITIVE_INFINITY} or {@link Float#NEGATIVE_INFINITY} is + * returned. + *

+ * + * @return this value as float + * @throws UnsupportedOperationException + * if this value is not a JSON number + */ + public Float asFloat() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as a double value, assuming that + * this value represents a JSON number. If this is not the case, an + * exception is thrown. + *

+ * If the JSON number is out of the Double range, + * {@link Double#POSITIVE_INFINITY} or {@link Double#NEGATIVE_INFINITY} is + * returned. + *

+ * + * @return this value as double + * @throws UnsupportedOperationException + * if this value is not a JSON number + */ + public Double asDouble() { + throw new UnsupportedOperationException("Not a number: " + toString()); + } + + /** + * Returns this JSON value as String, assuming that this value represents a + * JSON string. If this is not the case, an exception is thrown. + * + * @return the string represented by this value + * @throws UnsupportedOperationException + * if this value is not a JSON string + */ + public String asString() { + throw new UnsupportedOperationException("Not a string: " + toString()); + } + + /** + * Returns this JSON value as a boolean value, assuming that + * this value is either true or false. If this is + * not the case, an exception is thrown. + * + * @return this value as boolean + * @throws UnsupportedOperationException + * if this value is neither true or + * false + */ + public Boolean asBoolean() { + throw new UnsupportedOperationException("Not a boolean: " + toString()); + } + + /** + * Writes the JSON representation of this value to the given writer in its + * minimal form, without any additional whitespace. + *

+ * Writing performance can be improved by using a + * {@link java.io.BufferedWriter BufferedWriter}. + *

+ * + * @param writer + * the writer to write this value to + * @throws IOException + * if an I/O error occurs in the writer + */ + public void writeTo(Writer writer) throws IOException { + writeTo(writer, WriterConfig.MINIMAL); + } + + /** + * Writes the JSON representation of this value to the given writer using + * the given formatting. + *

+ * Writing performance can be improved by using a + * {@link java.io.BufferedWriter BufferedWriter}. + *

+ * + * @param writer + * the writer to write this value to + * @param config + * a configuration that controls the formatting or + * null for the minimal form + * @throws IOException + * if an I/O error occurs in the writer + */ + public void writeTo(Writer writer, WriterConfig config) throws IOException { + if (writer == null) { + throw new NullPointerException("writer is null"); + } + if (config == null) { + throw new NullPointerException("config is null"); + } + WritingBuffer buffer = new WritingBuffer(writer, 128); + write(config.createWriter(buffer)); + buffer.flush(); + } + + /** + * Returns the JSON string for this value in its minimal form, without any + * additional whitespace. The result is guaranteed to be a valid input for + * the method {@link #readFrom(String)} and to create a value that is + * equal to this object. + * + * @return a JSON string that represents this value + */ + @Override + public String toString() { + return toString(WriterConfig.MINIMAL); + } + + /** + * Returns the JSON string for this value using the given formatting. + * + * @param config + * a configuration that controls the formatting or + * null for the minimal form + * @return a JSON string that represents this value + */ + public String toString(WriterConfig config) { + StringWriter writer = new StringWriter(); + try { + writeTo(writer, config); + } catch (IOException exception) { + // StringWriter does not throw IOExceptions + throw new RuntimeException(exception); + } + return writer.toString(); + } + + /** + * Indicates whether some other object is "equal to" this one according to + * the contract specified in {@link Object#equals(Object)}. + *

+ * Two JsonValues are considered equal if and only if they represent the + * same JSON text. As a consequence, two given JsonObjects may be different + * even though they contain the same set of names with the same values, but + * in a different order. + *

+ * + * @param object + * the reference object with which to compare + * @return true if this object is the same as the object argument; false + * otherwise + */ + @Override + public boolean equals(Object object) { + return super.equals(object); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + abstract void write(JSONWriter writer) throws IOException; + +} diff --git a/blade-kit/src/main/java/blade/kit/json/JSONWriter.java b/blade-kit/src/main/java/com/blade/kit/json/JSONWriter.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/json/JSONWriter.java rename to blade-kit/src/main/java/com/blade/kit/json/JSONWriter.java index 2e2b53e49..db8957e81 100644 --- a/blade-kit/src/main/java/blade/kit/json/JSONWriter.java +++ b/blade-kit/src/main/java/com/blade/kit/json/JSONWriter.java @@ -1,145 +1,145 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; - - -class JSONWriter { - - private static final int CONTROL_CHARACTERS_END = 0x001f; - - private static final char[] QUOT_CHARS = {'\\', '"'}; - private static final char[] BS_CHARS = {'\\', '\\'}; - private static final char[] LF_CHARS = {'\\', 'n'}; - private static final char[] CR_CHARS = {'\\', 'r'}; - private static final char[] TAB_CHARS = {'\\', 't'}; - // In JavaScript, U+2028 and U+2029 characters count as line endings and must be encoded. - // http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character - private static final char[] UNICODE_2028_CHARS = {'\\', 'u', '2', '0', '2', '8'}; - private static final char[] UNICODE_2029_CHARS = {'\\', 'u', '2', '0', '2', '9'}; - private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f'}; - - protected final Writer writer; - - JSONWriter(Writer writer) { - this.writer = writer; - } - - protected void writeLiteral(String value) throws IOException { - writer.write(value); - } - - protected void writeNumber(String string) throws IOException { - writer.write(string); - } - - protected void writeString(String string) throws IOException { - writer.write('"'); - writeJsonString(string); - writer.write('"'); - } - - protected void writeArrayOpen() throws IOException { - writer.write('['); - } - - protected void writeArrayClose() throws IOException { - writer.write(']'); - } - - protected void writeArraySeparator() throws IOException { - writer.write(','); - } - - protected void writeObjectOpen() throws IOException { - writer.write('{'); - } - - protected void writeObjectClose() throws IOException { - writer.write('}'); - } - - protected void writeMemberName(String name) throws IOException { - writer.write('"'); - writeJsonString(name); - writer.write('"'); - } - - protected void writeMemberSeparator() throws IOException { - writer.write(':'); - } - - protected void writeObjectSeparator() throws IOException { - writer.write(','); - } - - protected void writeJsonString(String string) throws IOException { - int length = string.length(); - int start = 0; - for (int index = 0; index < length; index++) { - char[] replacement = getReplacementChars(string.charAt(index)); - if (replacement != null) { - writer.write(string, start, index - start); - writer.write(replacement); - start = index + 1; - } - } - writer.write(string, start, length - start); - } - - private static char[] getReplacementChars(char ch) { - if (ch > '\\') { - if (ch < '\u2028' || ch > '\u2029') { - // The lower range contains 'a' .. 'z'. Only 2 checks required. - return null; - } - return ch == '\u2028' ? UNICODE_2028_CHARS : UNICODE_2029_CHARS; - } - if (ch == '\\') { - return BS_CHARS; - } - if (ch > '"') { - // This range contains '0' .. '9' and 'A' .. 'Z'. Need 3 checks to get here. - return null; - } - if (ch == '"') { - return QUOT_CHARS; - } - if (ch > CONTROL_CHARACTERS_END) { - return null; - } - if (ch == '\n') { - return LF_CHARS; - } - if (ch == '\r') { - return CR_CHARS; - } - if (ch == '\t') { - return TAB_CHARS; - } - return new char[] {'\\', 'u', '0', '0', HEX_DIGITS[ch >> 4 & 0x000f], HEX_DIGITS[ch & 0x000f]}; - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; +import java.io.Writer; + + +class JSONWriter { + + private static final int CONTROL_CHARACTERS_END = 0x001f; + + private static final char[] QUOT_CHARS = {'\\', '"'}; + private static final char[] BS_CHARS = {'\\', '\\'}; + private static final char[] LF_CHARS = {'\\', 'n'}; + private static final char[] CR_CHARS = {'\\', 'r'}; + private static final char[] TAB_CHARS = {'\\', 't'}; + // In JavaScript, U+2028 and U+2029 characters count as line endings and must be encoded. + // http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character + private static final char[] UNICODE_2028_CHARS = {'\\', 'u', '2', '0', '2', '8'}; + private static final char[] UNICODE_2029_CHARS = {'\\', 'u', '2', '0', '2', '9'}; + private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; + + protected final Writer writer; + + JSONWriter(Writer writer) { + this.writer = writer; + } + + protected void writeLiteral(String value) throws IOException { + writer.write(value); + } + + protected void writeNumber(String string) throws IOException { + writer.write(string); + } + + protected void writeString(String string) throws IOException { + writer.write('"'); + writeJsonString(string); + writer.write('"'); + } + + protected void writeArrayOpen() throws IOException { + writer.write('['); + } + + protected void writeArrayClose() throws IOException { + writer.write(']'); + } + + protected void writeArraySeparator() throws IOException { + writer.write(','); + } + + protected void writeObjectOpen() throws IOException { + writer.write('{'); + } + + protected void writeObjectClose() throws IOException { + writer.write('}'); + } + + protected void writeMemberName(String name) throws IOException { + writer.write('"'); + writeJsonString(name); + writer.write('"'); + } + + protected void writeMemberSeparator() throws IOException { + writer.write(':'); + } + + protected void writeObjectSeparator() throws IOException { + writer.write(','); + } + + protected void writeJsonString(String string) throws IOException { + int length = string.length(); + int start = 0; + for (int index = 0; index < length; index++) { + char[] replacement = getReplacementChars(string.charAt(index)); + if (replacement != null) { + writer.write(string, start, index - start); + writer.write(replacement); + start = index + 1; + } + } + writer.write(string, start, length - start); + } + + private static char[] getReplacementChars(char ch) { + if (ch > '\\') { + if (ch < '\u2028' || ch > '\u2029') { + // The lower range contains 'a' .. 'z'. Only 2 checks required. + return null; + } + return ch == '\u2028' ? UNICODE_2028_CHARS : UNICODE_2029_CHARS; + } + if (ch == '\\') { + return BS_CHARS; + } + if (ch > '"') { + // This range contains '0' .. '9' and 'A' .. 'Z'. Need 3 checks to get here. + return null; + } + if (ch == '"') { + return QUOT_CHARS; + } + if (ch > CONTROL_CHARACTERS_END) { + return null; + } + if (ch == '\n') { + return LF_CHARS; + } + if (ch == '\r') { + return CR_CHARS; + } + if (ch == '\t') { + return TAB_CHARS; + } + return new char[] {'\\', 'u', '0', '0', HEX_DIGITS[ch >> 4 & 0x000f], HEX_DIGITS[ch & 0x000f]}; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/Location.java b/blade-kit/src/main/java/com/blade/kit/json/Location.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/json/Location.java rename to blade-kit/src/main/java/com/blade/kit/json/Location.java index fb2cb62f6..70d930bc9 100644 --- a/blade-kit/src/main/java/blade/kit/json/Location.java +++ b/blade-kit/src/main/java/com/blade/kit/json/Location.java @@ -1,76 +1,76 @@ -/******************************************************************************* - * Copyright (c) 2016 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - - -/** - * An immutable object that represents a location in the parsed text. - */ -public class Location { - - /** - * The absolute character index, starting at 0. - */ - public final int offset; - - /** - * The line number, starting at 1. - */ - public final int line; - - /** - * The column number, starting at 1. - */ - public final int column; - - Location(int offset, int line, int column) { - this.offset = offset; - this.column = column; - this.line = line; - } - - @Override - public String toString() { - return line + ":" + column; - } - - @Override - public int hashCode() { - return offset; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Location other = (Location)obj; - return offset == other.offset && column == other.column && line == other.line; - } - +/******************************************************************************* + * Copyright (c) 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + + +/** + * An immutable object that represents a location in the parsed text. + */ +public class Location { + + /** + * The absolute character index, starting at 0. + */ + public final int offset; + + /** + * The line number, starting at 1. + */ + public final int line; + + /** + * The column number, starting at 1. + */ + public final int column; + + Location(int offset, int line, int column) { + this.offset = offset; + this.column = column; + this.line = line; + } + + @Override + public String toString() { + return line + ":" + column; + } + + @Override + public int hashCode() { + return offset; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Location other = (Location)obj; + return offset == other.offset && column == other.column && line == other.line; + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/json/ParseException.java b/blade-kit/src/main/java/com/blade/kit/json/ParseException.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/json/ParseException.java rename to blade-kit/src/main/java/com/blade/kit/json/ParseException.java index 045d686c6..72b8e9b89 100644 --- a/blade-kit/src/main/java/blade/kit/json/ParseException.java +++ b/blade-kit/src/main/java/com/blade/kit/json/ParseException.java @@ -1,81 +1,81 @@ -/******************************************************************************* - * Copyright (c) 2013, 2016 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -/** - * An unchecked exception to indicate that an input does not qualify as valid JSON. - */ -@SuppressWarnings("serial") // use default serial UID -public class ParseException extends RuntimeException { - - private final Location location; - - ParseException(String message, Location location) { - super(message + " at " + location); - this.location = location; - } - - /** - * Returns the location at which the error occurred. - * - * @return the error location - */ - public Location getLocation() { - return location; - } - - /** - * Returns the absolute character index at which the error occurred. The offset of the first - * character of a document is 0. - * - * @return the character offset at which the error occurred, will be >= 0 - * @deprecated Use {@link #getLocation()} instead - */ - @Deprecated - public int getOffset() { - return location.offset; - } - - /** - * Returns the line number in which the error occurred. The number of the first line is 1. - * - * @return the line in which the error occurred, will be >= 1 - * @deprecated Use {@link #getLocation()} instead - */ - @Deprecated - public int getLine() { - return location.line; - } - - /** - * Returns the column number at which the error occurred, i.e. the number of the character in its - * line. The number of the first character of a line is 1. - * - * @return the column in which the error occurred, will be >= 1 - * @deprecated Use {@link #getLocation()} instead - */ - @Deprecated - public int getColumn() { - return location.column; - } - -} +/******************************************************************************* + * Copyright (c) 2013, 2016 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +/** + * An unchecked exception to indicate that an input does not qualify as valid JSON. + */ +@SuppressWarnings("serial") // use default serial UID +public class ParseException extends RuntimeException { + + private final Location location; + + ParseException(String message, Location location) { + super(message + " at " + location); + this.location = location; + } + + /** + * Returns the location at which the error occurred. + * + * @return the error location + */ + public Location getLocation() { + return location; + } + + /** + * Returns the absolute character index at which the error occurred. The offset of the first + * character of a document is 0. + * + * @return the character offset at which the error occurred, will be >= 0 + * @deprecated Use {@link #getLocation()} instead + */ + @Deprecated + public int getOffset() { + return location.offset; + } + + /** + * Returns the line number in which the error occurred. The number of the first line is 1. + * + * @return the line in which the error occurred, will be >= 1 + * @deprecated Use {@link #getLocation()} instead + */ + @Deprecated + public int getLine() { + return location.line; + } + + /** + * Returns the column number at which the error occurred, i.e. the number of the character in its + * line. The number of the first character of a line is 1. + * + * @return the column in which the error occurred, will be >= 1 + * @deprecated Use {@link #getLocation()} instead + */ + @Deprecated + public int getColumn() { + return location.column; + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java b/blade-kit/src/main/java/com/blade/kit/json/PrettyPrint.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/json/PrettyPrint.java rename to blade-kit/src/main/java/com/blade/kit/json/PrettyPrint.java index a14a10328..dc2f391e1 100644 --- a/blade-kit/src/main/java/blade/kit/json/PrettyPrint.java +++ b/blade-kit/src/main/java/com/blade/kit/json/PrettyPrint.java @@ -1,157 +1,157 @@ -/******************************************************************************* - * Copyright (c) 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; -import java.util.Arrays; - - -/** - * Enables human readable JSON output by inserting whitespace between values.after commas and - * colons. Example: - * - *
- * jsonValue.writeTo(writer, PrettyPrint.singleLine());
- * 
- */ -public class PrettyPrint extends WriterConfig { - - private final char[] indentChars; - - protected PrettyPrint(char[] indentChars) { - this.indentChars = indentChars; - } - - /** - * Print every value on a separate line. Use tabs (\t) for indentation. - * - * @return A PrettyPrint instance for wrapped mode with tab indentation - */ - public static PrettyPrint singleLine() { - return new PrettyPrint(null); - } - - /** - * Print every value on a separate line. Use the given number of spaces for indentation. - * - * @param number - * the number of spaces to use - * @return A PrettyPrint instance for wrapped mode with spaces indentation - */ - public static PrettyPrint indentWithSpaces(int number) { - if (number < 0) { - throw new IllegalArgumentException("number is negative"); - } - char[] chars = new char[number]; - Arrays.fill(chars, ' '); - return new PrettyPrint(chars); - } - - /** - * Do not break lines, but still insert whitespace between values. - * - * @return A PrettyPrint instance for single-line mode - */ - public static PrettyPrint indentWithTabs() { - return new PrettyPrint(new char[] {'\t'}); - } - - @Override - protected JSONWriter createWriter(Writer writer) { - return new PrettyPrintWriter(writer, indentChars); - } - - private static class PrettyPrintWriter extends JSONWriter { - - private final char[] indentChars; - private int indent; - - private PrettyPrintWriter(Writer writer, char[] indentChars) { - super(writer); - this.indentChars = indentChars; - } - - @Override - protected void writeArrayOpen() throws IOException { - indent++; - writer.write('['); - writeNewLine(); - } - - @Override - protected void writeArrayClose() throws IOException { - indent--; - writeNewLine(); - writer.write(']'); - } - - @Override - protected void writeArraySeparator() throws IOException { - writer.write(','); - if (!writeNewLine()) { - writer.write(' '); - } - } - - @Override - protected void writeObjectOpen() throws IOException { - indent++; - writer.write('{'); - writeNewLine(); - } - - @Override - protected void writeObjectClose() throws IOException { - indent--; - writeNewLine(); - writer.write('}'); - } - - @Override - protected void writeMemberSeparator() throws IOException { - writer.write(':'); - writer.write(' '); - } - - @Override - protected void writeObjectSeparator() throws IOException { - writer.write(','); - if (!writeNewLine()) { - writer.write(' '); - } - } - - private boolean writeNewLine() throws IOException { - if (indentChars == null) { - return false; - } - writer.write('\n'); - for (int i = 0; i < indent; i++) { - writer.write(indentChars); - } - return true; - } - - } - -} +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; +import java.io.Writer; +import java.util.Arrays; + + +/** + * Enables human readable JSON output by inserting whitespace between values.after commas and + * colons. Example: + * + *
+ * jsonValue.writeTo(writer, PrettyPrint.singleLine());
+ * 
+ */ +public class PrettyPrint extends WriterConfig { + + private final char[] indentChars; + + protected PrettyPrint(char[] indentChars) { + this.indentChars = indentChars; + } + + /** + * Print every value on a separate line. Use tabs (\t) for indentation. + * + * @return A PrettyPrint instance for wrapped mode with tab indentation + */ + public static PrettyPrint singleLine() { + return new PrettyPrint(null); + } + + /** + * Print every value on a separate line. Use the given number of spaces for indentation. + * + * @param number + * the number of spaces to use + * @return A PrettyPrint instance for wrapped mode with spaces indentation + */ + public static PrettyPrint indentWithSpaces(int number) { + if (number < 0) { + throw new IllegalArgumentException("number is negative"); + } + char[] chars = new char[number]; + Arrays.fill(chars, ' '); + return new PrettyPrint(chars); + } + + /** + * Do not break lines, but still insert whitespace between values. + * + * @return A PrettyPrint instance for single-line mode + */ + public static PrettyPrint indentWithTabs() { + return new PrettyPrint(new char[] {'\t'}); + } + + @Override + protected JSONWriter createWriter(Writer writer) { + return new PrettyPrintWriter(writer, indentChars); + } + + private static class PrettyPrintWriter extends JSONWriter { + + private final char[] indentChars; + private int indent; + + private PrettyPrintWriter(Writer writer, char[] indentChars) { + super(writer); + this.indentChars = indentChars; + } + + @Override + protected void writeArrayOpen() throws IOException { + indent++; + writer.write('['); + writeNewLine(); + } + + @Override + protected void writeArrayClose() throws IOException { + indent--; + writeNewLine(); + writer.write(']'); + } + + @Override + protected void writeArraySeparator() throws IOException { + writer.write(','); + if (!writeNewLine()) { + writer.write(' '); + } + } + + @Override + protected void writeObjectOpen() throws IOException { + indent++; + writer.write('{'); + writeNewLine(); + } + + @Override + protected void writeObjectClose() throws IOException { + indent--; + writeNewLine(); + writer.write('}'); + } + + @Override + protected void writeMemberSeparator() throws IOException { + writer.write(':'); + writer.write(' '); + } + + @Override + protected void writeObjectSeparator() throws IOException { + writer.write(','); + if (!writeNewLine()) { + writer.write(' '); + } + } + + private boolean writeNewLine() throws IOException { + if (indentChars == null) { + return false; + } + writer.write('\n'); + for (int i = 0; i < indent; i++) { + writer.write(indentChars); + } + return true; + } + + } + +} diff --git a/blade-kit/src/main/java/blade/kit/json/WriterConfig.java b/blade-kit/src/main/java/com/blade/kit/json/WriterConfig.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/json/WriterConfig.java rename to blade-kit/src/main/java/com/blade/kit/json/WriterConfig.java index 6573c80d2..4f3823d29 100644 --- a/blade-kit/src/main/java/blade/kit/json/WriterConfig.java +++ b/blade-kit/src/main/java/com/blade/kit/json/WriterConfig.java @@ -1,50 +1,50 @@ -/******************************************************************************* - * Copyright (c) 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.Writer; - - -/** - * Controls the formatting of the JSON output. Use one of the available constants. - */ -public abstract class WriterConfig { - - /** - * Write JSON in its minimal form, without any additional whitespace. This is the default. - */ - public static WriterConfig MINIMAL = new WriterConfig() { - @Override - JSONWriter createWriter(Writer writer) { - return new JSONWriter(writer); - } - }; - - /** - * Write JSON in pretty-print, with each value on a separate line and an indentation of two - * spaces. - */ - public static WriterConfig PRETTY_PRINT = PrettyPrint.indentWithSpaces(2); - - abstract JSONWriter createWriter(Writer writer); - -} +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.Writer; + + +/** + * Controls the formatting of the JSON output. Use one of the available constants. + */ +public abstract class WriterConfig { + + /** + * Write JSON in its minimal form, without any additional whitespace. This is the default. + */ + public static WriterConfig MINIMAL = new WriterConfig() { + @Override + JSONWriter createWriter(Writer writer) { + return new JSONWriter(writer); + } + }; + + /** + * Write JSON in pretty-print, with each value on a separate line and an indentation of two + * spaces. + */ + public static WriterConfig PRETTY_PRINT = PrettyPrint.indentWithSpaces(2); + + abstract JSONWriter createWriter(Writer writer); + +} diff --git a/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java b/blade-kit/src/main/java/com/blade/kit/json/WritingBuffer.java similarity index 96% rename from blade-kit/src/main/java/blade/kit/json/WritingBuffer.java rename to blade-kit/src/main/java/com/blade/kit/json/WritingBuffer.java index 58a779b0c..257a394fa 100644 --- a/blade-kit/src/main/java/blade/kit/json/WritingBuffer.java +++ b/blade-kit/src/main/java/com/blade/kit/json/WritingBuffer.java @@ -1,99 +1,99 @@ -/******************************************************************************* - * Copyright (c) 2015 EclipseSource. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ -package blade.kit.json; - -import java.io.IOException; -import java.io.Writer; - - -/** - * A lightweight writing buffer to reduce the amount of write operations to be performed on the - * underlying writer. This implementation is not thread-safe. It deliberately deviates from the - * contract of Writer. In particular, it does not flush or close the wrapped writer nor does it - * ensure that the wrapped writer is open. - */ -class WritingBuffer extends Writer { - - private final Writer writer; - private final char[] buffer; - private int fill = 0; - - WritingBuffer(Writer writer) { - this(writer, 16); - } - - WritingBuffer(Writer writer, int bufferSize) { - this.writer = writer; - buffer = new char[bufferSize]; - } - - @Override - public void write(int c) throws IOException { - if (fill > buffer.length - 1) { - flush(); - } - buffer[fill++] = (char)c; - } - - @Override - public void write(char[] cbuf, int off, int len) throws IOException { - if (fill > buffer.length - len) { - flush(); - if (len > buffer.length) { - writer.write(cbuf, off, len); - return; - } - } - System.arraycopy(cbuf, off, buffer, fill, len); - fill += len; - } - - @Override - public void write(String str, int off, int len) throws IOException { - if (fill > buffer.length - len) { - flush(); - if (len > buffer.length) { - writer.write(str, off, len); - return; - } - } - str.getChars(off, off + len, buffer, fill); - fill += len; - } - - /** - * Flushes the internal buffer but does not flush the wrapped writer. - */ - @Override - public void flush() throws IOException { - writer.write(buffer, 0, fill); - fill = 0; - } - - /** - * Does not close or flush the wrapped writer. - */ - @Override - public void close() throws IOException { - } - -} +/******************************************************************************* + * Copyright (c) 2015 EclipseSource. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ******************************************************************************/ +package com.blade.kit.json; + +import java.io.IOException; +import java.io.Writer; + + +/** + * A lightweight writing buffer to reduce the amount of write operations to be performed on the + * underlying writer. This implementation is not thread-safe. It deliberately deviates from the + * contract of Writer. In particular, it does not flush or close the wrapped writer nor does it + * ensure that the wrapped writer is open. + */ +class WritingBuffer extends Writer { + + private final Writer writer; + private final char[] buffer; + private int fill = 0; + + WritingBuffer(Writer writer) { + this(writer, 16); + } + + WritingBuffer(Writer writer, int bufferSize) { + this.writer = writer; + buffer = new char[bufferSize]; + } + + @Override + public void write(int c) throws IOException { + if (fill > buffer.length - 1) { + flush(); + } + buffer[fill++] = (char)c; + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + if (fill > buffer.length - len) { + flush(); + if (len > buffer.length) { + writer.write(cbuf, off, len); + return; + } + } + System.arraycopy(cbuf, off, buffer, fill, len); + fill += len; + } + + @Override + public void write(String str, int off, int len) throws IOException { + if (fill > buffer.length - len) { + flush(); + if (len > buffer.length) { + writer.write(str, off, len); + return; + } + } + str.getChars(off, off + len, buffer, fill); + fill += len; + } + + /** + * Flushes the internal buffer but does not flush the wrapped writer. + */ + @Override + public void flush() throws IOException { + writer.write(buffer, 0, fill); + fill = 0; + } + + /** + * Does not close or flush the wrapped writer. + */ + @Override + public void close() throws IOException { + } + +} diff --git a/blade-kit/src/main/java/blade/kit/package-info.java b/blade-kit/src/main/java/com/blade/kit/package-info.java similarity index 60% rename from blade-kit/src/main/java/blade/kit/package-info.java rename to blade-kit/src/main/java/com/blade/kit/package-info.java index 0bf487f17..f8e54277d 100644 --- a/blade-kit/src/main/java/blade/kit/package-info.java +++ b/blade-kit/src/main/java/com/blade/kit/package-info.java @@ -1,4 +1,4 @@ -/** - * 最常用的工具类集合 - */ -package blade.kit; \ No newline at end of file +/** + * 最常用的工具类集合 + */ +package com.blade.kit; \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/reflect/ClassDefine.java b/blade-kit/src/main/java/com/blade/kit/reflect/ClassDefine.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/reflect/ClassDefine.java rename to blade-kit/src/main/java/com/blade/kit/reflect/ClassDefine.java index e35ccc33c..fd9d63424 100644 --- a/blade-kit/src/main/java/blade/kit/reflect/ClassDefine.java +++ b/blade-kit/src/main/java/com/blade/kit/reflect/ClassDefine.java @@ -1,4 +1,4 @@ -package blade.kit.reflect; +package com.blade.kit.reflect; import java.lang.annotation.Annotation; import java.lang.reflect.Field; diff --git a/blade-kit/src/main/java/blade/kit/reflect/ConvertKit.java b/blade-kit/src/main/java/com/blade/kit/reflect/ConvertKit.java similarity index 92% rename from blade-kit/src/main/java/blade/kit/reflect/ConvertKit.java rename to blade-kit/src/main/java/com/blade/kit/reflect/ConvertKit.java index 07f614531..977b637d5 100644 --- a/blade-kit/src/main/java/blade/kit/reflect/ConvertKit.java +++ b/blade-kit/src/main/java/com/blade/kit/reflect/ConvertKit.java @@ -1,4 +1,4 @@ -package blade.kit.reflect; +package com.blade.kit.reflect; import java.util.HashSet; import java.util.Set; diff --git a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java b/blade-kit/src/main/java/com/blade/kit/reflect/ReflectKit.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java rename to blade-kit/src/main/java/com/blade/kit/reflect/ReflectKit.java index 280ce38d6..7c3ef12e6 100644 --- a/blade-kit/src/main/java/blade/kit/reflect/ReflectKit.java +++ b/blade-kit/src/main/java/com/blade/kit/reflect/ReflectKit.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit.reflect; +package com.blade.kit.reflect; import java.io.File; import java.io.IOException; @@ -31,12 +31,13 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; -import blade.kit.Emptys; -import blade.kit.ExceptionKit; -import blade.kit.StringKit; -import blade.kit.SystemKit; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Emptys; +import com.blade.kit.ExceptionKit; +import com.blade.kit.StringKit; +import com.blade.kit.SystemKit; /** * 有关 Reflection处理的工具类。 diff --git a/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java b/blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java similarity index 95% rename from blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java rename to blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java index 2185c1324..0f6b3750d 100644 --- a/blade-kit/src/main/java/blade/kit/resource/AbstractClassReader.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit.resource; +package com.blade.kit.resource; import java.io.File; import java.io.FileFilter; @@ -24,10 +24,11 @@ import java.util.Enumeration; import java.util.Set; -import blade.kit.Assert; -import blade.kit.CollectionKit; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.kit.CollectionKit; /** * 抽象类读取器 diff --git a/blade-kit/src/main/java/blade/kit/resource/ClassPathClassReader.java b/blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java similarity index 93% rename from blade-kit/src/main/java/blade/kit/resource/ClassPathClassReader.java rename to blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java index 54cc8ad18..144398ed4 100644 --- a/blade-kit/src/main/java/blade/kit/resource/ClassPathClassReader.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit.resource; +package com.blade.kit.resource; /** * 根据classpath加载类 diff --git a/blade-kit/src/main/java/blade/kit/resource/ClassReader.java b/blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java similarity index 94% rename from blade-kit/src/main/java/blade/kit/resource/ClassReader.java rename to blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java index b936fb3c5..ca5ff8ead 100644 --- a/blade-kit/src/main/java/blade/kit/resource/ClassReader.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit.resource; +package com.blade.kit.resource; import java.lang.annotation.Annotation; import java.util.Set; diff --git a/blade-kit/src/main/java/blade/kit/resource/DynamicClassReader.java b/blade-kit/src/main/java/com/blade/kit/resource/DynamicClassReader.java similarity index 93% rename from blade-kit/src/main/java/blade/kit/resource/DynamicClassReader.java rename to blade-kit/src/main/java/com/blade/kit/resource/DynamicClassReader.java index 36acca3ca..ae6389875 100644 --- a/blade-kit/src/main/java/blade/kit/resource/DynamicClassReader.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/DynamicClassReader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit.resource; +package com.blade.kit.resource; /** * 动态根据环境获取ClassReader diff --git a/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java b/blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java similarity index 94% rename from blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java rename to blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java index 5f3318478..dc62dd2b4 100644 --- a/blade-kit/src/main/java/blade/kit/resource/JarReaderImpl.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit.resource; +package com.blade.kit.resource; import java.io.IOException; import java.lang.annotation.Annotation; @@ -24,11 +24,12 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; -import blade.kit.Assert; -import blade.kit.CollectionKit; -import blade.kit.exception.ClassReaderException; -import blade.kit.logging.Logger; -import blade.kit.logging.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.kit.CollectionKit; +import com.blade.kit.exception.ClassReaderException; /** * 根据jar文件读取类 diff --git a/blade-kit/src/main/java/com/blade/kit/resource/package-info.java b/blade-kit/src/main/java/com/blade/kit/resource/package-info.java new file mode 100644 index 000000000..2a268b644 --- /dev/null +++ b/blade-kit/src/main/java/com/blade/kit/resource/package-info.java @@ -0,0 +1,4 @@ +/** + * 资源搜索包 + */ +package com.blade.kit.resource; \ No newline at end of file diff --git a/blade-kit/src/main/java/blade/kit/text/HTMLFilter.java b/blade-kit/src/main/java/com/blade/kit/text/HTMLFilter.java similarity index 97% rename from blade-kit/src/main/java/blade/kit/text/HTMLFilter.java rename to blade-kit/src/main/java/com/blade/kit/text/HTMLFilter.java index 2b437a289..3cb5dccd4 100644 --- a/blade-kit/src/main/java/blade/kit/text/HTMLFilter.java +++ b/blade-kit/src/main/java/com/blade/kit/text/HTMLFilter.java @@ -1,4 +1,4 @@ -package blade.kit.text; +package com.blade.kit.text; import java.util.ArrayList; import java.util.Collections; diff --git a/blade-kit/src/main/java/blade/kit/timw/TimwCounter.java b/blade-kit/src/main/java/com/blade/kit/timw/TimwCounter.java similarity index 94% rename from blade-kit/src/main/java/blade/kit/timw/TimwCounter.java rename to blade-kit/src/main/java/com/blade/kit/timw/TimwCounter.java index 68cd13cea..89b9a7b63 100644 --- a/blade-kit/src/main/java/blade/kit/timw/TimwCounter.java +++ b/blade-kit/src/main/java/com/blade/kit/timw/TimwCounter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit.timw; +package com.blade.kit.timw; /** * 计数器 diff --git a/blade-kit/src/main/java/blade/kit/timw/TimwManager.java b/blade-kit/src/main/java/com/blade/kit/timw/TimwManager.java similarity index 93% rename from blade-kit/src/main/java/blade/kit/timw/TimwManager.java rename to blade-kit/src/main/java/com/blade/kit/timw/TimwManager.java index 6ba736297..822233e8c 100644 --- a/blade-kit/src/main/java/blade/kit/timw/TimwManager.java +++ b/blade-kit/src/main/java/com/blade/kit/timw/TimwManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit.timw; +package com.blade.kit.timw; /** * 计时管理器 diff --git a/blade-kit/src/main/java/blade/kit/timw/TimwMonitor.java b/blade-kit/src/main/java/com/blade/kit/timw/TimwMonitor.java similarity index 91% rename from blade-kit/src/main/java/blade/kit/timw/TimwMonitor.java rename to blade-kit/src/main/java/com/blade/kit/timw/TimwMonitor.java index 945179b07..2c1fc370b 100644 --- a/blade-kit/src/main/java/blade/kit/timw/TimwMonitor.java +++ b/blade-kit/src/main/java/com/blade/kit/timw/TimwMonitor.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package blade.kit.timw; +package com.blade.kit.timw; -import blade.kit.TimwKit; +import com.blade.kit.TimwKit; /** * 计时器 diff --git a/blade-kit/src/main/java/com/blade/kit/timw/package-info.java b/blade-kit/src/main/java/com/blade/kit/timw/package-info.java new file mode 100644 index 000000000..e89c0c7a6 --- /dev/null +++ b/blade-kit/src/main/java/com/blade/kit/timw/package-info.java @@ -0,0 +1,4 @@ +/** + * 计时器包 + */ +package com.blade.kit.timw; \ No newline at end of file diff --git a/blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java b/blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java index d9a3dc03e..974cfbb40 100644 --- a/blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java +++ b/blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java @@ -2,7 +2,7 @@ import java.io.File; -import blade.kit.http.HttpRequest; +import com.blade.kit.http.HttpRequest; public class HttpRequestTest { diff --git a/blade-kit/src/test/java/com/blade/kit/JSONTest.java b/blade-kit/src/test/java/com/blade/kit/JSONTest.java index 84972fdd8..de991dec7 100644 --- a/blade-kit/src/test/java/com/blade/kit/JSONTest.java +++ b/blade-kit/src/test/java/com/blade/kit/JSONTest.java @@ -1,59 +1,59 @@ -package com.blade.kit; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import blade.kit.json.JSON; -import blade.kit.json.JSONArray; -import blade.kit.json.JSONHelper; -import blade.kit.json.JSONKit; -import blade.kit.json.JSONObject; -import blade.kit.json.JSONValue; - -public class JSONTest { - - public static void main(String[] args) { - //[{"text": "首页","href": "/"},{"text": "博客","href": "blog"},{"text": "关于","href": "about"},{"text": "联系","href": "contact"}] - String json = "[{\"text\": \"博客\",\"href\": \"blog\"}]"; - - // 下面构造两个map、一个list和一个Employee对象 - Map map1 = new HashMap(); - map1.put("name", "Alexia"); - map1.put("sex", "female"); - map1.put("age", "23"); - - List> list = new ArrayList>(); - Map map = new HashMap(); - - map.put("abc", "123456"); - map.put("def", "hmm"); - list.add(map); - - String string = JSONKit.toJSONString(list); - System.out.println(string); - - List list2 = JSON.parse(json).asArray().values(); - System.out.println(list2); - - JSONObject obj1 = new JSONObject(); - obj1.put("name", "jack"); - - System.out.println(obj1); - - JSONArray obj2 = new JSONArray(); - obj2.add("123"); - - System.out.println(obj2); - - User u1 = new User(); - u1.setAge(22); -// u1.setName("rose"); - - System.out.println(JSONHelper.toJSONValue(u1).toString()); - -// System.out.println(JSONKit.toJSONString(u1)); - } - -} +package com.blade.kit; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.blade.kit.json.JSON; +import com.blade.kit.json.JSONArray; +import com.blade.kit.json.JSONHelper; +import com.blade.kit.json.JSONKit; +import com.blade.kit.json.JSONObject; +import com.blade.kit.json.JSONValue; + +public class JSONTest { + + public static void main(String[] args) { + //[{"text": "首页","href": "/"},{"text": "博客","href": "blog"},{"text": "关于","href": "about"},{"text": "联系","href": "contact"}] + String json = "[{\"text\": \"博客\",\"href\": \"blog\"}]"; + + // 下面构造两个map、一个list和一个Employee对象 + Map map1 = new HashMap(); + map1.put("name", "Alexia"); + map1.put("sex", "female"); + map1.put("age", "23"); + + List> list = new ArrayList>(); + Map map = new HashMap(); + + map.put("abc", "123456"); + map.put("def", "hmm"); + list.add(map); + + String string = JSONKit.toJSONString(list); + System.out.println(string); + + List list2 = JSON.parse(json).asArray().values(); + System.out.println(list2); + + JSONObject obj1 = new JSONObject(); + obj1.put("name", "jack"); + + System.out.println(obj1); + + JSONArray obj2 = new JSONArray(); + obj2.add("123"); + + System.out.println(obj2); + + User u1 = new User(); + u1.setAge(22); +// u1.setName("rose"); + + System.out.println(JSONHelper.toJSONValue(u1).toString()); + +// System.out.println(JSONKit.toJSONString(u1)); + } + +} diff --git a/blade-kit/src/test/java/com/blade/kit/StringTest.java b/blade-kit/src/test/java/com/blade/kit/StringTest.java index 3b08574f5..f86998ce3 100644 --- a/blade-kit/src/test/java/com/blade/kit/StringTest.java +++ b/blade-kit/src/test/java/com/blade/kit/StringTest.java @@ -4,7 +4,7 @@ import java.util.Arrays; import java.util.List; -import blade.kit.StringKit; +import com.blade.kit.StringKit; public class StringTest { diff --git a/blade-kit/src/test/java/com/blade/kit/TaskTest.java b/blade-kit/src/test/java/com/blade/kit/TaskTest.java index 5fd0f02b0..56b8d192a 100644 --- a/blade-kit/src/test/java/com/blade/kit/TaskTest.java +++ b/blade-kit/src/test/java/com/blade/kit/TaskTest.java @@ -3,7 +3,7 @@ import java.util.Date; import java.util.concurrent.TimeUnit; -import blade.kit.TaskKit; +import com.blade.kit.TaskKit; public class TaskTest { diff --git a/pom.xml b/pom.xml index ce2c89fdd..2fe65f3d3 100644 --- a/pom.xml +++ b/pom.xml @@ -3,28 +3,32 @@ 4.0.0 com.bladejava - blade-root + blade 1.0 pom - blade-root + blade https://github.com/biezhi/blade 1.6 1.6 UTF-8 + 1.6.4 + 1.3.1 + 0.0.2 3.0.1 - 1.6.3 4.12 - 1.7.16 + 1.7.21 + 1.7.21 blade-kit blade-core blade-embed-jetty - + blade-auth + @@ -41,18 +45,26 @@ + + + org.slf4j + slf4j-api + ${slf4j-api.version} + + + + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} + + junit junit ${junit.version} test - - org.slf4j - slf4j-api - ${slf4j-api.version} - provided - + From 97fcc2a4369e78cbc1cd6581f72210a78aaca3db Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 26 Aug 2016 17:46:33 +0800 Subject: [PATCH 459/545] fix Bootstrap class is null --- blade-core/src/main/java/com/blade/Blade.java | 4 +++- .../java/com/blade/view/handle/RouteViewHandler.java | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 90bb0388f..67f2d5e88 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -416,7 +416,9 @@ public Blade app(Bootstrap bootstrap){ public Blade app(Class bootstrap){ Assert.notNull(bootstrap); try { - ioc.addBean(Bootstrap.class.getName(), ReflectKit.newInstance(bootstrap)); + Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); + ioc.addBean(Bootstrap.class.getName(), object); + this.bootstrap = object; } catch (Exception e) { e.printStackTrace(); } diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index f595d660f..40ac68ba5 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -10,6 +10,7 @@ import com.blade.annotation.PathVariable; import com.blade.annotation.RequestParam; import com.blade.ioc.Ioc; +import com.blade.kit.StringKit; import com.blade.kit.reflect.ReflectKit; import com.blade.route.Route; import com.blade.view.ModelAndView; @@ -46,28 +47,28 @@ private Object getRequestParam(Class parameterType, String val, String defaul Object result = null; if(parameterType.equals(String.class)){ String value = request.query(val); - if(null == value){ + if(null == value && null != defaultValue){ result = defaultValue; } else { result = value; } } else if(parameterType.equals(Integer.class) || parameterType.equals(int.class)){ Integer value = request.queryAsInt(val); - if(null == value){ + if(null == value && StringKit.isNotBlank(defaultValue)){ result = Integer.valueOf(defaultValue); } else { result = value; } } else if(parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)){ Boolean value = request.queryAsBool(val); - if(null == value){ + if(null == value && StringKit.isNotBlank(defaultValue)){ result = Boolean.valueOf(defaultValue); } else { result = value; } } else if(parameterType.equals(Long.class) || parameterType.equals(long.class)){ Long value = request.queryAsLong(val); - if(null == value){ + if(null == value && StringKit.isNotBlank(defaultValue)){ result = Long.valueOf(defaultValue); } else { result = value; From 4d91027f9a931752cbf7e380d7b1ce0f52543093 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 29 Aug 2016 18:49:17 +0800 Subject: [PATCH 460/545] fix some bug and optimized code --- blade-core/src/main/java/com/blade/Blade.java | 862 ++++++++++-------- .../src/main/java/com/blade/Bootstrap.java | 78 +- blade-core/src/main/java/com/blade/Const.java | 3 +- .../com/blade/annotation/RequestParam.java | 4 +- .../main/java/com/blade/annotation/Route.java | 2 +- .../ApplicationConfig.java} | 156 ++-- .../java/com/blade/config/BaseConfig.java | 7 + .../java/com/blade/config/ConfigLoader.java | 90 ++ ...ontext.java => ApplicationWebContext.java} | 16 +- .../com/blade/exception/BladeException.java | 27 + .../com/blade/exception/ConfigException.java | 27 + .../blade/exception/NotFoundException.java | 27 + .../java/com/blade/ioc/IocApplication.java | 6 +- .../main/java/com/blade/ioc/SimpleIoc.java | 4 +- .../java/com/blade/route/RouteBuilder.java | 20 +- .../loader/ClassPathControllerLoader.java | 170 ++-- .../blade/view/handle/RouteViewHandler.java | 216 +++-- .../com/blade/view/template/JspEngine.java | 6 +- .../main/java/com/blade/web/DispatchKit.java | 9 +- .../java/com/blade/web/DispatcherHandler.java | 19 +- .../java/com/blade/web/DispatcherServlet.java | 29 +- .../web/http/wrapper/ServletResponse.java | 6 +- .../com/blade/embedd/EmbedJettyServer.java | 10 +- .../main/java/com/blade/kit/Environment.java | 4 + pom.xml | 4 +- 25 files changed, 1047 insertions(+), 755 deletions(-) rename blade-core/src/main/java/com/blade/{context/BladeConfig.java => config/ApplicationConfig.java} (54%) create mode 100644 blade-core/src/main/java/com/blade/config/BaseConfig.java create mode 100644 blade-core/src/main/java/com/blade/config/ConfigLoader.java rename blade-core/src/main/java/com/blade/context/{BladeWebContext.java => ApplicationWebContext.java} (77%) create mode 100644 blade-core/src/main/java/com/blade/exception/BladeException.java create mode 100644 blade-core/src/main/java/com/blade/exception/ConfigException.java create mode 100644 blade-core/src/main/java/com/blade/exception/NotFoundException.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 67f2d5e88..852980f58 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -21,8 +21,11 @@ import java.util.List; import java.util.Set; -import com.blade.context.BladeConfig; +import com.blade.config.ApplicationConfig; +import com.blade.config.BaseConfig; +import com.blade.config.ConfigLoader; import com.blade.embedd.EmbedServer; +import com.blade.interceptor.Interceptor; import com.blade.ioc.Ioc; import com.blade.ioc.SimpleIoc; import com.blade.kit.Assert; @@ -30,6 +33,7 @@ import com.blade.kit.reflect.ReflectKit; import com.blade.plugin.Plugin; import com.blade.route.Route; +import com.blade.route.RouteBuilder; import com.blade.route.RouteException; import com.blade.route.RouteGroup; import com.blade.route.RouteHandler; @@ -42,308 +46,386 @@ /** * Blade Core Class * - * @author biezhi - * @since 1.0 + * @author biezhi + * @since 1.0 */ public class Blade { - - // Blade initialize - private boolean isInit = false; - - // Blade initialize config class - private Bootstrap bootstrap = null; - - // Global configuration Object - private BladeConfig bladeConfig = null; - - // IOC Container - private Ioc ioc = null; - - // default render is jspRender - private TemplateEngine templateEngine = null; - - // routes - private Routers routers = null; - - // jetty start port - private int port = Const.DEFAULT_PORT; - - // default context path - private String contextPath = Const.DEFAULT_CONTEXTPATH; - - // enableServer - private boolean enableServer = false; - - private Set> plugins; - + + // blade initialize + private boolean isInit = false; + + // blade bootstrap config class + private Bootstrap bootstrap = null; + + // global configuration Object + private ApplicationConfig applicationConfig = null; + + // ioc container + private Ioc ioc = new SimpleIoc(); + + // default render is jspRender + private TemplateEngine templateEngine = null; + + // routes + private Routers routers = new Routers(); + + // routebuilder + private RouteBuilder routeBuilder; + + // jetty start port + private int port = Const.DEFAULT_PORT; + + // default context path + private String contextPath = Const.DEFAULT_CONTEXTPATH; + + // enableServer + private boolean enableServer = false; + + // plugins + private Set> plugins; + + // global environment + private Environment environment; + + // config loader + private ConfigLoader configLoader; + private Blade() { - this.bladeConfig = new BladeConfig(); - this.ioc = new SimpleIoc(); - this.routers = new Routers(); + this.environment = new Environment(); + this.applicationConfig = new ApplicationConfig(); this.templateEngine = new JspEngine(); this.plugins = new HashSet>(); + this.routeBuilder = new RouteBuilder(this.routers); + this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); } - + static final class BladeHolder { private static final Blade ME = new Blade(); } - + /** - * @return Single case method returns Blade object + * @return Single case method returns Blade object */ - public static final Blade me(){ + @Deprecated + public static final Blade me() { return BladeHolder.ME; } - + /** * * @param appConf * @return */ - public static final Blade me(String appConf){ + @Deprecated + public static final Blade me(String confPath) { Blade blade = BladeHolder.ME; - blade.bladeConfig.load(appConf); + blade.environment.add(confPath); return blade; } - + + /** + * @return Single case method returns Blade object + */ + public static final Blade $() { + return BladeHolder.ME; + } + + /** + * @param confPath + * @return + */ + public static final Blade $(String confPath) { + Blade blade = BladeHolder.ME; + blade.environment.add(confPath); + return blade; + } + /** * Set Blade initialize - * @param isInit initialize + * + * @param isInit + * initialize */ public void init() { - if(!this.isInit){ + if (!this.isInit) { this.isInit = true; } } - + /** - * @return return route manager + * @return return route manager */ public Routers routers() { return routers; } - + /** - * @return return blade ioc container + * @return return RouteBuilder */ - public Ioc ioc(){ + public RouteBuilder routeBuilder() { + return routeBuilder; + } + + /** + * @return return ConfigLoader + */ + public ConfigLoader configLoader() { + return configLoader; + } + + /** + * @return return blade ioc container + */ + public Ioc ioc() { return ioc; } - + /** * Setting a ioc container - * @param container ioc object - * @return return blade + * + * @param container + * ioc object + * @return return blade */ - public Blade container(Ioc ioc){ + public Blade container(Ioc ioc) { Assert.notNull(ioc); this.ioc = ioc; return this; } - + + /** + * Setting Properties configuration file File path based on classpath + * + * @param confPath + * properties file name + * @return return blade + */ + public Blade loadAppConf(String confPath) { + Assert.notBlank(confPath); + environment.add(confPath); + return this; + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackage(String packageName) { + return this.addRoutePackages(packageName); + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackages(String... packages) { + Assert.notNull(packages); + applicationConfig.addRoutePackages(packages); + return this; + } + /** - * Setting Properties configuration file - * File path based on classpath * - * @param confName properties file name - * @return return blade + * @param basePackage + * @return */ - public Blade loadAppConf(String confName){ - Assert.notBlank(confName); - bladeConfig.load(confName); + public Blade basePackage(String basePackage) { + Assert.notBlank(basePackage); + applicationConfig.setBasePackage(basePackage); + applicationConfig.addIocPackages(basePackage + ".service.*"); + applicationConfig.addRoutePackages(basePackage + ".controller"); + applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); return this; } - - /** - * Setting route package,e.g:com.baldejava.route - * Can be introduced into multiple packages, all of which are in the package. - * - * @param packages route package path, is your package name - * @return return blade - */ - public Blade addRoutePackage(String packageName){ - return this.addRoutePackages(packageName); - } - - /** - * Setting route package,e.g:com.baldejava.route - * Can be introduced into multiple packages, all of which are in the package. - * - * @param packages route package path, is your package name - * @return return blade - */ - public Blade addRoutePackages(String...packages){ - Assert.notNull(packages); - bladeConfig.addRoutePackages(packages); - return this; - } - - /** - * - * @param basePackage - * @return - */ - public Blade basePackage(String basePackage){ - Assert.notBlank(basePackage); - bladeConfig.setBasePackage(basePackage); - bladeConfig.addIocPackages(basePackage + ".service.*"); - bladeConfig.addRoutePackages(basePackage + ".controller"); - bladeConfig.setInterceptorPackage(basePackage + ".interceptor"); - return this; - } - - /** - * Setting the path where the interceptor, e.g:com.bladejava.interceptor - * - * @param packageName interceptor packagename - * @return return blade - */ + + /** + * Setting the path where the interceptor, e.g:com.bladejava.interceptor + * + * @param packageName + * interceptor packagename + * @return return blade + */ public Blade interceptor(String packageName) { Assert.notBlank(packageName); - bladeConfig.setInterceptorPackage(packageName); + applicationConfig.setInterceptorPackage(packageName); + return this; + } + + /** + * Setting Ioc packages, e.g:com.bladejava.service + * + * @param packages + * All need to do into the package, can be introduced into a + * number of + * @return return blade + */ + public Blade ioc(String... packages) { + Assert.notNull(packages); + applicationConfig.addIocPackages(packages); return this; } - - /** - * Setting Ioc packages, e.g:com.bladejava.service - * - * @param packages All need to do into the package, can be introduced into a number of - * @return return blade - */ - public Blade ioc(String...packages){ - Assert.notNull(packages); - bladeConfig.addIocPackages(packages); - return this; - } - - /** - * Add a route - * - * @param path route path - * @param target Target object for routing - * @param method The method name of the route (at the same time, the HttpMethod is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @return return blade - */ - public Blade route(String path, Class clazz, String method){ + + /** + * Add a route + * + * @param path + * route path + * @param target + * Target object for routing + * @param method + * The method name of the route (at the same time, the HttpMethod + * is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade + */ + public Blade route(String path, Class clazz, String method) { routers.route(path, clazz, method); return this; } - + /** * Register a functional route * - * @param path route url - * @param clazz route processing class - * @param method route processing method name - * @param httpMethod HttpMethod Type, GET/POST/... - * @return Blade return blade - */ - public Blade route(String path, Class clazz, String method, HttpMethod httpMethod){ + * @param path + * route url + * @param clazz + * route processing class + * @param method + * route processing method name + * @param httpMethod + * HttpMethod Type, GET/POST/... + * @return Blade return blade + */ + public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { routers.route(path, clazz, method, httpMethod); return this; } - + /** * Add a route list - * @param routes route list - * @return return blade + * + * @param routes + * route list + * @return return blade */ - public Blade routes(List routes){ + public Blade routes(List routes) { Assert.notEmpty(routes, "Routes not is empty!"); routers.addRoutes(routes); return this; } - + /** * Register a GET request route * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade */ - public Blade get(String path, RouteHandler handler){ + public Blade get(String path, RouteHandler handler) { routers.route(path, handler, HttpMethod.GET); return this; } - + /** * Register a POST request route * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade */ - public Blade post(String path, RouteHandler handler){ + public Blade post(String path, RouteHandler handler) { routers.route(path, handler, HttpMethod.POST); return this; } - + /** * Register a DELETE request route * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade */ - public Blade delete(String path, RouteHandler handler){ + public Blade delete(String path, RouteHandler handler) { routers.route(path, handler, HttpMethod.DELETE); return this; } - + /** * Register a PUT request route * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade */ - public Blade put(String path, RouteHandler handler){ + public Blade put(String path, RouteHandler handler) { routers.route(path, handler, HttpMethod.PUT); return this; } - + /** * Register for any request routing * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade */ - public Blade all(String path, RouteHandler handler){ + public Blade all(String path, RouteHandler handler) { routers.route(path, handler, HttpMethod.ALL); return this; } - + /** * Register for any request routing * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade */ - public Blade any(String path, RouteHandler handler){ + public Blade any(String path, RouteHandler handler) { routers.route(path, handler, HttpMethod.ALL); return this; } - + /** * Route Group. e.g blade.group('/users').get().post() + * * @param g - * @return return blade + * @return return blade */ - public RouteGroup group(String prefix){ + public RouteGroup group(String prefix) { Assert.notNull(prefix, "Route group prefix not is null"); return new RouteGroup(this, prefix); } - + /** * Register a pre routing request interceptor * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade */ - public Blade before(String path, RouteHandler handler){ + public Blade before(String path, RouteHandler handler) { routers.route(path, handler, HttpMethod.BEFORE); return this; } @@ -351,243 +433,245 @@ public Blade before(String path, RouteHandler handler){ /** * Register a after routing request interceptor * - * @param path route path, request url - * @param handler execute route Handle - * @return return blade + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade */ - public Blade after(String path, RouteHandler handler){ + public Blade after(String path, RouteHandler handler) { routers.route(path, handler, HttpMethod.AFTER); return this; } - + /** * Setting Render Engin, Default is JspRender * - * @param templateEngine Render engine object - * @return return blade + * @param templateEngine + * Render engine object + * @return return blade */ public Blade viewEngin(TemplateEngine templateEngine) { Assert.notNull(templateEngine); this.templateEngine = templateEngine; return this; } - + /** * Setting the frame static file folder * - * @param folders List of directories to filter, e.g: "/public,/static,/images" - * @return return blade + * @param folders + * List of directories to filter, e.g: "/public,/static,/images" + * @return return blade */ - public Blade staticFolder(final String ... folders) { + public Blade staticFolder(final String... folders) { Assert.notNull(folders); - bladeConfig.setStaticFolders(folders); + applicationConfig.setStaticFolders(folders); return this; } - - /** - * Setting XSS is enable - * - * @param enableXSS enable XSS, default is false - * @return return blade - */ - public Blade enableXSS(boolean httpXss){ - bladeConfig.setHttpXss(httpXss); - return this; - } - - /** - * Dynamically set the global initialization class, the embedded Jetty boot - * - * @param bootstrap global initialization config class - * @return return blade - */ - public Blade app(Bootstrap bootstrap){ - Assert.notNull(bootstrap); - this.bootstrap = bootstrap; - return this; - } - - /** - * Dynamically set global initialization class - * - * @param bootstrap global initialization config class - * @return return blade - */ - public Blade app(Class bootstrap){ - Assert.notNull(bootstrap); - try { - Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); + + /** + * Dynamically set the global initialization class, the embedded Jetty boot + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Bootstrap bootstrap) { + Assert.notNull(bootstrap); + this.bootstrap = bootstrap; + return this; + } + + /** + * Dynamically set global initialization class + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Class bootstrap) { + Assert.notNull(bootstrap); + try { + Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); ioc.addBean(Bootstrap.class.getName(), object); this.bootstrap = object; } catch (Exception e) { e.printStackTrace(); } - return this; - } - - /** - * Setting 404 view page - * - * @param view404 404 view page - * @return return blade - */ - public Blade view404(final String view404){ - Assert.notBlank(view404); - bladeConfig.setView404(view404); - return this; - } - - /** - * Setting 500 view page - * - * @param view500 500 view page - * @return return blade - */ - public Blade view500(final String view500){ - Assert.notBlank(view500); - bladeConfig.setView500(view500); - return this; - } - - /** - * Setting blade web root path - * - * @param webRoot web root path - * @return return blade - */ - public Blade webRoot(final String webRoot){ - Assert.notBlank(webRoot); - bladeConfig.setWebRoot(webRoot); - return this; - } - - /** + return this; + } + + /** + * add interceptor + * + * @param interceptor interceptor class + * @return return blade obj + */ + public Blade addInterceptor(Class interceptor) { + routeBuilder.addInterceptor(interceptor); + return this; + } + + /** + * add config + * + * @param config config class + * @return return blade obj + */ + public Blade addConfig(Class config) { + configLoader.addConfig(config); + return this; + } + + /** + * Setting 404 view page + * + * @param view404 + * 404 view page + * @return return blade + */ + public Blade view404(final String view404) { + Assert.notBlank(view404); + applicationConfig.setView404(view404); + return this; + } + + /** + * Setting 500 view page + * + * @param view500 + * 500 view page + * @return return blade + */ + public Blade view500(final String view500) { + Assert.notBlank(view500); + applicationConfig.setView500(view500); + return this; + } + + /** + * Setting blade web root path + * + * @param webRoot + * web root path + * @return return blade + */ + public Blade webRoot(final String webRoot) { + Assert.notBlank(webRoot); + applicationConfig.setWebRoot(webRoot); + return this; + } + + /** * Setting blade run mode * - * @param isDev is dev mode - * @return return blade + * @param isDev + * is dev mode + * @return return blade */ - public Blade isDev(boolean isDev){ - bladeConfig.setDev(isDev); + public Blade isDev(boolean isDev) { + applicationConfig.setDev(isDev); return this; } - + /** * Setting jetty listen port * - * @param port port, default is 9000 - * @return return blade + * @param port + * port, default is 9000 + * @return return blade */ - public Blade listen(int port){ + public Blade listen(int port) { this.port = port; return this; } - - /** - * @return Return blade config object - */ - public BladeConfig config(){ - return bladeConfig; - } - - /** - * @return Return Blade Environment - */ - public Environment environment(){ - return bladeConfig.environment(); - } - - /** - * @return Return route packages - */ - public String[] routePackages(){ - return bladeConfig.getRoutePackages(); - } - - /** - * @return Return ioc packages - */ - public String[] iocs(){ - return bladeConfig.getIocPackages(); - } - - /** - * @return Returns the interceptor array, only one element here use String[] - */ - public String interceptorPackage(){ - return bladeConfig.getInterceptorPackage(); - } - - /** - * @return Return blade encoding, default is UTF-8 - */ - public String encoding(){ - return bladeConfig.getEncoding(); - } - - /** - * @return Return 404 view - */ - public String view404(){ - return bladeConfig.getView404(); - } - - /** - * @return Return 500 view - */ - public String view500(){ - return bladeConfig.getView500(); - } - - /** - * @return Return blade web root path - */ - public String webRoot(){ - return bladeConfig.getWebRoot(); - } - - /** - * @return Return is dev mode - */ - public boolean isDev(){ - return bladeConfig.isDev(); - } - - /** - * @return Return static resource directory - */ - public Set staticFolder(){ - return bladeConfig.getStaticFolders(); - } - - /** - * @return Return bootstrap object - */ - public Bootstrap bootstrap(){ - return this.bootstrap; + + /** + * @return Return blade config object + */ + public ApplicationConfig applicationConfig() { + return applicationConfig; } - + /** - * @return Return current templateEngine + * @return Return blade config object */ - public TemplateEngine templateEngine() { - return this.templateEngine; + public ApplicationConfig config() { + return applicationConfig; + } + + /** + * @return Return Blade Environment + */ + public Environment environment() { + return environment; + } + + /** + * @return Return blade encoding, default is UTF-8 + */ + public String encoding() { + return applicationConfig.getEncoding(); + } + + /** + * @return Return 404 view + */ + public String view404() { + return applicationConfig.getView404(); + } + + /** + * @return Return 500 view + */ + public String view500() { + return applicationConfig.getView500(); + } + + /** + * @return Return blade web root path + */ + public String webRoot() { + return applicationConfig.getWebRoot(); + } + + /** + * @return Return is dev mode + */ + public boolean isDev() { + return applicationConfig.isDev(); + } + + /** + * @return Return static resource directory + */ + public Set staticFolder() { + return applicationConfig.getStaticFolders(); } /** - * @return Return XSS is enabled + * @return Return bootstrap object */ - public boolean enableXSS(){ - return bladeConfig.isHttpXss(); + public Bootstrap bootstrap() { + return this.bootstrap; } - + + /** + * @return Return current templateEngine + */ + public TemplateEngine templateEngine() { + return this.templateEngine; + } + /** * return register plugin object * - * @param plugin plugin class - * @return return blade + * @param plugin + * plugin class + * @return return blade */ - public Blade plugin(Class plugin){ + public Blade plugin(Class plugin) { Assert.notNull(plugin); plugins.add(plugin); return this; @@ -596,19 +680,23 @@ public Blade plugin(Class plugin){ /** * Registration of a configuration file, e.g: "com.xxx.route","route.conf" * - * @param basePackage controller package name - * @return return blade + * @param basePackage + * controller package name + * @return return blade */ public Blade routeConf(String basePackage) { return routeConf(basePackage, "route.conf"); } - + /** * Registration of a configuration file, e.g: "com.xxx.route","route.conf" * - * @param basePackage controller package name - * @param conf Configuration file path, the configuration file must be in classpath - * @return return blade + * @param basePackage + * controller package name + * @param conf + * Configuration file path, the configuration file must be in + * classpath + * @return return blade */ public Blade routeConf(String basePackage, String conf) { try { @@ -626,39 +714,39 @@ public Blade routeConf(String basePackage, String conf) { } return this; } - + /** - * @return Return blade is initialize + * @return Return blade is initialize */ public boolean isInit() { return isInit; } - + public Blade enableServer(boolean enableServer) { this.enableServer = enableServer; return this; } - + public boolean enableServer() { return this.enableServer; } - - public boolean httpCache() { - return bladeConfig.isHttpCache(); - } - + public Set> plugins() { return this.plugins; } - + public void start(Class embedServer) throws Exception { + this.loadAppConf(Const.APP_PROPERTIES); + // init blade environment config + this.config().setEnv(environment); + embedServer.newInstance().startup(port, contextPath); this.enableServer = true; } - + public void start(EmbedServer embedServer) throws Exception { embedServer.startup(port, contextPath); + this.enableServer = true; } - } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/Bootstrap.java b/blade-core/src/main/java/com/blade/Bootstrap.java index fe68f7189..d82d8cc7e 100644 --- a/blade-core/src/main/java/com/blade/Bootstrap.java +++ b/blade-core/src/main/java/com/blade/Bootstrap.java @@ -1,39 +1,39 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -/** - * Blade global initialization class, you can do some operations at the start of the application - * - * @author biezhi - * @since 1.0 - */ -public abstract class Bootstrap { - - /** - * Initialization method, do some initialization operation when the application starts - * @param blade blade global object - */ - public abstract void init(Blade blade); - - /** - * After initialization configuration - * @param blade blade global object - */ - public void contextInitialized(Blade blade){ - // - } -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +/** + * Blade global initialization class, you can do some operations at the start of the application + * + * @author biezhi + * @since 1.0 + */ +public abstract class Bootstrap { + + /** + * Initialization method, do some initialization operation when the application starts + * @param blade blade global object + */ + public abstract void init(Blade blade); + + /** + * After initialization configuration + * @param blade blade global object + */ + public void contextInitialized(){ + // + } +} diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index b4249cd93..ae0039d71 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -24,7 +24,7 @@ public interface Const { // current blade version - String BLADE_VERSION = "1.6.4"; + String BLADE_VERSION = "1.6.5"; // default embedd server context path String DEFAULT_CONTEXTPATH = "/"; @@ -49,5 +49,6 @@ public interface Const { String BLADE_VIEW_404 = "blade.view404"; String BLADE_VIEW_500 = "blade.view500"; String BLADE_DEV = "blade.dev"; + String APP_PROPERTIES = "app.properties"; } diff --git a/blade-core/src/main/java/com/blade/annotation/RequestParam.java b/blade-core/src/main/java/com/blade/annotation/RequestParam.java index af3fc8cbf..6de54e133 100644 --- a/blade-core/src/main/java/com/blade/annotation/RequestParam.java +++ b/blade-core/src/main/java/com/blade/annotation/RequestParam.java @@ -10,9 +10,9 @@ @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestParam { - + String value(); - + boolean required() default true; String defaultValue() default ""; diff --git a/blade-core/src/main/java/com/blade/annotation/Route.java b/blade-core/src/main/java/com/blade/annotation/Route.java index 395fc3277..04eb53542 100644 --- a/blade-core/src/main/java/com/blade/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/annotation/Route.java @@ -49,7 +49,7 @@ /** * @return Request url */ - String value() default ""; + String value() default "/"; /** * @return Request HttpMethod diff --git a/blade-core/src/main/java/com/blade/context/BladeConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java similarity index 54% rename from blade-core/src/main/java/com/blade/context/BladeConfig.java rename to blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 695d67076..2213463f6 100644 --- a/blade-core/src/main/java/com/blade/context/BladeConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.context; +package com.blade.config; import java.util.Arrays; import java.util.HashSet; @@ -30,107 +30,91 @@ * @since 1.0 * */ -public class BladeConfig { +public class ApplicationConfig { - // Storage of all routing packets + // Storage of all routing packets private Set routePackages = new HashSet(); - - // Store all IOC packages + + // Store all IOC packages private Set iocPackages = new HashSet(); - - // Store all filter directories + + // Strore all config packages + private Set configPackages = new HashSet(); + + // Store all filter directories private Set staticFolders = new HashSet(); - + // Base package private String basePackage; // Interceptor package private String interceptorPackage; - + // Encoding private String encoding = "utf-8"; - + // web root path private String webRoot; - + // 404 view page private String view404; - + // 500 view page private String view500; - + // Is dev mode private boolean isDev = true; - // Enabled XSS - private boolean httpXss = false; - - private boolean httpCache = false; - - private boolean configInit = false; - - private Environment environment; - - public BladeConfig() { + private boolean isInit = false; + + public ApplicationConfig() { staticFolders.add("/public"); staticFolders.add("/assets"); staticFolders.add("/static"); } - - public void load(String confPath){ - if(!configInit){ - try { - Environment environment = Environment.load(confPath); - if(null != environment){ - this.environment = environment; - this.isDev = environment.getBoolean("app.dev", true); - this.httpCache = environment.getBoolean("http.cache", false); - this.httpXss = environment.getBoolean("http.xss", false); - this.encoding = environment.getString("http.encoding", "UTF-8"); - this.addIocPackages(environment.getString("app.ioc")); - this.view500 = environment.getString("app.view.500"); - this.view404 = environment.getString("app.view.404"); - - String httpFilters = environment.getString("http.filters"); - String basePackage = environment.getString("app.base-package"); - Integer port = environment.getInt("server.port"); - - if(null != port){ - Blade.me().listen(port); - } - - if(StringKit.isNotBlank(httpFilters)){ - this.setStaticFolders(httpFilters.split(",")); - } - - if(StringKit.isNotBlank(basePackage)){ - this.setBasePackage(basePackage); - this.addIocPackages(basePackage + ".service.*"); - this.addRoutePackages(basePackage + ".controller"); - this.setInterceptorPackage(basePackage + ".interceptor"); - } - - } - } catch (Exception e) { + + public void setEnv(Environment environment) { + if (null != environment && !isInit) { + this.isDev = environment.getBoolean("app.dev", true); + this.encoding = environment.getString("http.encoding", "UTF-8"); + this.addIocPackages(environment.getString("app.ioc")); + this.view500 = environment.getString("app.view.500"); + this.view404 = environment.getString("app.view.404"); + + String httpFilters = environment.getString("http.filters"); + String basePackage = environment.getString("app.base-package"); + Integer port = environment.getInt("server.port"); + + if (null != port) { + Blade.$().listen(port); } + + if (StringKit.isNotBlank(httpFilters)) { + this.setStaticFolders(httpFilters.split(",")); + } + + if (StringKit.isNotBlank(basePackage)) { + this.setBasePackage(basePackage); + this.addConfigPackages(basePackage + ".config"); + this.addIocPackages(basePackage + ".service.*"); + this.addRoutePackages(basePackage + ".controller"); + this.setInterceptorPackage(basePackage + ".interceptor"); + } + isInit = true; } } - - public Environment environment(){ - return this.environment; - } - + public String[] getRoutePackages() { String[] routeArr = new String[routePackages.size()]; return routePackages.toArray(routeArr); } - - public void addRoutePackages(String ... packages) { - if(null != packages && packages.length > 0){ + + public void addRoutePackages(String... packages) { + if (null != packages && packages.length > 0) { routePackages.addAll(Arrays.asList(packages)); } } - + public String getBasePackage() { return basePackage; } @@ -144,12 +128,23 @@ public String[] getIocPackages() { return iocPackages.toArray(iocArr); } - public void addIocPackages(String ... packages) { - if(null != packages && packages.length > 0){ + public String[] getConfigPackages() { + String[] configArr = new String[configPackages.size()]; + return configPackages.toArray(configArr); + } + + public void addIocPackages(String... packages) { + if (null != packages && packages.length > 0) { iocPackages.addAll(Arrays.asList(packages)); } } + public void addConfigPackages(String... packages) { + if (null != packages && packages.length > 0) { + configPackages.addAll(Arrays.asList(packages)); + } + } + public String getInterceptorPackage() { return interceptorPackage; } @@ -161,8 +156,8 @@ public void setInterceptorPackage(String interceptorPackage) { public Set getStaticFolders() { return staticFolders; } - - public void setStaticFolders(String ... packages) { + + public void setStaticFolders(String... packages) { staticFolders.addAll(Arrays.asList(packages)); } @@ -206,20 +201,7 @@ public void setEncoding(String encoding) { this.encoding = encoding; } - public boolean isHttpXss() { - return httpXss; + public boolean isInit(){ + return this.isInit; } - - public void setHttpXss(boolean httpXss) { - this.httpXss = httpXss; - } - - public boolean isHttpCache() { - return httpCache; - } - - public void setHttpCache(boolean httpCache) { - this.httpCache = httpCache; - } - } diff --git a/blade-core/src/main/java/com/blade/config/BaseConfig.java b/blade-core/src/main/java/com/blade/config/BaseConfig.java new file mode 100644 index 000000000..b78fd53c2 --- /dev/null +++ b/blade-core/src/main/java/com/blade/config/BaseConfig.java @@ -0,0 +1,7 @@ +package com.blade.config; + +public interface BaseConfig { + + void config(ApplicationConfig applicationConfig); + +} diff --git a/blade-core/src/main/java/com/blade/config/ConfigLoader.java b/blade-core/src/main/java/com/blade/config/ConfigLoader.java new file mode 100644 index 000000000..daa63bc4d --- /dev/null +++ b/blade-core/src/main/java/com/blade/config/ConfigLoader.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.lang.reflect.Modifier; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.exception.ConfigException; +import com.blade.ioc.Ioc; +import com.blade.ioc.annotation.Component; +import com.blade.kit.CollectionKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassReader; +import com.blade.kit.resource.DynamicClassReader; + +/** + * ConfigLoader + * + * @author biezhi + * @since 1.0 + */ +public class ConfigLoader { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); + + private ClassReader classReader; + private Ioc ioc; + private ApplicationConfig applicationConfig; + + public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { + this.ioc = ioc; + this.classReader = DynamicClassReader.getClassReader(); + this.applicationConfig = applicationConfig; + } + + @SuppressWarnings("unchecked") + public void loadConfig() { + String[] configPackages = Blade.$().config().getConfigPackages(); + if (null != configPackages && configPackages.length > 0) { + // Scan package all class + try { + for (String packageName : configPackages) { + Set> classes = classReader.getClassByAnnotation(packageName, Component.class, false); + if (CollectionKit.isNotEmpty(classes)) { + for (Class clazz : classes) { + boolean hasInterface = ReflectKit.hasInterface(clazz, BaseConfig.class); + if(hasInterface){ + addConfig((Class) clazz); + } + } + } + } + } catch (ConfigException e) { + LOGGER.error("load config error", e); + } + } + } + + public void addConfig(Class clazz) throws ConfigException { + if (!Modifier.isAbstract(clazz.getModifiers())) { + try { + BaseConfig baseConfig = (BaseConfig) ReflectKit.newInstance(clazz); + baseConfig.config(applicationConfig); + ioc.addBean(baseConfig); + } catch (InstantiationException e) { + throw new ConfigException(e); + } catch (IllegalAccessException e) { + throw new ConfigException(e); + } + } + } + +} diff --git a/blade-core/src/main/java/com/blade/context/BladeWebContext.java b/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java similarity index 77% rename from blade-core/src/main/java/com/blade/context/BladeWebContext.java rename to blade-core/src/main/java/com/blade/context/ApplicationWebContext.java index 7d3247622..548d4c628 100644 --- a/blade-core/src/main/java/com/blade/context/BladeWebContext.java +++ b/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java @@ -27,12 +27,12 @@ * @author biezhi * @since 1.0 */ -public class BladeWebContext { +public class ApplicationWebContext { /** * BladeWebContext object for the current thread */ - private static ThreadLocal ctx = new ThreadLocal(); + private static ThreadLocal ctx = new ThreadLocal(); /** * ServletContext Object that is created when the application is initialized @@ -49,20 +49,20 @@ public class BladeWebContext { */ private Response response; - private BladeWebContext(){} + private ApplicationWebContext(){} - public static BladeWebContext me(){ + public static ApplicationWebContext me(){ return ctx.get(); } - public static void setContext(ServletContext context) { - BladeWebContext bladeWebContext = new BladeWebContext(); + public static void init(ServletContext context) { + ApplicationWebContext bladeWebContext = new ApplicationWebContext(); bladeWebContext.context = context; ctx.set(bladeWebContext); } - public static void setContext(ServletContext context, Request request, Response response) { - BladeWebContext bladeWebContext = new BladeWebContext(); + public static void init(ServletContext context, Request request, Response response) { + ApplicationWebContext bladeWebContext = new ApplicationWebContext(); bladeWebContext.context = context; bladeWebContext.request = request; bladeWebContext.response = response; diff --git a/blade-core/src/main/java/com/blade/exception/BladeException.java b/blade-core/src/main/java/com/blade/exception/BladeException.java new file mode 100644 index 000000000..b197c8d3f --- /dev/null +++ b/blade-core/src/main/java/com/blade/exception/BladeException.java @@ -0,0 +1,27 @@ +package com.blade.exception; + +public class BladeException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public BladeException() { + super(); + } + + public BladeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public BladeException(String message, Throwable cause) { + super(message, cause); + } + + public BladeException(String message) { + super(message); + } + + public BladeException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/exception/ConfigException.java b/blade-core/src/main/java/com/blade/exception/ConfigException.java new file mode 100644 index 000000000..7cf03f86a --- /dev/null +++ b/blade-core/src/main/java/com/blade/exception/ConfigException.java @@ -0,0 +1,27 @@ +package com.blade.exception; + +public class ConfigException extends BladeException { + + private static final long serialVersionUID = 1L; + + public ConfigException() { + super(); + } + + public ConfigException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public ConfigException(String message, Throwable cause) { + super(message, cause); + } + + public ConfigException(String message) { + super(message); + } + + public ConfigException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/exception/NotFoundException.java b/blade-core/src/main/java/com/blade/exception/NotFoundException.java new file mode 100644 index 000000000..265113846 --- /dev/null +++ b/blade-core/src/main/java/com/blade/exception/NotFoundException.java @@ -0,0 +1,27 @@ +package com.blade.exception; + +public class NotFoundException extends BladeException { + + private static final long serialVersionUID = 1L; + + public NotFoundException() { + super(); + } + + public NotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public NotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public NotFoundException(String message) { + super(message); + } + + public NotFoundException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index a423f439a..b29f9cbec 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -69,13 +69,13 @@ public class IocApplication { private Blade blade; - public IocApplication(Blade blade) { - this.blade = blade; + public IocApplication() { + this.blade = Blade.$(); this.classReader = DynamicClassReader.getClassReader(); this.plugins = CollectionKit.newArrayList(); this.pluginTypes = blade.plugins(); this.ioc = blade.ioc(); - this.iocs = blade.iocs(); + this.iocs = blade.config().getIocPackages(); this.bootstrap = blade.bootstrap(); } diff --git a/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java index 2f67ac541..f64ef38c7 100644 --- a/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java @@ -105,7 +105,7 @@ public void addBean(String name, BeanDefine beanDefine) { Assert.notNull(name); Assert.notNull(beanDefine); - LOGGER.debug("addBean: {}", name); +// LOGGER.debug("addBean: {}", name); if (pool.put(name, beanDefine) != null) { LOGGER.warn("Duplicated Bean: {}", name); @@ -139,7 +139,7 @@ public void addBean(String name, Class beanClass, boolean singleton) { Assert.isFalse(beanClass.isInterface(), "Must not be interface: %s", beanClass.getName()); Assert.isFalse(Modifier.isAbstract(beanClass.getModifiers()), "Must not be abstract class: %s", beanClass.getName()); - LOGGER.debug("addBean: {} = {}", name, beanClass.getName()); +// LOGGER.debug("addBean: {} = {}", name, beanClass.getName()); BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton); diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index ba937c87c..89ce25c79 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -51,10 +51,8 @@ public class RouteBuilder { private String interceptorPackage; - public RouteBuilder(Blade blade) { - this.routers = blade.routers(); - this.routePackages = blade.routePackages(); - this.interceptorPackage = blade.interceptorPackage(); + public RouteBuilder(Routers routers) { + this.routers = routers; this.classReader = DynamicClassReader.getClassReader(); } @@ -63,6 +61,9 @@ public RouteBuilder(Blade blade) { */ public void building() { + this.routePackages = Blade.$().config().getRoutePackages(); + this.interceptorPackage = Blade.$().config().getInterceptorPackage(); + // Route if(null != routePackages && routePackages.length > 0){ this.buildRoute(routePackages); @@ -92,7 +93,7 @@ private void buildInterceptor(String... interceptorPackages){ classes = classReader.getClass(packageName, Interceptor.class, false); if(CollectionKit.isNotEmpty(classes)){ for(Class interceptorClazz : classes){ - parseInterceptor(interceptorClazz); + addInterceptor(interceptorClazz); } } } @@ -111,7 +112,7 @@ private void buildRoute(String... routePackages){ classes = classReader.getClassByAnnotation(packageName, Controller.class, true); if(CollectionKit.isNotEmpty(classes)){ for(Class pathClazz : classes){ - parseRouter(pathClazz); + addRouter(pathClazz); } } } @@ -123,7 +124,7 @@ private void buildRoute(String... routePackages){ * * @param interceptor resolve the interceptor class */ - private void parseInterceptor(final Class interceptor){ + public void addInterceptor(final Class interceptor){ boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); @@ -157,7 +158,7 @@ private void parseInterceptor(final Class interceptor){ * * @param controller resolve the routing class */ - private void parseRouter(final Class router){ + public void addRouter(final Class router){ Method[] methods = router.getMethods(); if(null == methods || methods.length == 0){ @@ -196,7 +197,10 @@ private void parseRouter(final Class router){ private String getRoutePath(String value, String nameSpace, String suffix){ String path = value.startsWith("/") ? value : "/" + value; + + nameSpace = nameSpace.startsWith("/") ? nameSpace : "/" + nameSpace; path = nameSpace + path; + path = path.replaceAll("[/]+", "/"); path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; diff --git a/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java index 75f49f5e2..954206102 100644 --- a/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java @@ -1,85 +1,85 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route.loader; - -import com.blade.Blade; -import com.blade.ioc.Ioc; -import com.blade.route.RouteException; - -/** - * ClassPath controller of loader - * - * @author biezhi - * @since 1.0 - */ -public class ClassPathControllerLoader implements ControllerLoader { - - private String basePackage; - - private ClassLoader classLoader = ClassPathControllerLoader.class.getClassLoader(); - - private Ioc ioc = Blade.me().ioc(); - - public ClassPathControllerLoader() { - this(""); - } - - public ClassPathControllerLoader(String basePackage) { - this.basePackage = basePackage; - - if (this.basePackage != null && !"".equals(this.basePackage)) { - if (!this.basePackage.endsWith(".")) { - this.basePackage += "."; - } - } - } - - @Override - public Object load(String controllerName) throws RouteException { - String className = basePackage + controllerName; - - try { - // Load controller instance - Class controllerClass = classLoader.loadClass(className); - - Object controller = ioc.getBean(controllerClass); - if(null == controller){ - ioc.addBean(controllerClass); - controller = ioc.getBean(controllerClass); - } - return controller; - } catch (Exception e) { - throw new RouteException(e); - } - } - - public String getBasePackage() { - return basePackage; - } - - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - } - - public ClassLoader getClassLoader() { - return classLoader; - } - - public void setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route.loader; + +import com.blade.Blade; +import com.blade.ioc.Ioc; +import com.blade.route.RouteException; + +/** + * ClassPath controller of loader + * + * @author biezhi + * @since 1.0 + */ +public class ClassPathControllerLoader implements ControllerLoader { + + private String basePackage; + + private ClassLoader classLoader = ClassPathControllerLoader.class.getClassLoader(); + + private Ioc ioc = Blade.$().ioc(); + + public ClassPathControllerLoader() { + this(""); + } + + public ClassPathControllerLoader(String basePackage) { + this.basePackage = basePackage; + + if (this.basePackage != null && !"".equals(this.basePackage)) { + if (!this.basePackage.endsWith(".")) { + this.basePackage += "."; + } + } + } + + @Override + public Object load(String controllerName) throws RouteException { + String className = basePackage + controllerName; + + try { + // Load controller instance + Class controllerClass = classLoader.loadClass(className); + + Object controller = ioc.getBean(controllerClass); + if(null == controller){ + ioc.addBean(controllerClass); + controller = ioc.getBean(controllerClass); + } + return controller; + } catch (Exception e) { + throw new RouteException(e); + } + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + +} diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 40ac68ba5..bc880c8d4 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -1,74 +1,68 @@ package com.blade.view.handle; -import java.lang.annotation.Annotation; import java.lang.reflect.Method; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import java.lang.reflect.Parameter; import com.blade.annotation.PathVariable; import com.blade.annotation.RequestParam; +import com.blade.exception.BladeException; +import com.blade.exception.NotFoundException; import com.blade.ioc.Ioc; import com.blade.kit.StringKit; import com.blade.kit.reflect.ReflectKit; import com.blade.route.Route; import com.blade.view.ModelAndView; -import com.blade.view.ModelMap; import com.blade.web.DispatchKit; import com.blade.web.http.Request; import com.blade.web.http.Response; -import com.blade.web.http.wrapper.Session; -import com.blade.web.multipart.FileItem; public class RouteViewHandler { - + private Ioc ioc; - public RouteViewHandler(Ioc ioc) { this.ioc = ioc; } - private Object getPathParam(Class parameterType, String val, Request request){ + private Object getPathParam(Class parameterType, String val, Request request) { Object result = null; - if(parameterType.equals(String.class)){ + if (parameterType.equals(String.class)) { result = request.param(val); - } else if(parameterType.equals(Integer.class) || parameterType.equals(int.class)){ + } else if (parameterType.equals(Integer.class) || parameterType.equals(int.class)) { result = request.paramAsInt(val); - } else if(parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)){ + } else if (parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)) { result = request.paramAsBool(val); - } else if(parameterType.equals(Long.class) || parameterType.equals(long.class)){ + } else if (parameterType.equals(Long.class) || parameterType.equals(long.class)) { result = request.paramAsLong(val); } return result; } - private Object getRequestParam(Class parameterType, String val, String defaultValue, Request request){ + private Object getRequestParam(Class parameterType, String val, String defaultValue, Request request) { Object result = null; - if(parameterType.equals(String.class)){ + if (parameterType.equals(String.class)) { String value = request.query(val); - if(null == value && null != defaultValue){ + if (null == value && null != defaultValue) { result = defaultValue; } else { result = value; } - } else if(parameterType.equals(Integer.class) || parameterType.equals(int.class)){ + } else if (parameterType.equals(Integer.class) || parameterType.equals(int.class)) { Integer value = request.queryAsInt(val); - if(null == value && StringKit.isNotBlank(defaultValue)){ + if (null == value && StringKit.isNotBlank(defaultValue)) { result = Integer.valueOf(defaultValue); } else { result = value; } - } else if(parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)){ + } else if (parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)) { Boolean value = request.queryAsBool(val); - if(null == value && StringKit.isNotBlank(defaultValue)){ + if (null == value && StringKit.isNotBlank(defaultValue)) { result = Boolean.valueOf(defaultValue); } else { result = value; } - } else if(parameterType.equals(Long.class) || parameterType.equals(long.class)){ + } else if (parameterType.equals(Long.class) || parameterType.equals(long.class)) { Long value = request.queryAsLong(val); - if(null == value && StringKit.isNotBlank(defaultValue)){ + if (null == value && StringKit.isNotBlank(defaultValue)) { result = Long.valueOf(defaultValue); } else { result = value; @@ -76,137 +70,171 @@ private Object getRequestParam(Class parameterType, String val, String defaul } return result; } - + /** * Parameters in the method * - * @param request Request object for injection to the method parameter list - * @param response Response object for injection to the method parameter list - * @param actionMethod Execute method - * @return Return the generated array of parameters + * @param request + * Request object for injection to the method parameter list + * @param response + * Response object for injection to the method parameter list + * @param actionMethod + * Execute method + * @return Return the generated array of parameters */ - public Object[] getArgs(Request request, Response response, Method actionMethod){ - Annotation[][] parameterAnnotations = actionMethod.getParameterAnnotations(); + public Object[] getArgs(Request request, Response response, Method actionMethod) throws NotFoundException { + Class[] parameterTypes = actionMethod.getParameterTypes(); + int len = parameterTypes.length; Object[] args = new Object[len]; actionMethod.setAccessible(true); - - int i = 0; - if(parameterAnnotations.length > 0){ - for (Annotation[] annotations : parameterAnnotations) { - Class parameterType = parameterTypes[i]; - for (Annotation annotation : annotations) { - Class anType = annotation.annotationType(); - if(anType.equals(PathVariable.class)){ - PathVariable pathVariable = (PathVariable) annotation; - String val = pathVariable.value(); - Object value = getPathParam(parameterType, val, request); - args[i] = value; - } else if(anType.equals(RequestParam.class)) { - RequestParam requestParam = (RequestParam) annotation; - String val = requestParam.value(); - Object value = getRequestParam(parameterType, val, requestParam.defaultValue(), request); - args[i] = value; + + Parameter[] parameters = actionMethod.getParameters(); + int pos = 0; + try { + for (Parameter parameter : parameters) { + + if (parameter.getType().getName().equals(Request.class.getName())) { + args[pos] = request; + } + + if (parameter.getType().getName().equals(Response.class.getName())) { + args[pos] = response; + } + + RequestParam requestParam = parameter.getAnnotation(RequestParam.class); + if (null != requestParam) { + String paramName = requestParam.value(); + String val = request.query(paramName); + if(StringKit.isBlank(val)){ + throw new NotFoundException("request param ["+ paramName +"] is null"); } + Object value = getRequestParam(parameter.getType(), val, requestParam.defaultValue(), request); + args[pos] = value; } - i++; - } - } - - for(i=0; i paramTypeClazz = parameterTypes[i]; - if(paramTypeClazz.equals(Request.class)){ - args[i] = request; - } else if(paramTypeClazz.equals(Response.class)){ - args[i] = response; - } else if(paramTypeClazz.equals(Session.class)){ - args[i] = request.session(); - } else if(paramTypeClazz.equals(ModelMap.class)){ - args[i] = new ModelMap(request); - } else if(paramTypeClazz.equals(HttpServletRequest.class)){ - args[i] = request.raw(); - } else if(paramTypeClazz.equals(HttpServletResponse.class)){ - args[i] = response.raw(); - } else if(paramTypeClazz.equals(HttpSession.class)){ - args[i] = request.raw().getSession(); - } else if(paramTypeClazz.equals(FileItem.class)){ - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - args[i] = fileItems[0]; + + PathVariable pathVariable = parameter.getAnnotation(PathVariable.class); + if (null != pathVariable) { + String paramName = pathVariable.value(); + String val = request.param(paramName); + if(StringKit.isBlank(val)){ + throw new NotFoundException("path param ["+ paramName +"] is null"); + } + Object value = getRequestParam(parameter.getType(), val, requestParam.defaultValue(), request); + args[pos] = value; } + pos++; } + } catch (BladeException e) { + throw e; } + + /* + * int i = 0; if(parameterAnnotations.length > 0){ for (Annotation[] + * annotations : parameterAnnotations) { Class parameterType = + * parameterTypes[i]; for (Annotation annotation : annotations) { + * Class anType = annotation.annotationType(); + * if(anType.equals(PathVariable.class)){ PathVariable pathVariable = + * (PathVariable) annotation; String val = pathVariable.value(); Object + * value = getPathParam(parameterType, val, request); args[i] = value; } + * else if(anType.equals(RequestParam.class)) { RequestParam + * requestParam = (RequestParam) annotation; String val = + * requestParam.value(); Object value = getRequestParam(parameterType, + * val, requestParam.defaultValue(), request); args[i] = value; } } i++; + * } } + * + * for(i=0; i paramTypeClazz = parameterTypes[i]; + * if(paramTypeClazz.equals(Request.class)){ args[i] = request; } else + * if(paramTypeClazz.equals(Response.class)){ args[i] = response; } else + * if(paramTypeClazz.equals(Session.class)){ args[i] = + * request.session(); } else if(paramTypeClazz.equals(ModelMap.class)){ + * args[i] = new ModelMap(request); } else + * if(paramTypeClazz.equals(HttpServletRequest.class)){ args[i] = + * request.raw(); } else + * if(paramTypeClazz.equals(HttpServletResponse.class)){ args[i] = + * response.raw(); } else if(paramTypeClazz.equals(HttpSession.class)){ + * args[i] = request.raw().getSession(); } else + * if(paramTypeClazz.equals(FileItem.class)){ FileItem[] fileItems = + * request.files(); if(null != fileItems && fileItems.length > 0){ + * args[i] = fileItems[0]; } } } + */ return args; } - public void handle(Request request, Response response, Route route){ + public void handle(Request request, Response response, Route route) throws BladeException { Method actionMethod = route.getAction(); Object target = route.getTarget(); // execute - + int len = actionMethod.getParameterTypes().length; try { Object returnParam = null; - if(len > 0){ + if (len > 0) { Object[] args = getArgs(request, response, actionMethod); returnParam = ReflectKit.invokeMehod(target, actionMethod, args); } else { returnParam = ReflectKit.invokeMehod(target, actionMethod); } - - if(null != returnParam){ + + if (null != returnParam) { Class returnType = returnParam.getClass(); - if(returnType == String.class){ - response.render( returnParam.toString() ); - } else if(returnType == ModelAndView.class){ + if (returnType == String.class) { + response.render(returnParam.toString()); + } else if (returnType == ModelAndView.class) { ModelAndView modelAndView = (ModelAndView) returnParam; - response.render( modelAndView ); + response.render(modelAndView); } } + } catch (BladeException e) { + throw e; } catch (Exception e) { request.abort(); DispatchKit.printError(e, 500, response); } - + } - - public boolean intercept(Request request, Response response, Route route){ + + public boolean intercept(Request request, Response response, Route route) { Method actionMethod = route.getAction(); Object target = route.getTarget(); - - if(null == target){ + + if (null == target) { Class clazz = route.getAction().getDeclaringClass(); target = ioc.getBean(clazz); route.setTarget(target); } - + // execute int len = actionMethod.getParameterTypes().length; actionMethod.setAccessible(true); try { Object returnParam = null; - if(len > 0){ + if (len > 0) { Object[] args = getArgs(request, response, actionMethod); returnParam = ReflectKit.invokeMehod(target, actionMethod, args); } else { returnParam = ReflectKit.invokeMehod(target, actionMethod); } - - if(null != returnParam){ + + if (null != returnParam) { Class returnType = returnParam.getClass(); - if(returnType == Boolean.class || returnType == boolean.class){ + if (returnType == Boolean.class || returnType == boolean.class) { return (Boolean) returnParam; } } - + return true; - + } catch (Exception e) { request.abort(); DispatchKit.printError(e, 500, response); } return false; } - + + private void setValue(Object object, Class type, Object value) { + + } + } diff --git a/blade-core/src/main/java/com/blade/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/view/template/JspEngine.java index 6173395f3..259c9ebe9 100644 --- a/blade-core/src/main/java/com/blade/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/JspEngine.java @@ -27,7 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.blade.context.BladeWebContext; +import com.blade.context.ApplicationWebContext; import com.blade.view.ModelAndView; @@ -52,8 +52,8 @@ public JspEngine(String viewPath) { @Override public void render(ModelAndView modelAndView, Writer writer) { - HttpServletRequest servletRequest = BladeWebContext.request().raw(); - HttpServletResponse servletResponse = BladeWebContext.response().raw(); + HttpServletRequest servletRequest = ApplicationWebContext.request().raw(); + HttpServletResponse servletResponse = ApplicationWebContext.response().raw(); try { Map model = modelAndView.getModel(); diff --git a/blade-core/src/main/java/com/blade/web/DispatchKit.java b/blade-core/src/main/java/com/blade/web/DispatchKit.java index 39a676423..4351993d5 100644 --- a/blade-core/src/main/java/com/blade/web/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/web/DispatchKit.java @@ -32,7 +32,7 @@ public class DispatchKit { private static final Logger LOGGER = LoggerFactory.getLogger(DispatchKit.class); - static final boolean isWeb = Blade.me().enableServer(); + static final boolean isWeb = Blade.$().enableServer(); private static Boolean isDev = null; @@ -83,9 +83,8 @@ public static void setFileDownloadHeader(HttpServletResponse response, String fi */ public static void printError(Throwable err, int code, Response response){ if(null == isDev){ - isDev = Blade.me().isDev(); + isDev = Blade.$().isDev(); } - err.printStackTrace(); try { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final PrintWriter writer = new PrintWriter(baos); @@ -98,7 +97,7 @@ public static void printError(Throwable err, int code, Response response){ writer.println(END); } else { if(code == 404){ - String view404 = Blade.me().view404(); + String view404 = Blade.$().view404(); if(StringKit.isNotBlank(view404)){ response.render(view404); return; @@ -106,7 +105,7 @@ public static void printError(Throwable err, int code, Response response){ writer.write(err.getMessage()); } } else { - String view500 = Blade.me().view500(); + String view500 = Blade.$().view500(); if(StringKit.isNotBlank(view500)){ response.render(view500); return; diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java index 4ddacc808..8c9ffb0d7 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -26,7 +26,9 @@ import com.blade.Blade; import com.blade.Const; -import com.blade.context.BladeWebContext; +import com.blade.context.ApplicationWebContext; +import com.blade.exception.BladeException; +import com.blade.exception.NotFoundException; import com.blade.ioc.Ioc; import com.blade.kit.StringKit; import com.blade.route.Route; @@ -66,7 +68,7 @@ public class DispatcherHandler { public DispatcherHandler(ServletContext servletContext, Routers routers) { this.servletContext = servletContext; - this.blade = Blade.me(); + this.blade = Blade.$(); this.ioc = blade.ioc(); this.routeMatcher = new RouteMatcher(routers); this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); @@ -99,7 +101,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo Request request = new ServletRequest(httpRequest); // Init Context - BladeWebContext.setContext(servletContext, request, response); + ApplicationWebContext.init(servletContext, request, response); Route route = routeMatcher.getRoute(method, uri); @@ -111,7 +113,6 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo List befores = routeMatcher.getBefore(uri); boolean result = invokeInterceptor(request, response, befores); if(result){ - // execute this.routeHandle(request, response, route); if(!request.isAbort()){ @@ -125,7 +126,13 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo render404(response, uri); } return; - } catch (Exception e) { + } catch (NotFoundException e) { + LOGGER.warn(e.getMessage()); + DispatchKit.printError(e, 404, response); + } catch (BladeException e) { + LOGGER.error(e.getMessage()); + DispatchKit.printError(e, 500, response); + } catch (Exception e) { DispatchKit.printError(e, 500, response); } return; @@ -186,7 +193,7 @@ private void routeHandle(Request request, Response response, Route route){ request.initPathParams(route.getPath()); // Init context - BladeWebContext.setContext(servletContext, request, response); + ApplicationWebContext.init(servletContext, request, response); if(route.getTargetType() == RouteHandler.class){ RouteHandler routeHandler = (RouteHandler) target; routeHandler.handle(request, response); diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 92223099a..cc87ab7bf 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -29,13 +29,13 @@ import com.blade.Blade; import com.blade.Bootstrap; -import com.blade.context.BladeWebContext; +import com.blade.Const; +import com.blade.context.ApplicationWebContext; import com.blade.ioc.IocApplication; import com.blade.kit.Environment; import com.blade.kit.StringKit; import com.blade.kit.SystemKit; import com.blade.kit.resource.DynamicClassReader; -import com.blade.route.RouteBuilder; /** * Blade Core DispatcherServlet @@ -49,7 +49,7 @@ public class DispatcherServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); - private Blade blade = Blade.me(); + private Blade blade = Blade.$(); private Bootstrap bootstrap; @@ -72,7 +72,6 @@ public void init(ServletConfig config) throws ServletException { servletContext = config.getServletContext(); if(!blade.isInit()){ - LOGGER.info("DispatcherServlet start ..."); LOGGER.info("jdk.version = {}", SystemKit.getJavaInfo().getVersion()); LOGGER.info("user.dir = {}", System.getProperty("user.dir")); LOGGER.info("java.io.tmpdir = {}", System.getProperty("java.io.tmpdir")); @@ -85,11 +84,17 @@ public void init(ServletConfig config) throws ServletException { blade.webRoot(DispatchKit.getWebRoot(servletContext).getPath()); - BladeWebContext.setContext(servletContext); + ApplicationWebContext.init(servletContext); LOGGER.info("blade.webroot = {}", blade.webRoot()); - this.bootstrap = blade.bootstrap(); + this.bootstrap = blade.bootstrap(); + + if(!blade.config().isInit()){ + blade.loadAppConf(Const.APP_PROPERTIES); + blade.config().setEnv(blade.environment()); + } + if(null == bootstrap){ String bootStrapClassName = config.getInitParameter("bootstrap"); if(StringKit.isNotBlank(bootStrapClassName)){ @@ -103,21 +108,24 @@ public void init(Blade blade) { } blade.app(this.bootstrap); } + + // load config + blade.configLoader().loadConfig(); this.bootstrap.init(blade); LOGGER.info("blade.isDev = {}", blade.isDev()); // buiding route - new RouteBuilder(blade).building(); + blade.routeBuilder().building(); // initialization ioc - iocApplication = new IocApplication(blade); + iocApplication = new IocApplication(); iocApplication.init(); blade.init(); - this.bootstrap.contextInitialized(blade); + this.bootstrap.contextInitialized(); dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); @@ -137,9 +145,6 @@ public void init(Blade blade) { protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { httpRequest.setCharacterEncoding(blade.encoding()); httpResponse.setCharacterEncoding(blade.encoding()); - if(!blade.httpCache()){ - DispatchKit.setNoCache(httpResponse); - } dispatcherHandler.handle(httpRequest, httpResponse); } diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index ce26212e5..f667ce7c1 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -23,7 +23,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; -import com.blade.context.BladeWebContext; +import com.blade.context.ApplicationWebContext; import com.blade.kit.Assert; import com.blade.view.ModelAndView; import com.blade.view.template.TemplateEngine; @@ -214,7 +214,7 @@ public Response html(String html) { @Override public Response json(String json) { - Request request = BladeWebContext.request(); + Request request = ApplicationWebContext.request(); String userAgent = request.userAgent(); if (userAgent.contains("MSIE")) { response.setContentType("text/html;charset=utf-8"); @@ -309,7 +309,7 @@ public void redirect(String path) { @Override public void go(String path) { try { - String ctx = BladeWebContext.servletContext().getContextPath(); + String ctx = ApplicationWebContext.servletContext().getContextPath(); String location = Path.fixPath(ctx + path); response.sendRedirect(location); } catch (IOException e) { diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index 03bf8b0e7..db0c77495 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -27,13 +27,9 @@ public class EmbedJettyServer implements EmbedServer { private Environment environment = null; public EmbedJettyServer() { - Environment bladeEnv = Blade.me().environment(); - if(null != bladeEnv){ - environment = bladeEnv.add("jetty.properties"); - } else{ - environment = Environment.load("jetty.properties"); - } - Blade.me().enableServer(true); + Blade.$().loadAppConf("jetty.properties"); + environment = Blade.$().environment(); + Blade.$().enableServer(true); } @Override diff --git a/blade-kit/src/main/java/com/blade/kit/Environment.java b/blade-kit/src/main/java/com/blade/kit/Environment.java index 28947d7a7..3ba6376a8 100644 --- a/blade-kit/src/main/java/com/blade/kit/Environment.java +++ b/blade-kit/src/main/java/com/blade/kit/Environment.java @@ -40,6 +40,10 @@ public class Environment { private Map envMap = new HashMap(20); + public Environment() { + + } + public Environment(String confPath){ this.envMap = loadMap(confPath); } diff --git a/pom.xml b/pom.xml index 2fe65f3d3..58a15880b 100644 --- a/pom.xml +++ b/pom.xml @@ -14,9 +14,9 @@ 1.6 1.6 UTF-8 - 1.6.4 + 1.6.5 1.3.1 - 0.0.2 + 0.0.3 3.0.1 4.12 1.7.21 From f0e167ab0eed21dd650ec6030fc955f6cdf58c70 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 30 Aug 2016 18:38:55 +0800 Subject: [PATCH 461/545] add asm and fix some bug --- blade-core/pom.xml | 6 + blade-core/src/main/java/com/blade/Blade.java | 16 +- .../com/blade/annotation/PathVariable.java | 4 +- .../com/blade/annotation/RequestParam.java | 2 +- .../main/java/com/blade/annotation/Route.java | 9 +- .../src/main/java/com/blade/aop/Aop.java | 60 + .../main/java/com/blade/aop/AopConfig.java | 22 + .../main/java/com/blade/aop/Invocaction.java | 33 + .../src/main/java/com/blade/aop/Log.java | 14 + .../java/com/blade/aop/LogClassVisitor.java | 19 + .../java/com/blade/aop/LogMethodVisitor.java | 28 + .../java/com/blade/aop/MethodInterceptor.java | 9 + .../java/com/blade/aop/MyClassLoader.java | 11 + .../src/main/java/com/blade/asm/AsmKit.java | 97 + .../java/com/blade/config/ConfigLoader.java | 12 +- .../exception/MethodInvokeException.java | 28 + .../src/main/java/com/blade/ioc/Ioc.java | 2 +- .../src/main/java/com/blade/ioc/IocKit.java | 17 - .../main/java/com/blade/ioc/SimpleIoc.java | 21 +- .../java/com/blade/route/RouteBuilder.java | 13 +- .../java/com/blade/view/ModelAndView.java | 4 + .../com/blade/view/handle/MethodArgument.java | 140 + .../blade/view/handle/RouteViewHandler.java | 159 +- .../blade/view/template/DefaultEngine.java | 78 + .../java/com/blade/web/DispatcherServlet.java | 2 +- .../org/objectweb/asm/AnnotationVisitor.java | 169 + .../org/objectweb/asm/AnnotationWriter.java | 371 +++ .../java/org/objectweb/asm/Attribute.java | 255 ++ .../java/org/objectweb/asm/ByteVector.java | 339 ++ .../java/org/objectweb/asm/ClassReader.java | 2507 ++++++++++++++ .../java/org/objectweb/asm/ClassVisitor.java | 320 ++ .../java/org/objectweb/asm/ClassWriter.java | 1811 ++++++++++ .../main/java/org/objectweb/asm/Context.java | 145 + .../src/main/java/org/objectweb/asm/Edge.java | 75 + .../java/org/objectweb/asm/FieldVisitor.java | 150 + .../java/org/objectweb/asm/FieldWriter.java | 329 ++ .../main/java/org/objectweb/asm/Frame.java | 1462 +++++++++ .../main/java/org/objectweb/asm/Handle.java | 222 ++ .../main/java/org/objectweb/asm/Handler.java | 121 + .../src/main/java/org/objectweb/asm/Item.java | 313 ++ .../main/java/org/objectweb/asm/Label.java | 565 ++++ .../java/org/objectweb/asm/MethodVisitor.java | 881 +++++ .../java/org/objectweb/asm/MethodWriter.java | 2915 +++++++++++++++++ .../main/java/org/objectweb/asm/Opcodes.java | 361 ++ .../src/main/java/org/objectweb/asm/Type.java | 896 +++++ .../main/java/org/objectweb/asm/TypePath.java | 196 ++ .../java/org/objectweb/asm/TypeReference.java | 452 +++ blade-kit/pom.xml | 2 +- .../com/blade/kit/reflect/ReflectKit.java | 58 + pom.xml | 3 +- 50 files changed, 15513 insertions(+), 211 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/aop/Aop.java create mode 100644 blade-core/src/main/java/com/blade/aop/AopConfig.java create mode 100644 blade-core/src/main/java/com/blade/aop/Invocaction.java create mode 100644 blade-core/src/main/java/com/blade/aop/Log.java create mode 100644 blade-core/src/main/java/com/blade/aop/LogClassVisitor.java create mode 100644 blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java create mode 100644 blade-core/src/main/java/com/blade/aop/MethodInterceptor.java create mode 100644 blade-core/src/main/java/com/blade/aop/MyClassLoader.java create mode 100644 blade-core/src/main/java/com/blade/asm/AsmKit.java create mode 100644 blade-core/src/main/java/com/blade/exception/MethodInvokeException.java create mode 100644 blade-core/src/main/java/com/blade/view/handle/MethodArgument.java create mode 100644 blade-core/src/main/java/com/blade/view/template/DefaultEngine.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/AnnotationVisitor.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/AnnotationWriter.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/Attribute.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/ByteVector.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/ClassReader.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/ClassVisitor.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/ClassWriter.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/Context.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/Edge.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/FieldVisitor.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/FieldWriter.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/Frame.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/Handle.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/Handler.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/Item.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/Label.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/MethodVisitor.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/MethodWriter.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/Opcodes.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/Type.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/TypePath.java create mode 100644 blade-core/src/main/java/org/objectweb/asm/TypeReference.java diff --git a/blade-core/pom.xml b/blade-core/pom.xml index d6e84d747..612ccb1e8 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -27,6 +27,12 @@ slf4j-log4j12 + + org.ow2.asm + asm + ${asm.version} + + com.bladejava blade-kit diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 852980f58..24ecab84d 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Set; +import com.blade.aop.Aop; import com.blade.config.ApplicationConfig; import com.blade.config.BaseConfig; import com.blade.config.ConfigLoader; @@ -39,7 +40,7 @@ import com.blade.route.RouteHandler; import com.blade.route.Routers; import com.blade.route.loader.ClassPathRouteLoader; -import com.blade.view.template.JspEngine; +import com.blade.view.template.DefaultEngine; import com.blade.view.template.TemplateEngine; import com.blade.web.http.HttpMethod; @@ -49,7 +50,7 @@ * @author biezhi * @since 1.0 */ -public class Blade { +public final class Blade { // blade initialize private boolean isInit = false; @@ -89,14 +90,17 @@ public class Blade { // config loader private ConfigLoader configLoader; + + private Aop aop; private Blade() { this.environment = new Environment(); this.applicationConfig = new ApplicationConfig(); - this.templateEngine = new JspEngine(); + this.templateEngine = new DefaultEngine(); this.plugins = new HashSet>(); this.routeBuilder = new RouteBuilder(this.routers); this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); + this.aop = new Aop(); } static final class BladeHolder { @@ -151,7 +155,11 @@ public void init() { this.isInit = true; } } - + + public Aop aop(){ + return this.aop; + } + /** * @return return route manager */ diff --git a/blade-core/src/main/java/com/blade/annotation/PathVariable.java b/blade-core/src/main/java/com/blade/annotation/PathVariable.java index 3edb7e5b8..dc6f04f3d 100644 --- a/blade-core/src/main/java/com/blade/annotation/PathVariable.java +++ b/blade-core/src/main/java/com/blade/annotation/PathVariable.java @@ -10,7 +10,7 @@ @Retention(RetentionPolicy.RUNTIME) @Documented public @interface PathVariable { - - String value(); + + String value() default ""; } diff --git a/blade-core/src/main/java/com/blade/annotation/RequestParam.java b/blade-core/src/main/java/com/blade/annotation/RequestParam.java index 6de54e133..ebb7167d6 100644 --- a/blade-core/src/main/java/com/blade/annotation/RequestParam.java +++ b/blade-core/src/main/java/com/blade/annotation/RequestParam.java @@ -11,7 +11,7 @@ @Documented public @interface RequestParam { - String value(); + String value() default ""; boolean required() default true; diff --git a/blade-core/src/main/java/com/blade/annotation/Route.java b/blade-core/src/main/java/com/blade/annotation/Route.java index 04eb53542..a009f9c16 100644 --- a/blade-core/src/main/java/com/blade/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/annotation/Route.java @@ -49,16 +49,11 @@ /** * @return Request url */ - String value() default "/"; + String[] value() default {"/"}; /** * @return Request HttpMethod */ HttpMethod method() default HttpMethod.ALL; - - /** - * @return Multiple requests - */ - String[] values() default {}; - + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/Aop.java b/blade-core/src/main/java/com/blade/aop/Aop.java new file mode 100644 index 000000000..83e627a58 --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/Aop.java @@ -0,0 +1,60 @@ +package com.blade.aop; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; + +import com.blade.kit.reflect.ReflectKit; + +public class Aop { + + private Set packages = new HashSet(); + + public Aop() { + packages.add("com.javachina.controller.api"); + } + + public void addPackage(AopConfig aopConfig){ + packages.addAll(aopConfig.getPackages()); + } + + public void addPackage(String packageName){ + packages.add(packageName); + } + + private Map maps = new HashMap(); + + public Object createBean(Class clazz) { + try { + String clsasName = clazz.getName(); + if(null == maps.get(clsasName)){ + String packageName = clazz.getPackage().getName(); + if (packages.contains(packageName)) { + ClassReader cr = new ClassReader(clazz.getName()); + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + cr.accept(new LogClassVisitor(cw), ClassReader.SKIP_DEBUG); + Object value = new MyClassLoader().defineClassForName(clazz.getName(), cw.toByteArray()).newInstance(); + maps.put(clsasName, value); + return value; + } + Object value = ReflectKit.newInstance(clazz); + maps.put(clsasName, value); + return value; + } + return maps.get(clsasName); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/blade-core/src/main/java/com/blade/aop/AopConfig.java b/blade-core/src/main/java/com/blade/aop/AopConfig.java new file mode 100644 index 000000000..1e6673992 --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/AopConfig.java @@ -0,0 +1,22 @@ +package com.blade.aop; + +import java.util.HashSet; +import java.util.Set; + +public final class AopConfig { + + private Set aopPackages = new HashSet(); + + public AopConfig() { + + } + + public void addPackage(String packageName) { + aopPackages.add(packageName); + } + + public Set getPackages() { + return aopPackages; + } + +} diff --git a/blade-core/src/main/java/com/blade/aop/Invocaction.java b/blade-core/src/main/java/com/blade/aop/Invocaction.java new file mode 100644 index 000000000..8ff6cb725 --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/Invocaction.java @@ -0,0 +1,33 @@ +package com.blade.aop; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import com.blade.exception.MethodInvokeException; +import com.blade.kit.reflect.ReflectKit; + +public class Invocaction { + + private Object target; + private Method method; + private Object[] args; + + public Invocaction(Object target, Method method, Object[] args) { + this.target = target; + this.method = method; + this.args = args; + } + + public Object invoke() throws MethodInvokeException{ + try { + return ReflectKit.invokeMehod(this.target, method, args); + } catch (IllegalAccessException e) { + throw new MethodInvokeException(e); + } catch (IllegalArgumentException e) { + throw new MethodInvokeException(e); + } catch (InvocationTargetException e) { + throw new MethodInvokeException(e); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/aop/Log.java b/blade-core/src/main/java/com/blade/aop/Log.java new file mode 100644 index 000000000..5221524e0 --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/Log.java @@ -0,0 +1,14 @@ +package com.blade.aop; + +public class Log +{ + public static void startLog() + { + System.out.println("start log ..."); + } + + public static void endLog() + { + System.out.println("end log ..."); + } +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java b/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java new file mode 100644 index 000000000..47d21db4a --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java @@ -0,0 +1,19 @@ +package com.blade.aop; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class LogClassVisitor extends ClassVisitor { + + public LogClassVisitor(ClassVisitor cv) { + super(Opcodes.ASM5, cv); + } + + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + if ("oper".equals(name)) { + return new LogMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions)); + } + return super.visitMethod(access, name, desc, signature, exceptions); + } +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java b/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java new file mode 100644 index 000000000..115b67445 --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java @@ -0,0 +1,28 @@ +package com.blade.aop; + +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class LogMethodVisitor extends MethodVisitor { + public LogMethodVisitor(MethodVisitor mv) { + super(Opcodes.ASM4, mv); + } + + public void visitCode() { + /** + * 方法执行之前植入代码 + */ + super.visitMethodInsn(Opcodes.INVOKESTATIC, "com/blade/aop/Log", "startLog", "()V", false); + super.visitCode(); + } + + public void visitInsn(int opcode) { + if (opcode == Opcodes.RETURN) { + /** + * 方法return之前,植入代码 + */ + super.visitMethodInsn(Opcodes.INVOKESTATIC, "com/blade/aop/Log", "endLog", "()V", false); + } + super.visitInsn(opcode); + } +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/MethodInterceptor.java b/blade-core/src/main/java/com/blade/aop/MethodInterceptor.java new file mode 100644 index 000000000..025f36ac3 --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/MethodInterceptor.java @@ -0,0 +1,9 @@ +package com.blade.aop; + +public interface MethodInterceptor { + + void config(Aop aop); + + Object doInvoke(Invocaction method); + +} diff --git a/blade-core/src/main/java/com/blade/aop/MyClassLoader.java b/blade-core/src/main/java/com/blade/aop/MyClassLoader.java new file mode 100644 index 000000000..d90dfa9e3 --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/MyClassLoader.java @@ -0,0 +1,11 @@ +package com.blade.aop; +public class MyClassLoader extends ClassLoader { + public MyClassLoader() { + super(Thread.currentThread().getContextClassLoader()); + } + + public Class defineClassForName(String name, byte[] data) { + return this.defineClass(name, data, 0, data.length); + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/asm/AsmKit.java b/blade-core/src/main/java/com/blade/asm/AsmKit.java new file mode 100644 index 000000000..22f6b343f --- /dev/null +++ b/blade-core/src/main/java/com/blade/asm/AsmKit.java @@ -0,0 +1,97 @@ +package com.blade.asm; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +public final class AsmKit { + + /** + * + *

+ * 比较参数类型是否一致 + *

+ * + * @param types + * asm的类型({@link Type}) + * @param clazzes + * java 类型({@link Class}) + * @return + */ + private static boolean sameType(Type[] types, Class[] clazzes) { + // 个数不同 + if (types.length != clazzes.length) { + return false; + } + + for (int i = 0; i < types.length; i++) { + if (!Type.getType(clazzes[i]).equals(types[i])) { + return false; + } + } + return true; + } + + /** + * + *

+ * 获取方法的参数名 + *

+ * + * @param m + * @return + */ + public static String[] getMethodParamNames(final Method m) { + final String[] paramNames = new String[m.getParameterTypes().length]; + final String n = m.getDeclaringClass().getName(); + ClassReader cr = null; + try { + cr = new ClassReader(n); + } catch (IOException e) { + throw new RuntimeException(e); + } + cr.accept(new ClassVisitor(Opcodes.ASM4) { + @Override + public MethodVisitor visitMethod(final int access, + final String name, final String desc, + final String signature, final String[] exceptions) { + final Type[] args = Type.getArgumentTypes(desc); + // 方法名相同并且参数个数相同 + if (!name.equals(m.getName()) + || !sameType(args, m.getParameterTypes())) { + return super.visitMethod(access, name, desc, signature, + exceptions); + } + MethodVisitor v = super.visitMethod(access, name, desc, + signature, exceptions); + return new MethodVisitor(Opcodes.ASM4, v) { + @Override + public void visitLocalVariable(String name, String desc, + String signature, Label start, Label end, int index) { + int i = index - 1; + // 如果是静态方法,则第一就是参数 + // 如果不是静态方法,则第一个是"this",然后才是方法的参数 + if (Modifier.isStatic(m.getModifiers())) { + i = index; + } + if (i >= 0 && i < paramNames.length) { + paramNames[i] = name; + } + super.visitLocalVariable(name, desc, signature, start, + end, index); + } + + }; + } + }, 0); + return paramNames; + } + +} diff --git a/blade-core/src/main/java/com/blade/config/ConfigLoader.java b/blade-core/src/main/java/com/blade/config/ConfigLoader.java index daa63bc4d..1ea9bd5a1 100644 --- a/blade-core/src/main/java/com/blade/config/ConfigLoader.java +++ b/blade-core/src/main/java/com/blade/config/ConfigLoader.java @@ -75,15 +75,9 @@ public void loadConfig() { public void addConfig(Class clazz) throws ConfigException { if (!Modifier.isAbstract(clazz.getModifiers())) { - try { - BaseConfig baseConfig = (BaseConfig) ReflectKit.newInstance(clazz); - baseConfig.config(applicationConfig); - ioc.addBean(baseConfig); - } catch (InstantiationException e) { - throw new ConfigException(e); - } catch (IllegalAccessException e) { - throw new ConfigException(e); - } + Object bean = ioc.addBean(clazz); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(applicationConfig); } } diff --git a/blade-core/src/main/java/com/blade/exception/MethodInvokeException.java b/blade-core/src/main/java/com/blade/exception/MethodInvokeException.java new file mode 100644 index 000000000..897356736 --- /dev/null +++ b/blade-core/src/main/java/com/blade/exception/MethodInvokeException.java @@ -0,0 +1,28 @@ +package com.blade.exception; + +public class MethodInvokeException extends BladeException { + + private static final long serialVersionUID = 1L; + + public MethodInvokeException() { + super(); + } + + public MethodInvokeException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public MethodInvokeException(String message, Throwable cause) { + super(message, cause); + } + + public MethodInvokeException(String message) { + super(message); + } + + public MethodInvokeException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/ioc/Ioc.java b/blade-core/src/main/java/com/blade/ioc/Ioc.java index f1546130a..e7ad38193 100644 --- a/blade-core/src/main/java/com/blade/ioc/Ioc.java +++ b/blade-core/src/main/java/com/blade/ioc/Ioc.java @@ -32,7 +32,7 @@ public interface Ioc { void addBean(Object bean); - void addBean(Class type); + Object addBean(Class type); void addBean(String name, Object bean); diff --git a/blade-core/src/main/java/com/blade/ioc/IocKit.java b/blade-core/src/main/java/com/blade/ioc/IocKit.java index fffc46a6f..00a498633 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocKit.java +++ b/blade-core/src/main/java/com/blade/ioc/IocKit.java @@ -77,21 +77,4 @@ public static void injection(Ioc ioc, BeanDefine beanDefine) { } } - /** - * Get bean according to BeanDefine - * - * @param ioc ioc container - * @param beanDefine beandefine object - * @return bean object - */ - /*public static Object getBean(Ioc ioc, BeanDefine beanDefine) { - ClassDefine classDefine = ClassDefine.create(beanDefine.getType()); - List fieldInjectors = IocKit.getInjectFields(ioc, classDefine); - Object bean = beanDefine.getBean(); - for (FieldInjector fieldInjector : fieldInjectors) { - fieldInjector.injection(bean); - } - return bean; - }*/ - } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java index f64ef38c7..82aa7b30c 100644 --- a/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java @@ -117,22 +117,22 @@ public void addBean(String name, BeanDefine beanDefine) { * Register @Component marked objects */ @Override - public void addBean(Class type) { - addBean(type, true); + public Object addBean(Class type) { + return addBean(type, true); } /** * Register @Component marked objects */ - public void addBean(Class type, boolean singleton) { + public Object addBean(Class type, boolean singleton) { Assert.notNull(type); - addBean(type.getName(), type, singleton); + return addBean(type.getName(), type, singleton); } /** * Register @Component marked objects */ - public void addBean(String name, Class beanClass, boolean singleton) { + public Object addBean(String name, Class beanClass, boolean singleton) { Assert.notNull(name); Assert.notNull(beanClass); @@ -157,9 +157,13 @@ public void addBean(String name, Class beanClass, boolean singleton) { this.addBean(interfaceClazz.getName(), beanDefine); } } + + return beanDefine.getBean(); } private BeanDefine getBeanDefine(Class beanClass, boolean singleton) { +// Object object = Blade.$().aop().createBean(beanClass); +// return new BeanDefine(object, beanClass, singleton); try { Object object = beanClass.newInstance(); return new BeanDefine(object, beanClass, singleton); @@ -174,7 +178,12 @@ private BeanDefine getBeanDefine(Class beanClass, boolean singleton) { @Override public T getBean(Class type) { Object bean = this.getBean(type.getName()); - return type.cast(bean); + try { + return type.cast(bean); + } catch (Exception e) { + e.printStackTrace(); + } + return null; } @Override diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index 89ce25c79..a9624a7b7 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -170,21 +170,12 @@ public void addRouter(final Class router){ final String suffix = router.getAnnotation(Controller.class).suffix(); for (Method method : methods) { - Route mapping = method.getAnnotation(Route.class); - //route method if (null != mapping) { - - // build - String path = getRoutePath(mapping.value(), nameSpace, suffix); - - HttpMethod methodType = mapping.method(); - - buildRoute(router, method, path, methodType); - // build multiple route - String[] paths = mapping.values(); + HttpMethod methodType = mapping.method(); + String[] paths = mapping.value(); if(null != paths && paths.length > 0){ for(String value : paths){ String pathV = getRoutePath(value, nameSpace, suffix); diff --git a/blade-core/src/main/java/com/blade/view/ModelAndView.java b/blade-core/src/main/java/com/blade/view/ModelAndView.java index a2e8ca20c..20b8b5ebb 100644 --- a/blade-core/src/main/java/com/blade/view/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/view/ModelAndView.java @@ -37,6 +37,10 @@ public class ModelAndView { */ private String view; + public ModelAndView() { + + } + /** * Create an empty view * diff --git a/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java new file mode 100644 index 000000000..7e330245f --- /dev/null +++ b/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java @@ -0,0 +1,140 @@ +package com.blade.view.handle; + +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; + +import com.blade.annotation.PathVariable; +import com.blade.annotation.RequestParam; +import com.blade.asm.AsmKit; +import com.blade.exception.BladeException; +import com.blade.exception.NotFoundException; +import com.blade.kit.StringKit; +import com.blade.view.ModelAndView; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.multipart.FileItem; + +public final class MethodArgument { + + public static Object[] getArgs(Request request, Response response, Method actionMethod) throws BladeException{ + Parameter[] parameters = actionMethod.getParameters(); + Object[] args = new Object[parameters.length]; + + try { + actionMethod.setAccessible(true); + String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); + + for (int i = 0, len = parameters.length; i < len; i++) { + + Class argType = parameters[i].getType(); + if (argType.getName().equals(Request.class.getName())) { + args[i] = request; + continue; + } + + if (argType.getName().equals(Response.class.getName())) { + args[i] = response; + continue; + } + + if (argType.getName().equals(ModelAndView.class.getName())) { + args[i] = new ModelAndView(); + continue; + } + + if(argType.getName().equals(FileItem.class.getName())){ + args[i] = new ModelAndView(); + continue; + } + + RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); + if (null != requestParam) { + String paramName = requestParam.value(); + String val = request.query(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.query(paramName); + } else { + if (StringKit.isBlank(val)) { + throw new NotFoundException("request param [" + paramName + "] is null"); + } + } + args[i] = getRequestParam(argType, val, requestParam.defaultValue()); + continue; + } + + PathVariable pathVariable = parameters[i].getAnnotation(PathVariable.class); + if (null != pathVariable) { + String paramName = pathVariable.value(); + String val = request.param(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.param(paramName); + } else { + if (StringKit.isBlank(val)) { + throw new NotFoundException("path param [" + paramName + "] is null"); + } + } + args[i] = getRequestParam(argType, val, null); + continue; + } + } + return args; + } catch (BladeException e) { + throw e; + } + } + + private static Object getRequestParam(Class parameterType, String val, String defaultValue) { + Object result = null; + if (parameterType.equals(String.class)) { + if (StringKit.isNotBlank(val)) { + result = val; + } else { + if (null != defaultValue) { + result = defaultValue; + } + } + } else if (parameterType.equals(Integer.class)) { + if (StringKit.isNotBlank(val)) { + result = Integer.parseInt(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Integer.parseInt(defaultValue); + } + } + } else if (parameterType.equals(int.class)) { + if (StringKit.isNotBlank(val)) { + result = Integer.parseInt(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Integer.parseInt(defaultValue); + } else { + result = 0; + } + } + } else if (parameterType.equals(Long.class)) { + if (StringKit.isNotBlank(val)) { + result = Long.parseLong(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Long.parseLong(defaultValue); + } + } + } else if (parameterType.equals(long.class)) { + if (StringKit.isNotBlank(val)) { + result = Long.parseLong(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Long.parseLong(defaultValue); + } else { + result = 0L; + } + } + } + return result; + } + +} diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index bc880c8d4..9ad01ceff 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -1,14 +1,12 @@ package com.blade.view.handle; import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import com.blade.annotation.PathVariable; -import com.blade.annotation.RequestParam; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.exception.BladeException; -import com.blade.exception.NotFoundException; import com.blade.ioc.Ioc; -import com.blade.kit.StringKit; import com.blade.kit.reflect.ReflectKit; import com.blade.route.Route; import com.blade.view.ModelAndView; @@ -18,149 +16,13 @@ public class RouteViewHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(RouteViewHandler.class); + private Ioc ioc; + public RouteViewHandler(Ioc ioc) { this.ioc = ioc; } - - private Object getPathParam(Class parameterType, String val, Request request) { - Object result = null; - if (parameterType.equals(String.class)) { - result = request.param(val); - } else if (parameterType.equals(Integer.class) || parameterType.equals(int.class)) { - result = request.paramAsInt(val); - } else if (parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)) { - result = request.paramAsBool(val); - } else if (parameterType.equals(Long.class) || parameterType.equals(long.class)) { - result = request.paramAsLong(val); - } - return result; - } - - private Object getRequestParam(Class parameterType, String val, String defaultValue, Request request) { - Object result = null; - if (parameterType.equals(String.class)) { - String value = request.query(val); - if (null == value && null != defaultValue) { - result = defaultValue; - } else { - result = value; - } - } else if (parameterType.equals(Integer.class) || parameterType.equals(int.class)) { - Integer value = request.queryAsInt(val); - if (null == value && StringKit.isNotBlank(defaultValue)) { - result = Integer.valueOf(defaultValue); - } else { - result = value; - } - } else if (parameterType.equals(Boolean.class) || parameterType.equals(boolean.class)) { - Boolean value = request.queryAsBool(val); - if (null == value && StringKit.isNotBlank(defaultValue)) { - result = Boolean.valueOf(defaultValue); - } else { - result = value; - } - } else if (parameterType.equals(Long.class) || parameterType.equals(long.class)) { - Long value = request.queryAsLong(val); - if (null == value && StringKit.isNotBlank(defaultValue)) { - result = Long.valueOf(defaultValue); - } else { - result = value; - } - } - return result; - } - - /** - * Parameters in the method - * - * @param request - * Request object for injection to the method parameter list - * @param response - * Response object for injection to the method parameter list - * @param actionMethod - * Execute method - * @return Return the generated array of parameters - */ - public Object[] getArgs(Request request, Response response, Method actionMethod) throws NotFoundException { - - Class[] parameterTypes = actionMethod.getParameterTypes(); - - int len = parameterTypes.length; - Object[] args = new Object[len]; - actionMethod.setAccessible(true); - - Parameter[] parameters = actionMethod.getParameters(); - int pos = 0; - try { - for (Parameter parameter : parameters) { - - if (parameter.getType().getName().equals(Request.class.getName())) { - args[pos] = request; - } - - if (parameter.getType().getName().equals(Response.class.getName())) { - args[pos] = response; - } - - RequestParam requestParam = parameter.getAnnotation(RequestParam.class); - if (null != requestParam) { - String paramName = requestParam.value(); - String val = request.query(paramName); - if(StringKit.isBlank(val)){ - throw new NotFoundException("request param ["+ paramName +"] is null"); - } - Object value = getRequestParam(parameter.getType(), val, requestParam.defaultValue(), request); - args[pos] = value; - } - - PathVariable pathVariable = parameter.getAnnotation(PathVariable.class); - if (null != pathVariable) { - String paramName = pathVariable.value(); - String val = request.param(paramName); - if(StringKit.isBlank(val)){ - throw new NotFoundException("path param ["+ paramName +"] is null"); - } - Object value = getRequestParam(parameter.getType(), val, requestParam.defaultValue(), request); - args[pos] = value; - } - pos++; - } - } catch (BladeException e) { - throw e; - } - - /* - * int i = 0; if(parameterAnnotations.length > 0){ for (Annotation[] - * annotations : parameterAnnotations) { Class parameterType = - * parameterTypes[i]; for (Annotation annotation : annotations) { - * Class anType = annotation.annotationType(); - * if(anType.equals(PathVariable.class)){ PathVariable pathVariable = - * (PathVariable) annotation; String val = pathVariable.value(); Object - * value = getPathParam(parameterType, val, request); args[i] = value; } - * else if(anType.equals(RequestParam.class)) { RequestParam - * requestParam = (RequestParam) annotation; String val = - * requestParam.value(); Object value = getRequestParam(parameterType, - * val, requestParam.defaultValue(), request); args[i] = value; } } i++; - * } } - * - * for(i=0; i paramTypeClazz = parameterTypes[i]; - * if(paramTypeClazz.equals(Request.class)){ args[i] = request; } else - * if(paramTypeClazz.equals(Response.class)){ args[i] = response; } else - * if(paramTypeClazz.equals(Session.class)){ args[i] = - * request.session(); } else if(paramTypeClazz.equals(ModelMap.class)){ - * args[i] = new ModelMap(request); } else - * if(paramTypeClazz.equals(HttpServletRequest.class)){ args[i] = - * request.raw(); } else - * if(paramTypeClazz.equals(HttpServletResponse.class)){ args[i] = - * response.raw(); } else if(paramTypeClazz.equals(HttpSession.class)){ - * args[i] = request.raw().getSession(); } else - * if(paramTypeClazz.equals(FileItem.class)){ FileItem[] fileItems = - * request.files(); if(null != fileItems && fileItems.length > 0){ - * args[i] = fileItems[0]; } } } - */ - return args; - } public void handle(Request request, Response response, Route route) throws BladeException { Method actionMethod = route.getAction(); @@ -171,7 +33,7 @@ public void handle(Request request, Response response, Route route) throws Blade try { Object returnParam = null; if (len > 0) { - Object[] args = getArgs(request, response, actionMethod); + Object[] args = MethodArgument.getArgs(request, response, actionMethod); returnParam = ReflectKit.invokeMehod(target, actionMethod, args); } else { returnParam = ReflectKit.invokeMehod(target, actionMethod); @@ -189,6 +51,7 @@ public void handle(Request request, Response response, Route route) throws Blade } catch (BladeException e) { throw e; } catch (Exception e) { + LOGGER.error("route view error", e); request.abort(); DispatchKit.printError(e, 500, response); } @@ -211,7 +74,7 @@ public boolean intercept(Request request, Response response, Route route) { try { Object returnParam = null; if (len > 0) { - Object[] args = getArgs(request, response, actionMethod); + Object[] args = MethodArgument.getArgs(request, response, actionMethod); returnParam = ReflectKit.invokeMehod(target, actionMethod, args); } else { returnParam = ReflectKit.invokeMehod(target, actionMethod); @@ -233,8 +96,4 @@ public boolean intercept(Request request, Response response, Route route) { return false; } - private void setValue(Object object, Class type, Object value) { - - } - } diff --git a/blade-core/src/main/java/com/blade/view/template/DefaultEngine.java b/blade-core/src/main/java/com/blade/view/template/DefaultEngine.java new file mode 100644 index 000000000..f79d85a8d --- /dev/null +++ b/blade-core/src/main/java/com/blade/view/template/DefaultEngine.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.ApplicationWebContext; +import com.blade.view.ModelAndView; + + +/** + * JSP Render, Default Render + * + * @author biezhi + * @since 1.0 + */ +public final class DefaultEngine implements TemplateEngine { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultEngine.class); + + private String viewPath = "/WEB-INF/"; + + public DefaultEngine() { + } + + public DefaultEngine(String viewPath) { + this.viewPath = viewPath; + } + + @Override + public void render(ModelAndView modelAndView, Writer writer) { + HttpServletRequest servletRequest = ApplicationWebContext.request().raw(); + HttpServletResponse servletResponse = ApplicationWebContext.response().raw(); + + try { + Map model = modelAndView.getModel(); + String realPath = viewPath + modelAndView.getView(); + + if (null != model && !model.isEmpty()) { + Set keys = model.keySet(); + for (String key : keys) { + servletRequest.setAttribute(key, model.get(key)); + } + } + servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); + } catch (ServletException e) { + e.printStackTrace(); + LOGGER.error("", e); + } catch (IOException e) { + e.printStackTrace(); + LOGGER.error("", e); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index cc87ab7bf..f29271f87 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -108,7 +108,7 @@ public void init(Blade blade) { } blade.app(this.bootstrap); } - + // load config blade.configLoader().loadConfig(); diff --git a/blade-core/src/main/java/org/objectweb/asm/AnnotationVisitor.java b/blade-core/src/main/java/org/objectweb/asm/AnnotationVisitor.java new file mode 100644 index 000000000..b64408372 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/AnnotationVisitor.java @@ -0,0 +1,169 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * A visitor to visit a Java annotation. The methods of this class must be + * called in the following order: ( visit | visitEnum | + * visitAnnotation | visitArray )* visitEnd. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public abstract class AnnotationVisitor { + + /** + * The ASM API version implemented by this visitor. The value of this field + * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + */ + protected final int api; + + /** + * The annotation visitor to which this visitor must delegate method calls. + * May be null. + */ + protected AnnotationVisitor av; + + /** + * Constructs a new {@link AnnotationVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + */ + public AnnotationVisitor(final int api) { + this(api, null); + } + + /** + * Constructs a new {@link AnnotationVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param av + * the annotation visitor to which this visitor must delegate + * method calls. May be null. + */ + public AnnotationVisitor(final int api, final AnnotationVisitor av) { + if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { + throw new IllegalArgumentException(); + } + this.api = api; + this.av = av; + } + + /** + * Visits a primitive value of the annotation. + * + * @param name + * the value name. + * @param value + * the actual value, whose type must be {@link Byte}, + * {@link Boolean}, {@link Character}, {@link Short}, + * {@link Integer} , {@link Long}, {@link Float}, {@link Double}, + * {@link String} or {@link Type} or OBJECT or ARRAY sort. This + * value can also be an array of byte, boolean, short, char, int, + * long, float or double values (this is equivalent to using + * {@link #visitArray visitArray} and visiting each array element + * in turn, but is more convenient). + */ + public void visit(String name, Object value) { + if (av != null) { + av.visit(name, value); + } + } + + /** + * Visits an enumeration value of the annotation. + * + * @param name + * the value name. + * @param desc + * the class descriptor of the enumeration class. + * @param value + * the actual enumeration value. + */ + public void visitEnum(String name, String desc, String value) { + if (av != null) { + av.visitEnum(name, desc, value); + } + } + + /** + * Visits a nested annotation value of the annotation. + * + * @param name + * the value name. + * @param desc + * the class descriptor of the nested annotation class. + * @return a visitor to visit the actual nested annotation value, or + * null if this visitor is not interested in visiting this + * nested annotation. The nested annotation value must be fully + * visited before calling other methods on this annotation + * visitor. + */ + public AnnotationVisitor visitAnnotation(String name, String desc) { + if (av != null) { + return av.visitAnnotation(name, desc); + } + return null; + } + + /** + * Visits an array value of the annotation. Note that arrays of primitive + * types (such as byte, boolean, short, char, int, long, float or double) + * can be passed as value to {@link #visit visit}. This is what + * {@link ClassReader} does. + * + * @param name + * the value name. + * @return a visitor to visit the actual array value elements, or + * null if this visitor is not interested in visiting these + * values. The 'name' parameters passed to the methods of this + * visitor are ignored. All the array values must be visited + * before calling other methods on this annotation visitor. + */ + public AnnotationVisitor visitArray(String name) { + if (av != null) { + return av.visitArray(name); + } + return null; + } + + /** + * Visits the end of the annotation. + */ + public void visitEnd() { + if (av != null) { + av.visitEnd(); + } + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/AnnotationWriter.java b/blade-core/src/main/java/org/objectweb/asm/AnnotationWriter.java new file mode 100644 index 000000000..6b95608ac --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/AnnotationWriter.java @@ -0,0 +1,371 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * An {@link AnnotationVisitor} that generates annotations in bytecode form. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +final class AnnotationWriter extends AnnotationVisitor { + + /** + * The class writer to which this annotation must be added. + */ + private final ClassWriter cw; + + /** + * The number of values in this annotation. + */ + private int size; + + /** + * true if values are named, false otherwise. Annotation + * writers used for annotation default and annotation arrays use unnamed + * values. + */ + private final boolean named; + + /** + * The annotation values in bytecode form. This byte vector only contains + * the values themselves, i.e. the number of values must be stored as a + * unsigned short just before these bytes. + */ + private final ByteVector bv; + + /** + * The byte vector to be used to store the number of values of this + * annotation. See {@link #bv}. + */ + private final ByteVector parent; + + /** + * Where the number of values of this annotation must be stored in + * {@link #parent}. + */ + private final int offset; + + /** + * Next annotation writer. This field is used to store annotation lists. + */ + AnnotationWriter next; + + /** + * Previous annotation writer. This field is used to store annotation lists. + */ + AnnotationWriter prev; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link AnnotationWriter}. + * + * @param cw + * the class writer to which this annotation must be added. + * @param named + * true if values are named, false otherwise. + * @param bv + * where the annotation values must be stored. + * @param parent + * where the number of annotation values must be stored. + * @param offset + * where in parent the number of annotation values must + * be stored. + */ + AnnotationWriter(final ClassWriter cw, final boolean named, + final ByteVector bv, final ByteVector parent, final int offset) { + super(Opcodes.ASM5); + this.cw = cw; + this.named = named; + this.bv = bv; + this.parent = parent; + this.offset = offset; + } + + // ------------------------------------------------------------------------ + // Implementation of the AnnotationVisitor abstract class + // ------------------------------------------------------------------------ + + @Override + public void visit(final String name, final Object value) { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + if (value instanceof String) { + bv.put12('s', cw.newUTF8((String) value)); + } else if (value instanceof Byte) { + bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); + } else if (value instanceof Boolean) { + int v = ((Boolean) value).booleanValue() ? 1 : 0; + bv.put12('Z', cw.newInteger(v).index); + } else if (value instanceof Character) { + bv.put12('C', cw.newInteger(((Character) value).charValue()).index); + } else if (value instanceof Short) { + bv.put12('S', cw.newInteger(((Short) value).shortValue()).index); + } else if (value instanceof Type) { + bv.put12('c', cw.newUTF8(((Type) value).getDescriptor())); + } else if (value instanceof byte[]) { + byte[] v = (byte[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('B', cw.newInteger(v[i]).index); + } + } else if (value instanceof boolean[]) { + boolean[] v = (boolean[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index); + } + } else if (value instanceof short[]) { + short[] v = (short[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('S', cw.newInteger(v[i]).index); + } + } else if (value instanceof char[]) { + char[] v = (char[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('C', cw.newInteger(v[i]).index); + } + } else if (value instanceof int[]) { + int[] v = (int[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('I', cw.newInteger(v[i]).index); + } + } else if (value instanceof long[]) { + long[] v = (long[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('J', cw.newLong(v[i]).index); + } + } else if (value instanceof float[]) { + float[] v = (float[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('F', cw.newFloat(v[i]).index); + } + } else if (value instanceof double[]) { + double[] v = (double[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('D', cw.newDouble(v[i]).index); + } + } else { + Item i = cw.newConstItem(value); + bv.put12(".s.IFJDCS".charAt(i.type), i.index); + } + } + + @Override + public void visitEnum(final String name, final String desc, + final String value) { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); + } + + @Override + public AnnotationVisitor visitAnnotation(final String name, + final String desc) { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + // write tag and type, and reserve space for values count + bv.put12('@', cw.newUTF8(desc)).putShort(0); + return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); + } + + @Override + public AnnotationVisitor visitArray(final String name) { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + // write tag, and reserve space for array size + bv.put12('[', 0); + return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); + } + + @Override + public void visitEnd() { + if (parent != null) { + byte[] data = parent.data; + data[offset] = (byte) (size >>> 8); + data[offset + 1] = (byte) size; + } + } + + // ------------------------------------------------------------------------ + // Utility methods + // ------------------------------------------------------------------------ + + /** + * Returns the size of this annotation writer list. + * + * @return the size of this annotation writer list. + */ + int getSize() { + int size = 0; + AnnotationWriter aw = this; + while (aw != null) { + size += aw.bv.length; + aw = aw.next; + } + return size; + } + + /** + * Puts the annotations of this annotation writer list into the given byte + * vector. + * + * @param out + * where the annotations must be put. + */ + void put(final ByteVector out) { + int n = 0; + int size = 2; + AnnotationWriter aw = this; + AnnotationWriter last = null; + while (aw != null) { + ++n; + size += aw.bv.length; + aw.visitEnd(); // in case user forgot to call visitEnd + aw.prev = last; + last = aw; + aw = aw.next; + } + out.putInt(size); + out.putShort(n); + aw = last; + while (aw != null) { + out.putByteArray(aw.bv.data, 0, aw.bv.length); + aw = aw.prev; + } + } + + /** + * Puts the given annotation lists into the given byte vector. + * + * @param panns + * an array of annotation writer lists. + * @param off + * index of the first annotation to be written. + * @param out + * where the annotations must be put. + */ + static void put(final AnnotationWriter[] panns, final int off, + final ByteVector out) { + int size = 1 + 2 * (panns.length - off); + for (int i = off; i < panns.length; ++i) { + size += panns[i] == null ? 0 : panns[i].getSize(); + } + out.putInt(size).putByte(panns.length - off); + for (int i = off; i < panns.length; ++i) { + AnnotationWriter aw = panns[i]; + AnnotationWriter last = null; + int n = 0; + while (aw != null) { + ++n; + aw.visitEnd(); // in case user forgot to call visitEnd + aw.prev = last; + last = aw; + aw = aw.next; + } + out.putShort(n); + aw = last; + while (aw != null) { + out.putByteArray(aw.bv.data, 0, aw.bv.length); + aw = aw.prev; + } + } + } + + /** + * Puts the given type reference and type path into the given bytevector. + * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported. + * + * @param typeRef + * a reference to the annotated type. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param out + * where the type reference and type path must be put. + */ + static void putTarget(int typeRef, TypePath typePath, ByteVector out) { + switch (typeRef >>> 24) { + case 0x00: // CLASS_TYPE_PARAMETER + case 0x01: // METHOD_TYPE_PARAMETER + case 0x16: // METHOD_FORMAL_PARAMETER + out.putShort(typeRef >>> 16); + break; + case 0x13: // FIELD + case 0x14: // METHOD_RETURN + case 0x15: // METHOD_RECEIVER + out.putByte(typeRef >>> 24); + break; + case 0x47: // CAST + case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT + case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT + out.putInt(typeRef); + break; + // case 0x10: // CLASS_EXTENDS + // case 0x11: // CLASS_TYPE_PARAMETER_BOUND + // case 0x12: // METHOD_TYPE_PARAMETER_BOUND + // case 0x17: // THROWS + // case 0x42: // EXCEPTION_PARAMETER + // case 0x43: // INSTANCEOF + // case 0x44: // NEW + // case 0x45: // CONSTRUCTOR_REFERENCE + // case 0x46: // METHOD_REFERENCE + default: + out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8); + break; + } + if (typePath == null) { + out.putByte(0); + } else { + int length = typePath.b[typePath.offset] * 2 + 1; + out.putByteArray(typePath.b, typePath.offset, length); + } + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/Attribute.java b/blade-core/src/main/java/org/objectweb/asm/Attribute.java new file mode 100644 index 000000000..8a2a882f8 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/Attribute.java @@ -0,0 +1,255 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * A non standard class, field, method or code attribute. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public class Attribute { + + /** + * The type of this attribute. + */ + public final String type; + + /** + * The raw value of this attribute, used only for unknown attributes. + */ + byte[] value; + + /** + * The next attribute in this attribute list. May be null. + */ + Attribute next; + + /** + * Constructs a new empty attribute. + * + * @param type + * the type of the attribute. + */ + protected Attribute(final String type) { + this.type = type; + } + + /** + * Returns true if this type of attribute is unknown. The default + * implementation of this method always returns true. + * + * @return true if this type of attribute is unknown. + */ + public boolean isUnknown() { + return true; + } + + /** + * Returns true if this type of attribute is a code attribute. + * + * @return true if this type of attribute is a code attribute. + */ + public boolean isCodeAttribute() { + return false; + } + + /** + * Returns the labels corresponding to this attribute. + * + * @return the labels corresponding to this attribute, or null if + * this attribute is not a code attribute that contains labels. + */ + protected Label[] getLabels() { + return null; + } + + /** + * Reads a {@link #type type} attribute. This method must return a + * new {@link Attribute} object, of type {@link #type type}, + * corresponding to the len bytes starting at the given offset, in + * the given class reader. + * + * @param cr + * the class that contains the attribute to be read. + * @param off + * index of the first byte of the attribute's content in + * {@link ClassReader#b cr.b}. The 6 attribute header bytes, + * containing the type and the length of the attribute, are not + * taken into account here. + * @param len + * the length of the attribute's content. + * @param buf + * buffer to be used to call {@link ClassReader#readUTF8 + * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass} + * or {@link ClassReader#readConst readConst}. + * @param codeOff + * index of the first byte of code's attribute content in + * {@link ClassReader#b cr.b}, or -1 if the attribute to be read + * is not a code attribute. The 6 attribute header bytes, + * containing the type and the length of the attribute, are not + * taken into account here. + * @param labels + * the labels of the method's code, or null if the + * attribute to be read is not a code attribute. + * @return a new {@link Attribute} object corresponding to the given + * bytes. + */ + protected Attribute read(final ClassReader cr, final int off, + final int len, final char[] buf, final int codeOff, + final Label[] labels) { + Attribute attr = new Attribute(type); + attr.value = new byte[len]; + System.arraycopy(cr.b, off, attr.value, 0, len); + return attr; + } + + /** + * Returns the byte array form of this attribute. + * + * @param cw + * the class to which this attribute must be added. This + * parameter can be used to add to the constant pool of this + * class the items that corresponds to this attribute. + * @param code + * the bytecode of the method corresponding to this code + * attribute, or null if this attribute is not a code + * attributes. + * @param len + * the length of the bytecode of the method corresponding to this + * code attribute, or null if this attribute is not a + * code attribute. + * @param maxStack + * the maximum stack size of the method corresponding to this + * code attribute, or -1 if this attribute is not a code + * attribute. + * @param maxLocals + * the maximum number of local variables of the method + * corresponding to this code attribute, or -1 if this attribute + * is not a code attribute. + * @return the byte array form of this attribute. + */ + protected ByteVector write(final ClassWriter cw, final byte[] code, + final int len, final int maxStack, final int maxLocals) { + ByteVector v = new ByteVector(); + v.data = value; + v.length = value.length; + return v; + } + + /** + * Returns the length of the attribute list that begins with this attribute. + * + * @return the length of the attribute list that begins with this attribute. + */ + final int getCount() { + int count = 0; + Attribute attr = this; + while (attr != null) { + count += 1; + attr = attr.next; + } + return count; + } + + /** + * Returns the size of all the attributes in this attribute list. + * + * @param cw + * the class writer to be used to convert the attributes into + * byte arrays, with the {@link #write write} method. + * @param code + * the bytecode of the method corresponding to these code + * attributes, or null if these attributes are not code + * attributes. + * @param len + * the length of the bytecode of the method corresponding to + * these code attributes, or null if these attributes + * are not code attributes. + * @param maxStack + * the maximum stack size of the method corresponding to these + * code attributes, or -1 if these attributes are not code + * attributes. + * @param maxLocals + * the maximum number of local variables of the method + * corresponding to these code attributes, or -1 if these + * attributes are not code attributes. + * @return the size of all the attributes in this attribute list. This size + * includes the size of the attribute headers. + */ + final int getSize(final ClassWriter cw, final byte[] code, final int len, + final int maxStack, final int maxLocals) { + Attribute attr = this; + int size = 0; + while (attr != null) { + cw.newUTF8(attr.type); + size += attr.write(cw, code, len, maxStack, maxLocals).length + 6; + attr = attr.next; + } + return size; + } + + /** + * Writes all the attributes of this attribute list in the given byte + * vector. + * + * @param cw + * the class writer to be used to convert the attributes into + * byte arrays, with the {@link #write write} method. + * @param code + * the bytecode of the method corresponding to these code + * attributes, or null if these attributes are not code + * attributes. + * @param len + * the length of the bytecode of the method corresponding to + * these code attributes, or null if these attributes + * are not code attributes. + * @param maxStack + * the maximum stack size of the method corresponding to these + * code attributes, or -1 if these attributes are not code + * attributes. + * @param maxLocals + * the maximum number of local variables of the method + * corresponding to these code attributes, or -1 if these + * attributes are not code attributes. + * @param out + * where the attributes must be written. + */ + final void put(final ClassWriter cw, final byte[] code, final int len, + final int maxStack, final int maxLocals, final ByteVector out) { + Attribute attr = this; + while (attr != null) { + ByteVector b = attr.write(cw, code, len, maxStack, maxLocals); + out.putShort(cw.newUTF8(attr.type)).putInt(b.length); + out.putByteArray(b.data, 0, b.length); + attr = attr.next; + } + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/ByteVector.java b/blade-core/src/main/java/org/objectweb/asm/ByteVector.java new file mode 100644 index 000000000..9c532be78 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/ByteVector.java @@ -0,0 +1,339 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * A dynamically extensible vector of bytes. This class is roughly equivalent to + * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient. + * + * @author Eric Bruneton + */ +public class ByteVector { + + /** + * The content of this vector. + */ + byte[] data; + + /** + * Actual number of bytes in this vector. + */ + int length; + + /** + * Constructs a new {@link ByteVector ByteVector} with a default initial + * size. + */ + public ByteVector() { + data = new byte[64]; + } + + /** + * Constructs a new {@link ByteVector ByteVector} with the given initial + * size. + * + * @param initialSize + * the initial size of the byte vector to be constructed. + */ + public ByteVector(final int initialSize) { + data = new byte[initialSize]; + } + + /** + * Puts a byte into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param b + * a byte. + * @return this byte vector. + */ + public ByteVector putByte(final int b) { + int length = this.length; + if (length + 1 > data.length) { + enlarge(1); + } + data[length++] = (byte) b; + this.length = length; + return this; + } + + /** + * Puts two bytes into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param b1 + * a byte. + * @param b2 + * another byte. + * @return this byte vector. + */ + ByteVector put11(final int b1, final int b2) { + int length = this.length; + if (length + 2 > data.length) { + enlarge(2); + } + byte[] data = this.data; + data[length++] = (byte) b1; + data[length++] = (byte) b2; + this.length = length; + return this; + } + + /** + * Puts a short into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param s + * a short. + * @return this byte vector. + */ + public ByteVector putShort(final int s) { + int length = this.length; + if (length + 2 > data.length) { + enlarge(2); + } + byte[] data = this.data; + data[length++] = (byte) (s >>> 8); + data[length++] = (byte) s; + this.length = length; + return this; + } + + /** + * Puts a byte and a short into this byte vector. The byte vector is + * automatically enlarged if necessary. + * + * @param b + * a byte. + * @param s + * a short. + * @return this byte vector. + */ + ByteVector put12(final int b, final int s) { + int length = this.length; + if (length + 3 > data.length) { + enlarge(3); + } + byte[] data = this.data; + data[length++] = (byte) b; + data[length++] = (byte) (s >>> 8); + data[length++] = (byte) s; + this.length = length; + return this; + } + + /** + * Puts an int into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param i + * an int. + * @return this byte vector. + */ + public ByteVector putInt(final int i) { + int length = this.length; + if (length + 4 > data.length) { + enlarge(4); + } + byte[] data = this.data; + data[length++] = (byte) (i >>> 24); + data[length++] = (byte) (i >>> 16); + data[length++] = (byte) (i >>> 8); + data[length++] = (byte) i; + this.length = length; + return this; + } + + /** + * Puts a long into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param l + * a long. + * @return this byte vector. + */ + public ByteVector putLong(final long l) { + int length = this.length; + if (length + 8 > data.length) { + enlarge(8); + } + byte[] data = this.data; + int i = (int) (l >>> 32); + data[length++] = (byte) (i >>> 24); + data[length++] = (byte) (i >>> 16); + data[length++] = (byte) (i >>> 8); + data[length++] = (byte) i; + i = (int) l; + data[length++] = (byte) (i >>> 24); + data[length++] = (byte) (i >>> 16); + data[length++] = (byte) (i >>> 8); + data[length++] = (byte) i; + this.length = length; + return this; + } + + /** + * Puts an UTF8 string into this byte vector. The byte vector is + * automatically enlarged if necessary. + * + * @param s + * a String whose UTF8 encoded length must be less than 65536. + * @return this byte vector. + */ + public ByteVector putUTF8(final String s) { + int charLength = s.length(); + if (charLength > 65535) { + throw new IllegalArgumentException(); + } + int len = length; + if (len + 2 + charLength > data.length) { + enlarge(2 + charLength); + } + byte[] data = this.data; + // optimistic algorithm: instead of computing the byte length and then + // serializing the string (which requires two loops), we assume the byte + // length is equal to char length (which is the most frequent case), and + // we start serializing the string right away. During the serialization, + // if we find that this assumption is wrong, we continue with the + // general method. + data[len++] = (byte) (charLength >>> 8); + data[len++] = (byte) charLength; + for (int i = 0; i < charLength; ++i) { + char c = s.charAt(i); + if (c >= '\001' && c <= '\177') { + data[len++] = (byte) c; + } else { + length = len; + return encodeUTF8(s, i, 65535); + } + } + length = len; + return this; + } + + /** + * Puts an UTF8 string into this byte vector. The byte vector is + * automatically enlarged if necessary. The string length is encoded in two + * bytes before the encoded characters, if there is space for that (i.e. if + * this.length - i - 2 >= 0). + * + * @param s + * the String to encode. + * @param i + * the index of the first character to encode. The previous + * characters are supposed to have already been encoded, using + * only one byte per character. + * @param maxByteLength + * the maximum byte length of the encoded string, including the + * already encoded characters. + * @return this byte vector. + */ + ByteVector encodeUTF8(final String s, int i, int maxByteLength) { + int charLength = s.length(); + int byteLength = i; + char c; + for (int j = i; j < charLength; ++j) { + c = s.charAt(j); + if (c >= '\001' && c <= '\177') { + byteLength++; + } else if (c > '\u07FF') { + byteLength += 3; + } else { + byteLength += 2; + } + } + if (byteLength > maxByteLength) { + throw new IllegalArgumentException(); + } + int start = length - i - 2; + if (start >= 0) { + data[start] = (byte) (byteLength >>> 8); + data[start + 1] = (byte) byteLength; + } + if (length + byteLength - i > data.length) { + enlarge(byteLength - i); + } + int len = length; + for (int j = i; j < charLength; ++j) { + c = s.charAt(j); + if (c >= '\001' && c <= '\177') { + data[len++] = (byte) c; + } else if (c > '\u07FF') { + data[len++] = (byte) (0xE0 | c >> 12 & 0xF); + data[len++] = (byte) (0x80 | c >> 6 & 0x3F); + data[len++] = (byte) (0x80 | c & 0x3F); + } else { + data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); + data[len++] = (byte) (0x80 | c & 0x3F); + } + } + length = len; + return this; + } + + /** + * Puts an array of bytes into this byte vector. The byte vector is + * automatically enlarged if necessary. + * + * @param b + * an array of bytes. May be null to put len + * null bytes into this byte vector. + * @param off + * index of the fist byte of b that must be copied. + * @param len + * number of bytes of b that must be copied. + * @return this byte vector. + */ + public ByteVector putByteArray(final byte[] b, final int off, final int len) { + if (length + len > data.length) { + enlarge(len); + } + if (b != null) { + System.arraycopy(b, off, data, length, len); + } + length += len; + return this; + } + + /** + * Enlarge this byte vector so that it can receive n more bytes. + * + * @param size + * number of additional bytes that this byte vector should be + * able to receive. + */ + private void enlarge(final int size) { + int length1 = 2 * data.length; + int length2 = length + size; + byte[] newData = new byte[length1 > length2 ? length1 : length2]; + System.arraycopy(data, 0, newData, 0, length); + data = newData; + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/ClassReader.java b/blade-core/src/main/java/org/objectweb/asm/ClassReader.java new file mode 100644 index 000000000..76b1600ee --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/ClassReader.java @@ -0,0 +1,2507 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +import java.io.IOException; +import java.io.InputStream; + +/** + * A Java class parser to make a {@link ClassVisitor} visit an existing class. + * This class parses a byte array conforming to the Java class file format and + * calls the appropriate visit methods of a given class visitor for each field, + * method and bytecode instruction encountered. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public class ClassReader { + + /** + * True to enable signatures support. + */ + static final boolean SIGNATURES = true; + + /** + * True to enable annotations support. + */ + static final boolean ANNOTATIONS = true; + + /** + * True to enable stack map frames support. + */ + static final boolean FRAMES = true; + + /** + * True to enable bytecode writing support. + */ + static final boolean WRITER = true; + + /** + * True to enable JSR_W and GOTO_W support. + */ + static final boolean RESIZE = true; + + /** + * Flag to skip method code. If this class is set CODE + * attribute won't be visited. This can be used, for example, to retrieve + * annotations for methods and method parameters. + */ + public static final int SKIP_CODE = 1; + + /** + * Flag to skip the debug information in the class. If this flag is set the + * debug information of the class is not visited, i.e. the + * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and + * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be + * called. + */ + public static final int SKIP_DEBUG = 2; + + /** + * Flag to skip the stack map frames in the class. If this flag is set the + * stack map frames of the class is not visited, i.e. the + * {@link MethodVisitor#visitFrame visitFrame} method will not be called. + * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is + * used: it avoids visiting frames that will be ignored and recomputed from + * scratch in the class writer. + */ + public static final int SKIP_FRAMES = 4; + + /** + * Flag to expand the stack map frames. By default stack map frames are + * visited in their original format (i.e. "expanded" for classes whose + * version is less than V1_6, and "compressed" for the other classes). If + * this flag is set, stack map frames are always visited in expanded format + * (this option adds a decompression/recompression step in ClassReader and + * ClassWriter which degrades performances quite a lot). + */ + public static final int EXPAND_FRAMES = 8; + + /** + * The class to be parsed. The content of this array must not be + * modified. This field is intended for {@link Attribute} sub classes, and + * is normally not needed by class generators or adapters. + */ + public final byte[] b; + + /** + * The start index of each constant pool item in {@link #b b}, plus one. The + * one byte offset skips the constant pool item tag that indicates its type. + */ + private final int[] items; + + /** + * The String objects corresponding to the CONSTANT_Utf8 items. This cache + * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item, + * which GREATLY improves performances (by a factor 2 to 3). This caching + * strategy could be extended to all constant pool items, but its benefit + * would not be so great for these items (because they are much less + * expensive to parse than CONSTANT_Utf8 items). + */ + private final String[] strings; + + /** + * Maximum length of the strings contained in the constant pool of the + * class. + */ + private final int maxStringLength; + + /** + * Start index of the class header information (access, name...) in + * {@link #b b}. + */ + public final int header; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link ClassReader} object. + * + * @param b + * the bytecode of the class to be read. + */ + public ClassReader(final byte[] b) { + this(b, 0, b.length); + } + + /** + * Constructs a new {@link ClassReader} object. + * + * @param b + * the bytecode of the class to be read. + * @param off + * the start offset of the class data. + * @param len + * the length of the class data. + */ + public ClassReader(final byte[] b, final int off, final int len) { + this.b = b; + // checks the class version + if (readShort(off + 6) > Opcodes.V1_8) { + throw new IllegalArgumentException(); + } + // parses the constant pool + items = new int[readUnsignedShort(off + 8)]; + int n = items.length; + strings = new String[n]; + int max = 0; + int index = off + 10; + for (int i = 1; i < n; ++i) { + items[i] = index + 1; + int size; + switch (b[index]) { + case ClassWriter.FIELD: + case ClassWriter.METH: + case ClassWriter.IMETH: + case ClassWriter.INT: + case ClassWriter.FLOAT: + case ClassWriter.NAME_TYPE: + case ClassWriter.INDY: + size = 5; + break; + case ClassWriter.LONG: + case ClassWriter.DOUBLE: + size = 9; + ++i; + break; + case ClassWriter.UTF8: + size = 3 + readUnsignedShort(index + 1); + if (size > max) { + max = size; + } + break; + case ClassWriter.HANDLE: + size = 4; + break; + // case ClassWriter.CLASS: + // case ClassWriter.STR: + // case ClassWriter.MTYPE + default: + size = 3; + break; + } + index += size; + } + maxStringLength = max; + // the class header information starts just after the constant pool + header = index; + } + + /** + * Returns the class's access flags (see {@link Opcodes}). This value may + * not reflect Deprecated and Synthetic flags when bytecode is before 1.5 + * and those flags are represented by attributes. + * + * @return the class access flags + * + * @see ClassVisitor#visit(int, int, String, String, String, String[]) + */ + public int getAccess() { + return readUnsignedShort(header); + } + + /** + * Returns the internal name of the class (see + * {@link Type#getInternalName() getInternalName}). + * + * @return the internal class name + * + * @see ClassVisitor#visit(int, int, String, String, String, String[]) + */ + public String getClassName() { + return readClass(header + 2, new char[maxStringLength]); + } + + /** + * Returns the internal of name of the super class (see + * {@link Type#getInternalName() getInternalName}). For interfaces, the + * super class is {@link Object}. + * + * @return the internal name of super class, or null for + * {@link Object} class. + * + * @see ClassVisitor#visit(int, int, String, String, String, String[]) + */ + public String getSuperName() { + return readClass(header + 4, new char[maxStringLength]); + } + + /** + * Returns the internal names of the class's interfaces (see + * {@link Type#getInternalName() getInternalName}). + * + * @return the array of internal names for all implemented interfaces or + * null. + * + * @see ClassVisitor#visit(int, int, String, String, String, String[]) + */ + public String[] getInterfaces() { + int index = header + 6; + int n = readUnsignedShort(index); + String[] interfaces = new String[n]; + if (n > 0) { + char[] buf = new char[maxStringLength]; + for (int i = 0; i < n; ++i) { + index += 2; + interfaces[i] = readClass(index, buf); + } + } + return interfaces; + } + + /** + * Copies the constant pool data into the given {@link ClassWriter}. Should + * be called before the {@link #accept(ClassVisitor,int)} method. + * + * @param classWriter + * the {@link ClassWriter} to copy constant pool into. + */ + void copyPool(final ClassWriter classWriter) { + char[] buf = new char[maxStringLength]; + int ll = items.length; + Item[] items2 = new Item[ll]; + for (int i = 1; i < ll; i++) { + int index = items[i]; + int tag = b[index - 1]; + Item item = new Item(i); + int nameType; + switch (tag) { + case ClassWriter.FIELD: + case ClassWriter.METH: + case ClassWriter.IMETH: + nameType = items[readUnsignedShort(index + 2)]; + item.set(tag, readClass(index, buf), readUTF8(nameType, buf), + readUTF8(nameType + 2, buf)); + break; + case ClassWriter.INT: + item.set(readInt(index)); + break; + case ClassWriter.FLOAT: + item.set(Float.intBitsToFloat(readInt(index))); + break; + case ClassWriter.NAME_TYPE: + item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf), + null); + break; + case ClassWriter.LONG: + item.set(readLong(index)); + ++i; + break; + case ClassWriter.DOUBLE: + item.set(Double.longBitsToDouble(readLong(index))); + ++i; + break; + case ClassWriter.UTF8: { + String s = strings[i]; + if (s == null) { + index = items[i]; + s = strings[i] = readUTF(index + 2, + readUnsignedShort(index), buf); + } + item.set(tag, s, null, null); + break; + } + case ClassWriter.HANDLE: { + int fieldOrMethodRef = items[readUnsignedShort(index + 1)]; + nameType = items[readUnsignedShort(fieldOrMethodRef + 2)]; + item.set(ClassWriter.HANDLE_BASE + readByte(index), + readClass(fieldOrMethodRef, buf), + readUTF8(nameType, buf), readUTF8(nameType + 2, buf)); + break; + } + case ClassWriter.INDY: + if (classWriter.bootstrapMethods == null) { + copyBootstrapMethods(classWriter, items2, buf); + } + nameType = items[readUnsignedShort(index + 2)]; + item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf), + readUnsignedShort(index)); + break; + // case ClassWriter.STR: + // case ClassWriter.CLASS: + // case ClassWriter.MTYPE + default: + item.set(tag, readUTF8(index, buf), null, null); + break; + } + + int index2 = item.hashCode % items2.length; + item.next = items2[index2]; + items2[index2] = item; + } + + int off = items[1] - 1; + classWriter.pool.putByteArray(b, off, header - off); + classWriter.items = items2; + classWriter.threshold = (int) (0.75d * ll); + classWriter.index = ll; + } + + /** + * Copies the bootstrap method data into the given {@link ClassWriter}. + * Should be called before the {@link #accept(ClassVisitor,int)} method. + * + * @param classWriter + * the {@link ClassWriter} to copy bootstrap methods into. + */ + private void copyBootstrapMethods(final ClassWriter classWriter, + final Item[] items, final char[] c) { + // finds the "BootstrapMethods" attribute + int u = getAttributes(); + boolean found = false; + for (int i = readUnsignedShort(u); i > 0; --i) { + String attrName = readUTF8(u + 2, c); + if ("BootstrapMethods".equals(attrName)) { + found = true; + break; + } + u += 6 + readInt(u + 4); + } + if (!found) { + return; + } + // copies the bootstrap methods in the class writer + int boostrapMethodCount = readUnsignedShort(u + 8); + for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) { + int position = v - u - 10; + int hashCode = readConst(readUnsignedShort(v), c).hashCode(); + for (int k = readUnsignedShort(v + 2); k > 0; --k) { + hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode(); + v += 2; + } + v += 4; + Item item = new Item(j); + item.set(position, hashCode & 0x7FFFFFFF); + int index = item.hashCode % items.length; + item.next = items[index]; + items[index] = item; + } + int attrSize = readInt(u + 4); + ByteVector bootstrapMethods = new ByteVector(attrSize + 62); + bootstrapMethods.putByteArray(b, u + 10, attrSize - 2); + classWriter.bootstrapMethodsCount = boostrapMethodCount; + classWriter.bootstrapMethods = bootstrapMethods; + } + + /** + * Constructs a new {@link ClassReader} object. + * + * @param is + * an input stream from which to read the class. + * @throws IOException + * if a problem occurs during reading. + */ + public ClassReader(final InputStream is) throws IOException { + this(readClass(is, false)); + } + + /** + * Constructs a new {@link ClassReader} object. + * + * @param name + * the binary qualified name of the class to be read. + * @throws IOException + * if an exception occurs during reading. + */ + public ClassReader(final String name) throws IOException { + this(readClass( + ClassLoader.getSystemResourceAsStream(name.replace('.', '/') + + ".class"), true)); + } + + /** + * Reads the bytecode of a class. + * + * @param is + * an input stream from which to read the class. + * @param close + * true to close the input stream after reading. + * @return the bytecode read from the given input stream. + * @throws IOException + * if a problem occurs during reading. + */ + private static byte[] readClass(final InputStream is, boolean close) + throws IOException { + if (is == null) { + throw new IOException("Class not found"); + } + try { + byte[] b = new byte[is.available()]; + int len = 0; + while (true) { + int n = is.read(b, len, b.length - len); + if (n == -1) { + if (len < b.length) { + byte[] c = new byte[len]; + System.arraycopy(b, 0, c, 0, len); + b = c; + } + return b; + } + len += n; + if (len == b.length) { + int last = is.read(); + if (last < 0) { + return b; + } + byte[] c = new byte[b.length + 1000]; + System.arraycopy(b, 0, c, 0, len); + c[len++] = (byte) last; + b = c; + } + } + } finally { + if (close) { + is.close(); + } + } + } + + // ------------------------------------------------------------------------ + // Public methods + // ------------------------------------------------------------------------ + + /** + * Makes the given visitor visit the Java class of this {@link ClassReader} + * . This class is the one specified in the constructor (see + * {@link #ClassReader(byte[]) ClassReader}). + * + * @param classVisitor + * the visitor that must visit this class. + * @param flags + * option flags that can be used to modify the default behavior + * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} + * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. + */ + public void accept(final ClassVisitor classVisitor, final int flags) { + accept(classVisitor, new Attribute[0], flags); + } + + /** + * Makes the given visitor visit the Java class of this {@link ClassReader}. + * This class is the one specified in the constructor (see + * {@link #ClassReader(byte[]) ClassReader}). + * + * @param classVisitor + * the visitor that must visit this class. + * @param attrs + * prototypes of the attributes that must be parsed during the + * visit of the class. Any attribute whose type is not equal to + * the type of one the prototypes will not be parsed: its byte + * array value will be passed unchanged to the ClassWriter. + * This may corrupt it if this value contains references to + * the constant pool, or has syntactic or semantic links with a + * class element that has been transformed by a class adapter + * between the reader and the writer. + * @param flags + * option flags that can be used to modify the default behavior + * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} + * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. + */ + public void accept(final ClassVisitor classVisitor, + final Attribute[] attrs, final int flags) { + int u = header; // current offset in the class file + char[] c = new char[maxStringLength]; // buffer used to read strings + + Context context = new Context(); + context.attrs = attrs; + context.flags = flags; + context.buffer = c; + + // reads the class declaration + int access = readUnsignedShort(u); + String name = readClass(u + 2, c); + String superClass = readClass(u + 4, c); + String[] interfaces = new String[readUnsignedShort(u + 6)]; + u += 8; + for (int i = 0; i < interfaces.length; ++i) { + interfaces[i] = readClass(u, c); + u += 2; + } + + // reads the class attributes + String signature = null; + String sourceFile = null; + String sourceDebug = null; + String enclosingOwner = null; + String enclosingName = null; + String enclosingDesc = null; + int anns = 0; + int ianns = 0; + int tanns = 0; + int itanns = 0; + int innerClasses = 0; + Attribute attributes = null; + + u = getAttributes(); + for (int i = readUnsignedShort(u); i > 0; --i) { + String attrName = readUTF8(u + 2, c); + // tests are sorted in decreasing frequency order + // (based on frequencies observed on typical classes) + if ("SourceFile".equals(attrName)) { + sourceFile = readUTF8(u + 8, c); + } else if ("InnerClasses".equals(attrName)) { + innerClasses = u + 8; + } else if ("EnclosingMethod".equals(attrName)) { + enclosingOwner = readClass(u + 8, c); + int item = readUnsignedShort(u + 10); + if (item != 0) { + enclosingName = readUTF8(items[item], c); + enclosingDesc = readUTF8(items[item] + 2, c); + } + } else if (SIGNATURES && "Signature".equals(attrName)) { + signature = readUTF8(u + 8, c); + } else if (ANNOTATIONS + && "RuntimeVisibleAnnotations".equals(attrName)) { + anns = u + 8; + } else if (ANNOTATIONS + && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + tanns = u + 8; + } else if ("Deprecated".equals(attrName)) { + access |= Opcodes.ACC_DEPRECATED; + } else if ("Synthetic".equals(attrName)) { + access |= Opcodes.ACC_SYNTHETIC + | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; + } else if ("SourceDebugExtension".equals(attrName)) { + int len = readInt(u + 4); + sourceDebug = readUTF(u + 8, len, new char[len]); + } else if (ANNOTATIONS + && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + itanns = u + 8; + } else if ("BootstrapMethods".equals(attrName)) { + int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; + for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { + bootstrapMethods[j] = v; + v += 2 + readUnsignedShort(v + 2) << 1; + } + context.bootstrapMethods = bootstrapMethods; + } else { + Attribute attr = readAttribute(attrs, attrName, u + 8, + readInt(u + 4), c, -1, null); + if (attr != null) { + attr.next = attributes; + attributes = attr; + } + } + u += 6 + readInt(u + 4); + } + + // visits the class declaration + classVisitor.visit(readInt(items[1] - 7), access, name, signature, + superClass, interfaces); + + // visits the source and debug info + if ((flags & SKIP_DEBUG) == 0 + && (sourceFile != null || sourceDebug != null)) { + classVisitor.visitSource(sourceFile, sourceDebug); + } + + // visits the outer class + if (enclosingOwner != null) { + classVisitor.visitOuterClass(enclosingOwner, enclosingName, + enclosingDesc); + } + + // visits the class annotations and type annotations + if (ANNOTATIONS && anns != 0) { + for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + classVisitor.visitAnnotation(readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && ianns != 0) { + for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + classVisitor.visitAnnotation(readUTF8(v, c), false)); + } + } + if (ANNOTATIONS && tanns != 0) { + for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + classVisitor.visitTypeAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && itanns != 0) { + for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + classVisitor.visitTypeAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), false)); + } + } + + // visits the attributes + while (attributes != null) { + Attribute attr = attributes.next; + attributes.next = null; + classVisitor.visitAttribute(attributes); + attributes = attr; + } + + // visits the inner classes + if (innerClasses != 0) { + int v = innerClasses + 2; + for (int i = readUnsignedShort(innerClasses); i > 0; --i) { + classVisitor.visitInnerClass(readClass(v, c), + readClass(v + 2, c), readUTF8(v + 4, c), + readUnsignedShort(v + 6)); + v += 8; + } + } + + // visits the fields and methods + u = header + 10 + 2 * interfaces.length; + for (int i = readUnsignedShort(u - 2); i > 0; --i) { + u = readField(classVisitor, context, u); + } + u += 2; + for (int i = readUnsignedShort(u - 2); i > 0; --i) { + u = readMethod(classVisitor, context, u); + } + + // visits the end of the class + classVisitor.visitEnd(); + } + + /** + * Reads a field and makes the given visitor visit it. + * + * @param classVisitor + * the visitor that must visit the field. + * @param context + * information about the class being parsed. + * @param u + * the start offset of the field in the class file. + * @return the offset of the first byte following the field in the class. + */ + private int readField(final ClassVisitor classVisitor, + final Context context, int u) { + // reads the field declaration + char[] c = context.buffer; + int access = readUnsignedShort(u); + String name = readUTF8(u + 2, c); + String desc = readUTF8(u + 4, c); + u += 6; + + // reads the field attributes + String signature = null; + int anns = 0; + int ianns = 0; + int tanns = 0; + int itanns = 0; + Object value = null; + Attribute attributes = null; + + for (int i = readUnsignedShort(u); i > 0; --i) { + String attrName = readUTF8(u + 2, c); + // tests are sorted in decreasing frequency order + // (based on frequencies observed on typical classes) + if ("ConstantValue".equals(attrName)) { + int item = readUnsignedShort(u + 8); + value = item == 0 ? null : readConst(item, c); + } else if (SIGNATURES && "Signature".equals(attrName)) { + signature = readUTF8(u + 8, c); + } else if ("Deprecated".equals(attrName)) { + access |= Opcodes.ACC_DEPRECATED; + } else if ("Synthetic".equals(attrName)) { + access |= Opcodes.ACC_SYNTHETIC + | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; + } else if (ANNOTATIONS + && "RuntimeVisibleAnnotations".equals(attrName)) { + anns = u + 8; + } else if (ANNOTATIONS + && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + tanns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + itanns = u + 8; + } else { + Attribute attr = readAttribute(context.attrs, attrName, u + 8, + readInt(u + 4), c, -1, null); + if (attr != null) { + attr.next = attributes; + attributes = attr; + } + } + u += 6 + readInt(u + 4); + } + u += 2; + + // visits the field declaration + FieldVisitor fv = classVisitor.visitField(access, name, desc, + signature, value); + if (fv == null) { + return u; + } + + // visits the field annotations and type annotations + if (ANNOTATIONS && anns != 0) { + for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + fv.visitAnnotation(readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && ianns != 0) { + for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + fv.visitAnnotation(readUTF8(v, c), false)); + } + } + if (ANNOTATIONS && tanns != 0) { + for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + fv.visitTypeAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && itanns != 0) { + for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + fv.visitTypeAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), false)); + } + } + + // visits the field attributes + while (attributes != null) { + Attribute attr = attributes.next; + attributes.next = null; + fv.visitAttribute(attributes); + attributes = attr; + } + + // visits the end of the field + fv.visitEnd(); + + return u; + } + + /** + * Reads a method and makes the given visitor visit it. + * + * @param classVisitor + * the visitor that must visit the method. + * @param context + * information about the class being parsed. + * @param u + * the start offset of the method in the class file. + * @return the offset of the first byte following the method in the class. + */ + private int readMethod(final ClassVisitor classVisitor, + final Context context, int u) { + // reads the method declaration + char[] c = context.buffer; + context.access = readUnsignedShort(u); + context.name = readUTF8(u + 2, c); + context.desc = readUTF8(u + 4, c); + u += 6; + + // reads the method attributes + int code = 0; + int exception = 0; + String[] exceptions = null; + String signature = null; + int methodParameters = 0; + int anns = 0; + int ianns = 0; + int tanns = 0; + int itanns = 0; + int dann = 0; + int mpanns = 0; + int impanns = 0; + int firstAttribute = u; + Attribute attributes = null; + + for (int i = readUnsignedShort(u); i > 0; --i) { + String attrName = readUTF8(u + 2, c); + // tests are sorted in decreasing frequency order + // (based on frequencies observed on typical classes) + if ("Code".equals(attrName)) { + if ((context.flags & SKIP_CODE) == 0) { + code = u + 8; + } + } else if ("Exceptions".equals(attrName)) { + exceptions = new String[readUnsignedShort(u + 8)]; + exception = u + 10; + for (int j = 0; j < exceptions.length; ++j) { + exceptions[j] = readClass(exception, c); + exception += 2; + } + } else if (SIGNATURES && "Signature".equals(attrName)) { + signature = readUTF8(u + 8, c); + } else if ("Deprecated".equals(attrName)) { + context.access |= Opcodes.ACC_DEPRECATED; + } else if (ANNOTATIONS + && "RuntimeVisibleAnnotations".equals(attrName)) { + anns = u + 8; + } else if (ANNOTATIONS + && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + tanns = u + 8; + } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { + dann = u + 8; + } else if ("Synthetic".equals(attrName)) { + context.access |= Opcodes.ACC_SYNTHETIC + | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; + } else if (ANNOTATIONS + && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + itanns = u + 8; + } else if (ANNOTATIONS + && "RuntimeVisibleParameterAnnotations".equals(attrName)) { + mpanns = u + 8; + } else if (ANNOTATIONS + && "RuntimeInvisibleParameterAnnotations".equals(attrName)) { + impanns = u + 8; + } else if ("MethodParameters".equals(attrName)) { + methodParameters = u + 8; + } else { + Attribute attr = readAttribute(context.attrs, attrName, u + 8, + readInt(u + 4), c, -1, null); + if (attr != null) { + attr.next = attributes; + attributes = attr; + } + } + u += 6 + readInt(u + 4); + } + u += 2; + + // visits the method declaration + MethodVisitor mv = classVisitor.visitMethod(context.access, + context.name, context.desc, signature, exceptions); + if (mv == null) { + return u; + } + + /* + * if the returned MethodVisitor is in fact a MethodWriter, it means + * there is no method adapter between the reader and the writer. If, in + * addition, the writer's constant pool was copied from this reader + * (mw.cw.cr == this), and the signature and exceptions of the method + * have not been changed, then it is possible to skip all visit events + * and just copy the original code of the method to the writer (the + * access, name and descriptor can have been changed, this is not + * important since they are not copied as is from the reader). + */ + if (WRITER && mv instanceof MethodWriter) { + MethodWriter mw = (MethodWriter) mv; + if (mw.cw.cr == this && signature == mw.signature) { + boolean sameExceptions = false; + if (exceptions == null) { + sameExceptions = mw.exceptionCount == 0; + } else if (exceptions.length == mw.exceptionCount) { + sameExceptions = true; + for (int j = exceptions.length - 1; j >= 0; --j) { + exception -= 2; + if (mw.exceptions[j] != readUnsignedShort(exception)) { + sameExceptions = false; + break; + } + } + } + if (sameExceptions) { + /* + * we do not copy directly the code into MethodWriter to + * save a byte array copy operation. The real copy will be + * done in ClassWriter.toByteArray(). + */ + mw.classReaderOffset = firstAttribute; + mw.classReaderLength = u - firstAttribute; + return u; + } + } + } + + // visit the method parameters + if (methodParameters != 0) { + for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) { + mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2)); + } + } + + // visits the method annotations + if (ANNOTATIONS && dann != 0) { + AnnotationVisitor dv = mv.visitAnnotationDefault(); + readAnnotationValue(dann, c, null, dv); + if (dv != null) { + dv.visitEnd(); + } + } + if (ANNOTATIONS && anns != 0) { + for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + mv.visitAnnotation(readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && ianns != 0) { + for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { + v = readAnnotationValues(v + 2, c, true, + mv.visitAnnotation(readUTF8(v, c), false)); + } + } + if (ANNOTATIONS && tanns != 0) { + for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + mv.visitTypeAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), true)); + } + } + if (ANNOTATIONS && itanns != 0) { + for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { + v = readAnnotationTarget(context, v); + v = readAnnotationValues(v + 2, c, true, + mv.visitTypeAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), false)); + } + } + if (ANNOTATIONS && mpanns != 0) { + readParameterAnnotations(mv, context, mpanns, true); + } + if (ANNOTATIONS && impanns != 0) { + readParameterAnnotations(mv, context, impanns, false); + } + + // visits the method attributes + while (attributes != null) { + Attribute attr = attributes.next; + attributes.next = null; + mv.visitAttribute(attributes); + attributes = attr; + } + + // visits the method code + if (code != 0) { + mv.visitCode(); + readCode(mv, context, code); + } + + // visits the end of the method + mv.visitEnd(); + + return u; + } + + /** + * Reads the bytecode of a method and makes the given visitor visit it. + * + * @param mv + * the visitor that must visit the method's code. + * @param context + * information about the class being parsed. + * @param u + * the start offset of the code attribute in the class file. + */ + private void readCode(final MethodVisitor mv, final Context context, int u) { + // reads the header + byte[] b = this.b; + char[] c = context.buffer; + int maxStack = readUnsignedShort(u); + int maxLocals = readUnsignedShort(u + 2); + int codeLength = readInt(u + 4); + u += 8; + + // reads the bytecode to find the labels + int codeStart = u; + int codeEnd = u + codeLength; + Label[] labels = context.labels = new Label[codeLength + 2]; + readLabel(codeLength + 1, labels); + while (u < codeEnd) { + int offset = u - codeStart; + int opcode = b[u] & 0xFF; + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + case ClassWriter.IMPLVAR_INSN: + u += 1; + break; + case ClassWriter.LABEL_INSN: + readLabel(offset + readShort(u + 1), labels); + u += 3; + break; + case ClassWriter.LABELW_INSN: + readLabel(offset + readInt(u + 1), labels); + u += 5; + break; + case ClassWriter.WIDE_INSN: + opcode = b[u + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + u += 6; + } else { + u += 4; + } + break; + case ClassWriter.TABL_INSN: + // skips 0 to 3 padding bytes + u = u + 4 - (offset & 3); + // reads instruction + readLabel(offset + readInt(u), labels); + for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) { + readLabel(offset + readInt(u + 12), labels); + u += 4; + } + u += 12; + break; + case ClassWriter.LOOK_INSN: + // skips 0 to 3 padding bytes + u = u + 4 - (offset & 3); + // reads instruction + readLabel(offset + readInt(u), labels); + for (int i = readInt(u + 4); i > 0; --i) { + readLabel(offset + readInt(u + 12), labels); + u += 8; + } + u += 8; + break; + case ClassWriter.VAR_INSN: + case ClassWriter.SBYTE_INSN: + case ClassWriter.LDC_INSN: + u += 2; + break; + case ClassWriter.SHORT_INSN: + case ClassWriter.LDCW_INSN: + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.TYPE_INSN: + case ClassWriter.IINC_INSN: + u += 3; + break; + case ClassWriter.ITFMETH_INSN: + case ClassWriter.INDYMETH_INSN: + u += 5; + break; + // case MANA_INSN: + default: + u += 4; + break; + } + } + + // reads the try catch entries to find the labels, and also visits them + for (int i = readUnsignedShort(u); i > 0; --i) { + Label start = readLabel(readUnsignedShort(u + 2), labels); + Label end = readLabel(readUnsignedShort(u + 4), labels); + Label handler = readLabel(readUnsignedShort(u + 6), labels); + String type = readUTF8(items[readUnsignedShort(u + 8)], c); + mv.visitTryCatchBlock(start, end, handler, type); + u += 8; + } + u += 2; + + // reads the code attributes + int[] tanns = null; // start index of each visible type annotation + int[] itanns = null; // start index of each invisible type annotation + int tann = 0; // current index in tanns array + int itann = 0; // current index in itanns array + int ntoff = -1; // next visible type annotation code offset + int nitoff = -1; // next invisible type annotation code offset + int varTable = 0; + int varTypeTable = 0; + boolean zip = true; + boolean unzip = (context.flags & EXPAND_FRAMES) != 0; + int stackMap = 0; + int stackMapSize = 0; + int frameCount = 0; + Context frame = null; + Attribute attributes = null; + + for (int i = readUnsignedShort(u); i > 0; --i) { + String attrName = readUTF8(u + 2, c); + if ("LocalVariableTable".equals(attrName)) { + if ((context.flags & SKIP_DEBUG) == 0) { + varTable = u + 8; + for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { + int label = readUnsignedShort(v + 10); + if (labels[label] == null) { + readLabel(label, labels).status |= Label.DEBUG; + } + label += readUnsignedShort(v + 12); + if (labels[label] == null) { + readLabel(label, labels).status |= Label.DEBUG; + } + v += 10; + } + } + } else if ("LocalVariableTypeTable".equals(attrName)) { + varTypeTable = u + 8; + } else if ("LineNumberTable".equals(attrName)) { + if ((context.flags & SKIP_DEBUG) == 0) { + for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { + int label = readUnsignedShort(v + 10); + if (labels[label] == null) { + readLabel(label, labels).status |= Label.DEBUG; + } + Label l = labels[label]; + while (l.line > 0) { + if (l.next == null) { + l.next = new Label(); + } + l = l.next; + } + l.line = readUnsignedShort(v + 12); + v += 4; + } + } + } else if (ANNOTATIONS + && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + tanns = readTypeAnnotations(mv, context, u + 8, true); + ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1 + : readUnsignedShort(tanns[0] + 1); + } else if (ANNOTATIONS + && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + itanns = readTypeAnnotations(mv, context, u + 8, false); + nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1 + : readUnsignedShort(itanns[0] + 1); + } else if (FRAMES && "StackMapTable".equals(attrName)) { + if ((context.flags & SKIP_FRAMES) == 0) { + stackMap = u + 10; + stackMapSize = readInt(u + 4); + frameCount = readUnsignedShort(u + 8); + } + /* + * here we do not extract the labels corresponding to the + * attribute content. This would require a full parsing of the + * attribute, which would need to be repeated in the second + * phase (see below). Instead the content of the attribute is + * read one frame at a time (i.e. after a frame has been + * visited, the next frame is read), and the labels it contains + * are also extracted one frame at a time. Thanks to the + * ordering of frames, having only a "one frame lookahead" is + * not a problem, i.e. it is not possible to see an offset + * smaller than the offset of the current insn and for which no + * Label exist. + */ + /* + * This is not true for UNINITIALIZED type offsets. We solve + * this by parsing the stack map table without a full decoding + * (see below). + */ + } else if (FRAMES && "StackMap".equals(attrName)) { + if ((context.flags & SKIP_FRAMES) == 0) { + zip = false; + stackMap = u + 10; + stackMapSize = readInt(u + 4); + frameCount = readUnsignedShort(u + 8); + } + /* + * IMPORTANT! here we assume that the frames are ordered, as in + * the StackMapTable attribute, although this is not guaranteed + * by the attribute format. + */ + } else { + for (int j = 0; j < context.attrs.length; ++j) { + if (context.attrs[j].type.equals(attrName)) { + Attribute attr = context.attrs[j].read(this, u + 8, + readInt(u + 4), c, codeStart - 8, labels); + if (attr != null) { + attr.next = attributes; + attributes = attr; + } + } + } + } + u += 6 + readInt(u + 4); + } + u += 2; + + // generates the first (implicit) stack map frame + if (FRAMES && stackMap != 0) { + /* + * for the first explicit frame the offset is not offset_delta + 1 + * but only offset_delta; setting the implicit frame offset to -1 + * allow the use of the "offset_delta + 1" rule in all cases + */ + frame = context; + frame.offset = -1; + frame.mode = 0; + frame.localCount = 0; + frame.localDiff = 0; + frame.stackCount = 0; + frame.local = new Object[maxLocals]; + frame.stack = new Object[maxStack]; + if (unzip) { + getImplicitFrame(context); + } + /* + * Finds labels for UNINITIALIZED frame types. Instead of decoding + * each element of the stack map table, we look for 3 consecutive + * bytes that "look like" an UNINITIALIZED type (tag 8, offset + * within code bounds, NEW instruction at this offset). We may find + * false positives (i.e. not real UNINITIALIZED types), but this + * should be rare, and the only consequence will be the creation of + * an unneeded label. This is better than creating a label for each + * NEW instruction, and faster than fully decoding the whole stack + * map table. + */ + for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) { + if (b[i] == 8) { // UNINITIALIZED FRAME TYPE + int v = readUnsignedShort(i + 1); + if (v >= 0 && v < codeLength) { + if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) { + readLabel(v, labels); + } + } + } + } + } + + // visits the instructions + u = codeStart; + while (u < codeEnd) { + int offset = u - codeStart; + + // visits the label and line number for this offset, if any + Label l = labels[offset]; + if (l != null) { + Label next = l.next; + l.next = null; + mv.visitLabel(l); + if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) { + mv.visitLineNumber(l.line, l); + while (next != null) { + mv.visitLineNumber(next.line, l); + next = next.next; + } + } + } + + // visits the frame for this offset, if any + while (FRAMES && frame != null + && (frame.offset == offset || frame.offset == -1)) { + // if there is a frame for this offset, makes the visitor visit + // it, and reads the next frame if there is one. + if (frame.offset != -1) { + if (!zip || unzip) { + mv.visitFrame(Opcodes.F_NEW, frame.localCount, + frame.local, frame.stackCount, frame.stack); + } else { + mv.visitFrame(frame.mode, frame.localDiff, frame.local, + frame.stackCount, frame.stack); + } + } + if (frameCount > 0) { + stackMap = readFrame(stackMap, zip, unzip, frame); + --frameCount; + } else { + frame = null; + } + } + + // visits the instruction at this offset + int opcode = b[u] & 0xFF; + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + mv.visitInsn(opcode); + u += 1; + break; + case ClassWriter.IMPLVAR_INSN: + if (opcode > Opcodes.ISTORE) { + opcode -= 59; // ISTORE_0 + mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), + opcode & 0x3); + } else { + opcode -= 26; // ILOAD_0 + mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3); + } + u += 1; + break; + case ClassWriter.LABEL_INSN: + mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]); + u += 3; + break; + case ClassWriter.LABELW_INSN: + mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]); + u += 5; + break; + case ClassWriter.WIDE_INSN: + opcode = b[u + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4)); + u += 6; + } else { + mv.visitVarInsn(opcode, readUnsignedShort(u + 2)); + u += 4; + } + break; + case ClassWriter.TABL_INSN: { + // skips 0 to 3 padding bytes + u = u + 4 - (offset & 3); + // reads instruction + int label = offset + readInt(u); + int min = readInt(u + 4); + int max = readInt(u + 8); + Label[] table = new Label[max - min + 1]; + u += 12; + for (int i = 0; i < table.length; ++i) { + table[i] = labels[offset + readInt(u)]; + u += 4; + } + mv.visitTableSwitchInsn(min, max, labels[label], table); + break; + } + case ClassWriter.LOOK_INSN: { + // skips 0 to 3 padding bytes + u = u + 4 - (offset & 3); + // reads instruction + int label = offset + readInt(u); + int len = readInt(u + 4); + int[] keys = new int[len]; + Label[] values = new Label[len]; + u += 8; + for (int i = 0; i < len; ++i) { + keys[i] = readInt(u); + values[i] = labels[offset + readInt(u + 4)]; + u += 8; + } + mv.visitLookupSwitchInsn(labels[label], keys, values); + break; + } + case ClassWriter.VAR_INSN: + mv.visitVarInsn(opcode, b[u + 1] & 0xFF); + u += 2; + break; + case ClassWriter.SBYTE_INSN: + mv.visitIntInsn(opcode, b[u + 1]); + u += 2; + break; + case ClassWriter.SHORT_INSN: + mv.visitIntInsn(opcode, readShort(u + 1)); + u += 3; + break; + case ClassWriter.LDC_INSN: + mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c)); + u += 2; + break; + case ClassWriter.LDCW_INSN: + mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c)); + u += 3; + break; + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.ITFMETH_INSN: { + int cpIndex = items[readUnsignedShort(u + 1)]; + boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; + String iowner = readClass(cpIndex, c); + cpIndex = items[readUnsignedShort(cpIndex + 2)]; + String iname = readUTF8(cpIndex, c); + String idesc = readUTF8(cpIndex + 2, c); + if (opcode < Opcodes.INVOKEVIRTUAL) { + mv.visitFieldInsn(opcode, iowner, iname, idesc); + } else { + mv.visitMethodInsn(opcode, iowner, iname, idesc, itf); + } + if (opcode == Opcodes.INVOKEINTERFACE) { + u += 5; + } else { + u += 3; + } + break; + } + case ClassWriter.INDYMETH_INSN: { + int cpIndex = items[readUnsignedShort(u + 1)]; + int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)]; + Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c); + int bsmArgCount = readUnsignedShort(bsmIndex + 2); + Object[] bsmArgs = new Object[bsmArgCount]; + bsmIndex += 4; + for (int i = 0; i < bsmArgCount; i++) { + bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c); + bsmIndex += 2; + } + cpIndex = items[readUnsignedShort(cpIndex + 2)]; + String iname = readUTF8(cpIndex, c); + String idesc = readUTF8(cpIndex + 2, c); + mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs); + u += 5; + break; + } + case ClassWriter.TYPE_INSN: + mv.visitTypeInsn(opcode, readClass(u + 1, c)); + u += 3; + break; + case ClassWriter.IINC_INSN: + mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]); + u += 3; + break; + // case MANA_INSN: + default: + mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF); + u += 4; + break; + } + + // visit the instruction annotations, if any + while (tanns != null && tann < tanns.length && ntoff <= offset) { + if (ntoff == offset) { + int v = readAnnotationTarget(context, tanns[tann]); + readAnnotationValues(v + 2, c, true, + mv.visitInsnAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), true)); + } + ntoff = ++tann >= tanns.length || readByte(tanns[tann]) < 0x43 ? -1 + : readUnsignedShort(tanns[tann] + 1); + } + while (itanns != null && itann < itanns.length && nitoff <= offset) { + if (nitoff == offset) { + int v = readAnnotationTarget(context, itanns[itann]); + readAnnotationValues(v + 2, c, true, + mv.visitInsnAnnotation(context.typeRef, + context.typePath, readUTF8(v, c), false)); + } + nitoff = ++itann >= itanns.length + || readByte(itanns[itann]) < 0x43 ? -1 + : readUnsignedShort(itanns[itann] + 1); + } + } + if (labels[codeLength] != null) { + mv.visitLabel(labels[codeLength]); + } + + // visits the local variable tables + if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) { + int[] typeTable = null; + if (varTypeTable != 0) { + u = varTypeTable + 2; + typeTable = new int[readUnsignedShort(varTypeTable) * 3]; + for (int i = typeTable.length; i > 0;) { + typeTable[--i] = u + 6; // signature + typeTable[--i] = readUnsignedShort(u + 8); // index + typeTable[--i] = readUnsignedShort(u); // start + u += 10; + } + } + u = varTable + 2; + for (int i = readUnsignedShort(varTable); i > 0; --i) { + int start = readUnsignedShort(u); + int length = readUnsignedShort(u + 2); + int index = readUnsignedShort(u + 8); + String vsignature = null; + if (typeTable != null) { + for (int j = 0; j < typeTable.length; j += 3) { + if (typeTable[j] == start && typeTable[j + 1] == index) { + vsignature = readUTF8(typeTable[j + 2], c); + break; + } + } + } + mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c), + vsignature, labels[start], labels[start + length], + index); + u += 10; + } + } + + // visits the local variables type annotations + if (tanns != null) { + for (int i = 0; i < tanns.length; ++i) { + if ((readByte(tanns[i]) >> 1) == (0x40 >> 1)) { + int v = readAnnotationTarget(context, tanns[i]); + v = readAnnotationValues(v + 2, c, true, + mv.visitLocalVariableAnnotation(context.typeRef, + context.typePath, context.start, + context.end, context.index, readUTF8(v, c), + true)); + } + } + } + if (itanns != null) { + for (int i = 0; i < itanns.length; ++i) { + if ((readByte(itanns[i]) >> 1) == (0x40 >> 1)) { + int v = readAnnotationTarget(context, itanns[i]); + v = readAnnotationValues(v + 2, c, true, + mv.visitLocalVariableAnnotation(context.typeRef, + context.typePath, context.start, + context.end, context.index, readUTF8(v, c), + false)); + } + } + } + + // visits the code attributes + while (attributes != null) { + Attribute attr = attributes.next; + attributes.next = null; + mv.visitAttribute(attributes); + attributes = attr; + } + + // visits the max stack and max locals values + mv.visitMaxs(maxStack, maxLocals); + } + + /** + * Parses a type annotation table to find the labels, and to visit the try + * catch block annotations. + * + * @param u + * the start offset of a type annotation table. + * @param mv + * the method visitor to be used to visit the try catch block + * annotations. + * @param context + * information about the class being parsed. + * @param visible + * if the type annotation table to parse contains runtime visible + * annotations. + * @return the start offset of each type annotation in the parsed table. + */ + private int[] readTypeAnnotations(final MethodVisitor mv, + final Context context, int u, boolean visible) { + char[] c = context.buffer; + int[] offsets = new int[readUnsignedShort(u)]; + u += 2; + for (int i = 0; i < offsets.length; ++i) { + offsets[i] = u; + int target = readInt(u); + switch (target >>> 24) { + case 0x00: // CLASS_TYPE_PARAMETER + case 0x01: // METHOD_TYPE_PARAMETER + case 0x16: // METHOD_FORMAL_PARAMETER + u += 2; + break; + case 0x13: // FIELD + case 0x14: // METHOD_RETURN + case 0x15: // METHOD_RECEIVER + u += 1; + break; + case 0x40: // LOCAL_VARIABLE + case 0x41: // RESOURCE_VARIABLE + for (int j = readUnsignedShort(u + 1); j > 0; --j) { + int start = readUnsignedShort(u + 3); + int length = readUnsignedShort(u + 5); + readLabel(start, context.labels); + readLabel(start + length, context.labels); + u += 6; + } + u += 3; + break; + case 0x47: // CAST + case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT + case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT + u += 4; + break; + // case 0x10: // CLASS_EXTENDS + // case 0x11: // CLASS_TYPE_PARAMETER_BOUND + // case 0x12: // METHOD_TYPE_PARAMETER_BOUND + // case 0x17: // THROWS + // case 0x42: // EXCEPTION_PARAMETER + // case 0x43: // INSTANCEOF + // case 0x44: // NEW + // case 0x45: // CONSTRUCTOR_REFERENCE + // case 0x46: // METHOD_REFERENCE + default: + u += 3; + break; + } + int pathLength = readByte(u); + if ((target >>> 24) == 0x42) { + TypePath path = pathLength == 0 ? null : new TypePath(b, u); + u += 1 + 2 * pathLength; + u = readAnnotationValues(u + 2, c, true, + mv.visitTryCatchAnnotation(target, path, + readUTF8(u, c), visible)); + } else { + u = readAnnotationValues(u + 3 + 2 * pathLength, c, true, null); + } + } + return offsets; + } + + /** + * Parses the header of a type annotation to extract its target_type and + * target_path (the result is stored in the given context), and returns the + * start offset of the rest of the type_annotation structure (i.e. the + * offset to the type_index field, which is followed by + * num_element_value_pairs and then the name,value pairs). + * + * @param context + * information about the class being parsed. This is where the + * extracted target_type and target_path must be stored. + * @param u + * the start offset of a type_annotation structure. + * @return the start offset of the rest of the type_annotation structure. + */ + private int readAnnotationTarget(final Context context, int u) { + int target = readInt(u); + switch (target >>> 24) { + case 0x00: // CLASS_TYPE_PARAMETER + case 0x01: // METHOD_TYPE_PARAMETER + case 0x16: // METHOD_FORMAL_PARAMETER + target &= 0xFFFF0000; + u += 2; + break; + case 0x13: // FIELD + case 0x14: // METHOD_RETURN + case 0x15: // METHOD_RECEIVER + target &= 0xFF000000; + u += 1; + break; + case 0x40: // LOCAL_VARIABLE + case 0x41: { // RESOURCE_VARIABLE + target &= 0xFF000000; + int n = readUnsignedShort(u + 1); + context.start = new Label[n]; + context.end = new Label[n]; + context.index = new int[n]; + u += 3; + for (int i = 0; i < n; ++i) { + int start = readUnsignedShort(u); + int length = readUnsignedShort(u + 2); + context.start[i] = readLabel(start, context.labels); + context.end[i] = readLabel(start + length, context.labels); + context.index[i] = readUnsignedShort(u + 4); + u += 6; + } + break; + } + case 0x47: // CAST + case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT + case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT + target &= 0xFF0000FF; + u += 4; + break; + // case 0x10: // CLASS_EXTENDS + // case 0x11: // CLASS_TYPE_PARAMETER_BOUND + // case 0x12: // METHOD_TYPE_PARAMETER_BOUND + // case 0x17: // THROWS + // case 0x42: // EXCEPTION_PARAMETER + // case 0x43: // INSTANCEOF + // case 0x44: // NEW + // case 0x45: // CONSTRUCTOR_REFERENCE + // case 0x46: // METHOD_REFERENCE + default: + target &= (target >>> 24) < 0x43 ? 0xFFFFFF00 : 0xFF000000; + u += 3; + break; + } + int pathLength = readByte(u); + context.typeRef = target; + context.typePath = pathLength == 0 ? null : new TypePath(b, u); + return u + 1 + 2 * pathLength; + } + + /** + * Reads parameter annotations and makes the given visitor visit them. + * + * @param mv + * the visitor that must visit the annotations. + * @param context + * information about the class being parsed. + * @param v + * start offset in {@link #b b} of the annotations to be read. + * @param visible + * true if the annotations to be read are visible at + * runtime. + */ + private void readParameterAnnotations(final MethodVisitor mv, + final Context context, int v, final boolean visible) { + int i; + int n = b[v++] & 0xFF; + // workaround for a bug in javac (javac compiler generates a parameter + // annotation array whose size is equal to the number of parameters in + // the Java source file, while it should generate an array whose size is + // equal to the number of parameters in the method descriptor - which + // includes the synthetic parameters added by the compiler). This work- + // around supposes that the synthetic parameters are the first ones. + int synthetics = Type.getArgumentTypes(context.desc).length - n; + AnnotationVisitor av; + for (i = 0; i < synthetics; ++i) { + // virtual annotation to detect synthetic parameters in MethodWriter + av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false); + if (av != null) { + av.visitEnd(); + } + } + char[] c = context.buffer; + for (; i < n + synthetics; ++i) { + int j = readUnsignedShort(v); + v += 2; + for (; j > 0; --j) { + av = mv.visitParameterAnnotation(i, readUTF8(v, c), visible); + v = readAnnotationValues(v + 2, c, true, av); + } + } + } + + /** + * Reads the values of an annotation and makes the given visitor visit them. + * + * @param v + * the start offset in {@link #b b} of the values to be read + * (including the unsigned short that gives the number of + * values). + * @param buf + * buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or {@link #readConst + * readConst}. + * @param named + * if the annotation values are named or not. + * @param av + * the visitor that must visit the values. + * @return the end offset of the annotation values. + */ + private int readAnnotationValues(int v, final char[] buf, + final boolean named, final AnnotationVisitor av) { + int i = readUnsignedShort(v); + v += 2; + if (named) { + for (; i > 0; --i) { + v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av); + } + } else { + for (; i > 0; --i) { + v = readAnnotationValue(v, buf, null, av); + } + } + if (av != null) { + av.visitEnd(); + } + return v; + } + + /** + * Reads a value of an annotation and makes the given visitor visit it. + * + * @param v + * the start offset in {@link #b b} of the value to be read + * (not including the value name constant pool index). + * @param buf + * buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or {@link #readConst + * readConst}. + * @param name + * the name of the value to be read. + * @param av + * the visitor that must visit the value. + * @return the end offset of the annotation value. + */ + private int readAnnotationValue(int v, final char[] buf, final String name, + final AnnotationVisitor av) { + int i; + if (av == null) { + switch (b[v] & 0xFF) { + case 'e': // enum_const_value + return v + 5; + case '@': // annotation_value + return readAnnotationValues(v + 3, buf, true, null); + case '[': // array_value + return readAnnotationValues(v + 1, buf, false, null); + default: + return v + 3; + } + } + switch (b[v++] & 0xFF) { + case 'I': // pointer to CONSTANT_Integer + case 'J': // pointer to CONSTANT_Long + case 'F': // pointer to CONSTANT_Float + case 'D': // pointer to CONSTANT_Double + av.visit(name, readConst(readUnsignedShort(v), buf)); + v += 2; + break; + case 'B': // pointer to CONSTANT_Byte + av.visit(name, (byte) readInt(items[readUnsignedShort(v)])); + v += 2; + break; + case 'Z': // pointer to CONSTANT_Boolean + av.visit(name, + readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE + : Boolean.TRUE); + v += 2; + break; + case 'S': // pointer to CONSTANT_Short + av.visit(name, (short) readInt(items[readUnsignedShort(v)])); + v += 2; + break; + case 'C': // pointer to CONSTANT_Char + av.visit(name, (char) readInt(items[readUnsignedShort(v)])); + v += 2; + break; + case 's': // pointer to CONSTANT_Utf8 + av.visit(name, readUTF8(v, buf)); + v += 2; + break; + case 'e': // enum_const_value + av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf)); + v += 4; + break; + case 'c': // class_info + av.visit(name, Type.getType(readUTF8(v, buf))); + v += 2; + break; + case '@': // annotation_value + v = readAnnotationValues(v + 2, buf, true, + av.visitAnnotation(name, readUTF8(v, buf))); + break; + case '[': // array_value + int size = readUnsignedShort(v); + v += 2; + if (size == 0) { + return readAnnotationValues(v - 2, buf, false, + av.visitArray(name)); + } + switch (this.b[v++] & 0xFF) { + case 'B': + byte[] bv = new byte[size]; + for (i = 0; i < size; i++) { + bv[i] = (byte) readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, bv); + --v; + break; + case 'Z': + boolean[] zv = new boolean[size]; + for (i = 0; i < size; i++) { + zv[i] = readInt(items[readUnsignedShort(v)]) != 0; + v += 3; + } + av.visit(name, zv); + --v; + break; + case 'S': + short[] sv = new short[size]; + for (i = 0; i < size; i++) { + sv[i] = (short) readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, sv); + --v; + break; + case 'C': + char[] cv = new char[size]; + for (i = 0; i < size; i++) { + cv[i] = (char) readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, cv); + --v; + break; + case 'I': + int[] iv = new int[size]; + for (i = 0; i < size; i++) { + iv[i] = readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, iv); + --v; + break; + case 'J': + long[] lv = new long[size]; + for (i = 0; i < size; i++) { + lv[i] = readLong(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, lv); + --v; + break; + case 'F': + float[] fv = new float[size]; + for (i = 0; i < size; i++) { + fv[i] = Float + .intBitsToFloat(readInt(items[readUnsignedShort(v)])); + v += 3; + } + av.visit(name, fv); + --v; + break; + case 'D': + double[] dv = new double[size]; + for (i = 0; i < size; i++) { + dv[i] = Double + .longBitsToDouble(readLong(items[readUnsignedShort(v)])); + v += 3; + } + av.visit(name, dv); + --v; + break; + default: + v = readAnnotationValues(v - 3, buf, false, av.visitArray(name)); + } + } + return v; + } + + /** + * Computes the implicit frame of the method currently being parsed (as + * defined in the given {@link Context}) and stores it in the given context. + * + * @param frame + * information about the class being parsed. + */ + private void getImplicitFrame(final Context frame) { + String desc = frame.desc; + Object[] locals = frame.local; + int local = 0; + if ((frame.access & Opcodes.ACC_STATIC) == 0) { + if ("".equals(frame.name)) { + locals[local++] = Opcodes.UNINITIALIZED_THIS; + } else { + locals[local++] = readClass(header + 2, frame.buffer); + } + } + int i = 1; + loop: while (true) { + int j = i; + switch (desc.charAt(i++)) { + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + locals[local++] = Opcodes.INTEGER; + break; + case 'F': + locals[local++] = Opcodes.FLOAT; + break; + case 'J': + locals[local++] = Opcodes.LONG; + break; + case 'D': + locals[local++] = Opcodes.DOUBLE; + break; + case '[': + while (desc.charAt(i) == '[') { + ++i; + } + if (desc.charAt(i) == 'L') { + ++i; + while (desc.charAt(i) != ';') { + ++i; + } + } + locals[local++] = desc.substring(j, ++i); + break; + case 'L': + while (desc.charAt(i) != ';') { + ++i; + } + locals[local++] = desc.substring(j + 1, i++); + break; + default: + break loop; + } + } + frame.localCount = local; + } + + /** + * Reads a stack map frame and stores the result in the given + * {@link Context} object. + * + * @param stackMap + * the start offset of a stack map frame in the class file. + * @param zip + * if the stack map frame at stackMap is compressed or not. + * @param unzip + * if the stack map frame must be uncompressed. + * @param frame + * where the parsed stack map frame must be stored. + * @return the offset of the first byte following the parsed frame. + */ + private int readFrame(int stackMap, boolean zip, boolean unzip, + Context frame) { + char[] c = frame.buffer; + Label[] labels = frame.labels; + int tag; + int delta; + if (zip) { + tag = b[stackMap++] & 0xFF; + } else { + tag = MethodWriter.FULL_FRAME; + frame.offset = -1; + } + frame.localDiff = 0; + if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) { + delta = tag; + frame.mode = Opcodes.F_SAME; + frame.stackCount = 0; + } else if (tag < MethodWriter.RESERVED) { + delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME; + stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); + frame.mode = Opcodes.F_SAME1; + frame.stackCount = 1; + } else { + delta = readUnsignedShort(stackMap); + stackMap += 2; + if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { + stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); + frame.mode = Opcodes.F_SAME1; + frame.stackCount = 1; + } else if (tag >= MethodWriter.CHOP_FRAME + && tag < MethodWriter.SAME_FRAME_EXTENDED) { + frame.mode = Opcodes.F_CHOP; + frame.localDiff = MethodWriter.SAME_FRAME_EXTENDED - tag; + frame.localCount -= frame.localDiff; + frame.stackCount = 0; + } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) { + frame.mode = Opcodes.F_SAME; + frame.stackCount = 0; + } else if (tag < MethodWriter.FULL_FRAME) { + int local = unzip ? frame.localCount : 0; + for (int i = tag - MethodWriter.SAME_FRAME_EXTENDED; i > 0; i--) { + stackMap = readFrameType(frame.local, local++, stackMap, c, + labels); + } + frame.mode = Opcodes.F_APPEND; + frame.localDiff = tag - MethodWriter.SAME_FRAME_EXTENDED; + frame.localCount += frame.localDiff; + frame.stackCount = 0; + } else { // if (tag == FULL_FRAME) { + frame.mode = Opcodes.F_FULL; + int n = readUnsignedShort(stackMap); + stackMap += 2; + frame.localDiff = n; + frame.localCount = n; + for (int local = 0; n > 0; n--) { + stackMap = readFrameType(frame.local, local++, stackMap, c, + labels); + } + n = readUnsignedShort(stackMap); + stackMap += 2; + frame.stackCount = n; + for (int stack = 0; n > 0; n--) { + stackMap = readFrameType(frame.stack, stack++, stackMap, c, + labels); + } + } + } + frame.offset += delta + 1; + readLabel(frame.offset, labels); + return stackMap; + } + + /** + * Reads a stack map frame type and stores it at the given index in the + * given array. + * + * @param frame + * the array where the parsed type must be stored. + * @param index + * the index in 'frame' where the parsed type must be stored. + * @param v + * the start offset of the stack map frame type to read. + * @param buf + * a buffer to read strings. + * @param labels + * the labels of the method currently being parsed, indexed by + * their offset. If the parsed type is an Uninitialized type, a + * new label for the corresponding NEW instruction is stored in + * this array if it does not already exist. + * @return the offset of the first byte after the parsed type. + */ + private int readFrameType(final Object[] frame, final int index, int v, + final char[] buf, final Label[] labels) { + int type = b[v++] & 0xFF; + switch (type) { + case 0: + frame[index] = Opcodes.TOP; + break; + case 1: + frame[index] = Opcodes.INTEGER; + break; + case 2: + frame[index] = Opcodes.FLOAT; + break; + case 3: + frame[index] = Opcodes.DOUBLE; + break; + case 4: + frame[index] = Opcodes.LONG; + break; + case 5: + frame[index] = Opcodes.NULL; + break; + case 6: + frame[index] = Opcodes.UNINITIALIZED_THIS; + break; + case 7: // Object + frame[index] = readClass(v, buf); + v += 2; + break; + default: // Uninitialized + frame[index] = readLabel(readUnsignedShort(v), labels); + v += 2; + } + return v; + } + + /** + * Returns the label corresponding to the given offset. The default + * implementation of this method creates a label for the given offset if it + * has not been already created. + * + * @param offset + * a bytecode offset in a method. + * @param labels + * the already created labels, indexed by their offset. If a + * label already exists for offset this method must not create a + * new one. Otherwise it must store the new label in this array. + * @return a non null Label, which must be equal to labels[offset]. + */ + protected Label readLabel(int offset, Label[] labels) { + if (labels[offset] == null) { + labels[offset] = new Label(); + } + return labels[offset]; + } + + /** + * Returns the start index of the attribute_info structure of this class. + * + * @return the start index of the attribute_info structure of this class. + */ + private int getAttributes() { + // skips the header + int u = header + 8 + readUnsignedShort(header + 6) * 2; + // skips fields and methods + for (int i = readUnsignedShort(u); i > 0; --i) { + for (int j = readUnsignedShort(u + 8); j > 0; --j) { + u += 6 + readInt(u + 12); + } + u += 8; + } + u += 2; + for (int i = readUnsignedShort(u); i > 0; --i) { + for (int j = readUnsignedShort(u + 8); j > 0; --j) { + u += 6 + readInt(u + 12); + } + u += 8; + } + // the attribute_info structure starts just after the methods + return u + 2; + } + + /** + * Reads an attribute in {@link #b b}. + * + * @param attrs + * prototypes of the attributes that must be parsed during the + * visit of the class. Any attribute whose type is not equal to + * the type of one the prototypes is ignored (i.e. an empty + * {@link Attribute} instance is returned). + * @param type + * the type of the attribute. + * @param off + * index of the first byte of the attribute's content in + * {@link #b b}. The 6 attribute header bytes, containing the + * type and the length of the attribute, are not taken into + * account here (they have already been read). + * @param len + * the length of the attribute's content. + * @param buf + * buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or {@link #readConst + * readConst}. + * @param codeOff + * index of the first byte of code's attribute content in + * {@link #b b}, or -1 if the attribute to be read is not a code + * attribute. The 6 attribute header bytes, containing the type + * and the length of the attribute, are not taken into account + * here. + * @param labels + * the labels of the method's code, or null if the + * attribute to be read is not a code attribute. + * @return the attribute that has been read, or null to skip this + * attribute. + */ + private Attribute readAttribute(final Attribute[] attrs, final String type, + final int off, final int len, final char[] buf, final int codeOff, + final Label[] labels) { + for (int i = 0; i < attrs.length; ++i) { + if (attrs[i].type.equals(type)) { + return attrs[i].read(this, off, len, buf, codeOff, labels); + } + } + return new Attribute(type).read(this, off, len, null, -1, null); + } + + // ------------------------------------------------------------------------ + // Utility methods: low level parsing + // ------------------------------------------------------------------------ + + /** + * Returns the number of constant pool items in {@link #b b}. + * + * @return the number of constant pool items in {@link #b b}. + */ + public int getItemCount() { + return items.length; + } + + /** + * Returns the start index of the constant pool item in {@link #b b}, plus + * one. This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param item + * the index a constant pool item. + * @return the start index of the constant pool item in {@link #b b}, plus + * one. + */ + public int getItem(final int item) { + return items[item]; + } + + /** + * Returns the maximum length of the strings contained in the constant pool + * of the class. + * + * @return the maximum length of the strings contained in the constant pool + * of the class. + */ + public int getMaxStringLength() { + return maxStringLength; + } + + /** + * Reads a byte value in {@link #b b}. This method is intended for + * {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters. + * + * @param index + * the start index of the value to be read in {@link #b b}. + * @return the read value. + */ + public int readByte(final int index) { + return b[index] & 0xFF; + } + + /** + * Reads an unsigned short value in {@link #b b}. This method is intended + * for {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters. + * + * @param index + * the start index of the value to be read in {@link #b b}. + * @return the read value. + */ + public int readUnsignedShort(final int index) { + byte[] b = this.b; + return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); + } + + /** + * Reads a signed short value in {@link #b b}. This method is intended + * for {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters. + * + * @param index + * the start index of the value to be read in {@link #b b}. + * @return the read value. + */ + public short readShort(final int index) { + byte[] b = this.b; + return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); + } + + /** + * Reads a signed int value in {@link #b b}. This method is intended for + * {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters. + * + * @param index + * the start index of the value to be read in {@link #b b}. + * @return the read value. + */ + public int readInt(final int index) { + byte[] b = this.b; + return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) + | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); + } + + /** + * Reads a signed long value in {@link #b b}. This method is intended for + * {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters. + * + * @param index + * the start index of the value to be read in {@link #b b}. + * @return the read value. + */ + public long readLong(final int index) { + long l1 = readInt(index); + long l0 = readInt(index + 4) & 0xFFFFFFFFL; + return (l1 << 32) | l0; + } + + /** + * Reads an UTF8 string constant pool item in {@link #b b}. This method + * is intended for {@link Attribute} sub classes, and is normally not needed + * by class generators or adapters. + * + * @param index + * the start index of an unsigned short value in {@link #b b}, + * whose value is the index of an UTF8 constant pool item. + * @param buf + * buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. + * @return the String corresponding to the specified UTF8 item. + */ + public String readUTF8(int index, final char[] buf) { + int item = readUnsignedShort(index); + if (index == 0 || item == 0) { + return null; + } + String s = strings[item]; + if (s != null) { + return s; + } + index = items[item]; + return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf); + } + + /** + * Reads UTF8 string in {@link #b b}. + * + * @param index + * start offset of the UTF8 string to be read. + * @param utfLen + * length of the UTF8 string to be read. + * @param buf + * buffer to be used to read the string. This buffer must be + * sufficiently large. It is not automatically resized. + * @return the String corresponding to the specified UTF8 string. + */ + private String readUTF(int index, final int utfLen, final char[] buf) { + int endIndex = index + utfLen; + byte[] b = this.b; + int strLen = 0; + int c; + int st = 0; + char cc = 0; + while (index < endIndex) { + c = b[index++]; + switch (st) { + case 0: + c = c & 0xFF; + if (c < 0x80) { // 0xxxxxxx + buf[strLen++] = (char) c; + } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx + cc = (char) (c & 0x1F); + st = 1; + } else { // 1110 xxxx 10xx xxxx 10xx xxxx + cc = (char) (c & 0x0F); + st = 2; + } + break; + + case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char + buf[strLen++] = (char) ((cc << 6) | (c & 0x3F)); + st = 0; + break; + + case 2: // byte 2 of 3-byte char + cc = (char) ((cc << 6) | (c & 0x3F)); + st = 1; + break; + } + } + return new String(buf, 0, strLen); + } + + /** + * Reads a class constant pool item in {@link #b b}. This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters. + * + * @param index + * the start index of an unsigned short value in {@link #b b}, + * whose value is the index of a class constant pool item. + * @param buf + * buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. + * @return the String corresponding to the specified class item. + */ + public String readClass(final int index, final char[] buf) { + // computes the start index of the CONSTANT_Class item in b + // and reads the CONSTANT_Utf8 item designated by + // the first two bytes of this CONSTANT_Class item + return readUTF8(items[readUnsignedShort(index)], buf); + } + + /** + * Reads a numeric or string constant pool item in {@link #b b}. This + * method is intended for {@link Attribute} sub classes, and is normally not + * needed by class generators or adapters. + * + * @param item + * the index of a constant pool item. + * @param buf + * buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. + * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, + * {@link String}, {@link Type} or {@link Handle} corresponding to + * the given constant pool item. + */ + public Object readConst(final int item, final char[] buf) { + int index = items[item]; + switch (b[index - 1]) { + case ClassWriter.INT: + return readInt(index); + case ClassWriter.FLOAT: + return Float.intBitsToFloat(readInt(index)); + case ClassWriter.LONG: + return readLong(index); + case ClassWriter.DOUBLE: + return Double.longBitsToDouble(readLong(index)); + case ClassWriter.CLASS: + return Type.getObjectType(readUTF8(index, buf)); + case ClassWriter.STR: + return readUTF8(index, buf); + case ClassWriter.MTYPE: + return Type.getMethodType(readUTF8(index, buf)); + default: // case ClassWriter.HANDLE_BASE + [1..9]: + int tag = readByte(index); + int[] items = this.items; + int cpIndex = items[readUnsignedShort(index + 1)]; + boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; + String owner = readClass(cpIndex, buf); + cpIndex = items[readUnsignedShort(cpIndex + 2)]; + String name = readUTF8(cpIndex, buf); + String desc = readUTF8(cpIndex + 2, buf); + return new Handle(tag, owner, name, desc, itf); + } + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/ClassVisitor.java b/blade-core/src/main/java/org/objectweb/asm/ClassVisitor.java new file mode 100644 index 000000000..107ada001 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/ClassVisitor.java @@ -0,0 +1,320 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * A visitor to visit a Java class. The methods of this class must be called in + * the following order: visit [ visitSource ] [ + * visitOuterClass ] ( visitAnnotation | + * visitTypeAnnotation | visitAttribute )* ( + * visitInnerClass | visitField | visitMethod )* + * visitEnd. + * + * @author Eric Bruneton + */ +public abstract class ClassVisitor { + + /** + * The ASM API version implemented by this visitor. The value of this field + * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + */ + protected final int api; + + /** + * The class visitor to which this visitor must delegate method calls. May + * be null. + */ + protected ClassVisitor cv; + + /** + * Constructs a new {@link ClassVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + */ + public ClassVisitor(final int api) { + this(api, null); + } + + /** + * Constructs a new {@link ClassVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param cv + * the class visitor to which this visitor must delegate method + * calls. May be null. + */ + public ClassVisitor(final int api, final ClassVisitor cv) { + if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { + throw new IllegalArgumentException(); + } + this.api = api; + this.cv = cv; + } + + /** + * Visits the header of the class. + * + * @param version + * the class version. + * @param access + * the class's access flags (see {@link Opcodes}). This parameter + * also indicates if the class is deprecated. + * @param name + * the internal name of the class (see + * {@link Type#getInternalName() getInternalName}). + * @param signature + * the signature of this class. May be null if the class + * is not a generic one, and does not extend or implement generic + * classes or interfaces. + * @param superName + * the internal of name of the super class (see + * {@link Type#getInternalName() getInternalName}). For + * interfaces, the super class is {@link Object}. May be + * null, but only for the {@link Object} class. + * @param interfaces + * the internal names of the class's interfaces (see + * {@link Type#getInternalName() getInternalName}). May be + * null. + */ + public void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { + if (cv != null) { + cv.visit(version, access, name, signature, superName, interfaces); + } + } + + /** + * Visits the source of the class. + * + * @param source + * the name of the source file from which the class was compiled. + * May be null. + * @param debug + * additional debug information to compute the correspondance + * between source and compiled elements of the class. May be + * null. + */ + public void visitSource(String source, String debug) { + if (cv != null) { + cv.visitSource(source, debug); + } + } + + /** + * Visits the enclosing class of the class. This method must be called only + * if the class has an enclosing class. + * + * @param owner + * internal name of the enclosing class of the class. + * @param name + * the name of the method that contains the class, or + * null if the class is not enclosed in a method of its + * enclosing class. + * @param desc + * the descriptor of the method that contains the class, or + * null if the class is not enclosed in a method of its + * enclosing class. + */ + public void visitOuterClass(String owner, String name, String desc) { + if (cv != null) { + cv.visitOuterClass(owner, name, desc); + } + } + + /** + * Visits an annotation of the class. + * + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + if (cv != null) { + return cv.visitAnnotation(desc, visible); + } + return null; + } + + /** + * Visits an annotation on a type in the class signature. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#CLASS_TYPE_PARAMETER + * CLASS_TYPE_PARAMETER}, + * {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND + * CLASS_TYPE_PARAMETER_BOUND} or + * {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See + * {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (cv != null) { + return cv.visitTypeAnnotation(typeRef, typePath, desc, visible); + } + return null; + } + + /** + * Visits a non standard attribute of the class. + * + * @param attr + * an attribute. + */ + public void visitAttribute(Attribute attr) { + if (cv != null) { + cv.visitAttribute(attr); + } + } + + /** + * Visits information about an inner class. This inner class is not + * necessarily a member of the class being visited. + * + * @param name + * the internal name of an inner class (see + * {@link Type#getInternalName() getInternalName}). + * @param outerName + * the internal name of the class to which the inner class + * belongs (see {@link Type#getInternalName() getInternalName}). + * May be null for not member classes. + * @param innerName + * the (simple) name of the inner class inside its enclosing + * class. May be null for anonymous inner classes. + * @param access + * the access flags of the inner class as originally declared in + * the enclosing class. + */ + public void visitInnerClass(String name, String outerName, + String innerName, int access) { + if (cv != null) { + cv.visitInnerClass(name, outerName, innerName, access); + } + } + + /** + * Visits a field of the class. + * + * @param access + * the field's access flags (see {@link Opcodes}). This parameter + * also indicates if the field is synthetic and/or deprecated. + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link Type Type}). + * @param signature + * the field's signature. May be null if the field's + * type does not use generic types. + * @param value + * the field's initial value. This parameter, which may be + * null if the field does not have an initial value, + * must be an {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double} or a {@link String} (for int, + * float, long or String fields + * respectively). This parameter is only used for static + * fields. Its value is ignored for non static fields, which + * must be initialized through bytecode instructions in + * constructors or methods. + * @return a visitor to visit field annotations and attributes, or + * null if this class visitor is not interested in visiting + * these annotations and attributes. + */ + public FieldVisitor visitField(int access, String name, String desc, + String signature, Object value) { + if (cv != null) { + return cv.visitField(access, name, desc, signature, value); + } + return null; + } + + /** + * Visits a method of the class. This method must return a new + * {@link MethodVisitor} instance (or null) each time it is called, + * i.e., it should not return a previously returned visitor. + * + * @param access + * the method's access flags (see {@link Opcodes}). This + * parameter also indicates if the method is synthetic and/or + * deprecated. + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type Type}). + * @param signature + * the method's signature. May be null if the method + * parameters, return type and exceptions do not use generic + * types. + * @param exceptions + * the internal names of the method's exception classes (see + * {@link Type#getInternalName() getInternalName}). May be + * null. + * @return an object to visit the byte code of the method, or null + * if this class visitor is not interested in visiting the code of + * this method. + */ + public MethodVisitor visitMethod(int access, String name, String desc, + String signature, String[] exceptions) { + if (cv != null) { + return cv.visitMethod(access, name, desc, signature, exceptions); + } + return null; + } + + /** + * Visits the end of the class. This method, which is the last one to be + * called, is used to inform the visitor that all the fields and methods of + * the class have been visited. + */ + public void visitEnd() { + if (cv != null) { + cv.visitEnd(); + } + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/ClassWriter.java b/blade-core/src/main/java/org/objectweb/asm/ClassWriter.java new file mode 100644 index 000000000..f4dd6c631 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/ClassWriter.java @@ -0,0 +1,1811 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * A {@link ClassVisitor} that generates classes in bytecode form. More + * precisely this visitor generates a byte array conforming to the Java class + * file format. It can be used alone, to generate a Java class "from scratch", + * or with one or more {@link ClassReader ClassReader} and adapter class visitor + * to generate a modified class from one or more existing Java classes. + * + * @author Eric Bruneton + */ +public class ClassWriter extends ClassVisitor { + + /** + * Flag to automatically compute the maximum stack size and the maximum + * number of local variables of methods. If this flag is set, then the + * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the + * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod} + * method will be ignored, and computed automatically from the signature and + * the bytecode of each method. + * + * @see #ClassWriter(int) + */ + public static final int COMPUTE_MAXS = 1; + + /** + * Flag to automatically compute the stack map frames of methods from + * scratch. If this flag is set, then the calls to the + * {@link MethodVisitor#visitFrame} method are ignored, and the stack map + * frames are recomputed from the methods bytecode. The arguments of the + * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and + * recomputed from the bytecode. In other words, computeFrames implies + * computeMaxs. + * + * @see #ClassWriter(int) + */ + public static final int COMPUTE_FRAMES = 2; + + /** + * Pseudo access flag to distinguish between the synthetic attribute and the + * synthetic access flag. + */ + static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000; + + /** + * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC. + */ + static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE + / Opcodes.ACC_SYNTHETIC; + + /** + * The type of instructions without any argument. + */ + static final int NOARG_INSN = 0; + + /** + * The type of instructions with an signed byte argument. + */ + static final int SBYTE_INSN = 1; + + /** + * The type of instructions with an signed short argument. + */ + static final int SHORT_INSN = 2; + + /** + * The type of instructions with a local variable index argument. + */ + static final int VAR_INSN = 3; + + /** + * The type of instructions with an implicit local variable index argument. + */ + static final int IMPLVAR_INSN = 4; + + /** + * The type of instructions with a type descriptor argument. + */ + static final int TYPE_INSN = 5; + + /** + * The type of field and method invocations instructions. + */ + static final int FIELDORMETH_INSN = 6; + + /** + * The type of the INVOKEINTERFACE/INVOKEDYNAMIC instruction. + */ + static final int ITFMETH_INSN = 7; + + /** + * The type of the INVOKEDYNAMIC instruction. + */ + static final int INDYMETH_INSN = 8; + + /** + * The type of instructions with a 2 bytes bytecode offset label. + */ + static final int LABEL_INSN = 9; + + /** + * The type of instructions with a 4 bytes bytecode offset label. + */ + static final int LABELW_INSN = 10; + + /** + * The type of the LDC instruction. + */ + static final int LDC_INSN = 11; + + /** + * The type of the LDC_W and LDC2_W instructions. + */ + static final int LDCW_INSN = 12; + + /** + * The type of the IINC instruction. + */ + static final int IINC_INSN = 13; + + /** + * The type of the TABLESWITCH instruction. + */ + static final int TABL_INSN = 14; + + /** + * The type of the LOOKUPSWITCH instruction. + */ + static final int LOOK_INSN = 15; + + /** + * The type of the MULTIANEWARRAY instruction. + */ + static final int MANA_INSN = 16; + + /** + * The type of the WIDE instruction. + */ + static final int WIDE_INSN = 17; + + /** + * The instruction types of all JVM opcodes. + */ + static final byte[] TYPE; + + /** + * The type of CONSTANT_Class constant pool items. + */ + static final int CLASS = 7; + + /** + * The type of CONSTANT_Fieldref constant pool items. + */ + static final int FIELD = 9; + + /** + * The type of CONSTANT_Methodref constant pool items. + */ + static final int METH = 10; + + /** + * The type of CONSTANT_InterfaceMethodref constant pool items. + */ + static final int IMETH = 11; + + /** + * The type of CONSTANT_String constant pool items. + */ + static final int STR = 8; + + /** + * The type of CONSTANT_Integer constant pool items. + */ + static final int INT = 3; + + /** + * The type of CONSTANT_Float constant pool items. + */ + static final int FLOAT = 4; + + /** + * The type of CONSTANT_Long constant pool items. + */ + static final int LONG = 5; + + /** + * The type of CONSTANT_Double constant pool items. + */ + static final int DOUBLE = 6; + + /** + * The type of CONSTANT_NameAndType constant pool items. + */ + static final int NAME_TYPE = 12; + + /** + * The type of CONSTANT_Utf8 constant pool items. + */ + static final int UTF8 = 1; + + /** + * The type of CONSTANT_MethodType constant pool items. + */ + static final int MTYPE = 16; + + /** + * The type of CONSTANT_MethodHandle constant pool items. + */ + static final int HANDLE = 15; + + /** + * The type of CONSTANT_InvokeDynamic constant pool items. + */ + static final int INDY = 18; + + /** + * The base value for all CONSTANT_MethodHandle constant pool items. + * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9 + * different items. + */ + static final int HANDLE_BASE = 20; + + /** + * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable}, + * instead of the constant pool, in order to avoid clashes with normal + * constant pool items in the ClassWriter constant pool's hash table. + */ + static final int TYPE_NORMAL = 30; + + /** + * Uninitialized type Item stored in the ClassWriter + * {@link ClassWriter#typeTable}, instead of the constant pool, in order to + * avoid clashes with normal constant pool items in the ClassWriter constant + * pool's hash table. + */ + static final int TYPE_UNINIT = 31; + + /** + * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable}, + * instead of the constant pool, in order to avoid clashes with normal + * constant pool items in the ClassWriter constant pool's hash table. + */ + static final int TYPE_MERGED = 32; + + /** + * The type of BootstrapMethods items. These items are stored in a special + * class attribute named BootstrapMethods and not in the constant pool. + */ + static final int BSM = 33; + + /** + * The class reader from which this class writer was constructed, if any. + */ + ClassReader cr; + + /** + * Minor and major version numbers of the class to be generated. + */ + int version; + + /** + * Index of the next item to be added in the constant pool. + */ + int index; + + /** + * The constant pool of this class. + */ + final ByteVector pool; + + /** + * The constant pool's hash table data. + */ + Item[] items; + + /** + * The threshold of the constant pool's hash table. + */ + int threshold; + + /** + * A reusable key used to look for items in the {@link #items} hash table. + */ + final Item key; + + /** + * A reusable key used to look for items in the {@link #items} hash table. + */ + final Item key2; + + /** + * A reusable key used to look for items in the {@link #items} hash table. + */ + final Item key3; + + /** + * A reusable key used to look for items in the {@link #items} hash table. + */ + final Item key4; + + /** + * A type table used to temporarily store internal names that will not + * necessarily be stored in the constant pool. This type table is used by + * the control flow and data flow analysis algorithm used to compute stack + * map frames from scratch. This array associates to each index i + * the Item whose index is i. All Item objects stored in this array + * are also stored in the {@link #items} hash table. These two arrays allow + * to retrieve an Item from its index or, conversely, to get the index of an + * Item from its value. Each Item stores an internal name in its + * {@link Item#strVal1} field. + */ + Item[] typeTable; + + /** + * Number of elements in the {@link #typeTable} array. + */ + private short typeCount; + + /** + * The access flags of this class. + */ + private int access; + + /** + * The constant pool item that contains the internal name of this class. + */ + private int name; + + /** + * The internal name of this class. + */ + String thisName; + + /** + * The constant pool item that contains the signature of this class. + */ + private int signature; + + /** + * The constant pool item that contains the internal name of the super class + * of this class. + */ + private int superName; + + /** + * Number of interfaces implemented or extended by this class or interface. + */ + private int interfaceCount; + + /** + * The interfaces implemented or extended by this class or interface. More + * precisely, this array contains the indexes of the constant pool items + * that contain the internal names of these interfaces. + */ + private int[] interfaces; + + /** + * The index of the constant pool item that contains the name of the source + * file from which this class was compiled. + */ + private int sourceFile; + + /** + * The SourceDebug attribute of this class. + */ + private ByteVector sourceDebug; + + /** + * The constant pool item that contains the name of the enclosing class of + * this class. + */ + private int enclosingMethodOwner; + + /** + * The constant pool item that contains the name and descriptor of the + * enclosing method of this class. + */ + private int enclosingMethod; + + /** + * The runtime visible annotations of this class. + */ + private AnnotationWriter anns; + + /** + * The runtime invisible annotations of this class. + */ + private AnnotationWriter ianns; + + /** + * The runtime visible type annotations of this class. + */ + private AnnotationWriter tanns; + + /** + * The runtime invisible type annotations of this class. + */ + private AnnotationWriter itanns; + + /** + * The non standard attributes of this class. + */ + private Attribute attrs; + + /** + * The number of entries in the InnerClasses attribute. + */ + private int innerClassesCount; + + /** + * The InnerClasses attribute. + */ + private ByteVector innerClasses; + + /** + * The number of entries in the BootstrapMethods attribute. + */ + int bootstrapMethodsCount; + + /** + * The BootstrapMethods attribute. + */ + ByteVector bootstrapMethods; + + /** + * The fields of this class. These fields are stored in a linked list of + * {@link FieldWriter} objects, linked to each other by their + * {@link FieldWriter#fv} field. This field stores the first element of this + * list. + */ + FieldWriter firstField; + + /** + * The fields of this class. These fields are stored in a linked list of + * {@link FieldWriter} objects, linked to each other by their + * {@link FieldWriter#fv} field. This field stores the last element of this + * list. + */ + FieldWriter lastField; + + /** + * The methods of this class. These methods are stored in a linked list of + * {@link MethodWriter} objects, linked to each other by their + * {@link MethodWriter#mv} field. This field stores the first element of + * this list. + */ + MethodWriter firstMethod; + + /** + * The methods of this class. These methods are stored in a linked list of + * {@link MethodWriter} objects, linked to each other by their + * {@link MethodWriter#mv} field. This field stores the last element of this + * list. + */ + MethodWriter lastMethod; + + /** + * true if the maximum stack size and number of local variables + * must be automatically computed. + */ + private boolean computeMaxs; + + /** + * true if the stack map frames must be recomputed from scratch. + */ + private boolean computeFrames; + + /** + * true if the stack map tables of this class are invalid. The + * {@link MethodWriter#resizeInstructions} method cannot transform existing + * stack map tables, and so produces potentially invalid classes when it is + * executed. In this case the class is reread and rewritten with the + * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize + * stack map tables when this option is used). + */ + boolean invalidFrames; + + // ------------------------------------------------------------------------ + // Static initializer + // ------------------------------------------------------------------------ + + /** + * Computes the instruction types of JVM opcodes. + */ + static { + int i; + byte[] b = new byte[220]; + String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" + + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA" + + "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ"; + for (i = 0; i < b.length; ++i) { + b[i] = (byte) (s.charAt(i) - 'A'); + } + TYPE = b; + + // code to generate the above string + // + // // SBYTE_INSN instructions + // b[Constants.NEWARRAY] = SBYTE_INSN; + // b[Constants.BIPUSH] = SBYTE_INSN; + // + // // SHORT_INSN instructions + // b[Constants.SIPUSH] = SHORT_INSN; + // + // // (IMPL)VAR_INSN instructions + // b[Constants.RET] = VAR_INSN; + // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) { + // b[i] = VAR_INSN; + // } + // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) { + // b[i] = VAR_INSN; + // } + // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3 + // b[i] = IMPLVAR_INSN; + // } + // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3 + // b[i] = IMPLVAR_INSN; + // } + // + // // TYPE_INSN instructions + // b[Constants.NEW] = TYPE_INSN; + // b[Constants.ANEWARRAY] = TYPE_INSN; + // b[Constants.CHECKCAST] = TYPE_INSN; + // b[Constants.INSTANCEOF] = TYPE_INSN; + // + // // (Set)FIELDORMETH_INSN instructions + // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) { + // b[i] = FIELDORMETH_INSN; + // } + // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN; + // b[Constants.INVOKEDYNAMIC] = INDYMETH_INSN; + // + // // LABEL(W)_INSN instructions + // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) { + // b[i] = LABEL_INSN; + // } + // b[Constants.IFNULL] = LABEL_INSN; + // b[Constants.IFNONNULL] = LABEL_INSN; + // b[200] = LABELW_INSN; // GOTO_W + // b[201] = LABELW_INSN; // JSR_W + // // temporary opcodes used internally by ASM - see Label and + // MethodWriter + // for (i = 202; i < 220; ++i) { + // b[i] = LABEL_INSN; + // } + // + // // LDC(_W) instructions + // b[Constants.LDC] = LDC_INSN; + // b[19] = LDCW_INSN; // LDC_W + // b[20] = LDCW_INSN; // LDC2_W + // + // // special instructions + // b[Constants.IINC] = IINC_INSN; + // b[Constants.TABLESWITCH] = TABL_INSN; + // b[Constants.LOOKUPSWITCH] = LOOK_INSN; + // b[Constants.MULTIANEWARRAY] = MANA_INSN; + // b[196] = WIDE_INSN; // WIDE + // + // for (i = 0; i < b.length; ++i) { + // System.err.print((char)('A' + b[i])); + // } + // System.err.println(); + } + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link ClassWriter} object. + * + * @param flags + * option flags that can be used to modify the default behavior + * of this class. See {@link #COMPUTE_MAXS}, + * {@link #COMPUTE_FRAMES}. + */ + public ClassWriter(final int flags) { + super(Opcodes.ASM5); + index = 1; + pool = new ByteVector(); + items = new Item[256]; + threshold = (int) (0.75d * items.length); + key = new Item(); + key2 = new Item(); + key3 = new Item(); + key4 = new Item(); + this.computeMaxs = (flags & COMPUTE_MAXS) != 0; + this.computeFrames = (flags & COMPUTE_FRAMES) != 0; + } + + /** + * Constructs a new {@link ClassWriter} object and enables optimizations for + * "mostly add" bytecode transformations. These optimizations are the + * following: + * + *
    + *
  • The constant pool from the original class is copied as is in the new + * class, which saves time. New constant pool entries will be added at the + * end if necessary, but unused constant pool entries won't be + * removed.
  • + *
  • Methods that are not transformed are copied as is in the new class, + * directly from the original class bytecode (i.e. without emitting visit + * events for all the method instructions), which saves a lot of + * time. Untransformed methods are detected by the fact that the + * {@link ClassReader} receives {@link MethodVisitor} objects that come from + * a {@link ClassWriter} (and not from any other {@link ClassVisitor} + * instance).
  • + *
+ * + * @param classReader + * the {@link ClassReader} used to read the original class. It + * will be used to copy the entire constant pool from the + * original class and also to copy other fragments of original + * bytecode where applicable. + * @param flags + * option flags that can be used to modify the default behavior + * of this class. These option flags do not affect methods + * that are copied as is in the new class. This means that the + * maximum stack size nor the stack frames will be computed for + * these methods. See {@link #COMPUTE_MAXS}, + * {@link #COMPUTE_FRAMES}. + */ + public ClassWriter(final ClassReader classReader, final int flags) { + this(flags); + classReader.copyPool(this); + this.cr = classReader; + } + + // ------------------------------------------------------------------------ + // Implementation of the ClassVisitor abstract class + // ------------------------------------------------------------------------ + + @Override + public final void visit(final int version, final int access, + final String name, final String signature, final String superName, + final String[] interfaces) { + this.version = version; + this.access = access; + this.name = newClass(name); + thisName = name; + if (ClassReader.SIGNATURES && signature != null) { + this.signature = newUTF8(signature); + } + this.superName = superName == null ? 0 : newClass(superName); + if (interfaces != null && interfaces.length > 0) { + interfaceCount = interfaces.length; + this.interfaces = new int[interfaceCount]; + for (int i = 0; i < interfaceCount; ++i) { + this.interfaces[i] = newClass(interfaces[i]); + } + } + } + + @Override + public final void visitSource(final String file, final String debug) { + if (file != null) { + sourceFile = newUTF8(file); + } + if (debug != null) { + sourceDebug = new ByteVector().encodeUTF8(debug, 0, + Integer.MAX_VALUE); + } + } + + @Override + public final void visitOuterClass(final String owner, final String name, + final String desc) { + enclosingMethodOwner = newClass(owner); + if (name != null && desc != null) { + enclosingMethod = newNameType(name, desc); + } + } + + @Override + public final AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write type, and reserve space for values count + bv.putShort(newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); + if (visible) { + aw.next = anns; + anns = aw; + } else { + aw.next = ianns; + ianns = aw; + } + return aw; + } + + @Override + public final AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, final String desc, final boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + AnnotationWriter.putTarget(typeRef, typePath, bv); + // write type, and reserve space for values count + bv.putShort(newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = tanns; + tanns = aw; + } else { + aw.next = itanns; + itanns = aw; + } + return aw; + } + + @Override + public final void visitAttribute(final Attribute attr) { + attr.next = attrs; + attrs = attr; + } + + @Override + public final void visitInnerClass(final String name, + final String outerName, final String innerName, final int access) { + if (innerClasses == null) { + innerClasses = new ByteVector(); + } + // Sec. 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the + // constant_pool table which represents a class or interface C that is + // not a package member must have exactly one corresponding entry in the + // classes array". To avoid duplicates we keep track in the intVal field + // of the Item of each CONSTANT_Class_info entry C whether an inner + // class entry has already been added for C (this field is unused for + // class entries, and changing its value does not change the hashcode + // and equality tests). If so we store the index of this inner class + // entry (plus one) in intVal. This hack allows duplicate detection in + // O(1) time. + Item nameItem = newClassItem(name); + if (nameItem.intVal == 0) { + ++innerClassesCount; + innerClasses.putShort(nameItem.index); + innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); + innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); + innerClasses.putShort(access); + nameItem.intVal = innerClassesCount; + } else { + // Compare the inner classes entry nameItem.intVal - 1 with the + // arguments of this method and throw an exception if there is a + // difference? + } + } + + @Override + public final FieldVisitor visitField(final int access, final String name, + final String desc, final String signature, final Object value) { + return new FieldWriter(this, access, name, desc, signature, value); + } + + @Override + public final MethodVisitor visitMethod(final int access, final String name, + final String desc, final String signature, final String[] exceptions) { + return new MethodWriter(this, access, name, desc, signature, + exceptions, computeMaxs, computeFrames); + } + + @Override + public final void visitEnd() { + } + + // ------------------------------------------------------------------------ + // Other public methods + // ------------------------------------------------------------------------ + + /** + * Returns the bytecode of the class that was build with this class writer. + * + * @return the bytecode of the class that was build with this class writer. + */ + public byte[] toByteArray() { + if (index > 0xFFFF) { + throw new RuntimeException("Class file too large!"); + } + // computes the real size of the bytecode of this class + int size = 24 + 2 * interfaceCount; + int nbFields = 0; + FieldWriter fb = firstField; + while (fb != null) { + ++nbFields; + size += fb.getSize(); + fb = (FieldWriter) fb.fv; + } + int nbMethods = 0; + MethodWriter mb = firstMethod; + while (mb != null) { + ++nbMethods; + size += mb.getSize(); + mb = (MethodWriter) mb.mv; + } + int attributeCount = 0; + if (bootstrapMethods != null) { + // we put it as first attribute in order to improve a bit + // ClassReader.copyBootstrapMethods + ++attributeCount; + size += 8 + bootstrapMethods.length; + newUTF8("BootstrapMethods"); + } + if (ClassReader.SIGNATURES && signature != 0) { + ++attributeCount; + size += 8; + newUTF8("Signature"); + } + if (sourceFile != 0) { + ++attributeCount; + size += 8; + newUTF8("SourceFile"); + } + if (sourceDebug != null) { + ++attributeCount; + size += sourceDebug.length + 6; + newUTF8("SourceDebugExtension"); + } + if (enclosingMethodOwner != 0) { + ++attributeCount; + size += 10; + newUTF8("EnclosingMethod"); + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + ++attributeCount; + size += 6; + newUTF8("Deprecated"); + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((version & 0xFFFF) < Opcodes.V1_5 + || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) { + ++attributeCount; + size += 6; + newUTF8("Synthetic"); + } + } + if (innerClasses != null) { + ++attributeCount; + size += 8 + innerClasses.length; + newUTF8("InnerClasses"); + } + if (ClassReader.ANNOTATIONS && anns != null) { + ++attributeCount; + size += 8 + anns.getSize(); + newUTF8("RuntimeVisibleAnnotations"); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + ++attributeCount; + size += 8 + ianns.getSize(); + newUTF8("RuntimeInvisibleAnnotations"); + } + if (ClassReader.ANNOTATIONS && tanns != null) { + ++attributeCount; + size += 8 + tanns.getSize(); + newUTF8("RuntimeVisibleTypeAnnotations"); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + ++attributeCount; + size += 8 + itanns.getSize(); + newUTF8("RuntimeInvisibleTypeAnnotations"); + } + if (attrs != null) { + attributeCount += attrs.getCount(); + size += attrs.getSize(this, null, 0, -1, -1); + } + size += pool.length; + // allocates a byte vector of this size, in order to avoid unnecessary + // arraycopy operations in the ByteVector.enlarge() method + ByteVector out = new ByteVector(size); + out.putInt(0xCAFEBABE).putInt(version); + out.putShort(index).putByteArray(pool.data, 0, pool.length); + int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE + | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC); + out.putShort(access & ~mask).putShort(name).putShort(superName); + out.putShort(interfaceCount); + for (int i = 0; i < interfaceCount; ++i) { + out.putShort(interfaces[i]); + } + out.putShort(nbFields); + fb = firstField; + while (fb != null) { + fb.put(out); + fb = (FieldWriter) fb.fv; + } + out.putShort(nbMethods); + mb = firstMethod; + while (mb != null) { + mb.put(out); + mb = (MethodWriter) mb.mv; + } + out.putShort(attributeCount); + if (bootstrapMethods != null) { + out.putShort(newUTF8("BootstrapMethods")); + out.putInt(bootstrapMethods.length + 2).putShort( + bootstrapMethodsCount); + out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length); + } + if (ClassReader.SIGNATURES && signature != 0) { + out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); + } + if (sourceFile != 0) { + out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); + } + if (sourceDebug != null) { + int len = sourceDebug.length; + out.putShort(newUTF8("SourceDebugExtension")).putInt(len); + out.putByteArray(sourceDebug.data, 0, len); + } + if (enclosingMethodOwner != 0) { + out.putShort(newUTF8("EnclosingMethod")).putInt(4); + out.putShort(enclosingMethodOwner).putShort(enclosingMethod); + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + out.putShort(newUTF8("Deprecated")).putInt(0); + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((version & 0xFFFF) < Opcodes.V1_5 + || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) { + out.putShort(newUTF8("Synthetic")).putInt(0); + } + } + if (innerClasses != null) { + out.putShort(newUTF8("InnerClasses")); + out.putInt(innerClasses.length + 2).putShort(innerClassesCount); + out.putByteArray(innerClasses.data, 0, innerClasses.length); + } + if (ClassReader.ANNOTATIONS && anns != null) { + out.putShort(newUTF8("RuntimeVisibleAnnotations")); + anns.put(out); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + out.putShort(newUTF8("RuntimeInvisibleAnnotations")); + ianns.put(out); + } + if (ClassReader.ANNOTATIONS && tanns != null) { + out.putShort(newUTF8("RuntimeVisibleTypeAnnotations")); + tanns.put(out); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations")); + itanns.put(out); + } + if (attrs != null) { + attrs.put(this, null, 0, -1, -1, out); + } + if (invalidFrames) { + anns = null; + ianns = null; + attrs = null; + innerClassesCount = 0; + innerClasses = null; + bootstrapMethodsCount = 0; + bootstrapMethods = null; + firstField = null; + lastField = null; + firstMethod = null; + lastMethod = null; + computeMaxs = false; + computeFrames = true; + invalidFrames = false; + new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES); + return toByteArray(); + } + return out.data; + } + + // ------------------------------------------------------------------------ + // Utility methods: constant pool management + // ------------------------------------------------------------------------ + + /** + * Adds a number or string constant to the constant pool of the class being + * build. Does nothing if the constant pool already contains a similar item. + * + * @param cst + * the value of the constant to be added to the constant pool. + * This parameter must be an {@link Integer}, a {@link Float}, a + * {@link Long}, a {@link Double}, a {@link String} or a + * {@link Type}. + * @return a new or already existing constant item with the given value. + */ + Item newConstItem(final Object cst) { + if (cst instanceof Integer) { + int val = ((Integer) cst).intValue(); + return newInteger(val); + } else if (cst instanceof Byte) { + int val = ((Byte) cst).intValue(); + return newInteger(val); + } else if (cst instanceof Character) { + int val = ((Character) cst).charValue(); + return newInteger(val); + } else if (cst instanceof Short) { + int val = ((Short) cst).intValue(); + return newInteger(val); + } else if (cst instanceof Boolean) { + int val = ((Boolean) cst).booleanValue() ? 1 : 0; + return newInteger(val); + } else if (cst instanceof Float) { + float val = ((Float) cst).floatValue(); + return newFloat(val); + } else if (cst instanceof Long) { + long val = ((Long) cst).longValue(); + return newLong(val); + } else if (cst instanceof Double) { + double val = ((Double) cst).doubleValue(); + return newDouble(val); + } else if (cst instanceof String) { + return newString((String) cst); + } else if (cst instanceof Type) { + Type t = (Type) cst; + int s = t.getSort(); + if (s == Type.OBJECT) { + return newClassItem(t.getInternalName()); + } else if (s == Type.METHOD) { + return newMethodTypeItem(t.getDescriptor()); + } else { // s == primitive type or array + return newClassItem(t.getDescriptor()); + } + } else if (cst instanceof Handle) { + Handle h = (Handle) cst; + return newHandleItem(h.tag, h.owner, h.name, h.desc, h.itf); + } else { + throw new IllegalArgumentException("value " + cst); + } + } + + /** + * Adds a number or string constant to the constant pool of the class being + * build. Does nothing if the constant pool already contains a similar item. + * This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param cst + * the value of the constant to be added to the constant pool. + * This parameter must be an {@link Integer}, a {@link Float}, a + * {@link Long}, a {@link Double} or a {@link String}. + * @return the index of a new or already existing constant item with the + * given value. + */ + public int newConst(final Object cst) { + return newConstItem(cst).index; + } + + /** + * Adds an UTF8 string to the constant pool of the class being build. Does + * nothing if the constant pool already contains a similar item. This + * method is intended for {@link Attribute} sub classes, and is normally not + * needed by class generators or adapters. + * + * @param value + * the String value. + * @return the index of a new or already existing UTF8 item. + */ + public int newUTF8(final String value) { + key.set(UTF8, value, null, null); + Item result = get(key); + if (result == null) { + pool.putByte(UTF8).putUTF8(value); + result = new Item(index++, key); + put(result); + } + return result.index; + } + + /** + * Adds a class reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param value + * the internal name of the class. + * @return a new or already existing class reference item. + */ + Item newClassItem(final String value) { + key2.set(CLASS, value, null, null); + Item result = get(key2); + if (result == null) { + pool.put12(CLASS, newUTF8(value)); + result = new Item(index++, key2); + put(result); + } + return result; + } + + /** + * Adds a class reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param value + * the internal name of the class. + * @return the index of a new or already existing class reference item. + */ + public int newClass(final String value) { + return newClassItem(value).index; + } + + /** + * Adds a method type reference to the constant pool of the class being + * build. Does nothing if the constant pool already contains a similar item. + * This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param methodDesc + * method descriptor of the method type. + * @return a new or already existing method type reference item. + */ + Item newMethodTypeItem(final String methodDesc) { + key2.set(MTYPE, methodDesc, null, null); + Item result = get(key2); + if (result == null) { + pool.put12(MTYPE, newUTF8(methodDesc)); + result = new Item(index++, key2); + put(result); + } + return result; + } + + /** + * Adds a method type reference to the constant pool of the class being + * build. Does nothing if the constant pool already contains a similar item. + * This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param methodDesc + * method descriptor of the method type. + * @return the index of a new or already existing method type reference + * item. + */ + public int newMethodType(final String methodDesc) { + return newMethodTypeItem(methodDesc).index; + } + + /** + * Adds a handle to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters. + * + * @param tag + * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, + * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, + * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the field or method owner class. + * @param name + * the name of the field or method. + * @param desc + * the descriptor of the field or method. + * @param itf + * true if the owner is an interface. + * @return a new or an already existing method type reference item. + */ + Item newHandleItem(final int tag, final String owner, final String name, + final String desc, final boolean itf) { + key4.set(HANDLE_BASE + tag, owner, name, desc); + Item result = get(key4); + if (result == null) { + if (tag <= Opcodes.H_PUTSTATIC) { + put112(HANDLE, tag, newField(owner, name, desc)); + } else { + put112(HANDLE, + tag, + newMethod(owner, name, desc, itf)); + } + result = new Item(index++, key4); + put(result); + } + return result; + } + + /** + * Adds a handle to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters. + * + * @param tag + * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, + * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, + * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the field or method owner class. + * @param name + * the name of the field or method. + * @param desc + * the descriptor of the field or method. + * @return the index of a new or already existing method type reference + * item. + * + * @deprecated this method is superseded by + * {@link #newHandle(int, String, String, String, boolean)}. + */ + @Deprecated + public int newHandle(final int tag, final String owner, final String name, + final String desc) { + return newHandle(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE); + } + + /** + * Adds a handle to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters. + * + * @param tag + * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, + * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, + * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the field or method owner class. + * @param name + * the name of the field or method. + * @param desc + * the descriptor of the field or method. + * @param itf + * true if the owner is an interface. + * @return the index of a new or already existing method type reference + * item. + */ + public int newHandle(final int tag, final String owner, final String name, + final String desc, final boolean itf) { + return newHandleItem(tag, owner, name, desc, itf).index; + } + + /** + * Adds an invokedynamic reference to the constant pool of the class being + * build. Does nothing if the constant pool already contains a similar item. + * This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param name + * name of the invoked method. + * @param desc + * descriptor of the invoke method. + * @param bsm + * the bootstrap method. + * @param bsmArgs + * the bootstrap method constant arguments. + * + * @return a new or an already existing invokedynamic type reference item. + */ + Item newInvokeDynamicItem(final String name, final String desc, + final Handle bsm, final Object... bsmArgs) { + // cache for performance + ByteVector bootstrapMethods = this.bootstrapMethods; + if (bootstrapMethods == null) { + bootstrapMethods = this.bootstrapMethods = new ByteVector(); + } + + int position = bootstrapMethods.length; // record current position + + int hashCode = bsm.hashCode(); + bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name, + bsm.desc, bsm.isInterface())); + + int argsLength = bsmArgs.length; + bootstrapMethods.putShort(argsLength); + + for (int i = 0; i < argsLength; i++) { + Object bsmArg = bsmArgs[i]; + hashCode ^= bsmArg.hashCode(); + bootstrapMethods.putShort(newConst(bsmArg)); + } + + byte[] data = bootstrapMethods.data; + int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments) + hashCode &= 0x7FFFFFFF; + Item result = items[hashCode % items.length]; + loop: while (result != null) { + if (result.type != BSM || result.hashCode != hashCode) { + result = result.next; + continue; + } + + // because the data encode the size of the argument + // we don't need to test if these size are equals + int resultPosition = result.intVal; + for (int p = 0; p < length; p++) { + if (data[position + p] != data[resultPosition + p]) { + result = result.next; + continue loop; + } + } + break; + } + + int bootstrapMethodIndex; + if (result != null) { + bootstrapMethodIndex = result.index; + bootstrapMethods.length = position; // revert to old position + } else { + bootstrapMethodIndex = bootstrapMethodsCount++; + result = new Item(bootstrapMethodIndex); + result.set(position, hashCode); + put(result); + } + + // now, create the InvokeDynamic constant + key3.set(name, desc, bootstrapMethodIndex); + result = get(key3); + if (result == null) { + put122(INDY, bootstrapMethodIndex, newNameType(name, desc)); + result = new Item(index++, key3); + put(result); + } + return result; + } + + /** + * Adds an invokedynamic reference to the constant pool of the class being + * build. Does nothing if the constant pool already contains a similar item. + * This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param name + * name of the invoked method. + * @param desc + * descriptor of the invoke method. + * @param bsm + * the bootstrap method. + * @param bsmArgs + * the bootstrap method constant arguments. + * + * @return the index of a new or already existing invokedynamic reference + * item. + */ + public int newInvokeDynamic(final String name, final String desc, + final Handle bsm, final Object... bsmArgs) { + return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index; + } + + /** + * Adds a field reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * + * @param owner + * the internal name of the field's owner class. + * @param name + * the field's name. + * @param desc + * the field's descriptor. + * @return a new or already existing field reference item. + */ + Item newFieldItem(final String owner, final String name, final String desc) { + key3.set(FIELD, owner, name, desc); + Item result = get(key3); + if (result == null) { + put122(FIELD, newClass(owner), newNameType(name, desc)); + result = new Item(index++, key3); + put(result); + } + return result; + } + + /** + * Adds a field reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param owner + * the internal name of the field's owner class. + * @param name + * the field's name. + * @param desc + * the field's descriptor. + * @return the index of a new or already existing field reference item. + */ + public int newField(final String owner, final String name, final String desc) { + return newFieldItem(owner, name, desc).index; + } + + /** + * Adds a method reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * + * @param owner + * the internal name of the method's owner class. + * @param name + * the method's name. + * @param desc + * the method's descriptor. + * @param itf + * true if owner is an interface. + * @return a new or already existing method reference item. + */ + Item newMethodItem(final String owner, final String name, + final String desc, final boolean itf) { + int type = itf ? IMETH : METH; + key3.set(type, owner, name, desc); + Item result = get(key3); + if (result == null) { + put122(type, newClass(owner), newNameType(name, desc)); + result = new Item(index++, key3); + put(result); + } + return result; + } + + /** + * Adds a method reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param owner + * the internal name of the method's owner class. + * @param name + * the method's name. + * @param desc + * the method's descriptor. + * @param itf + * true if owner is an interface. + * @return the index of a new or already existing method reference item. + */ + public int newMethod(final String owner, final String name, + final String desc, final boolean itf) { + return newMethodItem(owner, name, desc, itf).index; + } + + /** + * Adds an integer to the constant pool of the class being build. Does + * nothing if the constant pool already contains a similar item. + * + * @param value + * the int value. + * @return a new or already existing int item. + */ + Item newInteger(final int value) { + key.set(value); + Item result = get(key); + if (result == null) { + pool.putByte(INT).putInt(value); + result = new Item(index++, key); + put(result); + } + return result; + } + + /** + * Adds a float to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. + * + * @param value + * the float value. + * @return a new or already existing float item. + */ + Item newFloat(final float value) { + key.set(value); + Item result = get(key); + if (result == null) { + pool.putByte(FLOAT).putInt(key.intVal); + result = new Item(index++, key); + put(result); + } + return result; + } + + /** + * Adds a long to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. + * + * @param value + * the long value. + * @return a new or already existing long item. + */ + Item newLong(final long value) { + key.set(value); + Item result = get(key); + if (result == null) { + pool.putByte(LONG).putLong(value); + result = new Item(index, key); + index += 2; + put(result); + } + return result; + } + + /** + * Adds a double to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. + * + * @param value + * the double value. + * @return a new or already existing double item. + */ + Item newDouble(final double value) { + key.set(value); + Item result = get(key); + if (result == null) { + pool.putByte(DOUBLE).putLong(key.longVal); + result = new Item(index, key); + index += 2; + put(result); + } + return result; + } + + /** + * Adds a string to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. + * + * @param value + * the String value. + * @return a new or already existing string item. + */ + private Item newString(final String value) { + key2.set(STR, value, null, null); + Item result = get(key2); + if (result == null) { + pool.put12(STR, newUTF8(value)); + result = new Item(index++, key2); + put(result); + } + return result; + } + + /** + * Adds a name and type to the constant pool of the class being build. Does + * nothing if the constant pool already contains a similar item. This + * method is intended for {@link Attribute} sub classes, and is normally not + * needed by class generators or adapters. + * + * @param name + * a name. + * @param desc + * a type descriptor. + * @return the index of a new or already existing name and type item. + */ + public int newNameType(final String name, final String desc) { + return newNameTypeItem(name, desc).index; + } + + /** + * Adds a name and type to the constant pool of the class being build. Does + * nothing if the constant pool already contains a similar item. + * + * @param name + * a name. + * @param desc + * a type descriptor. + * @return a new or already existing name and type item. + */ + Item newNameTypeItem(final String name, final String desc) { + key2.set(NAME_TYPE, name, desc, null); + Item result = get(key2); + if (result == null) { + put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); + result = new Item(index++, key2); + put(result); + } + return result; + } + + /** + * Adds the given internal name to {@link #typeTable} and returns its index. + * Does nothing if the type table already contains this internal name. + * + * @param type + * the internal name to be added to the type table. + * @return the index of this internal name in the type table. + */ + int addType(final String type) { + key.set(TYPE_NORMAL, type, null, null); + Item result = get(key); + if (result == null) { + result = addType(key); + } + return result.index; + } + + /** + * Adds the given "uninitialized" type to {@link #typeTable} and returns its + * index. This method is used for UNINITIALIZED types, made of an internal + * name and a bytecode offset. + * + * @param type + * the internal name to be added to the type table. + * @param offset + * the bytecode offset of the NEW instruction that created this + * UNINITIALIZED type value. + * @return the index of this internal name in the type table. + */ + int addUninitializedType(final String type, final int offset) { + key.type = TYPE_UNINIT; + key.intVal = offset; + key.strVal1 = type; + key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset); + Item result = get(key); + if (result == null) { + result = addType(key); + } + return result.index; + } + + /** + * Adds the given Item to {@link #typeTable}. + * + * @param item + * the value to be added to the type table. + * @return the added Item, which a new Item instance with the same value as + * the given Item. + */ + private Item addType(final Item item) { + ++typeCount; + Item result = new Item(typeCount, key); + put(result); + if (typeTable == null) { + typeTable = new Item[16]; + } + if (typeCount == typeTable.length) { + Item[] newTable = new Item[2 * typeTable.length]; + System.arraycopy(typeTable, 0, newTable, 0, typeTable.length); + typeTable = newTable; + } + typeTable[typeCount] = result; + return result; + } + + /** + * Returns the index of the common super type of the two given types. This + * method calls {@link #getCommonSuperClass} and caches the result in the + * {@link #items} hash table to speedup future calls with the same + * parameters. + * + * @param type1 + * index of an internal name in {@link #typeTable}. + * @param type2 + * index of an internal name in {@link #typeTable}. + * @return the index of the common super type of the two given types. + */ + int getMergedType(final int type1, final int type2) { + key2.type = TYPE_MERGED; + key2.longVal = type1 | (((long) type2) << 32); + key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2); + Item result = get(key2); + if (result == null) { + String t = typeTable[type1].strVal1; + String u = typeTable[type2].strVal1; + key2.intVal = addType(getCommonSuperClass(t, u)); + result = new Item((short) 0, key2); + put(result); + } + return result.intVal; + } + + /** + * Returns the common super type of the two given types. The default + * implementation of this method loads the two given classes and uses + * the java.lang.Class methods to find the common super class. It can be + * overridden to compute this common super type in other ways, in particular + * without actually loading any class, or to take into account the class + * that is currently being generated by this ClassWriter, which can of + * course not be loaded since it is under construction. + * + * @param type1 + * the internal name of a class. + * @param type2 + * the internal name of another class. + * @return the internal name of the common super class of the two given + * classes. + */ + protected String getCommonSuperClass(final String type1, final String type2) { + Class c, d; + ClassLoader classLoader = getClass().getClassLoader(); + try { + c = Class.forName(type1.replace('/', '.'), false, classLoader); + d = Class.forName(type2.replace('/', '.'), false, classLoader); + } catch (Exception e) { + throw new RuntimeException(e.toString()); + } + if (c.isAssignableFrom(d)) { + return type1; + } + if (d.isAssignableFrom(c)) { + return type2; + } + if (c.isInterface() || d.isInterface()) { + return "java/lang/Object"; + } else { + do { + c = c.getSuperclass(); + } while (!c.isAssignableFrom(d)); + return c.getName().replace('.', '/'); + } + } + + /** + * Returns the constant pool's hash table item which is equal to the given + * item. + * + * @param key + * a constant pool item. + * @return the constant pool's hash table item which is equal to the given + * item, or null if there is no such item. + */ + private Item get(final Item key) { + Item i = items[key.hashCode % items.length]; + while (i != null && (i.type != key.type || !key.isEqualTo(i))) { + i = i.next; + } + return i; + } + + /** + * Puts the given item in the constant pool's hash table. The hash table + * must not already contains this item. + * + * @param i + * the item to be added to the constant pool's hash table. + */ + private void put(final Item i) { + if (index + typeCount > threshold) { + int ll = items.length; + int nl = ll * 2 + 1; + Item[] newItems = new Item[nl]; + for (int l = ll - 1; l >= 0; --l) { + Item j = items[l]; + while (j != null) { + int index = j.hashCode % newItems.length; + Item k = j.next; + j.next = newItems[index]; + newItems[index] = j; + j = k; + } + } + items = newItems; + threshold = (int) (nl * 0.75); + } + int index = i.hashCode % items.length; + i.next = items[index]; + items[index] = i; + } + + /** + * Puts one byte and two shorts into the constant pool. + * + * @param b + * a byte. + * @param s1 + * a short. + * @param s2 + * another short. + */ + private void put122(final int b, final int s1, final int s2) { + pool.put12(b, s1).putShort(s2); + } + + /** + * Puts two bytes and one short into the constant pool. + * + * @param b1 + * a byte. + * @param b2 + * another byte. + * @param s + * a short. + */ + private void put112(final int b1, final int b2, final int s) { + pool.put11(b1, b2).putShort(s); + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/Context.java b/blade-core/src/main/java/org/objectweb/asm/Context.java new file mode 100644 index 000000000..363b34cf8 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/Context.java @@ -0,0 +1,145 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ + +package org.objectweb.asm; + +/** + * Information about a class being parsed in a {@link ClassReader}. + * + * @author Eric Bruneton + */ +class Context { + + /** + * Prototypes of the attributes that must be parsed for this class. + */ + Attribute[] attrs; + + /** + * The {@link ClassReader} option flags for the parsing of this class. + */ + int flags; + + /** + * The buffer used to read strings. + */ + char[] buffer; + + /** + * The start index of each bootstrap method. + */ + int[] bootstrapMethods; + + /** + * The access flags of the method currently being parsed. + */ + int access; + + /** + * The name of the method currently being parsed. + */ + String name; + + /** + * The descriptor of the method currently being parsed. + */ + String desc; + + /** + * The label objects, indexed by bytecode offset, of the method currently + * being parsed (only bytecode offsets for which a label is needed have a + * non null associated Label object). + */ + Label[] labels; + + /** + * The target of the type annotation currently being parsed. + */ + int typeRef; + + /** + * The path of the type annotation currently being parsed. + */ + TypePath typePath; + + /** + * The offset of the latest stack map frame that has been parsed. + */ + int offset; + + /** + * The labels corresponding to the start of the local variable ranges in the + * local variable type annotation currently being parsed. + */ + Label[] start; + + /** + * The labels corresponding to the end of the local variable ranges in the + * local variable type annotation currently being parsed. + */ + Label[] end; + + /** + * The local variable indices for each local variable range in the local + * variable type annotation currently being parsed. + */ + int[] index; + + /** + * The encoding of the latest stack map frame that has been parsed. + */ + int mode; + + /** + * The number of locals in the latest stack map frame that has been parsed. + */ + int localCount; + + /** + * The number locals in the latest stack map frame that has been parsed, + * minus the number of locals in the previous frame. + */ + int localDiff; + + /** + * The local values of the latest stack map frame that has been parsed. + */ + Object[] local; + + /** + * The stack size of the latest stack map frame that has been parsed. + */ + int stackCount; + + /** + * The stack values of the latest stack map frame that has been parsed. + */ + Object[] stack; +} \ No newline at end of file diff --git a/blade-core/src/main/java/org/objectweb/asm/Edge.java b/blade-core/src/main/java/org/objectweb/asm/Edge.java new file mode 100644 index 000000000..4e87cbaba --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/Edge.java @@ -0,0 +1,75 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * An edge in the control flow graph of a method body. See {@link Label Label}. + * + * @author Eric Bruneton + */ +class Edge { + + /** + * Denotes a normal control flow graph edge. + */ + static final int NORMAL = 0; + + /** + * Denotes a control flow graph edge corresponding to an exception handler. + * More precisely any {@link Edge} whose {@link #info} is strictly positive + * corresponds to an exception handler. The actual value of {@link #info} is + * the index, in the {@link ClassWriter} type table, of the exception that + * is catched. + */ + static final int EXCEPTION = 0x7FFFFFFF; + + /** + * Information about this control flow graph edge. If + * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative) + * stack size in the basic block from which this edge originates. This size + * is equal to the stack size at the "jump" instruction to which this edge + * corresponds, relatively to the stack size at the beginning of the + * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used, + * this field is the kind of this control flow graph edge (i.e. NORMAL or + * EXCEPTION). + */ + int info; + + /** + * The successor block of the basic block from which this edge originates. + */ + Label successor; + + /** + * The next edge in the list of successors of the originating basic block. + * See {@link Label#successors successors}. + */ + Edge next; +} diff --git a/blade-core/src/main/java/org/objectweb/asm/FieldVisitor.java b/blade-core/src/main/java/org/objectweb/asm/FieldVisitor.java new file mode 100644 index 000000000..2372e4c7f --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/FieldVisitor.java @@ -0,0 +1,150 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * A visitor to visit a Java field. The methods of this class must be called in + * the following order: ( visitAnnotation | + * visitTypeAnnotation | visitAttribute )* visitEnd. + * + * @author Eric Bruneton + */ +public abstract class FieldVisitor { + + /** + * The ASM API version implemented by this visitor. The value of this field + * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + */ + protected final int api; + + /** + * The field visitor to which this visitor must delegate method calls. May + * be null. + */ + protected FieldVisitor fv; + + /** + * Constructs a new {@link FieldVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + */ + public FieldVisitor(final int api) { + this(api, null); + } + + /** + * Constructs a new {@link FieldVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param fv + * the field visitor to which this visitor must delegate method + * calls. May be null. + */ + public FieldVisitor(final int api, final FieldVisitor fv) { + if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { + throw new IllegalArgumentException(); + } + this.api = api; + this.fv = fv; + } + + /** + * Visits an annotation of the field. + * + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + if (fv != null) { + return fv.visitAnnotation(desc, visible); + } + return null; + } + + /** + * Visits an annotation on the type of the field. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#FIELD FIELD}. See + * {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (fv != null) { + return fv.visitTypeAnnotation(typeRef, typePath, desc, visible); + } + return null; + } + + /** + * Visits a non standard attribute of the field. + * + * @param attr + * an attribute. + */ + public void visitAttribute(Attribute attr) { + if (fv != null) { + fv.visitAttribute(attr); + } + } + + /** + * Visits the end of the field. This method, which is the last one to be + * called, is used to inform the visitor that all the annotations and + * attributes of the field have been visited. + */ + public void visitEnd() { + if (fv != null) { + fv.visitEnd(); + } + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/FieldWriter.java b/blade-core/src/main/java/org/objectweb/asm/FieldWriter.java new file mode 100644 index 000000000..84d92aae9 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/FieldWriter.java @@ -0,0 +1,329 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * An {@link FieldVisitor} that generates Java fields in bytecode form. + * + * @author Eric Bruneton + */ +final class FieldWriter extends FieldVisitor { + + /** + * The class writer to which this field must be added. + */ + private final ClassWriter cw; + + /** + * Access flags of this field. + */ + private final int access; + + /** + * The index of the constant pool item that contains the name of this + * method. + */ + private final int name; + + /** + * The index of the constant pool item that contains the descriptor of this + * field. + */ + private final int desc; + + /** + * The index of the constant pool item that contains the signature of this + * field. + */ + private int signature; + + /** + * The index of the constant pool item that contains the constant value of + * this field. + */ + private int value; + + /** + * The runtime visible annotations of this field. May be null. + */ + private AnnotationWriter anns; + + /** + * The runtime invisible annotations of this field. May be null. + */ + private AnnotationWriter ianns; + + /** + * The runtime visible type annotations of this field. May be null. + */ + private AnnotationWriter tanns; + + /** + * The runtime invisible type annotations of this field. May be + * null. + */ + private AnnotationWriter itanns; + + /** + * The non standard attributes of this field. May be null. + */ + private Attribute attrs; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link FieldWriter}. + * + * @param cw + * the class writer to which this field must be added. + * @param access + * the field's access flags (see {@link Opcodes}). + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link Type}). + * @param signature + * the field's signature. May be null. + * @param value + * the field's constant value. May be null. + */ + FieldWriter(final ClassWriter cw, final int access, final String name, + final String desc, final String signature, final Object value) { + super(Opcodes.ASM5); + if (cw.firstField == null) { + cw.firstField = this; + } else { + cw.lastField.fv = this; + } + cw.lastField = this; + this.cw = cw; + this.access = access; + this.name = cw.newUTF8(name); + this.desc = cw.newUTF8(desc); + if (ClassReader.SIGNATURES && signature != null) { + this.signature = cw.newUTF8(signature); + } + if (value != null) { + this.value = cw.newConstItem(value).index; + } + } + + // ------------------------------------------------------------------------ + // Implementation of the FieldVisitor abstract class + // ------------------------------------------------------------------------ + + @Override + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); + if (visible) { + aw.next = anns; + anns = aw; + } else { + aw.next = ianns; + ianns = aw; + } + return aw; + } + + @Override + public AnnotationVisitor visitTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + AnnotationWriter.putTarget(typeRef, typePath, bv); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = tanns; + tanns = aw; + } else { + aw.next = itanns; + itanns = aw; + } + return aw; + } + + @Override + public void visitAttribute(final Attribute attr) { + attr.next = attrs; + attrs = attr; + } + + @Override + public void visitEnd() { + } + + // ------------------------------------------------------------------------ + // Utility methods + // ------------------------------------------------------------------------ + + /** + * Returns the size of this field. + * + * @return the size of this field. + */ + int getSize() { + int size = 8; + if (value != 0) { + cw.newUTF8("ConstantValue"); + size += 8; + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + cw.newUTF8("Synthetic"); + size += 6; + } + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + cw.newUTF8("Deprecated"); + size += 6; + } + if (ClassReader.SIGNATURES && signature != 0) { + cw.newUTF8("Signature"); + size += 8; + } + if (ClassReader.ANNOTATIONS && anns != null) { + cw.newUTF8("RuntimeVisibleAnnotations"); + size += 8 + anns.getSize(); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + cw.newUTF8("RuntimeInvisibleAnnotations"); + size += 8 + ianns.getSize(); + } + if (ClassReader.ANNOTATIONS && tanns != null) { + cw.newUTF8("RuntimeVisibleTypeAnnotations"); + size += 8 + tanns.getSize(); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + cw.newUTF8("RuntimeInvisibleTypeAnnotations"); + size += 8 + itanns.getSize(); + } + if (attrs != null) { + size += attrs.getSize(cw, null, 0, -1, -1); + } + return size; + } + + /** + * Puts the content of this field into the given byte vector. + * + * @param out + * where the content of this field must be put. + */ + void put(final ByteVector out) { + final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; + int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE + | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); + out.putShort(access & ~mask).putShort(name).putShort(desc); + int attributeCount = 0; + if (value != 0) { + ++attributeCount; + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + ++attributeCount; + } + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + ++attributeCount; + } + if (ClassReader.SIGNATURES && signature != 0) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && anns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && ianns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && tanns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && itanns != null) { + ++attributeCount; + } + if (attrs != null) { + attributeCount += attrs.getCount(); + } + out.putShort(attributeCount); + if (value != 0) { + out.putShort(cw.newUTF8("ConstantValue")); + out.putInt(2).putShort(value); + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + out.putShort(cw.newUTF8("Synthetic")).putInt(0); + } + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + out.putShort(cw.newUTF8("Deprecated")).putInt(0); + } + if (ClassReader.SIGNATURES && signature != 0) { + out.putShort(cw.newUTF8("Signature")); + out.putInt(2).putShort(signature); + } + if (ClassReader.ANNOTATIONS && anns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); + anns.put(out); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); + ianns.put(out); + } + if (ClassReader.ANNOTATIONS && tanns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); + tanns.put(out); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); + itanns.put(out); + } + if (attrs != null) { + attrs.put(cw, null, 0, -1, -1, out); + } + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/Frame.java b/blade-core/src/main/java/org/objectweb/asm/Frame.java new file mode 100644 index 000000000..1f6106f66 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/Frame.java @@ -0,0 +1,1462 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * Information about the input and output stack map frames of a basic block. + * + * @author Eric Bruneton + */ +final class Frame { + + /* + * Frames are computed in a two steps process: during the visit of each + * instruction, the state of the frame at the end of current basic block is + * updated by simulating the action of the instruction on the previous state + * of this so called "output frame". In visitMaxs, a fix point algorithm is + * used to compute the "input frame" of each basic block, i.e. the stack map + * frame at the beginning of the basic block, starting from the input frame + * of the first basic block (which is computed from the method descriptor), + * and by using the previously computed output frames to compute the input + * state of the other blocks. + * + * All output and input frames are stored as arrays of integers. Reference + * and array types are represented by an index into a type table (which is + * not the same as the constant pool of the class, in order to avoid adding + * unnecessary constants in the pool - not all computed frames will end up + * being stored in the stack map table). This allows very fast type + * comparisons. + * + * Output stack map frames are computed relatively to the input frame of the + * basic block, which is not yet known when output frames are computed. It + * is therefore necessary to be able to represent abstract types such as + * "the type at position x in the input frame locals" or "the type at + * position x from the top of the input frame stack" or even "the type at + * position x in the input frame, with y more (or less) array dimensions". + * This explains the rather complicated type format used in output frames. + * + * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a + * signed number of array dimensions (from -8 to 7). KIND is either BASE, + * LOCAL or STACK. BASE is used for types that are not relative to the input + * frame. LOCAL is used for types that are relative to the input local + * variable types. STACK is used for types that are relative to the input + * stack types. VALUE depends on KIND. For LOCAL types, it is an index in + * the input local variable types. For STACK types, it is a position + * relatively to the top of input frame stack. For BASE types, it is either + * one of the constants defined below, or for OBJECT and UNINITIALIZED + * types, a tag and an index in the type table. + * + * Output frames can contain types of any kind and with a positive or + * negative dimension (and even unassigned types, represented by 0 - which + * does not correspond to any valid type value). Input frames can only + * contain BASE types of positive or null dimension. In all cases the type + * table contains only internal type names (array type descriptors are + * forbidden - dimensions must be represented through the DIM field). + * + * The LONG and DOUBLE types are always represented by using two slots (LONG + * + TOP or DOUBLE + TOP), for local variable types as well as in the + * operand stack. This is necessary to be able to simulate DUPx_y + * instructions, whose effect would be dependent on the actual type values + * if types were always represented by a single slot in the stack (and this + * is not possible, since actual type values are not always known - cf LOCAL + * and STACK type kinds). + */ + + /** + * Mask to get the dimension of a frame type. This dimension is a signed + * integer between -8 and 7. + */ + static final int DIM = 0xF0000000; + + /** + * Constant to be added to a type to get a type with one more dimension. + */ + static final int ARRAY_OF = 0x10000000; + + /** + * Constant to be added to a type to get a type with one less dimension. + */ + static final int ELEMENT_OF = 0xF0000000; + + /** + * Mask to get the kind of a frame type. + * + * @see #BASE + * @see #LOCAL + * @see #STACK + */ + static final int KIND = 0xF000000; + + /** + * Flag used for LOCAL and STACK types. Indicates that if this type happens + * to be a long or double type (during the computations of input frames), + * then it must be set to TOP because the second word of this value has been + * reused to store other data in the basic block. Hence the first word no + * longer stores a valid long or double value. + */ + static final int TOP_IF_LONG_OR_DOUBLE = 0x800000; + + /** + * Mask to get the value of a frame type. + */ + static final int VALUE = 0x7FFFFF; + + /** + * Mask to get the kind of base types. + */ + static final int BASE_KIND = 0xFF00000; + + /** + * Mask to get the value of base types. + */ + static final int BASE_VALUE = 0xFFFFF; + + /** + * Kind of the types that are not relative to an input stack map frame. + */ + static final int BASE = 0x1000000; + + /** + * Base kind of the base reference types. The BASE_VALUE of such types is an + * index into the type table. + */ + static final int OBJECT = BASE | 0x700000; + + /** + * Base kind of the uninitialized base types. The BASE_VALUE of such types + * in an index into the type table (the Item at that index contains both an + * instruction offset and an internal class name). + */ + static final int UNINITIALIZED = BASE | 0x800000; + + /** + * Kind of the types that are relative to the local variable types of an + * input stack map frame. The value of such types is a local variable index. + */ + private static final int LOCAL = 0x2000000; + + /** + * Kind of the the types that are relative to the stack of an input stack + * map frame. The value of such types is a position relatively to the top of + * this stack. + */ + private static final int STACK = 0x3000000; + + /** + * The TOP type. This is a BASE type. + */ + static final int TOP = BASE | 0; + + /** + * The BOOLEAN type. This is a BASE type mainly used for array types. + */ + static final int BOOLEAN = BASE | 9; + + /** + * The BYTE type. This is a BASE type mainly used for array types. + */ + static final int BYTE = BASE | 10; + + /** + * The CHAR type. This is a BASE type mainly used for array types. + */ + static final int CHAR = BASE | 11; + + /** + * The SHORT type. This is a BASE type mainly used for array types. + */ + static final int SHORT = BASE | 12; + + /** + * The INTEGER type. This is a BASE type. + */ + static final int INTEGER = BASE | 1; + + /** + * The FLOAT type. This is a BASE type. + */ + static final int FLOAT = BASE | 2; + + /** + * The DOUBLE type. This is a BASE type. + */ + static final int DOUBLE = BASE | 3; + + /** + * The LONG type. This is a BASE type. + */ + static final int LONG = BASE | 4; + + /** + * The NULL type. This is a BASE type. + */ + static final int NULL = BASE | 5; + + /** + * The UNINITIALIZED_THIS type. This is a BASE type. + */ + static final int UNINITIALIZED_THIS = BASE | 6; + + /** + * The stack size variation corresponding to each JVM instruction. This + * stack variation is equal to the size of the values produced by an + * instruction, minus the size of the values consumed by this instruction. + */ + static final int[] SIZE; + + /** + * Computes the stack size variation corresponding to each JVM instruction. + */ + static { + int i; + int[] b = new int[202]; + String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD" + + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD" + + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED" + + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE"; + for (i = 0; i < b.length; ++i) { + b[i] = s.charAt(i) - 'E'; + } + SIZE = b; + + // code to generate the above string + // + // int NA = 0; // not applicable (unused opcode or variable size opcode) + // + // b = new int[] { + // 0, //NOP, // visitInsn + // 1, //ACONST_NULL, // - + // 1, //ICONST_M1, // - + // 1, //ICONST_0, // - + // 1, //ICONST_1, // - + // 1, //ICONST_2, // - + // 1, //ICONST_3, // - + // 1, //ICONST_4, // - + // 1, //ICONST_5, // - + // 2, //LCONST_0, // - + // 2, //LCONST_1, // - + // 1, //FCONST_0, // - + // 1, //FCONST_1, // - + // 1, //FCONST_2, // - + // 2, //DCONST_0, // - + // 2, //DCONST_1, // - + // 1, //BIPUSH, // visitIntInsn + // 1, //SIPUSH, // - + // 1, //LDC, // visitLdcInsn + // NA, //LDC_W, // - + // NA, //LDC2_W, // - + // 1, //ILOAD, // visitVarInsn + // 2, //LLOAD, // - + // 1, //FLOAD, // - + // 2, //DLOAD, // - + // 1, //ALOAD, // - + // NA, //ILOAD_0, // - + // NA, //ILOAD_1, // - + // NA, //ILOAD_2, // - + // NA, //ILOAD_3, // - + // NA, //LLOAD_0, // - + // NA, //LLOAD_1, // - + // NA, //LLOAD_2, // - + // NA, //LLOAD_3, // - + // NA, //FLOAD_0, // - + // NA, //FLOAD_1, // - + // NA, //FLOAD_2, // - + // NA, //FLOAD_3, // - + // NA, //DLOAD_0, // - + // NA, //DLOAD_1, // - + // NA, //DLOAD_2, // - + // NA, //DLOAD_3, // - + // NA, //ALOAD_0, // - + // NA, //ALOAD_1, // - + // NA, //ALOAD_2, // - + // NA, //ALOAD_3, // - + // -1, //IALOAD, // visitInsn + // 0, //LALOAD, // - + // -1, //FALOAD, // - + // 0, //DALOAD, // - + // -1, //AALOAD, // - + // -1, //BALOAD, // - + // -1, //CALOAD, // - + // -1, //SALOAD, // - + // -1, //ISTORE, // visitVarInsn + // -2, //LSTORE, // - + // -1, //FSTORE, // - + // -2, //DSTORE, // - + // -1, //ASTORE, // - + // NA, //ISTORE_0, // - + // NA, //ISTORE_1, // - + // NA, //ISTORE_2, // - + // NA, //ISTORE_3, // - + // NA, //LSTORE_0, // - + // NA, //LSTORE_1, // - + // NA, //LSTORE_2, // - + // NA, //LSTORE_3, // - + // NA, //FSTORE_0, // - + // NA, //FSTORE_1, // - + // NA, //FSTORE_2, // - + // NA, //FSTORE_3, // - + // NA, //DSTORE_0, // - + // NA, //DSTORE_1, // - + // NA, //DSTORE_2, // - + // NA, //DSTORE_3, // - + // NA, //ASTORE_0, // - + // NA, //ASTORE_1, // - + // NA, //ASTORE_2, // - + // NA, //ASTORE_3, // - + // -3, //IASTORE, // visitInsn + // -4, //LASTORE, // - + // -3, //FASTORE, // - + // -4, //DASTORE, // - + // -3, //AASTORE, // - + // -3, //BASTORE, // - + // -3, //CASTORE, // - + // -3, //SASTORE, // - + // -1, //POP, // - + // -2, //POP2, // - + // 1, //DUP, // - + // 1, //DUP_X1, // - + // 1, //DUP_X2, // - + // 2, //DUP2, // - + // 2, //DUP2_X1, // - + // 2, //DUP2_X2, // - + // 0, //SWAP, // - + // -1, //IADD, // - + // -2, //LADD, // - + // -1, //FADD, // - + // -2, //DADD, // - + // -1, //ISUB, // - + // -2, //LSUB, // - + // -1, //FSUB, // - + // -2, //DSUB, // - + // -1, //IMUL, // - + // -2, //LMUL, // - + // -1, //FMUL, // - + // -2, //DMUL, // - + // -1, //IDIV, // - + // -2, //LDIV, // - + // -1, //FDIV, // - + // -2, //DDIV, // - + // -1, //IREM, // - + // -2, //LREM, // - + // -1, //FREM, // - + // -2, //DREM, // - + // 0, //INEG, // - + // 0, //LNEG, // - + // 0, //FNEG, // - + // 0, //DNEG, // - + // -1, //ISHL, // - + // -1, //LSHL, // - + // -1, //ISHR, // - + // -1, //LSHR, // - + // -1, //IUSHR, // - + // -1, //LUSHR, // - + // -1, //IAND, // - + // -2, //LAND, // - + // -1, //IOR, // - + // -2, //LOR, // - + // -1, //IXOR, // - + // -2, //LXOR, // - + // 0, //IINC, // visitIincInsn + // 1, //I2L, // visitInsn + // 0, //I2F, // - + // 1, //I2D, // - + // -1, //L2I, // - + // -1, //L2F, // - + // 0, //L2D, // - + // 0, //F2I, // - + // 1, //F2L, // - + // 1, //F2D, // - + // -1, //D2I, // - + // 0, //D2L, // - + // -1, //D2F, // - + // 0, //I2B, // - + // 0, //I2C, // - + // 0, //I2S, // - + // -3, //LCMP, // - + // -1, //FCMPL, // - + // -1, //FCMPG, // - + // -3, //DCMPL, // - + // -3, //DCMPG, // - + // -1, //IFEQ, // visitJumpInsn + // -1, //IFNE, // - + // -1, //IFLT, // - + // -1, //IFGE, // - + // -1, //IFGT, // - + // -1, //IFLE, // - + // -2, //IF_ICMPEQ, // - + // -2, //IF_ICMPNE, // - + // -2, //IF_ICMPLT, // - + // -2, //IF_ICMPGE, // - + // -2, //IF_ICMPGT, // - + // -2, //IF_ICMPLE, // - + // -2, //IF_ACMPEQ, // - + // -2, //IF_ACMPNE, // - + // 0, //GOTO, // - + // 1, //JSR, // - + // 0, //RET, // visitVarInsn + // -1, //TABLESWITCH, // visiTableSwitchInsn + // -1, //LOOKUPSWITCH, // visitLookupSwitch + // -1, //IRETURN, // visitInsn + // -2, //LRETURN, // - + // -1, //FRETURN, // - + // -2, //DRETURN, // - + // -1, //ARETURN, // - + // 0, //RETURN, // - + // NA, //GETSTATIC, // visitFieldInsn + // NA, //PUTSTATIC, // - + // NA, //GETFIELD, // - + // NA, //PUTFIELD, // - + // NA, //INVOKEVIRTUAL, // visitMethodInsn + // NA, //INVOKESPECIAL, // - + // NA, //INVOKESTATIC, // - + // NA, //INVOKEINTERFACE, // - + // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn + // 1, //NEW, // visitTypeInsn + // 0, //NEWARRAY, // visitIntInsn + // 0, //ANEWARRAY, // visitTypeInsn + // 0, //ARRAYLENGTH, // visitInsn + // NA, //ATHROW, // - + // 0, //CHECKCAST, // visitTypeInsn + // 0, //INSTANCEOF, // - + // -1, //MONITORENTER, // visitInsn + // -1, //MONITOREXIT, // - + // NA, //WIDE, // NOT VISITED + // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn + // -1, //IFNULL, // visitJumpInsn + // -1, //IFNONNULL, // - + // NA, //GOTO_W, // - + // NA, //JSR_W, // - + // }; + // for (i = 0; i < b.length; ++i) { + // System.err.print((char)('E' + b[i])); + // } + // System.err.println(); + } + + /** + * The label (i.e. basic block) to which these input and output stack map + * frames correspond. + */ + Label owner; + + /** + * The input stack map frame locals. + */ + int[] inputLocals; + + /** + * The input stack map frame stack. + */ + int[] inputStack; + + /** + * The output stack map frame locals. + */ + private int[] outputLocals; + + /** + * The output stack map frame stack. + */ + private int[] outputStack; + + /** + * Relative size of the output stack. The exact semantics of this field + * depends on the algorithm that is used. + * + * When only the maximum stack size is computed, this field is the size of + * the output stack relatively to the top of the input stack. + * + * When the stack map frames are completely computed, this field is the + * actual number of types in {@link #outputStack}. + */ + private int outputStackTop; + + /** + * Number of types that are initialized in the basic block. + * + * @see #initializations + */ + private int initializationCount; + + /** + * The types that are initialized in the basic block. A constructor + * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace + * every occurence of this type in the local variables and in the + * operand stack. This cannot be done during the first phase of the + * algorithm since, during this phase, the local variables and the operand + * stack are not completely computed. It is therefore necessary to store the + * types on which constructors are invoked in the basic block, in order to + * do this replacement during the second phase of the algorithm, where the + * frames are fully computed. Note that this array can contain types that + * are relative to input locals or to the input stack (see below for the + * description of the algorithm). + */ + private int[] initializations; + + /** + * Returns the output frame local variable type at the given index. + * + * @param local + * the index of the local that must be returned. + * @return the output frame local variable type at the given index. + */ + private int get(final int local) { + if (outputLocals == null || local >= outputLocals.length) { + // this local has never been assigned in this basic block, + // so it is still equal to its value in the input frame + return LOCAL | local; + } else { + int type = outputLocals[local]; + if (type == 0) { + // this local has never been assigned in this basic block, + // so it is still equal to its value in the input frame + type = outputLocals[local] = LOCAL | local; + } + return type; + } + } + + /** + * Sets the output frame local variable type at the given index. + * + * @param local + * the index of the local that must be set. + * @param type + * the value of the local that must be set. + */ + private void set(final int local, final int type) { + // creates and/or resizes the output local variables array if necessary + if (outputLocals == null) { + outputLocals = new int[10]; + } + int n = outputLocals.length; + if (local >= n) { + int[] t = new int[Math.max(local + 1, 2 * n)]; + System.arraycopy(outputLocals, 0, t, 0, n); + outputLocals = t; + } + // sets the local variable + outputLocals[local] = type; + } + + /** + * Pushes a new type onto the output frame stack. + * + * @param type + * the type that must be pushed. + */ + private void push(final int type) { + // creates and/or resizes the output stack array if necessary + if (outputStack == null) { + outputStack = new int[10]; + } + int n = outputStack.length; + if (outputStackTop >= n) { + int[] t = new int[Math.max(outputStackTop + 1, 2 * n)]; + System.arraycopy(outputStack, 0, t, 0, n); + outputStack = t; + } + // pushes the type on the output stack + outputStack[outputStackTop++] = type; + // updates the maximun height reached by the output stack, if needed + int top = owner.inputStackTop + outputStackTop; + if (top > owner.outputStackMax) { + owner.outputStackMax = top; + } + } + + /** + * Pushes a new type onto the output frame stack. + * + * @param cw + * the ClassWriter to which this label belongs. + * @param desc + * the descriptor of the type to be pushed. Can also be a method + * descriptor (in this case this method pushes its return type + * onto the output frame stack). + */ + private void push(final ClassWriter cw, final String desc) { + int type = type(cw, desc); + if (type != 0) { + push(type); + if (type == LONG || type == DOUBLE) { + push(TOP); + } + } + } + + /** + * Returns the int encoding of the given type. + * + * @param cw + * the ClassWriter to which this label belongs. + * @param desc + * a type descriptor. + * @return the int encoding of the given type. + */ + private static int type(final ClassWriter cw, final String desc) { + String t; + int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; + switch (desc.charAt(index)) { + case 'V': + return 0; + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + return INTEGER; + case 'F': + return FLOAT; + case 'J': + return LONG; + case 'D': + return DOUBLE; + case 'L': + // stores the internal name, not the descriptor! + t = desc.substring(index + 1, desc.length() - 1); + return OBJECT | cw.addType(t); + // case '[': + default: + // extracts the dimensions and the element type + int data; + int dims = index + 1; + while (desc.charAt(dims) == '[') { + ++dims; + } + switch (desc.charAt(dims)) { + case 'Z': + data = BOOLEAN; + break; + case 'C': + data = CHAR; + break; + case 'B': + data = BYTE; + break; + case 'S': + data = SHORT; + break; + case 'I': + data = INTEGER; + break; + case 'F': + data = FLOAT; + break; + case 'J': + data = LONG; + break; + case 'D': + data = DOUBLE; + break; + // case 'L': + default: + // stores the internal name, not the descriptor + t = desc.substring(dims + 1, desc.length() - 1); + data = OBJECT | cw.addType(t); + } + return (dims - index) << 28 | data; + } + } + + /** + * Pops a type from the output frame stack and returns its value. + * + * @return the type that has been popped from the output frame stack. + */ + private int pop() { + if (outputStackTop > 0) { + return outputStack[--outputStackTop]; + } else { + // if the output frame stack is empty, pops from the input stack + return STACK | -(--owner.inputStackTop); + } + } + + /** + * Pops the given number of types from the output frame stack. + * + * @param elements + * the number of types that must be popped. + */ + private void pop(final int elements) { + if (outputStackTop >= elements) { + outputStackTop -= elements; + } else { + // if the number of elements to be popped is greater than the number + // of elements in the output stack, clear it, and pops the remaining + // elements from the input stack. + owner.inputStackTop -= elements - outputStackTop; + outputStackTop = 0; + } + } + + /** + * Pops a type from the output frame stack. + * + * @param desc + * the descriptor of the type to be popped. Can also be a method + * descriptor (in this case this method pops the types + * corresponding to the method arguments). + */ + private void pop(final String desc) { + char c = desc.charAt(0); + if (c == '(') { + pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1); + } else if (c == 'J' || c == 'D') { + pop(2); + } else { + pop(1); + } + } + + /** + * Adds a new type to the list of types on which a constructor is invoked in + * the basic block. + * + * @param var + * a type on a which a constructor is invoked. + */ + private void init(final int var) { + // creates and/or resizes the initializations array if necessary + if (initializations == null) { + initializations = new int[2]; + } + int n = initializations.length; + if (initializationCount >= n) { + int[] t = new int[Math.max(initializationCount + 1, 2 * n)]; + System.arraycopy(initializations, 0, t, 0, n); + initializations = t; + } + // stores the type to be initialized + initializations[initializationCount++] = var; + } + + /** + * Replaces the given type with the appropriate type if it is one of the + * types on which a constructor is invoked in the basic block. + * + * @param cw + * the ClassWriter to which this label belongs. + * @param t + * a type + * @return t or, if t is one of the types on which a constructor is invoked + * in the basic block, the type corresponding to this constructor. + */ + private int init(final ClassWriter cw, final int t) { + int s; + if (t == UNINITIALIZED_THIS) { + s = OBJECT | cw.addType(cw.thisName); + } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) { + String type = cw.typeTable[t & BASE_VALUE].strVal1; + s = OBJECT | cw.addType(type); + } else { + return t; + } + for (int j = 0; j < initializationCount; ++j) { + int u = initializations[j]; + int dim = u & DIM; + int kind = u & KIND; + if (kind == LOCAL) { + u = dim + inputLocals[u & VALUE]; + } else if (kind == STACK) { + u = dim + inputStack[inputStack.length - (u & VALUE)]; + } + if (t == u) { + return s; + } + } + return t; + } + + /** + * Initializes the input frame of the first basic block from the method + * descriptor. + * + * @param cw + * the ClassWriter to which this label belongs. + * @param access + * the access flags of the method to which this label belongs. + * @param args + * the formal parameter types of this method. + * @param maxLocals + * the maximum number of local variables of this method. + */ + void initInputFrame(final ClassWriter cw, final int access, + final Type[] args, final int maxLocals) { + inputLocals = new int[maxLocals]; + inputStack = new int[0]; + int i = 0; + if ((access & Opcodes.ACC_STATIC) == 0) { + if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) { + inputLocals[i++] = OBJECT | cw.addType(cw.thisName); + } else { + inputLocals[i++] = UNINITIALIZED_THIS; + } + } + for (int j = 0; j < args.length; ++j) { + int t = type(cw, args[j].getDescriptor()); + inputLocals[i++] = t; + if (t == LONG || t == DOUBLE) { + inputLocals[i++] = TOP; + } + } + while (i < maxLocals) { + inputLocals[i++] = TOP; + } + } + + /** + * Simulates the action of the given instruction on the output stack frame. + * + * @param opcode + * the opcode of the instruction. + * @param arg + * the operand of the instruction, if any. + * @param cw + * the class writer to which this label belongs. + * @param item + * the operand of the instructions, if any. + */ + void execute(final int opcode, final int arg, final ClassWriter cw, + final Item item) { + int t1, t2, t3, t4; + switch (opcode) { + case Opcodes.NOP: + case Opcodes.INEG: + case Opcodes.LNEG: + case Opcodes.FNEG: + case Opcodes.DNEG: + case Opcodes.I2B: + case Opcodes.I2C: + case Opcodes.I2S: + case Opcodes.GOTO: + case Opcodes.RETURN: + break; + case Opcodes.ACONST_NULL: + push(NULL); + break; + case Opcodes.ICONST_M1: + case Opcodes.ICONST_0: + case Opcodes.ICONST_1: + case Opcodes.ICONST_2: + case Opcodes.ICONST_3: + case Opcodes.ICONST_4: + case Opcodes.ICONST_5: + case Opcodes.BIPUSH: + case Opcodes.SIPUSH: + case Opcodes.ILOAD: + push(INTEGER); + break; + case Opcodes.LCONST_0: + case Opcodes.LCONST_1: + case Opcodes.LLOAD: + push(LONG); + push(TOP); + break; + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + case Opcodes.FLOAD: + push(FLOAT); + break; + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + case Opcodes.DLOAD: + push(DOUBLE); + push(TOP); + break; + case Opcodes.LDC: + switch (item.type) { + case ClassWriter.INT: + push(INTEGER); + break; + case ClassWriter.LONG: + push(LONG); + push(TOP); + break; + case ClassWriter.FLOAT: + push(FLOAT); + break; + case ClassWriter.DOUBLE: + push(DOUBLE); + push(TOP); + break; + case ClassWriter.CLASS: + push(OBJECT | cw.addType("java/lang/Class")); + break; + case ClassWriter.STR: + push(OBJECT | cw.addType("java/lang/String")); + break; + case ClassWriter.MTYPE: + push(OBJECT | cw.addType("java/lang/invoke/MethodType")); + break; + // case ClassWriter.HANDLE_BASE + [1..9]: + default: + push(OBJECT | cw.addType("java/lang/invoke/MethodHandle")); + } + break; + case Opcodes.ALOAD: + push(get(arg)); + break; + case Opcodes.IALOAD: + case Opcodes.BALOAD: + case Opcodes.CALOAD: + case Opcodes.SALOAD: + pop(2); + push(INTEGER); + break; + case Opcodes.LALOAD: + case Opcodes.D2L: + pop(2); + push(LONG); + push(TOP); + break; + case Opcodes.FALOAD: + pop(2); + push(FLOAT); + break; + case Opcodes.DALOAD: + case Opcodes.L2D: + pop(2); + push(DOUBLE); + push(TOP); + break; + case Opcodes.AALOAD: + pop(1); + t1 = pop(); + push(ELEMENT_OF + t1); + break; + case Opcodes.ISTORE: + case Opcodes.FSTORE: + case Opcodes.ASTORE: + t1 = pop(); + set(arg, t1); + if (arg > 0) { + t2 = get(arg - 1); + // if t2 is of kind STACK or LOCAL we cannot know its size! + if (t2 == LONG || t2 == DOUBLE) { + set(arg - 1, TOP); + } else if ((t2 & KIND) != BASE) { + set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); + } + } + break; + case Opcodes.LSTORE: + case Opcodes.DSTORE: + pop(1); + t1 = pop(); + set(arg, t1); + set(arg + 1, TOP); + if (arg > 0) { + t2 = get(arg - 1); + // if t2 is of kind STACK or LOCAL we cannot know its size! + if (t2 == LONG || t2 == DOUBLE) { + set(arg - 1, TOP); + } else if ((t2 & KIND) != BASE) { + set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); + } + } + break; + case Opcodes.IASTORE: + case Opcodes.BASTORE: + case Opcodes.CASTORE: + case Opcodes.SASTORE: + case Opcodes.FASTORE: + case Opcodes.AASTORE: + pop(3); + break; + case Opcodes.LASTORE: + case Opcodes.DASTORE: + pop(4); + break; + case Opcodes.POP: + case Opcodes.IFEQ: + case Opcodes.IFNE: + case Opcodes.IFLT: + case Opcodes.IFGE: + case Opcodes.IFGT: + case Opcodes.IFLE: + case Opcodes.IRETURN: + case Opcodes.FRETURN: + case Opcodes.ARETURN: + case Opcodes.TABLESWITCH: + case Opcodes.LOOKUPSWITCH: + case Opcodes.ATHROW: + case Opcodes.MONITORENTER: + case Opcodes.MONITOREXIT: + case Opcodes.IFNULL: + case Opcodes.IFNONNULL: + pop(1); + break; + case Opcodes.POP2: + case Opcodes.IF_ICMPEQ: + case Opcodes.IF_ICMPNE: + case Opcodes.IF_ICMPLT: + case Opcodes.IF_ICMPGE: + case Opcodes.IF_ICMPGT: + case Opcodes.IF_ICMPLE: + case Opcodes.IF_ACMPEQ: + case Opcodes.IF_ACMPNE: + case Opcodes.LRETURN: + case Opcodes.DRETURN: + pop(2); + break; + case Opcodes.DUP: + t1 = pop(); + push(t1); + push(t1); + break; + case Opcodes.DUP_X1: + t1 = pop(); + t2 = pop(); + push(t1); + push(t2); + push(t1); + break; + case Opcodes.DUP_X2: + t1 = pop(); + t2 = pop(); + t3 = pop(); + push(t1); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.DUP2: + t1 = pop(); + t2 = pop(); + push(t2); + push(t1); + push(t2); + push(t1); + break; + case Opcodes.DUP2_X1: + t1 = pop(); + t2 = pop(); + t3 = pop(); + push(t2); + push(t1); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.DUP2_X2: + t1 = pop(); + t2 = pop(); + t3 = pop(); + t4 = pop(); + push(t2); + push(t1); + push(t4); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.SWAP: + t1 = pop(); + t2 = pop(); + push(t1); + push(t2); + break; + case Opcodes.IADD: + case Opcodes.ISUB: + case Opcodes.IMUL: + case Opcodes.IDIV: + case Opcodes.IREM: + case Opcodes.IAND: + case Opcodes.IOR: + case Opcodes.IXOR: + case Opcodes.ISHL: + case Opcodes.ISHR: + case Opcodes.IUSHR: + case Opcodes.L2I: + case Opcodes.D2I: + case Opcodes.FCMPL: + case Opcodes.FCMPG: + pop(2); + push(INTEGER); + break; + case Opcodes.LADD: + case Opcodes.LSUB: + case Opcodes.LMUL: + case Opcodes.LDIV: + case Opcodes.LREM: + case Opcodes.LAND: + case Opcodes.LOR: + case Opcodes.LXOR: + pop(4); + push(LONG); + push(TOP); + break; + case Opcodes.FADD: + case Opcodes.FSUB: + case Opcodes.FMUL: + case Opcodes.FDIV: + case Opcodes.FREM: + case Opcodes.L2F: + case Opcodes.D2F: + pop(2); + push(FLOAT); + break; + case Opcodes.DADD: + case Opcodes.DSUB: + case Opcodes.DMUL: + case Opcodes.DDIV: + case Opcodes.DREM: + pop(4); + push(DOUBLE); + push(TOP); + break; + case Opcodes.LSHL: + case Opcodes.LSHR: + case Opcodes.LUSHR: + pop(3); + push(LONG); + push(TOP); + break; + case Opcodes.IINC: + set(arg, INTEGER); + break; + case Opcodes.I2L: + case Opcodes.F2L: + pop(1); + push(LONG); + push(TOP); + break; + case Opcodes.I2F: + pop(1); + push(FLOAT); + break; + case Opcodes.I2D: + case Opcodes.F2D: + pop(1); + push(DOUBLE); + push(TOP); + break; + case Opcodes.F2I: + case Opcodes.ARRAYLENGTH: + case Opcodes.INSTANCEOF: + pop(1); + push(INTEGER); + break; + case Opcodes.LCMP: + case Opcodes.DCMPL: + case Opcodes.DCMPG: + pop(4); + push(INTEGER); + break; + case Opcodes.JSR: + case Opcodes.RET: + throw new RuntimeException( + "JSR/RET are not supported with computeFrames option"); + case Opcodes.GETSTATIC: + push(cw, item.strVal3); + break; + case Opcodes.PUTSTATIC: + pop(item.strVal3); + break; + case Opcodes.GETFIELD: + pop(1); + push(cw, item.strVal3); + break; + case Opcodes.PUTFIELD: + pop(item.strVal3); + pop(); + break; + case Opcodes.INVOKEVIRTUAL: + case Opcodes.INVOKESPECIAL: + case Opcodes.INVOKESTATIC: + case Opcodes.INVOKEINTERFACE: + pop(item.strVal3); + if (opcode != Opcodes.INVOKESTATIC) { + t1 = pop(); + if (opcode == Opcodes.INVOKESPECIAL + && item.strVal2.charAt(0) == '<') { + init(t1); + } + } + push(cw, item.strVal3); + break; + case Opcodes.INVOKEDYNAMIC: + pop(item.strVal2); + push(cw, item.strVal2); + break; + case Opcodes.NEW: + push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg)); + break; + case Opcodes.NEWARRAY: + pop(); + switch (arg) { + case Opcodes.T_BOOLEAN: + push(ARRAY_OF | BOOLEAN); + break; + case Opcodes.T_CHAR: + push(ARRAY_OF | CHAR); + break; + case Opcodes.T_BYTE: + push(ARRAY_OF | BYTE); + break; + case Opcodes.T_SHORT: + push(ARRAY_OF | SHORT); + break; + case Opcodes.T_INT: + push(ARRAY_OF | INTEGER); + break; + case Opcodes.T_FLOAT: + push(ARRAY_OF | FLOAT); + break; + case Opcodes.T_DOUBLE: + push(ARRAY_OF | DOUBLE); + break; + // case Opcodes.T_LONG: + default: + push(ARRAY_OF | LONG); + break; + } + break; + case Opcodes.ANEWARRAY: + String s = item.strVal1; + pop(); + if (s.charAt(0) == '[') { + push(cw, '[' + s); + } else { + push(ARRAY_OF | OBJECT | cw.addType(s)); + } + break; + case Opcodes.CHECKCAST: + s = item.strVal1; + pop(); + if (s.charAt(0) == '[') { + push(cw, s); + } else { + push(OBJECT | cw.addType(s)); + } + break; + // case Opcodes.MULTIANEWARRAY: + default: + pop(arg); + push(cw, item.strVal1); + break; + } + } + + /** + * Merges the input frame of the given basic block with the input and output + * frames of this basic block. Returns true if the input frame of + * the given label has been changed by this operation. + * + * @param cw + * the ClassWriter to which this label belongs. + * @param frame + * the basic block whose input frame must be updated. + * @param edge + * the kind of the {@link Edge} between this label and 'label'. + * See {@link Edge#info}. + * @return true if the input frame of the given label has been + * changed by this operation. + */ + boolean merge(final ClassWriter cw, final Frame frame, final int edge) { + boolean changed = false; + int i, s, dim, kind, t; + + int nLocal = inputLocals.length; + int nStack = inputStack.length; + if (frame.inputLocals == null) { + frame.inputLocals = new int[nLocal]; + changed = true; + } + + for (i = 0; i < nLocal; ++i) { + if (outputLocals != null && i < outputLocals.length) { + s = outputLocals[i]; + if (s == 0) { + t = inputLocals[i]; + } else { + dim = s & DIM; + kind = s & KIND; + if (kind == BASE) { + t = s; + } else { + if (kind == LOCAL) { + t = dim + inputLocals[s & VALUE]; + } else { + t = dim + inputStack[nStack - (s & VALUE)]; + } + if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 + && (t == LONG || t == DOUBLE)) { + t = TOP; + } + } + } + } else { + t = inputLocals[i]; + } + if (initializations != null) { + t = init(cw, t); + } + changed |= merge(cw, t, frame.inputLocals, i); + } + + if (edge > 0) { + for (i = 0; i < nLocal; ++i) { + t = inputLocals[i]; + changed |= merge(cw, t, frame.inputLocals, i); + } + if (frame.inputStack == null) { + frame.inputStack = new int[1]; + changed = true; + } + changed |= merge(cw, edge, frame.inputStack, 0); + return changed; + } + + int nInputStack = inputStack.length + owner.inputStackTop; + if (frame.inputStack == null) { + frame.inputStack = new int[nInputStack + outputStackTop]; + changed = true; + } + + for (i = 0; i < nInputStack; ++i) { + t = inputStack[i]; + if (initializations != null) { + t = init(cw, t); + } + changed |= merge(cw, t, frame.inputStack, i); + } + for (i = 0; i < outputStackTop; ++i) { + s = outputStack[i]; + dim = s & DIM; + kind = s & KIND; + if (kind == BASE) { + t = s; + } else { + if (kind == LOCAL) { + t = dim + inputLocals[s & VALUE]; + } else { + t = dim + inputStack[nStack - (s & VALUE)]; + } + if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 + && (t == LONG || t == DOUBLE)) { + t = TOP; + } + } + if (initializations != null) { + t = init(cw, t); + } + changed |= merge(cw, t, frame.inputStack, nInputStack + i); + } + return changed; + } + + /** + * Merges the type at the given index in the given type array with the given + * type. Returns true if the type array has been modified by this + * operation. + * + * @param cw + * the ClassWriter to which this label belongs. + * @param t + * the type with which the type array element must be merged. + * @param types + * an array of types. + * @param index + * the index of the type that must be merged in 'types'. + * @return true if the type array has been modified by this + * operation. + */ + private static boolean merge(final ClassWriter cw, int t, + final int[] types, final int index) { + int u = types[index]; + if (u == t) { + // if the types are equal, merge(u,t)=u, so there is no change + return false; + } + if ((t & ~DIM) == NULL) { + if (u == NULL) { + return false; + } + t = NULL; + } + if (u == 0) { + // if types[index] has never been assigned, merge(u,t)=t + types[index] = t; + return true; + } + int v; + if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) { + // if u is a reference type of any dimension + if (t == NULL) { + // if t is the NULL type, merge(u,t)=u, so there is no change + return false; + } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) { + // if t and u have the same dimension and same base kind + if ((u & BASE_KIND) == OBJECT) { + // if t is also a reference type, and if u and t have the + // same dimension merge(u,t) = dim(t) | common parent of the + // element types of u and t + v = (t & DIM) | OBJECT + | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE); + } else { + // if u and t are array types, but not with the same element + // type, merge(u,t) = dim(u) - 1 | java/lang/Object + int vdim = ELEMENT_OF + (u & DIM); + v = vdim | OBJECT | cw.addType("java/lang/Object"); + } + } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) { + // if t is any other reference or array type, the merged type + // is min(udim, tdim) | java/lang/Object, where udim is the + // array dimension of u, minus 1 if u is an array type with a + // primitive element type (and similarly for tdim). + int tdim = (((t & DIM) == 0 || (t & BASE_KIND) == OBJECT) ? 0 + : ELEMENT_OF) + (t & DIM); + int udim = (((u & DIM) == 0 || (u & BASE_KIND) == OBJECT) ? 0 + : ELEMENT_OF) + (u & DIM); + v = Math.min(tdim, udim) | OBJECT + | cw.addType("java/lang/Object"); + } else { + // if t is any other type, merge(u,t)=TOP + v = TOP; + } + } else if (u == NULL) { + // if u is the NULL type, merge(u,t)=t, + // or TOP if t is not a reference type + v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP; + } else { + // if u is any other type, merge(u,t)=TOP whatever t + v = TOP; + } + if (u != v) { + types[index] = v; + return true; + } + return false; + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/Handle.java b/blade-core/src/main/java/org/objectweb/asm/Handle.java new file mode 100644 index 000000000..ddc0368d6 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/Handle.java @@ -0,0 +1,222 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ + +package org.objectweb.asm; + +/** + * A reference to a field or a method. + * + * @author Remi Forax + * @author Eric Bruneton + */ +public final class Handle { + + /** + * The kind of field or method designated by this Handle. Should be + * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, + * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, + * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + */ + final int tag; + + /** + * The internal name of the class that owns the field or method designated + * by this handle. + */ + final String owner; + + /** + * The name of the field or method designated by this handle. + */ + final String name; + + /** + * The descriptor of the field or method designated by this handle. + */ + final String desc; + + + /** + * Indicate if the owner is an interface or not. + */ + final boolean itf; + + /** + * Constructs a new field or method handle. + * + * @param tag + * the kind of field or method designated by this Handle. Must be + * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, + * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, + * {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the class that owns the field or method + * designated by this handle. + * @param name + * the name of the field or method designated by this handle. + * @param desc + * the descriptor of the field or method designated by this + * handle. + * + * @deprecated this constructor has been superseded + * by {@link #Handle(int, String, String, String, boolean)}. + */ + @Deprecated + public Handle(int tag, String owner, String name, String desc) { + this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE); + } + + /** + * Constructs a new field or method handle. + * + * @param tag + * the kind of field or method designated by this Handle. Must be + * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, + * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, + * {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the class that owns the field or method + * designated by this handle. + * @param name + * the name of the field or method designated by this handle. + * @param desc + * the descriptor of the field or method designated by this + * handle. + * @param itf + * true if the owner is an interface. + */ + public Handle(int tag, String owner, String name, String desc, boolean itf) { + this.tag = tag; + this.owner = owner; + this.name = name; + this.desc = desc; + this.itf = itf; + } + + /** + * Returns the kind of field or method designated by this handle. + * + * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, + * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, + * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + */ + public int getTag() { + return tag; + } + + /** + * Returns the internal name of the class that owns the field or method + * designated by this handle. + * + * @return the internal name of the class that owns the field or method + * designated by this handle. + */ + public String getOwner() { + return owner; + } + + /** + * Returns the name of the field or method designated by this handle. + * + * @return the name of the field or method designated by this handle. + */ + public String getName() { + return name; + } + + /** + * Returns the descriptor of the field or method designated by this handle. + * + * @return the descriptor of the field or method designated by this handle. + */ + public String getDesc() { + return desc; + } + + /** + * Returns true if the owner of the field or method designated + * by this handle is an interface. + * + * @return true if the owner of the field or method designated + * by this handle is an interface. + */ + public boolean isInterface() { + return itf; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Handle)) { + return false; + } + Handle h = (Handle) obj; + return tag == h.tag && itf == h.itf && owner.equals(h.owner) + && name.equals(h.name) && desc.equals(h.desc); + } + + @Override + public int hashCode() { + return tag + (itf? 64: 0) + owner.hashCode() * name.hashCode() * desc.hashCode(); + } + + /** + * Returns the textual representation of this handle. The textual + * representation is: + * + *
+     * for a reference to a class:
+     * owner '.' name desc ' ' '(' tag ')'
+     * for a reference to an interface:
+     * owner '.' name desc ' ' '(' tag ' ' itf ')'
+     * 
+ * + * . As this format is unambiguous, it can be parsed if necessary. + */ + @Override + public String toString() { + return owner + '.' + name + desc + " (" + tag + (itf? " itf": "") + ')'; + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/Handler.java b/blade-core/src/main/java/org/objectweb/asm/Handler.java new file mode 100644 index 000000000..b24591d81 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/Handler.java @@ -0,0 +1,121 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * Information about an exception handler block. + * + * @author Eric Bruneton + */ +class Handler { + + /** + * Beginning of the exception handler's scope (inclusive). + */ + Label start; + + /** + * End of the exception handler's scope (exclusive). + */ + Label end; + + /** + * Beginning of the exception handler's code. + */ + Label handler; + + /** + * Internal name of the type of exceptions handled by this handler, or + * null to catch any exceptions. + */ + String desc; + + /** + * Constant pool index of the internal name of the type of exceptions + * handled by this handler, or 0 to catch any exceptions. + */ + int type; + + /** + * Next exception handler block info. + */ + Handler next; + + /** + * Removes the range between start and end from the given exception + * handlers. + * + * @param h + * an exception handler list. + * @param start + * the start of the range to be removed. + * @param end + * the end of the range to be removed. Maybe null. + * @return the exception handler list with the start-end range removed. + */ + static Handler remove(Handler h, Label start, Label end) { + if (h == null) { + return null; + } else { + h.next = remove(h.next, start, end); + } + int hstart = h.start.position; + int hend = h.end.position; + int s = start.position; + int e = end == null ? Integer.MAX_VALUE : end.position; + // if [hstart,hend[ and [s,e[ intervals intersect... + if (s < hend && e > hstart) { + if (s <= hstart) { + if (e >= hend) { + // [hstart,hend[ fully included in [s,e[, h removed + h = h.next; + } else { + // [hstart,hend[ minus [s,e[ = [e,hend[ + h.start = end; + } + } else if (e >= hend) { + // [hstart,hend[ minus [s,e[ = [hstart,s[ + h.end = start; + } else { + // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[ + Handler g = new Handler(); + g.start = end; + g.end = h.end; + g.handler = h.handler; + g.desc = h.desc; + g.type = h.type; + g.next = h.next; + h.end = start; + h.next = g; + } + } + return h; + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/Item.java b/blade-core/src/main/java/org/objectweb/asm/Item.java new file mode 100644 index 000000000..917524dde --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/Item.java @@ -0,0 +1,313 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * A constant pool item. Constant pool items can be created with the 'newXXX' + * methods in the {@link ClassWriter} class. + * + * @author Eric Bruneton + */ +final class Item { + + /** + * Index of this item in the constant pool. + */ + int index; + + /** + * Type of this constant pool item. A single class is used to represent all + * constant pool item types, in order to minimize the bytecode size of this + * package. The value of this field is one of {@link ClassWriter#INT}, + * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT}, + * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8}, + * {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, + * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD}, + * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, + * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}. + * + * MethodHandle constant 9 variations are stored using a range of 9 values + * from {@link ClassWriter#HANDLE_BASE} + 1 to + * {@link ClassWriter#HANDLE_BASE} + 9. + * + * Special Item types are used for Items that are stored in the ClassWriter + * {@link ClassWriter#typeTable}, instead of the constant pool, in order to + * avoid clashes with normal constant pool items in the ClassWriter constant + * pool's hash table. These special item types are + * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and + * {@link ClassWriter#TYPE_MERGED}. + */ + int type; + + /** + * Value of this item, for an integer item. + */ + int intVal; + + /** + * Value of this item, for a long item. + */ + long longVal; + + /** + * First part of the value of this item, for items that do not hold a + * primitive value. + */ + String strVal1; + + /** + * Second part of the value of this item, for items that do not hold a + * primitive value. + */ + String strVal2; + + /** + * Third part of the value of this item, for items that do not hold a + * primitive value. + */ + String strVal3; + + /** + * The hash code value of this constant pool item. + */ + int hashCode; + + /** + * Link to another constant pool item, used for collision lists in the + * constant pool's hash table. + */ + Item next; + + /** + * Constructs an uninitialized {@link Item}. + */ + Item() { + } + + /** + * Constructs an uninitialized {@link Item} for constant pool element at + * given position. + * + * @param index + * index of the item to be constructed. + */ + Item(final int index) { + this.index = index; + } + + /** + * Constructs a copy of the given item. + * + * @param index + * index of the item to be constructed. + * @param i + * the item that must be copied into the item to be constructed. + */ + Item(final int index, final Item i) { + this.index = index; + type = i.type; + intVal = i.intVal; + longVal = i.longVal; + strVal1 = i.strVal1; + strVal2 = i.strVal2; + strVal3 = i.strVal3; + hashCode = i.hashCode; + } + + /** + * Sets this item to an integer item. + * + * @param intVal + * the value of this item. + */ + void set(final int intVal) { + this.type = ClassWriter.INT; + this.intVal = intVal; + this.hashCode = 0x7FFFFFFF & (type + intVal); + } + + /** + * Sets this item to a long item. + * + * @param longVal + * the value of this item. + */ + void set(final long longVal) { + this.type = ClassWriter.LONG; + this.longVal = longVal; + this.hashCode = 0x7FFFFFFF & (type + (int) longVal); + } + + /** + * Sets this item to a float item. + * + * @param floatVal + * the value of this item. + */ + void set(final float floatVal) { + this.type = ClassWriter.FLOAT; + this.intVal = Float.floatToRawIntBits(floatVal); + this.hashCode = 0x7FFFFFFF & (type + (int) floatVal); + } + + /** + * Sets this item to a double item. + * + * @param doubleVal + * the value of this item. + */ + void set(final double doubleVal) { + this.type = ClassWriter.DOUBLE; + this.longVal = Double.doubleToRawLongBits(doubleVal); + this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal); + } + + /** + * Sets this item to an item that do not hold a primitive value. + * + * @param type + * the type of this item. + * @param strVal1 + * first part of the value of this item. + * @param strVal2 + * second part of the value of this item. + * @param strVal3 + * third part of the value of this item. + */ + @SuppressWarnings("fallthrough") + void set(final int type, final String strVal1, final String strVal2, + final String strVal3) { + this.type = type; + this.strVal1 = strVal1; + this.strVal2 = strVal2; + this.strVal3 = strVal3; + switch (type) { + case ClassWriter.CLASS: + this.intVal = 0; // intVal of a class must be zero, see visitInnerClass + case ClassWriter.UTF8: + case ClassWriter.STR: + case ClassWriter.MTYPE: + case ClassWriter.TYPE_NORMAL: + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); + return; + case ClassWriter.NAME_TYPE: { + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() + * strVal2.hashCode()); + return; + } + // ClassWriter.FIELD: + // ClassWriter.METH: + // ClassWriter.IMETH: + // ClassWriter.HANDLE_BASE + 1..9 + default: + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() + * strVal2.hashCode() * strVal3.hashCode()); + } + } + + /** + * Sets the item to an InvokeDynamic item. + * + * @param name + * invokedynamic's name. + * @param desc + * invokedynamic's desc. + * @param bsmIndex + * zero based index into the class attribute BootrapMethods. + */ + void set(String name, String desc, int bsmIndex) { + this.type = ClassWriter.INDY; + this.longVal = bsmIndex; + this.strVal1 = name; + this.strVal2 = desc; + this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex + * strVal1.hashCode() * strVal2.hashCode()); + } + + /** + * Sets the item to a BootstrapMethod item. + * + * @param position + * position in byte in the class attribute BootrapMethods. + * @param hashCode + * hashcode of the item. This hashcode is processed from the + * hashcode of the bootstrap method and the hashcode of all + * bootstrap arguments. + */ + void set(int position, int hashCode) { + this.type = ClassWriter.BSM; + this.intVal = position; + this.hashCode = hashCode; + } + + /** + * Indicates if the given item is equal to this one. This method assumes + * that the two items have the same {@link #type}. + * + * @param i + * the item to be compared to this one. Both items must have the + * same {@link #type}. + * @return true if the given item if equal to this one, + * false otherwise. + */ + boolean isEqualTo(final Item i) { + switch (type) { + case ClassWriter.UTF8: + case ClassWriter.STR: + case ClassWriter.CLASS: + case ClassWriter.MTYPE: + case ClassWriter.TYPE_NORMAL: + return i.strVal1.equals(strVal1); + case ClassWriter.TYPE_MERGED: + case ClassWriter.LONG: + case ClassWriter.DOUBLE: + return i.longVal == longVal; + case ClassWriter.INT: + case ClassWriter.FLOAT: + return i.intVal == intVal; + case ClassWriter.TYPE_UNINIT: + return i.intVal == intVal && i.strVal1.equals(strVal1); + case ClassWriter.NAME_TYPE: + return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2); + case ClassWriter.INDY: { + return i.longVal == longVal && i.strVal1.equals(strVal1) + && i.strVal2.equals(strVal2); + } + // case ClassWriter.FIELD: + // case ClassWriter.METH: + // case ClassWriter.IMETH: + // case ClassWriter.HANDLE_BASE + 1..9 + default: + return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2) + && i.strVal3.equals(strVal3); + } + } + +} diff --git a/blade-core/src/main/java/org/objectweb/asm/Label.java b/blade-core/src/main/java/org/objectweb/asm/Label.java new file mode 100644 index 000000000..6bca6fbe8 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/Label.java @@ -0,0 +1,565 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * A label represents a position in the bytecode of a method. Labels are used + * for jump, goto, and switch instructions, and for try catch blocks. A label + * designates the instruction that is just after. Note however that there + * can be other elements between a label and the instruction it designates (such + * as other labels, stack map frames, line numbers, etc.). + * + * @author Eric Bruneton + */ +public class Label { + + /** + * Indicates if this label is only used for debug attributes. Such a label + * is not the start of a basic block, the target of a jump instruction, or + * an exception handler. It can be safely ignored in control flow graph + * analysis algorithms (for optimization purposes). + */ + static final int DEBUG = 1; + + /** + * Indicates if the position of this label is known. + */ + static final int RESOLVED = 2; + + /** + * Indicates if this label has been updated, after instruction resizing. + */ + static final int RESIZED = 4; + + /** + * Indicates if this basic block has been pushed in the basic block stack. + * See {@link MethodWriter#visitMaxs visitMaxs}. + */ + static final int PUSHED = 8; + + /** + * Indicates if this label is the target of a jump instruction, or the start + * of an exception handler. + */ + static final int TARGET = 16; + + /** + * Indicates if a stack map frame must be stored for this label. + */ + static final int STORE = 32; + + /** + * Indicates if this label corresponds to a reachable basic block. + */ + static final int REACHABLE = 64; + + /** + * Indicates if this basic block ends with a JSR instruction. + */ + static final int JSR = 128; + + /** + * Indicates if this basic block ends with a RET instruction. + */ + static final int RET = 256; + + /** + * Indicates if this basic block is the start of a subroutine. + */ + static final int SUBROUTINE = 512; + + /** + * Indicates if this subroutine basic block has been visited by a + * visitSubroutine(null, ...) call. + */ + static final int VISITED = 1024; + + /** + * Indicates if this subroutine basic block has been visited by a + * visitSubroutine(!null, ...) call. + */ + static final int VISITED2 = 2048; + + /** + * Field used to associate user information to a label. Warning: this field + * is used by the ASM tree package. In order to use it with the ASM tree + * package you must override the + * {@link org.objectweb.asm.tree.MethodNode#getLabelNode} method. + */ + public Object info; + + /** + * Flags that indicate the status of this label. + * + * @see #DEBUG + * @see #RESOLVED + * @see #RESIZED + * @see #PUSHED + * @see #TARGET + * @see #STORE + * @see #REACHABLE + * @see #JSR + * @see #RET + */ + int status; + + /** + * The line number corresponding to this label, if known. If there are + * several lines, each line is stored in a separate label, all linked via + * their next field (these links are created in ClassReader and removed just + * before visitLabel is called, so that this does not impact the rest of the + * code). + */ + int line; + + /** + * The position of this label in the code, if known. + */ + int position; + + /** + * Number of forward references to this label, times two. + */ + private int referenceCount; + + /** + * Informations about forward references. Each forward reference is + * described by two consecutive integers in this array: the first one is the + * position of the first byte of the bytecode instruction that contains the + * forward reference, while the second is the position of the first byte of + * the forward reference itself. In fact the sign of the first integer + * indicates if this reference uses 2 or 4 bytes, and its absolute value + * gives the position of the bytecode instruction. This array is also used + * as a bitset to store the subroutines to which a basic block belongs. This + * information is needed in {@linked MethodWriter#visitMaxs}, after all + * forward references have been resolved. Hence the same array can be used + * for both purposes without problems. + */ + private int[] srcAndRefPositions; + + // ------------------------------------------------------------------------ + + /* + * Fields for the control flow and data flow graph analysis algorithms (used + * to compute the maximum stack size or the stack map frames). A control + * flow graph contains one node per "basic block", and one edge per "jump" + * from one basic block to another. Each node (i.e., each basic block) is + * represented by the Label object that corresponds to the first instruction + * of this basic block. Each node also stores the list of its successors in + * the graph, as a linked list of Edge objects. + * + * The control flow analysis algorithms used to compute the maximum stack + * size or the stack map frames are similar and use two steps. The first + * step, during the visit of each instruction, builds information about the + * state of the local variables and the operand stack at the end of each + * basic block, called the "output frame", relatively to the frame + * state at the beginning of the basic block, which is called the "input + * frame", and which is unknown during this step. The second step, in + * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes + * information about the input frame of each basic block, from the input + * state of the first basic block (known from the method signature), and by + * the using the previously computed relative output frames. + * + * The algorithm used to compute the maximum stack size only computes the + * relative output and absolute input stack heights, while the algorithm + * used to compute stack map frames computes relative output frames and + * absolute input frames. + */ + + /** + * Start of the output stack relatively to the input stack. The exact + * semantics of this field depends on the algorithm that is used. + * + * When only the maximum stack size is computed, this field is the number of + * elements in the input stack. + * + * When the stack map frames are completely computed, this field is the + * offset of the first output stack element relatively to the top of the + * input stack. This offset is always negative or null. A null offset means + * that the output stack must be appended to the input stack. A -n offset + * means that the first n output stack elements must replace the top n input + * stack elements, and that the other elements must be appended to the input + * stack. + */ + int inputStackTop; + + /** + * Maximum height reached by the output stack, relatively to the top of the + * input stack. This maximum is always positive or null. + */ + int outputStackMax; + + /** + * Information about the input and output stack map frames of this basic + * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES} + * option is used. + */ + Frame frame; + + /** + * The successor of this label, in the order they are visited. This linked + * list does not include labels used for debug info only. If + * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it + * does not contain successive labels that denote the same bytecode position + * (in this case only the first label appears in this list). + */ + Label successor; + + /** + * The successors of this node in the control flow graph. These successors + * are stored in a linked list of {@link Edge Edge} objects, linked to each + * other by their {@link Edge#next} field. + */ + Edge successors; + + /** + * The next basic block in the basic block stack. This stack is used in the + * main loop of the fix point algorithm used in the second step of the + * control flow analysis algorithms. It is also used in + * {@link #visitSubroutine} to avoid using a recursive method, and in + * ClassReader to temporarily store multiple source lines for a label. + * + * @see MethodWriter#visitMaxs + */ + Label next; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new label. + */ + public Label() { + } + + // ------------------------------------------------------------------------ + // Methods to compute offsets and to manage forward references + // ------------------------------------------------------------------------ + + /** + * Returns the offset corresponding to this label. This offset is computed + * from the start of the method's bytecode. This method is intended for + * {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters. + * + * @return the offset corresponding to this label. + * @throws IllegalStateException + * if this label is not resolved yet. + */ + public int getOffset() { + if ((status & RESOLVED) == 0) { + throw new IllegalStateException( + "Label offset position has not been resolved yet"); + } + return position; + } + + /** + * Puts a reference to this label in the bytecode of a method. If the + * position of the label is known, the offset is computed and written + * directly. Otherwise, a null offset is written and a new forward reference + * is declared for this label. + * + * @param owner + * the code writer that calls this method. + * @param out + * the bytecode of the method. + * @param source + * the position of first byte of the bytecode instruction that + * contains this label. + * @param wideOffset + * true if the reference must be stored in 4 bytes, or + * false if it must be stored with 2 bytes. + * @throws IllegalArgumentException + * if this label has not been created by the given code writer. + */ + void put(final MethodWriter owner, final ByteVector out, final int source, + final boolean wideOffset) { + if ((status & RESOLVED) == 0) { + if (wideOffset) { + addReference(-1 - source, out.length); + out.putInt(-1); + } else { + addReference(source, out.length); + out.putShort(-1); + } + } else { + if (wideOffset) { + out.putInt(position - source); + } else { + out.putShort(position - source); + } + } + } + + /** + * Adds a forward reference to this label. This method must be called only + * for a true forward reference, i.e. only if this label is not resolved + * yet. For backward references, the offset of the reference can be, and + * must be, computed and stored directly. + * + * @param sourcePosition + * the position of the referencing instruction. This position + * will be used to compute the offset of this forward reference. + * @param referencePosition + * the position where the offset for this forward reference must + * be stored. + */ + private void addReference(final int sourcePosition, + final int referencePosition) { + if (srcAndRefPositions == null) { + srcAndRefPositions = new int[6]; + } + if (referenceCount >= srcAndRefPositions.length) { + int[] a = new int[srcAndRefPositions.length + 6]; + System.arraycopy(srcAndRefPositions, 0, a, 0, + srcAndRefPositions.length); + srcAndRefPositions = a; + } + srcAndRefPositions[referenceCount++] = sourcePosition; + srcAndRefPositions[referenceCount++] = referencePosition; + } + + /** + * Resolves all forward references to this label. This method must be called + * when this label is added to the bytecode of the method, i.e. when its + * position becomes known. This method fills in the blanks that where left + * in the bytecode by each forward reference previously added to this label. + * + * @param owner + * the code writer that calls this method. + * @param position + * the position of this label in the bytecode. + * @param data + * the bytecode of the method. + * @return true if a blank that was left for this label was to + * small to store the offset. In such a case the corresponding jump + * instruction is replaced with a pseudo instruction (using unused + * opcodes) using an unsigned two bytes offset. These pseudo + * instructions will need to be replaced with true instructions with + * wider offsets (4 bytes instead of 2). This is done in + * {@link MethodWriter#resizeInstructions}. + * @throws IllegalArgumentException + * if this label has already been resolved, or if it has not + * been created by the given code writer. + */ + boolean resolve(final MethodWriter owner, final int position, + final byte[] data) { + boolean needUpdate = false; + this.status |= RESOLVED; + this.position = position; + int i = 0; + while (i < referenceCount) { + int source = srcAndRefPositions[i++]; + int reference = srcAndRefPositions[i++]; + int offset; + if (source >= 0) { + offset = position - source; + if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) { + /* + * changes the opcode of the jump instruction, in order to + * be able to find it later (see resizeInstructions in + * MethodWriter). These temporary opcodes are similar to + * jump instruction opcodes, except that the 2 bytes offset + * is unsigned (and can therefore represent values from 0 to + * 65535, which is sufficient since the size of a method is + * limited to 65535 bytes). + */ + int opcode = data[reference - 1] & 0xFF; + if (opcode <= Opcodes.JSR) { + // changes IFEQ ... JSR to opcodes 202 to 217 + data[reference - 1] = (byte) (opcode + 49); + } else { + // changes IFNULL and IFNONNULL to opcodes 218 and 219 + data[reference - 1] = (byte) (opcode + 20); + } + needUpdate = true; + } + data[reference++] = (byte) (offset >>> 8); + data[reference] = (byte) offset; + } else { + offset = position + source + 1; + data[reference++] = (byte) (offset >>> 24); + data[reference++] = (byte) (offset >>> 16); + data[reference++] = (byte) (offset >>> 8); + data[reference] = (byte) offset; + } + } + return needUpdate; + } + + /** + * Returns the first label of the series to which this label belongs. For an + * isolated label or for the first label in a series of successive labels, + * this method returns the label itself. For other labels it returns the + * first label of the series. + * + * @return the first label of the series to which this label belongs. + */ + Label getFirst() { + return !ClassReader.FRAMES || frame == null ? this : frame.owner; + } + + // ------------------------------------------------------------------------ + // Methods related to subroutines + // ------------------------------------------------------------------------ + + /** + * Returns true is this basic block belongs to the given subroutine. + * + * @param id + * a subroutine id. + * @return true is this basic block belongs to the given subroutine. + */ + boolean inSubroutine(final long id) { + if ((status & Label.VISITED) != 0) { + return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0; + } + return false; + } + + /** + * Returns true if this basic block and the given one belong to a common + * subroutine. + * + * @param block + * another basic block. + * @return true if this basic block and the given one belong to a common + * subroutine. + */ + boolean inSameSubroutine(final Label block) { + if ((status & VISITED) == 0 || (block.status & VISITED) == 0) { + return false; + } + for (int i = 0; i < srcAndRefPositions.length; ++i) { + if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) { + return true; + } + } + return false; + } + + /** + * Marks this basic block as belonging to the given subroutine. + * + * @param id + * a subroutine id. + * @param nbSubroutines + * the total number of subroutines in the method. + */ + void addToSubroutine(final long id, final int nbSubroutines) { + if ((status & VISITED) == 0) { + status |= VISITED; + srcAndRefPositions = new int[nbSubroutines / 32 + 1]; + } + srcAndRefPositions[(int) (id >>> 32)] |= (int) id; + } + + /** + * Finds the basic blocks that belong to a given subroutine, and marks these + * blocks as belonging to this subroutine. This method follows the control + * flow graph to find all the blocks that are reachable from the current + * block WITHOUT following any JSR target. + * + * @param JSR + * a JSR block that jumps to this subroutine. If this JSR is not + * null it is added to the successor of the RET blocks found in + * the subroutine. + * @param id + * the id of this subroutine. + * @param nbSubroutines + * the total number of subroutines in the method. + */ + void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) { + // user managed stack of labels, to avoid using a recursive method + // (recursivity can lead to stack overflow with very large methods) + Label stack = this; + while (stack != null) { + // removes a label l from the stack + Label l = stack; + stack = l.next; + l.next = null; + + if (JSR != null) { + if ((l.status & VISITED2) != 0) { + continue; + } + l.status |= VISITED2; + // adds JSR to the successors of l, if it is a RET block + if ((l.status & RET) != 0) { + if (!l.inSameSubroutine(JSR)) { + Edge e = new Edge(); + e.info = l.inputStackTop; + e.successor = JSR.successors.successor; + e.next = l.successors; + l.successors = e; + } + } + } else { + // if the l block already belongs to subroutine 'id', continue + if (l.inSubroutine(id)) { + continue; + } + // marks the l block as belonging to subroutine 'id' + l.addToSubroutine(id, nbSubroutines); + } + // pushes each successor of l on the stack, except JSR targets + Edge e = l.successors; + while (e != null) { + // if the l block is a JSR block, then 'l.successors.next' leads + // to the JSR target (see {@link #visitJumpInsn}) and must + // therefore not be followed + if ((l.status & Label.JSR) == 0 || e != l.successors.next) { + // pushes e.successor on the stack if it not already added + if (e.successor.next == null) { + e.successor.next = stack; + stack = e.successor; + } + } + e = e.next; + } + } + } + + // ------------------------------------------------------------------------ + // Overriden Object methods + // ------------------------------------------------------------------------ + + /** + * Returns a string representation of this label. + * + * @return a string representation of this label. + */ + @Override + public String toString() { + return "L" + System.identityHashCode(this); + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/MethodVisitor.java b/blade-core/src/main/java/org/objectweb/asm/MethodVisitor.java new file mode 100644 index 000000000..f0927e8be --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/MethodVisitor.java @@ -0,0 +1,881 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * A visitor to visit a Java method. The methods of this class must be called in + * the following order: ( visitParameter )* [ + * visitAnnotationDefault ] ( visitAnnotation | + * visitParameterAnnotation visitTypeAnnotation | + * visitAttribute )* [ visitCode ( visitFrame | + * visitXInsn | visitLabel | + * visitInsnAnnotation | visitTryCatchBlock | + * visitTryCatchAnnotation | visitLocalVariable | + * visitLocalVariableAnnotation | visitLineNumber )* + * visitMaxs ] visitEnd. In addition, the + * visitXInsn and visitLabel methods must be called in + * the sequential order of the bytecode instructions of the visited code, + * visitInsnAnnotation must be called after the annotated + * instruction, visitTryCatchBlock must be called before the + * labels passed as arguments have been visited, + * visitTryCatchBlockAnnotation must be called after the + * corresponding try catch block has been visited, and the + * visitLocalVariable, visitLocalVariableAnnotation and + * visitLineNumber methods must be called after the labels + * passed as arguments have been visited. + * + * @author Eric Bruneton + */ +public abstract class MethodVisitor { + + /** + * The ASM API version implemented by this visitor. The value of this field + * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + */ + protected final int api; + + /** + * The method visitor to which this visitor must delegate method calls. May + * be null. + */ + protected MethodVisitor mv; + + /** + * Constructs a new {@link MethodVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + */ + public MethodVisitor(final int api) { + this(api, null); + } + + /** + * Constructs a new {@link MethodVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * @param mv + * the method visitor to which this visitor must delegate method + * calls. May be null. + */ + public MethodVisitor(final int api, final MethodVisitor mv) { + if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { + throw new IllegalArgumentException(); + } + this.api = api; + this.mv = mv; + } + + // ------------------------------------------------------------------------- + // Parameters, annotations and non standard attributes + // ------------------------------------------------------------------------- + + /** + * Visits a parameter of this method. + * + * @param name + * parameter name or null if none is provided. + * @param access + * the parameter's access flags, only ACC_FINAL, + * ACC_SYNTHETIC or/and ACC_MANDATED are + * allowed (see {@link Opcodes}). + */ + public void visitParameter(String name, int access) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (mv != null) { + mv.visitParameter(name, access); + } + } + + /** + * Visits the default value of this annotation interface method. + * + * @return a visitor to the visit the actual default value of this + * annotation interface method, or null if this visitor is + * not interested in visiting this default value. The 'name' + * parameters passed to the methods of this annotation visitor are + * ignored. Moreover, exacly one visit method must be called on this + * annotation visitor, followed by visitEnd. + */ + public AnnotationVisitor visitAnnotationDefault() { + if (mv != null) { + return mv.visitAnnotationDefault(); + } + return null; + } + + /** + * Visits an annotation of this method. + * + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + if (mv != null) { + return mv.visitAnnotation(desc, visible); + } + return null; + } + + /** + * Visits an annotation on a type in the method signature. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#METHOD_TYPE_PARAMETER + * METHOD_TYPE_PARAMETER}, + * {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND + * METHOD_TYPE_PARAMETER_BOUND}, + * {@link TypeReference#METHOD_RETURN METHOD_RETURN}, + * {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER}, + * {@link TypeReference#METHOD_FORMAL_PARAMETER + * METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS + * THROWS}. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (mv != null) { + return mv.visitTypeAnnotation(typeRef, typePath, desc, visible); + } + return null; + } + + /** + * Visits an annotation of a parameter this method. + * + * @param parameter + * the parameter index. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitParameterAnnotation(int parameter, + String desc, boolean visible) { + if (mv != null) { + return mv.visitParameterAnnotation(parameter, desc, visible); + } + return null; + } + + /** + * Visits a non standard attribute of this method. + * + * @param attr + * an attribute. + */ + public void visitAttribute(Attribute attr) { + if (mv != null) { + mv.visitAttribute(attr); + } + } + + /** + * Starts the visit of the method's code, if any (i.e. non abstract method). + */ + public void visitCode() { + if (mv != null) { + mv.visitCode(); + } + } + + /** + * Visits the current state of the local variables and operand stack + * elements. This method must(*) be called just before any + * instruction i that follows an unconditional branch instruction + * such as GOTO or THROW, that is the target of a jump instruction, or that + * starts an exception handler block. The visited types must describe the + * values of the local variables and of the operand stack elements just + * before i is executed.
+ *
+ * (*) this is mandatory only for classes whose version is greater than or + * equal to {@link Opcodes#V1_6 V1_6}.
+ *
+ * The frames of a method must be given either in expanded form, or in + * compressed form (all frames must use the same format, i.e. you must not + * mix expanded and compressed frames within a single method): + *
    + *
  • In expanded form, all frames must have the F_NEW type.
  • + *
  • In compressed form, frames are basically "deltas" from the state of + * the previous frame: + *
      + *
    • {@link Opcodes#F_SAME} representing frame with exactly the same + * locals as the previous frame and with the empty stack.
    • + *
    • {@link Opcodes#F_SAME1} representing frame with exactly the same + * locals as the previous frame and with single value on the stack ( + * nStack is 1 and stack[0] contains value for the + * type of the stack item).
    • + *
    • {@link Opcodes#F_APPEND} representing frame with current locals are + * the same as the locals in the previous frame, except that additional + * locals are defined (nLocal is 1, 2 or 3 and + * local elements contains values representing added types).
    • + *
    • {@link Opcodes#F_CHOP} representing frame with current locals are the + * same as the locals in the previous frame, except that the last 1-3 locals + * are absent and with the empty stack (nLocals is 1, 2 or 3).
    • + *
    • {@link Opcodes#F_FULL} representing complete frame data.
    • + *
    + *
  • + *
+ *
+ * In both cases the first frame, corresponding to the method's parameters + * and access flags, is implicit and must not be visited. Also, it is + * illegal to visit two or more frames for the same code location (i.e., at + * least one instruction must be visited between two calls to visitFrame). + * + * @param type + * the type of this stack map frame. Must be + * {@link Opcodes#F_NEW} for expanded frames, or + * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, + * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or + * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for + * compressed frames. + * @param nLocal + * the number of local variables in the visited frame. + * @param local + * the local variable types in this frame. This array must not be + * modified. Primitive types are represented by + * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, + * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, + * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or + * {@link Opcodes#UNINITIALIZED_THIS} (long and double are + * represented by a single element). Reference types are + * represented by String objects (representing internal names), + * and uninitialized types by Label objects (this label + * designates the NEW instruction that created this uninitialized + * value). + * @param nStack + * the number of operand stack elements in the visited frame. + * @param stack + * the operand stack types in this frame. This array must not be + * modified. Its content has the same format as the "local" + * array. + * @throws IllegalStateException + * if a frame is visited just after another one, without any + * instruction between the two (unless this frame is a + * Opcodes#F_SAME frame, in which case it is silently ignored). + */ + public void visitFrame(int type, int nLocal, Object[] local, int nStack, + Object[] stack) { + if (mv != null) { + mv.visitFrame(type, nLocal, local, nStack, stack); + } + } + + // ------------------------------------------------------------------------- + // Normal instructions + // ------------------------------------------------------------------------- + + /** + * Visits a zero operand instruction. + * + * @param opcode + * the opcode of the instruction to be visited. This opcode is + * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, + * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, + * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, + * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, + * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, + * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, + * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, + * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, + * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, + * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, + * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, + * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, + * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, + * or MONITOREXIT. + */ + public void visitInsn(int opcode) { + if (mv != null) { + mv.visitInsn(opcode); + } + } + + /** + * Visits an instruction with a single int operand. + * + * @param opcode + * the opcode of the instruction to be visited. This opcode is + * either BIPUSH, SIPUSH or NEWARRAY. + * @param operand + * the operand of the instruction to be visited.
+ * When opcode is BIPUSH, operand value should be between + * Byte.MIN_VALUE and Byte.MAX_VALUE.
+ * When opcode is SIPUSH, operand value should be between + * Short.MIN_VALUE and Short.MAX_VALUE.
+ * When opcode is NEWARRAY, operand value should be one of + * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, + * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, + * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, + * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. + */ + public void visitIntInsn(int opcode, int operand) { + if (mv != null) { + mv.visitIntInsn(opcode, operand); + } + } + + /** + * Visits a local variable instruction. A local variable instruction is an + * instruction that loads or stores the value of a local variable. + * + * @param opcode + * the opcode of the local variable instruction to be visited. + * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, + * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. + * @param var + * the operand of the instruction to be visited. This operand is + * the index of a local variable. + */ + public void visitVarInsn(int opcode, int var) { + if (mv != null) { + mv.visitVarInsn(opcode, var); + } + } + + /** + * Visits a type instruction. A type instruction is an instruction that + * takes the internal name of a class as parameter. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. + * @param type + * the operand of the instruction to be visited. This operand + * must be the internal name of an object or array class (see + * {@link Type#getInternalName() getInternalName}). + */ + public void visitTypeInsn(int opcode, String type) { + if (mv != null) { + mv.visitTypeInsn(opcode, type); + } + } + + /** + * Visits a field instruction. A field instruction is an instruction that + * loads or stores the value of a field of an object. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. + * @param owner + * the internal name of the field's owner class (see + * {@link Type#getInternalName() getInternalName}). + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link Type Type}). + */ + public void visitFieldInsn(int opcode, String owner, String name, + String desc) { + if (mv != null) { + mv.visitFieldInsn(opcode, owner, name, desc); + } + } + + /** + * Visits a method instruction. A method instruction is an instruction that + * invokes a method. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or + * INVOKEINTERFACE. + * @param owner + * the internal name of the method's owner class (see + * {@link Type#getInternalName() getInternalName}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type Type}). + */ + @Deprecated + public void visitMethodInsn(int opcode, String owner, String name, + String desc) { + if (api >= Opcodes.ASM5) { + boolean itf = opcode == Opcodes.INVOKEINTERFACE; + visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + if (mv != null) { + mv.visitMethodInsn(opcode, owner, name, desc); + } + } + + /** + * Visits a method instruction. A method instruction is an instruction that + * invokes a method. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or + * INVOKEINTERFACE. + * @param owner + * the internal name of the method's owner class (see + * {@link Type#getInternalName() getInternalName}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type Type}). + * @param itf + * if the method's owner class is an interface. + */ + public void visitMethodInsn(int opcode, String owner, String name, + String desc, boolean itf) { + if (api < Opcodes.ASM5) { + if (itf != (opcode == Opcodes.INVOKEINTERFACE)) { + throw new IllegalArgumentException( + "INVOKESPECIAL/STATIC on interfaces require ASM 5"); + } + visitMethodInsn(opcode, owner, name, desc); + return; + } + if (mv != null) { + mv.visitMethodInsn(opcode, owner, name, desc, itf); + } + } + + /** + * Visits an invokedynamic instruction. + * + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type Type}). + * @param bsm + * the bootstrap method. + * @param bsmArgs + * the bootstrap method constant arguments. Each argument must be + * an {@link Integer}, {@link Float}, {@link Long}, + * {@link Double}, {@link String}, {@link Type} or {@link Handle} + * value. This method is allowed to modify the content of the + * array so a caller should expect that this array may change. + */ + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { + if (mv != null) { + mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); + } + } + + /** + * Visits a jump instruction. A jump instruction is an instruction that may + * jump to another instruction. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, + * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, + * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. + * @param label + * the operand of the instruction to be visited. This operand is + * a label that designates the instruction to which the jump + * instruction may jump. + */ + public void visitJumpInsn(int opcode, Label label) { + if (mv != null) { + mv.visitJumpInsn(opcode, label); + } + } + + /** + * Visits a label. A label designates the instruction that will be visited + * just after it. + * + * @param label + * a {@link Label Label} object. + */ + public void visitLabel(Label label) { + if (mv != null) { + mv.visitLabel(label); + } + } + + // ------------------------------------------------------------------------- + // Special instructions + // ------------------------------------------------------------------------- + + /** + * Visits a LDC instruction. Note that new constant types may be added in + * future versions of the Java Virtual Machine. To easily detect new + * constant types, implementations of this method should check for + * unexpected constant types, like this: + * + *
+     * if (cst instanceof Integer) {
+     *     // ...
+     * } else if (cst instanceof Float) {
+     *     // ...
+     * } else if (cst instanceof Long) {
+     *     // ...
+     * } else if (cst instanceof Double) {
+     *     // ...
+     * } else if (cst instanceof String) {
+     *     // ...
+     * } else if (cst instanceof Type) {
+     *     int sort = ((Type) cst).getSort();
+     *     if (sort == Type.OBJECT) {
+     *         // ...
+     *     } else if (sort == Type.ARRAY) {
+     *         // ...
+     *     } else if (sort == Type.METHOD) {
+     *         // ...
+     *     } else {
+     *         // throw an exception
+     *     }
+     * } else if (cst instanceof Handle) {
+     *     // ...
+     * } else {
+     *     // throw an exception
+     * }
+     * 
+ * + * @param cst + * the constant to be loaded on the stack. This parameter must be + * a non null {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double}, a {@link String}, a {@link Type} of OBJECT or + * ARRAY sort for .class constants, for classes whose + * version is 49.0, a {@link Type} of METHOD sort or a + * {@link Handle} for MethodType and MethodHandle constants, for + * classes whose version is 51.0. + */ + public void visitLdcInsn(Object cst) { + if (mv != null) { + mv.visitLdcInsn(cst); + } + } + + /** + * Visits an IINC instruction. + * + * @param var + * index of the local variable to be incremented. + * @param increment + * amount to increment the local variable by. + */ + public void visitIincInsn(int var, int increment) { + if (mv != null) { + mv.visitIincInsn(var, increment); + } + } + + /** + * Visits a TABLESWITCH instruction. + * + * @param min + * the minimum key value. + * @param max + * the maximum key value. + * @param dflt + * beginning of the default handler block. + * @param labels + * beginnings of the handler blocks. labels[i] is the + * beginning of the handler block for the min + i key. + */ + public void visitTableSwitchInsn(int min, int max, Label dflt, + Label... labels) { + if (mv != null) { + mv.visitTableSwitchInsn(min, max, dflt, labels); + } + } + + /** + * Visits a LOOKUPSWITCH instruction. + * + * @param dflt + * beginning of the default handler block. + * @param keys + * the values of the keys. + * @param labels + * beginnings of the handler blocks. labels[i] is the + * beginning of the handler block for the keys[i] key. + */ + public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { + if (mv != null) { + mv.visitLookupSwitchInsn(dflt, keys, labels); + } + } + + /** + * Visits a MULTIANEWARRAY instruction. + * + * @param desc + * an array type descriptor (see {@link Type Type}). + * @param dims + * number of dimensions of the array to allocate. + */ + public void visitMultiANewArrayInsn(String desc, int dims) { + if (mv != null) { + mv.visitMultiANewArrayInsn(desc, dims); + } + } + + /** + * Visits an annotation on an instruction. This method must be called just + * after the annotated instruction. It can be called several times + * for the same instruction. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#INSTANCEOF INSTANCEOF}, + * {@link TypeReference#NEW NEW}, + * {@link TypeReference#CONSTRUCTOR_REFERENCE + * CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE + * METHOD_REFERENCE}, {@link TypeReference#CAST CAST}, + * {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT + * METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT + * METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitInsnAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (mv != null) { + return mv.visitInsnAnnotation(typeRef, typePath, desc, visible); + } + return null; + } + + // ------------------------------------------------------------------------- + // Exceptions table entries, debug information, max stack and max locals + // ------------------------------------------------------------------------- + + /** + * Visits a try catch block. + * + * @param start + * beginning of the exception handler's scope (inclusive). + * @param end + * end of the exception handler's scope (exclusive). + * @param handler + * beginning of the exception handler's code. + * @param type + * internal name of the type of exceptions handled by the + * handler, or null to catch any exceptions (for + * "finally" blocks). + * @throws IllegalArgumentException + * if one of the labels has already been visited by this visitor + * (by the {@link #visitLabel visitLabel} method). + */ + public void visitTryCatchBlock(Label start, Label end, Label handler, + String type) { + if (mv != null) { + mv.visitTryCatchBlock(start, end, handler, type); + } + } + + /** + * Visits an annotation on an exception handler type. This method must be + * called after the {@link #visitTryCatchBlock} for the annotated + * exception handler. It can be called several times for the same exception + * handler. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#EXCEPTION_PARAMETER + * EXCEPTION_PARAMETER}. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitTryCatchAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (mv != null) { + return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible); + } + return null; + } + + /** + * Visits a local variable declaration. + * + * @param name + * the name of a local variable. + * @param desc + * the type descriptor of this local variable. + * @param signature + * the type signature of this local variable. May be + * null if the local variable type does not use generic + * types. + * @param start + * the first instruction corresponding to the scope of this local + * variable (inclusive). + * @param end + * the last instruction corresponding to the scope of this local + * variable (exclusive). + * @param index + * the local variable's index. + * @throws IllegalArgumentException + * if one of the labels has not already been visited by this + * visitor (by the {@link #visitLabel visitLabel} method). + */ + public void visitLocalVariable(String name, String desc, String signature, + Label start, Label end, int index) { + if (mv != null) { + mv.visitLocalVariable(name, desc, signature, start, end, index); + } + } + + /** + * Visits an annotation on a local variable type. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link TypeReference#LOCAL_VARIABLE + * LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE + * RESOURCE_VARIABLE}. See {@link TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param start + * the fist instructions corresponding to the continuous ranges + * that make the scope of this local variable (inclusive). + * @param end + * the last instructions corresponding to the continuous ranges + * that make the scope of this local variable (exclusive). This + * array must have the same size as the 'start' array. + * @param index + * the local variable's index in each range. This array must have + * the same size as the 'start' array. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null if + * this visitor is not interested in visiting this annotation. + */ + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, + TypePath typePath, Label[] start, Label[] end, int[] index, + String desc, boolean visible) { + if (api < Opcodes.ASM5) { + throw new RuntimeException(); + } + if (mv != null) { + return mv.visitLocalVariableAnnotation(typeRef, typePath, start, + end, index, desc, visible); + } + return null; + } + + /** + * Visits a line number declaration. + * + * @param line + * a line number. This number refers to the source file from + * which the class was compiled. + * @param start + * the first instruction corresponding to this line number. + * @throws IllegalArgumentException + * if start has not already been visited by this + * visitor (by the {@link #visitLabel visitLabel} method). + */ + public void visitLineNumber(int line, Label start) { + if (mv != null) { + mv.visitLineNumber(line, start); + } + } + + /** + * Visits the maximum stack size and the maximum number of local variables + * of the method. + * + * @param maxStack + * maximum stack size of the method. + * @param maxLocals + * maximum number of local variables for the method. + */ + public void visitMaxs(int maxStack, int maxLocals) { + if (mv != null) { + mv.visitMaxs(maxStack, maxLocals); + } + } + + /** + * Visits the end of the method. This method, which is the last one to be + * called, is used to inform the visitor that all the annotations and + * attributes of the method have been visited. + */ + public void visitEnd() { + if (mv != null) { + mv.visitEnd(); + } + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/MethodWriter.java b/blade-core/src/main/java/org/objectweb/asm/MethodWriter.java new file mode 100644 index 000000000..5d30ddc0e --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/MethodWriter.java @@ -0,0 +1,2915 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * A {@link MethodVisitor} that generates methods in bytecode form. Each visit + * method of this class appends the bytecode corresponding to the visited + * instruction to a byte vector, in the order these methods are called. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +class MethodWriter extends MethodVisitor { + + /** + * Pseudo access flag used to denote constructors. + */ + static final int ACC_CONSTRUCTOR = 0x80000; + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is zero. + */ + static final int SAME_FRAME = 0; // to 63 (0-3f) + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is 1 + */ + static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f) + + /** + * Reserved for future use + */ + static final int RESERVED = 128; + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is 1. Offset is bigger then 63; + */ + static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7 + + /** + * Frame where current locals are the same as the locals in the previous + * frame, except that the k last locals are absent. The value of k is given + * by the formula 251-frame_type. + */ + static final int CHOP_FRAME = 248; // to 250 (f8-fA) + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is zero. Offset is bigger then 63; + */ + static final int SAME_FRAME_EXTENDED = 251; // fb + + /** + * Frame where current locals are the same as the locals in the previous + * frame, except that k additional locals are defined. The value of k is + * given by the formula frame_type-251. + */ + static final int APPEND_FRAME = 252; // to 254 // fc-fe + + /** + * Full frame + */ + static final int FULL_FRAME = 255; // ff + + /** + * Indicates that the stack map frames must be recomputed from scratch. In + * this case the maximum stack size and number of local variables is also + * recomputed from scratch. + * + * @see #compute + */ + private static final int FRAMES = 0; + + /** + * Indicates that the maximum stack size and number of local variables must + * be automatically computed. + * + * @see #compute + */ + private static final int MAXS = 1; + + /** + * Indicates that nothing must be automatically computed. + * + * @see #compute + */ + private static final int NOTHING = 2; + + /** + * The class writer to which this method must be added. + */ + final ClassWriter cw; + + /** + * Access flags of this method. + */ + private int access; + + /** + * The index of the constant pool item that contains the name of this + * method. + */ + private final int name; + + /** + * The index of the constant pool item that contains the descriptor of this + * method. + */ + private final int desc; + + /** + * The descriptor of this method. + */ + private final String descriptor; + + /** + * The signature of this method. + */ + String signature; + + /** + * If not zero, indicates that the code of this method must be copied from + * the ClassReader associated to this writer in cw.cr. More + * precisely, this field gives the index of the first byte to copied from + * cw.cr.b. + */ + int classReaderOffset; + + /** + * If not zero, indicates that the code of this method must be copied from + * the ClassReader associated to this writer in cw.cr. More + * precisely, this field gives the number of bytes to copied from + * cw.cr.b. + */ + int classReaderLength; + + /** + * Number of exceptions that can be thrown by this method. + */ + int exceptionCount; + + /** + * The exceptions that can be thrown by this method. More precisely, this + * array contains the indexes of the constant pool items that contain the + * internal names of these exception classes. + */ + int[] exceptions; + + /** + * The annotation default attribute of this method. May be null. + */ + private ByteVector annd; + + /** + * The runtime visible annotations of this method. May be null. + */ + private AnnotationWriter anns; + + /** + * The runtime invisible annotations of this method. May be null. + */ + private AnnotationWriter ianns; + + /** + * The runtime visible type annotations of this method. May be null + * . + */ + private AnnotationWriter tanns; + + /** + * The runtime invisible type annotations of this method. May be + * null. + */ + private AnnotationWriter itanns; + + /** + * The runtime visible parameter annotations of this method. May be + * null. + */ + private AnnotationWriter[] panns; + + /** + * The runtime invisible parameter annotations of this method. May be + * null. + */ + private AnnotationWriter[] ipanns; + + /** + * The number of synthetic parameters of this method. + */ + private int synthetics; + + /** + * The non standard attributes of the method. + */ + private Attribute attrs; + + /** + * The bytecode of this method. + */ + private ByteVector code = new ByteVector(); + + /** + * Maximum stack size of this method. + */ + private int maxStack; + + /** + * Maximum number of local variables for this method. + */ + private int maxLocals; + + /** + * Number of local variables in the current stack map frame. + */ + private int currentLocals; + + /** + * Number of stack map frames in the StackMapTable attribute. + */ + private int frameCount; + + /** + * The StackMapTable attribute. + */ + private ByteVector stackMap; + + /** + * The offset of the last frame that was written in the StackMapTable + * attribute. + */ + private int previousFrameOffset; + + /** + * The last frame that was written in the StackMapTable attribute. + * + * @see #frame + */ + private int[] previousFrame; + + /** + * The current stack map frame. The first element contains the offset of the + * instruction to which the frame corresponds, the second element is the + * number of locals and the third one is the number of stack elements. The + * local variables start at index 3 and are followed by the operand stack + * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] = + * nStack, frame[3] = nLocal. All types are encoded as integers, with the + * same format as the one used in {@link Label}, but limited to BASE types. + */ + private int[] frame; + + /** + * Number of elements in the exception handler list. + */ + private int handlerCount; + + /** + * The first element in the exception handler list. + */ + private Handler firstHandler; + + /** + * The last element in the exception handler list. + */ + private Handler lastHandler; + + /** + * Number of entries in the MethodParameters attribute. + */ + private int methodParametersCount; + + /** + * The MethodParameters attribute. + */ + private ByteVector methodParameters; + + /** + * Number of entries in the LocalVariableTable attribute. + */ + private int localVarCount; + + /** + * The LocalVariableTable attribute. + */ + private ByteVector localVar; + + /** + * Number of entries in the LocalVariableTypeTable attribute. + */ + private int localVarTypeCount; + + /** + * The LocalVariableTypeTable attribute. + */ + private ByteVector localVarType; + + /** + * Number of entries in the LineNumberTable attribute. + */ + private int lineNumberCount; + + /** + * The LineNumberTable attribute. + */ + private ByteVector lineNumber; + + /** + * The start offset of the last visited instruction. + */ + private int lastCodeOffset; + + /** + * The runtime visible type annotations of the code. May be null. + */ + private AnnotationWriter ctanns; + + /** + * The runtime invisible type annotations of the code. May be null. + */ + private AnnotationWriter ictanns; + + /** + * The non standard attributes of the method's code. + */ + private Attribute cattrs; + + /** + * Indicates if some jump instructions are too small and need to be resized. + */ + private boolean resize; + + /** + * The number of subroutines in this method. + */ + private int subroutines; + + // ------------------------------------------------------------------------ + + /* + * Fields for the control flow graph analysis algorithm (used to compute the + * maximum stack size). A control flow graph contains one node per "basic + * block", and one edge per "jump" from one basic block to another. Each + * node (i.e., each basic block) is represented by the Label object that + * corresponds to the first instruction of this basic block. Each node also + * stores the list of its successors in the graph, as a linked list of Edge + * objects. + */ + + /** + * Indicates what must be automatically computed. + * + * @see #FRAMES + * @see #MAXS + * @see #NOTHING + */ + private final int compute; + + /** + * A list of labels. This list is the list of basic blocks in the method, + * i.e. a list of Label objects linked to each other by their + * {@link Label#successor} field, in the order they are visited by + * {@link MethodVisitor#visitLabel}, and starting with the first basic + * block. + */ + private Label labels; + + /** + * The previous basic block. + */ + private Label previousBlock; + + /** + * The current basic block. + */ + private Label currentBlock; + + /** + * The (relative) stack size after the last visited instruction. This size + * is relative to the beginning of the current basic block, i.e., the true + * stack size after the last visited instruction is equal to the + * {@link Label#inputStackTop beginStackSize} of the current basic block + * plus stackSize. + */ + private int stackSize; + + /** + * The (relative) maximum stack size after the last visited instruction. + * This size is relative to the beginning of the current basic block, i.e., + * the true maximum stack size after the last visited instruction is equal + * to the {@link Label#inputStackTop beginStackSize} of the current basic + * block plus stackSize. + */ + private int maxStackSize; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link MethodWriter}. + * + * @param cw + * the class writer in which the method must be added. + * @param access + * the method's access flags (see {@link Opcodes}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type}). + * @param signature + * the method's signature. May be null. + * @param exceptions + * the internal names of the method's exceptions. May be + * null. + * @param computeMaxs + * true if the maximum stack size and number of local + * variables must be automatically computed. + * @param computeFrames + * true if the stack map tables must be recomputed from + * scratch. + */ + MethodWriter(final ClassWriter cw, final int access, final String name, + final String desc, final String signature, + final String[] exceptions, final boolean computeMaxs, + final boolean computeFrames) { + super(Opcodes.ASM5); + if (cw.firstMethod == null) { + cw.firstMethod = this; + } else { + cw.lastMethod.mv = this; + } + cw.lastMethod = this; + this.cw = cw; + this.access = access; + if ("".equals(name)) { + this.access |= ACC_CONSTRUCTOR; + } + this.name = cw.newUTF8(name); + this.desc = cw.newUTF8(desc); + this.descriptor = desc; + if (ClassReader.SIGNATURES) { + this.signature = signature; + } + if (exceptions != null && exceptions.length > 0) { + exceptionCount = exceptions.length; + this.exceptions = new int[exceptionCount]; + for (int i = 0; i < exceptionCount; ++i) { + this.exceptions[i] = cw.newClass(exceptions[i]); + } + } + this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING); + if (computeMaxs || computeFrames) { + // updates maxLocals + int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2; + if ((access & Opcodes.ACC_STATIC) != 0) { + --size; + } + maxLocals = size; + currentLocals = size; + // creates and visits the label for the first basic block + labels = new Label(); + labels.status |= Label.PUSHED; + visitLabel(labels); + } + } + + // ------------------------------------------------------------------------ + // Implementation of the MethodVisitor abstract class + // ------------------------------------------------------------------------ + + @Override + public void visitParameter(String name, int access) { + if (methodParameters == null) { + methodParameters = new ByteVector(); + } + ++methodParametersCount; + methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name)) + .putShort(access); + } + + @Override + public AnnotationVisitor visitAnnotationDefault() { + if (!ClassReader.ANNOTATIONS) { + return null; + } + annd = new ByteVector(); + return new AnnotationWriter(cw, false, annd, null, 0); + } + + @Override + public AnnotationVisitor visitAnnotation(final String desc, + final boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); + if (visible) { + aw.next = anns; + anns = aw; + } else { + aw.next = ianns; + ianns = aw; + } + return aw; + } + + @Override + public AnnotationVisitor visitTypeAnnotation(final int typeRef, + final TypePath typePath, final String desc, final boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + AnnotationWriter.putTarget(typeRef, typePath, bv); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = tanns; + tanns = aw; + } else { + aw.next = itanns; + itanns = aw; + } + return aw; + } + + @Override + public AnnotationVisitor visitParameterAnnotation(final int parameter, + final String desc, final boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + if ("Ljava/lang/Synthetic;".equals(desc)) { + // workaround for a bug in javac with synthetic parameters + // see ClassReader.readParameterAnnotations + synthetics = Math.max(synthetics, parameter + 1); + return new AnnotationWriter(cw, false, bv, null, 0); + } + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); + if (visible) { + if (panns == null) { + panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; + } + aw.next = panns[parameter]; + panns[parameter] = aw; + } else { + if (ipanns == null) { + ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; + } + aw.next = ipanns[parameter]; + ipanns[parameter] = aw; + } + return aw; + } + + @Override + public void visitAttribute(final Attribute attr) { + if (attr.isCodeAttribute()) { + attr.next = cattrs; + cattrs = attr; + } else { + attr.next = attrs; + attrs = attr; + } + } + + @Override + public void visitCode() { + } + + @Override + public void visitFrame(final int type, final int nLocal, + final Object[] local, final int nStack, final Object[] stack) { + if (!ClassReader.FRAMES || compute == FRAMES) { + return; + } + + if (type == Opcodes.F_NEW) { + if (previousFrame == null) { + visitImplicitFirstFrame(); + } + currentLocals = nLocal; + int frameIndex = startFrame(code.length, nLocal, nStack); + for (int i = 0; i < nLocal; ++i) { + if (local[i] instanceof String) { + frame[frameIndex++] = Frame.OBJECT + | cw.addType((String) local[i]); + } else if (local[i] instanceof Integer) { + frame[frameIndex++] = ((Integer) local[i]).intValue(); + } else { + frame[frameIndex++] = Frame.UNINITIALIZED + | cw.addUninitializedType("", + ((Label) local[i]).position); + } + } + for (int i = 0; i < nStack; ++i) { + if (stack[i] instanceof String) { + frame[frameIndex++] = Frame.OBJECT + | cw.addType((String) stack[i]); + } else if (stack[i] instanceof Integer) { + frame[frameIndex++] = ((Integer) stack[i]).intValue(); + } else { + frame[frameIndex++] = Frame.UNINITIALIZED + | cw.addUninitializedType("", + ((Label) stack[i]).position); + } + } + endFrame(); + } else { + int delta; + if (stackMap == null) { + stackMap = new ByteVector(); + delta = code.length; + } else { + delta = code.length - previousFrameOffset - 1; + if (delta < 0) { + if (type == Opcodes.F_SAME) { + return; + } else { + throw new IllegalStateException(); + } + } + } + + switch (type) { + case Opcodes.F_FULL: + currentLocals = nLocal; + stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal); + for (int i = 0; i < nLocal; ++i) { + writeFrameType(local[i]); + } + stackMap.putShort(nStack); + for (int i = 0; i < nStack; ++i) { + writeFrameType(stack[i]); + } + break; + case Opcodes.F_APPEND: + currentLocals += nLocal; + stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta); + for (int i = 0; i < nLocal; ++i) { + writeFrameType(local[i]); + } + break; + case Opcodes.F_CHOP: + currentLocals -= nLocal; + stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta); + break; + case Opcodes.F_SAME: + if (delta < 64) { + stackMap.putByte(delta); + } else { + stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); + } + break; + case Opcodes.F_SAME1: + if (delta < 64) { + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); + } else { + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) + .putShort(delta); + } + writeFrameType(stack[0]); + break; + } + + previousFrameOffset = code.length; + ++frameCount; + } + + maxStack = Math.max(maxStack, nStack); + maxLocals = Math.max(maxLocals, currentLocals); + } + + @Override + public void visitInsn(final int opcode) { + lastCodeOffset = code.length; + // adds the instruction to the bytecode of the method + code.putByte(opcode); + // update currentBlock + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, 0, null, null); + } else { + // updates current and max stack sizes + int size = stackSize + Frame.SIZE[opcode]; + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + // if opcode == ATHROW or xRETURN, ends current block (no successor) + if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) + || opcode == Opcodes.ATHROW) { + noSuccessor(); + } + } + } + + @Override + public void visitIntInsn(final int opcode, final int operand) { + lastCodeOffset = code.length; + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, operand, null, null); + } else if (opcode != Opcodes.NEWARRAY) { + // updates current and max stack sizes only for NEWARRAY + // (stack size variation = 0 for BIPUSH or SIPUSH) + int size = stackSize + 1; + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + if (opcode == Opcodes.SIPUSH) { + code.put12(opcode, operand); + } else { // BIPUSH or NEWARRAY + code.put11(opcode, operand); + } + } + + @Override + public void visitVarInsn(final int opcode, final int var) { + lastCodeOffset = code.length; + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, var, null, null); + } else { + // updates current and max stack sizes + if (opcode == Opcodes.RET) { + // no stack change, but end of current block (no successor) + currentBlock.status |= Label.RET; + // save 'stackSize' here for future use + // (see {@link #findSubroutineSuccessors}) + currentBlock.inputStackTop = stackSize; + noSuccessor(); + } else { // xLOAD or xSTORE + int size = stackSize + Frame.SIZE[opcode]; + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + } + if (compute != NOTHING) { + // updates max locals + int n; + if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD + || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) { + n = var + 2; + } else { + n = var + 1; + } + if (n > maxLocals) { + maxLocals = n; + } + } + // adds the instruction to the bytecode of the method + if (var < 4 && opcode != Opcodes.RET) { + int opt; + if (opcode < Opcodes.ISTORE) { + /* ILOAD_0 */ + opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var; + } else { + /* ISTORE_0 */ + opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var; + } + code.putByte(opt); + } else if (var >= 256) { + code.putByte(196 /* WIDE */).put12(opcode, var); + } else { + code.put11(opcode, var); + } + if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) { + visitLabel(new Label()); + } + } + + @Override + public void visitTypeInsn(final int opcode, final String type) { + lastCodeOffset = code.length; + Item i = cw.newClassItem(type); + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, code.length, cw, i); + } else if (opcode == Opcodes.NEW) { + // updates current and max stack sizes only if opcode == NEW + // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF) + int size = stackSize + 1; + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + code.put12(opcode, i.index); + } + + @Override + public void visitFieldInsn(final int opcode, final String owner, + final String name, final String desc) { + lastCodeOffset = code.length; + Item i = cw.newFieldItem(owner, name, desc); + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, 0, cw, i); + } else { + int size; + // computes the stack size variation + char c = desc.charAt(0); + switch (opcode) { + case Opcodes.GETSTATIC: + size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); + break; + case Opcodes.PUTSTATIC: + size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); + break; + case Opcodes.GETFIELD: + size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); + break; + // case Constants.PUTFIELD: + default: + size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); + break; + } + // updates current and max stack sizes + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + code.put12(opcode, i.index); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + lastCodeOffset = code.length; + Item i = cw.newMethodItem(owner, name, desc, itf); + int argSize = i.intVal; + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, 0, cw, i); + } else { + /* + * computes the stack size variation. In order not to recompute + * several times this variation for the same Item, we use the + * intVal field of this item to store this variation, once it + * has been computed. More precisely this intVal field stores + * the sizes of the arguments and of the return value + * corresponding to desc. + */ + if (argSize == 0) { + // the above sizes have not been computed yet, + // so we compute them... + argSize = Type.getArgumentsAndReturnSizes(desc); + // ... and we save them in order + // not to recompute them in the future + i.intVal = argSize; + } + int size; + if (opcode == Opcodes.INVOKESTATIC) { + size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; + } else { + size = stackSize - (argSize >> 2) + (argSize & 0x03); + } + // updates current and max stack sizes + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + if (opcode == Opcodes.INVOKEINTERFACE) { + if (argSize == 0) { + argSize = Type.getArgumentsAndReturnSizes(desc); + i.intVal = argSize; + } + code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); + } else { + code.put12(opcode, i.index); + } + } + + @Override + public void visitInvokeDynamicInsn(final String name, final String desc, + final Handle bsm, final Object... bsmArgs) { + lastCodeOffset = code.length; + Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs); + int argSize = i.intVal; + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i); + } else { + /* + * computes the stack size variation. In order not to recompute + * several times this variation for the same Item, we use the + * intVal field of this item to store this variation, once it + * has been computed. More precisely this intVal field stores + * the sizes of the arguments and of the return value + * corresponding to desc. + */ + if (argSize == 0) { + // the above sizes have not been computed yet, + // so we compute them... + argSize = Type.getArgumentsAndReturnSizes(desc); + // ... and we save them in order + // not to recompute them in the future + i.intVal = argSize; + } + int size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; + + // updates current and max stack sizes + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + code.put12(Opcodes.INVOKEDYNAMIC, i.index); + code.putShort(0); + } + + @Override + public void visitJumpInsn(final int opcode, final Label label) { + lastCodeOffset = code.length; + Label nextInsn = null; + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, 0, null, null); + // 'label' is the target of a jump instruction + label.getFirst().status |= Label.TARGET; + // adds 'label' as a successor of this basic block + addSuccessor(Edge.NORMAL, label); + if (opcode != Opcodes.GOTO) { + // creates a Label for the next basic block + nextInsn = new Label(); + } + } else { + if (opcode == Opcodes.JSR) { + if ((label.status & Label.SUBROUTINE) == 0) { + label.status |= Label.SUBROUTINE; + ++subroutines; + } + currentBlock.status |= Label.JSR; + addSuccessor(stackSize + 1, label); + // creates a Label for the next basic block + nextInsn = new Label(); + /* + * note that, by construction in this method, a JSR block + * has at least two successors in the control flow graph: + * the first one leads the next instruction after the JSR, + * while the second one leads to the JSR target. + */ + } else { + // updates current stack size (max stack size unchanged + // because stack size variation always negative in this + // case) + stackSize += Frame.SIZE[opcode]; + addSuccessor(stackSize, label); + } + } + } + // adds the instruction to the bytecode of the method + if ((label.status & Label.RESOLVED) != 0 + && label.position - code.length < Short.MIN_VALUE) { + /* + * case of a backward jump with an offset < -32768. In this case we + * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx + * with IFNOTxxx GOTO_W , where IFNOTxxx is the + * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where + * designates the instruction just after the GOTO_W. + */ + if (opcode == Opcodes.GOTO) { + code.putByte(200); // GOTO_W + } else if (opcode == Opcodes.JSR) { + code.putByte(201); // JSR_W + } else { + // if the IF instruction is transformed into IFNOT GOTO_W the + // next instruction becomes the target of the IFNOT instruction + if (nextInsn != null) { + nextInsn.status |= Label.TARGET; + } + code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 + : opcode ^ 1); + code.putShort(8); // jump offset + code.putByte(200); // GOTO_W + } + label.put(this, code, code.length - 1, true); + } else { + /* + * case of a backward jump with an offset >= -32768, or of a forward + * jump with, of course, an unknown offset. In these cases we store + * the offset in 2 bytes (which will be increased in + * resizeInstructions, if needed). + */ + code.putByte(opcode); + label.put(this, code, code.length - 1, false); + } + if (currentBlock != null) { + if (nextInsn != null) { + // if the jump instruction is not a GOTO, the next instruction + // is also a successor of this instruction. Calling visitLabel + // adds the label of this next instruction as a successor of the + // current block, and starts a new basic block + visitLabel(nextInsn); + } + if (opcode == Opcodes.GOTO) { + noSuccessor(); + } + } + } + + @Override + public void visitLabel(final Label label) { + // resolves previous forward references to label, if any + resize |= label.resolve(this, code.length, code.data); + // updates currentBlock + if ((label.status & Label.DEBUG) != 0) { + return; + } + if (compute == FRAMES) { + if (currentBlock != null) { + if (label.position == currentBlock.position) { + // successive labels, do not start a new basic block + currentBlock.status |= (label.status & Label.TARGET); + label.frame = currentBlock.frame; + return; + } + // ends current block (with one new successor) + addSuccessor(Edge.NORMAL, label); + } + // begins a new current block + currentBlock = label; + if (label.frame == null) { + label.frame = new Frame(); + label.frame.owner = label; + } + // updates the basic block list + if (previousBlock != null) { + if (label.position == previousBlock.position) { + previousBlock.status |= (label.status & Label.TARGET); + label.frame = previousBlock.frame; + currentBlock = previousBlock; + return; + } + previousBlock.successor = label; + } + previousBlock = label; + } else if (compute == MAXS) { + if (currentBlock != null) { + // ends current block (with one new successor) + currentBlock.outputStackMax = maxStackSize; + addSuccessor(stackSize, label); + } + // begins a new current block + currentBlock = label; + // resets the relative current and max stack sizes + stackSize = 0; + maxStackSize = 0; + // updates the basic block list + if (previousBlock != null) { + previousBlock.successor = label; + } + previousBlock = label; + } + } + + @Override + public void visitLdcInsn(final Object cst) { + lastCodeOffset = code.length; + Item i = cw.newConstItem(cst); + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(Opcodes.LDC, 0, cw, i); + } else { + int size; + // computes the stack size variation + if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { + size = stackSize + 2; + } else { + size = stackSize + 1; + } + // updates current and max stack sizes + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + int index = i.index; + if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { + code.put12(20 /* LDC2_W */, index); + } else if (index >= 256) { + code.put12(19 /* LDC_W */, index); + } else { + code.put11(Opcodes.LDC, index); + } + } + + @Override + public void visitIincInsn(final int var, final int increment) { + lastCodeOffset = code.length; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(Opcodes.IINC, var, null, null); + } + } + if (compute != NOTHING) { + // updates max locals + int n = var + 1; + if (n > maxLocals) { + maxLocals = n; + } + } + // adds the instruction to the bytecode of the method + if ((var > 255) || (increment > 127) || (increment < -128)) { + code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var) + .putShort(increment); + } else { + code.putByte(Opcodes.IINC).put11(var, increment); + } + } + + @Override + public void visitTableSwitchInsn(final int min, final int max, + final Label dflt, final Label... labels) { + lastCodeOffset = code.length; + // adds the instruction to the bytecode of the method + int source = code.length; + code.putByte(Opcodes.TABLESWITCH); + code.putByteArray(null, 0, (4 - code.length % 4) % 4); + dflt.put(this, code, source, true); + code.putInt(min).putInt(max); + for (int i = 0; i < labels.length; ++i) { + labels[i].put(this, code, source, true); + } + // updates currentBlock + visitSwitchInsn(dflt, labels); + } + + @Override + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, + final Label[] labels) { + lastCodeOffset = code.length; + // adds the instruction to the bytecode of the method + int source = code.length; + code.putByte(Opcodes.LOOKUPSWITCH); + code.putByteArray(null, 0, (4 - code.length % 4) % 4); + dflt.put(this, code, source, true); + code.putInt(labels.length); + for (int i = 0; i < labels.length; ++i) { + code.putInt(keys[i]); + labels[i].put(this, code, source, true); + } + // updates currentBlock + visitSwitchInsn(dflt, labels); + } + + private void visitSwitchInsn(final Label dflt, final Label[] labels) { + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null); + // adds current block successors + addSuccessor(Edge.NORMAL, dflt); + dflt.getFirst().status |= Label.TARGET; + for (int i = 0; i < labels.length; ++i) { + addSuccessor(Edge.NORMAL, labels[i]); + labels[i].getFirst().status |= Label.TARGET; + } + } else { + // updates current stack size (max stack size unchanged) + --stackSize; + // adds current block successors + addSuccessor(stackSize, dflt); + for (int i = 0; i < labels.length; ++i) { + addSuccessor(stackSize, labels[i]); + } + } + // ends current block + noSuccessor(); + } + } + + @Override + public void visitMultiANewArrayInsn(final String desc, final int dims) { + lastCodeOffset = code.length; + Item i = cw.newClassItem(desc); + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i); + } else { + // updates current stack size (max stack size unchanged because + // stack size variation always negative or null) + stackSize += 1 - dims; + } + } + // adds the instruction to the bytecode of the method + code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims); + } + + @Override + public AnnotationVisitor visitInsnAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8); + AnnotationWriter.putTarget(typeRef, typePath, bv); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = ctanns; + ctanns = aw; + } else { + aw.next = ictanns; + ictanns = aw; + } + return aw; + } + + @Override + public void visitTryCatchBlock(final Label start, final Label end, + final Label handler, final String type) { + ++handlerCount; + Handler h = new Handler(); + h.start = start; + h.end = end; + h.handler = handler; + h.desc = type; + h.type = type != null ? cw.newClass(type) : 0; + if (lastHandler == null) { + firstHandler = h; + } else { + lastHandler.next = h; + } + lastHandler = h; + } + + @Override + public AnnotationVisitor visitTryCatchAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + AnnotationWriter.putTarget(typeRef, typePath, bv); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = ctanns; + ctanns = aw; + } else { + aw.next = ictanns; + ictanns = aw; + } + return aw; + } + + @Override + public void visitLocalVariable(final String name, final String desc, + final String signature, final Label start, final Label end, + final int index) { + if (signature != null) { + if (localVarType == null) { + localVarType = new ByteVector(); + } + ++localVarTypeCount; + localVarType.putShort(start.position) + .putShort(end.position - start.position) + .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature)) + .putShort(index); + } + if (localVar == null) { + localVar = new ByteVector(); + } + ++localVarCount; + localVar.putShort(start.position) + .putShort(end.position - start.position) + .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc)) + .putShort(index); + if (compute != NOTHING) { + // updates max locals + char c = desc.charAt(0); + int n = index + (c == 'J' || c == 'D' ? 2 : 1); + if (n > maxLocals) { + maxLocals = n; + } + } + } + + @Override + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, + TypePath typePath, Label[] start, Label[] end, int[] index, + String desc, boolean visible) { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write target_type and target_info + bv.putByte(typeRef >>> 24).putShort(start.length); + for (int i = 0; i < start.length; ++i) { + bv.putShort(start[i].position) + .putShort(end[i].position - start[i].position) + .putShort(index[i]); + } + if (typePath == null) { + bv.putByte(0); + } else { + int length = typePath.b[typePath.offset] * 2 + 1; + bv.putByteArray(typePath.b, typePath.offset, length); + } + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, + bv.length - 2); + if (visible) { + aw.next = ctanns; + ctanns = aw; + } else { + aw.next = ictanns; + ictanns = aw; + } + return aw; + } + + @Override + public void visitLineNumber(final int line, final Label start) { + if (lineNumber == null) { + lineNumber = new ByteVector(); + } + ++lineNumberCount; + lineNumber.putShort(start.position); + lineNumber.putShort(line); + } + + @Override + public void visitMaxs(final int maxStack, final int maxLocals) { + if (resize) { + // replaces the temporary jump opcodes introduced by Label.resolve. + if (ClassReader.RESIZE) { + resizeInstructions(); + } else { + throw new RuntimeException("Method code too large!"); + } + } + if (ClassReader.FRAMES && compute == FRAMES) { + // completes the control flow graph with exception handler blocks + Handler handler = firstHandler; + while (handler != null) { + Label l = handler.start.getFirst(); + Label h = handler.handler.getFirst(); + Label e = handler.end.getFirst(); + // computes the kind of the edges to 'h' + String t = handler.desc == null ? "java/lang/Throwable" + : handler.desc; + int kind = Frame.OBJECT | cw.addType(t); + // h is an exception handler + h.status |= Label.TARGET; + // adds 'h' as a successor of labels between 'start' and 'end' + while (l != e) { + // creates an edge to 'h' + Edge b = new Edge(); + b.info = kind; + b.successor = h; + // adds it to the successors of 'l' + b.next = l.successors; + l.successors = b; + // goes to the next label + l = l.successor; + } + handler = handler.next; + } + + // creates and visits the first (implicit) frame + Frame f = labels.frame; + Type[] args = Type.getArgumentTypes(descriptor); + f.initInputFrame(cw, access, args, this.maxLocals); + visitFrame(f); + + /* + * fix point algorithm: mark the first basic block as 'changed' + * (i.e. put it in the 'changed' list) and, while there are changed + * basic blocks, choose one, mark it as unchanged, and update its + * successors (which can be changed in the process). + */ + int max = 0; + Label changed = labels; + while (changed != null) { + // removes a basic block from the list of changed basic blocks + Label l = changed; + changed = changed.next; + l.next = null; + f = l.frame; + // a reachable jump target must be stored in the stack map + if ((l.status & Label.TARGET) != 0) { + l.status |= Label.STORE; + } + // all visited labels are reachable, by definition + l.status |= Label.REACHABLE; + // updates the (absolute) maximum stack size + int blockMax = f.inputStack.length + l.outputStackMax; + if (blockMax > max) { + max = blockMax; + } + // updates the successors of the current basic block + Edge e = l.successors; + while (e != null) { + Label n = e.successor.getFirst(); + boolean change = f.merge(cw, n.frame, e.info); + if (change && n.next == null) { + // if n has changed and is not already in the 'changed' + // list, adds it to this list + n.next = changed; + changed = n; + } + e = e.next; + } + } + + // visits all the frames that must be stored in the stack map + Label l = labels; + while (l != null) { + f = l.frame; + if ((l.status & Label.STORE) != 0) { + visitFrame(f); + } + if ((l.status & Label.REACHABLE) == 0) { + // finds start and end of dead basic block + Label k = l.successor; + int start = l.position; + int end = (k == null ? code.length : k.position) - 1; + // if non empty basic block + if (end >= start) { + max = Math.max(max, 1); + // replaces instructions with NOP ... NOP ATHROW + for (int i = start; i < end; ++i) { + code.data[i] = Opcodes.NOP; + } + code.data[end] = (byte) Opcodes.ATHROW; + // emits a frame for this unreachable block + int frameIndex = startFrame(start, 0, 1); + frame[frameIndex] = Frame.OBJECT + | cw.addType("java/lang/Throwable"); + endFrame(); + // removes the start-end range from the exception + // handlers + firstHandler = Handler.remove(firstHandler, l, k); + } + } + l = l.successor; + } + + handler = firstHandler; + handlerCount = 0; + while (handler != null) { + handlerCount += 1; + handler = handler.next; + } + + this.maxStack = max; + } else if (compute == MAXS) { + // completes the control flow graph with exception handler blocks + Handler handler = firstHandler; + while (handler != null) { + Label l = handler.start; + Label h = handler.handler; + Label e = handler.end; + // adds 'h' as a successor of labels between 'start' and 'end' + while (l != e) { + // creates an edge to 'h' + Edge b = new Edge(); + b.info = Edge.EXCEPTION; + b.successor = h; + // adds it to the successors of 'l' + if ((l.status & Label.JSR) == 0) { + b.next = l.successors; + l.successors = b; + } else { + // if l is a JSR block, adds b after the first two edges + // to preserve the hypothesis about JSR block successors + // order (see {@link #visitJumpInsn}) + b.next = l.successors.next.next; + l.successors.next.next = b; + } + // goes to the next label + l = l.successor; + } + handler = handler.next; + } + + if (subroutines > 0) { + // completes the control flow graph with the RET successors + /* + * first step: finds the subroutines. This step determines, for + * each basic block, to which subroutine(s) it belongs. + */ + // finds the basic blocks that belong to the "main" subroutine + int id = 0; + labels.visitSubroutine(null, 1, subroutines); + // finds the basic blocks that belong to the real subroutines + Label l = labels; + while (l != null) { + if ((l.status & Label.JSR) != 0) { + // the subroutine is defined by l's TARGET, not by l + Label subroutine = l.successors.next.successor; + // if this subroutine has not been visited yet... + if ((subroutine.status & Label.VISITED) == 0) { + // ...assigns it a new id and finds its basic blocks + id += 1; + subroutine.visitSubroutine(null, (id / 32L) << 32 + | (1L << (id % 32)), subroutines); + } + } + l = l.successor; + } + // second step: finds the successors of RET blocks + l = labels; + while (l != null) { + if ((l.status & Label.JSR) != 0) { + Label L = labels; + while (L != null) { + L.status &= ~Label.VISITED2; + L = L.successor; + } + // the subroutine is defined by l's TARGET, not by l + Label subroutine = l.successors.next.successor; + subroutine.visitSubroutine(l, 0, subroutines); + } + l = l.successor; + } + } + + /* + * control flow analysis algorithm: while the block stack is not + * empty, pop a block from this stack, update the max stack size, + * compute the true (non relative) begin stack size of the + * successors of this block, and push these successors onto the + * stack (unless they have already been pushed onto the stack). + * Note: by hypothesis, the {@link Label#inputStackTop} of the + * blocks in the block stack are the true (non relative) beginning + * stack sizes of these blocks. + */ + int max = 0; + Label stack = labels; + while (stack != null) { + // pops a block from the stack + Label l = stack; + stack = stack.next; + // computes the true (non relative) max stack size of this block + int start = l.inputStackTop; + int blockMax = start + l.outputStackMax; + // updates the global max stack size + if (blockMax > max) { + max = blockMax; + } + // analyzes the successors of the block + Edge b = l.successors; + if ((l.status & Label.JSR) != 0) { + // ignores the first edge of JSR blocks (virtual successor) + b = b.next; + } + while (b != null) { + l = b.successor; + // if this successor has not already been pushed... + if ((l.status & Label.PUSHED) == 0) { + // computes its true beginning stack size... + l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start + + b.info; + // ...and pushes it onto the stack + l.status |= Label.PUSHED; + l.next = stack; + stack = l; + } + b = b.next; + } + } + this.maxStack = Math.max(maxStack, max); + } else { + this.maxStack = maxStack; + this.maxLocals = maxLocals; + } + } + + @Override + public void visitEnd() { + } + + // ------------------------------------------------------------------------ + // Utility methods: control flow analysis algorithm + // ------------------------------------------------------------------------ + + /** + * Adds a successor to the {@link #currentBlock currentBlock} block. + * + * @param info + * information about the control flow edge to be added. + * @param successor + * the successor block to be added to the current block. + */ + private void addSuccessor(final int info, final Label successor) { + // creates and initializes an Edge object... + Edge b = new Edge(); + b.info = info; + b.successor = successor; + // ...and adds it to the successor list of the currentBlock block + b.next = currentBlock.successors; + currentBlock.successors = b; + } + + /** + * Ends the current basic block. This method must be used in the case where + * the current basic block does not have any successor. + */ + private void noSuccessor() { + if (compute == FRAMES) { + Label l = new Label(); + l.frame = new Frame(); + l.frame.owner = l; + l.resolve(this, code.length, code.data); + previousBlock.successor = l; + previousBlock = l; + } else { + currentBlock.outputStackMax = maxStackSize; + } + currentBlock = null; + } + + // ------------------------------------------------------------------------ + // Utility methods: stack map frames + // ------------------------------------------------------------------------ + + /** + * Visits a frame that has been computed from scratch. + * + * @param f + * the frame that must be visited. + */ + private void visitFrame(final Frame f) { + int i, t; + int nTop = 0; + int nLocal = 0; + int nStack = 0; + int[] locals = f.inputLocals; + int[] stacks = f.inputStack; + // computes the number of locals (ignores TOP types that are just after + // a LONG or a DOUBLE, and all trailing TOP types) + for (i = 0; i < locals.length; ++i) { + t = locals[i]; + if (t == Frame.TOP) { + ++nTop; + } else { + nLocal += nTop + 1; + nTop = 0; + } + if (t == Frame.LONG || t == Frame.DOUBLE) { + ++i; + } + } + // computes the stack size (ignores TOP types that are just after + // a LONG or a DOUBLE) + for (i = 0; i < stacks.length; ++i) { + t = stacks[i]; + ++nStack; + if (t == Frame.LONG || t == Frame.DOUBLE) { + ++i; + } + } + // visits the frame and its content + int frameIndex = startFrame(f.owner.position, nLocal, nStack); + for (i = 0; nLocal > 0; ++i, --nLocal) { + t = locals[i]; + frame[frameIndex++] = t; + if (t == Frame.LONG || t == Frame.DOUBLE) { + ++i; + } + } + for (i = 0; i < stacks.length; ++i) { + t = stacks[i]; + frame[frameIndex++] = t; + if (t == Frame.LONG || t == Frame.DOUBLE) { + ++i; + } + } + endFrame(); + } + + /** + * Visit the implicit first frame of this method. + */ + private void visitImplicitFirstFrame() { + // There can be at most descriptor.length() + 1 locals + int frameIndex = startFrame(0, descriptor.length() + 1, 0); + if ((access & Opcodes.ACC_STATIC) == 0) { + if ((access & ACC_CONSTRUCTOR) == 0) { + frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName); + } else { + frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS; + } + } + int i = 1; + loop: while (true) { + int j = i; + switch (descriptor.charAt(i++)) { + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + frame[frameIndex++] = 1; // Opcodes.INTEGER; + break; + case 'F': + frame[frameIndex++] = 2; // Opcodes.FLOAT; + break; + case 'J': + frame[frameIndex++] = 4; // Opcodes.LONG; + break; + case 'D': + frame[frameIndex++] = 3; // Opcodes.DOUBLE; + break; + case '[': + while (descriptor.charAt(i) == '[') { + ++i; + } + if (descriptor.charAt(i) == 'L') { + ++i; + while (descriptor.charAt(i) != ';') { + ++i; + } + } + frame[frameIndex++] = Frame.OBJECT + | cw.addType(descriptor.substring(j, ++i)); + break; + case 'L': + while (descriptor.charAt(i) != ';') { + ++i; + } + frame[frameIndex++] = Frame.OBJECT + | cw.addType(descriptor.substring(j + 1, i++)); + break; + default: + break loop; + } + } + frame[1] = frameIndex - 3; + endFrame(); + } + + /** + * Starts the visit of a stack map frame. + * + * @param offset + * the offset of the instruction to which the frame corresponds. + * @param nLocal + * the number of local variables in the frame. + * @param nStack + * the number of stack elements in the frame. + * @return the index of the next element to be written in this frame. + */ + private int startFrame(final int offset, final int nLocal, final int nStack) { + int n = 3 + nLocal + nStack; + if (frame == null || frame.length < n) { + frame = new int[n]; + } + frame[0] = offset; + frame[1] = nLocal; + frame[2] = nStack; + return 3; + } + + /** + * Checks if the visit of the current frame {@link #frame} is finished, and + * if yes, write it in the StackMapTable attribute. + */ + private void endFrame() { + if (previousFrame != null) { // do not write the first frame + if (stackMap == null) { + stackMap = new ByteVector(); + } + writeFrame(); + ++frameCount; + } + previousFrame = frame; + frame = null; + } + + /** + * Compress and writes the current frame {@link #frame} in the StackMapTable + * attribute. + */ + private void writeFrame() { + int clocalsSize = frame[1]; + int cstackSize = frame[2]; + if ((cw.version & 0xFFFF) < Opcodes.V1_6) { + stackMap.putShort(frame[0]).putShort(clocalsSize); + writeFrameTypes(3, 3 + clocalsSize); + stackMap.putShort(cstackSize); + writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); + return; + } + int localsSize = previousFrame[1]; + int type = FULL_FRAME; + int k = 0; + int delta; + if (frameCount == 0) { + delta = frame[0]; + } else { + delta = frame[0] - previousFrame[0] - 1; + } + if (cstackSize == 0) { + k = clocalsSize - localsSize; + switch (k) { + case -3: + case -2: + case -1: + type = CHOP_FRAME; + localsSize = clocalsSize; + break; + case 0: + type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED; + break; + case 1: + case 2: + case 3: + type = APPEND_FRAME; + break; + } + } else if (clocalsSize == localsSize && cstackSize == 1) { + type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME + : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED; + } + if (type != FULL_FRAME) { + // verify if locals are the same + int l = 3; + for (int j = 0; j < localsSize; j++) { + if (frame[l] != previousFrame[l]) { + type = FULL_FRAME; + break; + } + l++; + } + } + switch (type) { + case SAME_FRAME: + stackMap.putByte(delta); + break; + case SAME_LOCALS_1_STACK_ITEM_FRAME: + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); + writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); + break; + case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort( + delta); + writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); + break; + case SAME_FRAME_EXTENDED: + stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); + break; + case CHOP_FRAME: + stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); + break; + case APPEND_FRAME: + stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); + writeFrameTypes(3 + localsSize, 3 + clocalsSize); + break; + // case FULL_FRAME: + default: + stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize); + writeFrameTypes(3, 3 + clocalsSize); + stackMap.putShort(cstackSize); + writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); + } + } + + /** + * Writes some types of the current frame {@link #frame} into the + * StackMapTableAttribute. This method converts types from the format used + * in {@link Label} to the format used in StackMapTable attributes. In + * particular, it converts type table indexes to constant pool indexes. + * + * @param start + * index of the first type in {@link #frame} to write. + * @param end + * index of last type in {@link #frame} to write (exclusive). + */ + private void writeFrameTypes(final int start, final int end) { + for (int i = start; i < end; ++i) { + int t = frame[i]; + int d = t & Frame.DIM; + if (d == 0) { + int v = t & Frame.BASE_VALUE; + switch (t & Frame.BASE_KIND) { + case Frame.OBJECT: + stackMap.putByte(7).putShort( + cw.newClass(cw.typeTable[v].strVal1)); + break; + case Frame.UNINITIALIZED: + stackMap.putByte(8).putShort(cw.typeTable[v].intVal); + break; + default: + stackMap.putByte(v); + } + } else { + StringBuilder sb = new StringBuilder(); + d >>= 28; + while (d-- > 0) { + sb.append('['); + } + if ((t & Frame.BASE_KIND) == Frame.OBJECT) { + sb.append('L'); + sb.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1); + sb.append(';'); + } else { + switch (t & 0xF) { + case 1: + sb.append('I'); + break; + case 2: + sb.append('F'); + break; + case 3: + sb.append('D'); + break; + case 9: + sb.append('Z'); + break; + case 10: + sb.append('B'); + break; + case 11: + sb.append('C'); + break; + case 12: + sb.append('S'); + break; + default: + sb.append('J'); + } + } + stackMap.putByte(7).putShort(cw.newClass(sb.toString())); + } + } + } + + private void writeFrameType(final Object type) { + if (type instanceof String) { + stackMap.putByte(7).putShort(cw.newClass((String) type)); + } else if (type instanceof Integer) { + stackMap.putByte(((Integer) type).intValue()); + } else { + stackMap.putByte(8).putShort(((Label) type).position); + } + } + + // ------------------------------------------------------------------------ + // Utility methods: dump bytecode array + // ------------------------------------------------------------------------ + + /** + * Returns the size of the bytecode of this method. + * + * @return the size of the bytecode of this method. + */ + final int getSize() { + if (classReaderOffset != 0) { + return 6 + classReaderLength; + } + int size = 8; + if (code.length > 0) { + if (code.length > 65535) { + throw new RuntimeException("Method code too large!"); + } + cw.newUTF8("Code"); + size += 18 + code.length + 8 * handlerCount; + if (localVar != null) { + cw.newUTF8("LocalVariableTable"); + size += 8 + localVar.length; + } + if (localVarType != null) { + cw.newUTF8("LocalVariableTypeTable"); + size += 8 + localVarType.length; + } + if (lineNumber != null) { + cw.newUTF8("LineNumberTable"); + size += 8 + lineNumber.length; + } + if (stackMap != null) { + boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; + cw.newUTF8(zip ? "StackMapTable" : "StackMap"); + size += 8 + stackMap.length; + } + if (ClassReader.ANNOTATIONS && ctanns != null) { + cw.newUTF8("RuntimeVisibleTypeAnnotations"); + size += 8 + ctanns.getSize(); + } + if (ClassReader.ANNOTATIONS && ictanns != null) { + cw.newUTF8("RuntimeInvisibleTypeAnnotations"); + size += 8 + ictanns.getSize(); + } + if (cattrs != null) { + size += cattrs.getSize(cw, code.data, code.length, maxStack, + maxLocals); + } + } + if (exceptionCount > 0) { + cw.newUTF8("Exceptions"); + size += 8 + 2 * exceptionCount; + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + cw.newUTF8("Synthetic"); + size += 6; + } + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + cw.newUTF8("Deprecated"); + size += 6; + } + if (ClassReader.SIGNATURES && signature != null) { + cw.newUTF8("Signature"); + cw.newUTF8(signature); + size += 8; + } + if (methodParameters != null) { + cw.newUTF8("MethodParameters"); + size += 7 + methodParameters.length; + } + if (ClassReader.ANNOTATIONS && annd != null) { + cw.newUTF8("AnnotationDefault"); + size += 6 + annd.length; + } + if (ClassReader.ANNOTATIONS && anns != null) { + cw.newUTF8("RuntimeVisibleAnnotations"); + size += 8 + anns.getSize(); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + cw.newUTF8("RuntimeInvisibleAnnotations"); + size += 8 + ianns.getSize(); + } + if (ClassReader.ANNOTATIONS && tanns != null) { + cw.newUTF8("RuntimeVisibleTypeAnnotations"); + size += 8 + tanns.getSize(); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + cw.newUTF8("RuntimeInvisibleTypeAnnotations"); + size += 8 + itanns.getSize(); + } + if (ClassReader.ANNOTATIONS && panns != null) { + cw.newUTF8("RuntimeVisibleParameterAnnotations"); + size += 7 + 2 * (panns.length - synthetics); + for (int i = panns.length - 1; i >= synthetics; --i) { + size += panns[i] == null ? 0 : panns[i].getSize(); + } + } + if (ClassReader.ANNOTATIONS && ipanns != null) { + cw.newUTF8("RuntimeInvisibleParameterAnnotations"); + size += 7 + 2 * (ipanns.length - synthetics); + for (int i = ipanns.length - 1; i >= synthetics; --i) { + size += ipanns[i] == null ? 0 : ipanns[i].getSize(); + } + } + if (attrs != null) { + size += attrs.getSize(cw, null, 0, -1, -1); + } + return size; + } + + /** + * Puts the bytecode of this method in the given byte vector. + * + * @param out + * the byte vector into which the bytecode of this method must be + * copied. + */ + final void put(final ByteVector out) { + final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; + int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED + | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE + | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); + out.putShort(access & ~mask).putShort(name).putShort(desc); + if (classReaderOffset != 0) { + out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength); + return; + } + int attributeCount = 0; + if (code.length > 0) { + ++attributeCount; + } + if (exceptionCount > 0) { + ++attributeCount; + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + ++attributeCount; + } + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + ++attributeCount; + } + if (ClassReader.SIGNATURES && signature != null) { + ++attributeCount; + } + if (methodParameters != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && annd != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && anns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && ianns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && tanns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && itanns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && panns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && ipanns != null) { + ++attributeCount; + } + if (attrs != null) { + attributeCount += attrs.getCount(); + } + out.putShort(attributeCount); + if (code.length > 0) { + int size = 12 + code.length + 8 * handlerCount; + if (localVar != null) { + size += 8 + localVar.length; + } + if (localVarType != null) { + size += 8 + localVarType.length; + } + if (lineNumber != null) { + size += 8 + lineNumber.length; + } + if (stackMap != null) { + size += 8 + stackMap.length; + } + if (ClassReader.ANNOTATIONS && ctanns != null) { + size += 8 + ctanns.getSize(); + } + if (ClassReader.ANNOTATIONS && ictanns != null) { + size += 8 + ictanns.getSize(); + } + if (cattrs != null) { + size += cattrs.getSize(cw, code.data, code.length, maxStack, + maxLocals); + } + out.putShort(cw.newUTF8("Code")).putInt(size); + out.putShort(maxStack).putShort(maxLocals); + out.putInt(code.length).putByteArray(code.data, 0, code.length); + out.putShort(handlerCount); + if (handlerCount > 0) { + Handler h = firstHandler; + while (h != null) { + out.putShort(h.start.position).putShort(h.end.position) + .putShort(h.handler.position).putShort(h.type); + h = h.next; + } + } + attributeCount = 0; + if (localVar != null) { + ++attributeCount; + } + if (localVarType != null) { + ++attributeCount; + } + if (lineNumber != null) { + ++attributeCount; + } + if (stackMap != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && ctanns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && ictanns != null) { + ++attributeCount; + } + if (cattrs != null) { + attributeCount += cattrs.getCount(); + } + out.putShort(attributeCount); + if (localVar != null) { + out.putShort(cw.newUTF8("LocalVariableTable")); + out.putInt(localVar.length + 2).putShort(localVarCount); + out.putByteArray(localVar.data, 0, localVar.length); + } + if (localVarType != null) { + out.putShort(cw.newUTF8("LocalVariableTypeTable")); + out.putInt(localVarType.length + 2).putShort(localVarTypeCount); + out.putByteArray(localVarType.data, 0, localVarType.length); + } + if (lineNumber != null) { + out.putShort(cw.newUTF8("LineNumberTable")); + out.putInt(lineNumber.length + 2).putShort(lineNumberCount); + out.putByteArray(lineNumber.data, 0, lineNumber.length); + } + if (stackMap != null) { + boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; + out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap")); + out.putInt(stackMap.length + 2).putShort(frameCount); + out.putByteArray(stackMap.data, 0, stackMap.length); + } + if (ClassReader.ANNOTATIONS && ctanns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); + ctanns.put(out); + } + if (ClassReader.ANNOTATIONS && ictanns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); + ictanns.put(out); + } + if (cattrs != null) { + cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); + } + } + if (exceptionCount > 0) { + out.putShort(cw.newUTF8("Exceptions")).putInt( + 2 * exceptionCount + 2); + out.putShort(exceptionCount); + for (int i = 0; i < exceptionCount; ++i) { + out.putShort(exceptions[i]); + } + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if ((cw.version & 0xFFFF) < Opcodes.V1_5 + || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { + out.putShort(cw.newUTF8("Synthetic")).putInt(0); + } + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + out.putShort(cw.newUTF8("Deprecated")).putInt(0); + } + if (ClassReader.SIGNATURES && signature != null) { + out.putShort(cw.newUTF8("Signature")).putInt(2) + .putShort(cw.newUTF8(signature)); + } + if (methodParameters != null) { + out.putShort(cw.newUTF8("MethodParameters")); + out.putInt(methodParameters.length + 1).putByte( + methodParametersCount); + out.putByteArray(methodParameters.data, 0, methodParameters.length); + } + if (ClassReader.ANNOTATIONS && annd != null) { + out.putShort(cw.newUTF8("AnnotationDefault")); + out.putInt(annd.length); + out.putByteArray(annd.data, 0, annd.length); + } + if (ClassReader.ANNOTATIONS && anns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); + anns.put(out); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); + ianns.put(out); + } + if (ClassReader.ANNOTATIONS && tanns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); + tanns.put(out); + } + if (ClassReader.ANNOTATIONS && itanns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); + itanns.put(out); + } + if (ClassReader.ANNOTATIONS && panns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); + AnnotationWriter.put(panns, synthetics, out); + } + if (ClassReader.ANNOTATIONS && ipanns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); + AnnotationWriter.put(ipanns, synthetics, out); + } + if (attrs != null) { + attrs.put(cw, null, 0, -1, -1, out); + } + } + + // ------------------------------------------------------------------------ + // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W) + // ------------------------------------------------------------------------ + + /** + * Resizes and replaces the temporary instructions inserted by + * {@link Label#resolve} for wide forward jumps, while keeping jump offsets + * and instruction addresses consistent. This may require to resize other + * existing instructions, or even to introduce new instructions: for + * example, increasing the size of an instruction by 2 at the middle of a + * method can increases the offset of an IFEQ instruction from 32766 to + * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W + * 32765. This, in turn, may require to increase the size of another jump + * instruction, and so on... All these operations are handled automatically + * by this method. + *

+ * This method must be called after all the method that is being built + * has been visited. In particular, the {@link Label Label} objects used + * to construct the method are no longer valid after this method has been + * called. + */ + private void resizeInstructions() { + byte[] b = code.data; // bytecode of the method + int u, v, label; // indexes in b + int i, j; // loop indexes + /* + * 1st step: As explained above, resizing an instruction may require to + * resize another one, which may require to resize yet another one, and + * so on. The first step of the algorithm consists in finding all the + * instructions that need to be resized, without modifying the code. + * This is done by the following "fix point" algorithm: + * + * Parse the code to find the jump instructions whose offset will need + * more than 2 bytes to be stored (the future offset is computed from + * the current offset and from the number of bytes that will be inserted + * or removed between the source and target instructions). For each such + * instruction, adds an entry in (a copy of) the indexes and sizes + * arrays (if this has not already been done in a previous iteration!). + * + * If at least one entry has been added during the previous step, go + * back to the beginning, otherwise stop. + * + * In fact the real algorithm is complicated by the fact that the size + * of TABLESWITCH and LOOKUPSWITCH instructions depends on their + * position in the bytecode (because of padding). In order to ensure the + * convergence of the algorithm, the number of bytes to be added or + * removed from these instructions is over estimated during the previous + * loop, and computed exactly only after the loop is finished (this + * requires another pass to parse the bytecode of the method). + */ + int[] allIndexes = new int[0]; // copy of indexes + int[] allSizes = new int[0]; // copy of sizes + boolean[] resize; // instructions to be resized + int newOffset; // future offset of a jump instruction + + resize = new boolean[code.length]; + + // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done + int state = 3; + do { + if (state == 3) { + state = 2; + } + u = 0; + while (u < b.length) { + int opcode = b[u] & 0xFF; // opcode of current instruction + int insert = 0; // bytes to be added after this instruction + + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + case ClassWriter.IMPLVAR_INSN: + u += 1; + break; + case ClassWriter.LABEL_INSN: + if (opcode > 201) { + // converts temporary opcodes 202 to 217, 218 and + // 219 to IFEQ ... JSR (inclusive), IFNULL and + // IFNONNULL + opcode = opcode < 218 ? opcode - 49 : opcode - 20; + label = u + readUnsignedShort(b, u + 1); + } else { + label = u + readShort(b, u + 1); + } + newOffset = getNewOffset(allIndexes, allSizes, u, label); + if (newOffset < Short.MIN_VALUE + || newOffset > Short.MAX_VALUE) { + if (!resize[u]) { + if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { + // two additional bytes will be required to + // replace this GOTO or JSR instruction with + // a GOTO_W or a JSR_W + insert = 2; + } else { + // five additional bytes will be required to + // replace this IFxxx instruction with + // IFNOTxxx GOTO_W , where IFNOTxxx + // is the "opposite" opcode of IFxxx (i.e., + // IFNE for IFEQ) and where designates + // the instruction just after the GOTO_W. + insert = 5; + } + resize[u] = true; + } + } + u += 3; + break; + case ClassWriter.LABELW_INSN: + u += 5; + break; + case ClassWriter.TABL_INSN: + if (state == 1) { + // true number of bytes to be added (or removed) + // from this instruction = (future number of padding + // bytes - current number of padding byte) - + // previously over estimated variation = + // = ((3 - newOffset%4) - (3 - u%4)) - u%4 + // = (-newOffset%4 + u%4) - u%4 + // = -(newOffset & 3) + newOffset = getNewOffset(allIndexes, allSizes, 0, u); + insert = -(newOffset & 3); + } else if (!resize[u]) { + // over estimation of the number of bytes to be + // added to this instruction = 3 - current number + // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3 + insert = u & 3; + resize[u] = true; + } + // skips instruction + u = u + 4 - (u & 3); + u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; + break; + case ClassWriter.LOOK_INSN: + if (state == 1) { + // like TABL_INSN + newOffset = getNewOffset(allIndexes, allSizes, 0, u); + insert = -(newOffset & 3); + } else if (!resize[u]) { + // like TABL_INSN + insert = u & 3; + resize[u] = true; + } + // skips instruction + u = u + 4 - (u & 3); + u += 8 * readInt(b, u + 4) + 8; + break; + case ClassWriter.WIDE_INSN: + opcode = b[u + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + u += 6; + } else { + u += 4; + } + break; + case ClassWriter.VAR_INSN: + case ClassWriter.SBYTE_INSN: + case ClassWriter.LDC_INSN: + u += 2; + break; + case ClassWriter.SHORT_INSN: + case ClassWriter.LDCW_INSN: + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.TYPE_INSN: + case ClassWriter.IINC_INSN: + u += 3; + break; + case ClassWriter.ITFMETH_INSN: + case ClassWriter.INDYMETH_INSN: + u += 5; + break; + // case ClassWriter.MANA_INSN: + default: + u += 4; + break; + } + if (insert != 0) { + // adds a new (u, insert) entry in the allIndexes and + // allSizes arrays + int[] newIndexes = new int[allIndexes.length + 1]; + int[] newSizes = new int[allSizes.length + 1]; + System.arraycopy(allIndexes, 0, newIndexes, 0, + allIndexes.length); + System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); + newIndexes[allIndexes.length] = u; + newSizes[allSizes.length] = insert; + allIndexes = newIndexes; + allSizes = newSizes; + if (insert > 0) { + state = 3; + } + } + } + if (state < 3) { + --state; + } + } while (state != 0); + + // 2nd step: + // copies the bytecode of the method into a new bytevector, updates the + // offsets, and inserts (or removes) bytes as requested. + + ByteVector newCode = new ByteVector(code.length); + + u = 0; + while (u < code.length) { + int opcode = b[u] & 0xFF; + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + case ClassWriter.IMPLVAR_INSN: + newCode.putByte(opcode); + u += 1; + break; + case ClassWriter.LABEL_INSN: + if (opcode > 201) { + // changes temporary opcodes 202 to 217 (inclusive), 218 + // and 219 to IFEQ ... JSR (inclusive), IFNULL and + // IFNONNULL + opcode = opcode < 218 ? opcode - 49 : opcode - 20; + label = u + readUnsignedShort(b, u + 1); + } else { + label = u + readShort(b, u + 1); + } + newOffset = getNewOffset(allIndexes, allSizes, u, label); + if (resize[u]) { + // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx + // with IFNOTxxx GOTO_W , where IFNOTxxx is + // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) + // and where designates the instruction just after + // the GOTO_W. + if (opcode == Opcodes.GOTO) { + newCode.putByte(200); // GOTO_W + } else if (opcode == Opcodes.JSR) { + newCode.putByte(201); // JSR_W + } else { + newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 + : opcode ^ 1); + newCode.putShort(8); // jump offset + newCode.putByte(200); // GOTO_W + // newOffset now computed from start of GOTO_W + newOffset -= 3; + } + newCode.putInt(newOffset); + } else { + newCode.putByte(opcode); + newCode.putShort(newOffset); + } + u += 3; + break; + case ClassWriter.LABELW_INSN: + label = u + readInt(b, u + 1); + newOffset = getNewOffset(allIndexes, allSizes, u, label); + newCode.putByte(opcode); + newCode.putInt(newOffset); + u += 5; + break; + case ClassWriter.TABL_INSN: + // skips 0 to 3 padding bytes + v = u; + u = u + 4 - (v & 3); + // reads and copies instruction + newCode.putByte(Opcodes.TABLESWITCH); + newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + j = readInt(b, u); + u += 4; + newCode.putInt(j); + j = readInt(b, u) - j + 1; + u += 4; + newCode.putInt(readInt(b, u - 4)); + for (; j > 0; --j) { + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + } + break; + case ClassWriter.LOOK_INSN: + // skips 0 to 3 padding bytes + v = u; + u = u + 4 - (v & 3); + // reads and copies instruction + newCode.putByte(Opcodes.LOOKUPSWITCH); + newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + j = readInt(b, u); + u += 4; + newCode.putInt(j); + for (; j > 0; --j) { + newCode.putInt(readInt(b, u)); + u += 4; + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + } + break; + case ClassWriter.WIDE_INSN: + opcode = b[u + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + newCode.putByteArray(b, u, 6); + u += 6; + } else { + newCode.putByteArray(b, u, 4); + u += 4; + } + break; + case ClassWriter.VAR_INSN: + case ClassWriter.SBYTE_INSN: + case ClassWriter.LDC_INSN: + newCode.putByteArray(b, u, 2); + u += 2; + break; + case ClassWriter.SHORT_INSN: + case ClassWriter.LDCW_INSN: + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.TYPE_INSN: + case ClassWriter.IINC_INSN: + newCode.putByteArray(b, u, 3); + u += 3; + break; + case ClassWriter.ITFMETH_INSN: + case ClassWriter.INDYMETH_INSN: + newCode.putByteArray(b, u, 5); + u += 5; + break; + // case MANA_INSN: + default: + newCode.putByteArray(b, u, 4); + u += 4; + break; + } + } + + // updates the stack map frame labels + if (compute == FRAMES) { + Label l = labels; + while (l != null) { + /* + * Detects the labels that are just after an IF instruction that + * has been resized with the IFNOT GOTO_W pattern. These labels + * are now the target of a jump instruction (the IFNOT + * instruction). Note that we need the original label position + * here. getNewOffset must therefore never have been called for + * this label. + */ + u = l.position - 3; + if (u >= 0 && resize[u]) { + l.status |= Label.TARGET; + } + getNewOffset(allIndexes, allSizes, l); + l = l.successor; + } + // Update the offsets in the uninitialized types + if (cw.typeTable != null) { + for (i = 0; i < cw.typeTable.length; ++i) { + Item item = cw.typeTable[i]; + if (item != null && item.type == ClassWriter.TYPE_UNINIT) { + item.intVal = getNewOffset(allIndexes, allSizes, 0, + item.intVal); + } + } + } + // The stack map frames are not serialized yet, so we don't need + // to update them. They will be serialized in visitMaxs. + } else if (frameCount > 0) { + /* + * Resizing an existing stack map frame table is really hard. Not + * only the table must be parsed to update the offets, but new + * frames may be needed for jump instructions that were inserted by + * this method. And updating the offsets or inserting frames can + * change the format of the following frames, in case of packed + * frames. In practice the whole table must be recomputed. For this + * the frames are marked as potentially invalid. This will cause the + * whole class to be reread and rewritten with the COMPUTE_FRAMES + * option (see the ClassWriter.toByteArray method). This is not very + * efficient but is much easier and requires much less code than any + * other method I can think of. + */ + cw.invalidFrames = true; + } + // updates the exception handler block labels + Handler h = firstHandler; + while (h != null) { + getNewOffset(allIndexes, allSizes, h.start); + getNewOffset(allIndexes, allSizes, h.end); + getNewOffset(allIndexes, allSizes, h.handler); + h = h.next; + } + // updates the instructions addresses in the + // local var and line number tables + for (i = 0; i < 2; ++i) { + ByteVector bv = i == 0 ? localVar : localVarType; + if (bv != null) { + b = bv.data; + u = 0; + while (u < bv.length) { + label = readUnsignedShort(b, u); + newOffset = getNewOffset(allIndexes, allSizes, 0, label); + writeShort(b, u, newOffset); + label += readUnsignedShort(b, u + 2); + newOffset = getNewOffset(allIndexes, allSizes, 0, label) + - newOffset; + writeShort(b, u + 2, newOffset); + u += 10; + } + } + } + if (lineNumber != null) { + b = lineNumber.data; + u = 0; + while (u < lineNumber.length) { + writeShort( + b, + u, + getNewOffset(allIndexes, allSizes, 0, + readUnsignedShort(b, u))); + u += 4; + } + } + // updates the labels of the other attributes + Attribute attr = cattrs; + while (attr != null) { + Label[] labels = attr.getLabels(); + if (labels != null) { + for (i = labels.length - 1; i >= 0; --i) { + getNewOffset(allIndexes, allSizes, labels[i]); + } + } + attr = attr.next; + } + + // replaces old bytecodes with new ones + code = newCode; + } + + /** + * Reads an unsigned short value in the given byte array. + * + * @param b + * a byte array. + * @param index + * the start index of the value to be read. + * @return the read value. + */ + static int readUnsignedShort(final byte[] b, final int index) { + return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); + } + + /** + * Reads a signed short value in the given byte array. + * + * @param b + * a byte array. + * @param index + * the start index of the value to be read. + * @return the read value. + */ + static short readShort(final byte[] b, final int index) { + return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); + } + + /** + * Reads a signed int value in the given byte array. + * + * @param b + * a byte array. + * @param index + * the start index of the value to be read. + * @return the read value. + */ + static int readInt(final byte[] b, final int index) { + return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) + | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); + } + + /** + * Writes a short value in the given byte array. + * + * @param b + * a byte array. + * @param index + * where the first byte of the short value must be written. + * @param s + * the value to be written in the given byte array. + */ + static void writeShort(final byte[] b, final int index, final int s) { + b[index] = (byte) (s >>> 8); + b[index + 1] = (byte) s; + } + + /** + * Computes the future value of a bytecode offset. + *

+ * Note: it is possible to have several entries for the same instruction in + * the indexes and sizes: two entries (index=a,size=b) and + * (index=a,size=b') are equivalent to a single entry (index=a,size=b+b'). + * + * @param indexes + * current positions of the instructions to be resized. Each + * instruction must be designated by the index of its last + * byte, plus one (or, in other words, by the index of the + * first byte of the next instruction). + * @param sizes + * the number of bytes to be added to the above + * instructions. More precisely, for each i < len, + * sizes[i] bytes will be added at the end of the + * instruction designated by indexes[i] or, if + * sizes[i] is negative, the last | + * sizes[i]| bytes of the instruction will be removed + * (the instruction size must not become negative or + * null). + * @param begin + * index of the first byte of the source instruction. + * @param end + * index of the first byte of the target instruction. + * @return the future value of the given bytecode offset. + */ + static int getNewOffset(final int[] indexes, final int[] sizes, + final int begin, final int end) { + int offset = end - begin; + for (int i = 0; i < indexes.length; ++i) { + if (begin < indexes[i] && indexes[i] <= end) { + // forward jump + offset += sizes[i]; + } else if (end < indexes[i] && indexes[i] <= begin) { + // backward jump + offset -= sizes[i]; + } + } + return offset; + } + + /** + * Updates the offset of the given label. + * + * @param indexes + * current positions of the instructions to be resized. Each + * instruction must be designated by the index of its last + * byte, plus one (or, in other words, by the index of the + * first byte of the next instruction). + * @param sizes + * the number of bytes to be added to the above + * instructions. More precisely, for each i < len, + * sizes[i] bytes will be added at the end of the + * instruction designated by indexes[i] or, if + * sizes[i] is negative, the last | + * sizes[i]| bytes of the instruction will be removed + * (the instruction size must not become negative or + * null). + * @param label + * the label whose offset must be updated. + */ + static void getNewOffset(final int[] indexes, final int[] sizes, + final Label label) { + if ((label.status & Label.RESIZED) == 0) { + label.position = getNewOffset(indexes, sizes, 0, label.position); + label.status |= Label.RESIZED; + } + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/Opcodes.java b/blade-core/src/main/java/org/objectweb/asm/Opcodes.java new file mode 100644 index 000000000..e5c2b33fd --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/Opcodes.java @@ -0,0 +1,361 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +/** + * Defines the JVM opcodes, access flags and array type codes. This interface + * does not define all the JVM opcodes because some opcodes are automatically + * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced + * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n + * opcodes are therefore not defined in this interface. Likewise for LDC, + * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and + * JSR_W. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public interface Opcodes { + + // ASM API versions + + int ASM4 = 4 << 16 | 0 << 8 | 0; + int ASM5 = 5 << 16 | 0 << 8 | 0; + + // versions + + int V1_1 = 3 << 16 | 45; + int V1_2 = 0 << 16 | 46; + int V1_3 = 0 << 16 | 47; + int V1_4 = 0 << 16 | 48; + int V1_5 = 0 << 16 | 49; + int V1_6 = 0 << 16 | 50; + int V1_7 = 0 << 16 | 51; + int V1_8 = 0 << 16 | 52; + + // access flags + + int ACC_PUBLIC = 0x0001; // class, field, method + int ACC_PRIVATE = 0x0002; // class, field, method + int ACC_PROTECTED = 0x0004; // class, field, method + int ACC_STATIC = 0x0008; // field, method + int ACC_FINAL = 0x0010; // class, field, method, parameter + int ACC_SUPER = 0x0020; // class + int ACC_SYNCHRONIZED = 0x0020; // method + int ACC_VOLATILE = 0x0040; // field + int ACC_BRIDGE = 0x0040; // method + int ACC_VARARGS = 0x0080; // method + int ACC_TRANSIENT = 0x0080; // field + int ACC_NATIVE = 0x0100; // method + int ACC_INTERFACE = 0x0200; // class + int ACC_ABSTRACT = 0x0400; // class, method + int ACC_STRICT = 0x0800; // method + int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter + int ACC_ANNOTATION = 0x2000; // class + int ACC_ENUM = 0x4000; // class(?) field inner + int ACC_MANDATED = 0x8000; // parameter + + // ASM specific pseudo access flags + + int ACC_DEPRECATED = 0x20000; // class, field, method + + // types for NEWARRAY + + int T_BOOLEAN = 4; + int T_CHAR = 5; + int T_FLOAT = 6; + int T_DOUBLE = 7; + int T_BYTE = 8; + int T_SHORT = 9; + int T_INT = 10; + int T_LONG = 11; + + // tags for Handle + + int H_GETFIELD = 1; + int H_GETSTATIC = 2; + int H_PUTFIELD = 3; + int H_PUTSTATIC = 4; + int H_INVOKEVIRTUAL = 5; + int H_INVOKESTATIC = 6; + int H_INVOKESPECIAL = 7; + int H_NEWINVOKESPECIAL = 8; + int H_INVOKEINTERFACE = 9; + + // stack map frame types + + /** + * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}. + */ + int F_NEW = -1; + + /** + * Represents a compressed frame with complete frame data. + */ + int F_FULL = 0; + + /** + * Represents a compressed frame where locals are the same as the locals in + * the previous frame, except that additional 1-3 locals are defined, and + * with an empty stack. + */ + int F_APPEND = 1; + + /** + * Represents a compressed frame where locals are the same as the locals in + * the previous frame, except that the last 1-3 locals are absent and with + * an empty stack. + */ + int F_CHOP = 2; + + /** + * Represents a compressed frame with exactly the same locals as the + * previous frame and with an empty stack. + */ + int F_SAME = 3; + + /** + * Represents a compressed frame with exactly the same locals as the + * previous frame and with a single value on the stack. + */ + int F_SAME1 = 4; + + Integer TOP = new Integer(0); + Integer INTEGER = new Integer(1); + Integer FLOAT = new Integer(2); + Integer DOUBLE = new Integer(3); + Integer LONG = new Integer(4); + Integer NULL = new Integer(5); + Integer UNINITIALIZED_THIS = new Integer(6); + + // opcodes // visit method (- = idem) + + int NOP = 0; // visitInsn + int ACONST_NULL = 1; // - + int ICONST_M1 = 2; // - + int ICONST_0 = 3; // - + int ICONST_1 = 4; // - + int ICONST_2 = 5; // - + int ICONST_3 = 6; // - + int ICONST_4 = 7; // - + int ICONST_5 = 8; // - + int LCONST_0 = 9; // - + int LCONST_1 = 10; // - + int FCONST_0 = 11; // - + int FCONST_1 = 12; // - + int FCONST_2 = 13; // - + int DCONST_0 = 14; // - + int DCONST_1 = 15; // - + int BIPUSH = 16; // visitIntInsn + int SIPUSH = 17; // - + int LDC = 18; // visitLdcInsn + // int LDC_W = 19; // - + // int LDC2_W = 20; // - + int ILOAD = 21; // visitVarInsn + int LLOAD = 22; // - + int FLOAD = 23; // - + int DLOAD = 24; // - + int ALOAD = 25; // - + // int ILOAD_0 = 26; // - + // int ILOAD_1 = 27; // - + // int ILOAD_2 = 28; // - + // int ILOAD_3 = 29; // - + // int LLOAD_0 = 30; // - + // int LLOAD_1 = 31; // - + // int LLOAD_2 = 32; // - + // int LLOAD_3 = 33; // - + // int FLOAD_0 = 34; // - + // int FLOAD_1 = 35; // - + // int FLOAD_2 = 36; // - + // int FLOAD_3 = 37; // - + // int DLOAD_0 = 38; // - + // int DLOAD_1 = 39; // - + // int DLOAD_2 = 40; // - + // int DLOAD_3 = 41; // - + // int ALOAD_0 = 42; // - + // int ALOAD_1 = 43; // - + // int ALOAD_2 = 44; // - + // int ALOAD_3 = 45; // - + int IALOAD = 46; // visitInsn + int LALOAD = 47; // - + int FALOAD = 48; // - + int DALOAD = 49; // - + int AALOAD = 50; // - + int BALOAD = 51; // - + int CALOAD = 52; // - + int SALOAD = 53; // - + int ISTORE = 54; // visitVarInsn + int LSTORE = 55; // - + int FSTORE = 56; // - + int DSTORE = 57; // - + int ASTORE = 58; // - + // int ISTORE_0 = 59; // - + // int ISTORE_1 = 60; // - + // int ISTORE_2 = 61; // - + // int ISTORE_3 = 62; // - + // int LSTORE_0 = 63; // - + // int LSTORE_1 = 64; // - + // int LSTORE_2 = 65; // - + // int LSTORE_3 = 66; // - + // int FSTORE_0 = 67; // - + // int FSTORE_1 = 68; // - + // int FSTORE_2 = 69; // - + // int FSTORE_3 = 70; // - + // int DSTORE_0 = 71; // - + // int DSTORE_1 = 72; // - + // int DSTORE_2 = 73; // - + // int DSTORE_3 = 74; // - + // int ASTORE_0 = 75; // - + // int ASTORE_1 = 76; // - + // int ASTORE_2 = 77; // - + // int ASTORE_3 = 78; // - + int IASTORE = 79; // visitInsn + int LASTORE = 80; // - + int FASTORE = 81; // - + int DASTORE = 82; // - + int AASTORE = 83; // - + int BASTORE = 84; // - + int CASTORE = 85; // - + int SASTORE = 86; // - + int POP = 87; // - + int POP2 = 88; // - + int DUP = 89; // - + int DUP_X1 = 90; // - + int DUP_X2 = 91; // - + int DUP2 = 92; // - + int DUP2_X1 = 93; // - + int DUP2_X2 = 94; // - + int SWAP = 95; // - + int IADD = 96; // - + int LADD = 97; // - + int FADD = 98; // - + int DADD = 99; // - + int ISUB = 100; // - + int LSUB = 101; // - + int FSUB = 102; // - + int DSUB = 103; // - + int IMUL = 104; // - + int LMUL = 105; // - + int FMUL = 106; // - + int DMUL = 107; // - + int IDIV = 108; // - + int LDIV = 109; // - + int FDIV = 110; // - + int DDIV = 111; // - + int IREM = 112; // - + int LREM = 113; // - + int FREM = 114; // - + int DREM = 115; // - + int INEG = 116; // - + int LNEG = 117; // - + int FNEG = 118; // - + int DNEG = 119; // - + int ISHL = 120; // - + int LSHL = 121; // - + int ISHR = 122; // - + int LSHR = 123; // - + int IUSHR = 124; // - + int LUSHR = 125; // - + int IAND = 126; // - + int LAND = 127; // - + int IOR = 128; // - + int LOR = 129; // - + int IXOR = 130; // - + int LXOR = 131; // - + int IINC = 132; // visitIincInsn + int I2L = 133; // visitInsn + int I2F = 134; // - + int I2D = 135; // - + int L2I = 136; // - + int L2F = 137; // - + int L2D = 138; // - + int F2I = 139; // - + int F2L = 140; // - + int F2D = 141; // - + int D2I = 142; // - + int D2L = 143; // - + int D2F = 144; // - + int I2B = 145; // - + int I2C = 146; // - + int I2S = 147; // - + int LCMP = 148; // - + int FCMPL = 149; // - + int FCMPG = 150; // - + int DCMPL = 151; // - + int DCMPG = 152; // - + int IFEQ = 153; // visitJumpInsn + int IFNE = 154; // - + int IFLT = 155; // - + int IFGE = 156; // - + int IFGT = 157; // - + int IFLE = 158; // - + int IF_ICMPEQ = 159; // - + int IF_ICMPNE = 160; // - + int IF_ICMPLT = 161; // - + int IF_ICMPGE = 162; // - + int IF_ICMPGT = 163; // - + int IF_ICMPLE = 164; // - + int IF_ACMPEQ = 165; // - + int IF_ACMPNE = 166; // - + int GOTO = 167; // - + int JSR = 168; // - + int RET = 169; // visitVarInsn + int TABLESWITCH = 170; // visiTableSwitchInsn + int LOOKUPSWITCH = 171; // visitLookupSwitch + int IRETURN = 172; // visitInsn + int LRETURN = 173; // - + int FRETURN = 174; // - + int DRETURN = 175; // - + int ARETURN = 176; // - + int RETURN = 177; // - + int GETSTATIC = 178; // visitFieldInsn + int PUTSTATIC = 179; // - + int GETFIELD = 180; // - + int PUTFIELD = 181; // - + int INVOKEVIRTUAL = 182; // visitMethodInsn + int INVOKESPECIAL = 183; // - + int INVOKESTATIC = 184; // - + int INVOKEINTERFACE = 185; // - + int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn + int NEW = 187; // visitTypeInsn + int NEWARRAY = 188; // visitIntInsn + int ANEWARRAY = 189; // visitTypeInsn + int ARRAYLENGTH = 190; // visitInsn + int ATHROW = 191; // - + int CHECKCAST = 192; // visitTypeInsn + int INSTANCEOF = 193; // - + int MONITORENTER = 194; // visitInsn + int MONITOREXIT = 195; // - + // int WIDE = 196; // NOT VISITED + int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn + int IFNULL = 198; // visitJumpInsn + int IFNONNULL = 199; // - + // int GOTO_W = 200; // - + // int JSR_W = 201; // - +} diff --git a/blade-core/src/main/java/org/objectweb/asm/Type.java b/blade-core/src/main/java/org/objectweb/asm/Type.java new file mode 100644 index 000000000..6561fea3f --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/Type.java @@ -0,0 +1,896 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package org.objectweb.asm; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * A Java field or method type. This class can be used to make it easier to + * manipulate type and method descriptors. + * + * @author Eric Bruneton + * @author Chris Nokleberg + */ +public class Type { + + /** + * The sort of the void type. See {@link #getSort getSort}. + */ + public static final int VOID = 0; + + /** + * The sort of the boolean type. See {@link #getSort getSort}. + */ + public static final int BOOLEAN = 1; + + /** + * The sort of the char type. See {@link #getSort getSort}. + */ + public static final int CHAR = 2; + + /** + * The sort of the byte type. See {@link #getSort getSort}. + */ + public static final int BYTE = 3; + + /** + * The sort of the short type. See {@link #getSort getSort}. + */ + public static final int SHORT = 4; + + /** + * The sort of the int type. See {@link #getSort getSort}. + */ + public static final int INT = 5; + + /** + * The sort of the float type. See {@link #getSort getSort}. + */ + public static final int FLOAT = 6; + + /** + * The sort of the long type. See {@link #getSort getSort}. + */ + public static final int LONG = 7; + + /** + * The sort of the double type. See {@link #getSort getSort}. + */ + public static final int DOUBLE = 8; + + /** + * The sort of array reference types. See {@link #getSort getSort}. + */ + public static final int ARRAY = 9; + + /** + * The sort of object reference types. See {@link #getSort getSort}. + */ + public static final int OBJECT = 10; + + /** + * The sort of method types. See {@link #getSort getSort}. + */ + public static final int METHOD = 11; + + /** + * The void type. + */ + public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24) + | (5 << 16) | (0 << 8) | 0, 1); + + /** + * The boolean type. + */ + public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24) + | (0 << 16) | (5 << 8) | 1, 1); + + /** + * The char type. + */ + public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24) + | (0 << 16) | (6 << 8) | 1, 1); + + /** + * The byte type. + */ + public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24) + | (0 << 16) | (5 << 8) | 1, 1); + + /** + * The short type. + */ + public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24) + | (0 << 16) | (7 << 8) | 1, 1); + + /** + * The int type. + */ + public static final Type INT_TYPE = new Type(INT, null, ('I' << 24) + | (0 << 16) | (0 << 8) | 1, 1); + + /** + * The float type. + */ + public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24) + | (2 << 16) | (2 << 8) | 1, 1); + + /** + * The long type. + */ + public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24) + | (1 << 16) | (1 << 8) | 2, 1); + + /** + * The double type. + */ + public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24) + | (3 << 16) | (3 << 8) | 2, 1); + + // ------------------------------------------------------------------------ + // Fields + // ------------------------------------------------------------------------ + + /** + * The sort of this Java type. + */ + private final int sort; + + /** + * A buffer containing the internal name of this Java type. This field is + * only used for reference types. + */ + private final char[] buf; + + /** + * The offset of the internal name of this Java type in {@link #buf buf} or, + * for primitive types, the size, descriptor and getOpcode offsets for this + * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset + * for IALOAD or IASTORE, byte 3 the offset for all other instructions). + */ + private final int off; + + /** + * The length of the internal name of this Java type. + */ + private final int len; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Constructs a reference type. + * + * @param sort + * the sort of the reference type to be constructed. + * @param buf + * a buffer containing the descriptor of the previous type. + * @param off + * the offset of this descriptor in the previous buffer. + * @param len + * the length of this descriptor. + */ + private Type(final int sort, final char[] buf, final int off, final int len) { + this.sort = sort; + this.buf = buf; + this.off = off; + this.len = len; + } + + /** + * Returns the Java type corresponding to the given type descriptor. + * + * @param typeDescriptor + * a field or method type descriptor. + * @return the Java type corresponding to the given type descriptor. + */ + public static Type getType(final String typeDescriptor) { + return getType(typeDescriptor.toCharArray(), 0); + } + + /** + * Returns the Java type corresponding to the given internal name. + * + * @param internalName + * an internal name. + * @return the Java type corresponding to the given internal name. + */ + public static Type getObjectType(final String internalName) { + char[] buf = internalName.toCharArray(); + return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length); + } + + /** + * Returns the Java type corresponding to the given method descriptor. + * Equivalent to Type.getType(methodDescriptor). + * + * @param methodDescriptor + * a method descriptor. + * @return the Java type corresponding to the given method descriptor. + */ + public static Type getMethodType(final String methodDescriptor) { + return getType(methodDescriptor.toCharArray(), 0); + } + + /** + * Returns the Java method type corresponding to the given argument and + * return types. + * + * @param returnType + * the return type of the method. + * @param argumentTypes + * the argument types of the method. + * @return the Java type corresponding to the given argument and return + * types. + */ + public static Type getMethodType(final Type returnType, + final Type... argumentTypes) { + return getType(getMethodDescriptor(returnType, argumentTypes)); + } + + /** + * Returns the Java type corresponding to the given class. + * + * @param c + * a class. + * @return the Java type corresponding to the given class. + */ + public static Type getType(final Class c) { + if (c.isPrimitive()) { + if (c == Integer.TYPE) { + return INT_TYPE; + } else if (c == Void.TYPE) { + return VOID_TYPE; + } else if (c == Boolean.TYPE) { + return BOOLEAN_TYPE; + } else if (c == Byte.TYPE) { + return BYTE_TYPE; + } else if (c == Character.TYPE) { + return CHAR_TYPE; + } else if (c == Short.TYPE) { + return SHORT_TYPE; + } else if (c == Double.TYPE) { + return DOUBLE_TYPE; + } else if (c == Float.TYPE) { + return FLOAT_TYPE; + } else /* if (c == Long.TYPE) */{ + return LONG_TYPE; + } + } else { + return getType(getDescriptor(c)); + } + } + + /** + * Returns the Java method type corresponding to the given constructor. + * + * @param c + * a {@link Constructor Constructor} object. + * @return the Java method type corresponding to the given constructor. + */ + public static Type getType(final Constructor c) { + return getType(getConstructorDescriptor(c)); + } + + /** + * Returns the Java method type corresponding to the given method. + * + * @param m + * a {@link Method Method} object. + * @return the Java method type corresponding to the given method. + */ + public static Type getType(final Method m) { + return getType(getMethodDescriptor(m)); + } + + /** + * Returns the Java types corresponding to the argument types of the given + * method descriptor. + * + * @param methodDescriptor + * a method descriptor. + * @return the Java types corresponding to the argument types of the given + * method descriptor. + */ + public static Type[] getArgumentTypes(final String methodDescriptor) { + char[] buf = methodDescriptor.toCharArray(); + int off = 1; + int size = 0; + while (true) { + char car = buf[off++]; + if (car == ')') { + break; + } else if (car == 'L') { + while (buf[off++] != ';') { + } + ++size; + } else if (car != '[') { + ++size; + } + } + Type[] args = new Type[size]; + off = 1; + size = 0; + while (buf[off] != ')') { + args[size] = getType(buf, off); + off += args[size].len + (args[size].sort == OBJECT ? 2 : 0); + size += 1; + } + return args; + } + + /** + * Returns the Java types corresponding to the argument types of the given + * method. + * + * @param method + * a method. + * @return the Java types corresponding to the argument types of the given + * method. + */ + public static Type[] getArgumentTypes(final Method method) { + Class[] classes = method.getParameterTypes(); + Type[] types = new Type[classes.length]; + for (int i = classes.length - 1; i >= 0; --i) { + types[i] = getType(classes[i]); + } + return types; + } + + /** + * Returns the Java type corresponding to the return type of the given + * method descriptor. + * + * @param methodDescriptor + * a method descriptor. + * @return the Java type corresponding to the return type of the given + * method descriptor. + */ + public static Type getReturnType(final String methodDescriptor) { + char[] buf = methodDescriptor.toCharArray(); + return getType(buf, methodDescriptor.indexOf(')') + 1); + } + + /** + * Returns the Java type corresponding to the return type of the given + * method. + * + * @param method + * a method. + * @return the Java type corresponding to the return type of the given + * method. + */ + public static Type getReturnType(final Method method) { + return getType(method.getReturnType()); + } + + /** + * Computes the size of the arguments and of the return value of a method. + * + * @param desc + * the descriptor of a method. + * @return the size of the arguments of the method (plus one for the + * implicit this argument), argSize, and the size of its return + * value, retSize, packed into a single int i = + * (argSize << 2) | retSize (argSize is therefore equal to + * i >> 2, and retSize to i & 0x03). + */ + public static int getArgumentsAndReturnSizes(final String desc) { + int n = 1; + int c = 1; + while (true) { + char car = desc.charAt(c++); + if (car == ')') { + car = desc.charAt(c); + return n << 2 + | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); + } else if (car == 'L') { + while (desc.charAt(c++) != ';') { + } + n += 1; + } else if (car == '[') { + while ((car = desc.charAt(c)) == '[') { + ++c; + } + if (car == 'D' || car == 'J') { + n -= 1; + } + } else if (car == 'D' || car == 'J') { + n += 2; + } else { + n += 1; + } + } + } + + /** + * Returns the Java type corresponding to the given type descriptor. For + * method descriptors, buf is supposed to contain nothing more than the + * descriptor itself. + * + * @param buf + * a buffer containing a type descriptor. + * @param off + * the offset of this descriptor in the previous buffer. + * @return the Java type corresponding to the given type descriptor. + */ + private static Type getType(final char[] buf, final int off) { + int len; + switch (buf[off]) { + case 'V': + return VOID_TYPE; + case 'Z': + return BOOLEAN_TYPE; + case 'C': + return CHAR_TYPE; + case 'B': + return BYTE_TYPE; + case 'S': + return SHORT_TYPE; + case 'I': + return INT_TYPE; + case 'F': + return FLOAT_TYPE; + case 'J': + return LONG_TYPE; + case 'D': + return DOUBLE_TYPE; + case '[': + len = 1; + while (buf[off + len] == '[') { + ++len; + } + if (buf[off + len] == 'L') { + ++len; + while (buf[off + len] != ';') { + ++len; + } + } + return new Type(ARRAY, buf, off, len + 1); + case 'L': + len = 1; + while (buf[off + len] != ';') { + ++len; + } + return new Type(OBJECT, buf, off + 1, len - 1); + // case '(': + default: + return new Type(METHOD, buf, off, buf.length - off); + } + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * Returns the sort of this Java type. + * + * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, + * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, + * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, + * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD + * METHOD}. + */ + public int getSort() { + return sort; + } + + /** + * Returns the number of dimensions of this array type. This method should + * only be used for an array type. + * + * @return the number of dimensions of this array type. + */ + public int getDimensions() { + int i = 1; + while (buf[off + i] == '[') { + ++i; + } + return i; + } + + /** + * Returns the type of the elements of this array type. This method should + * only be used for an array type. + * + * @return Returns the type of the elements of this array type. + */ + public Type getElementType() { + return getType(buf, off + getDimensions()); + } + + /** + * Returns the binary name of the class corresponding to this type. This + * method must not be used on method types. + * + * @return the binary name of the class corresponding to this type. + */ + public String getClassName() { + switch (sort) { + case VOID: + return "void"; + case BOOLEAN: + return "boolean"; + case CHAR: + return "char"; + case BYTE: + return "byte"; + case SHORT: + return "short"; + case INT: + return "int"; + case FLOAT: + return "float"; + case LONG: + return "long"; + case DOUBLE: + return "double"; + case ARRAY: + StringBuilder sb = new StringBuilder(getElementType().getClassName()); + for (int i = getDimensions(); i > 0; --i) { + sb.append("[]"); + } + return sb.toString(); + case OBJECT: + return new String(buf, off, len).replace('/', '.'); + default: + return null; + } + } + + /** + * Returns the internal name of the class corresponding to this object or + * array type. The internal name of a class is its fully qualified name (as + * returned by Class.getName(), where '.' are replaced by '/'. This method + * should only be used for an object or array type. + * + * @return the internal name of the class corresponding to this object type. + */ + public String getInternalName() { + return new String(buf, off, len); + } + + /** + * Returns the argument types of methods of this type. This method should + * only be used for method types. + * + * @return the argument types of methods of this type. + */ + public Type[] getArgumentTypes() { + return getArgumentTypes(getDescriptor()); + } + + /** + * Returns the return type of methods of this type. This method should only + * be used for method types. + * + * @return the return type of methods of this type. + */ + public Type getReturnType() { + return getReturnType(getDescriptor()); + } + + /** + * Returns the size of the arguments and of the return value of methods of + * this type. This method should only be used for method types. + * + * @return the size of the arguments (plus one for the implicit this + * argument), argSize, and the size of the return value, retSize, + * packed into a single + * int i = (argSize << 2) | retSize + * (argSize is therefore equal to i >> 2, + * and retSize to i & 0x03). + */ + public int getArgumentsAndReturnSizes() { + return getArgumentsAndReturnSizes(getDescriptor()); + } + + // ------------------------------------------------------------------------ + // Conversion to type descriptors + // ------------------------------------------------------------------------ + + /** + * Returns the descriptor corresponding to this Java type. + * + * @return the descriptor corresponding to this Java type. + */ + public String getDescriptor() { + StringBuilder buf = new StringBuilder(); + getDescriptor(buf); + return buf.toString(); + } + + /** + * Returns the descriptor corresponding to the given argument and return + * types. + * + * @param returnType + * the return type of the method. + * @param argumentTypes + * the argument types of the method. + * @return the descriptor corresponding to the given argument and return + * types. + */ + public static String getMethodDescriptor(final Type returnType, + final Type... argumentTypes) { + StringBuilder buf = new StringBuilder(); + buf.append('('); + for (int i = 0; i < argumentTypes.length; ++i) { + argumentTypes[i].getDescriptor(buf); + } + buf.append(')'); + returnType.getDescriptor(buf); + return buf.toString(); + } + + /** + * Appends the descriptor corresponding to this Java type to the given + * string buffer. + * + * @param buf + * the string buffer to which the descriptor must be appended. + */ + private void getDescriptor(final StringBuilder buf) { + if (this.buf == null) { + // descriptor is in byte 3 of 'off' for primitive types (buf == + // null) + buf.append((char) ((off & 0xFF000000) >>> 24)); + } else if (sort == OBJECT) { + buf.append('L'); + buf.append(this.buf, off, len); + buf.append(';'); + } else { // sort == ARRAY || sort == METHOD + buf.append(this.buf, off, len); + } + } + + // ------------------------------------------------------------------------ + // Direct conversion from classes to type descriptors, + // without intermediate Type objects + // ------------------------------------------------------------------------ + + /** + * Returns the internal name of the given class. The internal name of a + * class is its fully qualified name, as returned by Class.getName(), where + * '.' are replaced by '/'. + * + * @param c + * an object or array class. + * @return the internal name of the given class. + */ + public static String getInternalName(final Class c) { + return c.getName().replace('.', '/'); + } + + /** + * Returns the descriptor corresponding to the given Java type. + * + * @param c + * an object class, a primitive class or an array class. + * @return the descriptor corresponding to the given class. + */ + public static String getDescriptor(final Class c) { + StringBuilder buf = new StringBuilder(); + getDescriptor(buf, c); + return buf.toString(); + } + + /** + * Returns the descriptor corresponding to the given constructor. + * + * @param c + * a {@link Constructor Constructor} object. + * @return the descriptor of the given constructor. + */ + public static String getConstructorDescriptor(final Constructor c) { + Class[] parameters = c.getParameterTypes(); + StringBuilder buf = new StringBuilder(); + buf.append('('); + for (int i = 0; i < parameters.length; ++i) { + getDescriptor(buf, parameters[i]); + } + return buf.append(")V").toString(); + } + + /** + * Returns the descriptor corresponding to the given method. + * + * @param m + * a {@link Method Method} object. + * @return the descriptor of the given method. + */ + public static String getMethodDescriptor(final Method m) { + Class[] parameters = m.getParameterTypes(); + StringBuilder buf = new StringBuilder(); + buf.append('('); + for (int i = 0; i < parameters.length; ++i) { + getDescriptor(buf, parameters[i]); + } + buf.append(')'); + getDescriptor(buf, m.getReturnType()); + return buf.toString(); + } + + /** + * Appends the descriptor of the given class to the given string buffer. + * + * @param buf + * the string buffer to which the descriptor must be appended. + * @param c + * the class whose descriptor must be computed. + */ + private static void getDescriptor(final StringBuilder buf, final Class c) { + Class d = c; + while (true) { + if (d.isPrimitive()) { + char car; + if (d == Integer.TYPE) { + car = 'I'; + } else if (d == Void.TYPE) { + car = 'V'; + } else if (d == Boolean.TYPE) { + car = 'Z'; + } else if (d == Byte.TYPE) { + car = 'B'; + } else if (d == Character.TYPE) { + car = 'C'; + } else if (d == Short.TYPE) { + car = 'S'; + } else if (d == Double.TYPE) { + car = 'D'; + } else if (d == Float.TYPE) { + car = 'F'; + } else /* if (d == Long.TYPE) */{ + car = 'J'; + } + buf.append(car); + return; + } else if (d.isArray()) { + buf.append('['); + d = d.getComponentType(); + } else { + buf.append('L'); + String name = d.getName(); + int len = name.length(); + for (int i = 0; i < len; ++i) { + char car = name.charAt(i); + buf.append(car == '.' ? '/' : car); + } + buf.append(';'); + return; + } + } + } + + // ------------------------------------------------------------------------ + // Corresponding size and opcodes + // ------------------------------------------------------------------------ + + /** + * Returns the size of values of this type. This method must not be used for + * method types. + * + * @return the size of values of this type, i.e., 2 for long and + * double, 0 for void and 1 otherwise. + */ + public int getSize() { + // the size is in byte 0 of 'off' for primitive types (buf == null) + return buf == null ? (off & 0xFF) : 1; + } + + /** + * Returns a JVM instruction opcode adapted to this Java type. This method + * must not be used for method types. + * + * @param opcode + * a JVM instruction opcode. This opcode must be one of ILOAD, + * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, + * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. + * @return an opcode that is similar to the given opcode, but adapted to + * this Java type. For example, if this type is float and + * opcode is IRETURN, this method returns FRETURN. + */ + public int getOpcode(final int opcode) { + if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { + // the offset for IALOAD or IASTORE is in byte 1 of 'off' for + // primitive types (buf == null) + return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4); + } else { + // the offset for other instructions is in byte 2 of 'off' for + // primitive types (buf == null) + return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4); + } + } + + // ------------------------------------------------------------------------ + // Equals, hashCode and toString + // ------------------------------------------------------------------------ + + /** + * Tests if the given object is equal to this type. + * + * @param o + * the object to be compared to this type. + * @return true if the given object is equal to this type. + */ + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Type)) { + return false; + } + Type t = (Type) o; + if (sort != t.sort) { + return false; + } + if (sort >= ARRAY) { + if (len != t.len) { + return false; + } + for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { + if (buf[i] != t.buf[j]) { + return false; + } + } + } + return true; + } + + /** + * Returns a hash code value for this type. + * + * @return a hash code value for this type. + */ + @Override + public int hashCode() { + int hc = 13 * sort; + if (sort >= ARRAY) { + for (int i = off, end = i + len; i < end; i++) { + hc = 17 * (hc + buf[i]); + } + } + return hc; + } + + /** + * Returns a string representation of this type. + * + * @return the descriptor of this type. + */ + @Override + public String toString() { + return getDescriptor(); + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/TypePath.java b/blade-core/src/main/java/org/objectweb/asm/TypePath.java new file mode 100644 index 000000000..d9c99b106 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/TypePath.java @@ -0,0 +1,196 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2013 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ + +package org.objectweb.asm; + +/** + * The path to a type argument, wildcard bound, array element type, or static + * inner type within an enclosing type. + * + * @author Eric Bruneton + */ +public class TypePath { + + /** + * A type path step that steps into the element type of an array type. See + * {@link #getStep getStep}. + */ + public final static int ARRAY_ELEMENT = 0; + + /** + * A type path step that steps into the nested type of a class type. See + * {@link #getStep getStep}. + */ + public final static int INNER_TYPE = 1; + + /** + * A type path step that steps into the bound of a wildcard type. See + * {@link #getStep getStep}. + */ + public final static int WILDCARD_BOUND = 2; + + /** + * A type path step that steps into a type argument of a generic type. See + * {@link #getStep getStep}. + */ + public final static int TYPE_ARGUMENT = 3; + + /** + * The byte array where the path is stored, in Java class file format. + */ + byte[] b; + + /** + * The offset of the first byte of the type path in 'b'. + */ + int offset; + + /** + * Creates a new type path. + * + * @param b + * the byte array containing the type path in Java class file + * format. + * @param offset + * the offset of the first byte of the type path in 'b'. + */ + TypePath(byte[] b, int offset) { + this.b = b; + this.offset = offset; + } + + /** + * Returns the length of this path. + * + * @return the length of this path. + */ + public int getLength() { + return b[offset]; + } + + /** + * Returns the value of the given step of this path. + * + * @param index + * an index between 0 and {@link #getLength()}, exclusive. + * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE + * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or + * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. + */ + public int getStep(int index) { + return b[offset + 2 * index + 1]; + } + + /** + * Returns the index of the type argument that the given step is stepping + * into. This method should only be used for steps whose value is + * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. + * + * @param index + * an index between 0 and {@link #getLength()}, exclusive. + * @return the index of the type argument that the given step is stepping + * into. + */ + public int getStepArgument(int index) { + return b[offset + 2 * index + 2]; + } + + /** + * Converts a type path in string form, in the format used by + * {@link #toString()}, into a TypePath object. + * + * @param typePath + * a type path in string form, in the format used by + * {@link #toString()}. May be null or empty. + * @return the corresponding TypePath object, or null if the path is empty. + */ + public static TypePath fromString(final String typePath) { + if (typePath == null || typePath.length() == 0) { + return null; + } + int n = typePath.length(); + ByteVector out = new ByteVector(n); + out.putByte(0); + for (int i = 0; i < n;) { + char c = typePath.charAt(i++); + if (c == '[') { + out.put11(ARRAY_ELEMENT, 0); + } else if (c == '.') { + out.put11(INNER_TYPE, 0); + } else if (c == '*') { + out.put11(WILDCARD_BOUND, 0); + } else if (c >= '0' && c <= '9') { + int typeArg = c - '0'; + while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') { + typeArg = typeArg * 10 + c - '0'; + i += 1; + } + if (i < n && typePath.charAt(i) == ';') { + i += 1; + } + out.put11(TYPE_ARGUMENT, typeArg); + } + } + out.data[0] = (byte) (out.length / 2); + return new TypePath(out.data, 0); + } + + /** + * Returns a string representation of this type path. {@link #ARRAY_ELEMENT + * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE + * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps + * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type + * argument index in decimal form followed by ';'. + */ + @Override + public String toString() { + int length = getLength(); + StringBuilder result = new StringBuilder(length * 2); + for (int i = 0; i < length; ++i) { + switch (getStep(i)) { + case ARRAY_ELEMENT: + result.append('['); + break; + case INNER_TYPE: + result.append('.'); + break; + case WILDCARD_BOUND: + result.append('*'); + break; + case TYPE_ARGUMENT: + result.append(getStepArgument(i)).append(';'); + break; + default: + result.append('_'); + } + } + return result.toString(); + } +} diff --git a/blade-core/src/main/java/org/objectweb/asm/TypeReference.java b/blade-core/src/main/java/org/objectweb/asm/TypeReference.java new file mode 100644 index 000000000..dff76c0b3 --- /dev/null +++ b/blade-core/src/main/java/org/objectweb/asm/TypeReference.java @@ -0,0 +1,452 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2013 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ + +package org.objectweb.asm; + +/** + * A reference to a type appearing in a class, field or method declaration, or + * on an instruction. Such a reference designates the part of the class where + * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws' + * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable + * declaration, etc). + * + * @author Eric Bruneton + */ +public class TypeReference { + + /** + * The sort of type references that target a type parameter of a generic + * class. See {@link #getSort getSort}. + */ + public final static int CLASS_TYPE_PARAMETER = 0x00; + + /** + * The sort of type references that target a type parameter of a generic + * method. See {@link #getSort getSort}. + */ + public final static int METHOD_TYPE_PARAMETER = 0x01; + + /** + * The sort of type references that target the super class of a class or one + * of the interfaces it implements. See {@link #getSort getSort}. + */ + public final static int CLASS_EXTENDS = 0x10; + + /** + * The sort of type references that target a bound of a type parameter of a + * generic class. See {@link #getSort getSort}. + */ + public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11; + + /** + * The sort of type references that target a bound of a type parameter of a + * generic method. See {@link #getSort getSort}. + */ + public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12; + + /** + * The sort of type references that target the type of a field. See + * {@link #getSort getSort}. + */ + public final static int FIELD = 0x13; + + /** + * The sort of type references that target the return type of a method. See + * {@link #getSort getSort}. + */ + public final static int METHOD_RETURN = 0x14; + + /** + * The sort of type references that target the receiver type of a method. + * See {@link #getSort getSort}. + */ + public final static int METHOD_RECEIVER = 0x15; + + /** + * The sort of type references that target the type of a formal parameter of + * a method. See {@link #getSort getSort}. + */ + public final static int METHOD_FORMAL_PARAMETER = 0x16; + + /** + * The sort of type references that target the type of an exception declared + * in the throws clause of a method. See {@link #getSort getSort}. + */ + public final static int THROWS = 0x17; + + /** + * The sort of type references that target the type of a local variable in a + * method. See {@link #getSort getSort}. + */ + public final static int LOCAL_VARIABLE = 0x40; + + /** + * The sort of type references that target the type of a resource variable + * in a method. See {@link #getSort getSort}. + */ + public final static int RESOURCE_VARIABLE = 0x41; + + /** + * The sort of type references that target the type of the exception of a + * 'catch' clause in a method. See {@link #getSort getSort}. + */ + public final static int EXCEPTION_PARAMETER = 0x42; + + /** + * The sort of type references that target the type declared in an + * 'instanceof' instruction. See {@link #getSort getSort}. + */ + public final static int INSTANCEOF = 0x43; + + /** + * The sort of type references that target the type of the object created by + * a 'new' instruction. See {@link #getSort getSort}. + */ + public final static int NEW = 0x44; + + /** + * The sort of type references that target the receiver type of a + * constructor reference. See {@link #getSort getSort}. + */ + public final static int CONSTRUCTOR_REFERENCE = 0x45; + + /** + * The sort of type references that target the receiver type of a method + * reference. See {@link #getSort getSort}. + */ + public final static int METHOD_REFERENCE = 0x46; + + /** + * The sort of type references that target the type declared in an explicit + * or implicit cast instruction. See {@link #getSort getSort}. + */ + public final static int CAST = 0x47; + + /** + * The sort of type references that target a type parameter of a generic + * constructor in a constructor call. See {@link #getSort getSort}. + */ + public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; + + /** + * The sort of type references that target a type parameter of a generic + * method in a method call. See {@link #getSort getSort}. + */ + public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; + + /** + * The sort of type references that target a type parameter of a generic + * constructor in a constructor reference. See {@link #getSort getSort}. + */ + public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; + + /** + * The sort of type references that target a type parameter of a generic + * method in a method reference. See {@link #getSort getSort}. + */ + public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; + + /** + * The type reference value in Java class file format. + */ + private int value; + + /** + * Creates a new TypeReference. + * + * @param typeRef + * the int encoded value of the type reference, as received in a + * visit method related to type annotations, like + * visitTypeAnnotation. + */ + public TypeReference(int typeRef) { + this.value = typeRef; + } + + /** + * Returns a type reference of the given sort. + * + * @param sort + * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, + * {@link #METHOD_RECEIVER METHOD_RECEIVER}, + * {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, + * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, + * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, + * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or + * {@link #METHOD_REFERENCE METHOD_REFERENCE}. + * @return a type reference of the given sort. + */ + public static TypeReference newTypeReference(int sort) { + return new TypeReference(sort << 24); + } + + /** + * Returns a reference to a type parameter of a generic class or method. + * + * @param sort + * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. + * @param paramIndex + * the type parameter index. + * @return a reference to the given generic class or method type parameter. + */ + public static TypeReference newTypeParameterReference(int sort, + int paramIndex) { + return new TypeReference((sort << 24) | (paramIndex << 16)); + } + + /** + * Returns a reference to a type parameter bound of a generic class or + * method. + * + * @param sort + * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. + * @param paramIndex + * the type parameter index. + * @param boundIndex + * the type bound index within the above type parameters. + * @return a reference to the given generic class or method type parameter + * bound. + */ + public static TypeReference newTypeParameterBoundReference(int sort, + int paramIndex, int boundIndex) { + return new TypeReference((sort << 24) | (paramIndex << 16) + | (boundIndex << 8)); + } + + /** + * Returns a reference to the super class or to an interface of the + * 'implements' clause of a class. + * + * @param itfIndex + * the index of an interface in the 'implements' clause of a + * class, or -1 to reference the super class of the class. + * @return a reference to the given super type of a class. + */ + public static TypeReference newSuperTypeReference(int itfIndex) { + itfIndex &= 0xFFFF; + return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8)); + } + + /** + * Returns a reference to the type of a formal parameter of a method. + * + * @param paramIndex + * the formal parameter index. + * + * @return a reference to the type of the given method formal parameter. + */ + public static TypeReference newFormalParameterReference(int paramIndex) { + return new TypeReference((METHOD_FORMAL_PARAMETER << 24) + | (paramIndex << 16)); + } + + /** + * Returns a reference to the type of an exception, in a 'throws' clause of + * a method. + * + * @param exceptionIndex + * the index of an exception in a 'throws' clause of a method. + * + * @return a reference to the type of the given exception. + */ + public static TypeReference newExceptionReference(int exceptionIndex) { + return new TypeReference((THROWS << 24) | (exceptionIndex << 8)); + } + + /** + * Returns a reference to the type of the exception declared in a 'catch' + * clause of a method. + * + * @param tryCatchBlockIndex + * the index of a try catch block (using the order in which they + * are visited with visitTryCatchBlock). + * + * @return a reference to the type of the given exception. + */ + public static TypeReference newTryCatchReference(int tryCatchBlockIndex) { + return new TypeReference((EXCEPTION_PARAMETER << 24) + | (tryCatchBlockIndex << 8)); + } + + /** + * Returns a reference to the type of a type argument in a constructor or + * method call or reference. + * + * @param sort + * {@link #CAST CAST}, + * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link #METHOD_INVOCATION_TYPE_ARGUMENT + * METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link #METHOD_REFERENCE_TYPE_ARGUMENT + * METHOD_REFERENCE_TYPE_ARGUMENT}. + * @param argIndex + * the type argument index. + * + * @return a reference to the type of the given type argument. + */ + public static TypeReference newTypeArgumentReference(int sort, int argIndex) { + return new TypeReference((sort << 24) | argIndex); + } + + /** + * Returns the sort of this type reference. + * + * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, + * {@link #CLASS_EXTENDS CLASS_EXTENDS}, + * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND}, + * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}, + * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, + * {@link #METHOD_RECEIVER METHOD_RECEIVER}, + * {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}, + * {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, + * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, + * {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER}, + * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, + * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, + * {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST}, + * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link #METHOD_INVOCATION_TYPE_ARGUMENT + * METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link #METHOD_REFERENCE_TYPE_ARGUMENT + * METHOD_REFERENCE_TYPE_ARGUMENT}. + */ + public int getSort() { + return value >>> 24; + } + + /** + * Returns the index of the type parameter referenced by this type + * reference. This method must only be used for type references whose sort + * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, + * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or + * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. + * + * @return a type parameter index. + */ + public int getTypeParameterIndex() { + return (value & 0x00FF0000) >> 16; + } + + /** + * Returns the index of the type parameter bound, within the type parameter + * {@link #getTypeParameterIndex}, referenced by this type reference. This + * method must only be used for type references whose sort is + * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or + * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. + * + * @return a type parameter bound index. + */ + public int getTypeParameterBoundIndex() { + return (value & 0x0000FF00) >> 8; + } + + /** + * Returns the index of the "super type" of a class that is referenced by + * this type reference. This method must only be used for type references + * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}. + * + * @return the index of an interface in the 'implements' clause of a class, + * or -1 if this type reference references the type of the super + * class. + */ + public int getSuperTypeIndex() { + return (short) ((value & 0x00FFFF00) >> 8); + } + + /** + * Returns the index of the formal parameter whose type is referenced by + * this type reference. This method must only be used for type references + * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}. + * + * @return a formal parameter index. + */ + public int getFormalParameterIndex() { + return (value & 0x00FF0000) >> 16; + } + + /** + * Returns the index of the exception, in a 'throws' clause of a method, + * whose type is referenced by this type reference. This method must only be + * used for type references whose sort is {@link #THROWS THROWS}. + * + * @return the index of an exception in the 'throws' clause of a method. + */ + public int getExceptionIndex() { + return (value & 0x00FFFF00) >> 8; + } + + /** + * Returns the index of the try catch block (using the order in which they + * are visited with visitTryCatchBlock), whose 'catch' type is referenced by + * this type reference. This method must only be used for type references + * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} . + * + * @return the index of an exception in the 'throws' clause of a method. + */ + public int getTryCatchBlockIndex() { + return (value & 0x00FFFF00) >> 8; + } + + /** + * Returns the index of the type argument referenced by this type reference. + * This method must only be used for type references whose sort is + * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}. + * + * @return a type parameter index. + */ + public int getTypeArgumentIndex() { + return value & 0xFF; + } + + /** + * Returns the int encoded value of this type reference, suitable for use in + * visit methods related to type annotations, like visitTypeAnnotation. + * + * @return the int encoded value of this type reference. + */ + public int getValue() { + return value; + } +} diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index bc2d4bab8..14e24bf78 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -26,7 +26,7 @@ junit junit - + dom4j dom4j diff --git a/blade-kit/src/main/java/com/blade/kit/reflect/ReflectKit.java b/blade-kit/src/main/java/com/blade/kit/reflect/ReflectKit.java index 7c3ef12e6..fb4bd21d9 100644 --- a/blade-kit/src/main/java/com/blade/kit/reflect/ReflectKit.java +++ b/blade-kit/src/main/java/com/blade/kit/reflect/ReflectKit.java @@ -203,6 +203,64 @@ public static Method getMethodByName(Class clazz, String methodName) { return ret; } + /*private static boolean sameType(Type[] types, Class[] clazzes) { + if (types.length != clazzes.length) { + return false; + } + for (int i = 0; i < types.length; i++) { + if (!Type.getType(clazzes[i]).equals(types[i])) { + return false; + } + } + return true; + } + + public static String[] getMethodParamsNames(final Method m) { + try { + final String[] paramNames = new String[m.getParameterTypes().length]; + Class declaringClass = m.getDeclaringClass(); + String className = declaringClass.getName(); + int lastDotIndex = className.lastIndexOf("."); + InputStream is = declaringClass.getResourceAsStream(className.substring(lastDotIndex + 1) + ".class"); + ClassReader cr = new ClassReader(is); + cr.accept(new ClassVisitor(Opcodes.ASM4) { + @Override + public MethodVisitor visitMethod(final int access, final String name, final String desc, + final String signature, final String[] exceptions) { + + final Type[] args = Type.getArgumentTypes(desc); + // 方法名相同并且参数个数相同 + if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { + return super.visitMethod(access, name, desc, signature, exceptions); + } + MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); + return new MethodVisitor(Opcodes.ASM4, v) { + @Override + public void visitLocalVariable(String name, String desc, String signature, Label start, + Label end, int index) { + int i = index - 1; + // 如果是静态方法,则第一就是参数 + // 如果不是静态方法,则第一个是"this",然后才是方法的参数 + if (Modifier.isStatic(m.getModifiers())) { + i = index; + } + if (i >= 0 && i < paramNames.length) { + paramNames[i] = name; + } + super.visitLocalVariable(name, desc, signature, start, end, index); + } + }; + } + }, 0); + return paramNames; + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + }*/ + /** * * @param bean 类实例 diff --git a/pom.xml b/pom.xml index 58a15880b..7f5f70223 100644 --- a/pom.xml +++ b/pom.xml @@ -15,12 +15,13 @@ 1.6 UTF-8 1.6.5 - 1.3.1 + 1.3.2 0.0.3 3.0.1 4.12 1.7.21 1.7.21 + 5.1 From 464b5f03e2507a05f64a6f96ac38af18e4a401ff Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 30 Aug 2016 18:39:58 +0800 Subject: [PATCH 462/545] update aop --- .../src/main/java/com/blade/aop/Aop.java | 28 ++----------------- .../src/main/java/com/blade/aop/Log.java | 14 ---------- .../java/com/blade/aop/LogClassVisitor.java | 19 ------------- .../java/com/blade/aop/LogMethodVisitor.java | 28 ------------------- .../java/com/blade/aop/MyClassLoader.java | 11 -------- 5 files changed, 2 insertions(+), 98 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/aop/Log.java delete mode 100644 blade-core/src/main/java/com/blade/aop/LogClassVisitor.java delete mode 100644 blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java delete mode 100644 blade-core/src/main/java/com/blade/aop/MyClassLoader.java diff --git a/blade-core/src/main/java/com/blade/aop/Aop.java b/blade-core/src/main/java/com/blade/aop/Aop.java index 83e627a58..54a44750d 100644 --- a/blade-core/src/main/java/com/blade/aop/Aop.java +++ b/blade-core/src/main/java/com/blade/aop/Aop.java @@ -1,14 +1,8 @@ package com.blade.aop; -import java.io.IOException; -import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.Set; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; - import com.blade.kit.reflect.ReflectKit; public class Aop { @@ -27,32 +21,14 @@ public void addPackage(String packageName){ packages.add(packageName); } - private Map maps = new HashMap(); - public Object createBean(Class clazz) { try { - String clsasName = clazz.getName(); - if(null == maps.get(clsasName)){ - String packageName = clazz.getPackage().getName(); - if (packages.contains(packageName)) { - ClassReader cr = new ClassReader(clazz.getName()); - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); - cr.accept(new LogClassVisitor(cw), ClassReader.SKIP_DEBUG); - Object value = new MyClassLoader().defineClassForName(clazz.getName(), cw.toByteArray()).newInstance(); - maps.put(clsasName, value); - return value; - } - Object value = ReflectKit.newInstance(clazz); - maps.put(clsasName, value); - return value; - } - return maps.get(clsasName); + Object value = ReflectKit.newInstance(clazz); + return value; } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); } return null; } diff --git a/blade-core/src/main/java/com/blade/aop/Log.java b/blade-core/src/main/java/com/blade/aop/Log.java deleted file mode 100644 index 5221524e0..000000000 --- a/blade-core/src/main/java/com/blade/aop/Log.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.blade.aop; - -public class Log -{ - public static void startLog() - { - System.out.println("start log ..."); - } - - public static void endLog() - { - System.out.println("end log ..."); - } -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java b/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java deleted file mode 100644 index 47d21db4a..000000000 --- a/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.blade.aop; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -public class LogClassVisitor extends ClassVisitor { - - public LogClassVisitor(ClassVisitor cv) { - super(Opcodes.ASM5, cv); - } - - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - if ("oper".equals(name)) { - return new LogMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions)); - } - return super.visitMethod(access, name, desc, signature, exceptions); - } -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java b/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java deleted file mode 100644 index 115b67445..000000000 --- a/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.blade.aop; - -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -public class LogMethodVisitor extends MethodVisitor { - public LogMethodVisitor(MethodVisitor mv) { - super(Opcodes.ASM4, mv); - } - - public void visitCode() { - /** - * 方法执行之前植入代码 - */ - super.visitMethodInsn(Opcodes.INVOKESTATIC, "com/blade/aop/Log", "startLog", "()V", false); - super.visitCode(); - } - - public void visitInsn(int opcode) { - if (opcode == Opcodes.RETURN) { - /** - * 方法return之前,植入代码 - */ - super.visitMethodInsn(Opcodes.INVOKESTATIC, "com/blade/aop/Log", "endLog", "()V", false); - } - super.visitInsn(opcode); - } -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/MyClassLoader.java b/blade-core/src/main/java/com/blade/aop/MyClassLoader.java deleted file mode 100644 index d90dfa9e3..000000000 --- a/blade-core/src/main/java/com/blade/aop/MyClassLoader.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.blade.aop; -public class MyClassLoader extends ClassLoader { - public MyClassLoader() { - super(Thread.currentThread().getContextClassLoader()); - } - - public Class defineClassForName(String name, byte[] data) { - return this.defineClass(name, data, 0, data.length); - } - -} \ No newline at end of file From 948c33b1a77223967de613d0330f01b83a211696 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 30 Aug 2016 21:28:45 +0800 Subject: [PATCH 463/545] unified init --- .../com/blade/context/ApplicationContext.java | 33 ++ .../java/com/blade/web/DispatcherServlet.java | 336 ++++++++---------- 2 files changed, 186 insertions(+), 183 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/context/ApplicationContext.java diff --git a/blade-core/src/main/java/com/blade/context/ApplicationContext.java b/blade-core/src/main/java/com/blade/context/ApplicationContext.java new file mode 100644 index 000000000..85269a5cd --- /dev/null +++ b/blade-core/src/main/java/com/blade/context/ApplicationContext.java @@ -0,0 +1,33 @@ +package com.blade.context; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.exception.BladeException; +import com.blade.ioc.IocApplication; + +public final class ApplicationContext { + + public static void init(Blade blade) throws BladeException{ + + blade.bootstrap().init(blade); + + if(!blade.config().isInit()){ + blade.loadAppConf(Const.APP_PROPERTIES); + blade.config().setEnv(blade.environment()); + } + // load config + blade.configLoader().loadConfig(); + + // buiding route + blade.routeBuilder().building(); + + // initialization ioc + IocApplication iocApplication = new IocApplication(); + iocApplication.init(); + blade.init(); + + blade.bootstrap().contextInitialized(); + + } + +} diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index f29271f87..e972eea50 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -1,183 +1,153 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; - -import java.io.IOException; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Bootstrap; -import com.blade.Const; -import com.blade.context.ApplicationWebContext; -import com.blade.ioc.IocApplication; -import com.blade.kit.Environment; -import com.blade.kit.StringKit; -import com.blade.kit.SystemKit; -import com.blade.kit.resource.DynamicClassReader; - -/** - * Blade Core DispatcherServlet - * - * @author biezhi - * @since 1.0 - */ -public class DispatcherServlet extends HttpServlet { - - private static final long serialVersionUID = -2607425162473178733L; - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); - - private Blade blade = Blade.$(); - - private Bootstrap bootstrap; - - private IocApplication iocApplication; - - private ServletContext servletContext; - - private DispatcherHandler dispatcherHandler; - - public DispatcherServlet() { - } - - public DispatcherServlet(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - blade.init(); - } - - @Override - public void init(ServletConfig config) throws ServletException { - servletContext = config.getServletContext(); - if(!blade.isInit()){ - - LOGGER.info("jdk.version = {}", SystemKit.getJavaInfo().getVersion()); - LOGGER.info("user.dir = {}", System.getProperty("user.dir")); - LOGGER.info("java.io.tmpdir = {}", System.getProperty("java.io.tmpdir")); - LOGGER.info("user.timezone = {}", System.getProperty("user.timezone")); - LOGGER.info("file.encoding = {}", System.getProperty("file.encoding")); - - DynamicClassReader.init(); - - long initStart = System.currentTimeMillis(); - - blade.webRoot(DispatchKit.getWebRoot(servletContext).getPath()); - - ApplicationWebContext.init(servletContext); - - LOGGER.info("blade.webroot = {}", blade.webRoot()); - - this.bootstrap = blade.bootstrap(); - - if(!blade.config().isInit()){ - blade.loadAppConf(Const.APP_PROPERTIES); - blade.config().setEnv(blade.environment()); - } - - if(null == bootstrap){ - String bootStrapClassName = config.getInitParameter("bootstrap"); - if(StringKit.isNotBlank(bootStrapClassName)){ - this.bootstrap = getBootstrap(bootStrapClassName); - } else { - this.bootstrap = new Bootstrap() { - @Override - public void init(Blade blade) { - } - }; - } - blade.app(this.bootstrap); - } - - // load config - blade.configLoader().loadConfig(); - - this.bootstrap.init(blade); - - LOGGER.info("blade.isDev = {}", blade.isDev()); - - // buiding route - blade.routeBuilder().building(); - - // initialization ioc - iocApplication = new IocApplication(); - iocApplication.init(); - - blade.init(); - - this.bootstrap.contextInitialized(); - - dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); - - new BladeBanner().print(); - - Environment environment = blade.environment(); - String appName = "Blade"; - if(null != environment){ - appName = environment.getString("app.name", "Blade"); - } - - LOGGER.info(appName + " initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); - } - } - - @Override - protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { - httpRequest.setCharacterEncoding(blade.encoding()); - httpResponse.setCharacterEncoding(blade.encoding()); - dispatcherHandler.handle(httpRequest, httpResponse); - } - - @Override - public void destroy() { - super.destroy(); - if(null != iocApplication){ - iocApplication.destroy(); - } - } - - /** - * Get global initialization object, the application of the initialization - * - * @param botstrapClassName botstrap class name - * @return return bootstrap object - * @throws ServletException - */ - @SuppressWarnings("unchecked") - private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { - Bootstrap bootstrapClass = null; - try { - if(null != botstrapClassName){ - Class applicationClass = (Class) Class.forName(botstrapClassName); - if(null != applicationClass){ - bootstrapClass = applicationClass.newInstance(); - } - } else { - throw new ServletException("bootstrapClass is null !"); - } - } catch (Exception e) { - throw new ServletException(e); - } - return bootstrapClass; - } -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Bootstrap; +import com.blade.context.ApplicationContext; +import com.blade.context.ApplicationWebContext; +import com.blade.kit.StringKit; +import com.blade.kit.SystemKit; +import com.blade.kit.resource.DynamicClassReader; + +/** + * Blade Core DispatcherServlet + * + * @author biezhi + * @since 1.0 + */ +public class DispatcherServlet extends HttpServlet { + + private static final long serialVersionUID = -2607425162473178733L; + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); + + private Blade blade = Blade.$(); + + private Bootstrap bootstrap; + + private ServletContext servletContext; + + private DispatcherHandler dispatcherHandler; + + public DispatcherServlet() { + } + + public DispatcherServlet(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + blade.init(); + } + + @Override + public void init(ServletConfig config) throws ServletException { + servletContext = config.getServletContext(); + if(!blade.isInit()){ + + LOGGER.info("jdk.version = {}", SystemKit.getJavaInfo().getVersion()); + LOGGER.info("user.dir = {}", System.getProperty("user.dir")); + LOGGER.info("java.io.tmpdir = {}", System.getProperty("java.io.tmpdir")); + LOGGER.info("user.timezone = {}", System.getProperty("user.timezone")); + LOGGER.info("file.encoding = {}", System.getProperty("file.encoding")); + + DynamicClassReader.init(); + + long initStart = System.currentTimeMillis(); + + blade.webRoot(DispatchKit.getWebRoot(servletContext).getPath()); + + ApplicationWebContext.init(servletContext); + + LOGGER.info("blade.webroot = {}", blade.webRoot()); + + this.bootstrap = blade.bootstrap(); + + if(null == bootstrap){ + String bootStrapClassName = config.getInitParameter("bootstrap"); + if(StringKit.isNotBlank(bootStrapClassName)){ + this.bootstrap = getBootstrap(bootStrapClassName); + } else { + this.bootstrap = new Bootstrap() { + @Override + public void init(Blade blade) { + } + }; + } + blade.app(this.bootstrap); + } + + ApplicationContext.init(blade); + + LOGGER.info("blade.isDev = {}", blade.isDev()); + + dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); + + new BladeBanner().print(); + + String appName = blade.environment().getString("app.name", "Blade"); + + LOGGER.info(appName + " initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); + } + } + + @Override + protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { + httpRequest.setCharacterEncoding(blade.encoding()); + httpResponse.setCharacterEncoding(blade.encoding()); + dispatcherHandler.handle(httpRequest, httpResponse); + } + + @Override + public void destroy() { + super.destroy(); + } + + /** + * Get global initialization object, the application of the initialization + * + * @param botstrapClassName botstrap class name + * @return return bootstrap object + * @throws ServletException + */ + @SuppressWarnings("unchecked") + private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { + Bootstrap bootstrapClass = null; + try { + if(null != botstrapClassName){ + Class applicationClass = (Class) Class.forName(botstrapClassName); + if(null != applicationClass){ + bootstrapClass = applicationClass.newInstance(); + } + } else { + throw new ServletException("bootstrapClass is null !"); + } + } catch (Exception e) { + throw new ServletException(e); + } + return bootstrapClass; + } +} From 6ccea6fcdc26cd46933e14daf9bcc88a9ad9d165 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 30 Aug 2016 22:30:31 +0800 Subject: [PATCH 464/545] add aop code --- .../src/main/java/com/blade/aop/Log.java | 13 + .../java/com/blade/aop/LogClassVisitor.java | 20 + .../java/com/blade/aop/LogMethodVisitor.java | 29 ++ .../java/com/blade/aop/ProxyClassLoader.java | 33 ++ .../java/com/blade/config/ConfigLoader.java | 169 +++---- .../com/blade/context/ApplicationContext.java | 9 + .../blade/context}/DynamicClassReader.java | 94 ++-- .../java/com/blade/ioc/IocApplication.java | 375 +++++++------- .../blade/ioc/loader/IocAnnotationLoader.java | 139 +++--- .../java/com/blade/route/RouteBuilder.java | 457 +++++++++--------- .../java/com/blade/web/DispatcherServlet.java | 2 +- blade-kit/pom.xml | 112 +++-- .../kit/resource/AbstractClassReader.java | 349 ++++++------- .../blade/kit/resource/BladeClassLoader.java | 12 + .../com/blade/kit/resource/ClassInfo.java | 30 ++ .../kit/resource/ClassPathClassReader.java | 54 ++- .../com/blade/kit/resource/ClassReader.java | 74 +-- .../com/blade/kit/resource/JarReaderImpl.java | 312 ++++++------ 18 files changed, 1238 insertions(+), 1045 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/aop/Log.java create mode 100644 blade-core/src/main/java/com/blade/aop/LogClassVisitor.java create mode 100644 blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java create mode 100644 blade-core/src/main/java/com/blade/aop/ProxyClassLoader.java rename {blade-kit/src/main/java/com/blade/kit/resource => blade-core/src/main/java/com/blade/context}/DynamicClassReader.java (78%) create mode 100644 blade-kit/src/main/java/com/blade/kit/resource/BladeClassLoader.java create mode 100644 blade-kit/src/main/java/com/blade/kit/resource/ClassInfo.java diff --git a/blade-core/src/main/java/com/blade/aop/Log.java b/blade-core/src/main/java/com/blade/aop/Log.java new file mode 100644 index 000000000..b9ff3bcd4 --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/Log.java @@ -0,0 +1,13 @@ +package com.blade.aop; +public class Log +{ + public static void startLog() + { + System.out.println("start log ..."); + } + + public static void endLog() + { + System.out.println("end log ..."); + } +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java b/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java new file mode 100644 index 000000000..62604bf3b --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java @@ -0,0 +1,20 @@ +package com.blade.aop; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class LogClassVisitor extends ClassVisitor { + + public LogClassVisitor(ClassVisitor cv) { + super(Opcodes.ASM5, cv); + } + + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + if ("getEnvCount".equals(name)) { + return new LogMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions)); + } + return super.visitMethod(access, name, desc, signature, exceptions); + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java b/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java new file mode 100644 index 000000000..d6dcf9d5d --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java @@ -0,0 +1,29 @@ +package com.blade.aop; + +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class LogMethodVisitor extends MethodVisitor { + + public LogMethodVisitor(MethodVisitor mv) { + super(Opcodes.ASM5, mv); + } + + public void visitCode() { + /** + * 方法执行之前植入代码 + */ + super.visitMethodInsn(Opcodes.INVOKESTATIC, "com/blade/aop/Log", "startLog", "()V", false); + super.visitCode(); + } + + public void visitInsn(int opcode) { + if (opcode == Opcodes.RETURN) { + /** + * 方法return之前,植入代码 + */ + super.visitMethodInsn(Opcodes.INVOKESTATIC, "com/blade/aop/Log", "endLog", "()V", false); + } + super.visitInsn(opcode); + } +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/ProxyClassLoader.java b/blade-core/src/main/java/com/blade/aop/ProxyClassLoader.java new file mode 100644 index 000000000..a556177b1 --- /dev/null +++ b/blade-core/src/main/java/com/blade/aop/ProxyClassLoader.java @@ -0,0 +1,33 @@ +package com.blade.aop; + +import java.io.IOException; + +import org.objectweb.asm.ClassWriter; + +import com.blade.kit.resource.BladeClassLoader; + +public class ProxyClassLoader extends BladeClassLoader { + + public ProxyClassLoader() { + } + + @Override + public Class defineClassByName(String name) throws ClassNotFoundException { + org.objectweb.asm.ClassReader cr; + + if (name.endsWith("Service")) { + return Class.forName(name); + } + try { + cr = new org.objectweb.asm.ClassReader(name); + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + cr.accept(new LogClassVisitor(cw), org.objectweb.asm.ClassReader.SKIP_DEBUG); + byte[] data = cw.toByteArray(); + return this.defineClass(name, data, 0, data.length); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/blade-core/src/main/java/com/blade/config/ConfigLoader.java b/blade-core/src/main/java/com/blade/config/ConfigLoader.java index 1ea9bd5a1..5e0691733 100644 --- a/blade-core/src/main/java/com/blade/config/ConfigLoader.java +++ b/blade-core/src/main/java/com/blade/config/ConfigLoader.java @@ -1,84 +1,85 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.lang.reflect.Modifier; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.exception.ConfigException; -import com.blade.ioc.Ioc; -import com.blade.ioc.annotation.Component; -import com.blade.kit.CollectionKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassReader; -import com.blade.kit.resource.DynamicClassReader; - -/** - * ConfigLoader - * - * @author biezhi - * @since 1.0 - */ -public class ConfigLoader { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); - - private ClassReader classReader; - private Ioc ioc; - private ApplicationConfig applicationConfig; - - public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { - this.ioc = ioc; - this.classReader = DynamicClassReader.getClassReader(); - this.applicationConfig = applicationConfig; - } - - @SuppressWarnings("unchecked") - public void loadConfig() { - String[] configPackages = Blade.$().config().getConfigPackages(); - if (null != configPackages && configPackages.length > 0) { - // Scan package all class - try { - for (String packageName : configPackages) { - Set> classes = classReader.getClassByAnnotation(packageName, Component.class, false); - if (CollectionKit.isNotEmpty(classes)) { - for (Class clazz : classes) { - boolean hasInterface = ReflectKit.hasInterface(clazz, BaseConfig.class); - if(hasInterface){ - addConfig((Class) clazz); - } - } - } - } - } catch (ConfigException e) { - LOGGER.error("load config error", e); - } - } - } - - public void addConfig(Class clazz) throws ConfigException { - if (!Modifier.isAbstract(clazz.getModifiers())) { - Object bean = ioc.addBean(clazz); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(applicationConfig); - } - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.lang.reflect.Modifier; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.context.DynamicClassReader; +import com.blade.exception.ConfigException; +import com.blade.ioc.Ioc; +import com.blade.ioc.annotation.Component; +import com.blade.kit.CollectionKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; + +/** + * ConfigLoader + * + * @author biezhi + * @since 1.0 + */ +public class ConfigLoader { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); + + private ClassReader classReader; + private Ioc ioc; + private ApplicationConfig applicationConfig; + + public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { + this.ioc = ioc; + this.classReader = DynamicClassReader.getClassReader(); + this.applicationConfig = applicationConfig; + } + + @SuppressWarnings("unchecked") + public void loadConfig() { + String[] configPackages = Blade.$().config().getConfigPackages(); + if (null != configPackages && configPackages.length > 0) { + // Scan package all class + try { + for (String packageName : configPackages) { + Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); + if (CollectionKit.isNotEmpty(classes)) { + for (ClassInfo classInfo : classes) { + boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); + if(hasInterface){ + addConfig((Class) classInfo.getClazz()); + } + } + } + } + } catch (ConfigException e) { + LOGGER.error("load config error", e); + } + } + } + + public void addConfig(Class clazz) throws ConfigException { + if (!Modifier.isAbstract(clazz.getModifiers())) { + Object bean = ioc.addBean(clazz); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(applicationConfig); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/context/ApplicationContext.java b/blade-core/src/main/java/com/blade/context/ApplicationContext.java index 85269a5cd..1dbb87dfe 100644 --- a/blade-core/src/main/java/com/blade/context/ApplicationContext.java +++ b/blade-core/src/main/java/com/blade/context/ApplicationContext.java @@ -2,8 +2,10 @@ import com.blade.Blade; import com.blade.Const; +import com.blade.aop.ProxyClassLoader; import com.blade.exception.BladeException; import com.blade.ioc.IocApplication; +import com.blade.kit.resource.BladeClassLoader; public final class ApplicationContext { @@ -15,6 +17,7 @@ public static void init(Blade blade) throws BladeException{ blade.loadAppConf(Const.APP_PROPERTIES); blade.config().setEnv(blade.environment()); } + // load config blade.configLoader().loadConfig(); @@ -30,4 +33,10 @@ public static void init(Blade blade) throws BladeException{ } + private static final BladeClassLoader CLASSLOADER = new ProxyClassLoader(); + + public static BladeClassLoader getClassLoader(){ + return CLASSLOADER; + } + } diff --git a/blade-kit/src/main/java/com/blade/kit/resource/DynamicClassReader.java b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java similarity index 78% rename from blade-kit/src/main/java/com/blade/kit/resource/DynamicClassReader.java rename to blade-core/src/main/java/com/blade/context/DynamicClassReader.java index ae6389875..3c1e8122a 100644 --- a/blade-kit/src/main/java/com/blade/kit/resource/DynamicClassReader.java +++ b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java @@ -1,45 +1,49 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; - -/** - * 动态根据环境获取ClassReader - * - * @author biezhi - * @since 1.0 - */ -public class DynamicClassReader { - - private static boolean IS_JAR_CONTEXT = false; - - private DynamicClassReader() { - } - - public static void init(){ - String rs = DynamicClassReader.class.getResource("").toString(); - if(rs.indexOf(".jar!") != -1){ - IS_JAR_CONTEXT = true; - } - } - - public static ClassReader getClassReader(){ - if(IS_JAR_CONTEXT){ - return new JarReaderImpl(); - } - return new ClassPathClassReader(); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import com.blade.kit.resource.ClassPathClassReader; +import com.blade.kit.resource.ClassReader; +import com.blade.kit.resource.JarReaderImpl; + +/** + * 动态根据环境获取ClassReader + * + * @author biezhi + * @since 1.0 + */ +public class DynamicClassReader { + + private static boolean IS_JAR_CONTEXT = false; + + private DynamicClassReader() { + } + + public static void init(){ + String rs = DynamicClassReader.class.getResource("").toString(); + if(rs.indexOf(".jar!") != -1){ + IS_JAR_CONTEXT = true; + } + } + + public static ClassReader getClassReader(){ + if(IS_JAR_CONTEXT){ + return new JarReaderImpl(ApplicationContext.getClassLoader()); + } + return new ClassPathClassReader(ApplicationContext.getClassLoader()); + } + +} diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index b29f9cbec..632449e47 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -1,188 +1,189 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Bootstrap; -import com.blade.ioc.annotation.Component; -import com.blade.ioc.annotation.Service; -import com.blade.kit.CollectionKit; -import com.blade.kit.StringKit; -import com.blade.kit.resource.ClassReader; -import com.blade.kit.resource.DynamicClassReader; -import com.blade.plugin.Plugin; -import com.blade.route.Route; -import com.blade.route.RouteHandler; -import com.blade.route.Routers; - -/** - * IOC container, used to initialize the IOC object - * - * @author biezhi - * @since 1.0 - */ -public class IocApplication { - - private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); - - /** - * Ioc Container - */ - private Ioc ioc = null; - - /** - * Class to read object, load class - */ - private ClassReader classReader = null; - - private String[] iocs; - private Bootstrap bootstrap; - - /** - * Plugin List - */ - private List plugins = null; - - private Set> pluginTypes; - - private Blade blade; - - public IocApplication() { - this.blade = Blade.$(); - this.classReader = DynamicClassReader.getClassReader(); - this.plugins = CollectionKit.newArrayList(); - this.pluginTypes = blade.plugins(); - this.ioc = blade.ioc(); - this.iocs = blade.config().getIocPackages(); - this.bootstrap = blade.bootstrap(); - } - - /** - * IOC initialize - * @param iocs ioc packages - * @param bootstrap bootstrap object - */ - public void init(){ - - // Initialize the global configuration class - if(null == ioc.getBean(Bootstrap.class)){ - ioc.addBean(bootstrap); - } - - // The object to initialize the IOC container loads the IOC package to configure the class that conforms to the IOC - if(null != iocs && iocs.length > 0){ - for(String packageName : iocs){ - registerBean(packageName); - } - } - - for(Class type : pluginTypes){ - ioc.addBean(type); - Plugin plugin = ioc.getBean(type); - plugins.add(plugin); - } - - // init controllers - Routers routers = blade.routers(); - Map routes = routers.getRoutes(); - if(CollectionKit.isNotEmpty(routes)){ - Collection routesList = routes.values(); - if(CollectionKit.isNotEmpty(routesList)){ - for(Route route : routesList){ - Class type = route.getTargetType(); - if(null != type && null == route.getTarget() && type != RouteHandler.class && null == ioc.getBean(type)){ - ioc.addBean(type); - } - } - } - } - - Map interceptors = routers.getInterceptors(); - if(CollectionKit.isNotEmpty(interceptors)){ - Collection routesList = interceptors.values(); - if(CollectionKit.isNotEmpty(routesList)){ - for(Route route : routesList){ - Class type = route.getTargetType(); - if(null != type && null == route.getTarget() && type != RouteHandler.class && null == ioc.getBean(type)){ - ioc.addBean(type); - } - } - } - } - - LOGGER.info("Add Object: {}", ioc.getBeans()); - - // injection - List beanDefines = ioc.getBeanDefines(); - for(BeanDefine beanDefine : beanDefines){ - IocKit.injection(ioc, beanDefine); - } - } - - /** - * Register all objects in a package - * - * @param packageName package name - */ - private void registerBean(String packageName) { - if(StringKit.isBlank(packageName)){ - return; - } - // Recursive scan - boolean recursive = false; - if (packageName.endsWith(".*")) { - packageName = packageName.substring(0, packageName.length() - 2); - recursive = true; - } - - // Scan package all class - Set> classes = classReader.getClass(packageName, recursive); - for (Class clazz : classes) { - if(!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())){ - Component component = clazz.getAnnotation(Component.class); - Service service = clazz.getAnnotation(Service.class); - if(null != component || null != service){ - // Register classes - ioc.addBean(clazz); - } - } - } - } - - public List getPlugins() { - return plugins; - } - - /** - * destroy - */ - public void destroy() { - // Clean IOC container - ioc.clearAll(); - for(Plugin plugin : plugins){ - plugin.destroy(); - } - } +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Bootstrap; +import com.blade.context.DynamicClassReader; +import com.blade.ioc.annotation.Component; +import com.blade.ioc.annotation.Service; +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.plugin.Plugin; +import com.blade.route.Route; +import com.blade.route.RouteHandler; +import com.blade.route.Routers; + +/** + * IOC container, used to initialize the IOC object + * + * @author biezhi + * @since 1.0 + */ +public class IocApplication { + + private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); + + /** + * Ioc Container + */ + private Ioc ioc = null; + + /** + * Class to read object, load class + */ + private ClassReader classReader = null; + private String[] iocs; + private Bootstrap bootstrap; + + /** + * Plugin List + */ + private List plugins = null; + + private Set> pluginTypes; + + private Blade blade; + + public IocApplication() { + this.blade = Blade.$(); + this.classReader = DynamicClassReader.getClassReader(); + this.plugins = CollectionKit.newArrayList(); + this.pluginTypes = blade.plugins(); + this.ioc = blade.ioc(); + this.iocs = blade.config().getIocPackages(); + this.bootstrap = blade.bootstrap(); + } + + /** + * IOC initialize + * @param iocs ioc packages + * @param bootstrap bootstrap object + */ + public void init(){ + + // Initialize the global configuration class + if(null == ioc.getBean(Bootstrap.class)){ + ioc.addBean(bootstrap); + } + + // The object to initialize the IOC container loads the IOC package to configure the class that conforms to the IOC + if(null != iocs && iocs.length > 0){ + for(String packageName : iocs){ + registerBean(packageName); + } + } + + for(Class type : pluginTypes){ + ioc.addBean(type); + Plugin plugin = ioc.getBean(type); + plugins.add(plugin); + } + + // init controllers + Routers routers = blade.routers(); + Map routes = routers.getRoutes(); + if(CollectionKit.isNotEmpty(routes)){ + Collection routesList = routes.values(); + if(CollectionKit.isNotEmpty(routesList)){ + for(Route route : routesList){ + Class type = route.getTargetType(); + if(null != type && null == route.getTarget() && type != RouteHandler.class && null == ioc.getBean(type)){ + ioc.addBean(type); + } + } + } + } + + Map interceptors = routers.getInterceptors(); + if(CollectionKit.isNotEmpty(interceptors)){ + Collection routesList = interceptors.values(); + if(CollectionKit.isNotEmpty(routesList)){ + for(Route route : routesList){ + Class type = route.getTargetType(); + if(null != type && null == route.getTarget() && type != RouteHandler.class && null == ioc.getBean(type)){ + ioc.addBean(type); + } + } + } + } + + LOGGER.info("Add Object: {}", ioc.getBeans()); + + // injection + List beanDefines = ioc.getBeanDefines(); + for(BeanDefine beanDefine : beanDefines){ + IocKit.injection(ioc, beanDefine); + } + } + + /** + * Register all objects in a package + * + * @param packageName package name + */ + private void registerBean(String packageName) { + if(StringKit.isBlank(packageName)){ + return; + } + // Recursive scan + boolean recursive = false; + if (packageName.endsWith(".*")) { + packageName = packageName.substring(0, packageName.length() - 2); + recursive = true; + } + + // Scan package all class + Set classes = classReader.getClass(packageName, recursive); + for (ClassInfo classInfo : classes) { + Class clazz = classInfo.getClazz(); + if(!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())){ + Component component = clazz.getAnnotation(Component.class); + Service service = clazz.getAnnotation(Service.class); + if(null != component || null != service){ + // Register classes + ioc.addBean(clazz); + } + } + } + } + + public List getPlugins() { + return plugins; + } + + /** + * destroy + */ + public void destroy() { + // Clean IOC container + ioc.clearAll(); + for(Plugin plugin : plugins){ + plugin.destroy(); + } + } } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java index 7479617ea..6741abe9c 100644 --- a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java @@ -1,67 +1,72 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.loader; - -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import com.blade.ioc.SimpleIoc; -import com.blade.ioc.annotation.Component; -import com.blade.kit.resource.ClassReader; -import com.blade.kit.resource.DynamicClassReader; - -public final class IocAnnotationLoader implements IocLoader { - - private Collection> classes; - - private ClassReader classReader = DynamicClassReader.getClassReader(); - - public IocAnnotationLoader(String... packageNames) { - List> annotations = new ArrayList>(1); - annotations.add(Component.class); - this.classes = finder(Arrays.asList(packageNames), annotations, true); - } - - private Collection> finder(List packageNames, List> annotations, boolean recursive){ - Collection> classes = new ArrayList>(); - for(String packageName : packageNames){ - for(Class annotation : annotations){ - classes.addAll(classReader.getClassByAnnotation(packageName, annotation, recursive)); - } - } - return classes; - } - - public IocAnnotationLoader(Collection> classes) { - this.classes = classes; - } - - @Override - public void load(SimpleIoc ioc) { - for (Class cls : classes) { - Component anno = cls.getAnnotation(Component.class); - if (anno != null) { - String name = anno.value().equals("") ? cls.getName() : anno.value(); - ioc.addBean(name, cls, true); - } - } - // free - classes = null; - } -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.loader; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import com.blade.context.DynamicClassReader; +import com.blade.ioc.SimpleIoc; +import com.blade.ioc.annotation.Component; +import com.blade.kit.CollectionKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; + +public final class IocAnnotationLoader implements IocLoader { + + private Collection classes; + + private ClassReader classReader = DynamicClassReader.getClassReader(); + + + + public IocAnnotationLoader(String... packageNames) { + List> annotations = new ArrayList>(1); + annotations.add(Component.class); + this.classes = finder(Arrays.asList(packageNames), annotations, true); + } + + private Collection finder(List packageNames, List> annotations, boolean recursive){ + Collection classes = CollectionKit.newArrayList(); + for(String packageName : packageNames){ + for(Class annotation : annotations){ + classes.addAll(classReader.getClassByAnnotation(packageName, annotation, recursive)); + } + } + return classes; + } + + public IocAnnotationLoader(Collection classes) { + this.classes = classes; + } + + @Override + public void load(SimpleIoc ioc) { + for (ClassInfo classInfo : classes) { + Class cls = classInfo.getClazz(); + Component anno = cls.getAnnotation(Component.class); + if (anno != null) { + String name = anno.value().equals("") ? cls.getName() : anno.value(); + ioc.addBean(name, cls, true); + } + } + // free + classes = null; + } +} diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index a9624a7b7..cf3745d9a 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -1,228 +1,231 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import java.lang.reflect.Method; -import java.util.Set; - -import com.blade.Blade; -import com.blade.annotation.Controller; -import com.blade.annotation.Intercept; -import com.blade.annotation.Route; -import com.blade.interceptor.Interceptor; -import com.blade.kit.CollectionKit; -import com.blade.kit.StringKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassReader; -import com.blade.kit.resource.DynamicClassReader; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -/** - * Route builder - * - * @author biezhi - * @since 1.0 - */ -public class RouteBuilder { - - /** - * Class reader, used to scan the class specified in the rules - */ - private ClassReader classReader; - - private Routers routers; - - private String[] routePackages; - - private String interceptorPackage; - - public RouteBuilder(Routers routers) { - this.routers = routers; - this.classReader = DynamicClassReader.getClassReader(); - } - - /** - * Start building route - */ - public void building() { - - this.routePackages = Blade.$().config().getRoutePackages(); - this.interceptorPackage = Blade.$().config().getInterceptorPackage(); - - // Route - if(null != routePackages && routePackages.length > 0){ - this.buildRoute(routePackages); - } - - // Inteceptor - if(StringKit.isNotBlank(interceptorPackage)){ - this.buildInterceptor(interceptorPackage); - } - - } - - /** - * Build interceptor - * - * @param interceptorPackages add the interceptor package - */ - private void buildInterceptor(String... interceptorPackages){ - - // Scan all Interceptor - Set> classes = null; - - // Traversal Interceptor - for(String packageName : interceptorPackages){ - - // Scan all Interceptor - classes = classReader.getClass(packageName, Interceptor.class, false); - if(CollectionKit.isNotEmpty(classes)){ - for(Class interceptorClazz : classes){ - addInterceptor(interceptorClazz); - } - } - } - } - - /** - * Build Route - * - * @param routePackages route packets to add - */ - private void buildRoute(String... routePackages){ - Set> classes = null; - // Traverse route - for(String packageName : routePackages){ - // Scan all Controoler - classes = classReader.getClassByAnnotation(packageName, Controller.class, true); - if(CollectionKit.isNotEmpty(classes)){ - for(Class pathClazz : classes){ - addRouter(pathClazz); - } - } - } - - } - - /** - * Parse Interceptor - * - * @param interceptor resolve the interceptor class - */ - public void addInterceptor(final Class interceptor){ - - boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); - - if(null == interceptor || !hasInterface){ - return; - } - -// ioc.addBean(interceptor); - - Intercept intercept = interceptor.getAnnotation(Intercept.class); - String partten = "/.*"; - if(null != intercept){ - partten = intercept.value(); - } - - try { - Method before = interceptor.getMethod("before", Request.class, Response.class); - Method after = interceptor.getMethod("after", Request.class, Response.class); - buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); - buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - - } - - /** - * Parse all routing in a controller - * - * @param controller resolve the routing class - */ - public void addRouter(final Class router){ - - Method[] methods = router.getMethods(); - if(null == methods || methods.length == 0){ - return; - } - - final String nameSpace = router.getAnnotation(Controller.class).value(); - - final String suffix = router.getAnnotation(Controller.class).suffix(); - - for (Method method : methods) { - Route mapping = method.getAnnotation(Route.class); - //route method - if (null != mapping) { - // build multiple route - HttpMethod methodType = mapping.method(); - String[] paths = mapping.value(); - if(null != paths && paths.length > 0){ - for(String value : paths){ - String pathV = getRoutePath(value, nameSpace, suffix); - buildRoute(router, method, pathV, methodType); - } - } - } - } - } - - private String getRoutePath(String value, String nameSpace, String suffix){ - String path = value.startsWith("/") ? value : "/" + value; - - nameSpace = nameSpace.startsWith("/") ? nameSpace : "/" + nameSpace; - path = nameSpace + path; - - path = path.replaceAll("[/]+", "/"); - - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - - path = path + suffix; - - return path; - } - - /** - * Build a route - * - * @param target route target execution class - * @param execMethod route execution method - * @param path route path - * @param method route httpmethod - */ - private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - - /** - * Build a route - * - * @param path route path - * @param target route target execution class - * @param execMethod route execution method - * @param method route httpmethod - */ - private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import java.lang.reflect.Method; +import java.util.Set; + +import com.blade.Blade; +import com.blade.annotation.Controller; +import com.blade.annotation.Intercept; +import com.blade.annotation.Route; +import com.blade.context.DynamicClassReader; +import com.blade.interceptor.Interceptor; +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * Route builder + * + * @author biezhi + * @since 1.0 + */ +public class RouteBuilder { + + /** + * Class reader, used to scan the class specified in the rules + */ + private ClassReader classReader; + + private Routers routers; + + private String[] routePackages; + + private String interceptorPackage; + + public RouteBuilder(Routers routers) { + this.routers = routers; + this.classReader = DynamicClassReader.getClassReader(); + } + + /** + * Start building route + */ + public void building() { + + this.routePackages = Blade.$().config().getRoutePackages(); + this.interceptorPackage = Blade.$().config().getInterceptorPackage(); + + // Route + if(null != routePackages && routePackages.length > 0){ + this.buildRoute(routePackages); + } + + // Inteceptor + if(StringKit.isNotBlank(interceptorPackage)){ + this.buildInterceptor(interceptorPackage); + } + + } + + /** + * Build interceptor + * + * @param interceptorPackages add the interceptor package + */ + private void buildInterceptor(String... interceptorPackages){ + + // Scan all Interceptor + Set classes = null; + + // Traversal Interceptor + for(String packageName : interceptorPackages){ + + // Scan all Interceptor + classes = classReader.getClass(packageName, Interceptor.class, false); + if(CollectionKit.isNotEmpty(classes)){ + for(ClassInfo classInfo : classes){ + Class interceptorClazz = classInfo.getClazz(); + addInterceptor(interceptorClazz); + } + } + } + } + + /** + * Build Route + * + * @param routePackages route packets to add + */ + private void buildRoute(String... routePackages){ + Set classes = null; + // Traverse route + for(String packageName : routePackages){ + // Scan all Controoler + classes = classReader.getClassByAnnotation(packageName, Controller.class, true); + if(CollectionKit.isNotEmpty(classes)){ + for(ClassInfo classInfo : classes){ + Class pathClazz = classInfo.getClazz(); + addRouter(pathClazz); + } + } + } + + } + + /** + * Parse Interceptor + * + * @param interceptor resolve the interceptor class + */ + public void addInterceptor(final Class interceptor){ + + boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); + + if(null == interceptor || !hasInterface){ + return; + } + +// ioc.addBean(interceptor); + + Intercept intercept = interceptor.getAnnotation(Intercept.class); + String partten = "/.*"; + if(null != intercept){ + partten = intercept.value(); + } + + try { + Method before = interceptor.getMethod("before", Request.class, Response.class); + Method after = interceptor.getMethod("after", Request.class, Response.class); + buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); + buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + + } + + /** + * Parse all routing in a controller + * + * @param controller resolve the routing class + */ + public void addRouter(final Class router){ + + Method[] methods = router.getMethods(); + if(null == methods || methods.length == 0){ + return; + } + + final String nameSpace = router.getAnnotation(Controller.class).value(); + + final String suffix = router.getAnnotation(Controller.class).suffix(); + + for (Method method : methods) { + Route mapping = method.getAnnotation(Route.class); + //route method + if (null != mapping) { + // build multiple route + HttpMethod methodType = mapping.method(); + String[] paths = mapping.value(); + if(null != paths && paths.length > 0){ + for(String value : paths){ + String pathV = getRoutePath(value, nameSpace, suffix); + buildRoute(router, method, pathV, methodType); + } + } + } + } + } + + private String getRoutePath(String value, String nameSpace, String suffix){ + String path = value.startsWith("/") ? value : "/" + value; + + nameSpace = nameSpace.startsWith("/") ? nameSpace : "/" + nameSpace; + path = nameSpace + path; + + path = path.replaceAll("[/]+", "/"); + + path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + + path = path + suffix; + + return path; + } + + /** + * Build a route + * + * @param target route target execution class + * @param execMethod route execution method + * @param path route path + * @param method route httpmethod + */ + private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + + /** + * Build a route + * + * @param path route path + * @param target route target execution class + * @param execMethod route execution method + * @param method route httpmethod + */ + private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index e972eea50..36aba1b42 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -31,9 +31,9 @@ import com.blade.Bootstrap; import com.blade.context.ApplicationContext; import com.blade.context.ApplicationWebContext; +import com.blade.context.DynamicClassReader; import com.blade.kit.StringKit; import com.blade.kit.SystemKit; -import com.blade.kit.resource.DynamicClassReader; /** * Blade Core DispatcherServlet diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index 14e24bf78..207801348 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -1,53 +1,59 @@ - - - 4.0.0 - - com.bladejava - blade - 1.0 - - - blade-kit - jar - ${blade-kit.version} - blade-kit - https://github.com/biezhi/blade/tree/master/blade-kit - - - - - org.slf4j - slf4j-api - - - - junit - junit - - - - dom4j - dom4j - 1.6.1 - provided - - - - jaxen - jaxen - 1.1.6 - provided - - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - - - + + + 4.0.0 + + com.bladejava + blade + 1.0 + + + blade-kit + jar + ${blade-kit.version} + blade-kit + https://github.com/biezhi/blade/tree/master/blade-kit + + + + + org.slf4j + slf4j-api + + + + junit + junit + + + + org.ow2.asm + asm + 5.1 + + + + dom4j + dom4j + 1.6.1 + provided + + + + jaxen + jaxen + 1.1.6 + provided + + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + + + diff --git a/blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java b/blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java index 0f6b3750d..c6c4b3b3b 100644 --- a/blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java @@ -1,166 +1,185 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.net.URL; -import java.net.URLDecoder; -import java.util.Enumeration; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.kit.Assert; -import com.blade.kit.CollectionKit; - -/** - * 抽象类读取器 - * - * @author biezhi - * @since 1.0 - */ -public abstract class AbstractClassReader implements ClassReader { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractClassReader.class); - - @Override - public Set> getClass(String packageName, boolean recursive) { - return this.getClassByAnnotation(packageName, null, null, recursive); - } - - /** - * 默认实现以文件形式的读取 - */ - @Override - public Set> getClass(String packageName, Class parent, boolean recursive) { - return this.getClassByAnnotation(packageName, parent, null, recursive); - } - - /** - * 根据条件获取class - * @param packageName - * @param packagePath - * @param parent - * @param annotation - * @param recursive - * @return - */ - private Set> findClassByPackage(final String packageName, final String packagePath, final Class parent, final Class annotation, final boolean recursive, Set> classes) { - // 获取此包的目录 建立一个File - File dir = new File(packagePath); - // 如果不存在或者 也不是目录就直接返回 - if ((!dir.exists()) || (!dir.isDirectory())) { - LOGGER.warn("The package [{}] not found.", packageName); - } - // 如果存在 就获取包下的所有文件 包括目录 - File[] dirfiles = accept(dir, recursive); - // 循环所有文件 - if(null != dirfiles && dirfiles.length > 0){ - for (File file : dirfiles) { - // 如果是目录 则继续扫描 - if (file.isDirectory()) { - findClassByPackage(packageName + "." + file.getName(), file.getAbsolutePath(), parent, annotation, recursive, classes); - } else { - // 如果是java类文件 去掉后面的.class 只留下类名 - String className = file.getName().substring(0, file.getName().length() - 6); - try { - Class clazz = Class.forName(packageName + '.' + className); - if(null != parent && null != annotation){ - if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent) && - null != clazz.getAnnotation(annotation)){ - classes.add(clazz); - } - continue; - } - if(null != parent){ - if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent)){ - classes.add(clazz); - } else { - if(null != clazz.getInterfaces() && clazz.getInterfaces().length > 0 && clazz.getInterfaces()[0].equals(parent)){ - classes.add(clazz); - } - } - continue; - } - if(null != annotation){ - if(null != clazz.getAnnotation(annotation)){ - classes.add(clazz); - } - continue; - } - classes.add(clazz); - } catch (ClassNotFoundException e) { - LOGGER.error("在扫描用户定义视图时从jar包获取文件出错,找不到.class类文件:" + e.getMessage()); - } - } - } - } - return classes; - } - - /** - * 过滤文件规则 - * @param file - * @param recursive - * @return - */ - private File[] accept(File file, final boolean recursive){ - File[] dirfiles = file.listFiles(new FileFilter() { - // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件) - public boolean accept(File file) { - return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")); - } - }); - return dirfiles; - } - - @Override - public Set> getClassByAnnotation(String packageName, Class annotation, boolean recursive) { - return this.getClassByAnnotation(packageName, null, annotation, recursive); - } - - @Override - public Set> getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive) { - Assert.notBlank(packageName); - Set> classes = CollectionKit.newHashSet(); - // 获取包的名字 并进行替换 - String packageDirName = packageName.replace('.', '/'); - // 定义一个枚举的集合 并进行循环来处理这个目录下的URL - Enumeration dirs; - try { - dirs = getClass().getClassLoader().getResources(packageDirName); - // 循环迭代下去 - while (dirs.hasMoreElements()) { - // 获取下一个元素 - URL url = dirs.nextElement(); - // 获取包的物理路径 - String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); - Set> subClasses = findClassByPackage(packageName, filePath, parent, annotation, recursive, classes); - if(subClasses.size() > 0){ - classes.addAll(subClasses); - } - } - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return classes; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; + +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.net.URL; +import java.net.URLDecoder; +import java.util.Enumeration; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.kit.CollectionKit; +import com.blade.kit.exception.ClassReaderException; + +/** + * 抽象类读取器 + * + * @author biezhi + * @since 1.0 + */ +public abstract class AbstractClassReader implements ClassReader { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractClassReader.class); + + protected BladeClassLoader classLoader; + + @Override + public BladeClassLoader getClassLoader() { + return classLoader; + } + + public AbstractClassReader(BladeClassLoader classLoader) { + if(null == classLoader){ + this.classLoader = this.getClassLoader(); + } else{ + this.classLoader = classLoader; + } + } + + @Override + public Set getClass(String packageName, boolean recursive) { + return this.getClassByAnnotation(packageName, null, null, recursive); + } + + /** + * 默认实现以文件形式的读取 + */ + @Override + public Set getClass(String packageName, Class parent, boolean recursive) { + return this.getClassByAnnotation(packageName, parent, null, recursive); + } + + /** + * 根据条件获取class + * @param packageName + * @param packagePath + * @param parent + * @param annotation + * @param recursive + * @return + */ + private Set findClassByPackage(final String packageName, final String packagePath, + final Class parent, final Class annotation, + final boolean recursive, Set classes) throws ClassNotFoundException { + + // 获取此包的目录 建立一个File + File dir = new File(packagePath); + // 如果不存在或者 也不是目录就直接返回 + if ((!dir.exists()) || (!dir.isDirectory())) { + LOGGER.warn("The package [{}] not found.", packageName); + } + // 如果存在 就获取包下的所有文件 包括目录 + File[] dirfiles = accept(dir, recursive); + // 循环所有文件 + if(null != dirfiles && dirfiles.length > 0){ + for (File file : dirfiles) { + // 如果是目录 则继续扫描 + if (file.isDirectory()) { + findClassByPackage(packageName + "." + file.getName(), file.getAbsolutePath(), parent, annotation, recursive, classes); + } else { + // 如果是java类文件 去掉后面的.class 只留下类名 + String className = file.getName().substring(0, file.getName().length() - 6); + Class clazz = classLoader.defineClassByName(packageName + '.' + className); +// Class clazz = Class.forName(packageName + '.' + className); + if(null != parent && null != annotation){ + if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent) && + null != clazz.getAnnotation(annotation)){ + classes.add(new ClassInfo(clazz)); + } + continue; + } + if(null != parent){ + if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent)){ + classes.add(new ClassInfo(clazz)); + } else { + if(null != clazz.getInterfaces() && clazz.getInterfaces().length > 0 && clazz.getInterfaces()[0].equals(parent)){ + classes.add(new ClassInfo(clazz)); + } + } + continue; + } + if(null != annotation){ + if(null != clazz.getAnnotation(annotation)){ + classes.add(new ClassInfo(clazz)); + } + continue; + } + classes.add(new ClassInfo(clazz)); + } + } + } + return classes; + } + + /** + * 过滤文件规则 + * @param file + * @param recursive + * @return + */ + private File[] accept(File file, final boolean recursive){ + File[] dirfiles = file.listFiles(new FileFilter() { + // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件) + public boolean accept(File file) { + return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")); + } + }); + return dirfiles; + } + + @Override + public Set getClassByAnnotation(String packageName, Class annotation, boolean recursive) { + return this.getClassByAnnotation(packageName, null, annotation, recursive); + } + + @Override + public Set getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive) { + Assert.notBlank(packageName); + Set classes = CollectionKit.newHashSet(); + // 获取包的名字 并进行替换 + String packageDirName = packageName.replace('.', '/'); + // 定义一个枚举的集合 并进行循环来处理这个目录下的URL + Enumeration dirs; + try { + dirs = classLoader.getResources(packageDirName); + // 循环迭代下去 + while (dirs.hasMoreElements()) { + // 获取下一个元素 + URL url = dirs.nextElement(); + // 获取包的物理路径 + String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); + Set subClasses = findClassByPackage(packageName, filePath, parent, annotation, recursive, classes); + if(subClasses.size() > 0){ + classes.addAll(subClasses); + } + } + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } catch (ClassNotFoundException e) { + LOGGER.error("Add user custom view class error Can't find such Class files."); + throw new ClassReaderException(e); + } + return classes; + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/com/blade/kit/resource/BladeClassLoader.java b/blade-kit/src/main/java/com/blade/kit/resource/BladeClassLoader.java new file mode 100644 index 000000000..5168ddbde --- /dev/null +++ b/blade-kit/src/main/java/com/blade/kit/resource/BladeClassLoader.java @@ -0,0 +1,12 @@ +package com.blade.kit.resource; + +public class BladeClassLoader extends ClassLoader { + + public BladeClassLoader() { + } + + public Class defineClassByName(String name) throws ClassNotFoundException{ + return Class.forName(name); + } + +} diff --git a/blade-kit/src/main/java/com/blade/kit/resource/ClassInfo.java b/blade-kit/src/main/java/com/blade/kit/resource/ClassInfo.java new file mode 100644 index 000000000..a4f15d319 --- /dev/null +++ b/blade-kit/src/main/java/com/blade/kit/resource/ClassInfo.java @@ -0,0 +1,30 @@ +package com.blade.kit.resource; + +public class ClassInfo { + + private String className; + private Class clazz; + + public ClassInfo(String className) { + this.className = className; + } + + public ClassInfo(Class clazz) { + this.clazz = clazz; + this.className = clazz.getName(); + } + + public ClassInfo(String className, Class clazz) { + this.clazz = clazz; + this.className = className; + } + + public String getClassName() { + return className; + } + + public Class getClazz() { + return clazz; + } + +} diff --git a/blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java b/blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java index 144398ed4..3d45e61da 100644 --- a/blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java @@ -1,26 +1,30 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; - -/** - * 根据classpath加载类 - * - * @author biezhi - * @since 1.0 - */ -public class ClassPathClassReader extends AbstractClassReader implements ClassReader { - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; + +/** + * 根据classpath加载类 + * + * @author biezhi + * @since 1.0 + */ +public class ClassPathClassReader extends AbstractClassReader implements ClassReader { + + public ClassPathClassReader(BladeClassLoader classLoader) { + super(classLoader); + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java b/blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java index ca5ff8ead..f9e39b290 100644 --- a/blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java @@ -1,37 +1,39 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; - -import java.lang.annotation.Annotation; -import java.util.Set; - -/** - * 一个类读取器的接口 - * - * @author biezhi - * @since 1.0 - */ -public interface ClassReader { - - public Set> getClass(String packageName, boolean recursive); - - public Set> getClass(String packageName, Class parent, boolean recursive); - - public Set> getClassByAnnotation(String packageName, Class annotation, boolean recursive); - - public Set> getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive); - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; + +import java.lang.annotation.Annotation; +import java.util.Set; + +/** + * 一个类读取器的接口 + * + * @author biezhi + * @since 1.0 + */ +public interface ClassReader { + + Set getClass(String packageName, boolean recursive); + + Set getClass(String packageName, Class parent, boolean recursive); + + Set getClassByAnnotation(String packageName, Class annotation, boolean recursive); + + Set getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive); + + BladeClassLoader getClassLoader(); + } \ No newline at end of file diff --git a/blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java b/blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java index dc62dd2b4..25ed301f2 100644 --- a/blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java @@ -1,156 +1,158 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; - -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.net.JarURLConnection; -import java.net.URL; -import java.util.Enumeration; -import java.util.Set; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.kit.Assert; -import com.blade.kit.CollectionKit; -import com.blade.kit.exception.ClassReaderException; - -/** - * 根据jar文件读取类 - * - * @author biezhi - * @since 1.0 - */ -public class JarReaderImpl extends AbstractClassReader implements ClassReader { - - private static final Logger LOGGER = LoggerFactory.getLogger(JarReaderImpl.class); - - @Override - public Set> getClass(String packageName, boolean recursive) { - return this.getClassByAnnotation(packageName, null, null, recursive); - } - - @Override - public Set> getClass(String packageName, Class parent, boolean recursive) { - return this.getClassByAnnotation(packageName, parent, null, recursive); - } - - @Override - public Set> getClassByAnnotation(String packageName, Class annotation, boolean recursive) { - return this.getClassByAnnotation(packageName, null, annotation, recursive); - } - - @Override - public Set> getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive) { - Assert.notBlank(packageName); - Set> classes = CollectionKit.newHashSet(); - // 获取包的名字 并进行替换 - String packageDirName = packageName.replace('.', '/'); - // 定义一个枚举的集合 并进行循环来处理这个目录下的URL - Enumeration dirs; - try { - dirs = getClass().getClassLoader().getResources(packageDirName); - // 循环迭代下去 - while (dirs.hasMoreElements()) { - // 获取下一个元素 - URL url = dirs.nextElement(); - Set> subClasses = this.getClasses(url, packageDirName, packageName, parent, annotation, recursive, classes); - if(subClasses.size() > 0){ - classes.addAll(subClasses); - } - } - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return classes; - } - - private Set> getClasses(final URL url, final String packageDirName, String packageName, final Class parent, - final Class annotation, final boolean recursive, Set> classes){ - try { - if( url.toString( ).startsWith( "jar:file:" ) || url.toString( ).startsWith( "wsjar:file:" ) ) { - - // 获取jar - JarFile jarFile = ( (JarURLConnection)url.openConnection() ).getJarFile( ); - - // 从此jar包 得到一个枚举类 - Enumeration eje = jarFile.entries( ); - - // 同样的进行循环迭代 - while (eje.hasMoreElements()) { - // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 - JarEntry entry = eje.nextElement(); - String name = entry.getName(); - // 如果是以/开头的 - if (name.charAt(0) == '/') { - // 获取后面的字符串 - name = name.substring(1); - } - // 如果前半部分和定义的包名相同 - if (name.startsWith(packageDirName)) { - int idx = name.lastIndexOf('/'); - // 如果以"/"结尾 是一个包 - if (idx != -1) { - // 获取包名 把"/"替换成"." - packageName = name.substring(0, idx).replace('/', '.'); - } - // 如果可以迭代下去 并且是一个包 - if ((idx != -1) || recursive) { - // 如果是一个.class文件 而且不是目录 - if (name.endsWith(".class") && !entry.isDirectory()) { - // 去掉后面的".class" 获取真正的类名 - String className = name.substring(packageName.length() + 1, name.length() - 6); - try { - // 添加到classes - Class clazz = Class.forName(packageName + '.' + className); - if(null != parent && null != annotation){ - if(null != clazz.getSuperclass() && - clazz.getSuperclass().equals(parent) && null != clazz.getAnnotation(annotation)){ - classes.add(clazz); - } - continue; - } - if(null != parent){ - if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent)){ - classes.add(clazz); - } - continue; - } - if(null != annotation){ - if(null != clazz.getAnnotation(annotation)){ - classes.add(clazz); - } - continue; - } - classes.add(clazz); - } catch (ClassNotFoundException e) { - LOGGER.error("Add user custom view class error Can't find such Class files."); - throw new ClassReaderException(e); - } - } - } - } - } - } - } catch (IOException e) { - LOGGER.error("The scan error when the user to define the view from a jar package file.", e); - } - return classes; - } +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.net.JarURLConnection; +import java.net.URL; +import java.util.Enumeration; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.kit.CollectionKit; + +/** + * 根据jar文件读取类 + * + * @author biezhi + * @since 1.0 + */ +public class JarReaderImpl extends AbstractClassReader implements ClassReader { + + private static final Logger LOGGER = LoggerFactory.getLogger(JarReaderImpl.class); + + public JarReaderImpl(BladeClassLoader classLoader) { + super(classLoader); + } + + @Override + public Set getClass(String packageName, boolean recursive) { + return this.getClassByAnnotation(packageName, null, null, recursive); + } + + @Override + public Set getClass(String packageName, Class parent, boolean recursive) { + return this.getClassByAnnotation(packageName, parent, null, recursive); + } + + @Override + public Set getClassByAnnotation(String packageName, Class annotation, boolean recursive) { + return this.getClassByAnnotation(packageName, null, annotation, recursive); + } + + @Override + public Set getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive) { + Assert.notBlank(packageName); + Set classes = CollectionKit.newHashSet(); + // 获取包的名字 并进行替换 + String packageDirName = packageName.replace('.', '/'); + // 定义一个枚举的集合 并进行循环来处理这个目录下的URL + Enumeration dirs; + try { + dirs = classLoader.getResources(packageDirName); + // 循环迭代下去 + while (dirs.hasMoreElements()) { + // 获取下一个元素 + URL url = dirs.nextElement(); + Set subClasses = this.getClasses(url, packageDirName, packageName, parent, annotation, recursive, classes); + if(subClasses.size() > 0){ + classes.addAll(subClasses); + } + } + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return classes; + } + + private Set getClasses(final URL url, final String packageDirName, String packageName, final Class parent, + final Class annotation, final boolean recursive, Set classes){ + try { + if( url.toString().startsWith( "jar:file:" ) || url.toString().startsWith( "wsjar:file:" ) ) { + + // 获取jar + JarFile jarFile = ( (JarURLConnection)url.openConnection() ).getJarFile(); + + // 从此jar包 得到一个枚举类 + Enumeration eje = jarFile.entries(); + + // 同样的进行循环迭代 + while (eje.hasMoreElements()) { + // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 + JarEntry entry = eje.nextElement(); + String name = entry.getName(); + // 如果是以/开头的 + if (name.charAt(0) == '/') { + // 获取后面的字符串 + name = name.substring(1); + } + // 如果前半部分和定义的包名相同 + if (name.startsWith(packageDirName)) { + int idx = name.lastIndexOf('/'); + // 如果以"/"结尾 是一个包 + if (idx != -1) { + // 获取包名 把"/"替换成"." + packageName = name.substring(0, idx).replace('/', '.'); + } + // 如果可以迭代下去 并且是一个包 + if ((idx != -1) || recursive) { + // 如果是一个.class文件 而且不是目录 + if (name.endsWith(".class") && !entry.isDirectory()) { + // 去掉后面的".class" 获取真正的类名 + String className = name.substring(packageName.length() + 1, name.length() - 6); + // 添加到classes +// Class clazz = Class.forName(packageName + '.' + className); + Class clazz = classLoader.defineClassByName(packageName + '.' + className); + if(null != parent && null != annotation){ + if(null != clazz.getSuperclass() && + clazz.getSuperclass().equals(parent) && null != clazz.getAnnotation(annotation)){ + classes.add(new ClassInfo(clazz)); + } + continue; + } + if(null != parent){ + if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent)){ + classes.add(new ClassInfo(clazz)); + } + continue; + } + if(null != annotation){ + if(null != clazz.getAnnotation(annotation)){ + classes.add(new ClassInfo(clazz)); + } + continue; + } + classes.add(new ClassInfo(clazz)); + } + } + } + } + } + } catch (IOException e) { + LOGGER.error("The scan error when the user to define the view from a jar package file.", e); + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return classes; + } } \ No newline at end of file From abd7414d0a690f3e44fd014af8b4d73bdc3b13f6 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 31 Aug 2016 17:28:50 +0800 Subject: [PATCH 465/545] add aop code --- blade-aop/pom.xml | 36 + .../blade/aop/AbstractMethodInterceptor.java | 40 + .../main/java/com/blade/aop/Invocaction.java | 33 + .../main/java/com/blade/aop/ProxyFactory.java | 68 + .../main/java/com/blade/aop/ProxyIocImpl.java | 22 + .../java/com/blade/aop/annotation/Aop.java | 20 + .../main/java/com/blade/plugin/AopPlugin.java | 24 + .../java/net/sf/cglib/beans/BeanCopier.java | 176 +++ .../net/sf/cglib/beans/BeanGenerator.java | 149 ++ .../main/java/net/sf/cglib/beans/BeanMap.java | 320 ++++ .../net/sf/cglib/beans/BeanMapEmitter.java | 192 +++ .../java/net/sf/cglib/beans/BulkBean.java | 142 ++ .../net/sf/cglib/beans/BulkBeanEmitter.java | 156 ++ .../net/sf/cglib/beans/BulkBeanException.java | 43 + .../java/net/sf/cglib/beans/FixedKeySet.java | 36 + .../net/sf/cglib/beans/ImmutableBean.java | 128 ++ .../sf/cglib/core/AbstractClassGenerator.java | 353 +++++ .../main/java/net/sf/cglib/core/Block.java | 49 + .../java/net/sf/cglib/core/ClassEmitter.java | 282 ++++ .../net/sf/cglib/core/ClassGenerator.java | 22 + .../java/net/sf/cglib/core/ClassInfo.java | 47 + .../net/sf/cglib/core/ClassNameReader.java | 63 + .../java/net/sf/cglib/core/ClassesKey.java | 46 + .../java/net/sf/cglib/core/CodeEmitter.java | 864 +++++++++++ .../cglib/core/CodeGenerationException.java | 32 + .../net/sf/cglib/core/CollectionUtils.java | 76 + .../java/net/sf/cglib/core/Constants.java | 68 + .../java/net/sf/cglib/core/Converter.java | 20 + .../java/net/sf/cglib/core/Customizer.java | 28 + .../sf/cglib/core/DebuggingClassWriter.java | 114 ++ .../cglib/core/DefaultGeneratorStrategy.java | 47 + .../sf/cglib/core/DefaultNamingPolicy.java | 71 + .../sf/cglib/core/DuplicatesPredicate.java | 27 + .../java/net/sf/cglib/core/EmitUtils.java | 960 ++++++++++++ .../sf/cglib/core/FieldTypeCustomizer.java | 23 + .../net/sf/cglib/core/GeneratorStrategy.java | 44 + .../net/sf/cglib/core/HashCodeCustomizer.java | 12 + .../java/net/sf/cglib/core/KeyFactory.java | 346 +++++ .../sf/cglib/core/KeyFactoryCustomizer.java | 7 + .../main/java/net/sf/cglib/core/Local.java | 37 + .../sf/cglib/core/LocalVariablesSorter.java | 158 ++ .../java/net/sf/cglib/core/MethodInfo.java | 47 + .../sf/cglib/core/MethodInfoTransformer.java | 37 + .../java/net/sf/cglib/core/MethodWrapper.java | 46 + .../java/net/sf/cglib/core/NamingPolicy.java | 43 + .../sf/cglib/core/ObjectSwitchCallback.java | 24 + .../java/net/sf/cglib/core/Predicate.java | 21 + .../sf/cglib/core/ProcessArrayCallback.java | 22 + .../sf/cglib/core/ProcessSwitchCallback.java | 23 + .../java/net/sf/cglib/core/ReflectUtils.java | 492 ++++++ .../cglib/core/RejectModifierPredicate.java | 30 + .../java/net/sf/cglib/core/Signature.java | 73 + .../java/net/sf/cglib/core/TinyBitSet.java | 78 + .../java/net/sf/cglib/core/Transformer.java | 20 + .../java/net/sf/cglib/core/TypeUtils.java | 421 ++++++ .../sf/cglib/core/VisibilityPredicate.java | 52 + .../java/net/sf/cglib/core/WeakCacheKey.java | 42 + .../core/internal/CustomizerRegistry.java | 48 + .../net/sf/cglib/core/internal/Function.java | 5 + .../sf/cglib/core/internal/LoadingCache.java | 86 ++ .../sf/cglib/proxy/BridgeMethodResolver.java | 114 ++ .../java/net/sf/cglib/proxy/Callback.java | 29 + .../net/sf/cglib/proxy/CallbackFilter.java | 46 + .../net/sf/cglib/proxy/CallbackGenerator.java | 36 + .../net/sf/cglib/proxy/CallbackHelper.java | 98 ++ .../java/net/sf/cglib/proxy/CallbackInfo.java | 116 ++ .../java/net/sf/cglib/proxy/Dispatcher.java | 30 + .../sf/cglib/proxy/DispatcherGenerator.java | 65 + .../java/net/sf/cglib/proxy/Enhancer.java | 1315 +++++++++++++++++ .../main/java/net/sf/cglib/proxy/Factory.java | 79 + .../java/net/sf/cglib/proxy/FixedValue.java | 35 + .../sf/cglib/proxy/FixedValueGenerator.java | 42 + .../net/sf/cglib/proxy/InterfaceMaker.java | 118 ++ .../net/sf/cglib/proxy/InvocationHandler.java | 35 + .../proxy/InvocationHandlerGenerator.java | 64 + .../java/net/sf/cglib/proxy/LazyLoader.java | 30 + .../sf/cglib/proxy/LazyLoaderGenerator.java | 88 ++ .../net/sf/cglib/proxy/MethodInterceptor.java | 42 + .../proxy/MethodInterceptorGenerator.java | 239 +++ .../java/net/sf/cglib/proxy/MethodProxy.java | 233 +++ .../main/java/net/sf/cglib/proxy/Mixin.java | 242 +++ .../net/sf/cglib/proxy/MixinBeanEmitter.java | 38 + .../java/net/sf/cglib/proxy/MixinEmitter.java | 93 ++ .../cglib/proxy/MixinEverythingEmitter.java | 49 + .../main/java/net/sf/cglib/proxy/NoOp.java | 28 + .../net/sf/cglib/proxy/NoOpGenerator.java | 44 + .../main/java/net/sf/cglib/proxy/Proxy.java | 101 ++ .../sf/cglib/proxy/ProxyRefDispatcher.java | 31 + .../proxy/UndeclaredThrowableException.java | 36 + .../sf/cglib/reflect/ConstructorDelegate.java | 123 ++ .../java/net/sf/cglib/reflect/FastClass.java | 207 +++ .../sf/cglib/reflect/FastClassEmitter.java | 226 +++ .../net/sf/cglib/reflect/FastConstructor.java | 46 + .../java/net/sf/cglib/reflect/FastMember.java | 65 + .../java/net/sf/cglib/reflect/FastMethod.java | 63 + .../net/sf/cglib/reflect/MethodDelegate.java | 268 ++++ .../sf/cglib/reflect/MulticastDelegate.java | 179 +++ .../AbstractClassFilterTransformer.java | 85 ++ .../cglib/transform/AbstractClassLoader.java | 118 ++ .../transform/AbstractClassTransformer.java | 29 + .../cglib/transform/AnnotationVisitorTee.java | 61 + .../transform/ClassEmitterTransformer.java | 21 + .../net/sf/cglib/transform/ClassFilter.java | 27 + .../transform/ClassFilterTransformer.java | 31 + .../cglib/transform/ClassReaderGenerator.java | 41 + .../sf/cglib/transform/ClassTransformer.java | 29 + .../transform/ClassTransformerChain.java | 56 + .../transform/ClassTransformerFactory.java | 20 + .../cglib/transform/ClassTransformerTee.java | 32 + .../sf/cglib/transform/ClassVisitorTee.java | 103 ++ .../sf/cglib/transform/FieldVisitorTee.java | 53 + .../net/sf/cglib/transform/MethodFilter.java | 23 + .../transform/MethodFilterTransformer.java | 43 + .../sf/cglib/transform/MethodVisitorTee.java | 187 +++ .../transform/TransformingClassGenerator.java | 35 + .../transform/TransformingClassLoader.java | 34 + .../impl/AbstractInterceptFieldCallback.java | 42 + .../impl/AccessFieldTransformer.java | 64 + .../impl/AddDelegateTransformer.java | 119 ++ .../transform/impl/AddInitTransformer.java | 63 + .../impl/AddPropertyTransformer.java | 47 + .../impl/AddStaticInitTransformer.java | 49 + .../cglib/transform/impl/FieldProvider.java | 34 + .../impl/FieldProviderTransformer.java | 208 +++ .../impl/InterceptFieldCallback.java | 42 + .../transform/impl/InterceptFieldEnabled.java | 21 + .../transform/impl/InterceptFieldFilter.java | 23 + .../impl/InterceptFieldTransformer.java | 210 +++ .../impl/UndeclaredThrowableStrategy.java | 61 + .../impl/UndeclaredThrowableTransformer.java | 60 + .../net/sf/cglib/util/ParallelSorter.java | 294 ++++ .../sf/cglib/util/ParallelSorterEmitter.java | 100 ++ .../net/sf/cglib/util/SorterTemplate.java | 173 +++ .../net/sf/cglib/util/StringSwitcher.java | 154 ++ blade-core/pom.xml | 10 +- blade-core/src/main/java/com/blade/Blade.java | 13 +- .../src/main/java/com/blade/aop/Aop.java | 36 - .../main/java/com/blade/aop/AopConfig.java | 22 - .../main/java/com/blade/aop/Invocaction.java | 33 - .../src/main/java/com/blade/aop/Log.java | 13 - .../java/com/blade/aop/LogClassVisitor.java | 20 - .../java/com/blade/aop/LogMethodVisitor.java | 29 - .../java/com/blade/aop/MethodInterceptor.java | 9 - .../java/com/blade/aop/ProxyClassLoader.java | 33 - .../blade}/asm/AnnotationVisitor.java | 2 +- .../blade}/asm/AnnotationWriter.java | 2 +- .../src/main/java/com/blade/asm/AsmKit.java | 30 +- .../blade}/asm/Attribute.java | 2 +- .../blade}/asm/ByteVector.java | 2 +- .../blade}/asm/ClassReader.java | 2 +- .../blade}/asm/ClassVisitor.java | 2 +- .../blade}/asm/ClassWriter.java | 2 +- .../objectweb => com/blade}/asm/Context.java | 2 +- .../objectweb => com/blade}/asm/Edge.java | 2 +- .../blade}/asm/FieldVisitor.java | 2 +- .../blade}/asm/FieldWriter.java | 2 +- .../objectweb => com/blade}/asm/Frame.java | 2 +- .../objectweb => com/blade}/asm/Handle.java | 2 +- .../objectweb => com/blade}/asm/Handler.java | 2 +- .../objectweb => com/blade}/asm/Item.java | 2 +- .../objectweb => com/blade}/asm/Label.java | 2 +- .../blade}/asm/MethodVisitor.java | 2 +- .../blade}/asm/MethodWriter.java | 2 +- .../objectweb => com/blade}/asm/Opcodes.java | 2 +- .../objectweb => com/blade}/asm/Type.java | 2 +- .../objectweb => com/blade}/asm/TypePath.java | 2 +- .../blade}/asm/TypeReference.java | 2 +- .../java/com/blade/config/ConfigLoader.java | 174 +-- .../com/blade/context/ApplicationContext.java | 78 +- .../com/blade/context/DynamicClassReader.java | 98 +- .../java/com/blade/ioc/IocApplication.java | 379 ++--- .../main/java/com/blade/ioc/SimpleIoc.java | 4 +- .../main/java/com/blade/plugin/Plugin.java | 4 +- .../main/java/com/blade/kit/Environment.java | 4 +- .../kit/resource/AbstractClassReader.java | 353 +++-- .../com/blade/kit/resource/ClassInfo.java | 68 +- .../kit/resource/ClassPathClassReader.java | 54 +- .../com/blade/kit/resource/ClassReader.java | 74 +- .../com/blade/kit/resource/JarReaderImpl.java | 309 ++-- pom.xml | 41 +- 180 files changed, 15325 insertions(+), 1083 deletions(-) create mode 100644 blade-aop/pom.xml create mode 100644 blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java create mode 100644 blade-aop/src/main/java/com/blade/aop/Invocaction.java create mode 100644 blade-aop/src/main/java/com/blade/aop/ProxyFactory.java create mode 100644 blade-aop/src/main/java/com/blade/aop/ProxyIocImpl.java create mode 100644 blade-aop/src/main/java/com/blade/aop/annotation/Aop.java create mode 100644 blade-aop/src/main/java/com/blade/plugin/AopPlugin.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/beans/BeanCopier.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/beans/BeanGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/beans/BeanMap.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/beans/BeanMapEmitter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/beans/BulkBean.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/beans/BulkBeanEmitter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/beans/BulkBeanException.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/beans/FixedKeySet.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/beans/ImmutableBean.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/AbstractClassGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/Block.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/ClassEmitter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/ClassGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/ClassInfo.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/ClassNameReader.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/ClassesKey.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/CodeEmitter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/CodeGenerationException.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/CollectionUtils.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/Constants.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/Converter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/Customizer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/DebuggingClassWriter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/DefaultGeneratorStrategy.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/DefaultNamingPolicy.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/DuplicatesPredicate.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/EmitUtils.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/FieldTypeCustomizer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/GeneratorStrategy.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/HashCodeCustomizer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/KeyFactory.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/KeyFactoryCustomizer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/Local.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/LocalVariablesSorter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/MethodInfo.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/MethodInfoTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/MethodWrapper.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/NamingPolicy.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/ObjectSwitchCallback.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/Predicate.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/ProcessArrayCallback.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/ProcessSwitchCallback.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/ReflectUtils.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/RejectModifierPredicate.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/Signature.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/TinyBitSet.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/Transformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/TypeUtils.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/VisibilityPredicate.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/WeakCacheKey.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/internal/CustomizerRegistry.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/internal/Function.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/core/internal/LoadingCache.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/BridgeMethodResolver.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/Callback.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/CallbackFilter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/CallbackGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/CallbackHelper.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/CallbackInfo.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/Dispatcher.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/DispatcherGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/Enhancer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/Factory.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/FixedValue.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/FixedValueGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/InterfaceMaker.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/InvocationHandler.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/InvocationHandlerGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/LazyLoader.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/LazyLoaderGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/MethodInterceptor.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/MethodInterceptorGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/MethodProxy.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/Mixin.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/MixinBeanEmitter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/MixinEmitter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/MixinEverythingEmitter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/NoOp.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/NoOpGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/Proxy.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/ProxyRefDispatcher.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/proxy/UndeclaredThrowableException.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/reflect/ConstructorDelegate.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/reflect/FastClass.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/reflect/FastClassEmitter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/reflect/FastConstructor.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/reflect/FastMember.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/reflect/FastMethod.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/reflect/MethodDelegate.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/reflect/MulticastDelegate.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassFilterTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassLoader.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/AnnotationVisitorTee.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/ClassEmitterTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/ClassFilter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/ClassFilterTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/ClassReaderGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerChain.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerFactory.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerTee.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/ClassVisitorTee.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/FieldVisitorTee.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/MethodFilter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/MethodFilterTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/MethodVisitorTee.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/TransformingClassGenerator.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/TransformingClassLoader.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/AbstractInterceptFieldCallback.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/AccessFieldTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/AddDelegateTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/AddInitTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/AddPropertyTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/AddStaticInitTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/FieldProvider.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/FieldProviderTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldCallback.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldEnabled.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldFilter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/UndeclaredThrowableStrategy.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/transform/impl/UndeclaredThrowableTransformer.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/util/ParallelSorter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/util/ParallelSorterEmitter.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/util/SorterTemplate.java create mode 100644 blade-aop/src/main/java/net/sf/cglib/util/StringSwitcher.java delete mode 100644 blade-core/src/main/java/com/blade/aop/Aop.java delete mode 100644 blade-core/src/main/java/com/blade/aop/AopConfig.java delete mode 100644 blade-core/src/main/java/com/blade/aop/Invocaction.java delete mode 100644 blade-core/src/main/java/com/blade/aop/Log.java delete mode 100644 blade-core/src/main/java/com/blade/aop/LogClassVisitor.java delete mode 100644 blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java delete mode 100644 blade-core/src/main/java/com/blade/aop/MethodInterceptor.java delete mode 100644 blade-core/src/main/java/com/blade/aop/ProxyClassLoader.java rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/AnnotationVisitor.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/AnnotationWriter.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/Attribute.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/ByteVector.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/ClassReader.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/ClassVisitor.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/ClassWriter.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/Context.java (96%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/Edge.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/FieldVisitor.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/FieldWriter.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/Frame.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/Handle.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/Handler.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/Item.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/Label.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/MethodVisitor.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/MethodWriter.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/Opcodes.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/Type.java (99%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/TypePath.java (96%) rename blade-core/src/main/java/{org/objectweb => com/blade}/asm/TypeReference.java (97%) diff --git a/blade-aop/pom.xml b/blade-aop/pom.xml new file mode 100644 index 000000000..0974d130e --- /dev/null +++ b/blade-aop/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + com.bladejava + blade + 1.0 + + blade-aop + ${blade-aop.version} + blade-aop + http://maven.apache.org + + + UTF-8 + + + + + org.slf4j + slf4j-api + + + com.bladejava + blade-core + ${blade-core.version} + + + junit + junit + test + + + diff --git a/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java b/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java new file mode 100644 index 000000000..8ebc025dd --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java @@ -0,0 +1,40 @@ +package com.blade.aop; + +import java.lang.reflect.Method; + +import com.blade.aop.annotation.Aop; + +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +public abstract class AbstractMethodInterceptor implements MethodInterceptor { + + public abstract Object doInvoke(Invocaction invocaction) throws Throwable; + + public void before(Invocaction invocaction) {} + + public void after(Invocaction invocaction) {} + + /** + * 切面逻辑 obj 代理对象实例 method 源对象的方法名 args 传递给方法的实际入参 proxyMethod + * 与源对象中的method相对应的代理对象中的方法 + */ + public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable { + // 执行源对象的method方法 + try { + String methodPrefix = method.getDeclaringClass().getAnnotation(Aop.class).methodPrefix(); + String methodName = method.getName(); + if(!"".equals(methodPrefix) && !methodName.startsWith(methodPrefix)){ + return proxy.invokeSuper(target, args); + } + Invocaction invocaction = new Invocaction(target, args, proxy); + before(invocaction); + Object returnValue = doInvoke(invocaction); + after(invocaction); + return returnValue; + } catch (Exception e) { + throw e; + } + } + +} diff --git a/blade-aop/src/main/java/com/blade/aop/Invocaction.java b/blade-aop/src/main/java/com/blade/aop/Invocaction.java new file mode 100644 index 000000000..c44c4559a --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/Invocaction.java @@ -0,0 +1,33 @@ +package com.blade.aop; + +import java.lang.reflect.InvocationTargetException; + +import net.sf.cglib.proxy.MethodProxy; + +public class Invocaction { + + private Object target; + private Object[] args; + private MethodProxy proxy; + + public Invocaction(Object target, Object[] args, MethodProxy proxy) { + this.target = target; + this.args = args; + this.proxy = proxy; + } + + public Object invoke() throws Throwable{ + try { + return proxy.invokeSuper(target, args); + } catch (IllegalAccessException e) { + throw e; + } catch (IllegalArgumentException e) { + throw e; + } catch (InvocationTargetException e) { + throw e; + } catch (Throwable e) { + throw e; + } + } + +} diff --git a/blade-aop/src/main/java/com/blade/aop/ProxyFactory.java b/blade-aop/src/main/java/com/blade/aop/ProxyFactory.java new file mode 100644 index 000000000..a3701975b --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/ProxyFactory.java @@ -0,0 +1,68 @@ +package com.blade.aop; + +import java.util.ArrayList; +import java.util.List; + +import com.blade.aop.annotation.Aop; +import com.blade.ioc.IocApplication; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.NoOp; + +/** + * 代理工厂 + */ +public final class ProxyFactory { + + private ProxyFactory() { + } + + private static MethodInterceptor[] aopInterceptors; + + static { + List aops = IocApplication.getAopInterceptors(); + if (null != aops && aops.size() > 0) { + aopInterceptors = new MethodInterceptor[aops.size()]; + for (int i = 0, len = aops.size(); i < len; i++) { + aopInterceptors[i] = (MethodInterceptor) aops.get(i); + } + } + } + + /* + * 获得代理对象 + */ + public static Object getProxyObj(Class clazz) throws Exception { + Enhancer hancer = new Enhancer(); + // 设置代理对象的父类 + hancer.setSuperclass(clazz); + // 设置回调对象,即调用代理对象里面的方法时,实际上执行的是回调对象(里的intercept方法)。 + MethodInterceptor[] methodInterceptors = filter(clazz); + if (null != methodInterceptors && methodInterceptors.length > 0) { + hancer.setCallbacks(methodInterceptors); + } else { + hancer.setCallback(NoOp.INSTANCE); + } + // 创建代理对象 + return hancer.create(); + } + + private static MethodInterceptor[] filter(Class clazz) { + if (null != aopInterceptors) { + Aop aop = clazz.getAnnotation(Aop.class); + if (null != aop) { + Class inteceptorType = aop.value(); + List methodInterceptors = new ArrayList(); + for (MethodInterceptor methodInterceptor : aopInterceptors) { + if (inteceptorType.equals(methodInterceptor.getClass())) { + methodInterceptors.add(methodInterceptor); + } + } + return methodInterceptors.toArray(new MethodInterceptor[methodInterceptors.size()]); + } + } + return null; + } + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/aop/ProxyIocImpl.java b/blade-aop/src/main/java/com/blade/aop/ProxyIocImpl.java new file mode 100644 index 000000000..7a573ac80 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/ProxyIocImpl.java @@ -0,0 +1,22 @@ +package com.blade.aop; + +import com.blade.ioc.BeanDefine; +import com.blade.ioc.SimpleIoc; + +public class ProxyIocImpl extends SimpleIoc { + + public BeanDefine getBeanDefine(Class beanClass, boolean singleton) { + try { + Object object = ProxyFactory.getProxyObj(beanClass); + return new BeanDefine(object, beanClass, singleton); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/blade-aop/src/main/java/com/blade/aop/annotation/Aop.java b/blade-aop/src/main/java/com/blade/aop/annotation/Aop.java new file mode 100644 index 000000000..982005010 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/aop/annotation/Aop.java @@ -0,0 +1,20 @@ +package com.blade.aop.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import net.sf.cglib.proxy.MethodInterceptor; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Aop{ + + Class value(); + + String methodPrefix() default ""; + +} \ No newline at end of file diff --git a/blade-aop/src/main/java/com/blade/plugin/AopPlugin.java b/blade-aop/src/main/java/com/blade/plugin/AopPlugin.java new file mode 100644 index 000000000..07d728216 --- /dev/null +++ b/blade-aop/src/main/java/com/blade/plugin/AopPlugin.java @@ -0,0 +1,24 @@ +package com.blade.plugin; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.aop.ProxyIocImpl; + +public class AopPlugin implements Plugin { + + private static final Logger LOGGER = LoggerFactory.getLogger(AopPlugin.class); + + @Override + public void start() { + LOGGER.info("Set Ioc container is {}", ProxyIocImpl.class.getName()); + Blade.$().container(new ProxyIocImpl()); + } + + @Override + public void destroy() { + + } + +} diff --git a/blade-aop/src/main/java/net/sf/cglib/beans/BeanCopier.java b/blade-aop/src/main/java/net/sf/cglib/beans/BeanCopier.java new file mode 100644 index 000000000..67b49ee2b --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/beans/BeanCopier.java @@ -0,0 +1,176 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.beans; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.*; +import java.security.ProtectionDomain; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; +import java.util.*; + +/** + * @author Chris Nokleberg + */ +abstract public class BeanCopier +{ + private static final BeanCopierKey KEY_FACTORY = + (BeanCopierKey)KeyFactory.create(BeanCopierKey.class); + private static final Type CONVERTER = + TypeUtils.parseType("net.sf.cglib.core.Converter"); + private static final Type BEAN_COPIER = + TypeUtils.parseType("net.sf.cglib.beans.BeanCopier"); + private static final Signature COPY = + new Signature("copy", Type.VOID_TYPE, new Type[]{ Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER }); + private static final Signature CONVERT = + TypeUtils.parseSignature("Object convert(Object, Class, Object)"); + + interface BeanCopierKey { + public Object newInstance(String source, String target, boolean useConverter); + } + + public static BeanCopier create(Class source, Class target, boolean useConverter) { + Generator gen = new Generator(); + gen.setSource(source); + gen.setTarget(target); + gen.setUseConverter(useConverter); + return gen.create(); + } + + abstract public void copy(Object from, Object to, Converter converter); + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(BeanCopier.class.getName()); + private Class source; + private Class target; + private boolean useConverter; + + public Generator() { + super(SOURCE); + } + + public void setSource(Class source) { + if(!Modifier.isPublic(source.getModifiers())){ + setNamePrefix(source.getName()); + } + this.source = source; + } + + public void setTarget(Class target) { + if(!Modifier.isPublic(target.getModifiers())){ + setNamePrefix(target.getName()); + } + + this.target = target; + } + + public void setUseConverter(boolean useConverter) { + this.useConverter = useConverter; + } + + protected ClassLoader getDefaultClassLoader() { + return source.getClassLoader(); + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(source); + } + + public BeanCopier create() { + Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter); + return (BeanCopier)super.create(key); + } + + public void generateClass(ClassVisitor v) { + Type sourceType = Type.getType(source); + Type targetType = Type.getType(target); + ClassEmitter ce = new ClassEmitter(v); + ce.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + getClassName(), + BEAN_COPIER, + null, + Constants.SOURCE_FILE); + + EmitUtils.null_constructor(ce); + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null); + PropertyDescriptor[] getters = ReflectUtils.getBeanGetters(source); + PropertyDescriptor[] setters = ReflectUtils.getBeanSetters(target); + + Map names = new HashMap(); + for (int i = 0; i < getters.length; i++) { + names.put(getters[i].getName(), getters[i]); + } + Local targetLocal = e.make_local(); + Local sourceLocal = e.make_local(); + if (useConverter) { + e.load_arg(1); + e.checkcast(targetType); + e.store_local(targetLocal); + e.load_arg(0); + e.checkcast(sourceType); + e.store_local(sourceLocal); + } else { + e.load_arg(1); + e.checkcast(targetType); + e.load_arg(0); + e.checkcast(sourceType); + } + for (int i = 0; i < setters.length; i++) { + PropertyDescriptor setter = setters[i]; + PropertyDescriptor getter = (PropertyDescriptor)names.get(setter.getName()); + if (getter != null) { + MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod()); + MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod()); + if (useConverter) { + Type setterType = write.getSignature().getArgumentTypes()[0]; + e.load_local(targetLocal); + e.load_arg(2); + e.load_local(sourceLocal); + e.invoke(read); + e.box(read.getSignature().getReturnType()); + EmitUtils.load_class(e, setterType); + e.push(write.getSignature().getName()); + e.invoke_interface(CONVERTER, CONVERT); + e.unbox_or_zero(setterType); + e.invoke(write); + } else if (compatible(getter, setter)) { + e.dup2(); + e.invoke(read); + e.invoke(write); + } + } + } + e.return_value(); + e.end_method(); + ce.end_class(); + } + + private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) { + // TODO: allow automatic widening conversions? + return setter.getPropertyType().isAssignableFrom(getter.getPropertyType()); + } + + protected Object firstInstance(Class type) { + return ReflectUtils.newInstance(type); + } + + protected Object nextInstance(Object instance) { + return instance; + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/beans/BeanGenerator.java b/blade-aop/src/main/java/net/sf/cglib/beans/BeanGenerator.java new file mode 100644 index 000000000..6b668b71a --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/beans/BeanGenerator.java @@ -0,0 +1,149 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.beans; + +import java.beans.PropertyDescriptor; +import java.security.ProtectionDomain; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; + +/** + * @author Juozas Baliuka, Chris Nokleberg + */ +public class BeanGenerator extends AbstractClassGenerator +{ + private static final Source SOURCE = new Source(BeanGenerator.class.getName()); + private static final BeanGeneratorKey KEY_FACTORY = + (BeanGeneratorKey)KeyFactory.create(BeanGeneratorKey.class); + + interface BeanGeneratorKey { + public Object newInstance(String superclass, Map props); + } + + private Class superclass; + private Map props = new HashMap(); + private boolean classOnly; + + public BeanGenerator() { + super(SOURCE); + } + + /** + * Set the class which the generated class will extend. The class + * must not be declared as final, and must have a non-private + * no-argument constructor. + * @param superclass class to extend, or null to extend Object + */ + public void setSuperclass(Class superclass) { + if (superclass != null && superclass.equals(Object.class)) { + superclass = null; + } + this.superclass = superclass; + } + + public void addProperty(String name, Class type) { + if (props.containsKey(name)) { + throw new IllegalArgumentException("Duplicate property name \"" + name + "\""); + } + props.put(name, Type.getType(type)); + } + + protected ClassLoader getDefaultClassLoader() { + if (superclass != null) { + return superclass.getClassLoader(); + } else { + return null; + } + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(superclass); + } + + public Object create() { + classOnly = false; + return createHelper(); + } + + public Object createClass() { + classOnly = true; + return createHelper(); + } + + private Object createHelper() { + if (superclass != null) { + setNamePrefix(superclass.getName()); + } + String superName = (superclass != null) ? superclass.getName() : "java.lang.Object"; + Object key = KEY_FACTORY.newInstance(superName, props); + return super.create(key); + } + + public void generateClass(ClassVisitor v) throws Exception { + int size = props.size(); + String[] names = (String[])props.keySet().toArray(new String[size]); + Type[] types = new Type[size]; + for (int i = 0; i < size; i++) { + types[i] = (Type)props.get(names[i]); + } + ClassEmitter ce = new ClassEmitter(v); + ce.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + getClassName(), + superclass != null ? Type.getType(superclass) : Constants.TYPE_OBJECT, + null, + null); + EmitUtils.null_constructor(ce); + EmitUtils.add_properties(ce, names, types); + ce.end_class(); + } + + protected Object firstInstance(Class type) { + if (classOnly) { + return type; + } else { + return ReflectUtils.newInstance(type); + } + } + + protected Object nextInstance(Object instance) { + Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass(); + if (classOnly) { + return protoclass; + } else { + return ReflectUtils.newInstance(protoclass); + } + } + + public static void addProperties(BeanGenerator gen, Map props) { + for (Iterator it = props.keySet().iterator(); it.hasNext();) { + String name = (String)it.next(); + gen.addProperty(name, (Class)props.get(name)); + } + } + + public static void addProperties(BeanGenerator gen, Class type) { + addProperties(gen, ReflectUtils.getBeanProperties(type)); + } + + public static void addProperties(BeanGenerator gen, PropertyDescriptor[] descriptors) { + for (int i = 0; i < descriptors.length; i++) { + gen.addProperty(descriptors[i].getName(), descriptors[i].getPropertyType()); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/beans/BeanMap.java b/blade-aop/src/main/java/net/sf/cglib/beans/BeanMap.java new file mode 100644 index 000000000..580f20a70 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/beans/BeanMap.java @@ -0,0 +1,320 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.beans; + +import java.security.ProtectionDomain; +import java.beans.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; + +/** + * A Map-based view of a JavaBean. The default set of keys is the + * union of all property names (getters or setters). An attempt to set + * a read-only property will be ignored, and write-only properties will + * be returned as null. Removal of objects is not a + * supported (the key set is fixed). + * @author Chris Nokleberg + */ +abstract public class BeanMap implements Map { + /** + * Limit the properties reflected in the key set of the map + * to readable properties. + * @see BeanMap.Generator#setRequire + */ + public static final int REQUIRE_GETTER = 1; + + /** + * Limit the properties reflected in the key set of the map + * to writable properties. + * @see BeanMap.Generator#setRequire + */ + public static final int REQUIRE_SETTER = 2; + + /** + * Helper method to create a new BeanMap. For finer + * control over the generated instance, use a new instance of + * BeanMap.Generator instead of this static method. + * @param bean the JavaBean underlying the map + * @return a new BeanMap instance + */ + public static BeanMap create(Object bean) { + Generator gen = new Generator(); + gen.setBean(bean); + return gen.create(); + } + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(BeanMap.class.getName()); + + private static final BeanMapKey KEY_FACTORY = + (BeanMapKey)KeyFactory.create(BeanMapKey.class, KeyFactory.CLASS_BY_NAME); + + interface BeanMapKey { + public Object newInstance(Class type, int require); + } + + private Object bean; + private Class beanClass; + private int require; + + public Generator() { + super(SOURCE); + } + + /** + * Set the bean that the generated map should reflect. The bean may be swapped + * out for another bean of the same type using {@link #setBean}. + * Calling this method overrides any value previously set using {@link #setBeanClass}. + * You must call either this method or {@link #setBeanClass} before {@link #create}. + * @param bean the initial bean + */ + public void setBean(Object bean) { + this.bean = bean; + if (bean != null) + beanClass = bean.getClass(); + } + + /** + * Set the class of the bean that the generated map should support. + * You must call either this method or {@link #setBeanClass} before {@link #create}. + * @param beanClass the class of the bean + */ + public void setBeanClass(Class beanClass) { + this.beanClass = beanClass; + } + + /** + * Limit the properties reflected by the generated map. + * @param require any combination of {@link #REQUIRE_GETTER} and + * {@link #REQUIRE_SETTER}; default is zero (any property allowed) + */ + public void setRequire(int require) { + this.require = require; + } + + protected ClassLoader getDefaultClassLoader() { + return beanClass.getClassLoader(); + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(beanClass); + } + + /** + * Create a new instance of the BeanMap. An existing + * generated class will be reused if possible. + */ + public BeanMap create() { + if (beanClass == null) + throw new IllegalArgumentException("Class of bean unknown"); + setNamePrefix(beanClass.getName()); + return (BeanMap)super.create(KEY_FACTORY.newInstance(beanClass, require)); + } + + public void generateClass(ClassVisitor v) throws Exception { + new BeanMapEmitter(v, getClassName(), beanClass, require); + } + + protected Object firstInstance(Class type) { + return ((BeanMap)ReflectUtils.newInstance(type)).newInstance(bean); + } + + protected Object nextInstance(Object instance) { + return ((BeanMap)instance).newInstance(bean); + } + } + + /** + * Create a new BeanMap instance using the specified bean. + * This is faster than using the {@link #create} static method. + * @param bean the JavaBean underlying the map + * @return a new BeanMap instance + */ + abstract public BeanMap newInstance(Object bean); + + /** + * Get the type of a property. + * @param name the name of the JavaBean property + * @return the type of the property, or null if the property does not exist + */ + abstract public Class getPropertyType(String name); + + protected Object bean; + + protected BeanMap() { + } + + protected BeanMap(Object bean) { + setBean(bean); + } + + public Object get(Object key) { + return get(bean, key); + } + + public Object put(Object key, Object value) { + return put(bean, key, value); + } + + /** + * Get the property of a bean. This allows a BeanMap + * to be used statically for multiple beans--the bean instance tied to the + * map is ignored and the bean passed to this method is used instead. + * @param bean the bean to query; must be compatible with the type of + * this BeanMap + * @param key must be a String + * @return the current value, or null if there is no matching property + */ + abstract public Object get(Object bean, Object key); + + /** + * Set the property of a bean. This allows a BeanMap + * to be used statically for multiple beans--the bean instance tied to the + * map is ignored and the bean passed to this method is used instead. + * @param key must be a String + * @return the old value, if there was one, or null + */ + abstract public Object put(Object bean, Object key, Object value); + + /** + * Change the underlying bean this map should use. + * @param bean the new JavaBean + * @see #getBean + */ + public void setBean(Object bean) { + this.bean = bean; + } + + /** + * Return the bean currently in use by this map. + * @return the current JavaBean + * @see #setBean + */ + public Object getBean() { + return bean; + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public boolean containsKey(Object key) { + return keySet().contains(key); + } + + public boolean containsValue(Object value) { + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object v = get(it.next()); + if (((value == null) && (v == null)) || (value != null && value.equals(v))) + return true; + } + return false; + } + + public int size() { + return keySet().size(); + } + + public boolean isEmpty() { + return size() == 0; + } + + public Object remove(Object key) { + throw new UnsupportedOperationException(); + } + + public void putAll(Map t) { + for (Iterator it = t.keySet().iterator(); it.hasNext();) { + Object key = it.next(); + put(key, t.get(key)); + } + } + + public boolean equals(Object o) { + if (o == null || !(o instanceof Map)) { + return false; + } + Map other = (Map)o; + if (size() != other.size()) { + return false; + } + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object key = it.next(); + if (!other.containsKey(key)) { + return false; + } + Object v1 = get(key); + Object v2 = other.get(key); + if (!((v1 == null) ? v2 == null : v1.equals(v2))) { + return false; + } + } + return true; + } + + public int hashCode() { + int code = 0; + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object key = it.next(); + Object value = get(key); + code += ((key == null) ? 0 : key.hashCode()) ^ + ((value == null) ? 0 : value.hashCode()); + } + return code; + } + + // TODO: optimize + public Set entrySet() { + HashMap copy = new HashMap(); + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object key = it.next(); + copy.put(key, get(key)); + } + return Collections.unmodifiableMap(copy).entrySet(); + } + + public Collection values() { + Set keys = keySet(); + List values = new ArrayList(keys.size()); + for (Iterator it = keys.iterator(); it.hasNext();) { + values.add(get(it.next())); + } + return Collections.unmodifiableCollection(values); + } + + /* + * @see java.util.AbstractMap#toString + */ + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append('{'); + for (Iterator it = keySet().iterator(); it.hasNext();) { + Object key = it.next(); + sb.append(key); + sb.append('='); + sb.append(get(key)); + if (it.hasNext()) { + sb.append(", "); + } + } + sb.append('}'); + return sb.toString(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/beans/BeanMapEmitter.java b/blade-aop/src/main/java/net/sf/cglib/beans/BeanMapEmitter.java new file mode 100644 index 000000000..c81314241 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/beans/BeanMapEmitter.java @@ -0,0 +1,192 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.beans; + +import java.beans.*; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +class BeanMapEmitter extends ClassEmitter { + private static final Type BEAN_MAP = + TypeUtils.parseType("net.sf.cglib.beans.BeanMap"); + private static final Type FIXED_KEY_SET = + TypeUtils.parseType("net.sf.cglib.beans.FixedKeySet"); + private static final Signature CSTRUCT_OBJECT = + TypeUtils.parseConstructor("Object"); + private static final Signature CSTRUCT_STRING_ARRAY = + TypeUtils.parseConstructor("String[]"); + private static final Signature BEAN_MAP_GET = + TypeUtils.parseSignature("Object get(Object, Object)"); + private static final Signature BEAN_MAP_PUT = + TypeUtils.parseSignature("Object put(Object, Object, Object)"); + private static final Signature KEY_SET = + TypeUtils.parseSignature("java.util.Set keySet()"); + private static final Signature NEW_INSTANCE = + new Signature("newInstance", BEAN_MAP, new Type[]{ Constants.TYPE_OBJECT }); + private static final Signature GET_PROPERTY_TYPE = + TypeUtils.parseSignature("Class getPropertyType(String)"); + + public BeanMapEmitter(ClassVisitor v, String className, Class type, int require) { + super(v); + + begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BEAN_MAP, null, Constants.SOURCE_FILE); + EmitUtils.null_constructor(this); + EmitUtils.factory_method(this, NEW_INSTANCE); + generateConstructor(); + + Map getters = makePropertyMap(ReflectUtils.getBeanGetters(type)); + Map setters = makePropertyMap(ReflectUtils.getBeanSetters(type)); + Map allProps = new HashMap(); + allProps.putAll(getters); + allProps.putAll(setters); + + if (require != 0) { + for (Iterator it = allProps.keySet().iterator(); it.hasNext();) { + String name = (String)it.next(); + if ((((require & BeanMap.REQUIRE_GETTER) != 0) && !getters.containsKey(name)) || + (((require & BeanMap.REQUIRE_SETTER) != 0) && !setters.containsKey(name))) { + it.remove(); + getters.remove(name); + setters.remove(name); + } + } + } + generateGet(type, getters); + generatePut(type, setters); + + String[] allNames = getNames(allProps); + generateKeySet(allNames); + generateGetPropertyType(allProps, allNames); + end_class(); + } + + private Map makePropertyMap(PropertyDescriptor[] props) { + Map names = new HashMap(); + for (int i = 0; i < props.length; i++) { + names.put(((PropertyDescriptor)props[i]).getName(), props[i]); + } + return names; + } + + private String[] getNames(Map propertyMap) { + return (String[])propertyMap.keySet().toArray(new String[propertyMap.size()]); + } + + private void generateConstructor() { + CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null); + e.load_this(); + e.load_arg(0); + e.super_invoke_constructor(CSTRUCT_OBJECT); + e.return_value(); + e.end_method(); + } + + private void generateGet(Class type, final Map getters) { + final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_GET, null); + e.load_arg(0); + e.checkcast(Type.getType(type)); + e.load_arg(1); + e.checkcast(Constants.TYPE_STRING); + EmitUtils.string_switch(e, getNames(getters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { + public void processCase(Object key, Label end) { + PropertyDescriptor pd = (PropertyDescriptor)getters.get(key); + MethodInfo method = ReflectUtils.getMethodInfo(pd.getReadMethod()); + e.invoke(method); + e.box(method.getSignature().getReturnType()); + e.return_value(); + } + public void processDefault() { + e.aconst_null(); + e.return_value(); + } + }); + e.end_method(); + } + + private void generatePut(Class type, final Map setters) { + final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_PUT, null); + e.load_arg(0); + e.checkcast(Type.getType(type)); + e.load_arg(1); + e.checkcast(Constants.TYPE_STRING); + EmitUtils.string_switch(e, getNames(setters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { + public void processCase(Object key, Label end) { + PropertyDescriptor pd = (PropertyDescriptor)setters.get(key); + if (pd.getReadMethod() == null) { + e.aconst_null(); + } else { + MethodInfo read = ReflectUtils.getMethodInfo(pd.getReadMethod()); + e.dup(); + e.invoke(read); + e.box(read.getSignature().getReturnType()); + } + e.swap(); // move old value behind bean + e.load_arg(2); // new value + MethodInfo write = ReflectUtils.getMethodInfo(pd.getWriteMethod()); + e.unbox(write.getSignature().getArgumentTypes()[0]); + e.invoke(write); + e.return_value(); + } + public void processDefault() { + // fall-through + } + }); + e.aconst_null(); + e.return_value(); + e.end_method(); + } + + private void generateKeySet(String[] allNames) { + // static initializer + declare_field(Constants.ACC_STATIC | Constants.ACC_PRIVATE, "keys", FIXED_KEY_SET, null); + + CodeEmitter e = begin_static(); + e.new_instance(FIXED_KEY_SET); + e.dup(); + EmitUtils.push_array(e, allNames); + e.invoke_constructor(FIXED_KEY_SET, CSTRUCT_STRING_ARRAY); + e.putfield("keys"); + e.return_value(); + e.end_method(); + + // keySet + e = begin_method(Constants.ACC_PUBLIC, KEY_SET, null); + e.load_this(); + e.getfield("keys"); + e.return_value(); + e.end_method(); + } + + private void generateGetPropertyType(final Map allProps, String[] allNames) { + final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_TYPE, null); + e.load_arg(0); + EmitUtils.string_switch(e, allNames, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { + public void processCase(Object key, Label end) { + PropertyDescriptor pd = (PropertyDescriptor)allProps.get(key); + EmitUtils.load_class(e, Type.getType(pd.getPropertyType())); + e.return_value(); + } + public void processDefault() { + e.aconst_null(); + e.return_value(); + } + }); + e.end_method(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/beans/BulkBean.java b/blade-aop/src/main/java/net/sf/cglib/beans/BulkBean.java new file mode 100644 index 000000000..21398fcfb --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/beans/BulkBean.java @@ -0,0 +1,142 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.beans; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.security.ProtectionDomain; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; + +/** + * @author Juozas Baliuka + */ +abstract public class BulkBean +{ + private static final BulkBeanKey KEY_FACTORY = + (BulkBeanKey)KeyFactory.create(BulkBeanKey.class); + + interface BulkBeanKey { + public Object newInstance(String target, String[] getters, String[] setters, String[] types); + } + + protected Class target; + protected String[] getters, setters; + protected Class[] types; + + protected BulkBean() { } + + abstract public void getPropertyValues(Object bean, Object[] values); + abstract public void setPropertyValues(Object bean, Object[] values); + + public Object[] getPropertyValues(Object bean) { + Object[] values = new Object[getters.length]; + getPropertyValues(bean, values); + return values; + } + + public Class[] getPropertyTypes() { + return (Class[])types.clone(); + } + + public String[] getGetters() { + return (String[])getters.clone(); + } + + public String[] getSetters() { + return (String[])setters.clone(); + } + + public static BulkBean create(Class target, String[] getters, String[] setters, Class[] types) { + Generator gen = new Generator(); + gen.setTarget(target); + gen.setGetters(getters); + gen.setSetters(setters); + gen.setTypes(types); + return gen.create(); + } + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(BulkBean.class.getName()); + private Class target; + private String[] getters; + private String[] setters; + private Class[] types; + + public Generator() { + super(SOURCE); + } + + public void setTarget(Class target) { + this.target = target; + } + + public void setGetters(String[] getters) { + this.getters = getters; + } + + public void setSetters(String[] setters) { + this.setters = setters; + } + + public void setTypes(Class[] types) { + this.types = types; + } + + protected ClassLoader getDefaultClassLoader() { + return target.getClassLoader(); + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(target); + } + + public BulkBean create() { + setNamePrefix(target.getName()); + String targetClassName = target.getName(); + String[] typeClassNames = ReflectUtils.getNames(types); + Object key = KEY_FACTORY.newInstance(targetClassName, getters, setters, typeClassNames); + return (BulkBean)super.create(key); + } + + public void generateClass(ClassVisitor v) throws Exception { + new BulkBeanEmitter(v, getClassName(), target, getters, setters, types); + } + + protected Object firstInstance(Class type) { + BulkBean instance = (BulkBean)ReflectUtils.newInstance(type); + instance.target = target; + + int length = getters.length; + instance.getters = new String[length]; + System.arraycopy(getters, 0, instance.getters, 0, length); + + instance.setters = new String[length]; + System.arraycopy(setters, 0, instance.setters, 0, length); + + instance.types = new Class[types.length]; + System.arraycopy(types, 0, instance.types, 0, types.length); + + return instance; + } + + protected Object nextInstance(Object instance) { + return instance; + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/beans/BulkBeanEmitter.java b/blade-aop/src/main/java/net/sf/cglib/beans/BulkBeanEmitter.java new file mode 100644 index 000000000..440069efe --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/beans/BulkBeanEmitter.java @@ -0,0 +1,156 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.beans; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; + +class BulkBeanEmitter extends ClassEmitter { + private static final Signature GET_PROPERTY_VALUES = + TypeUtils.parseSignature("void getPropertyValues(Object, Object[])"); + private static final Signature SET_PROPERTY_VALUES = + TypeUtils.parseSignature("void setPropertyValues(Object, Object[])"); + private static final Signature CSTRUCT_EXCEPTION = + TypeUtils.parseConstructor("Throwable, int"); + private static final Type BULK_BEAN = + TypeUtils.parseType("net.sf.cglib.beans.BulkBean"); + private static final Type BULK_BEAN_EXCEPTION = + TypeUtils.parseType("net.sf.cglib.beans.BulkBeanException"); + + public BulkBeanEmitter(ClassVisitor v, + String className, + Class target, + String[] getterNames, + String[] setterNames, + Class[] types) { + super(v); + + Method[] getters = new Method[getterNames.length]; + Method[] setters = new Method[setterNames.length]; + validate(target, getterNames, setterNames, types, getters, setters); + + begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BULK_BEAN, null, Constants.SOURCE_FILE); + EmitUtils.null_constructor(this); + generateGet(target, getters); + generateSet(target, setters); + end_class(); + } + + private void generateGet(final Class target, final Method[] getters) { + CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_VALUES, null); + if (getters.length >= 0) { + e.load_arg(0); + e.checkcast(Type.getType(target)); + Local bean = e.make_local(); + e.store_local(bean); + for (int i = 0; i < getters.length; i++) { + if (getters[i] != null) { + MethodInfo getter = ReflectUtils.getMethodInfo(getters[i]); + e.load_arg(1); + e.push(i); + e.load_local(bean); + e.invoke(getter); + e.box(getter.getSignature().getReturnType()); + e.aastore(); + } + } + } + e.return_value(); + e.end_method(); + } + + private void generateSet(final Class target, final Method[] setters) { + // setPropertyValues + CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SET_PROPERTY_VALUES, null); + if (setters.length > 0) { + Local index = e.make_local(Type.INT_TYPE); + e.push(0); + e.store_local(index); + e.load_arg(0); + e.checkcast(Type.getType(target)); + e.load_arg(1); + Block handler = e.begin_block(); + int lastIndex = 0; + for (int i = 0; i < setters.length; i++) { + if (setters[i] != null) { + MethodInfo setter = ReflectUtils.getMethodInfo(setters[i]); + int diff = i - lastIndex; + if (diff > 0) { + e.iinc(index, diff); + lastIndex = i; + } + e.dup2(); + e.aaload(i); + e.unbox(setter.getSignature().getArgumentTypes()[0]); + e.invoke(setter); + } + } + handler.end(); + e.return_value(); + e.catch_exception(handler, Constants.TYPE_THROWABLE); + e.new_instance(BULK_BEAN_EXCEPTION); + e.dup_x1(); + e.swap(); + e.load_local(index); + e.invoke_constructor(BULK_BEAN_EXCEPTION, CSTRUCT_EXCEPTION); + e.athrow(); + } else { + e.return_value(); + } + e.end_method(); + } + + private static void validate(Class target, + String[] getters, + String[] setters, + Class[] types, + Method[] getters_out, + Method[] setters_out) { + int i = -1; + if (setters.length != types.length || getters.length != types.length) { + throw new BulkBeanException("accessor array length must be equal type array length", i); + } + try { + for (i = 0; i < types.length; i++) { + if (getters[i] != null) { + Method method = ReflectUtils.findDeclaredMethod(target, getters[i], null); + if (method.getReturnType() != types[i]) { + throw new BulkBeanException("Specified type " + types[i] + + " does not match declared type " + method.getReturnType(), i); + } + if (Modifier.isPrivate(method.getModifiers())) { + throw new BulkBeanException("Property is private", i); + } + getters_out[i] = method; + } + if (setters[i] != null) { + Method method = ReflectUtils.findDeclaredMethod(target, setters[i], new Class[]{ types[i] }); + if (Modifier.isPrivate(method.getModifiers()) ){ + throw new BulkBeanException("Property is private", i); + } + setters_out[i] = method; + } + } + } catch (NoSuchMethodException e) { + throw new BulkBeanException("Cannot find specified property", i); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/beans/BulkBeanException.java b/blade-aop/src/main/java/net/sf/cglib/beans/BulkBeanException.java new file mode 100644 index 000000000..fcb4e3648 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/beans/BulkBeanException.java @@ -0,0 +1,43 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.beans; + +import net.sf.cglib.core.CodeGenerationException; + +public class BulkBeanException extends RuntimeException +{ + private int index; + private Throwable cause; + + public BulkBeanException(String message, int index) { + super(message); + this.index = index; + } + + public BulkBeanException(Throwable cause, int index) { + super(cause.getMessage()); + this.index = index; + this.cause = cause; + } + + public int getIndex() { + return index; + } + + public Throwable getCause() { + return cause; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/beans/FixedKeySet.java b/blade-aop/src/main/java/net/sf/cglib/beans/FixedKeySet.java new file mode 100644 index 000000000..13c91e41b --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/beans/FixedKeySet.java @@ -0,0 +1,36 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.beans; + +import java.util.*; + +public /* need it for class loading */ class FixedKeySet extends AbstractSet { + private Set set; + private int size; + + public FixedKeySet(String[] keys) { + size = keys.length; + set = Collections.unmodifiableSet(new HashSet(Arrays.asList(keys))); + } + + public Iterator iterator() { + return set.iterator(); + } + + public int size() { + return size; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/beans/ImmutableBean.java b/blade-aop/src/main/java/net/sf/cglib/beans/ImmutableBean.java new file mode 100644 index 000000000..33350ab33 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/beans/ImmutableBean.java @@ -0,0 +1,128 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.beans; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.security.ProtectionDomain; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; +/** + * @author Chris Nokleberg + */ +public class ImmutableBean +{ + private static final Type ILLEGAL_STATE_EXCEPTION = + TypeUtils.parseType("IllegalStateException"); + private static final Signature CSTRUCT_OBJECT = + TypeUtils.parseConstructor("Object"); + private static final Class[] OBJECT_CLASSES = { Object.class }; + private static final String FIELD_NAME = "CGLIB$RWBean"; + + private ImmutableBean() { + } + + public static Object create(Object bean) { + Generator gen = new Generator(); + gen.setBean(bean); + return gen.create(); + } + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(ImmutableBean.class.getName()); + private Object bean; + private Class target; + + public Generator() { + super(SOURCE); + } + + public void setBean(Object bean) { + this.bean = bean; + target = bean.getClass(); + } + + protected ClassLoader getDefaultClassLoader() { + return target.getClassLoader(); + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(target); + } + + public Object create() { + String name = target.getName(); + setNamePrefix(name); + return super.create(name); + } + + public void generateClass(ClassVisitor v) { + Type targetType = Type.getType(target); + ClassEmitter ce = new ClassEmitter(v); + ce.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + getClassName(), + targetType, + null, + Constants.SOURCE_FILE); + + ce.declare_field(Constants.ACC_FINAL | Constants.ACC_PRIVATE, FIELD_NAME, targetType, null); + + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null); + e.load_this(); + e.super_invoke_constructor(); + e.load_this(); + e.load_arg(0); + e.checkcast(targetType); + e.putfield(FIELD_NAME); + e.return_value(); + e.end_method(); + + PropertyDescriptor[] descriptors = ReflectUtils.getBeanProperties(target); + Method[] getters = ReflectUtils.getPropertyMethods(descriptors, true, false); + Method[] setters = ReflectUtils.getPropertyMethods(descriptors, false, true); + + for (int i = 0; i < getters.length; i++) { + MethodInfo getter = ReflectUtils.getMethodInfo(getters[i]); + e = EmitUtils.begin_method(ce, getter, Constants.ACC_PUBLIC); + e.load_this(); + e.getfield(FIELD_NAME); + e.invoke(getter); + e.return_value(); + e.end_method(); + } + + for (int i = 0; i < setters.length; i++) { + MethodInfo setter = ReflectUtils.getMethodInfo(setters[i]); + e = EmitUtils.begin_method(ce, setter, Constants.ACC_PUBLIC); + e.throw_exception(ILLEGAL_STATE_EXCEPTION, "Bean is immutable"); + e.end_method(); + } + + ce.end_class(); + } + + protected Object firstInstance(Class type) { + return ReflectUtils.newInstance(type, OBJECT_CLASSES, new Object[]{ bean }); + } + + // TODO: optimize + protected Object nextInstance(Object instance) { + return firstInstance(instance.getClass()); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/AbstractClassGenerator.java b/blade-aop/src/main/java/net/sf/cglib/core/AbstractClassGenerator.java new file mode 100644 index 000000000..d7abfce39 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/AbstractClassGenerator.java @@ -0,0 +1,353 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import net.sf.cglib.core.internal.Function; +import net.sf.cglib.core.internal.LoadingCache; +import org.objectweb.asm.ClassReader; + +import java.lang.ref.WeakReference; +import java.security.ProtectionDomain; +import java.util.Map; +import java.util.Set; +import java.util.HashSet; +import java.util.WeakHashMap; + +/** + * Abstract class for all code-generating CGLIB utilities. + * In addition to caching generated classes for performance, it provides hooks for + * customizing the ClassLoader, name of the generated class, and transformations + * applied before generation. + */ +abstract public class AbstractClassGenerator +implements ClassGenerator +{ + private static final ThreadLocal CURRENT = new ThreadLocal(); + + private static volatile Map CACHE = new WeakHashMap(); + + private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE; + private NamingPolicy namingPolicy = DefaultNamingPolicy.INSTANCE; + private Source source; + private ClassLoader classLoader; + private String namePrefix; + private Object key; + private boolean useCache = true; + private String className; + private boolean attemptLoad; + + protected static class ClassLoaderData { + private final Set reservedClassNames = new HashSet(); + + /** + * {@link AbstractClassGenerator} here holds "cache key" (e.g. {@link net.sf.cglib.proxy.Enhancer} + * configuration), and the value is the generated class plus some additional values + * (see {@link #unwrapCachedValue(Object)}. + *

The generated classes can be reused as long as their classloader is reachable.

+ *

Note: the only way to access a class is to find it through generatedClasses cache, thus + * the key should not expire as long as the class itself is alive (its classloader is alive).

+ */ + private final LoadingCache generatedClasses; + + /** + * Note: ClassLoaderData object is stored as a value of {@code WeakHashMap} thus + * this classLoader reference should be weak otherwise it would make classLoader strongly reachable + * and alive forever. + * Reference queue is not required since the cleanup is handled by {@link WeakHashMap}. + */ + private final WeakReference classLoader; + + private final Predicate uniqueNamePredicate = new Predicate() { + public boolean evaluate(Object name) { + return reservedClassNames.contains(name); + } + }; + + private static final Function GET_KEY = new Function() { + public Object apply(AbstractClassGenerator gen) { + return gen.key; + } + }; + + public ClassLoaderData(ClassLoader classLoader) { + if (classLoader == null) { + throw new IllegalArgumentException("classLoader == null is not yet supported"); + } + this.classLoader = new WeakReference(classLoader); + Function load = + new Function() { + public Object apply(AbstractClassGenerator gen) { + Class klass = gen.generate(ClassLoaderData.this); + return gen.wrapCachedClass(klass); + } + }; + generatedClasses = new LoadingCache(GET_KEY, load); + } + + public ClassLoader getClassLoader() { + return classLoader.get(); + } + + public void reserveName(String name) { + reservedClassNames.add(name); + } + + public Predicate getUniqueNamePredicate() { + return uniqueNamePredicate; + } + + public Object get(AbstractClassGenerator gen, boolean useCache) { + if (!useCache) { + return gen.generate(ClassLoaderData.this); + } else { + Object cachedValue = generatedClasses.get(gen); + return gen.unwrapCachedValue(cachedValue); + } + } + } + + protected T wrapCachedClass(Class klass) { + return (T) new WeakReference(klass); + } + + protected Object unwrapCachedValue(T cached) { + return ((WeakReference) cached).get(); + } + + protected static class Source { + String name; + public Source(String name) { + this.name = name; + } + } + + protected AbstractClassGenerator(Source source) { + this.source = source; + } + + protected void setNamePrefix(String namePrefix) { + this.namePrefix = namePrefix; + } + + final protected String getClassName() { + return className; + } + + private void setClassName(String className) { + this.className = className; + } + + private String generateClassName(Predicate nameTestPredicate) { + return namingPolicy.getClassName(namePrefix, source.name, key, nameTestPredicate); + } + + /** + * Set the ClassLoader in which the class will be generated. + * Concrete subclasses of AbstractClassGenerator (such as Enhancer) + * will try to choose an appropriate default if this is unset. + *

+ * Classes are cached per-ClassLoader using a WeakHashMap, to allow + * the generated classes to be removed when the associated loader is garbage collected. + * @param classLoader the loader to generate the new class with, or null to use the default + */ + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + /** + * Override the default naming policy. + * @see DefaultNamingPolicy + * @param namingPolicy the custom policy, or null to use the default + */ + public void setNamingPolicy(NamingPolicy namingPolicy) { + if (namingPolicy == null) + namingPolicy = DefaultNamingPolicy.INSTANCE; + this.namingPolicy = namingPolicy; + } + + /** + * @see #setNamingPolicy + */ + public NamingPolicy getNamingPolicy() { + return namingPolicy; + } + + /** + * Whether use and update the static cache of generated classes + * for a class with the same properties. Default is true. + */ + public void setUseCache(boolean useCache) { + this.useCache = useCache; + } + + /** + * @see #setUseCache + */ + public boolean getUseCache() { + return useCache; + } + + /** + * If set, CGLIB will attempt to load classes from the specified + * ClassLoader before generating them. Because generated + * class names are not guaranteed to be unique, the default is false. + */ + public void setAttemptLoad(boolean attemptLoad) { + this.attemptLoad = attemptLoad; + } + + public boolean getAttemptLoad() { + return attemptLoad; + } + + /** + * Set the strategy to use to create the bytecode from this generator. + * By default an instance of {@see DefaultGeneratorStrategy} is used. + */ + public void setStrategy(GeneratorStrategy strategy) { + if (strategy == null) + strategy = DefaultGeneratorStrategy.INSTANCE; + this.strategy = strategy; + } + + /** + * @see #setStrategy + */ + public GeneratorStrategy getStrategy() { + return strategy; + } + + /** + * Used internally by CGLIB. Returns the AbstractClassGenerator + * that is being used to generate a class in the current thread. + */ + public static AbstractClassGenerator getCurrent() { + return (AbstractClassGenerator)CURRENT.get(); + } + + public ClassLoader getClassLoader() { + ClassLoader t = classLoader; + if (t == null) { + t = getDefaultClassLoader(); + } + if (t == null) { + t = getClass().getClassLoader(); + } + if (t == null) { + t = Thread.currentThread().getContextClassLoader(); + } + if (t == null) { + throw new IllegalStateException("Cannot determine classloader"); + } + return t; + } + + abstract protected ClassLoader getDefaultClassLoader(); + + /** + * Returns the protection domain to use when defining the class. + *

+ * Default implementation returns null for using a default protection domain. Sub-classes may + * override to use a more specific protection domain. + *

+ * + * @return the protection domain (null for using a default) + */ + protected ProtectionDomain getProtectionDomain() { + return null; + } + + protected Object create(Object key) { + try { + ClassLoader loader = getClassLoader(); + Map cache = CACHE; + ClassLoaderData data = cache.get(loader); + if (data == null) { + synchronized (AbstractClassGenerator.class) { + cache = CACHE; + data = cache.get(loader); + if (data == null) { + Map newCache = new WeakHashMap(cache); + data = new ClassLoaderData(loader); + newCache.put(loader, data); + CACHE = newCache; + } + } + } + this.key = key; + Object obj = data.get(this, getUseCache()); + if (obj instanceof Class) { + return firstInstance((Class) obj); + } + return nextInstance(obj); + } catch (RuntimeException e) { + throw e; + } catch (Error e) { + throw e; + } catch (Exception e) { + throw new CodeGenerationException(e); + } + } + + protected Class generate(ClassLoaderData data) { + Class gen; + Object save = CURRENT.get(); + CURRENT.set(this); + try { + ClassLoader classLoader = data.getClassLoader(); + if (classLoader == null) { + throw new IllegalStateException("ClassLoader is null while trying to define class " + + getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " + + "Please file an issue at cglib's issue tracker."); + } + synchronized (classLoader) { + String name = generateClassName(data.getUniqueNamePredicate()); + data.reserveName(name); + this.setClassName(name); + } + if (attemptLoad) { + try { + gen = classLoader.loadClass(getClassName()); + return gen; + } catch (ClassNotFoundException e) { + // ignore + } + } + byte[] b = strategy.generate(this); + String className = ClassNameReader.getClassName(new ClassReader(b)); + ProtectionDomain protectionDomain = getProtectionDomain(); + synchronized (classLoader) { // just in case + if (protectionDomain == null) { + gen = ReflectUtils.defineClass(className, b, classLoader); + } else { + gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain); + } + } + return gen; + } catch (RuntimeException e) { + throw e; + } catch (Error e) { + throw e; + } catch (Exception e) { + throw new CodeGenerationException(e); + } finally { + CURRENT.set(save); + } + } + + abstract protected Object firstInstance(Class type) throws Exception; + abstract protected Object nextInstance(Object instance) throws Exception; +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/Block.java b/blade-aop/src/main/java/net/sf/cglib/core/Block.java new file mode 100644 index 000000000..4fb2e18e5 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/Block.java @@ -0,0 +1,49 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.Label; + +public class Block +{ + private CodeEmitter e; + private Label start; + private Label end; + + public Block(CodeEmitter e) { + this.e = e; + start = e.mark(); + } + + public CodeEmitter getCodeEmitter() { + return e; + } + + public void end() { + if (end != null) { + throw new IllegalStateException("end of label already set"); + } + end = e.mark(); + } + + public Label getStart() { + return start; + } + + public Label getEnd() { + return end; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/ClassEmitter.java b/blade-aop/src/main/java/net/sf/cglib/core/ClassEmitter.java new file mode 100644 index 000000000..1bee38207 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/ClassEmitter.java @@ -0,0 +1,282 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import net.sf.cglib.transform.ClassTransformer; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Juozas Baliuka, Chris Nokleberg + */ +public class ClassEmitter extends ClassTransformer { + private ClassInfo classInfo; + private Map fieldInfo; + + private static int hookCounter; + private MethodVisitor rawStaticInit; + private CodeEmitter staticInit; + private CodeEmitter staticHook; + private Signature staticHookSig; + + public ClassEmitter(ClassVisitor cv) { + setTarget(cv); + } + + public ClassEmitter() { + super(Opcodes.ASM5); + } + + public void setTarget(ClassVisitor cv) { + this.cv = cv; + fieldInfo = new HashMap(); + + // just to be safe + staticInit = staticHook = null; + staticHookSig = null; + } + + synchronized private static int getNextHook() { + return ++hookCounter; + } + + public ClassInfo getClassInfo() { + return classInfo; + } + + public void begin_class(int version, final int access, String className, final Type superType, final Type[] interfaces, String source) { + final Type classType = Type.getType("L" + className.replace('.', '/') + ";"); + classInfo = new ClassInfo() { + public Type getType() { + return classType; + } + public Type getSuperType() { + return (superType != null) ? superType : Constants.TYPE_OBJECT; + } + public Type[] getInterfaces() { + return interfaces; + } + public int getModifiers() { + return access; + } + }; + cv.visit(version, + access, + classInfo.getType().getInternalName(), + null, + classInfo.getSuperType().getInternalName(), + TypeUtils.toInternalNames(interfaces)); + if (source != null) + cv.visitSource(source, null); + init(); + } + + public CodeEmitter getStaticHook() { + if (TypeUtils.isInterface(getAccess())) { + throw new IllegalStateException("static hook is invalid for this class"); + } + if (staticHook == null) { + staticHookSig = new Signature("CGLIB$STATICHOOK" + getNextHook(), "()V"); + staticHook = begin_method(Constants.ACC_STATIC, + staticHookSig, + null); + if (staticInit != null) { + staticInit.invoke_static_this(staticHookSig); + } + } + return staticHook; + } + + protected void init() { + } + + public int getAccess() { + return classInfo.getModifiers(); + } + + public Type getClassType() { + return classInfo.getType(); + } + + public Type getSuperType() { + return classInfo.getSuperType(); + } + + public void end_class() { + if (staticHook != null && staticInit == null) { + // force creation of static init + begin_static(); + } + if (staticInit != null) { + staticHook.return_value(); + staticHook.end_method(); + rawStaticInit.visitInsn(Constants.RETURN); + rawStaticInit.visitMaxs(0, 0); + staticInit = staticHook = null; + staticHookSig = null; + } + cv.visitEnd(); + } + + public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) { + if (classInfo == null) + throw new IllegalStateException("classInfo is null! " + this); + MethodVisitor v = cv.visitMethod(access, + sig.getName(), + sig.getDescriptor(), + null, + TypeUtils.toInternalNames(exceptions)); + if (sig.equals(Constants.SIG_STATIC) && !TypeUtils.isInterface(getAccess())) { + rawStaticInit = v; + MethodVisitor wrapped = new MethodVisitor(Opcodes.ASM5, v) { + public void visitMaxs(int maxStack, int maxLocals) { + // ignore + } + public void visitInsn(int insn) { + if (insn != Constants.RETURN) { + super.visitInsn(insn); + } + } + }; + staticInit = new CodeEmitter(this, wrapped, access, sig, exceptions); + if (staticHook == null) { + // force static hook creation + getStaticHook(); + } else { + staticInit.invoke_static_this(staticHookSig); + } + return staticInit; + } else if (sig.equals(staticHookSig)) { + return new CodeEmitter(this, v, access, sig, exceptions) { + public boolean isStaticHook() { + return true; + } + }; + } else { + return new CodeEmitter(this, v, access, sig, exceptions); + } + } + + public CodeEmitter begin_static() { + return begin_method(Constants.ACC_STATIC, Constants.SIG_STATIC, null); + } + + public void declare_field(int access, String name, Type type, Object value) { + FieldInfo existing = (FieldInfo)fieldInfo.get(name); + FieldInfo info = new FieldInfo(access, name, type, value); + if (existing != null) { + if (!info.equals(existing)) { + throw new IllegalArgumentException("Field \"" + name + "\" has been declared differently"); + } + } else { + fieldInfo.put(name, info); + cv.visitField(access, name, type.getDescriptor(), null, value); + } + } + + // TODO: make public? + boolean isFieldDeclared(String name) { + return fieldInfo.get(name) != null; + } + + FieldInfo getFieldInfo(String name) { + FieldInfo field = (FieldInfo)fieldInfo.get(name); + if (field == null) { + throw new IllegalArgumentException("Field " + name + " is not declared in " + getClassType().getClassName()); + } + return field; + } + + static class FieldInfo { + int access; + String name; + Type type; + Object value; + + public FieldInfo(int access, String name, Type type, Object value) { + this.access = access; + this.name = name; + this.type = type; + this.value = value; + } + + public boolean equals(Object o) { + if (o == null) + return false; + if (!(o instanceof FieldInfo)) + return false; + FieldInfo other = (FieldInfo)o; + if (access != other.access || + !name.equals(other.name) || + !type.equals(other.type)) { + return false; + } + if ((value == null) ^ (other.value == null)) + return false; + if (value != null && !value.equals(other.value)) + return false; + return true; + } + + public int hashCode() { + return access ^ name.hashCode() ^ type.hashCode() ^ ((value == null) ? 0 : value.hashCode()); + } + } + + public void visit(int version, + int access, + String name, + String signature, + String superName, + String[] interfaces) { + begin_class(version, + access, + name.replace('/', '.'), + TypeUtils.fromInternalName(superName), + TypeUtils.fromInternalNames(interfaces), + null); // TODO + } + + public void visitEnd() { + end_class(); + } + + public FieldVisitor visitField(int access, + String name, + String desc, + String signature, + Object value) { + declare_field(access, name, Type.getType(desc), value); + return null; // TODO + } + + public MethodVisitor visitMethod(int access, + String name, + String desc, + String signature, + String[] exceptions) { + return begin_method(access, + new Signature(name, desc), + TypeUtils.fromInternalNames(exceptions)); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/ClassGenerator.java b/blade-aop/src/main/java/net/sf/cglib/core/ClassGenerator.java new file mode 100644 index 000000000..fe61815f7 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/ClassGenerator.java @@ -0,0 +1,22 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.ClassVisitor; + +public interface ClassGenerator { + void generateClass(ClassVisitor v) throws Exception; +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/ClassInfo.java b/blade-aop/src/main/java/net/sf/cglib/core/ClassInfo.java new file mode 100644 index 000000000..2e066b537 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/ClassInfo.java @@ -0,0 +1,47 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Type; + +abstract public class ClassInfo { + + protected ClassInfo() { + } + + abstract public Type getType(); + abstract public Type getSuperType(); + abstract public Type[] getInterfaces(); + abstract public int getModifiers(); + + public boolean equals(Object o) { + if (o == null) + return false; + if (!(o instanceof ClassInfo)) + return false; + return getType().equals(((ClassInfo)o).getType()); + } + + public int hashCode() { + return getType().hashCode(); + } + + public String toString() { + // TODO: include modifiers, superType, interfaces + return getType().getClassName(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/ClassNameReader.java b/blade-aop/src/main/java/net/sf/cglib/core/ClassNameReader.java new file mode 100644 index 000000000..1e198e55e --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/ClassNameReader.java @@ -0,0 +1,63 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; + +import java.util.*; + +// TODO: optimize (ClassReader buffers entire class before accept) +public class ClassNameReader { + private ClassNameReader() { + } + + private static final EarlyExitException EARLY_EXIT = new EarlyExitException(); + private static class EarlyExitException extends RuntimeException { } + + public static String getClassName(ClassReader r) { + + return getClassInfo(r)[0]; + + } + + public static String[] getClassInfo(ClassReader r) { + final List array = new ArrayList(); + try { + r.accept(new ClassVisitor(Opcodes.ASM5, null) { + public void visit(int version, + int access, + String name, + String signature, + String superName, + String[] interfaces) { + array.add( name.replace('/', '.') ); + if(superName != null){ + array.add( superName.replace('/', '.') ); + } + for(int i = 0; i < interfaces.length; i++ ){ + array.add( interfaces[i].replace('/', '.') ); + } + + throw EARLY_EXIT; + } + }, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + } catch (EarlyExitException e) { } + + return (String[])array.toArray( new String[]{} ); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/ClassesKey.java b/blade-aop/src/main/java/net/sf/cglib/core/ClassesKey.java new file mode 100644 index 000000000..0a0d8df3c --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/ClassesKey.java @@ -0,0 +1,46 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +public class ClassesKey { + private static final Key FACTORY = (Key)KeyFactory.create(Key.class); + + interface Key { + Object newInstance(Object[] array); + } + + private ClassesKey() { + } + + public static Object create(Object[] array) { + return FACTORY.newInstance(classNames(array)); + } + + private static String[] classNames(Object[] objects) { + if (objects == null) { + return null; + } + String[] classNames = new String[objects.length]; + for (int i = 0; i < objects.length; i++) { + Object object = objects[i]; + if (object != null) { + Class aClass = object.getClass(); + classNames[i] = aClass == null ? null : aClass.getName(); + } + } + return classNames; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/CodeEmitter.java b/blade-aop/src/main/java/net/sf/cglib/core/CodeEmitter.java new file mode 100644 index 000000000..63150503d --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/CodeEmitter.java @@ -0,0 +1,864 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.io.*; +import java.util.*; +import org.objectweb.asm.*; + +/** + * @author Juozas Baliuka, Chris Nokleberg + */ +public class CodeEmitter extends LocalVariablesSorter { + private static final Signature BOOLEAN_VALUE = + TypeUtils.parseSignature("boolean booleanValue()"); + private static final Signature CHAR_VALUE = + TypeUtils.parseSignature("char charValue()"); + private static final Signature LONG_VALUE = + TypeUtils.parseSignature("long longValue()"); + private static final Signature DOUBLE_VALUE = + TypeUtils.parseSignature("double doubleValue()"); + private static final Signature FLOAT_VALUE = + TypeUtils.parseSignature("float floatValue()"); + private static final Signature INT_VALUE = + TypeUtils.parseSignature("int intValue()"); + private static final Signature CSTRUCT_NULL = + TypeUtils.parseConstructor(""); + private static final Signature CSTRUCT_STRING = + TypeUtils.parseConstructor("String"); + + public static final int ADD = Constants.IADD; + public static final int MUL = Constants.IMUL; + public static final int XOR = Constants.IXOR; + public static final int USHR = Constants.IUSHR; + public static final int SUB = Constants.ISUB; + public static final int DIV = Constants.IDIV; + public static final int NEG = Constants.INEG; + public static final int REM = Constants.IREM; + public static final int AND = Constants.IAND; + public static final int OR = Constants.IOR; + + public static final int GT = Constants.IFGT; + public static final int LT = Constants.IFLT; + public static final int GE = Constants.IFGE; + public static final int LE = Constants.IFLE; + public static final int NE = Constants.IFNE; + public static final int EQ = Constants.IFEQ; + + private ClassEmitter ce; + private State state; + + private static class State + extends MethodInfo + { + ClassInfo classInfo; + int access; + Signature sig; + Type[] argumentTypes; + int localOffset; + Type[] exceptionTypes; + + State(ClassInfo classInfo, int access, Signature sig, Type[] exceptionTypes) { + this.classInfo = classInfo; + this.access = access; + this.sig = sig; + this.exceptionTypes = exceptionTypes; + localOffset = TypeUtils.isStatic(access) ? 0 : 1; + argumentTypes = sig.getArgumentTypes(); + } + + public ClassInfo getClassInfo() { + return classInfo; + } + + public int getModifiers() { + return access; + } + + public Signature getSignature() { + return sig; + } + + public Type[] getExceptionTypes() { + return exceptionTypes; + } + + public Attribute getAttribute() { + // TODO + return null; + } + } + + CodeEmitter(ClassEmitter ce, MethodVisitor mv, int access, Signature sig, Type[] exceptionTypes) { + super(access, sig.getDescriptor(), mv); + this.ce = ce; + state = new State(ce.getClassInfo(), access, sig, exceptionTypes); + } + + public CodeEmitter(CodeEmitter wrap) { + super(wrap); + this.ce = wrap.ce; + this.state = wrap.state; + } + + public boolean isStaticHook() { + return false; + } + + public Signature getSignature() { + return state.sig; + } + + public Type getReturnType() { + return state.sig.getReturnType(); + } + + public MethodInfo getMethodInfo() { + return state; + } + + public ClassEmitter getClassEmitter() { + return ce; + } + + public void end_method() { + visitMaxs(0, 0); + } + + public Block begin_block() { + return new Block(this); + } + + public void catch_exception(Block block, Type exception) { + if (block.getEnd() == null) { + throw new IllegalStateException("end of block is unset"); + } + mv.visitTryCatchBlock(block.getStart(), + block.getEnd(), + mark(), + exception.getInternalName()); + } + + public void goTo(Label label) { mv.visitJumpInsn(Constants.GOTO, label); } + public void ifnull(Label label) { mv.visitJumpInsn(Constants.IFNULL, label); } + public void ifnonnull(Label label) { mv.visitJumpInsn(Constants.IFNONNULL, label); } + + public void if_jump(int mode, Label label) { + mv.visitJumpInsn(mode, label); + } + + public void if_icmp(int mode, Label label) { + if_cmp(Type.INT_TYPE, mode, label); + } + + public void if_cmp(Type type, int mode, Label label) { + int intOp = -1; + int jumpmode = mode; + switch (mode) { + case GE: jumpmode = LT; break; + case LE: jumpmode = GT; break; + } + switch (type.getSort()) { + case Type.LONG: + mv.visitInsn(Constants.LCMP); + break; + case Type.DOUBLE: + mv.visitInsn(Constants.DCMPG); + break; + case Type.FLOAT: + mv.visitInsn(Constants.FCMPG); + break; + case Type.ARRAY: + case Type.OBJECT: + switch (mode) { + case EQ: + mv.visitJumpInsn(Constants.IF_ACMPEQ, label); + return; + case NE: + mv.visitJumpInsn(Constants.IF_ACMPNE, label); + return; + } + throw new IllegalArgumentException("Bad comparison for type " + type); + default: + switch (mode) { + case EQ: intOp = Constants.IF_ICMPEQ; break; + case NE: intOp = Constants.IF_ICMPNE; break; + case GE: swap(); /* fall through */ + case LT: intOp = Constants.IF_ICMPLT; break; + case LE: swap(); /* fall through */ + case GT: intOp = Constants.IF_ICMPGT; break; + } + mv.visitJumpInsn(intOp, label); + return; + } + if_jump(jumpmode, label); + } + + public void pop() { mv.visitInsn(Constants.POP); } + public void pop2() { mv.visitInsn(Constants.POP2); } + public void dup() { mv.visitInsn(Constants.DUP); } + public void dup2() { mv.visitInsn(Constants.DUP2); } + public void dup_x1() { mv.visitInsn(Constants.DUP_X1); } + public void dup_x2() { mv.visitInsn(Constants.DUP_X2); } + public void dup2_x1() { mv.visitInsn(Constants.DUP2_X1); } + public void dup2_x2() { mv.visitInsn(Constants.DUP2_X2); } + public void swap() { mv.visitInsn(Constants.SWAP); } + public void aconst_null() { mv.visitInsn(Constants.ACONST_NULL); } + + public void swap(Type prev, Type type) { + if (type.getSize() == 1) { + if (prev.getSize() == 1) { + swap(); // same as dup_x1(), pop(); + } else { + dup_x2(); + pop(); + } + } else { + if (prev.getSize() == 1) { + dup2_x1(); + pop2(); + } else { + dup2_x2(); + pop2(); + } + } + } + + public void monitorenter() { mv.visitInsn(Constants.MONITORENTER); } + public void monitorexit() { mv.visitInsn(Constants.MONITOREXIT); } + + public void math(int op, Type type) { mv.visitInsn(type.getOpcode(op)); } + + public void array_load(Type type) { mv.visitInsn(type.getOpcode(Constants.IALOAD)); } + public void array_store(Type type) { mv.visitInsn(type.getOpcode(Constants.IASTORE)); } + + /** + * Casts from one primitive numeric type to another + */ + public void cast_numeric(Type from, Type to) { + if (from != to) { + if (from == Type.DOUBLE_TYPE) { + if (to == Type.FLOAT_TYPE) { + mv.visitInsn(Constants.D2F); + } else if (to == Type.LONG_TYPE) { + mv.visitInsn(Constants.D2L); + } else { + mv.visitInsn(Constants.D2I); + cast_numeric(Type.INT_TYPE, to); + } + } else if (from == Type.FLOAT_TYPE) { + if (to == Type.DOUBLE_TYPE) { + mv.visitInsn(Constants.F2D); + } else if (to == Type.LONG_TYPE) { + mv.visitInsn(Constants.F2L); + } else { + mv.visitInsn(Constants.F2I); + cast_numeric(Type.INT_TYPE, to); + } + } else if (from == Type.LONG_TYPE) { + if (to == Type.DOUBLE_TYPE) { + mv.visitInsn(Constants.L2D); + } else if (to == Type.FLOAT_TYPE) { + mv.visitInsn(Constants.L2F); + } else { + mv.visitInsn(Constants.L2I); + cast_numeric(Type.INT_TYPE, to); + } + } else { + if (to == Type.BYTE_TYPE) { + mv.visitInsn(Constants.I2B); + } else if (to == Type.CHAR_TYPE) { + mv.visitInsn(Constants.I2C); + } else if (to == Type.DOUBLE_TYPE) { + mv.visitInsn(Constants.I2D); + } else if (to == Type.FLOAT_TYPE) { + mv.visitInsn(Constants.I2F); + } else if (to == Type.LONG_TYPE) { + mv.visitInsn(Constants.I2L); + } else if (to == Type.SHORT_TYPE) { + mv.visitInsn(Constants.I2S); + } + } + } + } + + public void push(int i) { + if (i < -1) { + mv.visitLdcInsn(new Integer(i)); + } else if (i <= 5) { + mv.visitInsn(TypeUtils.ICONST(i)); + } else if (i <= Byte.MAX_VALUE) { + mv.visitIntInsn(Constants.BIPUSH, i); + } else if (i <= Short.MAX_VALUE) { + mv.visitIntInsn(Constants.SIPUSH, i); + } else { + mv.visitLdcInsn(new Integer(i)); + } + } + + public void push(long value) { + if (value == 0L || value == 1L) { + mv.visitInsn(TypeUtils.LCONST(value)); + } else { + mv.visitLdcInsn(new Long(value)); + } + } + + public void push(float value) { + if (value == 0f || value == 1f || value == 2f) { + mv.visitInsn(TypeUtils.FCONST(value)); + } else { + mv.visitLdcInsn(new Float(value)); + } + } + public void push(double value) { + if (value == 0d || value == 1d) { + mv.visitInsn(TypeUtils.DCONST(value)); + } else { + mv.visitLdcInsn(new Double(value)); + } + } + + public void push(String value) { + mv.visitLdcInsn(value); + } + + public void newarray() { + newarray(Constants.TYPE_OBJECT); + } + + public void newarray(Type type) { + if (TypeUtils.isPrimitive(type)) { + mv.visitIntInsn(Constants.NEWARRAY, TypeUtils.NEWARRAY(type)); + } else { + emit_type(Constants.ANEWARRAY, type); + } + } + + public void arraylength() { + mv.visitInsn(Constants.ARRAYLENGTH); + } + + public void load_this() { + if (TypeUtils.isStatic(state.access)) { + throw new IllegalStateException("no 'this' pointer within static method"); + } + mv.visitVarInsn(Constants.ALOAD, 0); + } + + /** + * Pushes all of the arguments of the current method onto the stack. + */ + public void load_args() { + load_args(0, state.argumentTypes.length); + } + + /** + * Pushes the specified argument of the current method onto the stack. + * @param index the zero-based index into the argument list + */ + public void load_arg(int index) { + load_local(state.argumentTypes[index], + state.localOffset + skipArgs(index)); + } + + // zero-based (see load_this) + public void load_args(int fromArg, int count) { + int pos = state.localOffset + skipArgs(fromArg); + for (int i = 0; i < count; i++) { + Type t = state.argumentTypes[fromArg + i]; + load_local(t, pos); + pos += t.getSize(); + } + } + + private int skipArgs(int numArgs) { + int amount = 0; + for (int i = 0; i < numArgs; i++) { + amount += state.argumentTypes[i].getSize(); + } + return amount; + } + + private void load_local(Type t, int pos) { + // TODO: make t == null ok? + mv.visitVarInsn(t.getOpcode(Constants.ILOAD), pos); + } + + private void store_local(Type t, int pos) { + // TODO: make t == null ok? + mv.visitVarInsn(t.getOpcode(Constants.ISTORE), pos); + } + + public void iinc(Local local, int amount) { + mv.visitIincInsn(local.getIndex(), amount); + } + + public void store_local(Local local) { + store_local(local.getType(), local.getIndex()); + } + + public void load_local(Local local) { + load_local(local.getType(), local.getIndex()); + } + + public void return_value() { + mv.visitInsn(state.sig.getReturnType().getOpcode(Constants.IRETURN)); + } + + public void getfield(String name) { + ClassEmitter.FieldInfo info = ce.getFieldInfo(name); + int opcode = TypeUtils.isStatic(info.access) ? Constants.GETSTATIC : Constants.GETFIELD; + emit_field(opcode, ce.getClassType(), name, info.type); + } + + public void putfield(String name) { + ClassEmitter.FieldInfo info = ce.getFieldInfo(name); + int opcode = TypeUtils.isStatic(info.access) ? Constants.PUTSTATIC : Constants.PUTFIELD; + emit_field(opcode, ce.getClassType(), name, info.type); + } + + public void super_getfield(String name, Type type) { + emit_field(Constants.GETFIELD, ce.getSuperType(), name, type); + } + + public void super_putfield(String name, Type type) { + emit_field(Constants.PUTFIELD, ce.getSuperType(), name, type); + } + + public void super_getstatic(String name, Type type) { + emit_field(Constants.GETSTATIC, ce.getSuperType(), name, type); + } + + public void super_putstatic(String name, Type type) { + emit_field(Constants.PUTSTATIC, ce.getSuperType(), name, type); + } + + public void getfield(Type owner, String name, Type type) { + emit_field(Constants.GETFIELD, owner, name, type); + } + + public void putfield(Type owner, String name, Type type) { + emit_field(Constants.PUTFIELD, owner, name, type); + } + + public void getstatic(Type owner, String name, Type type) { + emit_field(Constants.GETSTATIC, owner, name, type); + } + + public void putstatic(Type owner, String name, Type type) { + emit_field(Constants.PUTSTATIC, owner, name, type); + } + + // package-protected for EmitUtils, try to fix + void emit_field(int opcode, Type ctype, String name, Type ftype) { + mv.visitFieldInsn(opcode, + ctype.getInternalName(), + name, + ftype.getDescriptor()); + } + + public void super_invoke() { + super_invoke(state.sig); + } + + public void super_invoke(Signature sig) { + emit_invoke(Constants.INVOKESPECIAL, ce.getSuperType(), sig); + } + + public void invoke_constructor(Type type) { + invoke_constructor(type, CSTRUCT_NULL); + } + + public void super_invoke_constructor() { + invoke_constructor(ce.getSuperType()); + } + + public void invoke_constructor_this() { + invoke_constructor(ce.getClassType()); + } + + private void emit_invoke(int opcode, Type type, Signature sig) { + if (sig.getName().equals(Constants.CONSTRUCTOR_NAME) && + ((opcode == Constants.INVOKEVIRTUAL) || + (opcode == Constants.INVOKESTATIC))) { + // TODO: error + } + mv.visitMethodInsn(opcode, + type.getInternalName(), + sig.getName(), + sig.getDescriptor(), + opcode == Opcodes.INVOKEINTERFACE); + } + + public void invoke_interface(Type owner, Signature sig) { + emit_invoke(Constants.INVOKEINTERFACE, owner, sig); + } + + public void invoke_virtual(Type owner, Signature sig) { + emit_invoke(Constants.INVOKEVIRTUAL, owner, sig); + } + + public void invoke_static(Type owner, Signature sig) { + emit_invoke(Constants.INVOKESTATIC, owner, sig); + } + + public void invoke_virtual_this(Signature sig) { + invoke_virtual(ce.getClassType(), sig); + } + + public void invoke_static_this(Signature sig) { + invoke_static(ce.getClassType(), sig); + } + + public void invoke_constructor(Type type, Signature sig) { + emit_invoke(Constants.INVOKESPECIAL, type, sig); + } + + public void invoke_constructor_this(Signature sig) { + invoke_constructor(ce.getClassType(), sig); + } + + public void super_invoke_constructor(Signature sig) { + invoke_constructor(ce.getSuperType(), sig); + } + + public void new_instance_this() { + new_instance(ce.getClassType()); + } + + public void new_instance(Type type) { + emit_type(Constants.NEW, type); + } + + private void emit_type(int opcode, Type type) { + String desc; + if (TypeUtils.isArray(type)) { + desc = type.getDescriptor(); + } else { + desc = type.getInternalName(); + } + mv.visitTypeInsn(opcode, desc); + } + + public void aaload(int index) { + push(index); + aaload(); + } + + public void aaload() { mv.visitInsn(Constants.AALOAD); } + public void aastore() { mv.visitInsn(Constants.AASTORE); } + public void athrow() { mv.visitInsn(Constants.ATHROW); } + + public Label make_label() { + return new Label(); + } + + public Local make_local() { + return make_local(Constants.TYPE_OBJECT); + } + + public Local make_local(Type type) { + return new Local(newLocal(type.getSize()), type); + } + + public void checkcast_this() { + checkcast(ce.getClassType()); + } + + public void checkcast(Type type) { + if (!type.equals(Constants.TYPE_OBJECT)) { + emit_type(Constants.CHECKCAST, type); + } + } + + public void instance_of(Type type) { + emit_type(Constants.INSTANCEOF, type); + } + + public void instance_of_this() { + instance_of(ce.getClassType()); + } + + public void process_switch(int[] keys, ProcessSwitchCallback callback) { + float density; + if (keys.length == 0) { + density = 0; + } else { + density = (float)keys.length / (keys[keys.length - 1] - keys[0] + 1); + } + process_switch(keys, callback, density >= 0.5f); + } + + public void process_switch(int[] keys, ProcessSwitchCallback callback, boolean useTable) { + if (!isSorted(keys)) + throw new IllegalArgumentException("keys to switch must be sorted ascending"); + Label def = make_label(); + Label end = make_label(); + + try { + if (keys.length > 0) { + int len = keys.length; + int min = keys[0]; + int max = keys[len - 1]; + int range = max - min + 1; + + if (useTable) { + Label[] labels = new Label[range]; + Arrays.fill(labels, def); + for (int i = 0; i < len; i++) { + labels[keys[i] - min] = make_label(); + } + mv.visitTableSwitchInsn(min, max, def, labels); + for (int i = 0; i < range; i++) { + Label label = labels[i]; + if (label != def) { + mark(label); + callback.processCase(i + min, end); + } + } + } else { + Label[] labels = new Label[len]; + for (int i = 0; i < len; i++) { + labels[i] = make_label(); + } + mv.visitLookupSwitchInsn(def, keys, labels); + for (int i = 0; i < len; i++) { + mark(labels[i]); + callback.processCase(keys[i], end); + } + } + } + + mark(def); + callback.processDefault(); + mark(end); + + } catch (RuntimeException e) { + throw e; + } catch (Error e) { + throw e; + } catch (Exception e) { + throw new CodeGenerationException(e); + } + } + + private static boolean isSorted(int[] keys) { + for (int i = 1; i < keys.length; i++) { + if (keys[i] < keys[i - 1]) + return false; + } + return true; + } + + public void mark(Label label) { + mv.visitLabel(label); + } + + Label mark() { + Label label = make_label(); + mv.visitLabel(label); + return label; + } + + public void push(boolean value) { + push(value ? 1 : 0); + } + + /** + * Toggles the integer on the top of the stack from 1 to 0 or vice versa + */ + public void not() { + push(1); + math(XOR, Type.INT_TYPE); + } + + public void throw_exception(Type type, String msg) { + new_instance(type); + dup(); + push(msg); + invoke_constructor(type, CSTRUCT_STRING); + athrow(); + } + + /** + * If the argument is a primitive class, replaces the primitive value + * on the top of the stack with the wrapped (Object) equivalent. For + * example, char -> Character. + * If the class is Void, a null is pushed onto the stack instead. + * @param type the class indicating the current type of the top stack value + */ + public void box(Type type) { + if (TypeUtils.isPrimitive(type)) { + if (type == Type.VOID_TYPE) { + aconst_null(); + } else { + Type boxed = TypeUtils.getBoxedType(type); + new_instance(boxed); + if (type.getSize() == 2) { + // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o + dup_x2(); + dup_x2(); + pop(); + } else { + // p -> po -> opo -> oop -> o + dup_x1(); + swap(); + } + invoke_constructor(boxed, new Signature(Constants.CONSTRUCTOR_NAME, Type.VOID_TYPE, new Type[]{ type })); + } + } + } + + /** + * If the argument is a primitive class, replaces the object + * on the top of the stack with the unwrapped (primitive) + * equivalent. For example, Character -> char. + * @param type the class indicating the desired type of the top stack value + * @return true if the value was unboxed + */ + public void unbox(Type type) { + Type t = Constants.TYPE_NUMBER; + Signature sig = null; + switch (type.getSort()) { + case Type.VOID: + return; + case Type.CHAR: + t = Constants.TYPE_CHARACTER; + sig = CHAR_VALUE; + break; + case Type.BOOLEAN: + t = Constants.TYPE_BOOLEAN; + sig = BOOLEAN_VALUE; + break; + case Type.DOUBLE: + sig = DOUBLE_VALUE; + break; + case Type.FLOAT: + sig = FLOAT_VALUE; + break; + case Type.LONG: + sig = LONG_VALUE; + break; + case Type.INT: + case Type.SHORT: + case Type.BYTE: + sig = INT_VALUE; + } + + if (sig == null) { + checkcast(type); + } else { + checkcast(t); + invoke_virtual(t, sig); + } + } + + /** + * Allocates and fills an Object[] array with the arguments to the + * current method. Primitive values are inserted as their boxed + * (Object) equivalents. + */ + public void create_arg_array() { + /* generates: + Object[] args = new Object[]{ arg1, new Integer(arg2) }; + */ + + push(state.argumentTypes.length); + newarray(); + for (int i = 0; i < state.argumentTypes.length; i++) { + dup(); + push(i); + load_arg(i); + box(state.argumentTypes[i]); + aastore(); + } + } + + + /** + * Pushes a zero onto the stack if the argument is a primitive class, or a null otherwise. + */ + public void zero_or_null(Type type) { + if (TypeUtils.isPrimitive(type)) { + switch (type.getSort()) { + case Type.DOUBLE: + push(0d); + break; + case Type.LONG: + push(0L); + break; + case Type.FLOAT: + push(0f); + break; + case Type.VOID: + aconst_null(); + default: + push(0); + } + } else { + aconst_null(); + } + } + + /** + * Unboxes the object on the top of the stack. If the object is null, the + * unboxed primitive value becomes zero. + */ + public void unbox_or_zero(Type type) { + if (TypeUtils.isPrimitive(type)) { + if (type != Type.VOID_TYPE) { + Label nonNull = make_label(); + Label end = make_label(); + dup(); + ifnonnull(nonNull); + pop(); + zero_or_null(type); + goTo(end); + mark(nonNull); + unbox(type); + mark(end); + } + } else { + checkcast(type); + } + } + + public void visitMaxs(int maxStack, int maxLocals) { + if (!TypeUtils.isAbstract(state.access)) { + mv.visitMaxs(0, 0); + } + } + + public void invoke(MethodInfo method, Type virtualType) { + ClassInfo classInfo = method.getClassInfo(); + Type type = classInfo.getType(); + Signature sig = method.getSignature(); + if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) { + invoke_constructor(type, sig); + } else if (TypeUtils.isInterface(classInfo.getModifiers())) { + invoke_interface(type, sig); + } else if (TypeUtils.isStatic(method.getModifiers())) { + invoke_static(type, sig); + } else { + invoke_virtual(virtualType, sig); + } + } + + public void invoke(MethodInfo method) { + invoke(method, method.getClassInfo().getType()); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/CodeGenerationException.java b/blade-aop/src/main/java/net/sf/cglib/core/CodeGenerationException.java new file mode 100644 index 000000000..14824e29d --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/CodeGenerationException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +/** + * @version $Id: CodeGenerationException.java,v 1.3 2004/06/24 21:15:21 herbyderby Exp $ + */ +public class CodeGenerationException extends RuntimeException { + private Throwable cause; + + public CodeGenerationException(Throwable cause) { + super(cause.getClass().getName() + "-->" + cause.getMessage()); + this.cause = cause; + } + + public Throwable getCause() { + return cause; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/CollectionUtils.java b/blade-aop/src/main/java/net/sf/cglib/core/CollectionUtils.java new file mode 100644 index 000000000..60e5140fe --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/CollectionUtils.java @@ -0,0 +1,76 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.util.*; +import java.lang.reflect.Array; + +/** + * @author Chris Nokleberg + * @version $Id: CollectionUtils.java,v 1.7 2004/06/24 21:15:21 herbyderby Exp $ + */ +public class CollectionUtils { + private CollectionUtils() { } + + public static Map bucket(Collection c, Transformer t) { + Map buckets = new HashMap(); + for (Iterator it = c.iterator(); it.hasNext();) { + Object value = (Object)it.next(); + Object key = t.transform(value); + List bucket = (List)buckets.get(key); + if (bucket == null) { + buckets.put(key, bucket = new LinkedList()); + } + bucket.add(value); + } + return buckets; + } + + public static void reverse(Map source, Map target) { + for (Iterator it = source.keySet().iterator(); it.hasNext();) { + Object key = it.next(); + target.put(source.get(key), key); + } + } + + public static Collection filter(Collection c, Predicate p) { + Iterator it = c.iterator(); + while (it.hasNext()) { + if (!p.evaluate(it.next())) { + it.remove(); + } + } + return c; + } + + public static List transform(Collection c, Transformer t) { + List result = new ArrayList(c.size()); + for (Iterator it = c.iterator(); it.hasNext();) { + result.add(t.transform(it.next())); + } + return result; + } + + public static Map getIndexMap(List list) { + Map indexes = new HashMap(); + int index = 0; + for (Iterator it = list.iterator(); it.hasNext();) { + indexes.put(it.next(), new Integer(index++)); + } + return indexes; + } +} + diff --git a/blade-aop/src/main/java/net/sf/cglib/core/Constants.java b/blade-aop/src/main/java/net/sf/cglib/core/Constants.java new file mode 100644 index 000000000..c652bc568 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/Constants.java @@ -0,0 +1,68 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.Type; + +/** + * @author Juozas Baliuka baliuka@mwm.lt + * @version $Id: Constants.java,v 1.21 2006/03/05 02:43:19 herbyderby Exp $ + */ +public interface Constants extends org.objectweb.asm.Opcodes { + public static final Class[] EMPTY_CLASS_ARRAY = {}; + public static final Type[] TYPES_EMPTY = {}; + + public static final Signature SIG_STATIC = + TypeUtils.parseSignature("void ()"); + + public static final Type TYPE_OBJECT_ARRAY = TypeUtils.parseType("Object[]"); + public static final Type TYPE_CLASS_ARRAY = TypeUtils.parseType("Class[]"); + public static final Type TYPE_STRING_ARRAY = TypeUtils.parseType("String[]"); + + public static final Type TYPE_OBJECT = TypeUtils.parseType("Object"); + public static final Type TYPE_CLASS = TypeUtils.parseType("Class"); + public static final Type TYPE_CLASS_LOADER = TypeUtils.parseType("ClassLoader"); + public static final Type TYPE_CHARACTER = TypeUtils.parseType("Character"); + public static final Type TYPE_BOOLEAN = TypeUtils.parseType("Boolean"); + public static final Type TYPE_DOUBLE = TypeUtils.parseType("Double"); + public static final Type TYPE_FLOAT = TypeUtils.parseType("Float"); + public static final Type TYPE_LONG = TypeUtils.parseType("Long"); + public static final Type TYPE_INTEGER = TypeUtils.parseType("Integer"); + public static final Type TYPE_SHORT = TypeUtils.parseType("Short"); + public static final Type TYPE_BYTE = TypeUtils.parseType("Byte"); + public static final Type TYPE_NUMBER = TypeUtils.parseType("Number"); + public static final Type TYPE_STRING = TypeUtils.parseType("String"); + public static final Type TYPE_THROWABLE = TypeUtils.parseType("Throwable"); + public static final Type TYPE_BIG_INTEGER = TypeUtils.parseType("java.math.BigInteger"); + public static final Type TYPE_BIG_DECIMAL = TypeUtils.parseType("java.math.BigDecimal"); + public static final Type TYPE_STRING_BUFFER = TypeUtils.parseType("StringBuffer"); + public static final Type TYPE_RUNTIME_EXCEPTION = TypeUtils.parseType("RuntimeException"); + public static final Type TYPE_ERROR = TypeUtils.parseType("Error"); + public static final Type TYPE_SYSTEM = TypeUtils.parseType("System"); + public static final Type TYPE_SIGNATURE = TypeUtils.parseType("net.sf.cglib.core.Signature"); + public static final Type TYPE_TYPE = Type.getType(Type.class); + + public static final String CONSTRUCTOR_NAME = ""; + public static final String STATIC_NAME = ""; + public static final String SOURCE_FILE = ""; + public static final String SUID_FIELD_NAME = "serialVersionUID"; + + public static final int PRIVATE_FINAL_STATIC = ACC_PRIVATE | ACC_FINAL | ACC_STATIC; + + public static final int SWITCH_STYLE_TRIE = 0; + public static final int SWITCH_STYLE_HASH = 1; + public static final int SWITCH_STYLE_HASHONLY = 2; +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/Converter.java b/blade-aop/src/main/java/net/sf/cglib/core/Converter.java new file mode 100644 index 000000000..00414358d --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/Converter.java @@ -0,0 +1,20 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +public interface Converter { + Object convert(Object value, Class target, Object context); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/Customizer.java b/blade-aop/src/main/java/net/sf/cglib/core/Customizer.java new file mode 100644 index 000000000..4297b163a --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/Customizer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.Type; + +/** + * Customizes key types for {@link KeyFactory} when building equals, hashCode, and toString. + * For customization of field types, use {@link FieldTypeCustomizer} + * + * @see KeyFactory#CLASS_BY_NAME + */ +public interface Customizer extends KeyFactoryCustomizer { + void customize(CodeEmitter e, Type type); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/DebuggingClassWriter.java b/blade-aop/src/main/java/net/sf/cglib/core/DebuggingClassWriter.java new file mode 100644 index 000000000..78f1ae7d4 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/DebuggingClassWriter.java @@ -0,0 +1,114 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; + +import java.io.*; +import java.lang.reflect.Constructor; + +public class DebuggingClassWriter extends ClassVisitor { + + public static final String DEBUG_LOCATION_PROPERTY = "cglib.debugLocation"; + + private static String debugLocation; + private static Constructor traceCtor; + + private String className; + private String superName; + + static { + debugLocation = System.getProperty(DEBUG_LOCATION_PROPERTY); + if (debugLocation != null) { + System.err.println("CGLIB debugging enabled, writing to '" + debugLocation + "'"); + try { + Class clazz = Class.forName("org.objectweb.asm.util.TraceClassVisitor"); + traceCtor = clazz.getConstructor(new Class[]{ClassVisitor.class, PrintWriter.class}); + } catch (Throwable ignore) { + } + } + } + + public DebuggingClassWriter(int flags) { + super(Opcodes.ASM5, new ClassWriter(flags)); + } + + public void visit(int version, + int access, + String name, + String signature, + String superName, + String[] interfaces) { + className = name.replace('/', '.'); + this.superName = superName.replace('/', '.'); + super.visit(version, access, name, signature, superName, interfaces); + } + + public String getClassName() { + return className; + } + + public String getSuperName() { + return superName; + } + + public byte[] toByteArray() { + + return (byte[]) java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + + + byte[] b = ((ClassWriter) DebuggingClassWriter.super.cv).toByteArray(); + if (debugLocation != null) { + String dirs = className.replace('.', File.separatorChar); + try { + new File(debugLocation + File.separatorChar + dirs).getParentFile().mkdirs(); + + File file = new File(new File(debugLocation), dirs + ".class"); + OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); + try { + out.write(b); + } finally { + out.close(); + } + + if (traceCtor != null) { + file = new File(new File(debugLocation), dirs + ".asm"); + out = new BufferedOutputStream(new FileOutputStream(file)); + try { + ClassReader cr = new ClassReader(b); + PrintWriter pw = new PrintWriter(new OutputStreamWriter(out)); + ClassVisitor tcv = (ClassVisitor)traceCtor.newInstance(new Object[]{null, pw}); + cr.accept(tcv, 0); + pw.flush(); + } finally { + out.close(); + } + } + } catch (Exception e) { + throw new CodeGenerationException(e); + } + } + return b; + } + }); + + } + } diff --git a/blade-aop/src/main/java/net/sf/cglib/core/DefaultGeneratorStrategy.java b/blade-aop/src/main/java/net/sf/cglib/core/DefaultGeneratorStrategy.java new file mode 100644 index 000000000..dd876c760 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/DefaultGeneratorStrategy.java @@ -0,0 +1,47 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.ClassWriter; + +public class DefaultGeneratorStrategy implements GeneratorStrategy { + public static final DefaultGeneratorStrategy INSTANCE = new DefaultGeneratorStrategy(); + + public byte[] generate(ClassGenerator cg) throws Exception { + DebuggingClassWriter cw = getClassVisitor(); + transform(cg).generateClass(cw); + return transform(cw.toByteArray()); + } + + protected DebuggingClassWriter getClassVisitor() throws Exception { + return new DebuggingClassWriter(ClassWriter.COMPUTE_FRAMES); + } + + protected final ClassWriter getClassWriter() { + // Cause compile / runtime errors for people who implemented the old + // interface without using @Override + throw new UnsupportedOperationException("You are calling " + + "getClassWriter, which no longer exists in this cglib version."); + } + + protected byte[] transform(byte[] b) throws Exception { + return b; + } + + protected ClassGenerator transform(ClassGenerator cg) throws Exception { + return cg; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/DefaultNamingPolicy.java b/blade-aop/src/main/java/net/sf/cglib/core/DefaultNamingPolicy.java new file mode 100644 index 000000000..dfdb6ab63 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/DefaultNamingPolicy.java @@ -0,0 +1,71 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.util.Set; + +/** + * The default policy used by {@link AbstractClassGenerator}. + * Generates names such as + *

net.sf.cglib.Foo$$EnhancerByCGLIB$$38272841

+ * This is composed of a prefix based on the name of the superclass, a fixed + * string incorporating the CGLIB class responsible for generation, and a + * hashcode derived from the parameters used to create the object. If the same + * name has been previously been used in the same ClassLoader, a + * suffix is added to ensure uniqueness. + */ +public class DefaultNamingPolicy implements NamingPolicy { + public static final DefaultNamingPolicy INSTANCE = new DefaultNamingPolicy(); + + /** + * This allows to test collisions of {@code key.hashCode()}. + */ + private final static boolean STRESS_HASH_CODE = Boolean.getBoolean("net.sf.cglib.test.stressHashCodes"); + + public String getClassName(String prefix, String source, Object key, Predicate names) { + if (prefix == null) { + prefix = "net.sf.cglib.empty.Object"; + } else if (prefix.startsWith("java")) { + prefix = "$" + prefix; + } + String base = + prefix + "$$" + + source.substring(source.lastIndexOf('.') + 1) + + getTag() + "$$" + + Integer.toHexString(STRESS_HASH_CODE ? 0 : key.hashCode()); + String attempt = base; + int index = 2; + while (names.evaluate(attempt)) + attempt = base + "_" + index++; + return attempt; + } + + /** + * Returns a string which is incorporated into every generated class name. + * By default returns "ByCGLIB" + */ + protected String getTag() { + return "ByCGLIB"; + } + + public int hashCode() { + return getTag().hashCode(); + } + + public boolean equals(Object o) { + return (o instanceof DefaultNamingPolicy) && ((DefaultNamingPolicy) o).getTag().equals(getTag()); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/DuplicatesPredicate.java b/blade-aop/src/main/java/net/sf/cglib/core/DuplicatesPredicate.java new file mode 100644 index 000000000..6ebee2c35 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/DuplicatesPredicate.java @@ -0,0 +1,27 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.lang.reflect.Method; +import java.util.*; + +public class DuplicatesPredicate implements Predicate { + private Set unique = new HashSet(); + + public boolean evaluate(Object arg) { + return unique.add(MethodWrapper.create((Method)arg)); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/EmitUtils.java b/blade-aop/src/main/java/net/sf/cglib/core/EmitUtils.java new file mode 100644 index 000000000..07bdab156 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/EmitUtils.java @@ -0,0 +1,960 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; + +import net.sf.cglib.core.internal.CustomizerRegistry; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +public class EmitUtils { + private static final Signature CSTRUCT_NULL = + TypeUtils.parseConstructor(""); + private static final Signature CSTRUCT_THROWABLE = + TypeUtils.parseConstructor("Throwable"); + + private static final Signature GET_NAME = + TypeUtils.parseSignature("String getName()"); + private static final Signature HASH_CODE = + TypeUtils.parseSignature("int hashCode()"); + private static final Signature EQUALS = + TypeUtils.parseSignature("boolean equals(Object)"); + private static final Signature STRING_LENGTH = + TypeUtils.parseSignature("int length()"); + private static final Signature STRING_CHAR_AT = + TypeUtils.parseSignature("char charAt(int)"); + private static final Signature FOR_NAME = + TypeUtils.parseSignature("Class forName(String)"); + private static final Signature DOUBLE_TO_LONG_BITS = + TypeUtils.parseSignature("long doubleToLongBits(double)"); + private static final Signature FLOAT_TO_INT_BITS = + TypeUtils.parseSignature("int floatToIntBits(float)"); + private static final Signature TO_STRING = + TypeUtils.parseSignature("String toString()"); + private static final Signature APPEND_STRING = + TypeUtils.parseSignature("StringBuffer append(String)"); + private static final Signature APPEND_INT = + TypeUtils.parseSignature("StringBuffer append(int)"); + private static final Signature APPEND_DOUBLE = + TypeUtils.parseSignature("StringBuffer append(double)"); + private static final Signature APPEND_FLOAT = + TypeUtils.parseSignature("StringBuffer append(float)"); + private static final Signature APPEND_CHAR = + TypeUtils.parseSignature("StringBuffer append(char)"); + private static final Signature APPEND_LONG = + TypeUtils.parseSignature("StringBuffer append(long)"); + private static final Signature APPEND_BOOLEAN = + TypeUtils.parseSignature("StringBuffer append(boolean)"); + private static final Signature LENGTH = + TypeUtils.parseSignature("int length()"); + private static final Signature SET_LENGTH = + TypeUtils.parseSignature("void setLength(int)"); + private static final Signature GET_DECLARED_METHOD = + TypeUtils.parseSignature("java.lang.reflect.Method getDeclaredMethod(String, Class[])"); + + + + public static final ArrayDelimiters DEFAULT_DELIMITERS = new ArrayDelimiters("{", ", ", "}"); + + private EmitUtils() { + } + + public static void factory_method(ClassEmitter ce, Signature sig) { + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, sig, null); + e.new_instance_this(); + e.dup(); + e.load_args(); + e.invoke_constructor_this(TypeUtils.parseConstructor(sig.getArgumentTypes())); + e.return_value(); + e.end_method(); + } + + public static void null_constructor(ClassEmitter ce) { + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_NULL, null); + e.load_this(); + e.super_invoke_constructor(); + e.return_value(); + e.end_method(); + } + + /** + * Process an array on the stack. Assumes the top item on the stack + * is an array of the specified type. For each element in the array, + * puts the element on the stack and triggers the callback. + * @param type the type of the array (type.isArray() must be true) + * @param callback the callback triggered for each element + */ + public static void process_array(CodeEmitter e, Type type, ProcessArrayCallback callback) { + Type componentType = TypeUtils.getComponentType(type); + Local array = e.make_local(); + Local loopvar = e.make_local(Type.INT_TYPE); + Label loopbody = e.make_label(); + Label checkloop = e.make_label(); + e.store_local(array); + e.push(0); + e.store_local(loopvar); + e.goTo(checkloop); + + e.mark(loopbody); + e.load_local(array); + e.load_local(loopvar); + e.array_load(componentType); + callback.processElement(componentType); + e.iinc(loopvar, 1); + + e.mark(checkloop); + e.load_local(loopvar); + e.load_local(array); + e.arraylength(); + e.if_icmp(e.LT, loopbody); + } + + /** + * Process two arrays on the stack in parallel. Assumes the top two items on the stack + * are arrays of the specified class. The arrays must be the same length. For each pair + * of elements in the arrays, puts the pair on the stack and triggers the callback. + * @param type the type of the arrays (type.isArray() must be true) + * @param callback the callback triggered for each pair of elements + */ + public static void process_arrays(CodeEmitter e, Type type, ProcessArrayCallback callback) { + Type componentType = TypeUtils.getComponentType(type); + Local array1 = e.make_local(); + Local array2 = e.make_local(); + Local loopvar = e.make_local(Type.INT_TYPE); + Label loopbody = e.make_label(); + Label checkloop = e.make_label(); + e.store_local(array1); + e.store_local(array2); + e.push(0); + e.store_local(loopvar); + e.goTo(checkloop); + + e.mark(loopbody); + e.load_local(array1); + e.load_local(loopvar); + e.array_load(componentType); + e.load_local(array2); + e.load_local(loopvar); + e.array_load(componentType); + callback.processElement(componentType); + e.iinc(loopvar, 1); + + e.mark(checkloop); + e.load_local(loopvar); + e.load_local(array1); + e.arraylength(); + e.if_icmp(e.LT, loopbody); + } + + public static void string_switch(CodeEmitter e, String[] strings, int switchStyle, ObjectSwitchCallback callback) { + try { + switch (switchStyle) { + case Constants.SWITCH_STYLE_TRIE: + string_switch_trie(e, strings, callback); + break; + case Constants.SWITCH_STYLE_HASH: + string_switch_hash(e, strings, callback, false); + break; + case Constants.SWITCH_STYLE_HASHONLY: + string_switch_hash(e, strings, callback, true); + break; + default: + throw new IllegalArgumentException("unknown switch style " + switchStyle); + } + } catch (RuntimeException ex) { + throw ex; + } catch (Error ex) { + throw ex; + } catch (Exception ex) { + throw new CodeGenerationException(ex); + } + } + + private static void string_switch_trie(final CodeEmitter e, + String[] strings, + final ObjectSwitchCallback callback) throws Exception { + final Label def = e.make_label(); + final Label end = e.make_label(); + final Map buckets = CollectionUtils.bucket(Arrays.asList(strings), new Transformer() { + public Object transform(Object value) { + return new Integer(((String)value).length()); + } + }); + e.dup(); + e.invoke_virtual(Constants.TYPE_STRING, STRING_LENGTH); + e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() { + public void processCase(int key, Label ignore_end) throws Exception { + List bucket = (List)buckets.get(new Integer(key)); + stringSwitchHelper(e, bucket, callback, def, end, 0); + } + public void processDefault() { + e.goTo(def); + } + }); + e.mark(def); + e.pop(); + callback.processDefault(); + e.mark(end); + } + + private static void stringSwitchHelper(final CodeEmitter e, + List strings, + final ObjectSwitchCallback callback, + final Label def, + final Label end, + final int index) throws Exception { + final int len = ((String)strings.get(0)).length(); + final Map buckets = CollectionUtils.bucket(strings, new Transformer() { + public Object transform(Object value) { + return new Integer(((String)value).charAt(index)); + } + }); + e.dup(); + e.push(index); + e.invoke_virtual(Constants.TYPE_STRING, STRING_CHAR_AT); + e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() { + public void processCase(int key, Label ignore_end) throws Exception { + List bucket = (List)buckets.get(new Integer(key)); + if (index + 1 == len) { + e.pop(); + callback.processCase(bucket.get(0), end); + } else { + stringSwitchHelper(e, bucket, callback, def, end, index + 1); + } + } + public void processDefault() { + e.goTo(def); + } + }); + } + + static int[] getSwitchKeys(Map buckets) { + int[] keys = new int[buckets.size()]; + int index = 0; + for (Iterator it = buckets.keySet().iterator(); it.hasNext();) { + keys[index++] = ((Integer)it.next()).intValue(); + } + Arrays.sort(keys); + return keys; + } + + private static void string_switch_hash(final CodeEmitter e, + final String[] strings, + final ObjectSwitchCallback callback, + final boolean skipEquals) throws Exception { + final Map buckets = CollectionUtils.bucket(Arrays.asList(strings), new Transformer() { + public Object transform(Object value) { + return new Integer(value.hashCode()); + } + }); + final Label def = e.make_label(); + final Label end = e.make_label(); + e.dup(); + e.invoke_virtual(Constants.TYPE_OBJECT, HASH_CODE); + e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() { + public void processCase(int key, Label ignore_end) throws Exception { + List bucket = (List)buckets.get(new Integer(key)); + Label next = null; + if (skipEquals && bucket.size() == 1) { + if (skipEquals) + e.pop(); + callback.processCase((String)bucket.get(0), end); + } else { + for (Iterator it = bucket.iterator(); it.hasNext();) { + String string = (String)it.next(); + if (next != null) { + e.mark(next); + } + if (it.hasNext()) { + e.dup(); + } + e.push(string); + e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS); + if (it.hasNext()) { + e.if_jump(e.EQ, next = e.make_label()); + e.pop(); + } else { + e.if_jump(e.EQ, def); + } + callback.processCase(string, end); + } + } + } + public void processDefault() { + e.pop(); + } + }); + e.mark(def); + callback.processDefault(); + e.mark(end); + } + + public static void load_class_this(CodeEmitter e) { + load_class_helper(e, e.getClassEmitter().getClassType()); + } + + public static void load_class(CodeEmitter e, Type type) { + if (TypeUtils.isPrimitive(type)) { + if (type == Type.VOID_TYPE) { + throw new IllegalArgumentException("cannot load void type"); + } + e.getstatic(TypeUtils.getBoxedType(type), "TYPE", Constants.TYPE_CLASS); + } else { + load_class_helper(e, type); + } + } + + private static void load_class_helper(CodeEmitter e, final Type type) { + if (e.isStaticHook()) { + // have to fall back on non-optimized load + e.push(TypeUtils.emulateClassGetName(type)); + e.invoke_static(Constants.TYPE_CLASS, FOR_NAME); + } else { + ClassEmitter ce = e.getClassEmitter(); + String typeName = TypeUtils.emulateClassGetName(type); + + // TODO: can end up with duplicated field names when using chained transformers; incorporate static hook # somehow + String fieldName = "CGLIB$load_class$" + TypeUtils.escapeType(typeName); + if (!ce.isFieldDeclared(fieldName)) { + ce.declare_field(Constants.PRIVATE_FINAL_STATIC, fieldName, Constants.TYPE_CLASS, null); + CodeEmitter hook = ce.getStaticHook(); + hook.push(typeName); + hook.invoke_static(Constants.TYPE_CLASS, FOR_NAME); + hook.putstatic(ce.getClassType(), fieldName, Constants.TYPE_CLASS); + } + e.getfield(fieldName); + } + } + + public static void push_array(CodeEmitter e, Object[] array) { + e.push(array.length); + e.newarray(Type.getType(remapComponentType(array.getClass().getComponentType()))); + for (int i = 0; i < array.length; i++) { + e.dup(); + e.push(i); + push_object(e, array[i]); + e.aastore(); + } + } + + private static Class remapComponentType(Class componentType) { + if (componentType.equals(Type.class)) + return Class.class; + return componentType; + } + + public static void push_object(CodeEmitter e, Object obj) { + if (obj == null) { + e.aconst_null(); + } else { + Class type = obj.getClass(); + if (type.isArray()) { + push_array(e, (Object[])obj); + } else if (obj instanceof String) { + e.push((String)obj); + } else if (obj instanceof Type) { + load_class(e, (Type)obj); + } else if (obj instanceof Class) { + load_class(e, Type.getType((Class)obj)); + } else if (obj instanceof BigInteger) { + e.new_instance(Constants.TYPE_BIG_INTEGER); + e.dup(); + e.push(obj.toString()); + e.invoke_constructor(Constants.TYPE_BIG_INTEGER); + } else if (obj instanceof BigDecimal) { + e.new_instance(Constants.TYPE_BIG_DECIMAL); + e.dup(); + e.push(obj.toString()); + e.invoke_constructor(Constants.TYPE_BIG_DECIMAL); + } else { + throw new IllegalArgumentException("unknown type: " + obj.getClass()); + } + } + } + + /** + * @deprecated use {@link #hash_code(CodeEmitter, Type, int, CustomizerRegistry)} instead + */ + @Deprecated + public static void hash_code(CodeEmitter e, Type type, int multiplier, final Customizer customizer) { + hash_code(e, type, multiplier, CustomizerRegistry.singleton(customizer)); + } + + public static void hash_code(CodeEmitter e, Type type, int multiplier, final CustomizerRegistry registry) { + if (TypeUtils.isArray(type)) { + hash_array(e, type, multiplier, registry); + } else { + e.swap(Type.INT_TYPE, type); + e.push(multiplier); + e.math(e.MUL, Type.INT_TYPE); + e.swap(type, Type.INT_TYPE); + if (TypeUtils.isPrimitive(type)) { + hash_primitive(e, type); + } else { + hash_object(e, type, registry); + } + e.math(e.ADD, Type.INT_TYPE); + } + } + + private static void hash_array(final CodeEmitter e, Type type, final int multiplier, final CustomizerRegistry registry) { + Label skip = e.make_label(); + Label end = e.make_label(); + e.dup(); + e.ifnull(skip); + EmitUtils.process_array(e, type, new ProcessArrayCallback() { + public void processElement(Type type) { + hash_code(e, type, multiplier, registry); + } + }); + e.goTo(end); + e.mark(skip); + e.pop(); + e.mark(end); + } + + private static void hash_object(CodeEmitter e, Type type, CustomizerRegistry registry) { + // (f == null) ? 0 : f.hashCode(); + Label skip = e.make_label(); + Label end = e.make_label(); + e.dup(); + e.ifnull(skip); + boolean customHashCode = false; + for (HashCodeCustomizer customizer : registry.get(HashCodeCustomizer.class)) { + if (customizer.customize(e, type)) { + customHashCode = true; + break; + } + } + if (!customHashCode) { + for (Customizer customizer : registry.get(Customizer.class)) { + customizer.customize(e, type); + } + e.invoke_virtual(Constants.TYPE_OBJECT, HASH_CODE); + } + e.goTo(end); + e.mark(skip); + e.pop(); + e.push(0); + e.mark(end); + } + + private static void hash_primitive(CodeEmitter e, Type type) { + switch (type.getSort()) { + case Type.BOOLEAN: + // f ? 0 : 1 + e.push(1); + e.math(e.XOR, Type.INT_TYPE); + break; + case Type.FLOAT: + // Float.floatToIntBits(f) + e.invoke_static(Constants.TYPE_FLOAT, FLOAT_TO_INT_BITS); + break; + case Type.DOUBLE: + // Double.doubleToLongBits(f), hash_code(Long.TYPE) + e.invoke_static(Constants.TYPE_DOUBLE, DOUBLE_TO_LONG_BITS); + // fall through + case Type.LONG: + hash_long(e); + } + } + + private static void hash_long(CodeEmitter e) { + // (int)(f ^ (f >>> 32)) + e.dup2(); + e.push(32); + e.math(e.USHR, Type.LONG_TYPE); + e.math(e.XOR, Type.LONG_TYPE); + e.cast_numeric(Type.LONG_TYPE, Type.INT_TYPE); + } + +// public static void not_equals(CodeEmitter e, Type type, Label notEquals) { +// not_equals(e, type, notEquals, null); +// } + + /** + * @deprecated use {@link #not_equals(CodeEmitter, Type, Label, CustomizerRegistry)} instead + */ + @Deprecated + public static void not_equals(CodeEmitter e, Type type, final Label notEquals, final Customizer customizer) { + not_equals(e, type, notEquals, CustomizerRegistry.singleton(customizer)); + } + + /** + * Branches to the specified label if the top two items on the stack + * are not equal. The items must both be of the specified + * class. Equality is determined by comparing primitive values + * directly and by invoking the equals method for + * Objects. Arrays are recursively processed in the same manner. + */ + public static void not_equals(final CodeEmitter e, Type type, final Label notEquals, final CustomizerRegistry registry) { + (new ProcessArrayCallback() { + public void processElement(Type type) { + not_equals_helper(e, type, notEquals, registry, this); + } + }).processElement(type); + } + + private static void not_equals_helper(CodeEmitter e, + Type type, + Label notEquals, + CustomizerRegistry registry, + ProcessArrayCallback callback) { + if (TypeUtils.isPrimitive(type)) { + e.if_cmp(type, e.NE, notEquals); + } else { + Label end = e.make_label(); + nullcmp(e, notEquals, end); + if (TypeUtils.isArray(type)) { + Label checkContents = e.make_label(); + e.dup2(); + e.arraylength(); + e.swap(); + e.arraylength(); + e.if_icmp(e.EQ, checkContents); + e.pop2(); + e.goTo(notEquals); + e.mark(checkContents); + EmitUtils.process_arrays(e, type, callback); + } else { + List customizers = registry.get(Customizer.class); + if (!customizers.isEmpty()) { + for (Customizer customizer : customizers) { + customizer.customize(e, type); + } + e.swap(); + for (Customizer customizer : customizers) { + customizer.customize(e, type); + } + } + e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS); + e.if_jump(e.EQ, notEquals); + } + e.mark(end); + } + } + + /** + * If both objects on the top of the stack are non-null, does nothing. + * If one is null, or both are null, both are popped off and execution + * branches to the respective label. + * @param oneNull label to branch to if only one of the objects is null + * @param bothNull label to branch to if both of the objects are null + */ + private static void nullcmp(CodeEmitter e, Label oneNull, Label bothNull) { + e.dup2(); + Label nonNull = e.make_label(); + Label oneNullHelper = e.make_label(); + Label end = e.make_label(); + e.ifnonnull(nonNull); + e.ifnonnull(oneNullHelper); + e.pop2(); + e.goTo(bothNull); + + e.mark(nonNull); + e.ifnull(oneNullHelper); + e.goTo(end); + + e.mark(oneNullHelper); + e.pop2(); + e.goTo(oneNull); + + e.mark(end); + } + + /* + public static void to_string(CodeEmitter e, + Type type, + ArrayDelimiters delims, + CustomizerRegistry registry) { + e.new_instance(Constants.TYPE_STRING_BUFFER); + e.dup(); + e.invoke_constructor(Constants.TYPE_STRING_BUFFER); + e.swap(); + append_string(e, type, delims, registry); + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING); + } + */ + + /** + * @deprecated use {@link #append_string(CodeEmitter, Type, ArrayDelimiters, CustomizerRegistry)} instead + */ + @Deprecated + public static void append_string(final CodeEmitter e, + Type type, + final ArrayDelimiters delims, + final Customizer customizer) { + append_string(e, type, delims, CustomizerRegistry.singleton(customizer)); + } + + public static void append_string(final CodeEmitter e, + Type type, + final ArrayDelimiters delims, + final CustomizerRegistry registry) { + final ArrayDelimiters d = (delims != null) ? delims : DEFAULT_DELIMITERS; + ProcessArrayCallback callback = new ProcessArrayCallback() { + public void processElement(Type type) { + append_string_helper(e, type, d, registry, this); + e.push(d.inside); + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); + } + }; + append_string_helper(e, type, d, registry, callback); + } + + private static void append_string_helper(CodeEmitter e, + Type type, + ArrayDelimiters delims, + CustomizerRegistry registry, + ProcessArrayCallback callback) { + Label skip = e.make_label(); + Label end = e.make_label(); + if (TypeUtils.isPrimitive(type)) { + switch (type.getSort()) { + case Type.INT: + case Type.SHORT: + case Type.BYTE: + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_INT); + break; + case Type.DOUBLE: + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_DOUBLE); + break; + case Type.FLOAT: + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_FLOAT); + break; + case Type.LONG: + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_LONG); + break; + case Type.BOOLEAN: + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_BOOLEAN); + break; + case Type.CHAR: + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_CHAR); + break; + } + } else if (TypeUtils.isArray(type)) { + e.dup(); + e.ifnull(skip); + e.swap(); + if (delims != null && delims.before != null && !"".equals(delims.before)) { + e.push(delims.before); + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); + e.swap(); + } + EmitUtils.process_array(e, type, callback); + shrinkStringBuffer(e, 2); + if (delims != null && delims.after != null && !"".equals(delims.after)) { + e.push(delims.after); + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); + } + } else { + e.dup(); + e.ifnull(skip); + for (Customizer customizer : registry.get(Customizer.class)) { + customizer.customize(e, type); + } + e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING); + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); + } + e.goTo(end); + e.mark(skip); + e.pop(); + e.push("null"); + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); + e.mark(end); + } + + private static void shrinkStringBuffer(CodeEmitter e, int amt) { + e.dup(); + e.dup(); + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, LENGTH); + e.push(amt); + e.math(e.SUB, Type.INT_TYPE); + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, SET_LENGTH); + } + + public static class ArrayDelimiters { + private String before; + private String inside; + private String after; + + public ArrayDelimiters(String before, String inside, String after) { + this.before = before; + this.inside = inside; + this.after = after; + } + } + + public static void load_method(CodeEmitter e, MethodInfo method) { + load_class(e, method.getClassInfo().getType()); + e.push(method.getSignature().getName()); + push_object(e, method.getSignature().getArgumentTypes()); + e.invoke_virtual(Constants.TYPE_CLASS, GET_DECLARED_METHOD); + } + + private interface ParameterTyper { + Type[] getParameterTypes(MethodInfo member); + } + + public static void method_switch(CodeEmitter e, + List methods, + ObjectSwitchCallback callback) { + member_switch_helper(e, methods, callback, true); + } + + public static void constructor_switch(CodeEmitter e, + List constructors, + ObjectSwitchCallback callback) { + member_switch_helper(e, constructors, callback, false); + } + + private static void member_switch_helper(final CodeEmitter e, + List members, + final ObjectSwitchCallback callback, + boolean useName) { + try { + final Map cache = new HashMap(); + final ParameterTyper cached = new ParameterTyper() { + public Type[] getParameterTypes(MethodInfo member) { + Type[] types = (Type[])cache.get(member); + if (types == null) { + cache.put(member, types = member.getSignature().getArgumentTypes()); + } + return types; + } + }; + final Label def = e.make_label(); + final Label end = e.make_label(); + if (useName) { + e.swap(); + final Map buckets = CollectionUtils.bucket(members, new Transformer() { + public Object transform(Object value) { + return ((MethodInfo)value).getSignature().getName(); + } + }); + String[] names = (String[])buckets.keySet().toArray(new String[buckets.size()]); + EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { + public void processCase(Object key, Label dontUseEnd) throws Exception { + member_helper_size(e, (List)buckets.get(key), callback, cached, def, end); + } + public void processDefault() throws Exception { + e.goTo(def); + } + }); + } else { + member_helper_size(e, members, callback, cached, def, end); + } + e.mark(def); + e.pop(); + callback.processDefault(); + e.mark(end); + } catch (RuntimeException ex) { + throw ex; + } catch (Error ex) { + throw ex; + } catch (Exception ex) { + throw new CodeGenerationException(ex); + } + } + + private static void member_helper_size(final CodeEmitter e, + List members, + final ObjectSwitchCallback callback, + final ParameterTyper typer, + final Label def, + final Label end) throws Exception { + final Map buckets = CollectionUtils.bucket(members, new Transformer() { + public Object transform(Object value) { + return new Integer(typer.getParameterTypes((MethodInfo)value).length); + } + }); + e.dup(); + e.arraylength(); + e.process_switch(EmitUtils.getSwitchKeys(buckets), new ProcessSwitchCallback() { + public void processCase(int key, Label dontUseEnd) throws Exception { + List bucket = (List)buckets.get(new Integer(key)); + member_helper_type(e, bucket, callback, typer, def, end, new BitSet()); + } + public void processDefault() throws Exception { + e.goTo(def); + } + }); + } + + private static void member_helper_type(final CodeEmitter e, + List members, + final ObjectSwitchCallback callback, + final ParameterTyper typer, + final Label def, + final Label end, + final BitSet checked) throws Exception { + if (members.size() == 1) { + MethodInfo member = (MethodInfo)members.get(0); + Type[] types = typer.getParameterTypes(member); + // need to check classes that have not already been checked via switches + for (int i = 0; i < types.length; i++) { + if (checked == null || !checked.get(i)) { + e.dup(); + e.aaload(i); + e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME); + e.push(TypeUtils.emulateClassGetName(types[i])); + e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS); + e.if_jump(e.EQ, def); + } + } + e.pop(); + callback.processCase(member, end); + } else { + // choose the index that has the best chance of uniquely identifying member + Type[] example = typer.getParameterTypes((MethodInfo)members.get(0)); + Map buckets = null; + int index = -1; + for (int i = 0; i < example.length; i++) { + final int j = i; + Map test = CollectionUtils.bucket(members, new Transformer() { + public Object transform(Object value) { + return TypeUtils.emulateClassGetName(typer.getParameterTypes((MethodInfo)value)[j]); + } + }); + if (buckets == null || test.size() > buckets.size()) { + buckets = test; + index = i; + } + } + if (buckets == null || buckets.size() == 1) { + // TODO: switch by returnType + // must have two methods with same name, types, and different return types + e.goTo(def); + } else { + checked.set(index); + + e.dup(); + e.aaload(index); + e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME); + + final Map fbuckets = buckets; + String[] names = (String[])buckets.keySet().toArray(new String[buckets.size()]); + EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { + public void processCase(Object key, Label dontUseEnd) throws Exception { + member_helper_type(e, (List)fbuckets.get(key), callback, typer, def, end, checked); + } + public void processDefault() throws Exception { + e.goTo(def); + } + }); + } + } + } + + public static void wrap_throwable(Block block, Type wrapper) { + CodeEmitter e = block.getCodeEmitter(); + e.catch_exception(block, Constants.TYPE_THROWABLE); + e.new_instance(wrapper); + e.dup_x1(); + e.swap(); + e.invoke_constructor(wrapper, CSTRUCT_THROWABLE); + e.athrow(); + } + + public static void add_properties(ClassEmitter ce, String[] names, Type[] types) { + for (int i = 0; i < names.length; i++) { + String fieldName = "$cglib_prop_" + names[i]; + ce.declare_field(Constants.ACC_PRIVATE, fieldName, types[i], null); + EmitUtils.add_property(ce, names[i], types[i], fieldName); + } + } + + public static void add_property(ClassEmitter ce, String name, Type type, String fieldName) { + String property = TypeUtils.upperFirst(name); + CodeEmitter e; + e = ce.begin_method(Constants.ACC_PUBLIC, + new Signature("get" + property, + type, + Constants.TYPES_EMPTY), + null); + e.load_this(); + e.getfield(fieldName); + e.return_value(); + e.end_method(); + + e = ce.begin_method(Constants.ACC_PUBLIC, + new Signature("set" + property, + Type.VOID_TYPE, + new Type[]{ type }), + null); + e.load_this(); + e.load_arg(0); + e.putfield(fieldName); + e.return_value(); + e.end_method(); + } + + /* generates: + } catch (RuntimeException e) { + throw e; + } catch (Error e) { + throw e; + } catch ( e) { + throw e; + } catch (Throwable e) { + throw new (e); + } + */ + public static void wrap_undeclared_throwable(CodeEmitter e, Block handler, Type[] exceptions, Type wrapper) { + Set set = (exceptions == null) ? Collections.EMPTY_SET : new HashSet(Arrays.asList(exceptions)); + + if (set.contains(Constants.TYPE_THROWABLE)) + return; + + boolean needThrow = exceptions != null; + if (!set.contains(Constants.TYPE_RUNTIME_EXCEPTION)) { + e.catch_exception(handler, Constants.TYPE_RUNTIME_EXCEPTION); + needThrow = true; + } + if (!set.contains(Constants.TYPE_ERROR)) { + e.catch_exception(handler, Constants.TYPE_ERROR); + needThrow = true; + } + if (exceptions != null) { + for (int i = 0; i < exceptions.length; i++) { + e.catch_exception(handler, exceptions[i]); + } + } + if (needThrow) { + e.athrow(); + } + // e -> eo -> oeo -> ooe -> o + e.catch_exception(handler, Constants.TYPE_THROWABLE); + e.new_instance(wrapper); + e.dup_x1(); + e.swap(); + e.invoke_constructor(wrapper, CSTRUCT_THROWABLE); + e.athrow(); + } + + public static CodeEmitter begin_method(ClassEmitter e, MethodInfo method) { + return begin_method(e, method, method.getModifiers()); + } + + public static CodeEmitter begin_method(ClassEmitter e, MethodInfo method, int access) { + return e.begin_method(access, + method.getSignature(), + method.getExceptionTypes()); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/FieldTypeCustomizer.java b/blade-aop/src/main/java/net/sf/cglib/core/FieldTypeCustomizer.java new file mode 100644 index 000000000..1caa076b7 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/FieldTypeCustomizer.java @@ -0,0 +1,23 @@ +package net.sf.cglib.core; + +import org.objectweb.asm.Type; + +/** + * Customizes key types for {@link KeyFactory} right in constructor. + */ +public interface FieldTypeCustomizer extends KeyFactoryCustomizer { + /** + * Customizes {@code this.FIELD_0 = ?} assignment in key constructor + * @param e code emitter + * @param index parameter index + * @param type parameter type + */ + void customize(CodeEmitter e, int index, Type type); + + /** + * Computes type of field for storing given parameter + * @param index parameter index + * @param type parameter type + */ + Type getOutType(int index, Type type); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/GeneratorStrategy.java b/blade-aop/src/main/java/net/sf/cglib/core/GeneratorStrategy.java new file mode 100644 index 000000000..8d5ee694f --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/GeneratorStrategy.java @@ -0,0 +1,44 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +/** + * The GeneratorStrategyClass. By providing your + * own strategy you may examine or modify the generated class before + * it is loaded. Typically this will be accomplished by subclassing + * {@link DefaultGeneratorStrategy} and overriding the appropriate + * protected method. + * @see AbstractClassGenerator#setStrategy + */ +public interface GeneratorStrategy { + /** + * Generate the class. + * @param cg a class generator on which you can call {@link ClassGenerator#generateClass} + * @return a byte array containing the bits of a valid Class + */ + byte[] generate(ClassGenerator cg) throws Exception; + + /** + * The GeneratorStrategy in use does not currently, but may + * in the future, affect the caching of classes generated by {@link + * AbstractClassGenerator}, so this is a reminder that you should + * correctly implement equals and hashCode + * to avoid generating too many classes. + */ + boolean equals(Object o); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/HashCodeCustomizer.java b/blade-aop/src/main/java/net/sf/cglib/core/HashCodeCustomizer.java new file mode 100644 index 000000000..b66b791cb --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/HashCodeCustomizer.java @@ -0,0 +1,12 @@ +package net.sf.cglib.core; + +import org.objectweb.asm.Type; + +public interface HashCodeCustomizer extends KeyFactoryCustomizer { + /** + * Customizes calculation of hashcode + * @param e code emitter + * @param type parameter type + */ + boolean customize(CodeEmitter e, Type type); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/KeyFactory.java b/blade-aop/src/main/java/net/sf/cglib/core/KeyFactory.java new file mode 100644 index 000000000..b9ea79851 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/KeyFactory.java @@ -0,0 +1,346 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import net.sf.cglib.core.internal.CustomizerRegistry; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +import java.lang.reflect.Method; +import java.security.ProtectionDomain; +import java.util.Collections; +import java.util.List; + +/** + * Generates classes to handle multi-valued keys, for use in things such as Maps and Sets. + * Code for equals and hashCode methods follow the + * the rules laid out in Effective Java by Joshua Bloch. + *

+ * To generate a KeyFactory, you need to supply an interface which + * describes the structure of the key. The interface should have a + * single method named newInstance, which returns an + * Object. The arguments array can be + * anything--Objects, primitive values, or single or + * multi-dimension arrays of either. For example: + *

+ *     private interface IntStringKey {
+ *         public Object newInstance(int i, String s);
+ *     }
+ * 

+ * Once you have made a KeyFactory, you generate a new key by calling + * the newInstance method defined by your interface. + *

+ *     IntStringKey factory = (IntStringKey)KeyFactory.create(IntStringKey.class);
+ *     Object key1 = factory.newInstance(4, "Hello");
+ *     Object key2 = factory.newInstance(4, "World");
+ * 

+ * Note: + * hashCode equality between two keys key1 and key2 is only guaranteed if + * key1.equals(key2) and the keys were produced by the same factory. + * + * @version $Id: KeyFactory.java,v 1.26 2006/03/05 02:43:19 herbyderby Exp $ + */ +abstract public class KeyFactory { + private static final Signature GET_NAME = + TypeUtils.parseSignature("String getName()"); + private static final Signature GET_CLASS = + TypeUtils.parseSignature("Class getClass()"); + private static final Signature HASH_CODE = + TypeUtils.parseSignature("int hashCode()"); + private static final Signature EQUALS = + TypeUtils.parseSignature("boolean equals(Object)"); + private static final Signature TO_STRING = + TypeUtils.parseSignature("String toString()"); + private static final Signature APPEND_STRING = + TypeUtils.parseSignature("StringBuffer append(String)"); + private static final Type KEY_FACTORY = + TypeUtils.parseType("net.sf.cglib.core.KeyFactory"); + private static final Signature GET_SORT = + TypeUtils.parseSignature("int getSort()"); + + //generated numbers: + private final static int PRIMES[] = { + 11, 73, 179, 331, + 521, 787, 1213, 1823, + 2609, 3691, 5189, 7247, + 10037, 13931, 19289, 26627, + 36683, 50441, 69403, 95401, + 131129, 180179, 247501, 340057, + 467063, 641371, 880603, 1209107, + 1660097, 2279161, 3129011, 4295723, + 5897291, 8095873, 11114263, 15257791, + 20946017, 28754629, 39474179, 54189869, + 74391461, 102123817, 140194277, 192456917, + 264202273, 362693231, 497900099, 683510293, + 938313161, 1288102441, 1768288259 }; + + + public static final Customizer CLASS_BY_NAME = new Customizer() { + public void customize(CodeEmitter e, Type type) { + if (type.equals(Constants.TYPE_CLASS)) { + e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME); + } + } + }; + + public static final FieldTypeCustomizer STORE_CLASS_AS_STRING = new FieldTypeCustomizer() { + public void customize(CodeEmitter e, int index, Type type) { + if (type.equals(Constants.TYPE_CLASS)) { + e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME); + } + } + + public Type getOutType(int index, Type type) { + if (type.equals(Constants.TYPE_CLASS)) { + return Constants.TYPE_STRING; + } + return type; + } + }; + + /** + * {@link Type#hashCode()} is very expensive as it traverses full descriptor to calculate hash code. + * This customizer uses {@link Type#getSort()} as a hash code. + */ + public static final HashCodeCustomizer HASH_ASM_TYPE = new HashCodeCustomizer() { + public boolean customize(CodeEmitter e, Type type) { + if (Constants.TYPE_TYPE.equals(type)) { + e.invoke_virtual(type, GET_SORT); + return true; + } + return false; + } + }; + + /** + * @deprecated this customizer might result in unexpected class leak since key object still holds a strong reference to the Object and class. + * It is recommended to have pre-processing method that would strip Objects and represent Classes as Strings + */ + @Deprecated + public static final Customizer OBJECT_BY_CLASS = new Customizer() { + public void customize(CodeEmitter e, Type type) { + e.invoke_virtual(Constants.TYPE_OBJECT, GET_CLASS); + } + }; + + protected KeyFactory() { + } + + public static KeyFactory create(Class keyInterface) { + return create(keyInterface, null); + } + + public static KeyFactory create(Class keyInterface, Customizer customizer) { + return create(keyInterface.getClassLoader(), keyInterface, customizer); + } + + public static KeyFactory create(Class keyInterface, KeyFactoryCustomizer first, List next) { + return create(keyInterface.getClassLoader(), keyInterface, first, next); + } + + public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) { + return create(loader, keyInterface, customizer, Collections.emptyList()); + } + + public static KeyFactory create(ClassLoader loader, Class keyInterface, KeyFactoryCustomizer customizer, + List next) { + Generator gen = new Generator(); + gen.setInterface(keyInterface); + + if (customizer != null) { + gen.addCustomizer(customizer); + } + if (next != null && !next.isEmpty()) { + for (KeyFactoryCustomizer keyFactoryCustomizer : next) { + gen.addCustomizer(keyFactoryCustomizer); + } + } + gen.setClassLoader(loader); + return gen.create(); + } + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(KeyFactory.class.getName()); + private static final Class[] KNOWN_CUSTOMIZER_TYPES = new Class[]{Customizer.class, FieldTypeCustomizer.class}; + + private Class keyInterface; + // TODO: Make me final when deprecated methods are removed + private CustomizerRegistry customizers = new CustomizerRegistry(KNOWN_CUSTOMIZER_TYPES); + private int constant; + private int multiplier; + + public Generator() { + super(SOURCE); + } + + protected ClassLoader getDefaultClassLoader() { + return keyInterface.getClassLoader(); + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(keyInterface); + } + + /** + * @deprecated Use {@link #addCustomizer(KeyFactoryCustomizer)} instead. + */ + @Deprecated + public void setCustomizer(Customizer customizer) { + customizers = CustomizerRegistry.singleton(customizer); + } + + public void addCustomizer(KeyFactoryCustomizer customizer) { + customizers.add(customizer); + } + + public List getCustomizers(Class klass) { + return customizers.get(klass); + } + + public void setInterface(Class keyInterface) { + this.keyInterface = keyInterface; + } + + public KeyFactory create() { + setNamePrefix(keyInterface.getName()); + return (KeyFactory)super.create(keyInterface.getName()); + } + + public void setHashConstant(int constant) { + this.constant = constant; + } + + public void setHashMultiplier(int multiplier) { + this.multiplier = multiplier; + } + + protected Object firstInstance(Class type) { + return ReflectUtils.newInstance(type); + } + + protected Object nextInstance(Object instance) { + return instance; + } + + public void generateClass(ClassVisitor v) { + ClassEmitter ce = new ClassEmitter(v); + + Method newInstance = ReflectUtils.findNewInstance(keyInterface); + if (!newInstance.getReturnType().equals(Object.class)) { + throw new IllegalArgumentException("newInstance method must return Object"); + } + + Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes()); + ce.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + getClassName(), + KEY_FACTORY, + new Type[]{ Type.getType(keyInterface) }, + Constants.SOURCE_FILE); + EmitUtils.null_constructor(ce); + EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance)); + + int seed = 0; + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, + TypeUtils.parseConstructor(parameterTypes), + null); + e.load_this(); + e.super_invoke_constructor(); + e.load_this(); + List fieldTypeCustomizers = getCustomizers(FieldTypeCustomizer.class); + for (int i = 0; i < parameterTypes.length; i++) { + Type parameterType = parameterTypes[i]; + Type fieldType = parameterType; + for (FieldTypeCustomizer customizer : fieldTypeCustomizers) { + fieldType = customizer.getOutType(i, fieldType); + } + seed += fieldType.hashCode(); + ce.declare_field(Constants.ACC_PRIVATE | Constants.ACC_FINAL, + getFieldName(i), + fieldType, + null); + e.dup(); + e.load_arg(i); + for (FieldTypeCustomizer customizer : fieldTypeCustomizers) { + customizer.customize(e, i, parameterType); + } + e.putfield(getFieldName(i)); + } + e.return_value(); + e.end_method(); + + // hash code + e = ce.begin_method(Constants.ACC_PUBLIC, HASH_CODE, null); + int hc = (constant != 0) ? constant : PRIMES[(int)(Math.abs(seed) % PRIMES.length)]; + int hm = (multiplier != 0) ? multiplier : PRIMES[(int)(Math.abs(seed * 13) % PRIMES.length)]; + e.push(hc); + for (int i = 0; i < parameterTypes.length; i++) { + e.load_this(); + e.getfield(getFieldName(i)); + EmitUtils.hash_code(e, parameterTypes[i], hm, customizers); + } + e.return_value(); + e.end_method(); + + // equals + e = ce.begin_method(Constants.ACC_PUBLIC, EQUALS, null); + Label fail = e.make_label(); + e.load_arg(0); + e.instance_of_this(); + e.if_jump(e.EQ, fail); + for (int i = 0; i < parameterTypes.length; i++) { + e.load_this(); + e.getfield(getFieldName(i)); + e.load_arg(0); + e.checkcast_this(); + e.getfield(getFieldName(i)); + EmitUtils.not_equals(e, parameterTypes[i], fail, customizers); + } + e.push(1); + e.return_value(); + e.mark(fail); + e.push(0); + e.return_value(); + e.end_method(); + + // toString + e = ce.begin_method(Constants.ACC_PUBLIC, TO_STRING, null); + e.new_instance(Constants.TYPE_STRING_BUFFER); + e.dup(); + e.invoke_constructor(Constants.TYPE_STRING_BUFFER); + for (int i = 0; i < parameterTypes.length; i++) { + if (i > 0) { + e.push(", "); + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); + } + e.load_this(); + e.getfield(getFieldName(i)); + EmitUtils.append_string(e, parameterTypes[i], EmitUtils.DEFAULT_DELIMITERS, customizers); + } + e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING); + e.return_value(); + e.end_method(); + + ce.end_class(); + } + + private String getFieldName(int arg) { + return "FIELD_" + arg; + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/KeyFactoryCustomizer.java b/blade-aop/src/main/java/net/sf/cglib/core/KeyFactoryCustomizer.java new file mode 100644 index 000000000..e6a5f2c56 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/KeyFactoryCustomizer.java @@ -0,0 +1,7 @@ +package net.sf.cglib.core; + +/** + * Marker interface for customizers of {@link KeyFactory} + */ +public interface KeyFactoryCustomizer { +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/Local.java b/blade-aop/src/main/java/net/sf/cglib/core/Local.java new file mode 100644 index 000000000..f39a1e298 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/Local.java @@ -0,0 +1,37 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.Type; + +public class Local +{ + private Type type; + private int index; + + public Local(int index, Type type) { + this.type = type; + this.index = index; + } + + public int getIndex() { + return index; + } + + public Type getType() { + return type; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/LocalVariablesSorter.java b/blade-aop/src/main/java/net/sf/cglib/core/LocalVariablesSorter.java new file mode 100644 index 000000000..6846d15b7 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/LocalVariablesSorter.java @@ -0,0 +1,158 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * 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. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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. + */ +package net.sf.cglib.core; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * A {@link MethodVisitor} that renumbers local variables in their order of + * appearance. This adapter allows one to easily add new local variables to a + * method. + * + * @author Chris Nokleberg + * @author Eric Bruneton + */ +public class LocalVariablesSorter extends MethodVisitor { + + /** + * Mapping from old to new local variable indexes. A local variable at index + * i of size 1 is remapped to 'mapping[2*i]', while a local variable at + * index i of size 2 is remapped to 'mapping[2*i+1]'. + */ + private static class State + { + int[] mapping = new int[40]; + int nextLocal; + } + + protected final int firstLocal; + private final State state; + + public LocalVariablesSorter( + final int access, + final String desc, + final MethodVisitor mv) + { + super(Opcodes.ASM5, mv); + state = new State(); + Type[] args = Type.getArgumentTypes(desc); + state.nextLocal = ((Opcodes.ACC_STATIC & access) != 0) ? 0 : 1; + for (int i = 0; i < args.length; i++) { + state.nextLocal += args[i].getSize(); + } + firstLocal = state.nextLocal; + } + + public LocalVariablesSorter(LocalVariablesSorter lvs) { + super(Opcodes.ASM5, lvs.mv); + state = lvs.state; + firstLocal = lvs.firstLocal; + } + + public void visitVarInsn(final int opcode, final int var) { + int size; + switch (opcode) { + case Opcodes.LLOAD: + case Opcodes.LSTORE: + case Opcodes.DLOAD: + case Opcodes.DSTORE: + size = 2; + break; + default: + size = 1; + } + mv.visitVarInsn(opcode, remap(var, size)); + } + + public void visitIincInsn(final int var, final int increment) { + mv.visitIincInsn(remap(var, 1), increment); + } + + public void visitMaxs(final int maxStack, final int maxLocals) { + mv.visitMaxs(maxStack, state.nextLocal); + } + + public void visitLocalVariable( + final String name, + final String desc, + final String signature, + final Label start, + final Label end, + final int index) + { + mv.visitLocalVariable(name, desc, signature, start, end, remap(index)); + } + + // ------------- + + protected int newLocal(final int size) { + int var = state.nextLocal; + state.nextLocal += size; + return var; + } + + private int remap(final int var, final int size) { + if (var < firstLocal) { + return var; + } + int key = 2 * var + size - 1; + int length = state.mapping.length; + if (key >= length) { + int[] newMapping = new int[Math.max(2 * length, key + 1)]; + System.arraycopy(state.mapping, 0, newMapping, 0, length); + state.mapping = newMapping; + } + int value = state.mapping[key]; + if (value == 0) { + value = state.nextLocal + 1; + state.mapping[key] = value; + state.nextLocal += size; + } + return value - 1; + } + + private int remap(final int var) { + if (var < firstLocal) { + return var; + } + int key = 2 * var; + int value = key < state.mapping.length ? state.mapping[key] : 0; + if (value == 0) { + value = key + 1 < state.mapping.length ? state.mapping[key + 1] : 0; + } + if (value == 0) { + throw new IllegalStateException("Unknown local variable " + var); + } + return value - 1; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/MethodInfo.java b/blade-aop/src/main/java/net/sf/cglib/core/MethodInfo.java new file mode 100644 index 000000000..dfaacd821 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/MethodInfo.java @@ -0,0 +1,47 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Type; + +abstract public class MethodInfo { + + protected MethodInfo() { + } + + abstract public ClassInfo getClassInfo(); + abstract public int getModifiers(); + abstract public Signature getSignature(); + abstract public Type[] getExceptionTypes(); + + public boolean equals(Object o) { + if (o == null) + return false; + if (!(o instanceof MethodInfo)) + return false; + return getSignature().equals(((MethodInfo)o).getSignature()); + } + + public int hashCode() { + return getSignature().hashCode(); + } + + public String toString() { + // TODO: include modifiers, exceptions + return getSignature().toString(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/MethodInfoTransformer.java b/blade-aop/src/main/java/net/sf/cglib/core/MethodInfoTransformer.java new file mode 100644 index 000000000..7b3a8fc3c --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/MethodInfoTransformer.java @@ -0,0 +1,37 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.lang.reflect.*; + +public class MethodInfoTransformer implements Transformer +{ + private static final MethodInfoTransformer INSTANCE = new MethodInfoTransformer(); + + public static MethodInfoTransformer getInstance() { + return INSTANCE; + } + + public Object transform(Object value) { + if (value instanceof Method) { + return ReflectUtils.getMethodInfo((Method)value); + } else if (value instanceof Constructor) { + return ReflectUtils.getMethodInfo((Constructor)value); + } else { + throw new IllegalArgumentException("cannot get method info for " + value); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/MethodWrapper.java b/blade-aop/src/main/java/net/sf/cglib/core/MethodWrapper.java new file mode 100644 index 000000000..5bea1acbe --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/MethodWrapper.java @@ -0,0 +1,46 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.lang.reflect.Method; +import java.util.*; + +public class MethodWrapper { + private static final MethodWrapperKey KEY_FACTORY = + (MethodWrapperKey)KeyFactory.create(MethodWrapperKey.class); + + /** Internal interface, only public due to ClassLoader issues. */ + public interface MethodWrapperKey { + public Object newInstance(String name, String[] parameterTypes, String returnType); + } + + private MethodWrapper() { + } + + public static Object create(Method method) { + return KEY_FACTORY.newInstance(method.getName(), + ReflectUtils.getNames(method.getParameterTypes()), + method.getReturnType().getName()); + } + + public static Set createSet(Collection methods) { + Set set = new HashSet(); + for (Iterator it = methods.iterator(); it.hasNext();) { + set.add(create((Method)it.next())); + } + return set; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/NamingPolicy.java b/blade-aop/src/main/java/net/sf/cglib/core/NamingPolicy.java new file mode 100644 index 000000000..d7dc68e3a --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/NamingPolicy.java @@ -0,0 +1,43 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.util.Set; + +/** + * Customize the generated class name for {@link AbstractClassGenerator}-based utilities. + */ +public interface NamingPolicy { + /** + * Choose a name for a generated class. + * @param prefix a dotted-name chosen by the generating class (possibly to put the generated class in a particular package) + * @param source the fully-qualified class name of the generating class (for example "net.sf.cglib.Enhancer") + * @param key A key object representing the state of the parameters; for caching to work properly, equal keys should result + * in the same generated class name. The default policy incorporates key.hashCode() into the class name. + * @param names a predicate that returns true if the given classname has already been used in the same ClassLoader. + * @return the fully-qualified class name + */ + String getClassName(String prefix, String source, Object key, Predicate names); + + /** + * The NamingPolicy in use does not currently, but may + * in the future, affect the caching of classes generated by {@link + * AbstractClassGenerator}, so this is a reminder that you should + * correctly implement equals and hashCode + * to avoid generating too many classes. + */ + boolean equals(Object o); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/ObjectSwitchCallback.java b/blade-aop/src/main/java/net/sf/cglib/core/ObjectSwitchCallback.java new file mode 100644 index 000000000..df179e015 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/ObjectSwitchCallback.java @@ -0,0 +1,24 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.Label; + +public interface ObjectSwitchCallback { + void processCase(Object key, Label end) throws Exception; + void processDefault() throws Exception; +} + diff --git a/blade-aop/src/main/java/net/sf/cglib/core/Predicate.java b/blade-aop/src/main/java/net/sf/cglib/core/Predicate.java new file mode 100644 index 000000000..ab367a83d --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/Predicate.java @@ -0,0 +1,21 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +public interface Predicate { + boolean evaluate(Object arg); +} + diff --git a/blade-aop/src/main/java/net/sf/cglib/core/ProcessArrayCallback.java b/blade-aop/src/main/java/net/sf/cglib/core/ProcessArrayCallback.java new file mode 100644 index 000000000..bb2a79712 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/ProcessArrayCallback.java @@ -0,0 +1,22 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.Type; + +public interface ProcessArrayCallback { + void processElement(Type type); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/ProcessSwitchCallback.java b/blade-aop/src/main/java/net/sf/cglib/core/ProcessSwitchCallback.java new file mode 100644 index 000000000..cac098562 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/ProcessSwitchCallback.java @@ -0,0 +1,23 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.Label; + +public interface ProcessSwitchCallback { + void processCase(int key, Label end) throws Exception; + void processDefault() throws Exception; +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/ReflectUtils.java b/blade-aop/src/main/java/net/sf/cglib/core/ReflectUtils.java new file mode 100644 index 000000000..df9579a0a --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/ReflectUtils.java @@ -0,0 +1,492 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.beans.*; +import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.ProtectionDomain; +import java.util.*; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Type; + +/** + * @version $Id: ReflectUtils.java,v 1.30 2009/01/11 19:47:49 herbyderby Exp $ + */ +public class ReflectUtils { + private ReflectUtils() { } + + private static final Map primitives = new HashMap(8); + private static final Map transforms = new HashMap(8); + private static final ClassLoader defaultLoader = ReflectUtils.class.getClassLoader(); + private static Method DEFINE_CLASS; + private static final ProtectionDomain PROTECTION_DOMAIN; + + private static final List OBJECT_METHODS = new ArrayList(); + + static { + PROTECTION_DOMAIN = getProtectionDomain(ReflectUtils.class); + + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Class loader = Class.forName("java.lang.ClassLoader"); // JVM crash w/o this + DEFINE_CLASS = loader.getDeclaredMethod("defineClass", + new Class[]{ String.class, + byte[].class, + Integer.TYPE, + Integer.TYPE, + ProtectionDomain.class }); + DEFINE_CLASS.setAccessible(true); + } catch (ClassNotFoundException e) { + throw new CodeGenerationException(e); + } catch (NoSuchMethodException e) { + throw new CodeGenerationException(e); + } + return null; + } + }); + Method[] methods = Object.class.getDeclaredMethods(); + for (Method method : methods) { + if ("finalize".equals(method.getName()) + || (method.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) > 0) { + continue; + } + OBJECT_METHODS.add(method); + } + } + + private static final String[] CGLIB_PACKAGES = { + "java.lang", + }; + + static { + primitives.put("byte", Byte.TYPE); + primitives.put("char", Character.TYPE); + primitives.put("double", Double.TYPE); + primitives.put("float", Float.TYPE); + primitives.put("int", Integer.TYPE); + primitives.put("long", Long.TYPE); + primitives.put("short", Short.TYPE); + primitives.put("boolean", Boolean.TYPE); + + transforms.put("byte", "B"); + transforms.put("char", "C"); + transforms.put("double", "D"); + transforms.put("float", "F"); + transforms.put("int", "I"); + transforms.put("long", "J"); + transforms.put("short", "S"); + transforms.put("boolean", "Z"); + } + + public static ProtectionDomain getProtectionDomain(final Class source) { + if(source == null) { + return null; + } + return (ProtectionDomain)AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return source.getProtectionDomain(); + } + }); + } + + public static Type[] getExceptionTypes(Member member) { + if (member instanceof Method) { + return TypeUtils.getTypes(((Method)member).getExceptionTypes()); + } else if (member instanceof Constructor) { + return TypeUtils.getTypes(((Constructor)member).getExceptionTypes()); + } else { + throw new IllegalArgumentException("Cannot get exception types of a field"); + } + } + + public static Signature getSignature(Member member) { + if (member instanceof Method) { + return new Signature(member.getName(), Type.getMethodDescriptor((Method)member)); + } else if (member instanceof Constructor) { + Type[] types = TypeUtils.getTypes(((Constructor)member).getParameterTypes()); + return new Signature(Constants.CONSTRUCTOR_NAME, + Type.getMethodDescriptor(Type.VOID_TYPE, types)); + + } else { + throw new IllegalArgumentException("Cannot get signature of a field"); + } + } + + public static Constructor findConstructor(String desc) { + return findConstructor(desc, defaultLoader); + } + + public static Constructor findConstructor(String desc, ClassLoader loader) { + try { + int lparen = desc.indexOf('('); + String className = desc.substring(0, lparen).trim(); + return getClass(className, loader).getConstructor(parseTypes(desc, loader)); + } catch (ClassNotFoundException e) { + throw new CodeGenerationException(e); + } catch (NoSuchMethodException e) { + throw new CodeGenerationException(e); + } + } + + public static Method findMethod(String desc) { + return findMethod(desc, defaultLoader); + } + + public static Method findMethod(String desc, ClassLoader loader) { + try { + int lparen = desc.indexOf('('); + int dot = desc.lastIndexOf('.', lparen); + String className = desc.substring(0, dot).trim(); + String methodName = desc.substring(dot + 1, lparen).trim(); + return getClass(className, loader).getDeclaredMethod(methodName, parseTypes(desc, loader)); + } catch (ClassNotFoundException e) { + throw new CodeGenerationException(e); + } catch (NoSuchMethodException e) { + throw new CodeGenerationException(e); + } + } + + private static Class[] parseTypes(String desc, ClassLoader loader) throws ClassNotFoundException { + int lparen = desc.indexOf('('); + int rparen = desc.indexOf(')', lparen); + List params = new ArrayList(); + int start = lparen + 1; + for (;;) { + int comma = desc.indexOf(',', start); + if (comma < 0) { + break; + } + params.add(desc.substring(start, comma).trim()); + start = comma + 1; + } + if (start < rparen) { + params.add(desc.substring(start, rparen).trim()); + } + Class[] types = new Class[params.size()]; + for (int i = 0; i < types.length; i++) { + types[i] = getClass((String)params.get(i), loader); + } + return types; + } + + private static Class getClass(String className, ClassLoader loader) throws ClassNotFoundException { + return getClass(className, loader, CGLIB_PACKAGES); + } + + private static Class getClass(String className, ClassLoader loader, String[] packages) throws ClassNotFoundException { + String save = className; + int dimensions = 0; + int index = 0; + while ((index = className.indexOf("[]", index) + 1) > 0) { + dimensions++; + } + StringBuffer brackets = new StringBuffer(className.length() - dimensions); + for (int i = 0; i < dimensions; i++) { + brackets.append('['); + } + className = className.substring(0, className.length() - 2 * dimensions); + + String prefix = (dimensions > 0) ? brackets + "L" : ""; + String suffix = (dimensions > 0) ? ";" : ""; + try { + return Class.forName(prefix + className + suffix, false, loader); + } catch (ClassNotFoundException ignore) { } + for (int i = 0; i < packages.length; i++) { + try { + return Class.forName(prefix + packages[i] + '.' + className + suffix, false, loader); + } catch (ClassNotFoundException ignore) { } + } + if (dimensions == 0) { + Class c = (Class)primitives.get(className); + if (c != null) { + return c; + } + } else { + String transform = (String)transforms.get(className); + if (transform != null) { + try { + return Class.forName(brackets + transform, false, loader); + } catch (ClassNotFoundException ignore) { } + } + } + throw new ClassNotFoundException(save); + } + + + public static Object newInstance(Class type) { + return newInstance(type, Constants.EMPTY_CLASS_ARRAY, null); + } + + public static Object newInstance(Class type, Class[] parameterTypes, Object[] args) { + return newInstance(getConstructor(type, parameterTypes), args); + } + + public static Object newInstance(final Constructor cstruct, final Object[] args) { + + boolean flag = cstruct.isAccessible(); + try { + if (!flag) { + cstruct.setAccessible(true); + } + Object result = cstruct.newInstance(args); + return result; + } catch (InstantiationException e) { + throw new CodeGenerationException(e); + } catch (IllegalAccessException e) { + throw new CodeGenerationException(e); + } catch (InvocationTargetException e) { + throw new CodeGenerationException(e.getTargetException()); + } finally { + if (!flag) { + cstruct.setAccessible(flag); + } + } + + } + + public static Constructor getConstructor(Class type, Class[] parameterTypes) { + try { + Constructor constructor = type.getDeclaredConstructor(parameterTypes); + constructor.setAccessible(true); + return constructor; + } catch (NoSuchMethodException e) { + throw new CodeGenerationException(e); + } + } + + public static String[] getNames(Class[] classes) + { + if (classes == null) + return null; + String[] names = new String[classes.length]; + for (int i = 0; i < names.length; i++) { + names[i] = classes[i].getName(); + } + return names; + } + + public static Class[] getClasses(Object[] objects) { + Class[] classes = new Class[objects.length]; + for (int i = 0; i < objects.length; i++) { + classes[i] = objects[i].getClass(); + } + return classes; + } + + public static Method findNewInstance(Class iface) { + Method m = findInterfaceMethod(iface); + if (!m.getName().equals("newInstance")) { + throw new IllegalArgumentException(iface + " missing newInstance method"); + } + return m; + } + + public static Method[] getPropertyMethods(PropertyDescriptor[] properties, boolean read, boolean write) { + Set methods = new HashSet(); + for (int i = 0; i < properties.length; i++) { + PropertyDescriptor pd = properties[i]; + if (read) { + methods.add(pd.getReadMethod()); + } + if (write) { + methods.add(pd.getWriteMethod()); + } + } + methods.remove(null); + return (Method[])methods.toArray(new Method[methods.size()]); + } + + public static PropertyDescriptor[] getBeanProperties(Class type) { + return getPropertiesHelper(type, true, true); + } + + public static PropertyDescriptor[] getBeanGetters(Class type) { + return getPropertiesHelper(type, true, false); + } + + public static PropertyDescriptor[] getBeanSetters(Class type) { + return getPropertiesHelper(type, false, true); + } + + private static PropertyDescriptor[] getPropertiesHelper(Class type, boolean read, boolean write) { + try { + BeanInfo info = Introspector.getBeanInfo(type, Object.class); + PropertyDescriptor[] all = info.getPropertyDescriptors(); + if (read && write) { + return all; + } + List properties = new ArrayList(all.length); + for (int i = 0; i < all.length; i++) { + PropertyDescriptor pd = all[i]; + if ((read && pd.getReadMethod() != null) || + (write && pd.getWriteMethod() != null)) { + properties.add(pd); + } + } + return (PropertyDescriptor[])properties.toArray(new PropertyDescriptor[properties.size()]); + } catch (IntrospectionException e) { + throw new CodeGenerationException(e); + } + } + + + + public static Method findDeclaredMethod(final Class type, + final String methodName, final Class[] parameterTypes) + throws NoSuchMethodException { + + Class cl = type; + while (cl != null) { + try { + return cl.getDeclaredMethod(methodName, parameterTypes); + } catch (NoSuchMethodException e) { + cl = cl.getSuperclass(); + } + } + throw new NoSuchMethodException(methodName); + + } + + public static List addAllMethods(final Class type, final List list) { + + + if (type == Object.class) { + list.addAll(OBJECT_METHODS); + } else + list.addAll(java.util.Arrays.asList(type.getDeclaredMethods())); + + Class superclass = type.getSuperclass(); + if (superclass != null) { + addAllMethods(superclass, list); + } + Class[] interfaces = type.getInterfaces(); + for (int i = 0; i < interfaces.length; i++) { + addAllMethods(interfaces[i], list); + } + + return list; + } + + public static List addAllInterfaces(Class type, List list) { + Class superclass = type.getSuperclass(); + if (superclass != null) { + list.addAll(Arrays.asList(type.getInterfaces())); + addAllInterfaces(superclass, list); + } + return list; + } + + + public static Method findInterfaceMethod(Class iface) { + if (!iface.isInterface()) { + throw new IllegalArgumentException(iface + " is not an interface"); + } + Method[] methods = iface.getDeclaredMethods(); + if (methods.length != 1) { + throw new IllegalArgumentException("expecting exactly 1 method in " + iface); + } + return methods[0]; + } + + public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception { + return defineClass(className, b, loader, PROTECTION_DOMAIN); + } + + public static Class defineClass(String className, byte[] b, ClassLoader loader, ProtectionDomain protectionDomain) throws Exception { + Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), protectionDomain }; + Class c = (Class)DEFINE_CLASS.invoke(loader, args); + // Force static initializers to run. + Class.forName(className, true, loader); + return c; + } + + public static int findPackageProtected(Class[] classes) { + for (int i = 0; i < classes.length; i++) { + if (!Modifier.isPublic(classes[i].getModifiers())) { + return i; + } + } + return 0; + } + + public static MethodInfo getMethodInfo(final Member member, final int modifiers) { + final Signature sig = getSignature(member); + return new MethodInfo() { + private ClassInfo ci; + public ClassInfo getClassInfo() { + if (ci == null) + ci = ReflectUtils.getClassInfo(member.getDeclaringClass()); + return ci; + } + public int getModifiers() { + return modifiers; + } + public Signature getSignature() { + return sig; + } + public Type[] getExceptionTypes() { + return ReflectUtils.getExceptionTypes(member); + } + public Attribute getAttribute() { + return null; + } + }; + } + + public static MethodInfo getMethodInfo(Member member) { + return getMethodInfo(member, member.getModifiers()); + } + + public static ClassInfo getClassInfo(final Class clazz) { + final Type type = Type.getType(clazz); + final Type sc = (clazz.getSuperclass() == null) ? null : Type.getType(clazz.getSuperclass()); + return new ClassInfo() { + public Type getType() { + return type; + } + public Type getSuperType() { + return sc; + } + public Type[] getInterfaces() { + return TypeUtils.getTypes(clazz.getInterfaces()); + } + public int getModifiers() { + return clazz.getModifiers(); + } + }; + } + + // used by MethodInterceptorGenerated generated code + public static Method[] findMethods(String[] namesAndDescriptors, Method[] methods) + { + Map map = new HashMap(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + map.put(method.getName() + Type.getMethodDescriptor(method), method); + } + Method[] result = new Method[namesAndDescriptors.length / 2]; + for (int i = 0; i < result.length; i++) { + result[i] = (Method)map.get(namesAndDescriptors[i * 2] + namesAndDescriptors[i * 2 + 1]); + if (result[i] == null) { + // TODO: error? + } + } + return result; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/RejectModifierPredicate.java b/blade-aop/src/main/java/net/sf/cglib/core/RejectModifierPredicate.java new file mode 100644 index 000000000..5ad7758a8 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/RejectModifierPredicate.java @@ -0,0 +1,30 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.lang.reflect.*; + +public class RejectModifierPredicate implements Predicate { + private int rejectMask; + + public RejectModifierPredicate(int rejectMask) { + this.rejectMask = rejectMask; + } + + public boolean evaluate(Object arg) { + return (((Member)arg).getModifiers() & rejectMask) == 0; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/Signature.java b/blade-aop/src/main/java/net/sf/cglib/core/Signature.java new file mode 100644 index 000000000..6a176e898 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/Signature.java @@ -0,0 +1,73 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import org.objectweb.asm.Type; + +/** + * A representation of a method signature, containing the method name, + * return type, and parameter types. + */ +public class Signature { + private String name; + private String desc; + + public Signature(String name, String desc) { + // TODO: better error checking + if (name.indexOf('(') >= 0) { + throw new IllegalArgumentException("Name '" + name + "' is invalid"); + } + this.name = name; + this.desc = desc; + } + + public Signature(String name, Type returnType, Type[] argumentTypes) { + this(name, Type.getMethodDescriptor(returnType, argumentTypes)); + } + + public String getName() { + return name; + } + + public String getDescriptor() { + return desc; + } + + public Type getReturnType() { + return Type.getReturnType(desc); + } + + public Type[] getArgumentTypes() { + return Type.getArgumentTypes(desc); + } + + public String toString() { + return name + desc; + } + + public boolean equals(Object o) { + if (o == null) + return false; + if (!(o instanceof Signature)) + return false; + Signature other = (Signature)o; + return name.equals(other.name) && desc.equals(other.desc); + } + + public int hashCode() { + return name.hashCode() ^ desc.hashCode(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/TinyBitSet.java b/blade-aop/src/main/java/net/sf/cglib/core/TinyBitSet.java new file mode 100644 index 000000000..993456e40 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/TinyBitSet.java @@ -0,0 +1,78 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +public class TinyBitSet { + private static int[] T = new int[256]; + private int value = 0; + + private static int gcount(int x) { + int c = 0; + while (x != 0) { + c++; + x &= (x - 1); + } + return c; + } + + static { + for(int j = 0; j < 256; j++) { + T[j] = gcount(j); + } + } + + private static int topbit(int i) { + int j; + for (j = 0; i != 0; i ^= j) { + j = i & -i; + } + return j; + } + + private static int log2(int i) { + int j = 0; + for (j = 0; i != 0; i >>= 1) { + j++; + } + return j; + } + + public int length() { + return log2(topbit(value)); + } + + public int cardinality() { + int w = value; + int c = 0; + while (w != 0) { + c += T[w & 255]; + w >>= 8; + } + return c; + } + + public boolean get(int index) { + return (value & (1 << index)) != 0; + } + + public void set(int index) { + value |= (1 << index); + } + + public void clear(int index) { + value &= ~(1 << index); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/Transformer.java b/blade-aop/src/main/java/net/sf/cglib/core/Transformer.java new file mode 100644 index 000000000..fc7afe6b0 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/Transformer.java @@ -0,0 +1,20 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +public interface Transformer { + Object transform(Object value); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/TypeUtils.java b/blade-aop/src/main/java/net/sf/cglib/core/TypeUtils.java new file mode 100644 index 000000000..960eb04d4 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/TypeUtils.java @@ -0,0 +1,421 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.util.*; +import org.objectweb.asm.Type; + +public class TypeUtils { + private static final Map transforms = new HashMap(); + private static final Map rtransforms = new HashMap(); + + private TypeUtils() { + } + + static { + transforms.put("void", "V"); + transforms.put("byte", "B"); + transforms.put("char", "C"); + transforms.put("double", "D"); + transforms.put("float", "F"); + transforms.put("int", "I"); + transforms.put("long", "J"); + transforms.put("short", "S"); + transforms.put("boolean", "Z"); + + CollectionUtils.reverse(transforms, rtransforms); + } + + public static Type getType(String className) { + return Type.getType("L" + className.replace('.', '/') + ";"); + } + + public static boolean isFinal(int access) { + return (Constants.ACC_FINAL & access) != 0; + } + + public static boolean isStatic(int access) { + return (Constants.ACC_STATIC & access) != 0; + } + + public static boolean isProtected(int access) { + return (Constants.ACC_PROTECTED & access) != 0; + } + + public static boolean isPublic(int access) { + return (Constants.ACC_PUBLIC & access) != 0; + } + + public static boolean isAbstract(int access) { + return (Constants.ACC_ABSTRACT & access) != 0; + } + + public static boolean isInterface(int access) { + return (Constants.ACC_INTERFACE & access) != 0; + } + + public static boolean isPrivate(int access) { + return (Constants.ACC_PRIVATE & access) != 0; + } + + public static boolean isSynthetic(int access) { + return (Constants.ACC_SYNTHETIC & access) != 0; + } + + public static boolean isBridge(int access) { + return (Constants.ACC_BRIDGE & access) != 0; + } + + // getPackage returns null on JDK 1.2 + public static String getPackageName(Type type) { + return getPackageName(getClassName(type)); + } + + public static String getPackageName(String className) { + int idx = className.lastIndexOf('.'); + return (idx < 0) ? "" : className.substring(0, idx); + } + + public static String upperFirst(String s) { + if (s == null || s.length() == 0) { + return s; + } + return Character.toUpperCase(s.charAt(0)) + s.substring(1); + } + + public static String getClassName(Type type) { + if (isPrimitive(type)) { + return (String)rtransforms.get(type.getDescriptor()); + } else if (isArray(type)) { + return getClassName(getComponentType(type)) + "[]"; + } else { + return type.getClassName(); + } + } + + public static Type[] add(Type[] types, Type extra) { + if (types == null) { + return new Type[]{ extra }; + } else { + List list = Arrays.asList(types); + if (list.contains(extra)) { + return types; + } + Type[] copy = new Type[types.length + 1]; + System.arraycopy(types, 0, copy, 0, types.length); + copy[types.length] = extra; + return copy; + } + } + + public static Type[] add(Type[] t1, Type[] t2) { + // TODO: set semantics? + Type[] all = new Type[t1.length + t2.length]; + System.arraycopy(t1, 0, all, 0, t1.length); + System.arraycopy(t2, 0, all, t1.length, t2.length); + return all; + } + + public static Type fromInternalName(String name) { + // TODO; primitives? + return Type.getType("L" + name + ";"); + } + + public static Type[] fromInternalNames(String[] names) { + if (names == null) { + return null; + } + Type[] types = new Type[names.length]; + for (int i = 0; i < names.length; i++) { + types[i] = fromInternalName(names[i]); + } + return types; + } + + public static int getStackSize(Type[] types) { + int size = 0; + for (int i = 0; i < types.length; i++) { + size += types[i].getSize(); + } + return size; + } + + public static String[] toInternalNames(Type[] types) { + if (types == null) { + return null; + } + String[] names = new String[types.length]; + for (int i = 0; i < types.length; i++) { + names[i] = types[i].getInternalName(); + } + return names; + } + + public static Signature parseSignature(String s) { + int space = s.indexOf(' '); + int lparen = s.indexOf('(', space); + int rparen = s.indexOf(')', lparen); + String returnType = s.substring(0, space); + String methodName = s.substring(space + 1, lparen); + StringBuffer sb = new StringBuffer(); + sb.append('('); + for (Iterator it = parseTypes(s, lparen + 1, rparen).iterator(); it.hasNext();) { + sb.append(it.next()); + } + sb.append(')'); + sb.append(map(returnType)); + return new Signature(methodName, sb.toString()); + } + + public static Type parseType(String s) { + return Type.getType(map(s)); + } + + public static Type[] parseTypes(String s) { + List names = parseTypes(s, 0, s.length()); + Type[] types = new Type[names.size()]; + for (int i = 0; i < types.length; i++) { + types[i] = Type.getType((String)names.get(i)); + } + return types; + } + + public static Signature parseConstructor(Type[] types) { + StringBuffer sb = new StringBuffer(); + sb.append("("); + for (int i = 0; i < types.length; i++) { + sb.append(types[i].getDescriptor()); + } + sb.append(")"); + sb.append("V"); + return new Signature(Constants.CONSTRUCTOR_NAME, sb.toString()); + } + + public static Signature parseConstructor(String sig) { + return parseSignature("void (" + sig + ")"); // TODO + } + + private static List parseTypes(String s, int mark, int end) { + List types = new ArrayList(5); + for (;;) { + int next = s.indexOf(',', mark); + if (next < 0) { + break; + } + types.add(map(s.substring(mark, next).trim())); + mark = next + 1; + } + types.add(map(s.substring(mark, end).trim())); + return types; + } + + private static String map(String type) { + if (type.equals("")) { + return type; + } + String t = (String)transforms.get(type); + if (t != null) { + return t; + } else if (type.indexOf('.') < 0) { + return map("java.lang." + type); + } else { + StringBuffer sb = new StringBuffer(); + int index = 0; + while ((index = type.indexOf("[]", index) + 1) > 0) { + sb.append('['); + } + type = type.substring(0, type.length() - sb.length() * 2); + sb.append('L').append(type.replace('.', '/')).append(';'); + return sb.toString(); + } + } + + public static Type getBoxedType(Type type) { + switch (type.getSort()) { + case Type.CHAR: + return Constants.TYPE_CHARACTER; + case Type.BOOLEAN: + return Constants.TYPE_BOOLEAN; + case Type.DOUBLE: + return Constants.TYPE_DOUBLE; + case Type.FLOAT: + return Constants.TYPE_FLOAT; + case Type.LONG: + return Constants.TYPE_LONG; + case Type.INT: + return Constants.TYPE_INTEGER; + case Type.SHORT: + return Constants.TYPE_SHORT; + case Type.BYTE: + return Constants.TYPE_BYTE; + default: + return type; + } + } + + public static Type getUnboxedType(Type type) { + if (Constants.TYPE_INTEGER.equals(type)) { + return Type.INT_TYPE; + } else if (Constants.TYPE_BOOLEAN.equals(type)) { + return Type.BOOLEAN_TYPE; + } else if (Constants.TYPE_DOUBLE.equals(type)) { + return Type.DOUBLE_TYPE; + } else if (Constants.TYPE_LONG.equals(type)) { + return Type.LONG_TYPE; + } else if (Constants.TYPE_CHARACTER.equals(type)) { + return Type.CHAR_TYPE; + } else if (Constants.TYPE_BYTE.equals(type)) { + return Type.BYTE_TYPE; + } else if (Constants.TYPE_FLOAT.equals(type)) { + return Type.FLOAT_TYPE; + } else if (Constants.TYPE_SHORT.equals(type)) { + return Type.SHORT_TYPE; + } else { + return type; + } + } + + public static boolean isArray(Type type) { + return type.getSort() == Type.ARRAY; + } + + public static Type getComponentType(Type type) { + if (!isArray(type)) { + throw new IllegalArgumentException("Type " + type + " is not an array"); + } + return Type.getType(type.getDescriptor().substring(1)); + } + + public static boolean isPrimitive(Type type) { + switch (type.getSort()) { + case Type.ARRAY: + case Type.OBJECT: + return false; + default: + return true; + } + } + + public static String emulateClassGetName(Type type) { + if (isArray(type)) { + return type.getDescriptor().replace('/', '.'); + } else { + return getClassName(type); + } + } + + public static boolean isConstructor(MethodInfo method) { + return method.getSignature().getName().equals(Constants.CONSTRUCTOR_NAME); + } + + public static Type[] getTypes(Class[] classes) { + if (classes == null) { + return null; + } + Type[] types = new Type[classes.length]; + for (int i = 0; i < classes.length; i++) { + types[i] = Type.getType(classes[i]); + } + return types; + } + + public static int ICONST(int value) { + switch (value) { + case -1: return Constants.ICONST_M1; + case 0: return Constants.ICONST_0; + case 1: return Constants.ICONST_1; + case 2: return Constants.ICONST_2; + case 3: return Constants.ICONST_3; + case 4: return Constants.ICONST_4; + case 5: return Constants.ICONST_5; + } + return -1; // error + } + + public static int LCONST(long value) { + if (value == 0L) { + return Constants.LCONST_0; + } else if (value == 1L) { + return Constants.LCONST_1; + } else { + return -1; // error + } + } + + public static int FCONST(float value) { + if (value == 0f) { + return Constants.FCONST_0; + } else if (value == 1f) { + return Constants.FCONST_1; + } else if (value == 2f) { + return Constants.FCONST_2; + } else { + return -1; // error + } + } + + public static int DCONST(double value) { + if (value == 0d) { + return Constants.DCONST_0; + } else if (value == 1d) { + return Constants.DCONST_1; + } else { + return -1; // error + } + } + + public static int NEWARRAY(Type type) { + switch (type.getSort()) { + case Type.BYTE: + return Constants.T_BYTE; + case Type.CHAR: + return Constants.T_CHAR; + case Type.DOUBLE: + return Constants.T_DOUBLE; + case Type.FLOAT: + return Constants.T_FLOAT; + case Type.INT: + return Constants.T_INT; + case Type.LONG: + return Constants.T_LONG; + case Type.SHORT: + return Constants.T_SHORT; + case Type.BOOLEAN: + return Constants.T_BOOLEAN; + default: + return -1; // error + } + } + + public static String escapeType(String s) { + StringBuffer sb = new StringBuffer(); + for (int i = 0, len = s.length(); i < len; i++) { + char c = s.charAt(i); + switch (c) { + case '$': sb.append("$24"); break; + case '.': sb.append("$2E"); break; + case '[': sb.append("$5B"); break; + case ';': sb.append("$3B"); break; + case '(': sb.append("$28"); break; + case ')': sb.append("$29"); break; + case '/': sb.append("$2F"); break; + default: + sb.append(c); + } + } + return sb.toString(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/VisibilityPredicate.java b/blade-aop/src/main/java/net/sf/cglib/core/VisibilityPredicate.java new file mode 100644 index 000000000..fbefab121 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/VisibilityPredicate.java @@ -0,0 +1,52 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.core; + +import java.lang.reflect.*; +import org.objectweb.asm.Type; + +public class VisibilityPredicate implements Predicate { + private boolean protectedOk; + private String pkg; + private boolean samePackageOk; + + public VisibilityPredicate(Class source, boolean protectedOk) { + this.protectedOk = protectedOk; + // same package is not ok for the bootstrap loaded classes. In all other cases we are + // generating classes in the same classloader + this.samePackageOk = source.getClassLoader() != null; + pkg = TypeUtils.getPackageName(Type.getType(source)); + } + + public boolean evaluate(Object arg) { + Member member = (Member)arg; + int mod = member.getModifiers(); + if (Modifier.isPrivate(mod)) { + return false; + } else if (Modifier.isPublic(mod)) { + return true; + } else if (Modifier.isProtected(mod) && protectedOk) { + // protected is fine if 'protectedOk' is true (for subclasses) + return true; + } else { + // protected/package private if the member is in the same package as the source class + // and we are generating into the same classloader. + return samePackageOk + && pkg.equals(TypeUtils.getPackageName(Type.getType(member.getDeclaringClass()))); + } + } +} + diff --git a/blade-aop/src/main/java/net/sf/cglib/core/WeakCacheKey.java b/blade-aop/src/main/java/net/sf/cglib/core/WeakCacheKey.java new file mode 100644 index 000000000..ebbb23b04 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/WeakCacheKey.java @@ -0,0 +1,42 @@ +package net.sf.cglib.core; + +import java.lang.ref.WeakReference; + +/** + * Allows to check for object equality, yet the class does not keep strong reference to the target. + * {@link #equals(Object)} returns true if and only if the reference is not yet expired and target + * objects are equal in terms of {@link #equals(Object)}. + *

+ * This an internal class, thus it might disappear in future cglib releases. + * + * @param type of the reference + */ +public class WeakCacheKey extends WeakReference { + private final int hash; + + public WeakCacheKey(T referent) { + super(referent); + this.hash = referent.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof WeakCacheKey)) { + return false; + } + Object ours = get(); + Object theirs = ((WeakCacheKey) obj).get(); + return ours != null && theirs != null && ours.equals(theirs); + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public String toString() { + T t = get(); + return t == null ? "Clean WeakIdentityKey, hash: " + hash : t.toString(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/internal/CustomizerRegistry.java b/blade-aop/src/main/java/net/sf/cglib/core/internal/CustomizerRegistry.java new file mode 100644 index 000000000..e04206b65 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/internal/CustomizerRegistry.java @@ -0,0 +1,48 @@ +package net.sf.cglib.core.internal; + +import net.sf.cglib.core.Customizer; +import net.sf.cglib.core.FieldTypeCustomizer; +import net.sf.cglib.core.KeyFactoryCustomizer; + +import java.util.*; + +public class CustomizerRegistry { + private final Class[] customizerTypes; + private Map> customizers = new HashMap>(); + + public CustomizerRegistry(Class[] customizerTypes) { + this.customizerTypes = customizerTypes; + } + + public void add(KeyFactoryCustomizer customizer) { + Class klass = customizer.getClass(); + for (Class type : customizerTypes) { + if (type.isAssignableFrom(klass)) { + List list = customizers.get(type); + if (list == null) { + customizers.put(type, list = new ArrayList()); + } + list.add(customizer); + } + } + } + + public List get(Class klass) { + List list = customizers.get(klass); + if (list == null) { + return Collections.emptyList(); + } + return (List) list; + } + + /** + * @deprecated Only to keep backward compatibility. + */ + @Deprecated + public static CustomizerRegistry singleton(Customizer customizer) + { + CustomizerRegistry registry = new CustomizerRegistry(new Class[]{Customizer.class}); + registry.add(customizer); + return registry; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/internal/Function.java b/blade-aop/src/main/java/net/sf/cglib/core/internal/Function.java new file mode 100644 index 000000000..5da759c61 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/internal/Function.java @@ -0,0 +1,5 @@ +package net.sf.cglib.core.internal; + +public interface Function { + V apply(K key); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/core/internal/LoadingCache.java b/blade-aop/src/main/java/net/sf/cglib/core/internal/LoadingCache.java new file mode 100644 index 000000000..24cd9e418 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/core/internal/LoadingCache.java @@ -0,0 +1,86 @@ +package net.sf.cglib.core.internal; + +import java.util.concurrent.*; + +public class LoadingCache { + protected final ConcurrentMap map; + protected final Function loader; + protected final Function keyMapper; + + public static final Function IDENTITY = new Function() { + public Object apply(Object key) { + return key; + } + }; + + public LoadingCache(Function keyMapper, Function loader) { + this.keyMapper = keyMapper; + this.loader = loader; + this.map = new ConcurrentHashMap(); + } + + @SuppressWarnings("unchecked") + public static Function identity() { + return IDENTITY; + } + + public V get(K key) { + final KK cacheKey = keyMapper.apply(key); + Object v = map.get(cacheKey); + if (v != null && !(v instanceof FutureTask)) { + return (V) v; + } + + return createEntry(key, cacheKey, v); + } + + /** + * Loads entry to the cache. + * If entry is missing, put {@link FutureTask} first so other competing thread might wait for the result. + * @param key original key that would be used to load the instance + * @param cacheKey key that would be used to store the entry in internal map + * @param v null or {@link FutureTask} + * @return newly created instance + */ + protected V createEntry(final K key, KK cacheKey, Object v) { + FutureTask task; + boolean creator = false; + if (v != null) { + // Another thread is already loading an instance + task = (FutureTask) v; + } else { + task = new FutureTask(new Callable() { + public V call() throws Exception { + return loader.apply(key); + } + }); + Object prevTask = map.putIfAbsent(cacheKey, task); + if (prevTask == null) { + // creator does the load + creator = true; + task.run(); + } else if (prevTask instanceof FutureTask) { + task = (FutureTask) prevTask; + } else { + return (V) prevTask; + } + } + + V result; + try { + result = task.get(); + } catch (InterruptedException e) { + throw new IllegalStateException("Interrupted while loading cache item", e); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) { + throw ((RuntimeException) cause); + } + throw new IllegalStateException("Unable to load cache item", cause); + } + if (creator) { + map.put(cacheKey, result); + } + return result; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/BridgeMethodResolver.java b/blade-aop/src/main/java/net/sf/cglib/proxy/BridgeMethodResolver.java new file mode 100644 index 000000000..574857c1c --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/BridgeMethodResolver.java @@ -0,0 +1,114 @@ +/* + * Copyright 2011 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import net.sf.cglib.core.Signature; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +/** + * Uses bytecode reflection to figure out the targets of all bridge methods + * that use invokespecial, so that we can later rewrite them to use invokevirtual. + * + * @author sberlin@gmail.com (Sam Berlin) + */ +class BridgeMethodResolver { + + private final Map/* */declToBridge; + + public BridgeMethodResolver(Map declToBridge) { + this.declToBridge = declToBridge; + } + + /** + * Finds all bridge methods that are being called with invokespecial & + * returns them. + */ + public Map/**/resolveAll() { + Map resolved = new HashMap(); + for (Iterator entryIter = declToBridge.entrySet().iterator(); entryIter.hasNext(); ) { + Map.Entry entry = (Map.Entry)entryIter.next(); + Class owner = (Class)entry.getKey(); + Set bridges = (Set)entry.getValue(); + try { + new ClassReader(owner.getName()) + .accept(new BridgedFinder(bridges, resolved), + ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); + } catch(IOException ignored) {} + } + return resolved; + } + + private static class BridgedFinder extends ClassVisitor { + private Map/**/ resolved; + private Set/**/ eligableMethods; + + private Signature currentMethod = null; + + BridgedFinder(Set eligableMethods, Map resolved) { + super(Opcodes.ASM5); + this.resolved = resolved; + this.eligableMethods = eligableMethods; + } + + public void visit(int version, int access, String name, + String signature, String superName, String[] interfaces) { + } + + public MethodVisitor visitMethod(int access, String name, String desc, + String signature, String[] exceptions) { + Signature sig = new Signature(name, desc); + if (eligableMethods.remove(sig)) { + currentMethod = sig; + return new MethodVisitor(Opcodes.ASM5) { + public void visitMethodInsn(int opcode, String owner, String name, + String desc, boolean itf) { + if (opcode == Opcodes.INVOKESPECIAL && currentMethod != null) { + Signature target = new Signature(name, desc); + // If the target signature is the same as the current, + // we shouldn't change our bridge becaues invokespecial + // is the only way to make progress (otherwise we'll + // get infinite recursion). This would typically + // only happen when a bridge method is created to widen + // the visibility of a superclass' method. + if (!target.equals(currentMethod)) { + resolved.put(currentMethod, target); + } + currentMethod = null; + } + } + }; + } else { + return null; + } + } + } + +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/Callback.java b/blade-aop/src/main/java/net/sf/cglib/proxy/Callback.java new file mode 100644 index 000000000..bcd7f5dd7 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/Callback.java @@ -0,0 +1,29 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +/** + * All callback interfaces used by {@link Enhancer} extend this interface. + * @see MethodInterceptor + * @see NoOp + * @see LazyLoader + * @see Dispatcher + * @see InvocationHandler + * @see FixedValue + */ +public interface Callback +{ +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackFilter.java b/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackFilter.java new file mode 100644 index 000000000..21f001926 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackFilter.java @@ -0,0 +1,46 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.lang.reflect.Method; + +/** + * Map methods of subclasses generated by {@link Enhancer} to a particular + * callback. The type of the callbacks chosen for each method affects + * the bytecode generated for that method in the subclass, and cannot + * change for the life of the class. + *

Note: {@link CallbackFilter} implementations are supposed to be + * lightweight as cglib might keep {@link CallbackFilter} objects + * alive to enable caching of generated classes. Prefer using {@code static} + * classes for implementation of {@link CallbackFilter}.

+ */ +public interface CallbackFilter { + /** + * Map a method to a callback. + * @param method the intercepted method + * @return the index into the array of callbacks (as specified by {@link Enhancer#setCallbacks}) to use for the method, + */ + int accept(Method method); + + /** + * The CallbackFilter in use affects which cached class + * the Enhancer will use, so this is a reminder that + * you should correctly implement equals and + * hashCode for custom CallbackFilter + * implementations in order to improve performance. + */ + boolean equals(Object o); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackGenerator.java b/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackGenerator.java new file mode 100644 index 000000000..283f22ac7 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackGenerator.java @@ -0,0 +1,36 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.util.List; +import net.sf.cglib.core.*; + +interface CallbackGenerator +{ + void generate(ClassEmitter ce, Context context, List methods) throws Exception; + void generateStatic(CodeEmitter e, Context context, List methods) throws Exception; + + interface Context + { + ClassLoader getClassLoader(); + CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method); + int getOriginalModifiers(MethodInfo method); + int getIndex(MethodInfo method); + void emitCallback(CodeEmitter ce, int index); + Signature getImplSignature(MethodInfo method); + void emitInvoke(CodeEmitter e, MethodInfo method); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackHelper.java b/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackHelper.java new file mode 100644 index 000000000..b2e7e3039 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackHelper.java @@ -0,0 +1,98 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import net.sf.cglib.core.ReflectUtils; +import java.lang.reflect.Method; +import java.util.*; + +/** + * @version $Id: CallbackHelper.java,v 1.2 2004/06/24 21:15:20 herbyderby Exp $ + */ +abstract public class CallbackHelper +implements CallbackFilter +{ + private Map methodMap = new HashMap(); + private List callbacks = new ArrayList(); + + public CallbackHelper(Class superclass, Class[] interfaces) + { + List methods = new ArrayList(); + Enhancer.getMethods(superclass, interfaces, methods); + Map indexes = new HashMap(); + for (int i = 0, size = methods.size(); i < size; i++) { + Method method = (Method)methods.get(i); + Object callback = getCallback(method); + if (callback == null) + throw new IllegalStateException("getCallback cannot return null"); + boolean isCallback = callback instanceof Callback; + if (!(isCallback || (callback instanceof Class))) + throw new IllegalStateException("getCallback must return a Callback or a Class"); + if (i > 0 && ((callbacks.get(i - 1) instanceof Callback) ^ isCallback)) + throw new IllegalStateException("getCallback must return a Callback or a Class consistently for every Method"); + Integer index = (Integer)indexes.get(callback); + if (index == null) { + index = new Integer(callbacks.size()); + indexes.put(callback, index); + } + methodMap.put(method, index); + callbacks.add(callback); + } + } + + abstract protected Object getCallback(Method method); + + public Callback[] getCallbacks() + { + if (callbacks.size() == 0) + return new Callback[0]; + if (callbacks.get(0) instanceof Callback) { + return (Callback[])callbacks.toArray(new Callback[callbacks.size()]); + } else { + throw new IllegalStateException("getCallback returned classes, not callbacks; call getCallbackTypes instead"); + } + } + + public Class[] getCallbackTypes() + { + if (callbacks.size() == 0) + return new Class[0]; + if (callbacks.get(0) instanceof Callback) { + return ReflectUtils.getClasses(getCallbacks()); + } else { + return (Class[])callbacks.toArray(new Class[callbacks.size()]); + } + } + + public int accept(Method method) + { + return ((Integer)methodMap.get(method)).intValue(); + } + + public int hashCode() + { + return methodMap.hashCode(); + } + + public boolean equals(Object o) + { + if (o == null) + return false; + if (!(o instanceof CallbackHelper)) + return false; + return methodMap.equals(((CallbackHelper)o).methodMap); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackInfo.java b/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackInfo.java new file mode 100644 index 000000000..2fcece882 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/CallbackInfo.java @@ -0,0 +1,116 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import org.objectweb.asm.Type; + +class CallbackInfo +{ + public static Type[] determineTypes(Class[] callbackTypes) { + return determineTypes(callbackTypes, true); + } + + public static Type[] determineTypes(Class[] callbackTypes, boolean checkAll) { + Type[] types = new Type[callbackTypes.length]; + for (int i = 0; i < types.length; i++) { + types[i] = determineType(callbackTypes[i], checkAll); + } + return types; + } + + public static Type[] determineTypes(Callback[] callbacks) { + return determineTypes(callbacks, true); + } + + public static Type[] determineTypes(Callback[] callbacks, boolean checkAll) { + Type[] types = new Type[callbacks.length]; + for (int i = 0; i < types.length; i++) { + types[i] = determineType(callbacks[i], checkAll); + } + return types; + } + + public static CallbackGenerator[] getGenerators(Type[] callbackTypes) { + CallbackGenerator[] generators = new CallbackGenerator[callbackTypes.length]; + for (int i = 0; i < generators.length; i++) { + generators[i] = getGenerator(callbackTypes[i]); + } + return generators; + } + + //////////////////// PRIVATE //////////////////// + + private Class cls; + private CallbackGenerator generator; + private Type type; + + private static final CallbackInfo[] CALLBACKS = { + new CallbackInfo(NoOp.class, NoOpGenerator.INSTANCE), + new CallbackInfo(MethodInterceptor.class, MethodInterceptorGenerator.INSTANCE), + new CallbackInfo(InvocationHandler.class, InvocationHandlerGenerator.INSTANCE), + new CallbackInfo(LazyLoader.class, LazyLoaderGenerator.INSTANCE), + new CallbackInfo(Dispatcher.class, DispatcherGenerator.INSTANCE), + new CallbackInfo(FixedValue.class, FixedValueGenerator.INSTANCE), + new CallbackInfo(ProxyRefDispatcher.class, DispatcherGenerator.PROXY_REF_INSTANCE), + }; + + private CallbackInfo(Class cls, CallbackGenerator generator) { + this.cls = cls; + this.generator = generator; + type = Type.getType(cls); + } + + private static Type determineType(Callback callback, boolean checkAll) { + if (callback == null) { + throw new IllegalStateException("Callback is null"); + } + return determineType(callback.getClass(), checkAll); + } + + private static Type determineType(Class callbackType, boolean checkAll) { + Class cur = null; + Type type = null; + for (int i = 0; i < CALLBACKS.length; i++) { + CallbackInfo info = CALLBACKS[i]; + if (info.cls.isAssignableFrom(callbackType)) { + if (cur != null) { + throw new IllegalStateException("Callback implements both " + cur + " and " + info.cls); + } + cur = info.cls; + type = info.type; + if (!checkAll) { + break; + } + } + } + if (cur == null) { + throw new IllegalStateException("Unknown callback type " + callbackType); + } + return type; + } + + private static CallbackGenerator getGenerator(Type callbackType) { + for (int i = 0; i < CALLBACKS.length; i++) { + CallbackInfo info = CALLBACKS[i]; + if (info.type.equals(callbackType)) { + return info.generator; + } + } + throw new IllegalStateException("Unknown callback type " + callbackType); + } +} + + diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/Dispatcher.java b/blade-aop/src/main/java/net/sf/cglib/proxy/Dispatcher.java new file mode 100644 index 000000000..374a06efd --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/Dispatcher.java @@ -0,0 +1,30 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +/** + * Dispatching {@link Enhancer} callback. This is identical to the + * {@link LazyLoader} interface but needs to be separate so that Enhancer + * knows which type of code to generate. + */ +public interface Dispatcher extends Callback { + /** + * Return the object which the original method invocation should + * be dispatched. This method is called for every method invocation. + * @return an object that can invoke the method + */ + Object loadObject() throws Exception; +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/DispatcherGenerator.java b/blade-aop/src/main/java/net/sf/cglib/proxy/DispatcherGenerator.java new file mode 100644 index 000000000..3a337ad72 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/DispatcherGenerator.java @@ -0,0 +1,65 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.Type; + +class DispatcherGenerator implements CallbackGenerator { + public static final DispatcherGenerator INSTANCE = + new DispatcherGenerator(false); + public static final DispatcherGenerator PROXY_REF_INSTANCE = + new DispatcherGenerator(true); + + private static final Type DISPATCHER = + TypeUtils.parseType("net.sf.cglib.proxy.Dispatcher"); + private static final Type PROXY_REF_DISPATCHER = + TypeUtils.parseType("net.sf.cglib.proxy.ProxyRefDispatcher"); + private static final Signature LOAD_OBJECT = + TypeUtils.parseSignature("Object loadObject()"); + private static final Signature PROXY_REF_LOAD_OBJECT = + TypeUtils.parseSignature("Object loadObject(Object)"); + + private boolean proxyRef; + + private DispatcherGenerator(boolean proxyRef) { + this.proxyRef = proxyRef; + } + + public void generate(ClassEmitter ce, Context context, List methods) { + for (Iterator it = methods.iterator(); it.hasNext();) { + MethodInfo method = (MethodInfo)it.next(); + if (!TypeUtils.isProtected(method.getModifiers())) { + CodeEmitter e = context.beginMethod(ce, method); + context.emitCallback(e, context.getIndex(method)); + if (proxyRef) { + e.load_this(); + e.invoke_interface(PROXY_REF_DISPATCHER, PROXY_REF_LOAD_OBJECT); + } else { + e.invoke_interface(DISPATCHER, LOAD_OBJECT); + } + e.checkcast(method.getClassInfo().getType()); + e.load_args(); + e.invoke(method); + e.return_value(); + e.end_method(); + } + } + } + + public void generateStatic(CodeEmitter e, Context context, List methods) { } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/Enhancer.java b/blade-aop/src/main/java/net/sf/cglib/proxy/Enhancer.java new file mode 100644 index 000000000..7e7d831bc --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/Enhancer.java @@ -0,0 +1,1315 @@ +/* + * Copyright 2002,2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.lang.ref.WeakReference; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.ProtectionDomain; +import java.util.*; + +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; +import org.objectweb.asm.Label; + +/** + * Generates dynamic subclasses to enable method interception. This + * class started as a substitute for the standard Dynamic Proxy support + * included with JDK 1.3, but one that allowed the proxies to extend a + * concrete base class, in addition to implementing interfaces. The dynamically + * generated subclasses override the non-final methods of the superclass and + * have hooks which callback to user-defined interceptor + * implementations. + *

+ * The original and most general callback type is the {@link MethodInterceptor}, which + * in AOP terms enables "around advice"--that is, you can invoke custom code both before + * and after the invocation of the "super" method. In addition you can modify the + * arguments before calling the super method, or not call it at all. + *

+ * Although MethodInterceptor is generic enough to meet any + * interception need, it is often overkill. For simplicity and performance, additional + * specialized callback types, such as {@link LazyLoader} are also available. + * Often a single callback will be used per enhanced class, but you can control + * which callback is used on a per-method basis with a {@link CallbackFilter}. + *

+ * The most common uses of this class are embodied in the static helper methods. For + * advanced needs, such as customizing the ClassLoader to use, you should create + * a new instance of Enhancer. Other classes within CGLIB follow a similar pattern. + *

+ * All enhanced objects implement the {@link Factory} interface, unless {@link #setUseFactory} is + * used to explicitly disable this feature. The Factory interface provides an API + * to change the callbacks of an existing object, as well as a faster and easier way to create + * new instances of the same type. + *

+ * For an almost drop-in replacement for + * java.lang.reflect.Proxy, see the {@link Proxy} class. + */ +public class Enhancer extends AbstractClassGenerator +{ + private static final CallbackFilter ALL_ZERO = new CallbackFilter(){ + public int accept(Method method) { + return 0; + } + }; + + private static final Source SOURCE = new Source(Enhancer.class.getName()); + private static final EnhancerKey KEY_FACTORY = + (EnhancerKey)KeyFactory.create(EnhancerKey.class, KeyFactory.HASH_ASM_TYPE, null); + + private static final String BOUND_FIELD = "CGLIB$BOUND"; + private static final String FACTORY_DATA_FIELD = "CGLIB$FACTORY_DATA"; + private static final String THREAD_CALLBACKS_FIELD = "CGLIB$THREAD_CALLBACKS"; + private static final String STATIC_CALLBACKS_FIELD = "CGLIB$STATIC_CALLBACKS"; + private static final String SET_THREAD_CALLBACKS_NAME = "CGLIB$SET_THREAD_CALLBACKS"; + private static final String SET_STATIC_CALLBACKS_NAME = "CGLIB$SET_STATIC_CALLBACKS"; + private static final String CONSTRUCTED_FIELD = "CGLIB$CONSTRUCTED"; + /** + * {@link net.sf.cglib.core.AbstractClassGenerator.ClassLoaderData#generatedClasses} requires to keep cache key + * in a good shape (the keys should be up and running if the proxy class is alive), and one of the cache keys is + * {@link CallbackFilter}. That is why the generated class contains static field that keeps strong reference to + * the {@link #filter}. + *

This dance achieves two goals: ensures generated class is reusable and available through generatedClasses + * cache, and it enables to unload classloader and the related {@link CallbackFilter} in case user does not need + * that

+ */ + private static final String CALLBACK_FILTER_FIELD = "CGLIB$CALLBACK_FILTER"; + + private static final Type OBJECT_TYPE = + TypeUtils.parseType("Object"); + private static final Type FACTORY = + TypeUtils.parseType("net.sf.cglib.proxy.Factory"); + private static final Type ILLEGAL_STATE_EXCEPTION = + TypeUtils.parseType("IllegalStateException"); + private static final Type ILLEGAL_ARGUMENT_EXCEPTION = + TypeUtils.parseType("IllegalArgumentException"); + private static final Type THREAD_LOCAL = + TypeUtils.parseType("ThreadLocal"); + private static final Type CALLBACK = + TypeUtils.parseType("net.sf.cglib.proxy.Callback"); + private static final Type CALLBACK_ARRAY = + Type.getType(Callback[].class); + private static final Signature CSTRUCT_NULL = + TypeUtils.parseConstructor(""); + private static final Signature SET_THREAD_CALLBACKS = + new Signature(SET_THREAD_CALLBACKS_NAME, Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY }); + private static final Signature SET_STATIC_CALLBACKS = + new Signature(SET_STATIC_CALLBACKS_NAME, Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY }); + private static final Signature NEW_INSTANCE = + new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{ CALLBACK_ARRAY }); + private static final Signature MULTIARG_NEW_INSTANCE = + new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{ + Constants.TYPE_CLASS_ARRAY, + Constants.TYPE_OBJECT_ARRAY, + CALLBACK_ARRAY, + }); + private static final Signature SINGLE_NEW_INSTANCE = + new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{ CALLBACK }); + private static final Signature SET_CALLBACK = + new Signature("setCallback", Type.VOID_TYPE, new Type[]{ Type.INT_TYPE, CALLBACK }); + private static final Signature GET_CALLBACK = + new Signature("getCallback", CALLBACK, new Type[]{ Type.INT_TYPE }); + private static final Signature SET_CALLBACKS = + new Signature("setCallbacks", Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY }); + private static final Signature GET_CALLBACKS = + new Signature("getCallbacks", CALLBACK_ARRAY, new Type[0]); + private static final Signature THREAD_LOCAL_GET = + TypeUtils.parseSignature("Object get()"); + private static final Signature THREAD_LOCAL_SET = + TypeUtils.parseSignature("void set(Object)"); + private static final Signature BIND_CALLBACKS = + TypeUtils.parseSignature("void CGLIB$BIND_CALLBACKS(Object)"); + + private EnhancerFactoryData currentData; + private Object currentKey; + + /** Internal interface, only public due to ClassLoader issues. */ + public interface EnhancerKey { + public Object newInstance(String type, + String[] interfaces, + WeakCacheKey filter, + Type[] callbackTypes, + boolean useFactory, + boolean interceptDuringConstruction, + Long serialVersionUID); + } + + private Class[] interfaces; + private CallbackFilter filter; + private Callback[] callbacks; + private Type[] callbackTypes; + private boolean validateCallbackTypes; + private boolean classOnly; + private Class superclass; + private Class[] argumentTypes; + private Object[] arguments; + private boolean useFactory = true; + private Long serialVersionUID; + private boolean interceptDuringConstruction = true; + + /** + * Create a new Enhancer. A new Enhancer + * object should be used for each generated object, and should not + * be shared across threads. To create additional instances of a + * generated class, use the Factory interface. + * @see Factory + */ + public Enhancer() { + super(SOURCE); + } + + /** + * Set the class which the generated class will extend. As a convenience, + * if the supplied superclass is actually an interface, setInterfaces + * will be called with the appropriate argument instead. + * A non-interface argument must not be declared as final, and must have an + * accessible constructor. + * @param superclass class to extend or interface to implement + * @see #setInterfaces(Class[]) + */ + public void setSuperclass(Class superclass) { + if (superclass != null && superclass.isInterface()) { + setInterfaces(new Class[]{ superclass }); + } else if (superclass != null && superclass.equals(Object.class)) { + // affects choice of ClassLoader + this.superclass = null; + } else { + this.superclass = superclass; + } + } + + /** + * Set the interfaces to implement. The Factory interface will + * always be implemented regardless of what is specified here. + * @param interfaces array of interfaces to implement, or null + * @see Factory + */ + public void setInterfaces(Class[] interfaces) { + this.interfaces = interfaces; + } + + /** + * Set the {@link CallbackFilter} used to map the generated class' methods + * to a particular callback index. + * New object instances will always use the same mapping, but may use different + * actual callback objects. + * @param filter the callback filter to use when generating a new class + * @see #setCallbacks + */ + public void setCallbackFilter(CallbackFilter filter) { + this.filter = filter; + } + + + /** + * Set the single {@link Callback} to use. + * Ignored if you use {@link #createClass}. + * @param callback the callback to use for all methods + * @see #setCallbacks + */ + public void setCallback(final Callback callback) { + setCallbacks(new Callback[]{ callback }); + } + + /** + * Set the array of callbacks to use. + * Ignored if you use {@link #createClass}. + * You must use a {@link CallbackFilter} to specify the index into this + * array for each method in the proxied class. + * @param callbacks the callback array + * @see #setCallbackFilter + * @see #setCallback + */ + public void setCallbacks(Callback[] callbacks) { + if (callbacks != null && callbacks.length == 0) { + throw new IllegalArgumentException("Array cannot be empty"); + } + this.callbacks = callbacks; + } + + /** + * Set whether the enhanced object instances should implement + * the {@link Factory} interface. + * This was added for tools that need for proxies to be more + * indistinguishable from their targets. Also, in some cases it may + * be necessary to disable the Factory interface to + * prevent code from changing the underlying callbacks. + * @param useFactory whether to implement Factory; default is true + */ + public void setUseFactory(boolean useFactory) { + this.useFactory = useFactory; + } + + /** + * Set whether methods called from within the proxy's constructer + * will be intercepted. The default value is true. Unintercepted methods + * will call the method of the proxy's base class, if it exists. + * @param interceptDuringConstruction whether to intercept methods called from the constructor + */ + public void setInterceptDuringConstruction(boolean interceptDuringConstruction) { + this.interceptDuringConstruction = interceptDuringConstruction; + } + + /** + * Set the single type of {@link Callback} to use. + * This may be used instead of {@link #setCallback} when calling + * {@link #createClass}, since it may not be possible to have + * an array of actual callback instances. + * @param callbackType the type of callback to use for all methods + * @see #setCallbackTypes + */ + public void setCallbackType(Class callbackType) { + setCallbackTypes(new Class[]{ callbackType }); + } + + /** + * Set the array of callback types to use. + * This may be used instead of {@link #setCallbacks} when calling + * {@link #createClass}, since it may not be possible to have + * an array of actual callback instances. + * You must use a {@link CallbackFilter} to specify the index into this + * array for each method in the proxied class. + * @param callbackTypes the array of callback types + */ + public void setCallbackTypes(Class[] callbackTypes) { + if (callbackTypes != null && callbackTypes.length == 0) { + throw new IllegalArgumentException("Array cannot be empty"); + } + this.callbackTypes = CallbackInfo.determineTypes(callbackTypes); + } + + /** + * Generate a new class if necessary and uses the specified + * callbacks (if any) to create a new object instance. + * Uses the no-arg constructor of the superclass. + * @return a new instance + */ + public Object create() { + classOnly = false; + argumentTypes = null; + return createHelper(); + } + + /** + * Generate a new class if necessary and uses the specified + * callbacks (if any) to create a new object instance. + * Uses the constructor of the superclass matching the argumentTypes + * parameter, with the given arguments. + * @param argumentTypes constructor signature + * @param arguments compatible wrapped arguments to pass to constructor + * @return a new instance + */ + public Object create(Class[] argumentTypes, Object[] arguments) { + classOnly = false; + if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) { + throw new IllegalArgumentException("Arguments must be non-null and of equal length"); + } + this.argumentTypes = argumentTypes; + this.arguments = arguments; + return createHelper(); + } + + /** + * Generate a new class if necessary and return it without creating a new instance. + * This ignores any callbacks that have been set. + * To create a new instance you will have to use reflection, and methods + * called during the constructor will not be intercepted. To avoid this problem, + * use the multi-arg create method. + * @see #create(Class[], Object[]) + */ + public Class createClass() { + classOnly = true; + return (Class)createHelper(); + } + + /** + * Insert a static serialVersionUID field into the generated class. + * @param sUID the field value, or null to avoid generating field. + */ + public void setSerialVersionUID(Long sUID) { + serialVersionUID = sUID; + } + + private void preValidate() { + if (callbackTypes == null) { + callbackTypes = CallbackInfo.determineTypes(callbacks, false); + validateCallbackTypes = true; + } + if (filter == null) { + if (callbackTypes.length > 1) { + throw new IllegalStateException("Multiple callback types possible but no filter specified"); + } + filter = ALL_ZERO; + } + } + + private void validate() { + if (classOnly ^ (callbacks == null)) { + if (classOnly) { + throw new IllegalStateException("createClass does not accept callbacks"); + } else { + throw new IllegalStateException("Callbacks are required"); + } + } + if (classOnly && (callbackTypes == null)) { + throw new IllegalStateException("Callback types are required"); + } + if (validateCallbackTypes) { + callbackTypes = null; + } + if (callbacks != null && callbackTypes != null) { + if (callbacks.length != callbackTypes.length) { + throw new IllegalStateException("Lengths of callback and callback types array must be the same"); + } + Type[] check = CallbackInfo.determineTypes(callbacks); + for (int i = 0; i < check.length; i++) { + if (!check[i].equals(callbackTypes[i])) { + throw new IllegalStateException("Callback " + check[i] + " is not assignable to " + callbackTypes[i]); + } + } + } else if (callbacks != null) { + callbackTypes = CallbackInfo.determineTypes(callbacks); + } + if (interfaces != null) { + for (int i = 0; i < interfaces.length; i++) { + if (interfaces[i] == null) { + throw new IllegalStateException("Interfaces cannot be null"); + } + if (!interfaces[i].isInterface()) { + throw new IllegalStateException(interfaces[i] + " is not an interface"); + } + } + } + } + + /** + * The idea of the class is to cache relevant java.lang.reflect instances so + * proxy-class can be instantiated faster that when using {@link ReflectUtils#newInstance(Class, Class[], Object[])} + * and {@link Enhancer#setThreadCallbacks(Class, Callback[])} + */ + static class EnhancerFactoryData { + public final Class generatedClass; + private final Method setThreadCallbacks; + private final Class[] primaryConstructorArgTypes; + private final Constructor primaryConstructor; + + public EnhancerFactoryData(Class generatedClass, Class[] primaryConstructorArgTypes, boolean classOnly) { + this.generatedClass = generatedClass; + try { + setThreadCallbacks = getCallbacksSetter(generatedClass, SET_THREAD_CALLBACKS_NAME); + if (classOnly) { + this.primaryConstructorArgTypes = null; + this.primaryConstructor = null; + } else { + this.primaryConstructorArgTypes = primaryConstructorArgTypes; + this.primaryConstructor = ReflectUtils.getConstructor(generatedClass, primaryConstructorArgTypes); + } + } catch (NoSuchMethodException e) { + throw new CodeGenerationException(e); + } + } + + /** + * Creates proxy instance for given argument types, and assigns the callbacks. + * Ideally, for each proxy class, just one set of argument types should be used, + * otherwise it would have to spend time on constructor lookup. + * Technically, it is a re-implementation of {@link Enhancer#createUsingReflection(Class)}, + * with "cache {@link #setThreadCallbacks} and {@link #primaryConstructor}" + * + * @see #createUsingReflection(Class) + * @param argumentTypes constructor argument types + * @param arguments constructor arguments + * @param callbacks callbacks to set for the new instance + * @return newly created proxy + */ + public Object newInstance(Class[] argumentTypes, Object[] arguments, Callback[] callbacks) { + setThreadCallbacks(callbacks); + try { + // Explicit reference equality is added here just in case Arrays.equals does not have one + if (primaryConstructorArgTypes == argumentTypes || + Arrays.equals(primaryConstructorArgTypes, argumentTypes)) { + // If we have relevant Constructor instance at hand, just call it + // This skips "get constructors" machinery + return ReflectUtils.newInstance(primaryConstructor, arguments); + } + // Take a slow path if observing unexpected argument types + return ReflectUtils.newInstance(generatedClass, argumentTypes, arguments); + } finally { + // clear thread callbacks to allow them to be gc'd + setThreadCallbacks(null); + } + + } + + private void setThreadCallbacks(Callback[] callbacks) { + try { + setThreadCallbacks.invoke(generatedClass, (Object) callbacks); + } catch (IllegalAccessException e) { + throw new CodeGenerationException(e); + } catch (InvocationTargetException e) { + throw new CodeGenerationException(e.getTargetException()); + } + } + } + + private Object createHelper() { + preValidate(); + Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null, + ReflectUtils.getNames(interfaces), + filter == ALL_ZERO ? null : new WeakCacheKey(filter), + callbackTypes, + useFactory, + interceptDuringConstruction, + serialVersionUID); + this.currentKey = key; + Object result = super.create(key); + return result; + } + + @Override + protected Class generate(ClassLoaderData data) { + validate(); + if (superclass != null) { + setNamePrefix(superclass.getName()); + } else if (interfaces != null) { + setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName()); + } + return super.generate(data); + } + + protected ClassLoader getDefaultClassLoader() { + if (superclass != null) { + return superclass.getClassLoader(); + } else if (interfaces != null) { + return interfaces[0].getClassLoader(); + } else { + return null; + } + } + + protected ProtectionDomain getProtectionDomain() { + if (superclass != null) { + return ReflectUtils.getProtectionDomain(superclass); + } else if (interfaces != null) { + return ReflectUtils.getProtectionDomain(interfaces[0]); + } else { + return null; + } + } + + private Signature rename(Signature sig, int index) { + return new Signature("CGLIB$" + sig.getName() + "$" + index, + sig.getDescriptor()); + } + + /** + * Finds all of the methods that will be extended by an + * Enhancer-generated class using the specified superclass and + * interfaces. This can be useful in building a list of Callback + * objects. The methods are added to the end of the given list. Due + * to the subclassing nature of the classes generated by Enhancer, + * the methods are guaranteed to be non-static, non-final, and + * non-private. Each method signature will only occur once, even if + * it occurs in multiple classes. + * @param superclass the class that will be extended, or null + * @param interfaces the list of interfaces that will be implemented, or null + * @param methods the list into which to copy the applicable methods + */ + public static void getMethods(Class superclass, Class[] interfaces, List methods) + { + getMethods(superclass, interfaces, methods, null, null); + } + + private static void getMethods(Class superclass, Class[] interfaces, List methods, List interfaceMethods, Set forcePublic) + { + ReflectUtils.addAllMethods(superclass, methods); + List target = (interfaceMethods != null) ? interfaceMethods : methods; + if (interfaces != null) { + for (int i = 0; i < interfaces.length; i++) { + if (interfaces[i] != Factory.class) { + ReflectUtils.addAllMethods(interfaces[i], target); + } + } + } + if (interfaceMethods != null) { + if (forcePublic != null) { + forcePublic.addAll(MethodWrapper.createSet(interfaceMethods)); + } + methods.addAll(interfaceMethods); + } + CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC_STATIC)); + CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true)); + CollectionUtils.filter(methods, new DuplicatesPredicate()); + CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC_FINAL)); + } + + public void generateClass(ClassVisitor v) throws Exception { + Class sc = (superclass == null) ? Object.class : superclass; + + if (TypeUtils.isFinal(sc.getModifiers())) + throw new IllegalArgumentException("Cannot subclass final class " + sc.getName()); + List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors())); + filterConstructors(sc, constructors); + + // Order is very important: must add superclass, then + // its superclass chain, then each interface and + // its superinterfaces. + List actualMethods = new ArrayList(); + List interfaceMethods = new ArrayList(); + final Set forcePublic = new HashSet(); + getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic); + + List methods = CollectionUtils.transform(actualMethods, new Transformer() { + public Object transform(Object value) { + Method method = (Method)value; + int modifiers = Constants.ACC_FINAL + | (method.getModifiers() + & ~Constants.ACC_ABSTRACT + & ~Constants.ACC_NATIVE + & ~Constants.ACC_SYNCHRONIZED); + if (forcePublic.contains(MethodWrapper.create(method))) { + modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC; + } + return ReflectUtils.getMethodInfo(method, modifiers); + } + }); + + ClassEmitter e = new ClassEmitter(v); + if (currentData == null) { + e.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + getClassName(), + Type.getType(sc), + (useFactory ? + TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) : + TypeUtils.getTypes(interfaces)), + Constants.SOURCE_FILE); + } else { + e.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + getClassName(), + null, + new Type[]{FACTORY}, + Constants.SOURCE_FILE); + } + List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance()); + + e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null); + e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null); + if (!interceptDuringConstruction) { + e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null); + } + e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null); + e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null); + if (serialVersionUID != null) { + e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID); + } + + for (int i = 0; i < callbackTypes.length; i++) { + e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null); + } + // This is declared private to avoid "public field" pollution + e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, CALLBACK_FILTER_FIELD, OBJECT_TYPE, null); + + if (currentData == null) { + emitMethods(e, methods, actualMethods); + emitConstructors(e, constructorInfo); + } else { + emitDefaultConstructor(e); + } + emitSetThreadCallbacks(e); + emitSetStaticCallbacks(e); + emitBindCallbacks(e); + + if (useFactory || currentData != null) { + int[] keys = getCallbackKeys(); + emitNewInstanceCallbacks(e); + emitNewInstanceCallback(e); + emitNewInstanceMultiarg(e, constructorInfo); + emitGetCallback(e, keys); + emitSetCallback(e, keys); + emitGetCallbacks(e); + emitSetCallbacks(e); + } + + e.end_class(); + } + + /** + * Filter the list of constructors from the superclass. The + * constructors which remain will be included in the generated + * class. The default implementation is to filter out all private + * constructors, but subclasses may extend Enhancer to override this + * behavior. + * @param sc the superclass + * @param constructors the list of all declared constructors from the superclass + * @throws IllegalArgumentException if there are no non-private constructors + */ + protected void filterConstructors(Class sc, List constructors) { + CollectionUtils.filter(constructors, new VisibilityPredicate(sc, true)); + if (constructors.size() == 0) + throw new IllegalArgumentException("No visible constructors in " + sc); + } + + /** + * This method should not be called in regular flow. + * Technically speaking {@link #wrapCachedClass(Class)} uses {@link EnhancerFactoryData} as a cache value, + * and the latter enables faster instantiation than plain old reflection lookup and invoke. + * This method is left intact for backward compatibility reasons: just in case it was ever used. + * + * @param type class to instantiate + * @return newly created proxy instance + * @throws Exception if something goes wrong + */ + protected Object firstInstance(Class type) throws Exception { + if (classOnly) { + return type; + } else { + return createUsingReflection(type); + } + } + + protected Object nextInstance(Object instance) { + EnhancerFactoryData data = (EnhancerFactoryData) instance; + + if (classOnly) { + return data.generatedClass; + } + + Class[] argumentTypes = this.argumentTypes; + Object[] arguments = this.arguments; + if (argumentTypes == null) { + argumentTypes = Constants.EMPTY_CLASS_ARRAY; + arguments = null; + } + return data.newInstance(argumentTypes, arguments, callbacks); + } + + @Override + protected Object wrapCachedClass(Class klass) { + Class[] argumentTypes = this.argumentTypes; + if (argumentTypes == null) { + argumentTypes = Constants.EMPTY_CLASS_ARRAY; + } + EnhancerFactoryData factoryData = new EnhancerFactoryData(klass, argumentTypes, classOnly); + Field factoryDataField = null; + try { + // The subsequent dance is performed just once for each class, + // so it does not matter much how fast it goes + factoryDataField = klass.getField(FACTORY_DATA_FIELD); + factoryDataField.set(null, factoryData); + Field callbackFilterField = klass.getDeclaredField(CALLBACK_FILTER_FIELD); + callbackFilterField.setAccessible(true); + callbackFilterField.set(null, this.filter); + } catch (NoSuchFieldException e) { + throw new CodeGenerationException(e); + } catch (IllegalAccessException e) { + throw new CodeGenerationException(e); + } + return new WeakReference(factoryData); + } + + @Override + protected Object unwrapCachedValue(Object cached) { + if (currentKey instanceof EnhancerKey) { + EnhancerFactoryData data = ((WeakReference) cached).get(); + return data; + } + return super.unwrapCachedValue(cached); + } + + /** + * Call this method to register the {@link Callback} array to use before + * creating a new instance of the generated class via reflection. If you are using + * an instance of Enhancer or the {@link Factory} interface to create + * new instances, this method is unnecessary. Its primary use is for when you want to + * cache and reuse a generated class yourself, and the generated class does + * not implement the {@link Factory} interface. + *

+ * Note that this method only registers the callbacks on the current thread. + * If you want to register callbacks for instances created by multiple threads, + * use {@link #registerStaticCallbacks}. + *

+ * The registered callbacks are overwritten and subsequently cleared + * when calling any of the create methods (such as + * {@link #create}), or any {@link Factory} newInstance method. + * Otherwise they are not cleared, and you should be careful to set them + * back to null after creating new instances via reflection if + * memory leakage is a concern. + * @param generatedClass a class previously created by {@link Enhancer} + * @param callbacks the array of callbacks to use when instances of the generated + * class are created + * @see #setUseFactory + */ + public static void registerCallbacks(Class generatedClass, Callback[] callbacks) { + setThreadCallbacks(generatedClass, callbacks); + } + + /** + * Similar to {@link #registerCallbacks}, but suitable for use + * when multiple threads will be creating instances of the generated class. + * The thread-level callbacks will always override the static callbacks. + * Static callbacks are never cleared. + * @param generatedClass a class previously created by {@link Enhancer} + * @param callbacks the array of callbacks to use when instances of the generated + * class are created + */ + public static void registerStaticCallbacks(Class generatedClass, Callback[] callbacks) { + setCallbacksHelper(generatedClass, callbacks, SET_STATIC_CALLBACKS_NAME); + } + + /** + * Determine if a class was generated using Enhancer. + * @param type any class + * @return whether the class was generated using Enhancer + */ + public static boolean isEnhanced(Class type) { + try { + getCallbacksSetter(type, SET_THREAD_CALLBACKS_NAME); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } + + private static void setThreadCallbacks(Class type, Callback[] callbacks) { + setCallbacksHelper(type, callbacks, SET_THREAD_CALLBACKS_NAME); + } + + private static void setCallbacksHelper(Class type, Callback[] callbacks, String methodName) { + // TODO: optimize + try { + Method setter = getCallbacksSetter(type, methodName); + setter.invoke(null, new Object[]{ callbacks }); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException(type + " is not an enhanced class"); + } catch (IllegalAccessException e) { + throw new CodeGenerationException(e); + } catch (InvocationTargetException e) { + throw new CodeGenerationException(e); + } + } + + private static Method getCallbacksSetter(Class type, String methodName) throws NoSuchMethodException { + return type.getDeclaredMethod(methodName, new Class[]{ Callback[].class }); + } + + /** + * Instantiates a proxy instance and assigns callback values. + * Implementation detail: java.lang.reflect instances are not cached, so this method should not + * be used on a hot path. + * This method is used when {@link #setUseCache(boolean)} is set to {@code false}. + * + * @param type class to instantiate + * @return newly created instance + */ + private Object createUsingReflection(Class type) { + setThreadCallbacks(type, callbacks); + try{ + + if (argumentTypes != null) { + + return ReflectUtils.newInstance(type, argumentTypes, arguments); + + } else { + + return ReflectUtils.newInstance(type); + + } + }finally{ + // clear thread callbacks to allow them to be gc'd + setThreadCallbacks(type, null); + } + } + + /** + * Helper method to create an intercepted object. + * For finer control over the generated instance, use a new instance of Enhancer + * instead of this static method. + * @param type class to extend or interface to implement + * @param callback the callback to use for all methods + */ + public static Object create(Class type, Callback callback) { + Enhancer e = new Enhancer(); + e.setSuperclass(type); + e.setCallback(callback); + return e.create(); + } + + /** + * Helper method to create an intercepted object. + * For finer control over the generated instance, use a new instance of Enhancer + * instead of this static method. + * @param superclass class to extend or interface to implement + * @param interfaces array of interfaces to implement, or null + * @param callback the callback to use for all methods + */ + public static Object create(Class superclass, Class interfaces[], Callback callback) { + Enhancer e = new Enhancer(); + e.setSuperclass(superclass); + e.setInterfaces(interfaces); + e.setCallback(callback); + return e.create(); + } + + /** + * Helper method to create an intercepted object. + * For finer control over the generated instance, use a new instance of Enhancer + * instead of this static method. + * @param superclass class to extend or interface to implement + * @param interfaces array of interfaces to implement, or null + * @param filter the callback filter to use when generating a new class + * @param callbacks callback implementations to use for the enhanced object + */ + public static Object create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) { + Enhancer e = new Enhancer(); + e.setSuperclass(superclass); + e.setInterfaces(interfaces); + e.setCallbackFilter(filter); + e.setCallbacks(callbacks); + return e.create(); + } + + private void emitDefaultConstructor(ClassEmitter ce) { + Constructor declaredConstructor; + try { + declaredConstructor = Object.class.getDeclaredConstructor(); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Object should have default constructor ", e); + } + MethodInfo constructor = (MethodInfo) MethodInfoTransformer.getInstance().transform(declaredConstructor); + CodeEmitter e = EmitUtils.begin_method(ce, constructor, Constants.ACC_PUBLIC); + e.load_this(); + e.dup(); + Signature sig = constructor.getSignature(); + e.super_invoke_constructor(sig); + e.return_value(); + e.end_method(); + } + + private void emitConstructors(ClassEmitter ce, List constructors) { + boolean seenNull = false; + for (Iterator it = constructors.iterator(); it.hasNext();) { + MethodInfo constructor = (MethodInfo)it.next(); + if (currentData != null && !"()V".equals(constructor.getSignature().getDescriptor())) { + continue; + } + CodeEmitter e = EmitUtils.begin_method(ce, constructor, Constants.ACC_PUBLIC); + e.load_this(); + e.dup(); + e.load_args(); + Signature sig = constructor.getSignature(); + seenNull = seenNull || sig.getDescriptor().equals("()V"); + e.super_invoke_constructor(sig); + if (currentData == null) { + e.invoke_static_this(BIND_CALLBACKS); + if (!interceptDuringConstruction) { + e.load_this(); + e.push(1); + e.putfield(CONSTRUCTED_FIELD); + } + } + e.return_value(); + e.end_method(); + } + if (!classOnly && !seenNull && arguments == null) + throw new IllegalArgumentException("Superclass has no null constructors but no arguments were given"); + } + + private int[] getCallbackKeys() { + int[] keys = new int[callbackTypes.length]; + for (int i = 0; i < callbackTypes.length; i++) { + keys[i] = i; + } + return keys; + } + + private void emitGetCallback(ClassEmitter ce, int[] keys) { + final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, GET_CALLBACK, null); + e.load_this(); + e.invoke_static_this(BIND_CALLBACKS); + e.load_this(); + e.load_arg(0); + e.process_switch(keys, new ProcessSwitchCallback() { + public void processCase(int key, Label end) { + e.getfield(getCallbackField(key)); + e.goTo(end); + } + public void processDefault() { + e.pop(); // stack height + e.aconst_null(); + } + }); + e.return_value(); + e.end_method(); + } + + private void emitSetCallback(ClassEmitter ce, int[] keys) { + final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SET_CALLBACK, null); + e.load_arg(0); + e.process_switch(keys, new ProcessSwitchCallback() { + public void processCase(int key, Label end) { + e.load_this(); + e.load_arg(1); + e.checkcast(callbackTypes[key]); + e.putfield(getCallbackField(key)); + e.goTo(end); + } + public void processDefault() { + // TODO: error? + } + }); + e.return_value(); + e.end_method(); + } + + private void emitSetCallbacks(ClassEmitter ce) { + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SET_CALLBACKS, null); + e.load_this(); + e.load_arg(0); + for (int i = 0; i < callbackTypes.length; i++) { + e.dup2(); + e.aaload(i); + e.checkcast(callbackTypes[i]); + e.putfield(getCallbackField(i)); + } + e.return_value(); + e.end_method(); + } + + private void emitGetCallbacks(ClassEmitter ce) { + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, GET_CALLBACKS, null); + e.load_this(); + e.invoke_static_this(BIND_CALLBACKS); + e.load_this(); + e.push(callbackTypes.length); + e.newarray(CALLBACK); + for (int i = 0; i < callbackTypes.length; i++) { + e.dup(); + e.push(i); + e.load_this(); + e.getfield(getCallbackField(i)); + e.aastore(); + } + e.return_value(); + e.end_method(); + } + + private void emitNewInstanceCallbacks(ClassEmitter ce) { + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null); + Type thisType = getThisType(e); + e.load_arg(0); + e.invoke_static(thisType, SET_THREAD_CALLBACKS); + emitCommonNewInstance(e); + } + + private Type getThisType(CodeEmitter e) { + if (currentData == null) { + return e.getClassEmitter().getClassType(); + } else { + return Type.getType(currentData.generatedClass); + } + } + + private void emitCommonNewInstance(CodeEmitter e) { + Type thisType = getThisType(e); + e.new_instance(thisType); + e.dup(); + e.invoke_constructor(thisType); + e.aconst_null(); + e.invoke_static(thisType, SET_THREAD_CALLBACKS); + e.return_value(); + e.end_method(); + } + + private void emitNewInstanceCallback(ClassEmitter ce) { + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SINGLE_NEW_INSTANCE, null); + switch (callbackTypes.length) { + case 0: + // TODO: make sure Callback is null + break; + case 1: + // for now just make a new array; TODO: optimize + e.push(1); + e.newarray(CALLBACK); + e.dup(); + e.push(0); + e.load_arg(0); + e.aastore(); + e.invoke_static(getThisType(e), SET_THREAD_CALLBACKS); + break; + default: + e.throw_exception(ILLEGAL_STATE_EXCEPTION, "More than one callback object required"); + } + emitCommonNewInstance(e); + } + + private void emitNewInstanceMultiarg(ClassEmitter ce, List constructors) { + final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, MULTIARG_NEW_INSTANCE, null); + final Type thisType = getThisType(e); + e.load_arg(2); + e.invoke_static(thisType, SET_THREAD_CALLBACKS); + e.new_instance(thisType); + e.dup(); + e.load_arg(0); + EmitUtils.constructor_switch(e, constructors, new ObjectSwitchCallback() { + public void processCase(Object key, Label end) { + MethodInfo constructor = (MethodInfo)key; + Type types[] = constructor.getSignature().getArgumentTypes(); + for (int i = 0; i < types.length; i++) { + e.load_arg(1); + e.push(i); + e.aaload(); + e.unbox(types[i]); + } + e.invoke_constructor(thisType, constructor.getSignature()); + e.goTo(end); + } + public void processDefault() { + e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Constructor not found"); + } + }); + e.aconst_null(); + e.invoke_static(thisType, SET_THREAD_CALLBACKS); + e.return_value(); + e.end_method(); + } + + private void emitMethods(final ClassEmitter ce, List methods, List actualMethods) { + CallbackGenerator[] generators = CallbackInfo.getGenerators(callbackTypes); + + Map groups = new HashMap(); + final Map indexes = new HashMap(); + final Map originalModifiers = new HashMap(); + final Map positions = CollectionUtils.getIndexMap(methods); + final Map declToBridge = new HashMap(); + + Iterator it1 = methods.iterator(); + Iterator it2 = (actualMethods != null) ? actualMethods.iterator() : null; + + while (it1.hasNext()) { + MethodInfo method = (MethodInfo)it1.next(); + Method actualMethod = (it2 != null) ? (Method)it2.next() : null; + int index = filter.accept(actualMethod); + if (index >= callbackTypes.length) { + throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index); + } + originalModifiers.put(method, new Integer((actualMethod != null) ? actualMethod.getModifiers() : method.getModifiers())); + indexes.put(method, new Integer(index)); + List group = (List)groups.get(generators[index]); + if (group == null) { + groups.put(generators[index], group = new ArrayList(methods.size())); + } + group.add(method); + + // Optimization: build up a map of Class -> bridge methods in class + // so that we can look up all the bridge methods in one pass for a class. + if (TypeUtils.isBridge(actualMethod.getModifiers())) { + Set bridges = (Set)declToBridge.get(actualMethod.getDeclaringClass()); + if (bridges == null) { + bridges = new HashSet(); + declToBridge.put(actualMethod.getDeclaringClass(), bridges); + } + bridges.add(method.getSignature()); + } + } + + final Map bridgeToTarget = new BridgeMethodResolver(declToBridge).resolveAll(); + + Set seenGen = new HashSet(); + CodeEmitter se = ce.getStaticHook(); + se.new_instance(THREAD_LOCAL); + se.dup(); + se.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL); + se.putfield(THREAD_CALLBACKS_FIELD); + + final Object[] state = new Object[1]; + CallbackGenerator.Context context = new CallbackGenerator.Context() { + public ClassLoader getClassLoader() { + return Enhancer.this.getClassLoader(); + } + public int getOriginalModifiers(MethodInfo method) { + return ((Integer)originalModifiers.get(method)).intValue(); + } + public int getIndex(MethodInfo method) { + return ((Integer)indexes.get(method)).intValue(); + } + public void emitCallback(CodeEmitter e, int index) { + emitCurrentCallback(e, index); + } + public Signature getImplSignature(MethodInfo method) { + return rename(method.getSignature(), ((Integer)positions.get(method)).intValue()); + } + public void emitInvoke(CodeEmitter e, MethodInfo method) { + // If this is a bridge and we know the target was called from invokespecial, + // then we need to invoke_virtual w/ the bridge target instead of doing + // a super, because super may itself be using super, which would bypass + // any proxies on the target. + Signature bridgeTarget = (Signature)bridgeToTarget.get(method.getSignature()); + if (bridgeTarget != null) { + // TODO: this assumes that the target has wider or the same type + // parameters than the current. + // In reality this should always be true because otherwise we wouldn't + // have had a bridge doing an invokespecial. + // If it isn't true, we would need to checkcast each argument + // against the target's argument types + e.invoke_virtual_this(bridgeTarget); + + Type retType = method.getSignature().getReturnType(); + // Not necessary to cast if the target & bridge have + // the same return type. + // (This conveniently includes void and primitive types, + // which would fail if casted. It's not possible to + // covariant from boxed to unbox (or vice versa), so no having + // to box/unbox for bridges). + // TODO: It also isn't necessary to checkcast if the return is + // assignable from the target. (This would happen if a subclass + // used covariant returns to narrow the return type within a bridge + // method.) + if (!retType.equals(bridgeTarget.getReturnType())) { + e.checkcast(retType); + } + } else { + e.super_invoke(method.getSignature()); + } + } + public CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method) { + CodeEmitter e = EmitUtils.begin_method(ce, method); + if (!interceptDuringConstruction && + !TypeUtils.isAbstract(method.getModifiers())) { + Label constructed = e.make_label(); + e.load_this(); + e.getfield(CONSTRUCTED_FIELD); + e.if_jump(e.NE, constructed); + e.load_this(); + e.load_args(); + e.super_invoke(); + e.return_value(); + e.mark(constructed); + } + return e; + } + }; + for (int i = 0; i < callbackTypes.length; i++) { + CallbackGenerator gen = generators[i]; + if (!seenGen.contains(gen)) { + seenGen.add(gen); + final List fmethods = (List)groups.get(gen); + if (fmethods != null) { + try { + gen.generate(ce, context, fmethods); + gen.generateStatic(se, context, fmethods); + } catch (RuntimeException x) { + throw x; + } catch (Exception x) { + throw new CodeGenerationException(x); + } + } + } + } + se.return_value(); + se.end_method(); + } + + private void emitSetThreadCallbacks(ClassEmitter ce) { + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC, + SET_THREAD_CALLBACKS, + null); + e.getfield(THREAD_CALLBACKS_FIELD); + e.load_arg(0); + e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET); + e.return_value(); + e.end_method(); + } + + private void emitSetStaticCallbacks(ClassEmitter ce) { + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC, + SET_STATIC_CALLBACKS, + null); + e.load_arg(0); + e.putfield(STATIC_CALLBACKS_FIELD); + e.return_value(); + e.end_method(); + } + + private void emitCurrentCallback(CodeEmitter e, int index) { + e.load_this(); + e.getfield(getCallbackField(index)); + e.dup(); + Label end = e.make_label(); + e.ifnonnull(end); + e.pop(); // stack height + e.load_this(); + e.invoke_static_this(BIND_CALLBACKS); + e.load_this(); + e.getfield(getCallbackField(index)); + e.mark(end); + } + + private void emitBindCallbacks(ClassEmitter ce) { + CodeEmitter e = ce.begin_method(Constants.PRIVATE_FINAL_STATIC, + BIND_CALLBACKS, + null); + Local me = e.make_local(); + e.load_arg(0); + e.checkcast_this(); + e.store_local(me); + + Label end = e.make_label(); + e.load_local(me); + e.getfield(BOUND_FIELD); + e.if_jump(e.NE, end); + e.load_local(me); + e.push(1); + e.putfield(BOUND_FIELD); + + e.getfield(THREAD_CALLBACKS_FIELD); + e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_GET); + e.dup(); + Label found_callback = e.make_label(); + e.ifnonnull(found_callback); + e.pop(); + + e.getfield(STATIC_CALLBACKS_FIELD); + e.dup(); + e.ifnonnull(found_callback); + e.pop(); + e.goTo(end); + + e.mark(found_callback); + e.checkcast(CALLBACK_ARRAY); + e.load_local(me); + e.swap(); + for (int i = callbackTypes.length - 1; i >= 0; i--) { + if (i != 0) { + e.dup2(); + } + e.aaload(i); + e.checkcast(callbackTypes[i]); + e.putfield(getCallbackField(i)); + } + + e.mark(end); + e.return_value(); + e.end_method(); + } + + private static String getCallbackField(int index) { + return "CGLIB$CALLBACK_" + index; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/Factory.java b/blade-aop/src/main/java/net/sf/cglib/proxy/Factory.java new file mode 100644 index 000000000..437f6ae13 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/Factory.java @@ -0,0 +1,79 @@ +/* + * Copyright 2002,2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +/** + * All enhanced instances returned by the {@link Enhancer} class implement this interface. + * Using this interface for new instances is faster than going through the Enhancer + * interface or using reflection. In addition, to intercept methods called during + * object construction you must use these methods instead of reflection. + * @author Juozas Baliuka baliuka@mwm.lt + * @version $Id: Factory.java,v 1.13 2004/06/24 21:15:20 herbyderby Exp $ + */ +public interface Factory { + /** + * Creates new instance of the same type, using the no-arg constructor. + * The class of this object must have been created using a single Callback type. + * If multiple callbacks are required an exception will be thrown. + * @param callback the new interceptor to use + * @return new instance of the same type + */ + Object newInstance(Callback callback); + + /** + * Creates new instance of the same type, using the no-arg constructor. + * @param callbacks the new callbacks(s) to use + * @return new instance of the same type + */ + Object newInstance(Callback[] callbacks); + + /** + * Creates a new instance of the same type, using the constructor + * matching the given signature. + * @param types the constructor argument types + * @param args the constructor arguments + * @param callbacks the new interceptor(s) to use + * @return new instance of the same type + */ + Object newInstance(Class[] types, Object[] args, Callback[] callbacks); + + /** + * Return the Callback implementation at the specified index. + * @param index the callback index + * @return the callback implementation + */ + Callback getCallback(int index); + + /** + * Set the callback for this object for the given type. + * @param index the callback index to replace + * @param callback the new callback + */ + void setCallback(int index, Callback callback); + + /** + * Replace all of the callbacks for this object at once. + * @param callbacks the new callbacks(s) to use + */ + void setCallbacks(Callback[] callbacks); + + /** + * Get the current set of callbacks for ths object. + * @return a new array instance + */ + Callback[] getCallbacks(); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/FixedValue.java b/blade-aop/src/main/java/net/sf/cglib/proxy/FixedValue.java new file mode 100644 index 000000000..06afdba8b --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/FixedValue.java @@ -0,0 +1,35 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +/** + * {@link Enhancer} callback that simply returns the value to return + * from the proxied method. No information about what method + * is being called is available to the callback, and the type of + * the returned object must be compatible with the return type of + * the proxied method. This makes this callback primarily useful + * for forcing a particular method (through the use of a {@link CallbackFilter} + * to return a fixed value with little overhead. + */ +public interface FixedValue extends Callback { + /** + * Return the object which the original method invocation should + * return. This method is called for every method invocation. + * @return an object matching the type of the return value for every + * method this callback is mapped to + */ + Object loadObject() throws Exception; +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/FixedValueGenerator.java b/blade-aop/src/main/java/net/sf/cglib/proxy/FixedValueGenerator.java new file mode 100644 index 000000000..1cd6e92e2 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/FixedValueGenerator.java @@ -0,0 +1,42 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.Type; + +class FixedValueGenerator implements CallbackGenerator { + public static final FixedValueGenerator INSTANCE = new FixedValueGenerator(); + private static final Type FIXED_VALUE = + TypeUtils.parseType("net.sf.cglib.proxy.FixedValue"); + private static final Signature LOAD_OBJECT = + TypeUtils.parseSignature("Object loadObject()"); + + public void generate(ClassEmitter ce, Context context, List methods) { + for (Iterator it = methods.iterator(); it.hasNext();) { + MethodInfo method = (MethodInfo)it.next(); + CodeEmitter e = context.beginMethod(ce, method); + context.emitCallback(e, context.getIndex(method)); + e.invoke_interface(FIXED_VALUE, LOAD_OBJECT); + e.unbox_or_zero(e.getReturnType()); + e.return_value(); + e.end_method(); + } + } + + public void generateStatic(CodeEmitter e, Context context, List methods) { } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/InterfaceMaker.java b/blade-aop/src/main/java/net/sf/cglib/proxy/InterfaceMaker.java new file mode 100644 index 000000000..f4f8b71f2 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/InterfaceMaker.java @@ -0,0 +1,118 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.lang.reflect.*; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; + +/** + * Generates new interfaces at runtime. + * By passing a generated interface to the Enhancer's list of interfaces to + * implement, you can make your enhanced classes handle an arbitrary set + * of method signatures. + * @author Chris Nokleberg + * @version $Id: InterfaceMaker.java,v 1.4 2006/03/05 02:43:19 herbyderby Exp $ + */ +public class InterfaceMaker extends AbstractClassGenerator +{ + private static final Source SOURCE = new Source(InterfaceMaker.class.getName()); + private Map signatures = new HashMap(); + + /** + * Create a new InterfaceMaker. A new InterfaceMaker + * object should be used for each generated interface, and should not + * be shared across threads. + */ + public InterfaceMaker() { + super(SOURCE); + } + + /** + * Add a method signature to the interface. + * @param sig the method signature to add to the interface + * @param exceptions an array of exception types to declare for the method + */ + public void add(Signature sig, Type[] exceptions) { + signatures.put(sig, exceptions); + } + + /** + * Add a method signature to the interface. The method modifiers are ignored, + * since interface methods are by definition abstract and public. + * @param method the method to add to the interface + */ + public void add(Method method) { + add(ReflectUtils.getSignature(method), + ReflectUtils.getExceptionTypes(method)); + } + + /** + * Add all the public methods in the specified class. + * Methods from superclasses are included, except for methods declared in the base + * Object class (e.g. getClass, equals, hashCode). + * @param class the class containing the methods to add to the interface + */ + public void add(Class clazz) { + Method[] methods = clazz.getMethods(); + for (int i = 0; i < methods.length; i++) { + Method m = methods[i]; + if (!m.getDeclaringClass().getName().equals("java.lang.Object")) { + add(m); + } + } + } + + /** + * Create an interface using the current set of method signatures. + */ + public Class create() { + setUseCache(false); + return (Class)super.create(this); + } + + protected ClassLoader getDefaultClassLoader() { + return null; + } + + protected Object firstInstance(Class type) { + return type; + } + + protected Object nextInstance(Object instance) { + throw new IllegalStateException("InterfaceMaker does not cache"); + } + + public void generateClass(ClassVisitor v) throws Exception { + ClassEmitter ce = new ClassEmitter(v); + ce.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC | Constants.ACC_INTERFACE, + getClassName(), + null, + null, + Constants.SOURCE_FILE); + for (Iterator it = signatures.keySet().iterator(); it.hasNext();) { + Signature sig = (Signature)it.next(); + Type[] exceptions = (Type[])signatures.get(sig); + ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT, + sig, + exceptions).end_method(); + } + ce.end_class(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/InvocationHandler.java b/blade-aop/src/main/java/net/sf/cglib/proxy/InvocationHandler.java new file mode 100644 index 000000000..4307a6d19 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/InvocationHandler.java @@ -0,0 +1,35 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.lang.reflect.Method; + +/** + * {@link java.lang.reflect.InvocationHandler} replacement (unavailable under JDK 1.2). + * This callback type is primarily for use by the {@link Proxy} class but + * may be used with {@link Enhancer} as well. + * @author Neeme Praks neeme@apache.org + * @version $Id: InvocationHandler.java,v 1.3 2004/06/24 21:15:20 herbyderby Exp $ + */ +public interface InvocationHandler +extends Callback +{ + /** + * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object) + */ + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; + +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/InvocationHandlerGenerator.java b/blade-aop/src/main/java/net/sf/cglib/proxy/InvocationHandlerGenerator.java new file mode 100644 index 000000000..dcb028fcd --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/InvocationHandlerGenerator.java @@ -0,0 +1,64 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import net.sf.cglib.core.*; +import java.util.*; +import org.objectweb.asm.Type; + +class InvocationHandlerGenerator +implements CallbackGenerator +{ + public static final InvocationHandlerGenerator INSTANCE = new InvocationHandlerGenerator(); + + private static final Type INVOCATION_HANDLER = + TypeUtils.parseType("net.sf.cglib.proxy.InvocationHandler"); + private static final Type UNDECLARED_THROWABLE_EXCEPTION = + TypeUtils.parseType("net.sf.cglib.proxy.UndeclaredThrowableException"); + private static final Type METHOD = + TypeUtils.parseType("java.lang.reflect.Method"); + private static final Signature INVOKE = + TypeUtils.parseSignature("Object invoke(Object, java.lang.reflect.Method, Object[])"); + + public void generate(ClassEmitter ce, Context context, List methods) { + for (Iterator it = methods.iterator(); it.hasNext();) { + MethodInfo method = (MethodInfo)it.next(); + Signature impl = context.getImplSignature(method); + ce.declare_field(Constants.PRIVATE_FINAL_STATIC, impl.getName(), METHOD, null); + + CodeEmitter e = context.beginMethod(ce, method); + Block handler = e.begin_block(); + context.emitCallback(e, context.getIndex(method)); + e.load_this(); + e.getfield(impl.getName()); + e.create_arg_array(); + e.invoke_interface(INVOCATION_HANDLER, INVOKE); + e.unbox(method.getSignature().getReturnType()); + e.return_value(); + handler.end(); + EmitUtils.wrap_undeclared_throwable(e, handler, method.getExceptionTypes(), UNDECLARED_THROWABLE_EXCEPTION); + e.end_method(); + } + } + + public void generateStatic(CodeEmitter e, Context context, List methods) { + for (Iterator it = methods.iterator(); it.hasNext();) { + MethodInfo method = (MethodInfo)it.next(); + EmitUtils.load_method(e, method); + e.putfield(context.getImplSignature(method).getName()); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/LazyLoader.java b/blade-aop/src/main/java/net/sf/cglib/proxy/LazyLoader.java new file mode 100644 index 000000000..874c2a396 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/LazyLoader.java @@ -0,0 +1,30 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +/** + * Lazy-loading {@link Enhancer} callback. + */ +public interface LazyLoader extends Callback { + /** + * Return the object which the original method invocation should be + * dispatched. Called as soon as the first lazily-loaded method in + * the enhanced instance is invoked. The same object is then used + * for every future method call to the proxy instance. + * @return an object that can invoke the method + */ + Object loadObject() throws Exception; +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/LazyLoaderGenerator.java b/blade-aop/src/main/java/net/sf/cglib/proxy/LazyLoaderGenerator.java new file mode 100644 index 000000000..b7f92c1ca --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/LazyLoaderGenerator.java @@ -0,0 +1,88 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +class LazyLoaderGenerator implements CallbackGenerator { + public static final LazyLoaderGenerator INSTANCE = new LazyLoaderGenerator(); + + private static final Signature LOAD_OBJECT = + TypeUtils.parseSignature("Object loadObject()"); + private static final Type LAZY_LOADER = + TypeUtils.parseType("net.sf.cglib.proxy.LazyLoader"); + + public void generate(ClassEmitter ce, Context context, List methods) { + Set indexes = new HashSet(); + for (Iterator it = methods.iterator(); it.hasNext();) { + MethodInfo method = (MethodInfo)it.next(); + if (TypeUtils.isProtected(method.getModifiers())) { + // ignore protected methods + } else { + int index = context.getIndex(method); + indexes.add(new Integer(index)); + CodeEmitter e = context.beginMethod(ce, method); + e.load_this(); + e.dup(); + e.invoke_virtual_this(loadMethod(index)); + e.checkcast(method.getClassInfo().getType()); + e.load_args(); + e.invoke(method); + e.return_value(); + e.end_method(); + } + } + + for (Iterator it = indexes.iterator(); it.hasNext();) { + int index = ((Integer)it.next()).intValue(); + + String delegate = "CGLIB$LAZY_LOADER_" + index; + ce.declare_field(Constants.ACC_PRIVATE, delegate, Constants.TYPE_OBJECT, null); + + CodeEmitter e = ce.begin_method(Constants.ACC_PRIVATE | + Constants.ACC_SYNCHRONIZED | + Constants.ACC_FINAL, + loadMethod(index), + null); + e.load_this(); + e.getfield(delegate); + e.dup(); + Label end = e.make_label(); + e.ifnonnull(end); + e.pop(); + e.load_this(); + context.emitCallback(e, index); + e.invoke_interface(LAZY_LOADER, LOAD_OBJECT); + e.dup_x1(); + e.putfield(delegate); + e.mark(end); + e.return_value(); + e.end_method(); + + } + } + + private Signature loadMethod(int index) { + return new Signature("CGLIB$LOAD_PRIVATE_" + index, + Constants.TYPE_OBJECT, + Constants.TYPES_EMPTY); + } + + public void generateStatic(CodeEmitter e, Context context, List methods) { } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/MethodInterceptor.java b/blade-aop/src/main/java/net/sf/cglib/proxy/MethodInterceptor.java new file mode 100644 index 000000000..c0a24429d --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/MethodInterceptor.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002,2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +/** + * General-purpose {@link Enhancer} callback which provides for "around advice". + * @author Juozas Baliuka baliuka@mwm.lt + * @version $Id: MethodInterceptor.java,v 1.8 2004/06/24 21:15:20 herbyderby Exp $ + */ +public interface MethodInterceptor +extends Callback +{ + /** + * All generated proxied methods call this method instead of the original method. + * The original method may either be invoked by normal reflection using the Method object, + * or by using the MethodProxy (faster). + * @param obj "this", the enhanced object + * @param method intercepted Method + * @param args argument array; primitive types are wrapped + * @param proxy used to invoke super (non-intercepted method); may be called + * as many times as needed + * @throws Throwable any exception may be thrown; if so, super method will not be invoked + * @return any value compatible with the signature of the proxied method. Method returning void will ignore this value. + * @see MethodProxy + */ + public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, + MethodProxy proxy) throws Throwable; + +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/MethodInterceptorGenerator.java b/blade-aop/src/main/java/net/sf/cglib/proxy/MethodInterceptorGenerator.java new file mode 100644 index 000000000..b0e00a9da --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/MethodInterceptorGenerator.java @@ -0,0 +1,239 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.lang.reflect.Method; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +class MethodInterceptorGenerator +implements CallbackGenerator +{ + public static final MethodInterceptorGenerator INSTANCE = new MethodInterceptorGenerator(); + + static final String EMPTY_ARGS_NAME = "CGLIB$emptyArgs"; + static final String FIND_PROXY_NAME = "CGLIB$findMethodProxy"; + static final Class[] FIND_PROXY_TYPES = { Signature.class }; + + private static final Type ABSTRACT_METHOD_ERROR = + TypeUtils.parseType("AbstractMethodError"); + private static final Type METHOD = + TypeUtils.parseType("java.lang.reflect.Method"); + private static final Type REFLECT_UTILS = + TypeUtils.parseType("net.sf.cglib.core.ReflectUtils"); + private static final Type METHOD_PROXY = + TypeUtils.parseType("net.sf.cglib.proxy.MethodProxy"); + private static final Type METHOD_INTERCEPTOR = + TypeUtils.parseType("net.sf.cglib.proxy.MethodInterceptor"); + private static final Signature GET_DECLARED_METHODS = + TypeUtils.parseSignature("java.lang.reflect.Method[] getDeclaredMethods()"); + private static final Signature GET_DECLARING_CLASS = + TypeUtils.parseSignature("Class getDeclaringClass()"); + private static final Signature FIND_METHODS = + TypeUtils.parseSignature("java.lang.reflect.Method[] findMethods(String[], java.lang.reflect.Method[])"); + private static final Signature MAKE_PROXY = + new Signature("create", METHOD_PROXY, new Type[]{ + Constants.TYPE_CLASS, + Constants.TYPE_CLASS, + Constants.TYPE_STRING, + Constants.TYPE_STRING, + Constants.TYPE_STRING + }); + private static final Signature INTERCEPT = + new Signature("intercept", Constants.TYPE_OBJECT, new Type[]{ + Constants.TYPE_OBJECT, + METHOD, + Constants.TYPE_OBJECT_ARRAY, + METHOD_PROXY + }); + private static final Signature FIND_PROXY = + new Signature(FIND_PROXY_NAME, METHOD_PROXY, new Type[]{ Constants.TYPE_SIGNATURE }); + private static final Signature TO_STRING = + TypeUtils.parseSignature("String toString()"); + private static final Transformer METHOD_TO_CLASS = new Transformer(){ + public Object transform(Object value) { + return ((MethodInfo)value).getClassInfo(); + } + }; + private static final Signature CSTRUCT_SIGNATURE = + TypeUtils.parseConstructor("String, String"); + + private String getMethodField(Signature impl) { + return impl.getName() + "$Method"; + } + private String getMethodProxyField(Signature impl) { + return impl.getName() + "$Proxy"; + } + + public void generate(ClassEmitter ce, Context context, List methods) { + Map sigMap = new HashMap(); + for (Iterator it = methods.iterator(); it.hasNext();) { + MethodInfo method = (MethodInfo)it.next(); + Signature sig = method.getSignature(); + Signature impl = context.getImplSignature(method); + + String methodField = getMethodField(impl); + String methodProxyField = getMethodProxyField(impl); + + sigMap.put(sig.toString(), methodProxyField); + ce.declare_field(Constants.PRIVATE_FINAL_STATIC, methodField, METHOD, null); + ce.declare_field(Constants.PRIVATE_FINAL_STATIC, methodProxyField, METHOD_PROXY, null); + ce.declare_field(Constants.PRIVATE_FINAL_STATIC, EMPTY_ARGS_NAME, Constants.TYPE_OBJECT_ARRAY, null); + CodeEmitter e; + + // access method + e = ce.begin_method(Constants.ACC_FINAL, + impl, + method.getExceptionTypes()); + superHelper(e, method, context); + e.return_value(); + e.end_method(); + + // around method + e = context.beginMethod(ce, method); + Label nullInterceptor = e.make_label(); + context.emitCallback(e, context.getIndex(method)); + e.dup(); + e.ifnull(nullInterceptor); + + e.load_this(); + e.getfield(methodField); + + if (sig.getArgumentTypes().length == 0) { + e.getfield(EMPTY_ARGS_NAME); + } else { + e.create_arg_array(); + } + + e.getfield(methodProxyField); + e.invoke_interface(METHOD_INTERCEPTOR, INTERCEPT); + e.unbox_or_zero(sig.getReturnType()); + e.return_value(); + + e.mark(nullInterceptor); + superHelper(e, method, context); + e.return_value(); + e.end_method(); + } + generateFindProxy(ce, sigMap); + } + + private static void superHelper(CodeEmitter e, MethodInfo method, Context context) + { + if (TypeUtils.isAbstract(method.getModifiers())) { + e.throw_exception(ABSTRACT_METHOD_ERROR, method.toString() + " is abstract" ); + } else { + e.load_this(); + e.load_args(); + context.emitInvoke(e, method); + } + } + + public void generateStatic(CodeEmitter e, Context context, List methods) throws Exception { + /* generates: + static { + Class thisClass = Class.forName("NameOfThisClass"); + Class cls = Class.forName("java.lang.Object"); + String[] sigs = new String[]{ "toString", "()Ljava/lang/String;", ... }; + Method[] methods = cls.getDeclaredMethods(); + methods = ReflectUtils.findMethods(sigs, methods); + METHOD_0 = methods[0]; + CGLIB$ACCESS_0 = MethodProxy.create(cls, thisClass, "()Ljava/lang/String;", "toString", "CGLIB$ACCESS_0"); + ... + } + */ + + e.push(0); + e.newarray(); + e.putfield(EMPTY_ARGS_NAME); + + Local thisclass = e.make_local(); + Local declaringclass = e.make_local(); + EmitUtils.load_class_this(e); + e.store_local(thisclass); + + Map methodsByClass = CollectionUtils.bucket(methods, METHOD_TO_CLASS); + for (Iterator i = methodsByClass.keySet().iterator(); i.hasNext();) { + ClassInfo classInfo = (ClassInfo)i.next(); + + List classMethods = (List)methodsByClass.get(classInfo); + e.push(2 * classMethods.size()); + e.newarray(Constants.TYPE_STRING); + for (int index = 0; index < classMethods.size(); index++) { + MethodInfo method = (MethodInfo)classMethods.get(index); + Signature sig = method.getSignature(); + e.dup(); + e.push(2 * index); + e.push(sig.getName()); + e.aastore(); + e.dup(); + e.push(2 * index + 1); + e.push(sig.getDescriptor()); + e.aastore(); + } + + EmitUtils.load_class(e, classInfo.getType()); + e.dup(); + e.store_local(declaringclass); + e.invoke_virtual(Constants.TYPE_CLASS, GET_DECLARED_METHODS); + e.invoke_static(REFLECT_UTILS, FIND_METHODS); + + for (int index = 0; index < classMethods.size(); index++) { + MethodInfo method = (MethodInfo)classMethods.get(index); + Signature sig = method.getSignature(); + Signature impl = context.getImplSignature(method); + e.dup(); + e.push(index); + e.array_load(METHOD); + e.putfield(getMethodField(impl)); + + e.load_local(declaringclass); + e.load_local(thisclass); + e.push(sig.getDescriptor()); + e.push(sig.getName()); + e.push(impl.getName()); + e.invoke_static(METHOD_PROXY, MAKE_PROXY); + e.putfield(getMethodProxyField(impl)); + } + e.pop(); + } + } + + public void generateFindProxy(ClassEmitter ce, final Map sigMap) { + final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC, + FIND_PROXY, + null); + e.load_arg(0); + e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING); + ObjectSwitchCallback callback = new ObjectSwitchCallback() { + public void processCase(Object key, Label end) { + e.getfield((String)sigMap.get(key)); + e.return_value(); + } + public void processDefault() { + e.aconst_null(); + e.return_value(); + } + }; + EmitUtils.string_switch(e, + (String[])sigMap.keySet().toArray(new String[0]), + Constants.SWITCH_STYLE_HASH, + callback); + e.end_method(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/MethodProxy.java b/blade-aop/src/main/java/net/sf/cglib/proxy/MethodProxy.java new file mode 100644 index 000000000..c8bc95f9a --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/MethodProxy.java @@ -0,0 +1,233 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import net.sf.cglib.core.AbstractClassGenerator; +import net.sf.cglib.core.CodeGenerationException; +import net.sf.cglib.core.GeneratorStrategy; +import net.sf.cglib.core.NamingPolicy; +import net.sf.cglib.core.Signature; +import net.sf.cglib.reflect.FastClass; + +/** + * Classes generated by {@link Enhancer} pass this object to the + * registered {@link MethodInterceptor} objects when an intercepted method is invoked. It can + * be used to either invoke the original method, or call the same method on a different + * object of the same type. + * @version $Id: MethodProxy.java,v 1.16 2009/01/11 20:09:48 herbyderby Exp $ + */ +public class MethodProxy { + private Signature sig1; + private Signature sig2; + private CreateInfo createInfo; + + private final Object initLock = new Object(); + private volatile FastClassInfo fastClassInfo; + + /** + * For internal use by {@link Enhancer} only; see the {@link net.sf.cglib.reflect.FastMethod} class + * for similar functionality. + */ + public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) { + MethodProxy proxy = new MethodProxy(); + proxy.sig1 = new Signature(name1, desc); + proxy.sig2 = new Signature(name2, desc); + proxy.createInfo = new CreateInfo(c1, c2); + return proxy; + } + + private void init() + { + /* + * Using a volatile invariant allows us to initialize the FastClass and + * method index pairs atomically. + * + * Double-checked locking is safe with volatile in Java 5. Before 1.5 this + * code could allow fastClassInfo to be instantiated more than once, which + * appears to be benign. + */ + if (fastClassInfo == null) + { + synchronized (initLock) + { + if (fastClassInfo == null) + { + CreateInfo ci = createInfo; + + FastClassInfo fci = new FastClassInfo(); + fci.f1 = helper(ci, ci.c1); + fci.f2 = helper(ci, ci.c2); + fci.i1 = fci.f1.getIndex(sig1); + fci.i2 = fci.f2.getIndex(sig2); + fastClassInfo = fci; + createInfo = null; + } + } + } + } + + private static class FastClassInfo + { + FastClass f1; + FastClass f2; + int i1; + int i2; + } + + private static class CreateInfo + { + Class c1; + Class c2; + NamingPolicy namingPolicy; + GeneratorStrategy strategy; + boolean attemptLoad; + + public CreateInfo(Class c1, Class c2) + { + this.c1 = c1; + this.c2 = c2; + AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent(); + if (fromEnhancer != null) { + namingPolicy = fromEnhancer.getNamingPolicy(); + strategy = fromEnhancer.getStrategy(); + attemptLoad = fromEnhancer.getAttemptLoad(); + } + } + } + + private static FastClass helper(CreateInfo ci, Class type) { + FastClass.Generator g = new FastClass.Generator(); + g.setType(type); + g.setClassLoader(ci.c2.getClassLoader()); + g.setNamingPolicy(ci.namingPolicy); + g.setStrategy(ci.strategy); + g.setAttemptLoad(ci.attemptLoad); + return g.create(); + } + + private MethodProxy() { + } + + /** + * Return the signature of the proxied method. + */ + public Signature getSignature() { + return sig1; + } + + /** + * Return the name of the synthetic method created by CGLIB which is + * used by {@link #invokeSuper} to invoke the superclass + * (non-intercepted) method implementation. The parameter types are + * the same as the proxied method. + */ + public String getSuperName() { + return sig2.getName(); + } + + /** + * Return the {@link net.sf.cglib.reflect.FastClass} method index + * for the method used by {@link #invokeSuper}. This index uniquely + * identifies the method within the generated proxy, and therefore + * can be useful to reference external metadata. + * @see #getSuperName + */ + public int getSuperIndex() { + init(); + return fastClassInfo.i2; + } + + // For testing + FastClass getFastClass() { + init(); + return fastClassInfo.f1; + } + + // For testing + FastClass getSuperFastClass() { + init(); + return fastClassInfo.f2; + } + + /** + * Return the MethodProxy used when intercepting the method + * matching the given signature. + * @param type the class generated by Enhancer + * @param sig the signature to match + * @return the MethodProxy instance, or null if no applicable matching method is found + * @throws IllegalArgumentException if the Class was not created by Enhancer or does not use a MethodInterceptor + */ + public static MethodProxy find(Class type, Signature sig) { + try { + Method m = type.getDeclaredMethod(MethodInterceptorGenerator.FIND_PROXY_NAME, + MethodInterceptorGenerator.FIND_PROXY_TYPES); + return (MethodProxy)m.invoke(null, new Object[]{ sig }); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("Class " + type + " does not use a MethodInterceptor"); + } catch (IllegalAccessException e) { + throw new CodeGenerationException(e); + } catch (InvocationTargetException e) { + throw new CodeGenerationException(e); + } + } + + /** + * Invoke the original method, on a different object of the same type. + * @param obj the compatible object; recursion will result if you use the object passed as the first + * argument to the MethodInterceptor (usually not what you want) + * @param args the arguments passed to the intercepted method; you may substitute a different + * argument array as long as the types are compatible + * @see MethodInterceptor#intercept + * @throws Throwable the bare exceptions thrown by the called method are passed through + * without wrapping in an InvocationTargetException + */ + public Object invoke(Object obj, Object[] args) throws Throwable { + try { + init(); + FastClassInfo fci = fastClassInfo; + return fci.f1.invoke(fci.i1, obj, args); + } catch (InvocationTargetException e) { + throw e.getTargetException(); + } catch (IllegalArgumentException e) { + if (fastClassInfo.i1 < 0) + throw new IllegalArgumentException("Protected method: " + sig1); + throw e; + } + } + + /** + * Invoke the original (super) method on the specified object. + * @param obj the enhanced object, must be the object passed as the first + * argument to the MethodInterceptor + * @param args the arguments passed to the intercepted method; you may substitute a different + * argument array as long as the types are compatible + * @see MethodInterceptor#intercept + * @throws Throwable the bare exceptions thrown by the called method are passed through + * without wrapping in an InvocationTargetException + */ + public Object invokeSuper(Object obj, Object[] args) throws Throwable { + try { + init(); + FastClassInfo fci = fastClassInfo; + return fci.f2.invoke(fci.i2, obj, args); + } catch (InvocationTargetException e) { + throw e.getTargetException(); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/Mixin.java b/blade-aop/src/main/java/net/sf/cglib/proxy/Mixin.java new file mode 100644 index 000000000..821bbc47d --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/Mixin.java @@ -0,0 +1,242 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.security.ProtectionDomain; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; + + + +/** + * Mixin allows + * multiple objects to be combined into a single larger object. The + * methods in the generated object simply call the original methods in the + * underlying "delegate" objects. + * @author Chris Nokleberg + * @version $Id: Mixin.java,v 1.7 2005/09/27 11:42:27 baliuka Exp $ + */ +abstract public class Mixin { + private static final MixinKey KEY_FACTORY = + (MixinKey)KeyFactory.create(MixinKey.class, KeyFactory.CLASS_BY_NAME); + private static final Map ROUTE_CACHE = Collections.synchronizedMap(new HashMap()); + + public static final int STYLE_INTERFACES = 0; + public static final int STYLE_BEANS = 1; + public static final int STYLE_EVERYTHING = 2; + + interface MixinKey { + public Object newInstance(int style, String[] classes, int[] route); + } + + abstract public Mixin newInstance(Object[] delegates); + + /** + * Helper method to create an interface mixin. For finer control over the + * generated instance, use a new instance of Mixin + * instead of this static method. + * TODO + */ + public static Mixin create(Object[] delegates) { + Generator gen = new Generator(); + gen.setDelegates(delegates); + return gen.create(); + } + + /** + * Helper method to create an interface mixin. For finer control over the + * generated instance, use a new instance of Mixin + * instead of this static method. + * TODO + */ + public static Mixin create(Class[] interfaces, Object[] delegates) { + Generator gen = new Generator(); + gen.setClasses(interfaces); + gen.setDelegates(delegates); + return gen.create(); + } + + + public static Mixin createBean(Object[] beans) { + + return createBean(null, beans); + + } + /** + * Helper method to create a bean mixin. For finer control over the + * generated instance, use a new instance of Mixin + * instead of this static method. + * TODO + */ + public static Mixin createBean(ClassLoader loader,Object[] beans) { + Generator gen = new Generator(); + gen.setStyle(STYLE_BEANS); + gen.setDelegates(beans); + gen.setClassLoader(loader); + return gen.create(); + } + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(Mixin.class.getName()); + + private Class[] classes; + private Object[] delegates; + private int style = STYLE_INTERFACES; + + private int[] route; + + public Generator() { + super(SOURCE); + } + + protected ClassLoader getDefaultClassLoader() { + return classes[0].getClassLoader(); // is this right? + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(classes[0]); + } + + public void setStyle(int style) { + switch (style) { + case STYLE_INTERFACES: + case STYLE_BEANS: + case STYLE_EVERYTHING: + this.style = style; + break; + default: + throw new IllegalArgumentException("Unknown mixin style: " + style); + } + } + + public void setClasses(Class[] classes) { + this.classes = classes; + } + + public void setDelegates(Object[] delegates) { + this.delegates = delegates; + } + + public Mixin create() { + if (classes == null && delegates == null) { + throw new IllegalStateException("Either classes or delegates must be set"); + } + switch (style) { + case STYLE_INTERFACES: + if (classes == null) { + Route r = route(delegates); + classes = r.classes; + route = r.route; + } + break; + case STYLE_BEANS: + // fall-through + case STYLE_EVERYTHING: + if (classes == null) { + classes = ReflectUtils.getClasses(delegates); + } else { + if (delegates != null) { + Class[] temp = ReflectUtils.getClasses(delegates); + if (classes.length != temp.length) { + throw new IllegalStateException("Specified classes are incompatible with delegates"); + } + for (int i = 0; i < classes.length; i++) { + if (!classes[i].isAssignableFrom(temp[i])) { + throw new IllegalStateException("Specified class " + classes[i] + " is incompatible with delegate class " + temp[i] + " (index " + i + ")"); + } + } + } + } + } + setNamePrefix(classes[ReflectUtils.findPackageProtected(classes)].getName()); + + return (Mixin)super.create(KEY_FACTORY.newInstance(style, ReflectUtils.getNames( classes ), route)); + } + + public void generateClass(ClassVisitor v) { + switch (style) { + case STYLE_INTERFACES: + new MixinEmitter(v, getClassName(), classes, route); + break; + case STYLE_BEANS: + new MixinBeanEmitter(v, getClassName(), classes); + break; + case STYLE_EVERYTHING: + new MixinEverythingEmitter(v, getClassName(), classes); + break; + } + } + + protected Object firstInstance(Class type) { + return ((Mixin)ReflectUtils.newInstance(type)).newInstance(delegates); + } + + protected Object nextInstance(Object instance) { + return ((Mixin)instance).newInstance(delegates); + } + } + + public static Class[] getClasses(Object[] delegates) { + return (Class[])route(delegates).classes.clone(); + } + +// public static int[] getRoute(Object[] delegates) { +// return (int[])route(delegates).route.clone(); +// } + + private static Route route(Object[] delegates) { + Object key = ClassesKey.create(delegates); + Route route = (Route)ROUTE_CACHE.get(key); + if (route == null) { + ROUTE_CACHE.put(key, route = new Route(delegates)); + } + return route; + } + + private static class Route + { + private Class[] classes; + private int[] route; + + Route(Object[] delegates) { + Map map = new HashMap(); + ArrayList collect = new ArrayList(); + for (int i = 0; i < delegates.length; i++) { + Class delegate = delegates[i].getClass(); + collect.clear(); + ReflectUtils.addAllInterfaces(delegate, collect); + for (Iterator it = collect.iterator(); it.hasNext();) { + Class iface = (Class)it.next(); + if (!map.containsKey(iface)) { + map.put(iface, new Integer(i)); + } + } + } + classes = new Class[map.size()]; + route = new int[map.size()]; + int index = 0; + for (Iterator it = map.keySet().iterator(); it.hasNext();) { + Class key = (Class)it.next(); + classes[index] = key; + route[index] = ((Integer)map.get(key)).intValue(); + index++; + } + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/MixinBeanEmitter.java b/blade-aop/src/main/java/net/sf/cglib/proxy/MixinBeanEmitter.java new file mode 100644 index 000000000..c48cc9209 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/MixinBeanEmitter.java @@ -0,0 +1,38 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.lang.reflect.Method; +import net.sf.cglib.core.ReflectUtils; +import org.objectweb.asm.ClassVisitor; + +/** + * @author Chris Nokleberg + * @version $Id: MixinBeanEmitter.java,v 1.2 2004/06/24 21:15:20 herbyderby Exp $ + */ +class MixinBeanEmitter extends MixinEmitter { + public MixinBeanEmitter(ClassVisitor v, String className, Class[] classes) { + super(v, className, classes, null); + } + + protected Class[] getInterfaces(Class[] classes) { + return null; + } + + protected Method[] getMethods(Class type) { + return ReflectUtils.getPropertyMethods(ReflectUtils.getBeanProperties(type), true, true); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/MixinEmitter.java b/blade-aop/src/main/java/net/sf/cglib/proxy/MixinEmitter.java new file mode 100644 index 000000000..b5cfc6d97 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/MixinEmitter.java @@ -0,0 +1,93 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.lang.reflect.Method; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; + +/** + * @author Chris Nokleberg + * @version $Id: MixinEmitter.java,v 1.9 2006/08/27 21:04:37 herbyderby Exp $ + */ +class MixinEmitter extends ClassEmitter { + private static final String FIELD_NAME = "CGLIB$DELEGATES"; + private static final Signature CSTRUCT_OBJECT_ARRAY = + TypeUtils.parseConstructor("Object[]"); + private static final Type MIXIN = + TypeUtils.parseType("net.sf.cglib.proxy.Mixin"); + private static final Signature NEW_INSTANCE = + new Signature("newInstance", MIXIN, new Type[]{ Constants.TYPE_OBJECT_ARRAY }); + + public MixinEmitter(ClassVisitor v, String className, Class[] classes, int[] route) { + super(v); + + begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + className, + MIXIN, + TypeUtils.getTypes(getInterfaces(classes)), + Constants.SOURCE_FILE); + EmitUtils.null_constructor(this); + EmitUtils.factory_method(this, NEW_INSTANCE); + + declare_field(Constants.ACC_PRIVATE, FIELD_NAME, Constants.TYPE_OBJECT_ARRAY, null); + + CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null); + e.load_this(); + e.super_invoke_constructor(); + e.load_this(); + e.load_arg(0); + e.putfield(FIELD_NAME); + e.return_value(); + e.end_method(); + + Set unique = new HashSet(); + for (int i = 0; i < classes.length; i++) { + Method[] methods = getMethods(classes[i]); + for (int j = 0; j < methods.length; j++) { + if (unique.add(MethodWrapper.create(methods[j]))) { + MethodInfo method = ReflectUtils.getMethodInfo(methods[j]); + int modifiers = Constants.ACC_PUBLIC; + if ((method.getModifiers() & Constants.ACC_VARARGS) == Constants.ACC_VARARGS) { + modifiers |= Constants.ACC_VARARGS; + } + e = EmitUtils.begin_method(this, method, modifiers); + e.load_this(); + e.getfield(FIELD_NAME); + e.aaload((route != null) ? route[i] : i); + e.checkcast(method.getClassInfo().getType()); + e.load_args(); + e.invoke(method); + e.return_value(); + e.end_method(); + } + } + } + + end_class(); + } + + protected Class[] getInterfaces(Class[] classes) { + return classes; + } + + protected Method[] getMethods(Class type) { + return type.getMethods(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/MixinEverythingEmitter.java b/blade-aop/src/main/java/net/sf/cglib/proxy/MixinEverythingEmitter.java new file mode 100644 index 000000000..ffb45700b --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/MixinEverythingEmitter.java @@ -0,0 +1,49 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; +import net.sf.cglib.core.CollectionUtils; +import net.sf.cglib.core.ReflectUtils; +import net.sf.cglib.core.RejectModifierPredicate; +import org.objectweb.asm.ClassVisitor; + +/** + * @author Chris Nokleberg + * @version $Id: MixinEverythingEmitter.java,v 1.3 2004/06/24 21:15:19 herbyderby Exp $ + */ +class MixinEverythingEmitter extends MixinEmitter { + + public MixinEverythingEmitter(ClassVisitor v, String className, Class[] classes) { + super(v, className, classes, null); + } + + protected Class[] getInterfaces(Class[] classes) { + List list = new ArrayList(); + for (int i = 0; i < classes.length; i++) { + ReflectUtils.addAllInterfaces(classes[i], list); + } + return (Class[])list.toArray(new Class[list.size()]); + } + + protected Method[] getMethods(Class type) { + List methods = new ArrayList(Arrays.asList(type.getMethods())); + CollectionUtils.filter(methods, new RejectModifierPredicate(Modifier.FINAL | Modifier.STATIC)); + return (Method[])methods.toArray(new Method[methods.size()]); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/NoOp.java b/blade-aop/src/main/java/net/sf/cglib/proxy/NoOp.java new file mode 100644 index 000000000..227617590 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/NoOp.java @@ -0,0 +1,28 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +/** + * Methods using this {@link Enhancer} callback will delegate directly to the + * default (super) implementation in the base class. + */ +public interface NoOp extends Callback +{ + /** + * A thread-safe singleton instance of the NoOp callback. + */ + public static final NoOp INSTANCE = new NoOp() { }; +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/NoOpGenerator.java b/blade-aop/src/main/java/net/sf/cglib/proxy/NoOpGenerator.java new file mode 100644 index 000000000..84920be6b --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/NoOpGenerator.java @@ -0,0 +1,44 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.util.Iterator; +import java.util.List; +import net.sf.cglib.core.*; + +class NoOpGenerator +implements CallbackGenerator +{ + public static final NoOpGenerator INSTANCE = new NoOpGenerator(); + + public void generate(ClassEmitter ce, Context context, List methods) { + for (Iterator it = methods.iterator(); it.hasNext();) { + MethodInfo method = (MethodInfo)it.next(); + if (TypeUtils.isBridge(method.getModifiers()) || ( + TypeUtils.isProtected(context.getOriginalModifiers(method)) && + TypeUtils.isPublic(method.getModifiers()))) { + CodeEmitter e = EmitUtils.begin_method(ce, method); + e.load_this(); + e.load_args(); + context.emitInvoke(e, method); + e.return_value(); + e.end_method(); + } + } + } + + public void generateStatic(CodeEmitter e, Context context, List methods) { } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/Proxy.java b/blade-aop/src/main/java/net/sf/cglib/proxy/Proxy.java new file mode 100644 index 000000000..fe5f4f93e --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/Proxy.java @@ -0,0 +1,101 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.lang.reflect.Member; +import net.sf.cglib.core.CodeGenerationException; + +/** + * This class is meant to be used as replacement for + * java.lang.reflect.Proxy under JDK 1.2. There are some known + * subtle differences: + *
    + *
  • The exceptions returned by invoking getExceptionTypes + * on the Method passed to the invoke method + * are the exact set that can be thrown without resulting in an + * UndeclaredThrowableException being thrown. + *
  • {@link UndeclaredThrowableException} is used instead + * of java.lang.reflect.UndeclaredThrowableException. + *
+ *

+ * @version $Id: Proxy.java,v 1.6 2004/06/24 21:15:19 herbyderby Exp $ + */ +public class Proxy implements Serializable { + protected InvocationHandler h; + + private static final CallbackFilter BAD_OBJECT_METHOD_FILTER = new CallbackFilter() { + public int accept(Method method) { + if (method.getDeclaringClass().getName().equals("java.lang.Object")) { + String name = method.getName(); + if (!(name.equals("hashCode") || + name.equals("equals") || + name.equals("toString"))) { + return 1; + } + } + return 0; + } + }; + + protected Proxy(InvocationHandler h) { + Enhancer.registerCallbacks(getClass(), new Callback[]{ h, null }); + this.h = h; + } + + // private for security of isProxyClass + private static class ProxyImpl extends Proxy { + protected ProxyImpl(InvocationHandler h) { + super(h); + } + } + + public static InvocationHandler getInvocationHandler(Object proxy) { + if (!(proxy instanceof ProxyImpl)) { + throw new IllegalArgumentException("Object is not a proxy"); + } + return ((Proxy)proxy).h; + } + + public static Class getProxyClass(ClassLoader loader, Class[] interfaces) { + Enhancer e = new Enhancer(); + e.setSuperclass(ProxyImpl.class); + e.setInterfaces(interfaces); + e.setCallbackTypes(new Class[]{ + InvocationHandler.class, + NoOp.class, + }); + e.setCallbackFilter(BAD_OBJECT_METHOD_FILTER); + e.setUseFactory(false); + return e.createClass(); + } + + public static boolean isProxyClass(Class cl) { + return cl.getSuperclass().equals(ProxyImpl.class); + } + + public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) { + try { + Class clazz = getProxyClass(loader, interfaces); + return clazz.getConstructor(new Class[]{ InvocationHandler.class }).newInstance(new Object[]{ h }); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new CodeGenerationException(e); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/ProxyRefDispatcher.java b/blade-aop/src/main/java/net/sf/cglib/proxy/ProxyRefDispatcher.java new file mode 100644 index 000000000..701088590 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/ProxyRefDispatcher.java @@ -0,0 +1,31 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +/** + * Dispatching {@link Enhancer} callback. This is the same as the + * {@link Dispatcher} except for the addition of an argument + * which references the proxy object. + */ +public interface ProxyRefDispatcher extends Callback { + /** + * Return the object which the original method invocation should + * be dispatched. This method is called for every method invocation. + * @param proxy a reference to the proxy (generated) object + * @return an object that can invoke the method + */ + Object loadObject(Object proxy) throws Exception; +} diff --git a/blade-aop/src/main/java/net/sf/cglib/proxy/UndeclaredThrowableException.java b/blade-aop/src/main/java/net/sf/cglib/proxy/UndeclaredThrowableException.java new file mode 100644 index 000000000..09f8db5a1 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/proxy/UndeclaredThrowableException.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002,2003 The Apache Software Foundation + * + * 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 net.sf.cglib.proxy; + +import net.sf.cglib.core.CodeGenerationException; + +/** + * Used by {@link Proxy} as a replacement for java.lang.reflect.UndeclaredThrowableException. + * @author Juozas Baliuka + */ +public class UndeclaredThrowableException extends CodeGenerationException { + /** + * Creates a new instance of UndeclaredThrowableException without detail message. + */ + public UndeclaredThrowableException(Throwable t) { + super(t); + } + + public Throwable getUndeclaredThrowable() { + return getCause(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/reflect/ConstructorDelegate.java b/blade-aop/src/main/java/net/sf/cglib/reflect/ConstructorDelegate.java new file mode 100644 index 000000000..ae302c6a7 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/reflect/ConstructorDelegate.java @@ -0,0 +1,123 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.reflect; + +import java.lang.reflect.*; +import java.security.ProtectionDomain; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; + +/** + * @author Chris Nokleberg + * @version $Id: ConstructorDelegate.java,v 1.20 2006/03/05 02:43:19 herbyderby Exp $ + */ +abstract public class ConstructorDelegate { + private static final ConstructorKey KEY_FACTORY = + (ConstructorKey)KeyFactory.create(ConstructorKey.class, KeyFactory.CLASS_BY_NAME); + + interface ConstructorKey { + public Object newInstance(String declaring, String iface); + } + + protected ConstructorDelegate() { + } + + public static ConstructorDelegate create(Class targetClass, Class iface) { + Generator gen = new Generator(); + gen.setTargetClass(targetClass); + gen.setInterface(iface); + return gen.create(); + } + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(ConstructorDelegate.class.getName()); + private static final Type CONSTRUCTOR_DELEGATE = + TypeUtils.parseType("net.sf.cglib.reflect.ConstructorDelegate"); + + private Class iface; + private Class targetClass; + + public Generator() { + super(SOURCE); + } + + public void setInterface(Class iface) { + this.iface = iface; + } + + public void setTargetClass(Class targetClass) { + this.targetClass = targetClass; + } + + public ConstructorDelegate create() { + setNamePrefix(targetClass.getName()); + Object key = KEY_FACTORY.newInstance(iface.getName(), targetClass.getName()); + return (ConstructorDelegate)super.create(key); + } + + protected ClassLoader getDefaultClassLoader() { + return targetClass.getClassLoader(); + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(targetClass); + } + + public void generateClass(ClassVisitor v) { + setNamePrefix(targetClass.getName()); + + final Method newInstance = ReflectUtils.findNewInstance(iface); + if (!newInstance.getReturnType().isAssignableFrom(targetClass)) { + throw new IllegalArgumentException("incompatible return type"); + } + final Constructor constructor; + try { + constructor = targetClass.getDeclaredConstructor(newInstance.getParameterTypes()); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("interface does not match any known constructor"); + } + + ClassEmitter ce = new ClassEmitter(v); + ce.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + getClassName(), + CONSTRUCTOR_DELEGATE, + new Type[]{ Type.getType(iface) }, + Constants.SOURCE_FILE); + Type declaring = Type.getType(constructor.getDeclaringClass()); + EmitUtils.null_constructor(ce); + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, + ReflectUtils.getSignature(newInstance), + ReflectUtils.getExceptionTypes(newInstance)); + e.new_instance(declaring); + e.dup(); + e.load_args(); + e.invoke_constructor(declaring, ReflectUtils.getSignature(constructor)); + e.return_value(); + e.end_method(); + ce.end_class(); + } + + protected Object firstInstance(Class type) { + return ReflectUtils.newInstance(type); + } + + protected Object nextInstance(Object instance) { + return instance; + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/reflect/FastClass.java b/blade-aop/src/main/java/net/sf/cglib/reflect/FastClass.java new file mode 100644 index 000000000..ce9026ad2 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/reflect/FastClass.java @@ -0,0 +1,207 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.reflect; + +import net.sf.cglib.core.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.ProtectionDomain; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; + +abstract public class FastClass +{ + private Class type; + + protected FastClass() { + throw new Error("Using the FastClass empty constructor--please report to the cglib-devel mailing list"); + } + + protected FastClass(Class type) { + this.type = type; + } + + public static FastClass create(Class type) { + + return create(type.getClassLoader(),type); + + } + public static FastClass create(ClassLoader loader, Class type) { + Generator gen = new Generator(); + gen.setType(type); + gen.setClassLoader(loader); + return gen.create(); + } + + public static class Generator extends AbstractClassGenerator + { + private static final Source SOURCE = new Source(FastClass.class.getName()); + private Class type; + + public Generator() { + super(SOURCE); + } + + public void setType(Class type) { + this.type = type; + } + + public FastClass create() { + setNamePrefix(type.getName()); + return (FastClass)super.create(type.getName()); + } + + protected ClassLoader getDefaultClassLoader() { + return type.getClassLoader(); + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(type); + } + + public void generateClass(ClassVisitor v) throws Exception { + new FastClassEmitter(v, getClassName(), type); + } + + protected Object firstInstance(Class type) { + return ReflectUtils.newInstance(type, + new Class[]{ Class.class }, + new Object[]{ this.type }); + } + + protected Object nextInstance(Object instance) { + return instance; + } + } + + public Object invoke(String name, Class[] parameterTypes, Object obj, Object[] args) throws InvocationTargetException { + return invoke(getIndex(name, parameterTypes), obj, args); + } + + public Object newInstance() throws InvocationTargetException { + return newInstance(getIndex(Constants.EMPTY_CLASS_ARRAY), null); + } + + public Object newInstance(Class[] parameterTypes, Object[] args) throws InvocationTargetException { + return newInstance(getIndex(parameterTypes), args); + } + + public FastMethod getMethod(Method method) { + return new FastMethod(this, method); + } + + public FastConstructor getConstructor(Constructor constructor) { + return new FastConstructor(this, constructor); + } + + public FastMethod getMethod(String name, Class[] parameterTypes) { + try { + return getMethod(type.getMethod(name, parameterTypes)); + } catch (NoSuchMethodException e) { + throw new NoSuchMethodError(e.getMessage()); + } + } + + public FastConstructor getConstructor(Class[] parameterTypes) { + try { + return getConstructor(type.getConstructor(parameterTypes)); + } catch (NoSuchMethodException e) { + throw new NoSuchMethodError(e.getMessage()); + } + } + + public String getName() { + return type.getName(); + } + + public Class getJavaClass() { + return type; + } + + public String toString() { + return type.toString(); + } + + public int hashCode() { + return type.hashCode(); + } + + public boolean equals(Object o) { + if (o == null || !(o instanceof FastClass)) { + return false; + } + return type.equals(((FastClass)o).type); + } + + /** + * Return the index of the matching method. The index may be used + * later to invoke the method with less overhead. If more than one + * method matches (i.e. they differ by return type only), one is + * chosen arbitrarily. + * @see #invoke(int, Object, Object[]) + * @param name the method name + * @param parameterTypes the parameter array + * @return the index, or -1 if none is found. + */ + abstract public int getIndex(String name, Class[] parameterTypes); + + /** + * Return the index of the matching constructor. The index may be used + * later to create a new instance with less overhead. + * @see #newInstance(int, Object[]) + * @param parameterTypes the parameter array + * @return the constructor index, or -1 if none is found. + */ + abstract public int getIndex(Class[] parameterTypes); + + /** + * Invoke the method with the specified index. + * @see getIndex(name, Class[]) + * @param index the method index + * @param obj the object the underlying method is invoked from + * @param args the arguments used for the method call + * @throws java.lang.reflect.InvocationTargetException if the underlying method throws an exception + */ + abstract public Object invoke(int index, Object obj, Object[] args) throws InvocationTargetException; + + /** + * Create a new instance using the specified constructor index and arguments. + * @see getIndex(Class[]) + * @param index the constructor index + * @param args the arguments passed to the constructor + * @throws java.lang.reflect.InvocationTargetException if the constructor throws an exception + */ + abstract public Object newInstance(int index, Object[] args) throws InvocationTargetException; + + abstract public int getIndex(Signature sig); + + /** + * Returns the maximum method index for this class. + */ + abstract public int getMaxIndex(); + + protected static String getSignatureWithoutReturnType(String name, Class[] parameterTypes) { + StringBuffer sb = new StringBuffer(); + sb.append(name); + sb.append('('); + for (int i = 0; i < parameterTypes.length; i++) { + sb.append(Type.getDescriptor(parameterTypes[i])); + } + sb.append(')'); + return sb.toString(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/reflect/FastClassEmitter.java b/blade-aop/src/main/java/net/sf/cglib/reflect/FastClassEmitter.java new file mode 100644 index 000000000..61990e28f --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/reflect/FastClassEmitter.java @@ -0,0 +1,226 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.reflect; + +import java.lang.reflect.*; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +class FastClassEmitter extends ClassEmitter { + private static final Signature CSTRUCT_CLASS = + TypeUtils.parseConstructor("Class"); + private static final Signature METHOD_GET_INDEX = + TypeUtils.parseSignature("int getIndex(String, Class[])"); + private static final Signature SIGNATURE_GET_INDEX = + new Signature("getIndex", Type.INT_TYPE, new Type[]{ Constants.TYPE_SIGNATURE }); + private static final Signature TO_STRING = + TypeUtils.parseSignature("String toString()"); + private static final Signature CONSTRUCTOR_GET_INDEX = + TypeUtils.parseSignature("int getIndex(Class[])"); + private static final Signature INVOKE = + TypeUtils.parseSignature("Object invoke(int, Object, Object[])"); + private static final Signature NEW_INSTANCE = + TypeUtils.parseSignature("Object newInstance(int, Object[])"); + private static final Signature GET_MAX_INDEX = + TypeUtils.parseSignature("int getMaxIndex()"); + private static final Signature GET_SIGNATURE_WITHOUT_RETURN_TYPE = + TypeUtils.parseSignature("String getSignatureWithoutReturnType(String, Class[])"); + private static final Type FAST_CLASS = + TypeUtils.parseType("net.sf.cglib.reflect.FastClass"); + private static final Type ILLEGAL_ARGUMENT_EXCEPTION = + TypeUtils.parseType("IllegalArgumentException"); + private static final Type INVOCATION_TARGET_EXCEPTION = + TypeUtils.parseType("java.lang.reflect.InvocationTargetException"); + private static final Type[] INVOCATION_TARGET_EXCEPTION_ARRAY = { INVOCATION_TARGET_EXCEPTION }; + + public FastClassEmitter(ClassVisitor v, String className, Class type) { + super(v); + + Type base = Type.getType(type); + begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, FAST_CLASS, null, Constants.SOURCE_FILE); + + // constructor + CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_CLASS, null); + e.load_this(); + e.load_args(); + e.super_invoke_constructor(CSTRUCT_CLASS); + e.return_value(); + e.end_method(); + + VisibilityPredicate vp = new VisibilityPredicate(type, false); + List methods = ReflectUtils.addAllMethods(type, new ArrayList()); + CollectionUtils.filter(methods, vp); + CollectionUtils.filter(methods, new DuplicatesPredicate()); + List constructors = new ArrayList(Arrays.asList(type.getDeclaredConstructors())); + CollectionUtils.filter(constructors, vp); + + // getIndex(String) + emitIndexBySignature(methods); + + // getIndex(String, Class[]) + emitIndexByClassArray(methods); + + // getIndex(Class[]) + e = begin_method(Constants.ACC_PUBLIC, CONSTRUCTOR_GET_INDEX, null); + e.load_args(); + List info = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance()); + EmitUtils.constructor_switch(e, info, new GetIndexCallback(e, info)); + e.end_method(); + + // invoke(int, Object, Object[]) + e = begin_method(Constants.ACC_PUBLIC, INVOKE, INVOCATION_TARGET_EXCEPTION_ARRAY); + e.load_arg(1); + e.checkcast(base); + e.load_arg(0); + invokeSwitchHelper(e, methods, 2, base); + e.end_method(); + + // newInstance(int, Object[]) + e = begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, INVOCATION_TARGET_EXCEPTION_ARRAY); + e.new_instance(base); + e.dup(); + e.load_arg(0); + invokeSwitchHelper(e, constructors, 1, base); + e.end_method(); + + // getMaxIndex() + e = begin_method(Constants.ACC_PUBLIC, GET_MAX_INDEX, null); + e.push(methods.size() - 1); + e.return_value(); + e.end_method(); + + end_class(); + } + + // TODO: support constructor indices ("") + private void emitIndexBySignature(List methods) { + CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SIGNATURE_GET_INDEX, null); + List signatures = CollectionUtils.transform(methods, new Transformer() { + public Object transform(Object obj) { + return ReflectUtils.getSignature((Method)obj).toString(); + } + }); + e.load_arg(0); + e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING); + signatureSwitchHelper(e, signatures); + e.end_method(); + } + + private static final int TOO_MANY_METHODS = 100; // TODO + private void emitIndexByClassArray(List methods) { + CodeEmitter e = begin_method(Constants.ACC_PUBLIC, METHOD_GET_INDEX, null); + if (methods.size() > TOO_MANY_METHODS) { + // hack for big classes + List signatures = CollectionUtils.transform(methods, new Transformer() { + public Object transform(Object obj) { + String s = ReflectUtils.getSignature((Method)obj).toString(); + return s.substring(0, s.lastIndexOf(')') + 1); + } + }); + e.load_args(); + e.invoke_static(FAST_CLASS, GET_SIGNATURE_WITHOUT_RETURN_TYPE); + signatureSwitchHelper(e, signatures); + } else { + e.load_args(); + List info = CollectionUtils.transform(methods, MethodInfoTransformer.getInstance()); + EmitUtils.method_switch(e, info, new GetIndexCallback(e, info)); + } + e.end_method(); + } + + private void signatureSwitchHelper(final CodeEmitter e, final List signatures) { + ObjectSwitchCallback callback = new ObjectSwitchCallback() { + public void processCase(Object key, Label end) { + // TODO: remove linear indexOf + e.push(signatures.indexOf(key)); + e.return_value(); + } + public void processDefault() { + e.push(-1); + e.return_value(); + } + }; + EmitUtils.string_switch(e, + (String[])signatures.toArray(new String[signatures.size()]), + Constants.SWITCH_STYLE_HASH, + callback); + } + + private static void invokeSwitchHelper(final CodeEmitter e, List members, final int arg, final Type base) { + final List info = CollectionUtils.transform(members, MethodInfoTransformer.getInstance()); + final Label illegalArg = e.make_label(); + Block block = e.begin_block(); + e.process_switch(getIntRange(info.size()), new ProcessSwitchCallback() { + public void processCase(int key, Label end) { + MethodInfo method = (MethodInfo)info.get(key); + Type[] types = method.getSignature().getArgumentTypes(); + for (int i = 0; i < types.length; i++) { + e.load_arg(arg); + e.aaload(i); + e.unbox(types[i]); + } + // TODO: change method lookup process so MethodInfo will already reference base + // instead of superclass when superclass method is inaccessible + e.invoke(method, base); + if (!TypeUtils.isConstructor(method)) { + e.box(method.getSignature().getReturnType()); + } + e.return_value(); + } + public void processDefault() { + e.goTo(illegalArg); + } + }); + block.end(); + EmitUtils.wrap_throwable(block, INVOCATION_TARGET_EXCEPTION); + e.mark(illegalArg); + e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Cannot find matching method/constructor"); + } + + private static class GetIndexCallback implements ObjectSwitchCallback { + private CodeEmitter e; + private Map indexes = new HashMap(); + + public GetIndexCallback(CodeEmitter e, List methods) { + this.e = e; + int index = 0; + for (Iterator it = methods.iterator(); it.hasNext();) { + indexes.put(it.next(), new Integer(index++)); + } + } + + public void processCase(Object key, Label end) { + e.push(((Integer)indexes.get(key)).intValue()); + e.return_value(); + } + + public void processDefault() { + e.push(-1); + e.return_value(); + } + } + + private static int[] getIntRange(int length) { + int[] range = new int[length]; + for (int i = 0; i < length; i++) { + range[i] = i; + } + return range; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/reflect/FastConstructor.java b/blade-aop/src/main/java/net/sf/cglib/reflect/FastConstructor.java new file mode 100644 index 000000000..7b25697c2 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/reflect/FastConstructor.java @@ -0,0 +1,46 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.reflect; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +public class FastConstructor extends FastMember +{ + FastConstructor(FastClass fc, Constructor constructor) { + super(fc, constructor, fc.getIndex(constructor.getParameterTypes())); + } + + public Class[] getParameterTypes() { + return ((Constructor)member).getParameterTypes(); + } + + public Class[] getExceptionTypes() { + return ((Constructor)member).getExceptionTypes(); + } + + public Object newInstance() throws InvocationTargetException { + return fc.newInstance(index, null); + } + + public Object newInstance(Object[] args) throws InvocationTargetException { + return fc.newInstance(index, args); + } + + public Constructor getJavaConstructor() { + return (Constructor)member; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/reflect/FastMember.java b/blade-aop/src/main/java/net/sf/cglib/reflect/FastMember.java new file mode 100644 index 000000000..08dc5cc7f --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/reflect/FastMember.java @@ -0,0 +1,65 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.reflect; + +import java.lang.reflect.Member; + +abstract public class FastMember +{ + protected FastClass fc; + protected Member member; + protected int index; + + protected FastMember(FastClass fc, Member member, int index) { + this.fc = fc; + this.member = member; + this.index = index; + } + + abstract public Class[] getParameterTypes(); + abstract public Class[] getExceptionTypes(); + + public int getIndex() { + return index; + } + + public String getName() { + return member.getName(); + } + + public Class getDeclaringClass() { + return fc.getJavaClass(); + } + + public int getModifiers() { + return member.getModifiers(); + } + + public String toString() { + return member.toString(); + } + + public int hashCode() { + return member.hashCode(); + } + + public boolean equals(Object o) { + if (o == null || !(o instanceof FastMember)) { + return false; + } + return member.equals(((FastMember)o).member); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/reflect/FastMethod.java b/blade-aop/src/main/java/net/sf/cglib/reflect/FastMethod.java new file mode 100644 index 000000000..0c027be3a --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/reflect/FastMethod.java @@ -0,0 +1,63 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.reflect; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import net.sf.cglib.core.Signature; + +import org.objectweb.asm.Type; + +public class FastMethod extends FastMember +{ + FastMethod(FastClass fc, Method method) { + super(fc, method, helper(fc, method)); + } + + private static int helper(FastClass fc, Method method) { + int index = fc.getIndex(new Signature(method.getName(), Type.getMethodDescriptor(method))); + if (index < 0) { + Class[] types = method.getParameterTypes(); + System.err.println("hash=" + method.getName().hashCode() + " size=" + types.length); + for (int i = 0; i < types.length; i++) { + System.err.println(" types[" + i + "]=" + types[i].getName()); + } + throw new IllegalArgumentException("Cannot find method " + method); + } + return index; + } + + public Class getReturnType() { + return ((Method)member).getReturnType(); + } + + public Class[] getParameterTypes() { + return ((Method)member).getParameterTypes(); + } + + public Class[] getExceptionTypes() { + return ((Method)member).getExceptionTypes(); + } + + public Object invoke(Object obj, Object[] args) throws InvocationTargetException { + return fc.invoke(index, obj, args); + } + + public Method getJavaMethod() { + return (Method)member; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/reflect/MethodDelegate.java b/blade-aop/src/main/java/net/sf/cglib/reflect/MethodDelegate.java new file mode 100644 index 000000000..54da1d355 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/reflect/MethodDelegate.java @@ -0,0 +1,268 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.reflect; + +import java.lang.reflect.*; +import java.security.ProtectionDomain; +import net.sf.cglib.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; + +// TODO: don't require exact match for return type + +/** + * DOCUMENTATION FROM APACHE AVALON DELEGATE CLASS + * + *

+ * Delegates are a typesafe pointer to another method. Since Java does not + * have language support for such a construct, this utility will construct + * a proxy that forwards method calls to any method with the same signature. + * This utility is inspired in part by the C# delegate mechanism. We + * implemented it in a Java-centric manner. + *

+ * + *

Delegate

+ *

+ * Any interface with one method can become the interface for a delegate. + * Consider the example below: + *

+ * + *
+ *   public interface MainDelegate {
+ *       int main(String[] args);
+ *   }
+ * 
+ * + *

+ * The interface above is an example of an interface that can become a + * delegate. It has only one method, and the interface is public. In + * order to create a delegate for that method, all we have to do is + * call MethodDelegate.create(this, "alternateMain", MainDelegate.class). + * The following program will show how to use it: + *

+ * + *
+ *   public class Main {
+ *       public static int main( String[] args ) {
+ *           Main newMain = new Main();
+ *           MainDelegate start = (MainDelegate)
+ *               MethodDelegate.create(newMain, "alternateMain", MainDelegate.class);
+ *           return start.main( args );
+ *       }
+ *
+ *       public int alternateMain( String[] args ) {
+ *           for (int i = 0; i < args.length; i++) {
+ *               System.out.println( args[i] );
+ *           }
+ *           return args.length;
+ *       }
+ *   }
+ * 
+ * + *

+ * By themselves, delegates don't do much. Their true power lies in the fact that + * they can be treated like objects, and passed to other methods. In fact that is + * one of the key building blocks of building Intelligent Agents which in tern are + * the foundation of artificial intelligence. In the above program, we could have + * easily created the delegate to match the static main method by + * substituting the delegate creation call with this: + * MethodDelegate.createStatic(getClass(), "main", MainDelegate.class). + *

+ *

+ * Another key use for Delegates is to register event listeners. It is much easier + * to have all the code for your events separated out into methods instead of individual + * classes. One of the ways Java gets around that is to create anonymous classes. + * They are particularly troublesome because many Debuggers do not know what to do + * with them. Anonymous classes tend to duplicate alot of code as well. We can + * use any interface with one declared method to forward events to any method that + * matches the signature (although the method name can be different). + *

+ * + *

Equality

+ * The criteria that we use to test if two delegates are equal are: + *
    + *
  • + * They both refer to the same instance. That is, the instance + * parameter passed to the newDelegate method was the same for both. The + * instances are compared with the identity equality operator, ==. + *
  • + *
  • They refer to the same method as resolved by Method.equals.
  • + *
+ * + * @version $Id: MethodDelegate.java,v 1.25 2006/03/05 02:43:19 herbyderby Exp $ + */ +abstract public class MethodDelegate { + private static final MethodDelegateKey KEY_FACTORY = + (MethodDelegateKey)KeyFactory.create(MethodDelegateKey.class, KeyFactory.CLASS_BY_NAME); + + protected Object target; + protected String eqMethod; + + interface MethodDelegateKey { + Object newInstance(Class delegateClass, String methodName, Class iface); + } + + public static MethodDelegate createStatic(Class targetClass, String methodName, Class iface) { + Generator gen = new Generator(); + gen.setTargetClass(targetClass); + gen.setMethodName(methodName); + gen.setInterface(iface); + return gen.create(); + } + + public static MethodDelegate create(Object target, String methodName, Class iface) { + Generator gen = new Generator(); + gen.setTarget(target); + gen.setMethodName(methodName); + gen.setInterface(iface); + return gen.create(); + } + + public boolean equals(Object obj) { + MethodDelegate other = (MethodDelegate)obj; + return (other != null && target == other.target) && eqMethod.equals(other.eqMethod); + } + + public int hashCode() { + return target.hashCode() ^ eqMethod.hashCode(); + } + + public Object getTarget() { + return target; + } + + abstract public MethodDelegate newInstance(Object target); + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(MethodDelegate.class.getName()); + private static final Type METHOD_DELEGATE = + TypeUtils.parseType("net.sf.cglib.reflect.MethodDelegate"); + private static final Signature NEW_INSTANCE = + new Signature("newInstance", METHOD_DELEGATE, new Type[]{ Constants.TYPE_OBJECT }); + + private Object target; + private Class targetClass; + private String methodName; + private Class iface; + + public Generator() { + super(SOURCE); + } + + public void setTarget(Object target) { + this.target = target; + this.targetClass = target.getClass(); + } + + public void setTargetClass(Class targetClass) { + this.targetClass = targetClass; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public void setInterface(Class iface) { + this.iface = iface; + } + + protected ClassLoader getDefaultClassLoader() { + return targetClass.getClassLoader(); + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(targetClass); + } + + public MethodDelegate create() { + setNamePrefix(targetClass.getName()); + Object key = KEY_FACTORY.newInstance(targetClass, methodName, iface); + return (MethodDelegate)super.create(key); + } + + protected Object firstInstance(Class type) { + return ((MethodDelegate)ReflectUtils.newInstance(type)).newInstance(target); + } + + protected Object nextInstance(Object instance) { + return ((MethodDelegate)instance).newInstance(target); + } + + public void generateClass(ClassVisitor v) throws NoSuchMethodException { + Method proxy = ReflectUtils.findInterfaceMethod(iface); + final Method method = targetClass.getMethod(methodName, proxy.getParameterTypes()); + if (!proxy.getReturnType().isAssignableFrom(method.getReturnType())) { + throw new IllegalArgumentException("incompatible return types"); + } + + MethodInfo methodInfo = ReflectUtils.getMethodInfo(method); + + boolean isStatic = TypeUtils.isStatic(methodInfo.getModifiers()); + if ((target == null) ^ isStatic) { + throw new IllegalArgumentException("Static method " + (isStatic ? "not " : "") + "expected"); + } + + ClassEmitter ce = new ClassEmitter(v); + CodeEmitter e; + ce.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + getClassName(), + METHOD_DELEGATE, + new Type[]{ Type.getType(iface) }, + Constants.SOURCE_FILE); + ce.declare_field(Constants.PRIVATE_FINAL_STATIC, "eqMethod", Constants.TYPE_STRING, null); + EmitUtils.null_constructor(ce); + + // generate proxied method + MethodInfo proxied = ReflectUtils.getMethodInfo(iface.getDeclaredMethods()[0]); + int modifiers = Constants.ACC_PUBLIC; + if ((proxied.getModifiers() & Constants.ACC_VARARGS) == Constants.ACC_VARARGS) { + modifiers |= Constants.ACC_VARARGS; + } + e = EmitUtils.begin_method(ce, proxied, modifiers); + e.load_this(); + e.super_getfield("target", Constants.TYPE_OBJECT); + e.checkcast(methodInfo.getClassInfo().getType()); + e.load_args(); + e.invoke(methodInfo); + e.return_value(); + e.end_method(); + + // newInstance + e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null); + e.new_instance_this(); + e.dup(); + e.dup2(); + e.invoke_constructor_this(); + e.getfield("eqMethod"); + e.super_putfield("eqMethod", Constants.TYPE_STRING); + e.load_arg(0); + e.super_putfield("target", Constants.TYPE_OBJECT); + e.return_value(); + e.end_method(); + + // static initializer + e = ce.begin_static(); + e.push(methodInfo.getSignature().toString()); + e.putfield("eqMethod"); + e.return_value(); + e.end_method(); + + ce.end_class(); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/reflect/MulticastDelegate.java b/blade-aop/src/main/java/net/sf/cglib/reflect/MulticastDelegate.java new file mode 100644 index 000000000..fe5e7b8d2 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/reflect/MulticastDelegate.java @@ -0,0 +1,179 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.reflect; + +import java.lang.reflect.*; +import java.security.ProtectionDomain; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; + +abstract public class MulticastDelegate implements Cloneable { + protected Object[] targets = {}; + + protected MulticastDelegate() { + } + + public List getTargets() { + return new ArrayList(Arrays.asList(targets)); + } + + abstract public MulticastDelegate add(Object target); + + protected MulticastDelegate addHelper(Object target) { + MulticastDelegate copy = newInstance(); + copy.targets = new Object[targets.length + 1]; + System.arraycopy(targets, 0, copy.targets, 0, targets.length); + copy.targets[targets.length] = target; + return copy; + } + + public MulticastDelegate remove(Object target) { + for (int i = targets.length - 1; i >= 0; i--) { + if (targets[i].equals(target)) { + MulticastDelegate copy = newInstance(); + copy.targets = new Object[targets.length - 1]; + System.arraycopy(targets, 0, copy.targets, 0, i); + System.arraycopy(targets, i + 1, copy.targets, i, targets.length - i - 1); + return copy; + } + } + return this; + } + + abstract public MulticastDelegate newInstance(); + + public static MulticastDelegate create(Class iface) { + Generator gen = new Generator(); + gen.setInterface(iface); + return gen.create(); + } + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(MulticastDelegate.class.getName()); + private static final Type MULTICAST_DELEGATE = + TypeUtils.parseType("net.sf.cglib.reflect.MulticastDelegate"); + private static final Signature NEW_INSTANCE = + new Signature("newInstance", MULTICAST_DELEGATE, new Type[0]); + private static final Signature ADD_DELEGATE = + new Signature("add", MULTICAST_DELEGATE, new Type[]{ Constants.TYPE_OBJECT }); + private static final Signature ADD_HELPER = + new Signature("addHelper", MULTICAST_DELEGATE, new Type[]{ Constants.TYPE_OBJECT }); + + private Class iface; + + public Generator() { + super(SOURCE); + } + + protected ClassLoader getDefaultClassLoader() { + return iface.getClassLoader(); + } + + protected ProtectionDomain getProtectionDomain() { + return ReflectUtils.getProtectionDomain(iface); + } + + public void setInterface(Class iface) { + this.iface = iface; + } + + public MulticastDelegate create() { + setNamePrefix(MulticastDelegate.class.getName()); + return (MulticastDelegate)super.create(iface.getName()); + } + + public void generateClass(ClassVisitor cv) { + final MethodInfo method = ReflectUtils.getMethodInfo(ReflectUtils.findInterfaceMethod(iface)); + + ClassEmitter ce = new ClassEmitter(cv); + ce.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + getClassName(), + MULTICAST_DELEGATE, + new Type[]{ Type.getType(iface) }, + Constants.SOURCE_FILE); + EmitUtils.null_constructor(ce); + + // generate proxied method + emitProxy(ce, method); + + // newInstance + CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null); + e.new_instance_this(); + e.dup(); + e.invoke_constructor_this(); + e.return_value(); + e.end_method(); + + // add + e = ce.begin_method(Constants.ACC_PUBLIC, ADD_DELEGATE, null); + e.load_this(); + e.load_arg(0); + e.checkcast(Type.getType(iface)); + e.invoke_virtual_this(ADD_HELPER); + e.return_value(); + e.end_method(); + + ce.end_class(); + } + + private void emitProxy(ClassEmitter ce, final MethodInfo method) { + int modifiers = Constants.ACC_PUBLIC; + if ((method.getModifiers() & Constants.ACC_VARARGS) == Constants.ACC_VARARGS) { + modifiers |= Constants.ACC_VARARGS; + } + final CodeEmitter e = EmitUtils.begin_method(ce, method, modifiers); + Type returnType = method.getSignature().getReturnType(); + final boolean returns = returnType != Type.VOID_TYPE; + Local result = null; + if (returns) { + result = e.make_local(returnType); + e.zero_or_null(returnType); + e.store_local(result); + } + e.load_this(); + e.super_getfield("targets", Constants.TYPE_OBJECT_ARRAY); + final Local result2 = result; + EmitUtils.process_array(e, Constants.TYPE_OBJECT_ARRAY, new ProcessArrayCallback() { + public void processElement(Type type) { + e.checkcast(Type.getType(iface)); + e.load_args(); + e.invoke(method); + if (returns) { + e.store_local(result2); + } + } + }); + if (returns) { + e.load_local(result); + } + e.return_value(); + e.end_method(); + } + + protected Object firstInstance(Class type) { + // make a new instance in case first object is used with a long list of targets + return ((MulticastDelegate)ReflectUtils.newInstance(type)).newInstance(); + } + + protected Object nextInstance(Object instance) { + return ((MulticastDelegate)instance).newInstance(); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassFilterTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassFilterTransformer.java new file mode 100644 index 000000000..53742fb6f --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassFilterTransformer.java @@ -0,0 +1,85 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.*; + +abstract public class AbstractClassFilterTransformer extends AbstractClassTransformer { + private ClassTransformer pass; + private ClassVisitor target; + + public void setTarget(ClassVisitor target) { + super.setTarget(target); + pass.setTarget(target); + } + + protected AbstractClassFilterTransformer(ClassTransformer pass) { + this.pass = pass; + } + + abstract protected boolean accept(int version, int access, String name, String signature, String superName, String[] interfaces); + + public void visit(int version, + int access, + String name, + String signature, + String superName, + String[] interfaces) { + target = accept(version, access, name, signature, superName, interfaces) ? pass : cv; + target.visit(version, access, name, signature, superName, interfaces); + } + + public void visitSource(String source, String debug) { + target.visitSource(source, debug); + } + + public void visitOuterClass(String owner, String name, String desc) { + target.visitOuterClass(owner, name, desc); + } + + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + return target.visitAnnotation(desc, visible); + } + + public void visitAttribute(Attribute attr) { + target.visitAttribute(attr); + } + + public void visitInnerClass(String name, String outerName, String innerName, int access) { + target.visitInnerClass(name, outerName, innerName, access); + } + + public FieldVisitor visitField(int access, + String name, + String desc, + String signature, + Object value) { + return target.visitField(access, name, desc, signature, value); + } + + public MethodVisitor visitMethod(int access, + String name, + String desc, + String signature, + String[] exceptions) { + return target.visitMethod(access, name, desc, signature, exceptions); + } + + public void visitEnd() { + target.visitEnd(); + target = null; // just to be safe + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassLoader.java b/blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassLoader.java new file mode 100644 index 000000000..8f25e4fd6 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassLoader.java @@ -0,0 +1,118 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import net.sf.cglib.core.CodeGenerationException; +import net.sf.cglib.core.ClassGenerator; +import net.sf.cglib.core.DebuggingClassWriter; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Attribute; + +import java.io.IOException; + +abstract public class AbstractClassLoader extends ClassLoader { + private ClassFilter filter; + private ClassLoader classPath; + private static java.security.ProtectionDomain DOMAIN ; + + static{ + + DOMAIN = (java.security.ProtectionDomain) + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + return AbstractClassLoader.class.getProtectionDomain(); + } + }); + } + + protected AbstractClassLoader(ClassLoader parent, ClassLoader classPath, ClassFilter filter) { + super(parent); + this.filter = filter; + this.classPath = classPath; + } + + public Class loadClass(String name) throws ClassNotFoundException { + + Class loaded = findLoadedClass(name); + + if( loaded != null ){ + if( loaded.getClassLoader() == this ){ + return loaded; + }//else reload with this class loader + } + + if (!filter.accept(name)) { + return super.loadClass(name); + } + ClassReader r; + try { + + java.io.InputStream is = classPath.getResourceAsStream( + name.replace('.','/') + ".class" + ); + + if (is == null) { + + throw new ClassNotFoundException(name); + + } + try { + + r = new ClassReader(is); + + } finally { + + is.close(); + + } + } catch (IOException e) { + throw new ClassNotFoundException(name + ":" + e.getMessage()); + } + + try { + DebuggingClassWriter w = + new DebuggingClassWriter(ClassWriter.COMPUTE_FRAMES); + getGenerator(r).generateClass(w); + byte[] b = w.toByteArray(); + Class c = super.defineClass(name, b, 0, b.length, DOMAIN); + postProcess(c); + return c; + } catch (RuntimeException e) { + throw e; + } catch (Error e) { + throw e; + } catch (Exception e) { + throw new CodeGenerationException(e); + } + } + + protected ClassGenerator getGenerator(ClassReader r) { + return new ClassReaderGenerator(r, attributes(), getFlags()); + } + + protected int getFlags() { + return 0; + } + + protected Attribute[] attributes() { + return null; + } + + protected void postProcess(Class c) { + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassTransformer.java new file mode 100644 index 000000000..67102054e --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/AbstractClassTransformer.java @@ -0,0 +1,29 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; + +abstract public class AbstractClassTransformer extends ClassTransformer { + protected AbstractClassTransformer() { + super(Opcodes.ASM5); + } + + public void setTarget(ClassVisitor target) { + cv = target; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/AnnotationVisitorTee.java b/blade-aop/src/main/java/net/sf/cglib/transform/AnnotationVisitorTee.java new file mode 100644 index 000000000..5ca4a22a1 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/AnnotationVisitorTee.java @@ -0,0 +1,61 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Opcodes; + +public class AnnotationVisitorTee extends AnnotationVisitor { + private AnnotationVisitor av1, av2; + + public static AnnotationVisitor getInstance(AnnotationVisitor av1, AnnotationVisitor av2) { + if (av1 == null) + return av2; + if (av2 == null) + return av1; + return new AnnotationVisitorTee(av1, av2); + } + + public AnnotationVisitorTee(AnnotationVisitor av1, AnnotationVisitor av2) { + super(Opcodes.ASM5); + this.av1 = av1; + this.av2 = av2; + } + + public void visit(String name, Object value) { + av2.visit(name, value); + av2.visit(name, value); + } + + public void visitEnum(String name, String desc, String value) { + av1.visitEnum(name, desc, value); + av2.visitEnum(name, desc, value); + } + + public AnnotationVisitor visitAnnotation(String name, String desc) { + return getInstance(av1.visitAnnotation(name, desc), + av2.visitAnnotation(name, desc)); + } + + public AnnotationVisitor visitArray(String name) { + return getInstance(av1.visitArray(name), av2.visitArray(name)); + } + + public void visitEnd() { + av1.visitEnd(); + av2.visitEnd(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/ClassEmitterTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/ClassEmitterTransformer.java new file mode 100644 index 000000000..8d0adb599 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/ClassEmitterTransformer.java @@ -0,0 +1,21 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import net.sf.cglib.core.ClassEmitter; + +abstract public class ClassEmitterTransformer extends ClassEmitter { +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/ClassFilter.java b/blade-aop/src/main/java/net/sf/cglib/transform/ClassFilter.java new file mode 100644 index 000000000..10bc52285 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/ClassFilter.java @@ -0,0 +1,27 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +/** + * + * @author baliuka + */ +public interface ClassFilter { + + boolean accept(String className); + +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/ClassFilterTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/ClassFilterTransformer.java new file mode 100644 index 000000000..7f9e7bef3 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/ClassFilterTransformer.java @@ -0,0 +1,31 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.*; + +public class ClassFilterTransformer extends AbstractClassFilterTransformer { + private ClassFilter filter; + + public ClassFilterTransformer(ClassFilter filter, ClassTransformer pass) { + super(pass); + this.filter = filter; + } + + protected boolean accept(int version, int access, String name, String signature, String superName, String[] interfaces) { + return filter.accept(name.replace('/', '.')); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/ClassReaderGenerator.java b/blade-aop/src/main/java/net/sf/cglib/transform/ClassReaderGenerator.java new file mode 100644 index 000000000..9274f843d --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/ClassReaderGenerator.java @@ -0,0 +1,41 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import net.sf.cglib.core.ClassGenerator; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; + +public class ClassReaderGenerator implements ClassGenerator { + private final ClassReader r; + private final Attribute[] attrs; + private final int flags; + + public ClassReaderGenerator(ClassReader r, int flags) { + this(r, null, flags); + } + + public ClassReaderGenerator(ClassReader r, Attribute[] attrs, int flags) { + this.r = r; + this.attrs = (attrs != null) ? attrs : new Attribute[0]; + this.flags = flags; + } + + public void generateClass(ClassVisitor v) { + r.accept(v, attrs, flags); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformer.java new file mode 100644 index 000000000..853020c04 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformer.java @@ -0,0 +1,29 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; + +public abstract class ClassTransformer extends ClassVisitor { + public ClassTransformer() { + super(Opcodes.ASM5); + } + public ClassTransformer(int opcode) { + super(opcode); + } + public abstract void setTarget(ClassVisitor target); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerChain.java b/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerChain.java new file mode 100644 index 000000000..acce06ff6 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerChain.java @@ -0,0 +1,56 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.*; + +public class ClassTransformerChain extends AbstractClassTransformer { + private ClassTransformer[] chain; + + public ClassTransformerChain(ClassTransformer[] chain) { + this.chain = (ClassTransformer[])chain.clone(); + } + + public void setTarget(ClassVisitor v) { + super.setTarget(chain[0]); + ClassVisitor next = v; + for (int i = chain.length - 1; i >= 0; i--) { + chain[i].setTarget(next); + next = chain[i]; + } + } + + public MethodVisitor visitMethod(int access, + String name, + String desc, + String signature, + String[] exceptions) { + return cv.visitMethod(access, name, desc, signature, exceptions); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("ClassTransformerChain{"); + for (int i = 0; i < chain.length; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(chain[i].toString()); + } + sb.append("}"); + return sb.toString(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerFactory.java b/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerFactory.java new file mode 100644 index 000000000..cceac9261 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerFactory.java @@ -0,0 +1,20 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +public interface ClassTransformerFactory { + ClassTransformer newInstance(); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerTee.java b/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerTee.java new file mode 100644 index 000000000..367c3f7dc --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/ClassTransformerTee.java @@ -0,0 +1,32 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; + +public class ClassTransformerTee extends ClassTransformer { + private ClassVisitor branch; + + public ClassTransformerTee(ClassVisitor branch) { + super(Opcodes.ASM5); + this.branch = branch; + } + + public void setTarget(ClassVisitor target) { + cv = new ClassVisitorTee(branch, target); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/ClassVisitorTee.java b/blade-aop/src/main/java/net/sf/cglib/transform/ClassVisitorTee.java new file mode 100644 index 000000000..b4cb967fb --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/ClassVisitorTee.java @@ -0,0 +1,103 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.*; + +public class ClassVisitorTee extends ClassVisitor { + private ClassVisitor cv1, cv2; + + public ClassVisitorTee(ClassVisitor cv1, ClassVisitor cv2) { + super(Opcodes.ASM5); + this.cv1 = cv1; + this.cv2 = cv2; + } + + public void visit(int version, + int access, + String name, + String signature, + String superName, + String[] interfaces) { + cv1.visit(version, access, name, signature, superName, interfaces); + cv2.visit(version, access, name, signature, superName, interfaces); + } + + public void visitEnd() { + cv1.visitEnd(); + cv2.visitEnd(); + cv1 = cv2 = null; + } + + public void visitInnerClass(String name, String outerName, String innerName, int access) { + cv1.visitInnerClass(name, outerName, innerName, access); + cv2.visitInnerClass(name, outerName, innerName, access); + } + + public FieldVisitor visitField(int access, + String name, + String desc, + String signature, + Object value) { + FieldVisitor fv1 = cv1.visitField(access, name, desc, signature, value); + FieldVisitor fv2 = cv2.visitField(access, name, desc, signature, value); + if (fv1 == null) + return fv2; + if (fv2 == null) + return fv1; + return new FieldVisitorTee(fv1, fv2); + } + + + public MethodVisitor visitMethod(int access, + String name, + String desc, + String signature, + String[] exceptions) { + MethodVisitor mv1 = cv1.visitMethod(access, name, desc, signature, exceptions); + MethodVisitor mv2 = cv2.visitMethod(access, name, desc, signature, exceptions); + if (mv1 == null) + return mv2; + if (mv2 == null) + return mv1; + return new MethodVisitorTee(mv1, mv2); + } + + public void visitSource(String source, String debug) { + cv1.visitSource(source, debug); + cv2.visitSource(source, debug); + } + + public void visitOuterClass(String owner, String name, String desc) { + cv1.visitOuterClass(owner, name, desc); + cv2.visitOuterClass(owner, name, desc); + } + + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + return AnnotationVisitorTee.getInstance(cv1.visitAnnotation(desc, visible), + cv2.visitAnnotation(desc, visible)); + } + + public void visitAttribute(Attribute attrs) { + cv1.visitAttribute(attrs); + cv2.visitAttribute(attrs); + } + + public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { + return AnnotationVisitorTee.getInstance(cv1.visitTypeAnnotation(typeRef, typePath, desc, visible), + cv2.visitTypeAnnotation(typeRef, typePath, desc, visible)); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/FieldVisitorTee.java b/blade-aop/src/main/java/net/sf/cglib/transform/FieldVisitorTee.java new file mode 100644 index 000000000..1ade1dcd3 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/FieldVisitorTee.java @@ -0,0 +1,53 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.TypePath; + +public class FieldVisitorTee extends FieldVisitor { + private FieldVisitor fv1, fv2; + + public FieldVisitorTee(FieldVisitor fv1, FieldVisitor fv2) { + super(Opcodes.ASM5); + this.fv1 = fv1; + this.fv2 = fv2; + } + + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + return AnnotationVisitorTee.getInstance(fv1.visitAnnotation(desc, visible), + fv2.visitAnnotation(desc, visible)); + } + + public void visitAttribute(Attribute attr) { + fv1.visitAttribute(attr); + fv2.visitAttribute(attr); + } + + public void visitEnd() { + fv1.visitEnd(); + fv2.visitEnd(); + } + + public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { + return AnnotationVisitorTee.getInstance(fv1.visitTypeAnnotation(typeRef, typePath, desc, visible), + fv2.visitTypeAnnotation(typeRef, typePath, desc, visible)); + } +} + diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/MethodFilter.java b/blade-aop/src/main/java/net/sf/cglib/transform/MethodFilter.java new file mode 100644 index 000000000..2772f8165 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/MethodFilter.java @@ -0,0 +1,23 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.Attribute; + +public interface MethodFilter { + // TODO: pass class name too? + boolean accept(int access, String name, String desc, String signature, String[] exceptions); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/MethodFilterTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/MethodFilterTransformer.java new file mode 100644 index 000000000..1220cb0a8 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/MethodFilterTransformer.java @@ -0,0 +1,43 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.*; + +public class MethodFilterTransformer extends AbstractClassTransformer { + private MethodFilter filter; + private ClassTransformer pass; + private ClassVisitor direct; + + public MethodFilterTransformer(MethodFilter filter, ClassTransformer pass) { + this.filter = filter; + this.pass = pass; + super.setTarget(pass); + } + + public MethodVisitor visitMethod(int access, + String name, + String desc, + String signature, + String[] exceptions) { + return (filter.accept(access, name, desc, signature, exceptions) ? pass : direct).visitMethod(access, name, desc, signature, exceptions); + } + + public void setTarget(ClassVisitor target) { + pass.setTarget(target); + direct = target; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/MethodVisitorTee.java b/blade-aop/src/main/java/net/sf/cglib/transform/MethodVisitorTee.java new file mode 100644 index 000000000..17eeca062 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/MethodVisitorTee.java @@ -0,0 +1,187 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import org.objectweb.asm.*; + +public class MethodVisitorTee extends MethodVisitor { + private final MethodVisitor mv1; + private final MethodVisitor mv2; + + public MethodVisitorTee(MethodVisitor mv1, MethodVisitor mv2) { + super(Opcodes.ASM5); + this.mv1 = mv1; + this.mv2 = mv2; + } + + public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { + mv1.visitFrame(type, nLocal, local, nStack, stack); + mv2.visitFrame(type, nLocal, local, nStack, stack); + } + + public AnnotationVisitor visitAnnotationDefault() { + return AnnotationVisitorTee.getInstance(mv1.visitAnnotationDefault(), + mv2.visitAnnotationDefault()); + } + + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + return AnnotationVisitorTee.getInstance(mv1.visitAnnotation(desc, visible), + mv2.visitAnnotation(desc, visible)); + } + + public AnnotationVisitor visitParameterAnnotation(int parameter, + String desc, + boolean visible) { + return AnnotationVisitorTee.getInstance(mv1.visitParameterAnnotation(parameter, desc, visible), + mv2.visitParameterAnnotation(parameter, desc, visible)); + } + + public void visitAttribute(Attribute attr) { + mv1.visitAttribute(attr); + mv2.visitAttribute(attr); + } + + public void visitCode() { + mv1.visitCode(); + mv2.visitCode(); + } + + public void visitInsn(int opcode) { + mv1.visitInsn(opcode); + mv2.visitInsn(opcode); + } + + public void visitIntInsn(int opcode, int operand) { + mv1.visitIntInsn(opcode, operand); + mv2.visitIntInsn(opcode, operand); + } + + public void visitVarInsn(int opcode, int var) { + mv1.visitVarInsn(opcode, var); + mv2.visitVarInsn(opcode, var); + } + + public void visitTypeInsn(int opcode, String desc) { + mv1.visitTypeInsn(opcode, desc); + mv2.visitTypeInsn(opcode, desc); + } + + public void visitFieldInsn(int opcode, String owner, String name, String desc) { + mv1.visitFieldInsn(opcode, owner, name, desc); + mv2.visitFieldInsn(opcode, owner, name, desc); + } + + public void visitMethodInsn(int opcode, String owner, String name, String desc) { + mv1.visitMethodInsn(opcode, owner, name, desc); + mv2.visitMethodInsn(opcode, owner, name, desc); + } + + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { + mv1.visitMethodInsn(opcode, owner, name, desc, itf); + mv2.visitMethodInsn(opcode, owner, name, desc, itf); + } + + public void visitJumpInsn(int opcode, Label label) { + mv1.visitJumpInsn(opcode, label); + mv2.visitJumpInsn(opcode, label); + } + + public void visitLabel(Label label) { + mv1.visitLabel(label); + mv2.visitLabel(label); + } + + public void visitLdcInsn(Object cst) { + mv1.visitLdcInsn(cst); + mv2.visitLdcInsn(cst); + } + + public void visitIincInsn(int var, int increment) { + mv1.visitIincInsn(var, increment); + mv2.visitIincInsn(var, increment); + } + + public void visitTableSwitchInsn(int min, int max, Label dflt, Label labels[]) { + mv1.visitTableSwitchInsn(min, max, dflt, labels); + mv2.visitTableSwitchInsn(min, max, dflt, labels); + } + + public void visitLookupSwitchInsn(Label dflt, int keys[], Label labels[]) { + mv1.visitLookupSwitchInsn(dflt, keys, labels); + mv2.visitLookupSwitchInsn(dflt, keys, labels); + } + + public void visitMultiANewArrayInsn(String desc, int dims) { + mv1.visitMultiANewArrayInsn(desc, dims); + mv2.visitMultiANewArrayInsn(desc, dims); + } + + public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { + mv1.visitTryCatchBlock(start, end, handler, type); + mv2.visitTryCatchBlock(start, end, handler, type); + } + + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { + mv1.visitLocalVariable(name, desc, signature, start, end, index); + mv2.visitLocalVariable(name, desc, signature, start, end, index); + } + + public void visitLineNumber(int line, Label start) { + mv1.visitLineNumber(line, start); + mv2.visitLineNumber(line, start); + } + + public void visitMaxs(int maxStack, int maxLocals) { + mv1.visitMaxs(maxStack, maxLocals); + mv2.visitMaxs(maxStack, maxLocals); + } + + public void visitEnd() { + mv1.visitEnd(); + mv2.visitEnd(); + } + + public void visitParameter(String name, int access) { + mv1.visitParameter(name, access); + mv2.visitParameter(name, access); + } + + public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { + return AnnotationVisitorTee.getInstance(mv1.visitTypeAnnotation(typeRef, typePath, desc, visible), + mv2.visitTypeAnnotation(typeRef, typePath, desc, visible)); + } + + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { + mv1.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); + mv2.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); + } + + public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { + return AnnotationVisitorTee.getInstance(mv1.visitInsnAnnotation(typeRef, typePath, desc, visible), + mv2.visitInsnAnnotation(typeRef, typePath, desc, visible)); + } + + public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { + return AnnotationVisitorTee.getInstance(mv1.visitTryCatchAnnotation(typeRef, typePath, desc, visible), + mv2.visitTryCatchAnnotation(typeRef, typePath, desc, visible)); + } + + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) { + return AnnotationVisitorTee.getInstance(mv1.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, desc, visible), + mv2.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, desc, visible)); + } +} + diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/TransformingClassGenerator.java b/blade-aop/src/main/java/net/sf/cglib/transform/TransformingClassGenerator.java new file mode 100644 index 000000000..386155fee --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/TransformingClassGenerator.java @@ -0,0 +1,35 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import net.sf.cglib.core.ClassGenerator; +import net.sf.cglib.core.Transformer; +import org.objectweb.asm.ClassVisitor; + +public class TransformingClassGenerator implements ClassGenerator { + private ClassGenerator gen; + private ClassTransformer t; + + public TransformingClassGenerator(ClassGenerator gen, ClassTransformer t) { + this.gen = gen; + this.t = t; + } + + public void generateClass(ClassVisitor v) throws Exception { + t.setTarget(v); + gen.generateClass(t); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/TransformingClassLoader.java b/blade-aop/src/main/java/net/sf/cglib/transform/TransformingClassLoader.java new file mode 100644 index 000000000..505f621e2 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/TransformingClassLoader.java @@ -0,0 +1,34 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform; + +import java.util.*; +import net.sf.cglib.core.ClassGenerator; +import org.objectweb.asm.*; + +public class TransformingClassLoader extends AbstractClassLoader { + private ClassTransformerFactory t; + + public TransformingClassLoader(ClassLoader parent, ClassFilter filter, ClassTransformerFactory t) { + super(parent, parent, filter); + this.t = t; + } + + protected ClassGenerator getGenerator(ClassReader r) { + ClassTransformer t2 = (ClassTransformer)t.newInstance(); + return new TransformingClassGenerator(super.getGenerator(r), t2); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/AbstractInterceptFieldCallback.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AbstractInterceptFieldCallback.java new file mode 100644 index 000000000..302bd3567 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AbstractInterceptFieldCallback.java @@ -0,0 +1,42 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +/** + * @author Chris Nokleberg + */ +public class AbstractInterceptFieldCallback implements InterceptFieldCallback { + + public int writeInt(Object obj, String name, int oldValue, int newValue) { return newValue; } + public char writeChar(Object obj, String name, char oldValue, char newValue) { return newValue; } + public byte writeByte(Object obj, String name, byte oldValue, byte newValue) { return newValue; } + public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue) { return newValue; } + public short writeShort(Object obj, String name, short oldValue, short newValue) { return newValue; } + public float writeFloat(Object obj, String name, float oldValue, float newValue) { return newValue; } + public double writeDouble(Object obj, String name, double oldValue, double newValue) { return newValue; } + public long writeLong(Object obj, String name, long oldValue, long newValue) { return newValue; } + public Object writeObject(Object obj, String name, Object oldValue, Object newValue) { return newValue; } + + public int readInt(Object obj, String name, int oldValue) { return oldValue; } + public char readChar(Object obj, String name, char oldValue) { return oldValue; } + public byte readByte(Object obj, String name, byte oldValue) { return oldValue; } + public boolean readBoolean(Object obj, String name, boolean oldValue) { return oldValue; } + public short readShort(Object obj, String name, short oldValue) { return oldValue; } + public float readFloat(Object obj, String name, float oldValue) { return oldValue; } + public double readDouble(Object obj, String name, double oldValue) { return oldValue; } + public long readLong(Object obj, String name, long oldValue) { return oldValue; } + public Object readObject(Object obj, String name, Object oldValue) { return oldValue; } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/AccessFieldTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AccessFieldTransformer.java new file mode 100644 index 000000000..9de468eb4 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AccessFieldTransformer.java @@ -0,0 +1,64 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +import net.sf.cglib.transform.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Type; + +public class AccessFieldTransformer extends ClassEmitterTransformer { + private Callback callback; + + public AccessFieldTransformer(Callback callback) { + this.callback = callback; + } + + public interface Callback { + String getPropertyName(Type owner, String fieldName); + } + + public void declare_field(int access, final String name, Type type, Object value) { + super.declare_field(access, name, type, value); + + String property = TypeUtils.upperFirst(callback.getPropertyName(getClassType(), name)); + if (property != null) { + CodeEmitter e; + e = begin_method(Constants.ACC_PUBLIC, + new Signature("get" + property, + type, + Constants.TYPES_EMPTY), + null); + e.load_this(); + e.getfield(name); + e.return_value(); + e.end_method(); + + e = begin_method(Constants.ACC_PUBLIC, + new Signature("set" + property, + Type.VOID_TYPE, + new Type[]{ type }), + null); + e.load_this(); + e.load_arg(0); + e.putfield(name); + e.return_value(); + e.end_method(); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddDelegateTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddDelegateTransformer.java new file mode 100644 index 000000000..a5423a7c4 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddDelegateTransformer.java @@ -0,0 +1,119 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +import net.sf.cglib.transform.*; +import java.lang.reflect.*; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Type; + +/** + * @author Juozas Baliuka + */ +public class AddDelegateTransformer extends ClassEmitterTransformer { + private static final String DELEGATE = "$CGLIB_DELEGATE"; + private static final Signature CSTRUCT_OBJECT = + TypeUtils.parseSignature("void (Object)"); + + private Class[] delegateIf; + private Class delegateImpl; + private Type delegateType; + + /** Creates a new instance of AddDelegateTransformer */ + public AddDelegateTransformer(Class delegateIf[], Class delegateImpl) { + try { + delegateImpl.getConstructor(new Class[]{ Object.class }); + this.delegateIf = delegateIf; + this.delegateImpl = delegateImpl; + delegateType = Type.getType(delegateImpl); + } catch (NoSuchMethodException e) { + throw new CodeGenerationException(e); + } + } + + public void begin_class(int version, int access, String className, Type superType, Type[] interfaces, String sourceFile) { + + if(!TypeUtils.isInterface(access)){ + + Type[] all = TypeUtils.add(interfaces, TypeUtils.getTypes(delegateIf)); + super.begin_class(version, access, className, superType, all, sourceFile); + + declare_field(Constants.ACC_PRIVATE | Constants.ACC_TRANSIENT, + DELEGATE, + delegateType, + null); + for (int i = 0; i < delegateIf.length; i++) { + Method[] methods = delegateIf[i].getMethods(); + for (int j = 0; j < methods.length; j++) { + if (Modifier.isAbstract(methods[j].getModifiers())) { + addDelegate(methods[j]); + } + } + } + }else{ + super.begin_class(version, access, className, superType, interfaces, sourceFile); + } + } + + public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) { + final CodeEmitter e = super.begin_method(access, sig, exceptions); + if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) { + return new CodeEmitter(e) { + private boolean transformInit = true; + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + if (transformInit && opcode == Constants.INVOKESPECIAL) { + load_this(); + new_instance(delegateType); + dup(); + load_this(); + invoke_constructor(delegateType, CSTRUCT_OBJECT); + putfield(DELEGATE); + transformInit = false; + } + } + }; + } + return e; + } + + private void addDelegate(Method m) { + Method delegate; + try { + delegate = delegateImpl.getMethod(m.getName(), m.getParameterTypes()); + if (!delegate.getReturnType().getName().equals(m.getReturnType().getName())){ + throw new IllegalArgumentException("Invalid delegate signature " + delegate); + } + } catch (NoSuchMethodException e) { + throw new CodeGenerationException(e); + } + + final Signature sig = ReflectUtils.getSignature(m); + Type[] exceptions = TypeUtils.getTypes(m.getExceptionTypes()); + CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, sig, exceptions); + e.load_this(); + e.getfield(DELEGATE); + e.load_args(); + e.invoke_virtual(delegateType, sig); + e.return_value(); + e.end_method(); + } +} + + + diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddInitTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddInitTransformer.java new file mode 100644 index 000000000..a17a9f79f --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddInitTransformer.java @@ -0,0 +1,63 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +import java.lang.reflect.Method; + +import net.sf.cglib.core.CodeEmitter; +import net.sf.cglib.core.Constants; +import net.sf.cglib.core.MethodInfo; +import net.sf.cglib.core.ReflectUtils; +import net.sf.cglib.core.Signature; +import net.sf.cglib.transform.ClassEmitterTransformer; + +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Type; + +/** + * @author Mark Hobson + */ +public class AddInitTransformer extends ClassEmitterTransformer { + private MethodInfo info; + + public AddInitTransformer(Method method) { + info = ReflectUtils.getMethodInfo(method); + + Type[] types = info.getSignature().getArgumentTypes(); + if (types.length != 1 || + !types[0].equals(Constants.TYPE_OBJECT) || + !info.getSignature().getReturnType().equals(Type.VOID_TYPE)) { + throw new IllegalArgumentException(method + " illegal signature"); + } + } + + public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) { + final CodeEmitter emitter = super.begin_method(access, sig, exceptions); + if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) { + return new CodeEmitter(emitter) { + public void visitInsn(int opcode) { + if (opcode == Constants.RETURN) { + load_this(); + invoke(info); + } + super.visitInsn(opcode); + } + }; + } + return emitter; + } +} + diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddPropertyTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddPropertyTransformer.java new file mode 100644 index 000000000..e13071acb --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddPropertyTransformer.java @@ -0,0 +1,47 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +import net.sf.cglib.transform.*; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.Type; + +public class AddPropertyTransformer extends ClassEmitterTransformer { + private final String[] names; + private final Type[] types; + + public AddPropertyTransformer(Map props) { + int size = props.size(); + names = (String[])props.keySet().toArray(new String[size]); + types = new Type[size]; + for (int i = 0; i < size; i++) { + types[i] = (Type)props.get(names[i]); + } + } + + public AddPropertyTransformer(String[] names, Type[] types) { + this.names = names; + this.types = types; + } + + public void end_class() { + if (!TypeUtils.isAbstract(getAccess())) { + EmitUtils.add_properties(this, names, types); + } + super.end_class(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddStaticInitTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddStaticInitTransformer.java new file mode 100644 index 000000000..94a2eaebf --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/AddStaticInitTransformer.java @@ -0,0 +1,49 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +import java.lang.reflect.Method; +import net.sf.cglib.core.*; +import net.sf.cglib.transform.*; +import org.objectweb.asm.Type; + +/** + * @author Juozas Baliuka, Chris Nokleberg + */ +public class AddStaticInitTransformer extends ClassEmitterTransformer { + private MethodInfo info; + + public AddStaticInitTransformer(Method classInit) { + info = ReflectUtils.getMethodInfo(classInit); + if (!TypeUtils.isStatic(info.getModifiers())) { + throw new IllegalArgumentException(classInit + " is not static"); + } + Type[] types = info.getSignature().getArgumentTypes(); + if (types.length != 1 || + !types[0].equals(Constants.TYPE_CLASS) || + !info.getSignature().getReturnType().equals(Type.VOID_TYPE)) { + throw new IllegalArgumentException(classInit + " illegal signature"); + } + } + + protected void init() { + if (!TypeUtils.isInterface(getAccess())) { + CodeEmitter e = getStaticHook(); + EmitUtils.load_class_this(e); + e.invoke(info); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/FieldProvider.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/FieldProvider.java new file mode 100644 index 000000000..d1eaace29 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/FieldProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +public interface FieldProvider { + + String[] getFieldNames(); + + Class[] getFieldTypes(); + + void setField(int index, Object value); + + Object getField(int index); + + + void setField(String name, Object value); + + Object getField(String name); + + +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/FieldProviderTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/FieldProviderTransformer.java new file mode 100644 index 000000000..90c9d1bd8 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/FieldProviderTransformer.java @@ -0,0 +1,208 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +import net.sf.cglib.transform.*; +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +public class FieldProviderTransformer extends ClassEmitterTransformer { + + private static final String FIELD_NAMES = "CGLIB$FIELD_NAMES"; + private static final String FIELD_TYPES = "CGLIB$FIELD_TYPES"; + + private static final Type FIELD_PROVIDER = + TypeUtils.parseType("net.sf.cglib.transform.impl.FieldProvider"); + private static final Type ILLEGAL_ARGUMENT_EXCEPTION = + TypeUtils.parseType("IllegalArgumentException"); + private static final Signature PROVIDER_GET = + TypeUtils.parseSignature("Object getField(String)"); + private static final Signature PROVIDER_SET = + TypeUtils.parseSignature("void setField(String, Object)"); + private static final Signature PROVIDER_SET_BY_INDEX = + TypeUtils.parseSignature("void setField(int, Object)"); + private static final Signature PROVIDER_GET_BY_INDEX = + TypeUtils.parseSignature("Object getField(int)"); + private static final Signature PROVIDER_GET_TYPES = + TypeUtils.parseSignature("Class[] getFieldTypes()"); + private static final Signature PROVIDER_GET_NAMES = + TypeUtils.parseSignature("String[] getFieldNames()"); + + private int access; + private Map fields; + + public void begin_class(int version, int access, String className, Type superType, Type[] interfaces, String sourceFile) { + if (!TypeUtils.isAbstract(access)) { + interfaces = TypeUtils.add(interfaces, FIELD_PROVIDER); + } + this.access = access; + fields = new HashMap(); + super.begin_class(version, access, className, superType, interfaces, sourceFile); + } + + public void declare_field(int access, String name, Type type, Object value) { + super.declare_field(access, name, type, value); + + if (!TypeUtils.isStatic(access)) { + fields.put(name, type); + } + } + + public void end_class() { + if (!TypeUtils.isInterface(access)) { + try { + generate(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new CodeGenerationException(e); + } + } + super.end_class(); + } + + private void generate() throws Exception { + final String[] names = (String[])fields.keySet().toArray(new String[fields.size()]); + + int indexes[] = new int[names.length]; + for (int i = 0; i < indexes.length; i++) { + indexes[i] = i; + } + + super.declare_field(Constants.PRIVATE_FINAL_STATIC, FIELD_NAMES, Constants.TYPE_STRING_ARRAY, null); + super.declare_field(Constants.PRIVATE_FINAL_STATIC, FIELD_TYPES, Constants.TYPE_CLASS_ARRAY, null); + + // use separate methods here because each process switch inner class needs a final CodeEmitter + initFieldProvider(names); + getNames(); + getTypes(); + getField(names); + setField(names); + setByIndex(names, indexes); + getByIndex(names, indexes); + } + + private void initFieldProvider(String[] names) { + CodeEmitter e = getStaticHook(); + EmitUtils.push_object(e, names); + e.putstatic(getClassType(), FIELD_NAMES, Constants.TYPE_STRING_ARRAY); + + e.push(names.length); + e.newarray(Constants.TYPE_CLASS); + e.dup(); + for(int i = 0; i < names.length; i++ ){ + e.dup(); + e.push(i); + Type type = (Type)fields.get(names[i]); + EmitUtils.load_class(e, type); + e.aastore(); + } + e.putstatic(getClassType(), FIELD_TYPES, Constants.TYPE_CLASS_ARRAY); + } + + private void getNames() { + CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_NAMES, null); + e.getstatic(getClassType(), FIELD_NAMES, Constants.TYPE_STRING_ARRAY); + e.return_value(); + e.end_method(); + } + + private void getTypes() { + CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_TYPES, null); + e.getstatic(getClassType(), FIELD_TYPES, Constants.TYPE_CLASS_ARRAY); + e.return_value(); + e.end_method(); + } + + private void setByIndex(final String[] names, final int[] indexes) throws Exception { + final CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_SET_BY_INDEX, null); + e.load_this(); + e.load_arg(1); + e.load_arg(0); + e.process_switch(indexes, new ProcessSwitchCallback() { + public void processCase(int key, Label end) throws Exception { + Type type = (Type)fields.get(names[key]); + e.unbox(type); + e.putfield(names[key]); + e.return_value(); + } + public void processDefault() throws Exception { + e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field index"); + } + }); + e.end_method(); + } + + private void getByIndex(final String[] names, final int[] indexes) throws Exception { + final CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_BY_INDEX, null); + e.load_this(); + e.load_arg(0); + e.process_switch(indexes, new ProcessSwitchCallback() { + public void processCase(int key, Label end) throws Exception { + Type type = (Type)fields.get(names[key]); + e.getfield(names[key]); + e.box(type); + e.return_value(); + } + public void processDefault() throws Exception { + e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field index"); + } + }); + e.end_method(); + } + + // TODO: if this is used to enhance class files SWITCH_STYLE_TRIE should be used + // to avoid JVM hashcode implementation incompatibilities + private void getField(String[] names) throws Exception { + final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, PROVIDER_GET, null); + e.load_this(); + e.load_arg(0); + EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { + public void processCase(Object key, Label end) { + Type type = (Type)fields.get(key); + e.getfield((String)key); + e.box(type); + e.return_value(); + } + public void processDefault() { + e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field name"); + } + }); + e.end_method(); + } + + private void setField(String[] names) throws Exception { + final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, PROVIDER_SET, null); + e.load_this(); + e.load_arg(1); + e.load_arg(0); + EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { + public void processCase(Object key, Label end) { + Type type = (Type)fields.get(key); + e.unbox(type); + e.putfield((String)key); + e.return_value(); + } + public void processDefault() { + e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field name"); + } + }); + e.end_method(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldCallback.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldCallback.java new file mode 100644 index 000000000..b53461b54 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldCallback.java @@ -0,0 +1,42 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +/** + * @author Juozas Baliuka + */ +public interface InterceptFieldCallback { + + int writeInt(Object obj, String name, int oldValue, int newValue); + char writeChar(Object obj, String name, char oldValue, char newValue); + byte writeByte(Object obj, String name, byte oldValue, byte newValue); + boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue); + short writeShort(Object obj, String name, short oldValue, short newValue); + float writeFloat(Object obj, String name, float oldValue, float newValue); + double writeDouble(Object obj, String name, double oldValue, double newValue); + long writeLong(Object obj, String name, long oldValue, long newValue); + Object writeObject(Object obj, String name, Object oldValue, Object newValue); + + int readInt(Object obj, String name, int oldValue); + char readChar(Object obj, String name, char oldValue); + byte readByte(Object obj, String name, byte oldValue); + boolean readBoolean(Object obj, String name, boolean oldValue); + short readShort(Object obj, String name, short oldValue); + float readFloat(Object obj, String name, float oldValue); + double readDouble(Object obj, String name, double oldValue); + long readLong(Object obj, String name, long oldValue); + Object readObject(Object obj, String name, Object oldValue); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldEnabled.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldEnabled.java new file mode 100644 index 000000000..a4119e278 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldEnabled.java @@ -0,0 +1,21 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +public interface InterceptFieldEnabled { + void setInterceptFieldCallback(InterceptFieldCallback callback); + InterceptFieldCallback getInterceptFieldCallback(); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldFilter.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldFilter.java new file mode 100644 index 000000000..0259dba39 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldFilter.java @@ -0,0 +1,23 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +import org.objectweb.asm.Type; + +public interface InterceptFieldFilter { + boolean acceptRead(Type owner, String name); + boolean acceptWrite(Type owner, String name); +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldTransformer.java new file mode 100644 index 000000000..c61521010 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/InterceptFieldTransformer.java @@ -0,0 +1,210 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +import net.sf.cglib.transform.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +/** + * @author Juozas Baliuka, Chris Nokleberg + */ +public class InterceptFieldTransformer extends ClassEmitterTransformer { + private static final String CALLBACK_FIELD = "$CGLIB_READ_WRITE_CALLBACK"; + private static final Type CALLBACK = + TypeUtils.parseType("net.sf.cglib.transform.impl.InterceptFieldCallback"); + private static final Type ENABLED = + TypeUtils.parseType("net.sf.cglib.transform.impl.InterceptFieldEnabled"); + private static final Signature ENABLED_SET = + new Signature("setInterceptFieldCallback", Type.VOID_TYPE, new Type[]{ CALLBACK }); + private static final Signature ENABLED_GET = + new Signature("getInterceptFieldCallback", CALLBACK, new Type[0]); + + private InterceptFieldFilter filter; + + public InterceptFieldTransformer(InterceptFieldFilter filter) { + this.filter = filter; + } + + public void begin_class(int version, int access, String className, Type superType, Type[] interfaces, String sourceFile) { + if (!TypeUtils.isInterface(access)) { + super.begin_class(version, access, className, superType, TypeUtils.add(interfaces, ENABLED), sourceFile); + + super.declare_field(Constants.ACC_PRIVATE | Constants.ACC_TRANSIENT, + CALLBACK_FIELD, + CALLBACK, + null); + + CodeEmitter e; + e = super.begin_method(Constants.ACC_PUBLIC, ENABLED_GET, null); + e.load_this(); + e.getfield(CALLBACK_FIELD); + e.return_value(); + e.end_method(); + + e = super.begin_method(Constants.ACC_PUBLIC, ENABLED_SET, null); + e.load_this(); + e.load_arg(0); + e.putfield(CALLBACK_FIELD); + e.return_value(); + e.end_method(); + } else { + super.begin_class(version, access, className, superType, interfaces, sourceFile); + } + } + + public void declare_field(int access, String name, Type type, Object value) { + super.declare_field(access, name, type, value); + if (!TypeUtils.isStatic(access)) { + if (filter.acceptRead(getClassType(), name)) { + addReadMethod(name, type); + } + if (filter.acceptWrite(getClassType(), name)) { + addWriteMethod(name, type); + } + } + } + + private void addReadMethod(String name, Type type) { + CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, + readMethodSig(name, type.getDescriptor()), + null); + e.load_this(); + e.getfield(name); + e.load_this(); + e.invoke_interface(ENABLED,ENABLED_GET); + Label intercept = e.make_label(); + e.ifnonnull(intercept); + e.return_value(); + + e.mark(intercept); + Local result = e.make_local(type); + e.store_local(result); + e.load_this(); + e.invoke_interface(ENABLED,ENABLED_GET); + e.load_this(); + e.push(name); + e.load_local(result); + e.invoke_interface(CALLBACK, readCallbackSig(type)); + if (!TypeUtils.isPrimitive(type)) { + e.checkcast(type); + } + e.return_value(); + e.end_method(); + } + + private void addWriteMethod(String name, Type type) { + CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, + writeMethodSig(name, type.getDescriptor()), + null); + e.load_this(); + e.dup(); + e.invoke_interface(ENABLED,ENABLED_GET); + Label skip = e.make_label(); + e.ifnull(skip); + + e.load_this(); + e.invoke_interface(ENABLED,ENABLED_GET); + e.load_this(); + e.push(name); + e.load_this(); + e.getfield(name); + e.load_arg(0); + e.invoke_interface(CALLBACK, writeCallbackSig(type)); + if (!TypeUtils.isPrimitive(type)) { + e.checkcast(type); + } + Label go = e.make_label(); + e.goTo(go); + e.mark(skip); + e.load_arg(0); + e.mark(go); + e.putfield(name); + e.return_value(); + e.end_method(); + } + + public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) { + return new CodeEmitter(super.begin_method(access, sig, exceptions)) { + public void visitFieldInsn(int opcode, String owner, String name, String desc) { + Type towner = TypeUtils.fromInternalName(owner); + switch (opcode) { + case Constants.GETFIELD: + if (filter.acceptRead(towner, name)) { + helper(towner, readMethodSig(name, desc)); + return; + } + break; + case Constants.PUTFIELD: + if (filter.acceptWrite(towner, name)) { + helper(towner, writeMethodSig(name, desc)); + return; + } + break; + } + super.visitFieldInsn(opcode, owner, name, desc); + } + + private void helper(Type owner, Signature sig) { + invoke_virtual(owner, sig); + } + }; + } + + private static Signature readMethodSig(String name, String desc) { + return new Signature("$cglib_read_" + name, "()" + desc); + } + + private static Signature writeMethodSig(String name, String desc) { + return new Signature("$cglib_write_" + name, "(" + desc + ")V"); + } + + private static Signature readCallbackSig(Type type) { + Type remap = remap(type); + return new Signature("read" + callbackName(remap), + remap, + new Type[]{ Constants.TYPE_OBJECT, + Constants.TYPE_STRING, + remap }); + } + + private static Signature writeCallbackSig(Type type) { + Type remap = remap(type); + return new Signature("write" + callbackName(remap), + remap, + new Type[]{ Constants.TYPE_OBJECT, + Constants.TYPE_STRING, + remap, + remap }); + } + + private static Type remap(Type type) { + switch (type.getSort()) { + case Type.OBJECT: + case Type.ARRAY: + return Constants.TYPE_OBJECT; + default: + return type; + } + } + + private static String callbackName(Type type) { + return (type == Constants.TYPE_OBJECT) ? + "Object" : + TypeUtils.upperFirst(TypeUtils.getClassName(type)); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/UndeclaredThrowableStrategy.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/UndeclaredThrowableStrategy.java new file mode 100644 index 000000000..aaf3789dd --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/UndeclaredThrowableStrategy.java @@ -0,0 +1,61 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +import net.sf.cglib.core.ClassGenerator; +import net.sf.cglib.core.DefaultGeneratorStrategy; +import net.sf.cglib.core.GeneratorStrategy; +import net.sf.cglib.core.TypeUtils; +import net.sf.cglib.transform.ClassTransformer; +import net.sf.cglib.transform.MethodFilter; +import net.sf.cglib.transform.MethodFilterTransformer; +import net.sf.cglib.transform.TransformingClassGenerator; + +/** + * A {@link GeneratorStrategy} suitable for use with {@link net.sf.cglib.Enhancer} which + * causes all undeclared exceptions thrown from within a proxied method to be wrapped + * in an alternative exception of your choice. + */ +public class UndeclaredThrowableStrategy extends DefaultGeneratorStrategy { + + + private Class wrapper; + + /** + * Create a new instance of this strategy. + * @param wrapper a class which extends either directly or + * indirectly from Throwable and which has at least one + * constructor that takes a single argument of type + * Throwable, for example + * java.lang.reflect.UndeclaredThrowableException.class + */ + public UndeclaredThrowableStrategy(Class wrapper) { + this.wrapper = wrapper; + } + + private static final MethodFilter TRANSFORM_FILTER = new MethodFilter() { + public boolean accept(int access, String name, String desc, String signature, String[] exceptions) { + return !TypeUtils.isPrivate(access) && name.indexOf('$') < 0; + } + }; + + protected ClassGenerator transform(ClassGenerator cg) throws Exception { + ClassTransformer tr = new UndeclaredThrowableTransformer(wrapper); + tr = new MethodFilterTransformer(TRANSFORM_FILTER, tr); + return new TransformingClassGenerator(cg, tr); + } +} + diff --git a/blade-aop/src/main/java/net/sf/cglib/transform/impl/UndeclaredThrowableTransformer.java b/blade-aop/src/main/java/net/sf/cglib/transform/impl/UndeclaredThrowableTransformer.java new file mode 100644 index 000000000..6369abae4 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/transform/impl/UndeclaredThrowableTransformer.java @@ -0,0 +1,60 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.transform.impl; + +import java.lang.reflect.Constructor; +import net.sf.cglib.core.*; +import net.sf.cglib.transform.*; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Type; +import org.objectweb.asm.ClassVisitor; + +public class UndeclaredThrowableTransformer extends ClassEmitterTransformer { + private Type wrapper; + + public UndeclaredThrowableTransformer(Class wrapper) { + this.wrapper = Type.getType(wrapper); + boolean found = false; + Constructor[] cstructs = wrapper.getConstructors(); + for (int i = 0; i < cstructs.length; i++) { + Class[] types = cstructs[i].getParameterTypes(); + if (types.length == 1 && types[0].equals(Throwable.class)) { + found = true; + break; + } + } + if (!found) + throw new IllegalArgumentException(wrapper + " does not have a single-arg constructor that takes a Throwable"); + } + + public CodeEmitter begin_method(int access, final Signature sig, final Type[] exceptions) { + CodeEmitter e = super.begin_method(access, sig, exceptions); + if (TypeUtils.isAbstract(access) || sig.equals(Constants.SIG_STATIC)) { + return e; + } + return new CodeEmitter(e) { + private Block handler; + /* init */ { + handler = begin_block(); + } + public void visitMaxs(int maxStack, int maxLocals) { + handler.end(); + EmitUtils.wrap_undeclared_throwable(this, handler, exceptions, wrapper); + super.visitMaxs(maxStack, maxLocals); + } + }; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/util/ParallelSorter.java b/blade-aop/src/main/java/net/sf/cglib/util/ParallelSorter.java new file mode 100644 index 000000000..04574a315 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/util/ParallelSorter.java @@ -0,0 +1,294 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.util; + +import java.lang.reflect.*; +import java.util.Comparator; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; + +/** + * For the efficient sorting of multiple arrays in parallel. + *

+ * Given two arrays of equal length and varying types, the standard + * technique for sorting them in parallel is to create a new temporary + * object for each row, store the objects in a temporary array, sort the + * array using a custom comparator, and the extract the original values + * back into their respective arrays. This is wasteful in both time and + * memory. + *

+ * This class generates bytecode customized to the particular set of + * arrays you need to sort, in such a way that both arrays are sorted + * in-place, simultaneously. + *

+ * Two sorting algorithms are provided. + * Quicksort is best when you only need to sort by a single column, as + * it requires very few comparisons and swaps. Mergesort is best used + * when sorting multiple columns, as it is a "stable" sort--that is, it + * does not affect the relative order of equal objects from previous sorts. + *

+ * The mergesort algorithm here is an "in-place" variant, which while + * slower, does not require a temporary array. + * + * @author Chris Nokleberg + */ +abstract public class ParallelSorter extends SorterTemplate { + protected Object[] a; + private Comparer comparer; + + protected ParallelSorter() { + } + + abstract public ParallelSorter newInstance(Object[] arrays); + + /** + * Create a new ParallelSorter object for a set of arrays. You may + * sort the arrays multiple times via the same ParallelSorter object. + * @param arrays An array of arrays to sort. The arrays may be a mix + * of primitive and non-primitive types, but should all be the same + * length. + * @param loader ClassLoader for generated class, uses "current" if null + */ + public static ParallelSorter create(Object[] arrays) { + Generator gen = new Generator(); + gen.setArrays(arrays); + return gen.create(); + } + + private int len() { + return ((Object[])a[0]).length; + } + + /** + * Sort the arrays using the quicksort algorithm. + * @param index array (column) to sort by + */ + public void quickSort(int index) { + quickSort(index, 0, len(), null); + } + + /** + * Sort the arrays using the quicksort algorithm. + * @param index array (column) to sort by + * @param lo starting array index (row), inclusive + * @param hi ending array index (row), exclusive + */ + public void quickSort(int index, int lo, int hi) { + quickSort(index, lo, hi, null); + } + + /** + * Sort the arrays using the quicksort algorithm. + * @param index array (column) to sort by + * @param cmp Comparator to use if the specified column is non-primitive + */ + public void quickSort(int index, Comparator cmp) { + quickSort(index, 0, len(), cmp); + } + + /** + * Sort the arrays using the quicksort algorithm. + * @param index array (column) to sort by + * @param lo starting array index (row), inclusive + * @param hi ending array index (row), exclusive + * @param cmp Comparator to use if the specified column is non-primitive + */ + public void quickSort(int index, int lo, int hi, Comparator cmp) { + chooseComparer(index, cmp); + super.quickSort(lo, hi - 1); + } + + /** + * @param index array (column) to sort by + */ + public void mergeSort(int index) { + mergeSort(index, 0, len(), null); + } + + /** + * Sort the arrays using an in-place merge sort. + * @param index array (column) to sort by + * @param lo starting array index (row), inclusive + * @param hi ending array index (row), exclusive + */ + public void mergeSort(int index, int lo, int hi) { + mergeSort(index, lo, hi, null); + } + + /** + * Sort the arrays using an in-place merge sort. + * @param index array (column) to sort by + * @param lo starting array index (row), inclusive + * @param hi ending array index (row), exclusive + */ + public void mergeSort(int index, Comparator cmp) { + mergeSort(index, 0, len(), cmp); + } + + /** + * Sort the arrays using an in-place merge sort. + * @param index array (column) to sort by + * @param lo starting array index (row), inclusive + * @param hi ending array index (row), exclusive + * @param cmp Comparator to use if the specified column is non-primitive + */ + public void mergeSort(int index, int lo, int hi, Comparator cmp) { + chooseComparer(index, cmp); + super.mergeSort(lo, hi - 1); + } + + private void chooseComparer(int index, Comparator cmp) { + Object array = a[index]; + Class type = array.getClass().getComponentType(); + if (type.equals(Integer.TYPE)) { + comparer = new IntComparer((int[])array); + } else if (type.equals(Long.TYPE)) { + comparer = new LongComparer((long[])array); + } else if (type.equals(Double.TYPE)) { + comparer = new DoubleComparer((double[])array); + } else if (type.equals(Float.TYPE)) { + comparer = new FloatComparer((float[])array); + } else if (type.equals(Short.TYPE)) { + comparer = new ShortComparer((short[])array); + } else if (type.equals(Byte.TYPE)) { + comparer = new ByteComparer((byte[])array); + } else if (cmp != null) { + comparer = new ComparatorComparer((Object[])array, cmp); + } else { + comparer = new ObjectComparer((Object[])array); + } + } + + protected int compare(int i, int j) { + return comparer.compare(i, j); + } + + interface Comparer { + int compare(int i, int j); + } + + static class ComparatorComparer implements Comparer { + private Object[] a; + private Comparator cmp; + + public ComparatorComparer(Object[] a, Comparator cmp) { + this.a = a; + this.cmp = cmp; + } + + public int compare(int i, int j) { + return cmp.compare(a[i], a[j]); + } + } + + static class ObjectComparer implements Comparer { + private Object[] a; + public ObjectComparer(Object[] a) { this.a = a; } + public int compare(int i, int j) { + return ((Comparable)a[i]).compareTo(a[j]); + } + } + + static class IntComparer implements Comparer { + private int[] a; + public IntComparer(int[] a) { this.a = a; } + public int compare(int i, int j) { return a[i] - a[j]; } + } + + static class LongComparer implements Comparer { + private long[] a; + public LongComparer(long[] a) { this.a = a; } + public int compare(int i, int j) { + long vi = a[i]; + long vj = a[j]; + return (vi == vj) ? 0 : (vi > vj) ? 1 : -1; + } + } + + static class FloatComparer implements Comparer { + private float[] a; + public FloatComparer(float[] a) { this.a = a; } + public int compare(int i, int j) { + float vi = a[i]; + float vj = a[j]; + return (vi == vj) ? 0 : (vi > vj) ? 1 : -1; + } + } + + static class DoubleComparer implements Comparer { + private double[] a; + public DoubleComparer(double[] a) { this.a = a; } + public int compare(int i, int j) { + double vi = a[i]; + double vj = a[j]; + return (vi == vj) ? 0 : (vi > vj) ? 1 : -1; + } + } + + static class ShortComparer implements Comparer { + private short[] a; + public ShortComparer(short[] a) { this.a = a; } + public int compare(int i, int j) { return a[i] - a[j]; } + } + + static class ByteComparer implements Comparer { + private byte[] a; + public ByteComparer(byte[] a) { this.a = a; } + public int compare(int i, int j) { return a[i] - a[j]; } + } + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(ParallelSorter.class.getName()); + + private Object[] arrays; + + public Generator() { + super(SOURCE); + } + + protected ClassLoader getDefaultClassLoader() { + return null; // TODO + } + + public void setArrays(Object[] arrays) { + this.arrays = arrays; + } + + public ParallelSorter create() { + return (ParallelSorter)super.create(ClassesKey.create(arrays)); + } + + public void generateClass(ClassVisitor v) throws Exception { + if (arrays.length == 0) { + throw new IllegalArgumentException("No arrays specified to sort"); + } + for (int i = 0; i < arrays.length; i++) { + if (!arrays[i].getClass().isArray()) { + throw new IllegalArgumentException(arrays[i].getClass() + " is not an array"); + } + } + new ParallelSorterEmitter(v, getClassName(), arrays); + } + + protected Object firstInstance(Class type) { + return ((ParallelSorter)ReflectUtils.newInstance(type)).newInstance(arrays); + } + + protected Object nextInstance(Object instance) { + return ((ParallelSorter)instance).newInstance(arrays); + } + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/util/ParallelSorterEmitter.java b/blade-aop/src/main/java/net/sf/cglib/util/ParallelSorterEmitter.java new file mode 100644 index 000000000..06351a9cf --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/util/ParallelSorterEmitter.java @@ -0,0 +1,100 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.util; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Type; + +class ParallelSorterEmitter extends ClassEmitter { + private static final Type PARALLEL_SORTER = + TypeUtils.parseType("net.sf.cglib.util.ParallelSorter"); + private static final Signature CSTRUCT_OBJECT_ARRAY = + TypeUtils.parseConstructor("Object[]"); + private static final Signature NEW_INSTANCE = + new Signature("newInstance", PARALLEL_SORTER, new Type[]{ Constants.TYPE_OBJECT_ARRAY }); + private static final Signature SWAP = + TypeUtils.parseSignature("void swap(int, int)"); + + public ParallelSorterEmitter(ClassVisitor v, String className, Object[] arrays) { + super(v); + begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, PARALLEL_SORTER, null, Constants.SOURCE_FILE); + EmitUtils.null_constructor(this); + EmitUtils.factory_method(this, NEW_INSTANCE); + generateConstructor(arrays); + generateSwap(arrays); + end_class(); + } + + private String getFieldName(int index) { + return "FIELD_" + index; + } + + private void generateConstructor(Object[] arrays) { + CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null); + e.load_this(); + e.super_invoke_constructor(); + e.load_this(); + e.load_arg(0); + e.super_putfield("a", Constants.TYPE_OBJECT_ARRAY); + for (int i = 0; i < arrays.length; i++) { + Type type = Type.getType(arrays[i].getClass()); + declare_field(Constants.ACC_PRIVATE, getFieldName(i), type, null); + e.load_this(); + e.load_arg(0); + e.push(i); + e.aaload(); + e.checkcast(type); + e.putfield(getFieldName(i)); + } + e.return_value(); + e.end_method(); + } + + private void generateSwap(final Object[] arrays) { + CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SWAP, null); + for (int i = 0; i < arrays.length; i++) { + Type type = Type.getType(arrays[i].getClass()); + Type component = TypeUtils.getComponentType(type); + Local T = e.make_local(type); + + e.load_this(); + e.getfield(getFieldName(i)); + e.store_local(T); + + e.load_local(T); + e.load_arg(0); + + e.load_local(T); + e.load_arg(1); + e.array_load(component); + + e.load_local(T); + e.load_arg(1); + + e.load_local(T); + e.load_arg(0); + e.array_load(component); + + e.array_store(component); + e.array_store(component); + } + e.return_value(); + e.end_method(); + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/util/SorterTemplate.java b/blade-aop/src/main/java/net/sf/cglib/util/SorterTemplate.java new file mode 100644 index 000000000..b5c95f53c --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/util/SorterTemplate.java @@ -0,0 +1,173 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.util; + +import java.util.*; + +abstract class SorterTemplate { + private static final int MERGESORT_THRESHOLD = 12; + private static final int QUICKSORT_THRESHOLD = 7; + + abstract protected void swap(int i, int j); + abstract protected int compare(int i, int j); + + protected void quickSort(int lo, int hi) { + quickSortHelper(lo, hi); + insertionSort(lo, hi); + } + + private void quickSortHelper(int lo, int hi) { + for (;;) { + int diff = hi - lo; + if (diff <= QUICKSORT_THRESHOLD) { + break; + } + int i = (hi + lo) / 2; + if (compare(lo, i) > 0) { + swap(lo, i); + } + if (compare(lo, hi) > 0) { + swap(lo, hi); + } + if (compare(i, hi) > 0) { + swap(i, hi); + } + int j = hi - 1; + swap(i, j); + i = lo; + int v = j; + for (;;) { + while (compare(++i, v) < 0) { + /* nothing */; + } + while (compare(--j, v) > 0) { + /* nothing */; + } + if (j < i) { + break; + } + swap(i, j); + } + swap(i, hi - 1); + if (j - lo <= hi - i + 1) { + quickSortHelper(lo, j); + lo = i + 1; + } else { + quickSortHelper(i + 1, hi); + hi = j; + } + } + } + + private void insertionSort(int lo, int hi) { + for (int i = lo + 1 ; i <= hi; i++) { + for (int j = i; j > lo; j--) { + if (compare(j - 1, j) > 0) { + swap(j - 1, j); + } else { + break; + } + } + } + } + + protected void mergeSort(int lo, int hi) { + int diff = hi - lo; + if (diff <= MERGESORT_THRESHOLD) { + insertionSort(lo, hi); + return; + } + int mid = lo + diff / 2; + mergeSort(lo, mid); + mergeSort(mid, hi); + merge(lo, mid, hi, mid - lo, hi - mid); + } + + private void merge(int lo, int pivot, int hi, int len1, int len2) { + if (len1 == 0 || len2 == 0) { + return; + } + if (len1 + len2 == 2) { + if (compare(pivot, lo) < 0) { + swap(pivot, lo); + } + return; + } + int first_cut, second_cut; + int len11, len22; + if (len1 > len2) { + len11 = len1 / 2; + first_cut = lo + len11; + second_cut = lower(pivot, hi, first_cut); + len22 = second_cut - pivot; + } else { + len22 = len2 / 2; + second_cut = pivot + len22; + first_cut = upper(lo, pivot, second_cut); + len11 = first_cut - lo; + } + rotate(first_cut, pivot, second_cut); + int new_mid = first_cut + len22; + merge(lo, first_cut, new_mid, len11, len22); + merge(new_mid, second_cut, hi, len1 - len11, len2 - len22); + } + + private void rotate(int lo, int mid, int hi) { + int lot = lo; + int hit = mid - 1; + while (lot < hit) { + swap(lot++, hit--); + } + lot = mid; hit = hi - 1; + while (lot < hit) { + swap(lot++, hit--); + } + lot = lo; hit = hi - 1; + while (lot < hit) { + swap(lot++, hit--); + } + } + + private int lower(int lo, int hi, int val) { + int len = hi - lo; + while (len > 0) { + int half = len / 2; + int mid= lo + half; + if (compare(mid, val) < 0) { + lo = mid + 1; + len = len - half -1; + } else { + len = half; + } + } + return lo; + } + + private int upper(int lo, int hi, int val) { + int len = hi - lo; + while (len > 0) { + int half = len / 2; + int mid = lo + half; + if (compare(val, mid) < 0) { + len = half; + } else { + lo = mid + 1; + len = len - half -1; + } + } + return lo; + } +} diff --git a/blade-aop/src/main/java/net/sf/cglib/util/StringSwitcher.java b/blade-aop/src/main/java/net/sf/cglib/util/StringSwitcher.java new file mode 100644 index 000000000..df6248822 --- /dev/null +++ b/blade-aop/src/main/java/net/sf/cglib/util/StringSwitcher.java @@ -0,0 +1,154 @@ +/* + * Copyright 2003 The Apache Software Foundation + * + * 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 net.sf.cglib.util; + +import java.util.*; +import net.sf.cglib.core.*; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +/** + * This class implements a simple String->int mapping for a fixed set of keys. + */ +abstract public class StringSwitcher { + private static final Type STRING_SWITCHER = + TypeUtils.parseType("net.sf.cglib.util.StringSwitcher"); + private static final Signature INT_VALUE = + TypeUtils.parseSignature("int intValue(String)"); + private static final StringSwitcherKey KEY_FACTORY = + (StringSwitcherKey)KeyFactory.create(StringSwitcherKey.class); + + interface StringSwitcherKey { + public Object newInstance(String[] strings, int[] ints, boolean fixedInput); + } + + /** + * Helper method to create a StringSwitcher. + * For finer control over the generated instance, use a new instance of StringSwitcher.Generator + * instead of this static method. + * @param strings the array of String keys; must be the same length as the value array + * @param ints the array of integer results; must be the same length as the key array + * @param fixedInput if false, an unknown key will be returned from {@link #intValue} as -1; if true, + * the result will be undefined, and the resulting code will be faster + */ + public static StringSwitcher create(String[] strings, int[] ints, boolean fixedInput) { + Generator gen = new Generator(); + gen.setStrings(strings); + gen.setInts(ints); + gen.setFixedInput(fixedInput); + return gen.create(); + } + + protected StringSwitcher() { + } + + /** + * Return the integer associated with the given key. + * @param s the key + * @return the associated integer value, or -1 if the key is unknown (unless + * fixedInput was specified when this StringSwitcher was created, + * in which case the return value for an unknown key is undefined) + */ + abstract public int intValue(String s); + + public static class Generator extends AbstractClassGenerator { + private static final Source SOURCE = new Source(StringSwitcher.class.getName()); + + private String[] strings; + private int[] ints; + private boolean fixedInput; + + public Generator() { + super(SOURCE); + } + + /** + * Set the array of recognized Strings. + * @param strings the array of String keys; must be the same length as the value array + * @see #setInts + */ + public void setStrings(String[] strings) { + this.strings = strings; + } + + /** + * Set the array of integer results. + * @param ints the array of integer results; must be the same length as the key array + * @see #setStrings + */ + public void setInts(int[] ints) { + this.ints = ints; + } + + /** + * Configure how unknown String keys will be handled. + * @param fixedInput if false, an unknown key will be returned from {@link #intValue} as -1; if true, + * the result will be undefined, and the resulting code will be faster + */ + public void setFixedInput(boolean fixedInput) { + this.fixedInput = fixedInput; + } + + protected ClassLoader getDefaultClassLoader() { + return getClass().getClassLoader(); + } + + /** + * Generate the StringSwitcher. + */ + public StringSwitcher create() { + setNamePrefix(StringSwitcher.class.getName()); + Object key = KEY_FACTORY.newInstance(strings, ints, fixedInput); + return (StringSwitcher)super.create(key); + } + + public void generateClass(ClassVisitor v) throws Exception { + ClassEmitter ce = new ClassEmitter(v); + ce.begin_class(Constants.V1_2, + Constants.ACC_PUBLIC, + getClassName(), + STRING_SWITCHER, + null, + Constants.SOURCE_FILE); + EmitUtils.null_constructor(ce); + final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, INT_VALUE, null); + e.load_arg(0); + final List stringList = Arrays.asList(strings); + int style = fixedInput ? Constants.SWITCH_STYLE_HASHONLY : Constants.SWITCH_STYLE_HASH; + EmitUtils.string_switch(e, strings, style, new ObjectSwitchCallback() { + public void processCase(Object key, Label end) { + e.push(ints[stringList.indexOf(key)]); + e.return_value(); + } + public void processDefault() { + e.push(-1); + e.return_value(); + } + }); + e.end_method(); + ce.end_class(); + } + + protected Object firstInstance(Class type) { + return (StringSwitcher)ReflectUtils.newInstance(type); + } + + protected Object nextInstance(Object instance) { + return instance; + } + } +} diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 612ccb1e8..d35da3f20 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -26,13 +26,7 @@ org.slf4j slf4j-log4j12 - - - org.ow2.asm - asm - ${asm.version} - - + com.bladejava blade-kit @@ -45,7 +39,7 @@ ${servlet.version} provided - + junit junit diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 24ecab84d..107251a87 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -21,7 +21,6 @@ import java.util.List; import java.util.Set; -import com.blade.aop.Aop; import com.blade.config.ApplicationConfig; import com.blade.config.BaseConfig; import com.blade.config.ConfigLoader; @@ -75,7 +74,7 @@ public final class Blade { // jetty start port private int port = Const.DEFAULT_PORT; - + // default context path private String contextPath = Const.DEFAULT_CONTEXTPATH; @@ -91,8 +90,6 @@ public final class Blade { // config loader private ConfigLoader configLoader; - private Aop aop; - private Blade() { this.environment = new Environment(); this.applicationConfig = new ApplicationConfig(); @@ -100,7 +97,6 @@ private Blade() { this.plugins = new HashSet>(); this.routeBuilder = new RouteBuilder(this.routers); this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); - this.aop = new Aop(); } static final class BladeHolder { @@ -156,10 +152,6 @@ public void init() { } } - public Aop aop(){ - return this.aop; - } - /** * @return return route manager */ @@ -187,7 +179,7 @@ public ConfigLoader configLoader() { public Ioc ioc() { return ioc; } - + /** * Setting a ioc container * @@ -198,6 +190,7 @@ public Ioc ioc() { public Blade container(Ioc ioc) { Assert.notNull(ioc); this.ioc = ioc; + this.configLoader.setIoc(ioc); return this; } diff --git a/blade-core/src/main/java/com/blade/aop/Aop.java b/blade-core/src/main/java/com/blade/aop/Aop.java deleted file mode 100644 index 54a44750d..000000000 --- a/blade-core/src/main/java/com/blade/aop/Aop.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.blade.aop; - -import java.util.HashSet; -import java.util.Set; - -import com.blade.kit.reflect.ReflectKit; - -public class Aop { - - private Set packages = new HashSet(); - - public Aop() { - packages.add("com.javachina.controller.api"); - } - - public void addPackage(AopConfig aopConfig){ - packages.addAll(aopConfig.getPackages()); - } - - public void addPackage(String packageName){ - packages.add(packageName); - } - - public Object createBean(Class clazz) { - try { - Object value = ReflectKit.newInstance(clazz); - return value; - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; - } - -} diff --git a/blade-core/src/main/java/com/blade/aop/AopConfig.java b/blade-core/src/main/java/com/blade/aop/AopConfig.java deleted file mode 100644 index 1e6673992..000000000 --- a/blade-core/src/main/java/com/blade/aop/AopConfig.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.blade.aop; - -import java.util.HashSet; -import java.util.Set; - -public final class AopConfig { - - private Set aopPackages = new HashSet(); - - public AopConfig() { - - } - - public void addPackage(String packageName) { - aopPackages.add(packageName); - } - - public Set getPackages() { - return aopPackages; - } - -} diff --git a/blade-core/src/main/java/com/blade/aop/Invocaction.java b/blade-core/src/main/java/com/blade/aop/Invocaction.java deleted file mode 100644 index 8ff6cb725..000000000 --- a/blade-core/src/main/java/com/blade/aop/Invocaction.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.blade.aop; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import com.blade.exception.MethodInvokeException; -import com.blade.kit.reflect.ReflectKit; - -public class Invocaction { - - private Object target; - private Method method; - private Object[] args; - - public Invocaction(Object target, Method method, Object[] args) { - this.target = target; - this.method = method; - this.args = args; - } - - public Object invoke() throws MethodInvokeException{ - try { - return ReflectKit.invokeMehod(this.target, method, args); - } catch (IllegalAccessException e) { - throw new MethodInvokeException(e); - } catch (IllegalArgumentException e) { - throw new MethodInvokeException(e); - } catch (InvocationTargetException e) { - throw new MethodInvokeException(e); - } - } - -} diff --git a/blade-core/src/main/java/com/blade/aop/Log.java b/blade-core/src/main/java/com/blade/aop/Log.java deleted file mode 100644 index b9ff3bcd4..000000000 --- a/blade-core/src/main/java/com/blade/aop/Log.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.blade.aop; -public class Log -{ - public static void startLog() - { - System.out.println("start log ..."); - } - - public static void endLog() - { - System.out.println("end log ..."); - } -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java b/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java deleted file mode 100644 index 62604bf3b..000000000 --- a/blade-core/src/main/java/com/blade/aop/LogClassVisitor.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.blade.aop; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -public class LogClassVisitor extends ClassVisitor { - - public LogClassVisitor(ClassVisitor cv) { - super(Opcodes.ASM5, cv); - } - - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - if ("getEnvCount".equals(name)) { - return new LogMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions)); - } - return super.visitMethod(access, name, desc, signature, exceptions); - } - -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java b/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java deleted file mode 100644 index d6dcf9d5d..000000000 --- a/blade-core/src/main/java/com/blade/aop/LogMethodVisitor.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.blade.aop; - -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -public class LogMethodVisitor extends MethodVisitor { - - public LogMethodVisitor(MethodVisitor mv) { - super(Opcodes.ASM5, mv); - } - - public void visitCode() { - /** - * 方法执行之前植入代码 - */ - super.visitMethodInsn(Opcodes.INVOKESTATIC, "com/blade/aop/Log", "startLog", "()V", false); - super.visitCode(); - } - - public void visitInsn(int opcode) { - if (opcode == Opcodes.RETURN) { - /** - * 方法return之前,植入代码 - */ - super.visitMethodInsn(Opcodes.INVOKESTATIC, "com/blade/aop/Log", "endLog", "()V", false); - } - super.visitInsn(opcode); - } -} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/aop/MethodInterceptor.java b/blade-core/src/main/java/com/blade/aop/MethodInterceptor.java deleted file mode 100644 index 025f36ac3..000000000 --- a/blade-core/src/main/java/com/blade/aop/MethodInterceptor.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.blade.aop; - -public interface MethodInterceptor { - - void config(Aop aop); - - Object doInvoke(Invocaction method); - -} diff --git a/blade-core/src/main/java/com/blade/aop/ProxyClassLoader.java b/blade-core/src/main/java/com/blade/aop/ProxyClassLoader.java deleted file mode 100644 index a556177b1..000000000 --- a/blade-core/src/main/java/com/blade/aop/ProxyClassLoader.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.blade.aop; - -import java.io.IOException; - -import org.objectweb.asm.ClassWriter; - -import com.blade.kit.resource.BladeClassLoader; - -public class ProxyClassLoader extends BladeClassLoader { - - public ProxyClassLoader() { - } - - @Override - public Class defineClassByName(String name) throws ClassNotFoundException { - org.objectweb.asm.ClassReader cr; - - if (name.endsWith("Service")) { - return Class.forName(name); - } - try { - cr = new org.objectweb.asm.ClassReader(name); - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); - cr.accept(new LogClassVisitor(cw), org.objectweb.asm.ClassReader.SKIP_DEBUG); - byte[] data = cw.toByteArray(); - return this.defineClass(name, data, 0, data.length); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - -} diff --git a/blade-core/src/main/java/org/objectweb/asm/AnnotationVisitor.java b/blade-core/src/main/java/com/blade/asm/AnnotationVisitor.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/AnnotationVisitor.java rename to blade-core/src/main/java/com/blade/asm/AnnotationVisitor.java index b64408372..ab02091d0 100644 --- a/blade-core/src/main/java/org/objectweb/asm/AnnotationVisitor.java +++ b/blade-core/src/main/java/com/blade/asm/AnnotationVisitor.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A visitor to visit a Java annotation. The methods of this class must be diff --git a/blade-core/src/main/java/org/objectweb/asm/AnnotationWriter.java b/blade-core/src/main/java/com/blade/asm/AnnotationWriter.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/AnnotationWriter.java rename to blade-core/src/main/java/com/blade/asm/AnnotationWriter.java index 6b95608ac..e4f3bbad0 100644 --- a/blade-core/src/main/java/org/objectweb/asm/AnnotationWriter.java +++ b/blade-core/src/main/java/com/blade/asm/AnnotationWriter.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * An {@link AnnotationVisitor} that generates annotations in bytecode form. diff --git a/blade-core/src/main/java/com/blade/asm/AsmKit.java b/blade-core/src/main/java/com/blade/asm/AsmKit.java index 22f6b343f..96a5a688d 100644 --- a/blade-core/src/main/java/com/blade/asm/AsmKit.java +++ b/blade-core/src/main/java/com/blade/asm/AsmKit.java @@ -4,15 +4,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - public final class AsmKit { - + /** * *

@@ -59,22 +52,18 @@ public static String[] getMethodParamNames(final Method m) { } cr.accept(new ClassVisitor(Opcodes.ASM4) { @Override - public MethodVisitor visitMethod(final int access, - final String name, final String desc, + public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { final Type[] args = Type.getArgumentTypes(desc); // 方法名相同并且参数个数相同 - if (!name.equals(m.getName()) - || !sameType(args, m.getParameterTypes())) { - return super.visitMethod(access, name, desc, signature, - exceptions); + if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { + return super.visitMethod(access, name, desc, signature, exceptions); } - MethodVisitor v = super.visitMethod(access, name, desc, - signature, exceptions); + MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); return new MethodVisitor(Opcodes.ASM4, v) { @Override - public void visitLocalVariable(String name, String desc, - String signature, Label start, Label end, int index) { + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, + int index) { int i = index - 1; // 如果是静态方法,则第一就是参数 // 如果不是静态方法,则第一个是"this",然后才是方法的参数 @@ -84,8 +73,7 @@ public void visitLocalVariable(String name, String desc, if (i >= 0 && i < paramNames.length) { paramNames[i] = name; } - super.visitLocalVariable(name, desc, signature, start, - end, index); + super.visitLocalVariable(name, desc, signature, start, end, index); } }; @@ -93,5 +81,5 @@ public void visitLocalVariable(String name, String desc, }, 0); return paramNames; } - + } diff --git a/blade-core/src/main/java/org/objectweb/asm/Attribute.java b/blade-core/src/main/java/com/blade/asm/Attribute.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/Attribute.java rename to blade-core/src/main/java/com/blade/asm/Attribute.java index 8a2a882f8..cc444da2f 100644 --- a/blade-core/src/main/java/org/objectweb/asm/Attribute.java +++ b/blade-core/src/main/java/com/blade/asm/Attribute.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A non standard class, field, method or code attribute. diff --git a/blade-core/src/main/java/org/objectweb/asm/ByteVector.java b/blade-core/src/main/java/com/blade/asm/ByteVector.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/ByteVector.java rename to blade-core/src/main/java/com/blade/asm/ByteVector.java index 9c532be78..7546cd099 100644 --- a/blade-core/src/main/java/org/objectweb/asm/ByteVector.java +++ b/blade-core/src/main/java/com/blade/asm/ByteVector.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A dynamically extensible vector of bytes. This class is roughly equivalent to diff --git a/blade-core/src/main/java/org/objectweb/asm/ClassReader.java b/blade-core/src/main/java/com/blade/asm/ClassReader.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/ClassReader.java rename to blade-core/src/main/java/com/blade/asm/ClassReader.java index 76b1600ee..3e8228c6c 100644 --- a/blade-core/src/main/java/org/objectweb/asm/ClassReader.java +++ b/blade-core/src/main/java/com/blade/asm/ClassReader.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; import java.io.IOException; import java.io.InputStream; diff --git a/blade-core/src/main/java/org/objectweb/asm/ClassVisitor.java b/blade-core/src/main/java/com/blade/asm/ClassVisitor.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/ClassVisitor.java rename to blade-core/src/main/java/com/blade/asm/ClassVisitor.java index 107ada001..153e307e4 100644 --- a/blade-core/src/main/java/org/objectweb/asm/ClassVisitor.java +++ b/blade-core/src/main/java/com/blade/asm/ClassVisitor.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A visitor to visit a Java class. The methods of this class must be called in diff --git a/blade-core/src/main/java/org/objectweb/asm/ClassWriter.java b/blade-core/src/main/java/com/blade/asm/ClassWriter.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/ClassWriter.java rename to blade-core/src/main/java/com/blade/asm/ClassWriter.java index f4dd6c631..b23d69044 100644 --- a/blade-core/src/main/java/org/objectweb/asm/ClassWriter.java +++ b/blade-core/src/main/java/com/blade/asm/ClassWriter.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A {@link ClassVisitor} that generates classes in bytecode form. More diff --git a/blade-core/src/main/java/org/objectweb/asm/Context.java b/blade-core/src/main/java/com/blade/asm/Context.java similarity index 96% rename from blade-core/src/main/java/org/objectweb/asm/Context.java rename to blade-core/src/main/java/com/blade/asm/Context.java index 363b34cf8..2ec67fe27 100644 --- a/blade-core/src/main/java/org/objectweb/asm/Context.java +++ b/blade-core/src/main/java/com/blade/asm/Context.java @@ -28,7 +28,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * Information about a class being parsed in a {@link ClassReader}. diff --git a/blade-core/src/main/java/org/objectweb/asm/Edge.java b/blade-core/src/main/java/com/blade/asm/Edge.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/Edge.java rename to blade-core/src/main/java/com/blade/asm/Edge.java index 4e87cbaba..2c5ee185f 100644 --- a/blade-core/src/main/java/org/objectweb/asm/Edge.java +++ b/blade-core/src/main/java/com/blade/asm/Edge.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * An edge in the control flow graph of a method body. See {@link Label Label}. diff --git a/blade-core/src/main/java/org/objectweb/asm/FieldVisitor.java b/blade-core/src/main/java/com/blade/asm/FieldVisitor.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/FieldVisitor.java rename to blade-core/src/main/java/com/blade/asm/FieldVisitor.java index 2372e4c7f..026535ae7 100644 --- a/blade-core/src/main/java/org/objectweb/asm/FieldVisitor.java +++ b/blade-core/src/main/java/com/blade/asm/FieldVisitor.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A visitor to visit a Java field. The methods of this class must be called in diff --git a/blade-core/src/main/java/org/objectweb/asm/FieldWriter.java b/blade-core/src/main/java/com/blade/asm/FieldWriter.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/FieldWriter.java rename to blade-core/src/main/java/com/blade/asm/FieldWriter.java index 84d92aae9..8b495bc39 100644 --- a/blade-core/src/main/java/org/objectweb/asm/FieldWriter.java +++ b/blade-core/src/main/java/com/blade/asm/FieldWriter.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * An {@link FieldVisitor} that generates Java fields in bytecode form. diff --git a/blade-core/src/main/java/org/objectweb/asm/Frame.java b/blade-core/src/main/java/com/blade/asm/Frame.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/Frame.java rename to blade-core/src/main/java/com/blade/asm/Frame.java index 1f6106f66..663b0e7fa 100644 --- a/blade-core/src/main/java/org/objectweb/asm/Frame.java +++ b/blade-core/src/main/java/com/blade/asm/Frame.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * Information about the input and output stack map frames of a basic block. diff --git a/blade-core/src/main/java/org/objectweb/asm/Handle.java b/blade-core/src/main/java/com/blade/asm/Handle.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/Handle.java rename to blade-core/src/main/java/com/blade/asm/Handle.java index ddc0368d6..1bd2ea985 100644 --- a/blade-core/src/main/java/org/objectweb/asm/Handle.java +++ b/blade-core/src/main/java/com/blade/asm/Handle.java @@ -28,7 +28,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A reference to a field or a method. diff --git a/blade-core/src/main/java/org/objectweb/asm/Handler.java b/blade-core/src/main/java/com/blade/asm/Handler.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/Handler.java rename to blade-core/src/main/java/com/blade/asm/Handler.java index b24591d81..f47439838 100644 --- a/blade-core/src/main/java/org/objectweb/asm/Handler.java +++ b/blade-core/src/main/java/com/blade/asm/Handler.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * Information about an exception handler block. diff --git a/blade-core/src/main/java/org/objectweb/asm/Item.java b/blade-core/src/main/java/com/blade/asm/Item.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/Item.java rename to blade-core/src/main/java/com/blade/asm/Item.java index 917524dde..8d86ec0e6 100644 --- a/blade-core/src/main/java/org/objectweb/asm/Item.java +++ b/blade-core/src/main/java/com/blade/asm/Item.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A constant pool item. Constant pool items can be created with the 'newXXX' diff --git a/blade-core/src/main/java/org/objectweb/asm/Label.java b/blade-core/src/main/java/com/blade/asm/Label.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/Label.java rename to blade-core/src/main/java/com/blade/asm/Label.java index 6bca6fbe8..b35c1a76c 100644 --- a/blade-core/src/main/java/org/objectweb/asm/Label.java +++ b/blade-core/src/main/java/com/blade/asm/Label.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A label represents a position in the bytecode of a method. Labels are used diff --git a/blade-core/src/main/java/org/objectweb/asm/MethodVisitor.java b/blade-core/src/main/java/com/blade/asm/MethodVisitor.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/MethodVisitor.java rename to blade-core/src/main/java/com/blade/asm/MethodVisitor.java index f0927e8be..a0340ea49 100644 --- a/blade-core/src/main/java/org/objectweb/asm/MethodVisitor.java +++ b/blade-core/src/main/java/com/blade/asm/MethodVisitor.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A visitor to visit a Java method. The methods of this class must be called in diff --git a/blade-core/src/main/java/org/objectweb/asm/MethodWriter.java b/blade-core/src/main/java/com/blade/asm/MethodWriter.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/MethodWriter.java rename to blade-core/src/main/java/com/blade/asm/MethodWriter.java index 5d30ddc0e..3d32d7686 100644 --- a/blade-core/src/main/java/org/objectweb/asm/MethodWriter.java +++ b/blade-core/src/main/java/com/blade/asm/MethodWriter.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A {@link MethodVisitor} that generates methods in bytecode form. Each visit diff --git a/blade-core/src/main/java/org/objectweb/asm/Opcodes.java b/blade-core/src/main/java/com/blade/asm/Opcodes.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/Opcodes.java rename to blade-core/src/main/java/com/blade/asm/Opcodes.java index e5c2b33fd..c82ec544b 100644 --- a/blade-core/src/main/java/org/objectweb/asm/Opcodes.java +++ b/blade-core/src/main/java/com/blade/asm/Opcodes.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * Defines the JVM opcodes, access flags and array type codes. This interface diff --git a/blade-core/src/main/java/org/objectweb/asm/Type.java b/blade-core/src/main/java/com/blade/asm/Type.java similarity index 99% rename from blade-core/src/main/java/org/objectweb/asm/Type.java rename to blade-core/src/main/java/com/blade/asm/Type.java index 6561fea3f..f9488eb90 100644 --- a/blade-core/src/main/java/org/objectweb/asm/Type.java +++ b/blade-core/src/main/java/com/blade/asm/Type.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; import java.lang.reflect.Constructor; import java.lang.reflect.Method; diff --git a/blade-core/src/main/java/org/objectweb/asm/TypePath.java b/blade-core/src/main/java/com/blade/asm/TypePath.java similarity index 96% rename from blade-core/src/main/java/org/objectweb/asm/TypePath.java rename to blade-core/src/main/java/com/blade/asm/TypePath.java index d9c99b106..15b0bbe78 100644 --- a/blade-core/src/main/java/org/objectweb/asm/TypePath.java +++ b/blade-core/src/main/java/com/blade/asm/TypePath.java @@ -28,7 +28,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * The path to a type argument, wildcard bound, array element type, or static diff --git a/blade-core/src/main/java/org/objectweb/asm/TypeReference.java b/blade-core/src/main/java/com/blade/asm/TypeReference.java similarity index 97% rename from blade-core/src/main/java/org/objectweb/asm/TypeReference.java rename to blade-core/src/main/java/com/blade/asm/TypeReference.java index dff76c0b3..23012377c 100644 --- a/blade-core/src/main/java/org/objectweb/asm/TypeReference.java +++ b/blade-core/src/main/java/com/blade/asm/TypeReference.java @@ -28,7 +28,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -package org.objectweb.asm; +package com.blade.asm; /** * A reference to a type appearing in a class, field or method declaration, or diff --git a/blade-core/src/main/java/com/blade/config/ConfigLoader.java b/blade-core/src/main/java/com/blade/config/ConfigLoader.java index 5e0691733..f949aa567 100644 --- a/blade-core/src/main/java/com/blade/config/ConfigLoader.java +++ b/blade-core/src/main/java/com/blade/config/ConfigLoader.java @@ -1,85 +1,89 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.lang.reflect.Modifier; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.context.DynamicClassReader; -import com.blade.exception.ConfigException; -import com.blade.ioc.Ioc; -import com.blade.ioc.annotation.Component; -import com.blade.kit.CollectionKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; - -/** - * ConfigLoader - * - * @author biezhi - * @since 1.0 - */ -public class ConfigLoader { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); - - private ClassReader classReader; - private Ioc ioc; - private ApplicationConfig applicationConfig; - - public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { - this.ioc = ioc; - this.classReader = DynamicClassReader.getClassReader(); - this.applicationConfig = applicationConfig; - } - - @SuppressWarnings("unchecked") - public void loadConfig() { - String[] configPackages = Blade.$().config().getConfigPackages(); - if (null != configPackages && configPackages.length > 0) { - // Scan package all class - try { - for (String packageName : configPackages) { - Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); - if (CollectionKit.isNotEmpty(classes)) { - for (ClassInfo classInfo : classes) { - boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); - if(hasInterface){ - addConfig((Class) classInfo.getClazz()); - } - } - } - } - } catch (ConfigException e) { - LOGGER.error("load config error", e); - } - } - } - - public void addConfig(Class clazz) throws ConfigException { - if (!Modifier.isAbstract(clazz.getModifiers())) { - Object bean = ioc.addBean(clazz); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(applicationConfig); - } - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.lang.reflect.Modifier; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.context.DynamicClassReader; +import com.blade.exception.ConfigException; +import com.blade.ioc.Ioc; +import com.blade.ioc.annotation.Component; +import com.blade.kit.CollectionKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; + +/** + * ConfigLoader + * + * @author biezhi + * @since 1.0 + */ +public class ConfigLoader { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); + + private ClassReader classReader; + private Ioc ioc; + private ApplicationConfig applicationConfig; + + public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { + this.ioc = ioc; + this.classReader = DynamicClassReader.getClassReader(); + this.applicationConfig = applicationConfig; + } + + public void setIoc(Ioc ioc){ + this.ioc = ioc; + } + + @SuppressWarnings("unchecked") + public void loadConfig() { + String[] configPackages = Blade.$().config().getConfigPackages(); + if (null != configPackages && configPackages.length > 0) { + // Scan package all class + try { + for (String packageName : configPackages) { + Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); + if (CollectionKit.isNotEmpty(classes)) { + for (ClassInfo classInfo : classes) { + boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); + if(hasInterface){ + addConfig((Class) classInfo.getClazz()); + } + } + } + } + } catch (ConfigException e) { + LOGGER.error("load config error", e); + } + } + } + + public void addConfig(Class clazz) throws ConfigException { + if (!Modifier.isAbstract(clazz.getModifiers())) { + Object bean = ioc.addBean(clazz); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(applicationConfig); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/context/ApplicationContext.java b/blade-core/src/main/java/com/blade/context/ApplicationContext.java index 1dbb87dfe..4a7fd180c 100644 --- a/blade-core/src/main/java/com/blade/context/ApplicationContext.java +++ b/blade-core/src/main/java/com/blade/context/ApplicationContext.java @@ -1,42 +1,36 @@ -package com.blade.context; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.aop.ProxyClassLoader; -import com.blade.exception.BladeException; -import com.blade.ioc.IocApplication; -import com.blade.kit.resource.BladeClassLoader; - -public final class ApplicationContext { - - public static void init(Blade blade) throws BladeException{ - - blade.bootstrap().init(blade); - - if(!blade.config().isInit()){ - blade.loadAppConf(Const.APP_PROPERTIES); - blade.config().setEnv(blade.environment()); - } - - // load config - blade.configLoader().loadConfig(); - - // buiding route - blade.routeBuilder().building(); - - // initialization ioc - IocApplication iocApplication = new IocApplication(); - iocApplication.init(); - blade.init(); - - blade.bootstrap().contextInitialized(); - - } - - private static final BladeClassLoader CLASSLOADER = new ProxyClassLoader(); - - public static BladeClassLoader getClassLoader(){ - return CLASSLOADER; - } - -} +package com.blade.context; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.exception.BladeException; +import com.blade.ioc.IocApplication; + +public final class ApplicationContext { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContext.class); + + public static void init(Blade blade) throws BladeException{ + try { + blade.bootstrap().init(blade); + + if(!blade.config().isInit()){ + blade.loadAppConf(Const.APP_PROPERTIES); + blade.config().setEnv(blade.environment()); + } + + // initialization ioc + IocApplication iocApplication = new IocApplication(); + iocApplication.initBeans(); + + blade.init(); + blade.bootstrap().contextInitialized(); + } catch (Exception e) { + LOGGER.error("ApplicationContext init error", e); + } + + } + +} diff --git a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java index 3c1e8122a..01375cb31 100644 --- a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java +++ b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java @@ -1,49 +1,49 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; - -import com.blade.kit.resource.ClassPathClassReader; -import com.blade.kit.resource.ClassReader; -import com.blade.kit.resource.JarReaderImpl; - -/** - * 动态根据环境获取ClassReader - * - * @author biezhi - * @since 1.0 - */ -public class DynamicClassReader { - - private static boolean IS_JAR_CONTEXT = false; - - private DynamicClassReader() { - } - - public static void init(){ - String rs = DynamicClassReader.class.getResource("").toString(); - if(rs.indexOf(".jar!") != -1){ - IS_JAR_CONTEXT = true; - } - } - - public static ClassReader getClassReader(){ - if(IS_JAR_CONTEXT){ - return new JarReaderImpl(ApplicationContext.getClassLoader()); - } - return new ClassPathClassReader(ApplicationContext.getClassLoader()); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import com.blade.kit.resource.ClassPathClassReader; +import com.blade.kit.resource.ClassReader; +import com.blade.kit.resource.JarReaderImpl; + +/** + * 动态根据环境获取ClassReader + * + * @author biezhi + * @since 1.0 + */ +public class DynamicClassReader { + + private static boolean IS_JAR_CONTEXT = false; + + private DynamicClassReader() { + } + + public static void init(){ + String rs = DynamicClassReader.class.getResource("").toString(); + if(rs.indexOf(".jar!") != -1){ + IS_JAR_CONTEXT = true; + } + } + + public static ClassReader getClassReader(){ + if(IS_JAR_CONTEXT){ + return new JarReaderImpl(); + } + return new ClassPathClassReader(); + } + +} diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 632449e47..8239f6de1 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -1,189 +1,192 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Bootstrap; -import com.blade.context.DynamicClassReader; -import com.blade.ioc.annotation.Component; -import com.blade.ioc.annotation.Service; -import com.blade.kit.CollectionKit; -import com.blade.kit.StringKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; -import com.blade.plugin.Plugin; -import com.blade.route.Route; -import com.blade.route.RouteHandler; -import com.blade.route.Routers; - -/** - * IOC container, used to initialize the IOC object - * - * @author biezhi - * @since 1.0 - */ -public class IocApplication { - - private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); - - /** - * Ioc Container - */ - private Ioc ioc = null; - - /** - * Class to read object, load class - */ - private ClassReader classReader = null; - private String[] iocs; - private Bootstrap bootstrap; - - /** - * Plugin List - */ - private List plugins = null; - - private Set> pluginTypes; - - private Blade blade; - - public IocApplication() { - this.blade = Blade.$(); - this.classReader = DynamicClassReader.getClassReader(); - this.plugins = CollectionKit.newArrayList(); - this.pluginTypes = blade.plugins(); - this.ioc = blade.ioc(); - this.iocs = blade.config().getIocPackages(); - this.bootstrap = blade.bootstrap(); - } - - /** - * IOC initialize - * @param iocs ioc packages - * @param bootstrap bootstrap object - */ - public void init(){ - - // Initialize the global configuration class - if(null == ioc.getBean(Bootstrap.class)){ - ioc.addBean(bootstrap); - } - - // The object to initialize the IOC container loads the IOC package to configure the class that conforms to the IOC - if(null != iocs && iocs.length > 0){ - for(String packageName : iocs){ - registerBean(packageName); - } - } - - for(Class type : pluginTypes){ - ioc.addBean(type); - Plugin plugin = ioc.getBean(type); - plugins.add(plugin); - } - - // init controllers - Routers routers = blade.routers(); - Map routes = routers.getRoutes(); - if(CollectionKit.isNotEmpty(routes)){ - Collection routesList = routes.values(); - if(CollectionKit.isNotEmpty(routesList)){ - for(Route route : routesList){ - Class type = route.getTargetType(); - if(null != type && null == route.getTarget() && type != RouteHandler.class && null == ioc.getBean(type)){ - ioc.addBean(type); - } - } - } - } - - Map interceptors = routers.getInterceptors(); - if(CollectionKit.isNotEmpty(interceptors)){ - Collection routesList = interceptors.values(); - if(CollectionKit.isNotEmpty(routesList)){ - for(Route route : routesList){ - Class type = route.getTargetType(); - if(null != type && null == route.getTarget() && type != RouteHandler.class && null == ioc.getBean(type)){ - ioc.addBean(type); - } - } - } - } - - LOGGER.info("Add Object: {}", ioc.getBeans()); - - // injection - List beanDefines = ioc.getBeanDefines(); - for(BeanDefine beanDefine : beanDefines){ - IocKit.injection(ioc, beanDefine); - } - } - - /** - * Register all objects in a package - * - * @param packageName package name - */ - private void registerBean(String packageName) { - if(StringKit.isBlank(packageName)){ - return; - } - // Recursive scan - boolean recursive = false; - if (packageName.endsWith(".*")) { - packageName = packageName.substring(0, packageName.length() - 2); - recursive = true; - } - - // Scan package all class - Set classes = classReader.getClass(packageName, recursive); - for (ClassInfo classInfo : classes) { - Class clazz = classInfo.getClazz(); - if(!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())){ - Component component = clazz.getAnnotation(Component.class); - Service service = clazz.getAnnotation(Service.class); - if(null != component || null != service){ - // Register classes - ioc.addBean(clazz); - } - } - } - } - - public List getPlugins() { - return plugins; - } - - /** - * destroy - */ - public void destroy() { - // Clean IOC container - ioc.clearAll(); - for(Plugin plugin : plugins){ - plugin.destroy(); - } - } +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.annotation.Controller; +import com.blade.config.BaseConfig; +import com.blade.context.DynamicClassReader; +import com.blade.interceptor.Interceptor; +import com.blade.ioc.annotation.Component; +import com.blade.ioc.annotation.Service; +import com.blade.kit.StringKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.route.RouteBuilder; + +/** + * IOC container, used to initialize the IOC object + * + * @author biezhi + * @since 1.0 + */ +public class IocApplication { + + private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); + + private static List aopInterceptors = new ArrayList(); + + /** + * Class to read object, load class + */ + private ClassReader classReader = null; + private Blade blade; + + public IocApplication() { + this.blade = Blade.$(); + this.classReader = DynamicClassReader.getClassReader(); + } + + private List loadCondigs() throws Exception{ + List configs = null; + String[] configPackages = blade.config().getConfigPackages(); + if (null != configPackages && configPackages.length > 0) { + configs = new ArrayList(10); + for (String packageName : configPackages) { + Set configClasses = classReader.getClassByAnnotation(packageName, Component.class, false); + if(null != configClasses){ + for(ClassInfo classInfo : configClasses){ + if(classInfo.getClazz().getSuperclass().getName().equals("com.blade.aop.AbstractMethodInterceptor")){ + aopInterceptors.add(classInfo.newInstance()); + } + Class[] interfaces = classInfo.getClazz().getInterfaces(); + for(Class in : interfaces){ + if(in.equals(BaseConfig.class)){ + configs.add(classInfo); + } + } + } + } + } + } + return configs; + } + + private List loadServices() throws Exception{ + List services = null; + String[] configPackages = blade.config().getIocPackages(); + if (null != configPackages && configPackages.length > 0) { + services = new ArrayList(20); + for (String packageName : configPackages) { + if(StringKit.isBlank(packageName)){ + continue; + } + // Recursive scan + boolean recursive = false; + if (packageName.endsWith(".*")) { + packageName = packageName.substring(0, packageName.length() - 2); + recursive = true; + } + + // Scan package all class + Set iocClasses = classReader.getClass(packageName, recursive); + for (ClassInfo classInfo : iocClasses) { + Class clazz = classInfo.getClazz(); + if(!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())){ + Component component = clazz.getAnnotation(Component.class); + Service service = clazz.getAnnotation(Service.class); + if(null != service || null != component){ + services.add(classInfo); + } + } + } + } + } + return services; + } + + private List loadControllers() { + List controllers = null; + String[] routePackages = blade.config().getRoutePackages(); + if(null != routePackages && routePackages.length > 0){ + controllers = new ArrayList(); + for(String packageName : routePackages){ + // Scan all Controoler + controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); + } + } + return controllers; + } + + private List loadInterceptors() { + List interceptors = null; + String interceptorPackage = blade.config().getInterceptorPackage(); + if(StringKit.isNotBlank(interceptorPackage)){ + interceptors = new ArrayList(10); + interceptors.addAll(classReader.getClass(interceptorPackage, Interceptor.class, false)); + } + return interceptors; + } + + public void initBeans() throws Exception{ + List services = this.loadServices(); + List configs = this.loadCondigs(); + List controllers = this.loadControllers(); + // web + List inteceptors = this.loadInterceptors(); + + // 先获取所有被容器托管的Class, 再依次注入 + + Ioc ioc = blade.ioc(); + + RouteBuilder routeBuilder = blade.routeBuilder(); + + // 1. 初始化service + for(ClassInfo classInfo : services){ + ioc.addBean(classInfo.getClazz()); + } + + // 2. 初始化配置文件 + for(ClassInfo classInfo : configs){ + Object bean = ioc.addBean(classInfo.getClazz()); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(blade.applicationConfig()); + } + + // 3. 初始化controller + for(ClassInfo classInfo : controllers){ + ioc.addBean(classInfo.getClazz()); + routeBuilder.addRouter(classInfo.getClazz()); + } + + // 4. 初始化interceptor + for(ClassInfo classInfo : inteceptors){ + ioc.addBean(classInfo.getClazz()); + routeBuilder.addInterceptor(classInfo.getClazz()); + } + + LOGGER.info("Add Object: {}", ioc.getBeans()); + + // injection + List beanDefines = ioc.getBeanDefines(); + for(BeanDefine beanDefine : beanDefines){ + IocKit.injection(ioc, beanDefine); + } + } + + public static List getAopInterceptors(){ + return aopInterceptors; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java index 82aa7b30c..c7dbb05a8 100644 --- a/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java @@ -161,9 +161,7 @@ public Object addBean(String name, Class beanClass, boolean singleton) { return beanDefine.getBean(); } - private BeanDefine getBeanDefine(Class beanClass, boolean singleton) { -// Object object = Blade.$().aop().createBean(beanClass); -// return new BeanDefine(object, beanClass, singleton); + public BeanDefine getBeanDefine(Class beanClass, boolean singleton) { try { Object object = beanClass.newInstance(); return new BeanDefine(object, beanClass, singleton); diff --git a/blade-core/src/main/java/com/blade/plugin/Plugin.java b/blade-core/src/main/java/com/blade/plugin/Plugin.java index 1bc35d6be..b9d71e4fb 100644 --- a/blade-core/src/main/java/com/blade/plugin/Plugin.java +++ b/blade-core/src/main/java/com/blade/plugin/Plugin.java @@ -24,9 +24,9 @@ public interface Plugin { /** - * Run Plugin + * Start Plugin */ - void run(); + void start(); /** * Destroy, release resources diff --git a/blade-kit/src/main/java/com/blade/kit/Environment.java b/blade-kit/src/main/java/com/blade/kit/Environment.java index 3ba6376a8..5f89a94c4 100644 --- a/blade-kit/src/main/java/com/blade/kit/Environment.java +++ b/blade-kit/src/main/java/com/blade/kit/Environment.java @@ -71,11 +71,11 @@ private Map loadMap(String confPath){ } envMap.put(key, value); } - LOGGER.info("load environment config [classpath:" + confPath + "]"); + LOGGER.info("Load environment config [classpath:" + confPath + "]"); } } } catch (IOException e) { - LOGGER.error("load environment config error", e); + LOGGER.error("Load environment config error", e); } finally { IOKit.closeQuietly(in); } diff --git a/blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java b/blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java index c6c4b3b3b..6d9ad3c2a 100644 --- a/blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/AbstractClassReader.java @@ -1,185 +1,170 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.net.URL; -import java.net.URLDecoder; -import java.util.Enumeration; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.kit.Assert; -import com.blade.kit.CollectionKit; -import com.blade.kit.exception.ClassReaderException; - -/** - * 抽象类读取器 - * - * @author biezhi - * @since 1.0 - */ -public abstract class AbstractClassReader implements ClassReader { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractClassReader.class); - - protected BladeClassLoader classLoader; - - @Override - public BladeClassLoader getClassLoader() { - return classLoader; - } - - public AbstractClassReader(BladeClassLoader classLoader) { - if(null == classLoader){ - this.classLoader = this.getClassLoader(); - } else{ - this.classLoader = classLoader; - } - } - - @Override - public Set getClass(String packageName, boolean recursive) { - return this.getClassByAnnotation(packageName, null, null, recursive); - } - - /** - * 默认实现以文件形式的读取 - */ - @Override - public Set getClass(String packageName, Class parent, boolean recursive) { - return this.getClassByAnnotation(packageName, parent, null, recursive); - } - - /** - * 根据条件获取class - * @param packageName - * @param packagePath - * @param parent - * @param annotation - * @param recursive - * @return - */ - private Set findClassByPackage(final String packageName, final String packagePath, - final Class parent, final Class annotation, - final boolean recursive, Set classes) throws ClassNotFoundException { - - // 获取此包的目录 建立一个File - File dir = new File(packagePath); - // 如果不存在或者 也不是目录就直接返回 - if ((!dir.exists()) || (!dir.isDirectory())) { - LOGGER.warn("The package [{}] not found.", packageName); - } - // 如果存在 就获取包下的所有文件 包括目录 - File[] dirfiles = accept(dir, recursive); - // 循环所有文件 - if(null != dirfiles && dirfiles.length > 0){ - for (File file : dirfiles) { - // 如果是目录 则继续扫描 - if (file.isDirectory()) { - findClassByPackage(packageName + "." + file.getName(), file.getAbsolutePath(), parent, annotation, recursive, classes); - } else { - // 如果是java类文件 去掉后面的.class 只留下类名 - String className = file.getName().substring(0, file.getName().length() - 6); - Class clazz = classLoader.defineClassByName(packageName + '.' + className); -// Class clazz = Class.forName(packageName + '.' + className); - if(null != parent && null != annotation){ - if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent) && - null != clazz.getAnnotation(annotation)){ - classes.add(new ClassInfo(clazz)); - } - continue; - } - if(null != parent){ - if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent)){ - classes.add(new ClassInfo(clazz)); - } else { - if(null != clazz.getInterfaces() && clazz.getInterfaces().length > 0 && clazz.getInterfaces()[0].equals(parent)){ - classes.add(new ClassInfo(clazz)); - } - } - continue; - } - if(null != annotation){ - if(null != clazz.getAnnotation(annotation)){ - classes.add(new ClassInfo(clazz)); - } - continue; - } - classes.add(new ClassInfo(clazz)); - } - } - } - return classes; - } - - /** - * 过滤文件规则 - * @param file - * @param recursive - * @return - */ - private File[] accept(File file, final boolean recursive){ - File[] dirfiles = file.listFiles(new FileFilter() { - // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件) - public boolean accept(File file) { - return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")); - } - }); - return dirfiles; - } - - @Override - public Set getClassByAnnotation(String packageName, Class annotation, boolean recursive) { - return this.getClassByAnnotation(packageName, null, annotation, recursive); - } - - @Override - public Set getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive) { - Assert.notBlank(packageName); - Set classes = CollectionKit.newHashSet(); - // 获取包的名字 并进行替换 - String packageDirName = packageName.replace('.', '/'); - // 定义一个枚举的集合 并进行循环来处理这个目录下的URL - Enumeration dirs; - try { - dirs = classLoader.getResources(packageDirName); - // 循环迭代下去 - while (dirs.hasMoreElements()) { - // 获取下一个元素 - URL url = dirs.nextElement(); - // 获取包的物理路径 - String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); - Set subClasses = findClassByPackage(packageName, filePath, parent, annotation, recursive, classes); - if(subClasses.size() > 0){ - classes.addAll(subClasses); - } - } - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } catch (ClassNotFoundException e) { - LOGGER.error("Add user custom view class error Can't find such Class files."); - throw new ClassReaderException(e); - } - return classes; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; + +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.net.URL; +import java.net.URLDecoder; +import java.util.Enumeration; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.kit.CollectionKit; +import com.blade.kit.exception.ClassReaderException; + +/** + * 抽象类读取器 + * + * @author biezhi + * @since 1.0 + */ +public abstract class AbstractClassReader implements ClassReader { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractClassReader.class); + + @Override + public Set getClass(String packageName, boolean recursive) { + return this.getClassByAnnotation(packageName, null, null, recursive); + } + + /** + * 默认实现以文件形式的读取 + */ + @Override + public Set getClass(String packageName, Class parent, boolean recursive) { + return this.getClassByAnnotation(packageName, parent, null, recursive); + } + + /** + * 根据条件获取class + * @param packageName + * @param packagePath + * @param parent + * @param annotation + * @param recursive + * @return + */ + private Set findClassByPackage(final String packageName, final String packagePath, + final Class parent, final Class annotation, + final boolean recursive, Set classes) throws ClassNotFoundException { + + // 获取此包的目录 建立一个File + File dir = new File(packagePath); + // 如果不存在或者 也不是目录就直接返回 + if ((!dir.exists()) || (!dir.isDirectory())) { + LOGGER.warn("The package [{}] not found.", packageName); + } + // 如果存在 就获取包下的所有文件 包括目录 + File[] dirfiles = accept(dir, recursive); + // 循环所有文件 + if(null != dirfiles && dirfiles.length > 0){ + for (File file : dirfiles) { + // 如果是目录 则继续扫描 + if (file.isDirectory()) { + findClassByPackage(packageName + "." + file.getName(), file.getAbsolutePath(), parent, annotation, recursive, classes); + } else { + // 如果是java类文件 去掉后面的.class 只留下类名 + String className = file.getName().substring(0, file.getName().length() - 6); +// Class clazz = classLoader.defineClassByName(packageName + '.' + className); + Class clazz = Class.forName(packageName + '.' + className); + if(null != parent && null != annotation){ + if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent) && + null != clazz.getAnnotation(annotation)){ + classes.add(new ClassInfo(clazz)); + } + continue; + } + if(null != parent){ + if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent)){ + classes.add(new ClassInfo(clazz)); + } else { + if(null != clazz.getInterfaces() && clazz.getInterfaces().length > 0 && clazz.getInterfaces()[0].equals(parent)){ + classes.add(new ClassInfo(clazz)); + } + } + continue; + } + if(null != annotation){ + if(null != clazz.getAnnotation(annotation)){ + classes.add(new ClassInfo(clazz)); + } + continue; + } + classes.add(new ClassInfo(clazz)); + } + } + } + return classes; + } + + /** + * 过滤文件规则 + * @param file + * @param recursive + * @return + */ + private File[] accept(File file, final boolean recursive){ + File[] dirfiles = file.listFiles(new FileFilter() { + // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件) + public boolean accept(File file) { + return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")); + } + }); + return dirfiles; + } + + @Override + public Set getClassByAnnotation(String packageName, Class annotation, boolean recursive) { + return this.getClassByAnnotation(packageName, null, annotation, recursive); + } + + @Override + public Set getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive) { + Assert.notBlank(packageName); + Set classes = CollectionKit.newHashSet(); + // 获取包的名字 并进行替换 + String packageDirName = packageName.replace('.', '/'); + // 定义一个枚举的集合 并进行循环来处理这个目录下的URL + Enumeration dirs; + try { + dirs = this.getClass().getClassLoader().getResources(packageDirName); + // 循环迭代下去 + while (dirs.hasMoreElements()) { + // 获取下一个元素 + URL url = dirs.nextElement(); + // 获取包的物理路径 + String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); + Set subClasses = findClassByPackage(packageName, filePath, parent, annotation, recursive, classes); + if(subClasses.size() > 0){ + classes.addAll(subClasses); + } + } + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } catch (ClassNotFoundException e) { + LOGGER.error("Add user custom view class error Can't find such Class files."); + throw new ClassReaderException(e); + } + return classes; + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/com/blade/kit/resource/ClassInfo.java b/blade-kit/src/main/java/com/blade/kit/resource/ClassInfo.java index a4f15d319..0ee29ba52 100644 --- a/blade-kit/src/main/java/com/blade/kit/resource/ClassInfo.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/ClassInfo.java @@ -1,30 +1,38 @@ -package com.blade.kit.resource; - -public class ClassInfo { - - private String className; - private Class clazz; - - public ClassInfo(String className) { - this.className = className; - } - - public ClassInfo(Class clazz) { - this.clazz = clazz; - this.className = clazz.getName(); - } - - public ClassInfo(String className, Class clazz) { - this.clazz = clazz; - this.className = className; - } - - public String getClassName() { - return className; - } - - public Class getClazz() { - return clazz; - } - -} +package com.blade.kit.resource; + +public class ClassInfo { + + private String className; + private Class clazz; + + public ClassInfo(String className) { + this.className = className; + } + + public ClassInfo(Class clazz) { + this.clazz = clazz; + this.className = clazz.getName(); + } + + public ClassInfo(String className, Class clazz) { + this.clazz = clazz; + this.className = className; + } + + public String getClassName() { + return className; + } + + public Class getClazz() { + return clazz; + } + + public Object newInstance() throws InstantiationException, IllegalAccessException{ + return clazz.newInstance(); + } + + @Override + public String toString() { + return clazz.toString(); + } +} diff --git a/blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java b/blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java index 3d45e61da..ab86badf5 100644 --- a/blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/ClassPathClassReader.java @@ -1,30 +1,26 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; - -/** - * 根据classpath加载类 - * - * @author biezhi - * @since 1.0 - */ -public class ClassPathClassReader extends AbstractClassReader implements ClassReader { - - public ClassPathClassReader(BladeClassLoader classLoader) { - super(classLoader); - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; + +/** + * 根据classpath加载类 + * + * @author biezhi + * @since 1.0 + */ +public class ClassPathClassReader extends AbstractClassReader implements ClassReader { + } \ No newline at end of file diff --git a/blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java b/blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java index f9e39b290..84e1226d0 100644 --- a/blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/ClassReader.java @@ -1,39 +1,37 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; - -import java.lang.annotation.Annotation; -import java.util.Set; - -/** - * 一个类读取器的接口 - * - * @author biezhi - * @since 1.0 - */ -public interface ClassReader { - - Set getClass(String packageName, boolean recursive); - - Set getClass(String packageName, Class parent, boolean recursive); - - Set getClassByAnnotation(String packageName, Class annotation, boolean recursive); - - Set getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive); - - BladeClassLoader getClassLoader(); - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; + +import java.lang.annotation.Annotation; +import java.util.Set; + +/** + * 一个类读取器的接口 + * + * @author biezhi + * @since 1.0 + */ +public interface ClassReader { + + Set getClass(String packageName, boolean recursive); + + Set getClass(String packageName, Class parent, boolean recursive); + + Set getClassByAnnotation(String packageName, Class annotation, boolean recursive); + + Set getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive); + } \ No newline at end of file diff --git a/blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java b/blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java index 25ed301f2..701f3a8bf 100644 --- a/blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java +++ b/blade-kit/src/main/java/com/blade/kit/resource/JarReaderImpl.java @@ -1,158 +1,153 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; - -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.net.JarURLConnection; -import java.net.URL; -import java.util.Enumeration; -import java.util.Set; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.kit.Assert; -import com.blade.kit.CollectionKit; - -/** - * 根据jar文件读取类 - * - * @author biezhi - * @since 1.0 - */ -public class JarReaderImpl extends AbstractClassReader implements ClassReader { - - private static final Logger LOGGER = LoggerFactory.getLogger(JarReaderImpl.class); - - public JarReaderImpl(BladeClassLoader classLoader) { - super(classLoader); - } - - @Override - public Set getClass(String packageName, boolean recursive) { - return this.getClassByAnnotation(packageName, null, null, recursive); - } - - @Override - public Set getClass(String packageName, Class parent, boolean recursive) { - return this.getClassByAnnotation(packageName, parent, null, recursive); - } - - @Override - public Set getClassByAnnotation(String packageName, Class annotation, boolean recursive) { - return this.getClassByAnnotation(packageName, null, annotation, recursive); - } - - @Override - public Set getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive) { - Assert.notBlank(packageName); - Set classes = CollectionKit.newHashSet(); - // 获取包的名字 并进行替换 - String packageDirName = packageName.replace('.', '/'); - // 定义一个枚举的集合 并进行循环来处理这个目录下的URL - Enumeration dirs; - try { - dirs = classLoader.getResources(packageDirName); - // 循环迭代下去 - while (dirs.hasMoreElements()) { - // 获取下一个元素 - URL url = dirs.nextElement(); - Set subClasses = this.getClasses(url, packageDirName, packageName, parent, annotation, recursive, classes); - if(subClasses.size() > 0){ - classes.addAll(subClasses); - } - } - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return classes; - } - - private Set getClasses(final URL url, final String packageDirName, String packageName, final Class parent, - final Class annotation, final boolean recursive, Set classes){ - try { - if( url.toString().startsWith( "jar:file:" ) || url.toString().startsWith( "wsjar:file:" ) ) { - - // 获取jar - JarFile jarFile = ( (JarURLConnection)url.openConnection() ).getJarFile(); - - // 从此jar包 得到一个枚举类 - Enumeration eje = jarFile.entries(); - - // 同样的进行循环迭代 - while (eje.hasMoreElements()) { - // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 - JarEntry entry = eje.nextElement(); - String name = entry.getName(); - // 如果是以/开头的 - if (name.charAt(0) == '/') { - // 获取后面的字符串 - name = name.substring(1); - } - // 如果前半部分和定义的包名相同 - if (name.startsWith(packageDirName)) { - int idx = name.lastIndexOf('/'); - // 如果以"/"结尾 是一个包 - if (idx != -1) { - // 获取包名 把"/"替换成"." - packageName = name.substring(0, idx).replace('/', '.'); - } - // 如果可以迭代下去 并且是一个包 - if ((idx != -1) || recursive) { - // 如果是一个.class文件 而且不是目录 - if (name.endsWith(".class") && !entry.isDirectory()) { - // 去掉后面的".class" 获取真正的类名 - String className = name.substring(packageName.length() + 1, name.length() - 6); - // 添加到classes -// Class clazz = Class.forName(packageName + '.' + className); - Class clazz = classLoader.defineClassByName(packageName + '.' + className); - if(null != parent && null != annotation){ - if(null != clazz.getSuperclass() && - clazz.getSuperclass().equals(parent) && null != clazz.getAnnotation(annotation)){ - classes.add(new ClassInfo(clazz)); - } - continue; - } - if(null != parent){ - if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent)){ - classes.add(new ClassInfo(clazz)); - } - continue; - } - if(null != annotation){ - if(null != clazz.getAnnotation(annotation)){ - classes.add(new ClassInfo(clazz)); - } - continue; - } - classes.add(new ClassInfo(clazz)); - } - } - } - } - } - } catch (IOException e) { - LOGGER.error("The scan error when the user to define the view from a jar package file.", e); - } catch (ClassNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return classes; - } +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.resource; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.net.JarURLConnection; +import java.net.URL; +import java.util.Enumeration; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.kit.CollectionKit; + +/** + * 根据jar文件读取类 + * + * @author biezhi + * @since 1.0 + */ +public class JarReaderImpl extends AbstractClassReader implements ClassReader { + + private static final Logger LOGGER = LoggerFactory.getLogger(JarReaderImpl.class); + + @Override + public Set getClass(String packageName, boolean recursive) { + return this.getClassByAnnotation(packageName, null, null, recursive); + } + + @Override + public Set getClass(String packageName, Class parent, boolean recursive) { + return this.getClassByAnnotation(packageName, parent, null, recursive); + } + + @Override + public Set getClassByAnnotation(String packageName, Class annotation, boolean recursive) { + return this.getClassByAnnotation(packageName, null, annotation, recursive); + } + + @Override + public Set getClassByAnnotation(String packageName, Class parent, Class annotation, boolean recursive) { + Assert.notBlank(packageName); + Set classes = CollectionKit.newHashSet(); + // 获取包的名字 并进行替换 + String packageDirName = packageName.replace('.', '/'); + // 定义一个枚举的集合 并进行循环来处理这个目录下的URL + Enumeration dirs; + try { + dirs = this.getClass().getClassLoader().getResources(packageDirName); + // 循环迭代下去 + while (dirs.hasMoreElements()) { + // 获取下一个元素 + URL url = dirs.nextElement(); + Set subClasses = this.getClasses(url, packageDirName, packageName, parent, annotation, recursive, classes); + if(subClasses.size() > 0){ + classes.addAll(subClasses); + } + } + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return classes; + } + + private Set getClasses(final URL url, final String packageDirName, String packageName, final Class parent, + final Class annotation, final boolean recursive, Set classes){ + try { + if( url.toString().startsWith( "jar:file:" ) || url.toString().startsWith( "wsjar:file:" ) ) { + + // 获取jar + JarFile jarFile = ( (JarURLConnection)url.openConnection() ).getJarFile(); + + // 从此jar包 得到一个枚举类 + Enumeration eje = jarFile.entries(); + + // 同样的进行循环迭代 + while (eje.hasMoreElements()) { + // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 + JarEntry entry = eje.nextElement(); + String name = entry.getName(); + // 如果是以/开头的 + if (name.charAt(0) == '/') { + // 获取后面的字符串 + name = name.substring(1); + } + // 如果前半部分和定义的包名相同 + if (name.startsWith(packageDirName)) { + int idx = name.lastIndexOf('/'); + // 如果以"/"结尾 是一个包 + if (idx != -1) { + // 获取包名 把"/"替换成"." + packageName = name.substring(0, idx).replace('/', '.'); + } + // 如果可以迭代下去 并且是一个包 + if ((idx != -1) || recursive) { + // 如果是一个.class文件 而且不是目录 + if (name.endsWith(".class") && !entry.isDirectory()) { + // 去掉后面的".class" 获取真正的类名 + String className = name.substring(packageName.length() + 1, name.length() - 6); + // 添加到classes + Class clazz = Class.forName(packageName + '.' + className); + if(null != parent && null != annotation){ + if(null != clazz.getSuperclass() && + clazz.getSuperclass().equals(parent) && null != clazz.getAnnotation(annotation)){ + classes.add(new ClassInfo(clazz)); + } + continue; + } + if(null != parent){ + if(null != clazz.getSuperclass() && clazz.getSuperclass().equals(parent)){ + classes.add(new ClassInfo(clazz)); + } + continue; + } + if(null != annotation){ + if(null != clazz.getAnnotation(annotation)){ + classes.add(new ClassInfo(clazz)); + } + continue; + } + classes.add(new ClassInfo(clazz)); + } + } + } + } + } + } catch (IOException e) { + LOGGER.error("The scan error when the user to define the view from a jar package file.", e); + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return classes; + } } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7f5f70223..111ee0824 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 com.bladejava @@ -9,26 +10,30 @@ blade https://github.com/biezhi/blade - + 1.6 1.6 UTF-8 - 1.6.5 - 1.3.2 - 0.0.3 + 3.0.1 4.12 1.7.21 1.7.21 - 5.1 + + 1.6.5 + 1.3.2 + 1.0.0 + 0.0.3 + blade-kit blade-core - blade-embed-jetty - blade-auth + blade-embed-jetty + blade-auth + blade-aop @@ -46,26 +51,26 @@ - + - org.slf4j - slf4j-api - ${slf4j-api.version} + org.slf4j + slf4j-api + ${slf4j-api.version} - + - org.slf4j - slf4j-log4j12 - ${slf4j-log4j12.version} + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} - + junit junit ${junit.version} test - + From 3822dd693fba6b9314ec575ef83f88c44915cf59 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 31 Aug 2016 19:04:08 +0800 Subject: [PATCH 466/545] release blade-core 1.6.5 --- README.md | 59 +++---- .../src/main/java/com/blade/asm/AsmKit.java | 7 + .../java/com/blade/ioc/IocApplication.java | 150 ++++++++++-------- .../objectweb}/asm/AnnotationVisitor.java | 2 +- .../objectweb}/asm/AnnotationWriter.java | 2 +- .../objectweb}/asm/Attribute.java | 2 +- .../objectweb}/asm/ByteVector.java | 2 +- .../objectweb}/asm/ClassReader.java | 2 +- .../objectweb}/asm/ClassVisitor.java | 2 +- .../objectweb}/asm/ClassWriter.java | 2 +- .../blade => org/objectweb}/asm/Context.java | 2 +- .../blade => org/objectweb}/asm/Edge.java | 2 +- .../objectweb}/asm/FieldVisitor.java | 2 +- .../objectweb}/asm/FieldWriter.java | 2 +- .../blade => org/objectweb}/asm/Frame.java | 2 +- .../blade => org/objectweb}/asm/Handle.java | 2 +- .../blade => org/objectweb}/asm/Handler.java | 2 +- .../blade => org/objectweb}/asm/Item.java | 2 +- .../blade => org/objectweb}/asm/Label.java | 2 +- .../objectweb}/asm/MethodVisitor.java | 2 +- .../objectweb}/asm/MethodWriter.java | 2 +- .../blade => org/objectweb}/asm/Opcodes.java | 2 +- .../blade => org/objectweb}/asm/Type.java | 2 +- .../blade => org/objectweb}/asm/TypePath.java | 2 +- .../objectweb}/asm/TypeReference.java | 2 +- 25 files changed, 128 insertions(+), 132 deletions(-) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/AnnotationVisitor.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/AnnotationWriter.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/Attribute.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/ByteVector.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/ClassReader.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/ClassVisitor.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/ClassWriter.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/Context.java (96%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/Edge.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/FieldVisitor.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/FieldWriter.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/Frame.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/Handle.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/Handler.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/Item.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/Label.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/MethodVisitor.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/MethodWriter.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/Opcodes.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/Type.java (99%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/TypePath.java (96%) rename blade-core/src/main/java/{com/blade => org/objectweb}/asm/TypeReference.java (97%) diff --git a/README.md b/README.md index 33625c937..ab3fb5296 100644 --- a/README.md +++ b/README.md @@ -38,18 +38,18 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.4 + 1.6.5 com.bladejava blade-embed-jetty - 0.0.2 + 0.0.3 ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.4' -compile 'com.bladejava:blade-embed-jetty:0.0.2' +compile 'com.bladejava:blade-core:1.6.5' +compile 'com.bladejava:blade-embed-jetty:0.0.3' ``` Create `Main` method like this: @@ -58,11 +58,10 @@ Create `Main` method like this: public class App { public static void main(String[] args) { - Blade blade = me(); - blade.get("/", (request, response) -> { + $().get("/", (request, response) -> { response.html("

Hello blade!

"); }); - blade.start(EmbedJettyServer.class); + $().start(EmbedJettyServer.class); } } ``` @@ -73,12 +72,11 @@ Run it and point your browser to [http://localhost:9000](http://localhost:9000). ```java public static void main(String[] args) { - Blade blade = me(); - blade.get("/user/21", getxxx); - blade.post("/save", postxxx); - blade.delete("/del/21", deletexxx); - blade.put("/put", putxxx); - blade.start(EmbedJettyServer.class); + $().get("/user/21", getxxx); + $().post("/save", postxxx); + $().delete("/del/21", deletexxx); + $().put("/put", putxxx); + $().start(EmbedJettyServer.class); } ``` @@ -86,20 +84,19 @@ public static void main(String[] args) { ```java public static void main(String[] args) { - Blade blade = me(); - blade.get("/user/:uid", (request, response) -> { + $().get("/user/:uid", (request, response) -> { Integer uid = request.paramAsInt("uid"); response.text("uid : " + uid); }); - blade.get("/users/:uid/post/:pid", (request, response) -> { + $().get("/users/:uid/post/:pid", (request, response) -> { Integer uid = request.paramAsInt("uid"); Integer pid = request.paramAsInt("pid"); String msg = "uid = " + uid + ", pid = " + pid; response.text(msg); }); - blade.start(EmbedJettyServer.class); + $().start(EmbedJettyServer.class); } ``` @@ -107,12 +104,11 @@ public static void main(String[] args) { ```java public static void main(String[] args) { - Blade blade = me(); - blade.get("/user", (request, response) -> { + $().get("/user", (request, response) -> { Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); }); - blade.start(EmbedJettyServer.class); + $().start(EmbedJettyServer.class); } ``` @@ -150,32 +146,13 @@ POST /upload_img UploadRoute.upload_img ```java public static void main(String[] args) { - Blade blade = me(); - blade.before("/.*", (request, response) -> { + $().before("/.*", (request, response) -> { System.out.println("before..."); }); - blade.start(EmbedJettyServer.class); + $().start(EmbedJettyServer.class); } ``` -## DSL DB Operation - -```java -// query -List posts = - AR.find("where title like ? order by id desc limit ?,?", title, page, count).list(Post.class); - -// save -String insertSql = "insert into t_post (title, content, view_count, create_time) values (?,?,?,?)"; -AR.update(insertSql, title, content, 0, new Date()).commit(); - -// update -AR.update("update t_post set title = ? and content = ? where id = ?",title, content, id).commit(); - -// delete -AR.update("delete from t_post where id = ?",id).commit() -``` - You may refer to these examples for additional guidance: + [Hello Blade](https://github.com/blade-samples/hello) diff --git a/blade-core/src/main/java/com/blade/asm/AsmKit.java b/blade-core/src/main/java/com/blade/asm/AsmKit.java index 96a5a688d..7f91709c3 100644 --- a/blade-core/src/main/java/com/blade/asm/AsmKit.java +++ b/blade-core/src/main/java/com/blade/asm/AsmKit.java @@ -4,6 +4,13 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + public final class AsmKit { /** diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 8239f6de1..c993188c5 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -38,41 +38,42 @@ /** * IOC container, used to initialize the IOC object * - * @author biezhi - * @since 1.0 + * @author biezhi + * @since 1.0 */ public class IocApplication { private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); - + private static List aopInterceptors = new ArrayList(); - + /** * Class to read object, load class */ private ClassReader classReader = null; private Blade blade; - + public IocApplication() { this.blade = Blade.$(); this.classReader = DynamicClassReader.getClassReader(); } - - private List loadCondigs() throws Exception{ + + private List loadCondigs() throws Exception { List configs = null; String[] configPackages = blade.config().getConfigPackages(); if (null != configPackages && configPackages.length > 0) { configs = new ArrayList(10); for (String packageName : configPackages) { Set configClasses = classReader.getClassByAnnotation(packageName, Component.class, false); - if(null != configClasses){ - for(ClassInfo classInfo : configClasses){ - if(classInfo.getClazz().getSuperclass().getName().equals("com.blade.aop.AbstractMethodInterceptor")){ + if (null != configClasses) { + for (ClassInfo classInfo : configClasses) { + if (classInfo.getClazz().getSuperclass().getName() + .equals("com.blade.aop.AbstractMethodInterceptor")) { aopInterceptors.add(classInfo.newInstance()); } Class[] interfaces = classInfo.getClazz().getInterfaces(); - for(Class in : interfaces){ - if(in.equals(BaseConfig.class)){ + for (Class in : interfaces) { + if (in.equals(BaseConfig.class)) { configs.add(classInfo); } } @@ -82,31 +83,31 @@ private List loadCondigs() throws Exception{ } return configs; } - - private List loadServices() throws Exception{ + + private List loadServices() throws Exception { List services = null; String[] configPackages = blade.config().getIocPackages(); if (null != configPackages && configPackages.length > 0) { services = new ArrayList(20); for (String packageName : configPackages) { - if(StringKit.isBlank(packageName)){ + if (StringKit.isBlank(packageName)) { continue; } // Recursive scan - boolean recursive = false; + boolean recursive = false; if (packageName.endsWith(".*")) { packageName = packageName.substring(0, packageName.length() - 2); recursive = true; } - + // Scan package all class Set iocClasses = classReader.getClass(packageName, recursive); for (ClassInfo classInfo : iocClasses) { Class clazz = classInfo.getClazz(); - if(!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())){ + if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { Component component = clazz.getAnnotation(Component.class); Service service = clazz.getAnnotation(Service.class); - if(null != service || null != component){ + if (null != service || null != component) { services.add(classInfo); } } @@ -115,78 +116,89 @@ private List loadServices() throws Exception{ } return services; } - + private List loadControllers() { List controllers = null; String[] routePackages = blade.config().getRoutePackages(); - if(null != routePackages && routePackages.length > 0){ + if (null != routePackages && routePackages.length > 0) { controllers = new ArrayList(); - for(String packageName : routePackages){ - // Scan all Controoler - controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); - } - } + for (String packageName : routePackages) { + // Scan all Controoler + controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); + } + } return controllers; } - + private List loadInterceptors() { List interceptors = null; String interceptorPackage = blade.config().getInterceptorPackage(); - if(StringKit.isNotBlank(interceptorPackage)){ + if (StringKit.isNotBlank(interceptorPackage)) { interceptors = new ArrayList(10); interceptors.addAll(classReader.getClass(interceptorPackage, Interceptor.class, false)); - } + } return interceptors; } - - public void initBeans() throws Exception{ + + public void initBeans() throws Exception { List services = this.loadServices(); List configs = this.loadCondigs(); List controllers = this.loadControllers(); // web List inteceptors = this.loadInterceptors(); - + // 先获取所有被容器托管的Class, 再依次注入 - - Ioc ioc = blade.ioc(); - - RouteBuilder routeBuilder = blade.routeBuilder(); - - // 1. 初始化service - for(ClassInfo classInfo : services){ - ioc.addBean(classInfo.getClazz()); - } - - // 2. 初始化配置文件 - for(ClassInfo classInfo : configs){ - Object bean = ioc.addBean(classInfo.getClazz()); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(blade.applicationConfig()); - } - - // 3. 初始化controller - for(ClassInfo classInfo : controllers){ - ioc.addBean(classInfo.getClazz()); - routeBuilder.addRouter(classInfo.getClazz()); - } - - // 4. 初始化interceptor - for(ClassInfo classInfo : inteceptors){ - ioc.addBean(classInfo.getClazz()); - routeBuilder.addInterceptor(classInfo.getClazz()); - } - - LOGGER.info("Add Object: {}", ioc.getBeans()); - - // injection + + Ioc ioc = blade.ioc(); + + RouteBuilder routeBuilder = blade.routeBuilder(); + + // 1. 初始化service + if (null != services) { + for (ClassInfo classInfo : services) { + ioc.addBean(classInfo.getClazz()); + } + } + + // 2. 初始化配置文件 + if (null != configs) { + for (ClassInfo classInfo : configs) { + Object bean = ioc.addBean(classInfo.getClazz()); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(blade.applicationConfig()); + } + } + + // 3. 初始化controller + if (null != controllers) { + for (ClassInfo classInfo : controllers) { + ioc.addBean(classInfo.getClazz()); + routeBuilder.addRouter(classInfo.getClazz()); + } + } + + // 4. 初始化interceptor + if (null != inteceptors) { + for (ClassInfo classInfo : inteceptors) { + ioc.addBean(classInfo.getClazz()); + routeBuilder.addInterceptor(classInfo.getClazz()); + } + } + + LOGGER.info("Add Object: {}", ioc.getBeans()); + + // injection List beanDefines = ioc.getBeanDefines(); - for(BeanDefine beanDefine : beanDefines){ - IocKit.injection(ioc, beanDefine); + if (null != beanDefines) { + for (BeanDefine beanDefine : beanDefines) { + IocKit.injection(ioc, beanDefine); + } } + } - - public static List getAopInterceptors(){ + + public static List getAopInterceptors() { return aopInterceptors; } - + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/asm/AnnotationVisitor.java b/blade-core/src/main/java/org/objectweb/asm/AnnotationVisitor.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/AnnotationVisitor.java rename to blade-core/src/main/java/org/objectweb/asm/AnnotationVisitor.java index ab02091d0..b64408372 100644 --- a/blade-core/src/main/java/com/blade/asm/AnnotationVisitor.java +++ b/blade-core/src/main/java/org/objectweb/asm/AnnotationVisitor.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A visitor to visit a Java annotation. The methods of this class must be diff --git a/blade-core/src/main/java/com/blade/asm/AnnotationWriter.java b/blade-core/src/main/java/org/objectweb/asm/AnnotationWriter.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/AnnotationWriter.java rename to blade-core/src/main/java/org/objectweb/asm/AnnotationWriter.java index e4f3bbad0..6b95608ac 100644 --- a/blade-core/src/main/java/com/blade/asm/AnnotationWriter.java +++ b/blade-core/src/main/java/org/objectweb/asm/AnnotationWriter.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * An {@link AnnotationVisitor} that generates annotations in bytecode form. diff --git a/blade-core/src/main/java/com/blade/asm/Attribute.java b/blade-core/src/main/java/org/objectweb/asm/Attribute.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/Attribute.java rename to blade-core/src/main/java/org/objectweb/asm/Attribute.java index cc444da2f..8a2a882f8 100644 --- a/blade-core/src/main/java/com/blade/asm/Attribute.java +++ b/blade-core/src/main/java/org/objectweb/asm/Attribute.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A non standard class, field, method or code attribute. diff --git a/blade-core/src/main/java/com/blade/asm/ByteVector.java b/blade-core/src/main/java/org/objectweb/asm/ByteVector.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/ByteVector.java rename to blade-core/src/main/java/org/objectweb/asm/ByteVector.java index 7546cd099..9c532be78 100644 --- a/blade-core/src/main/java/com/blade/asm/ByteVector.java +++ b/blade-core/src/main/java/org/objectweb/asm/ByteVector.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A dynamically extensible vector of bytes. This class is roughly equivalent to diff --git a/blade-core/src/main/java/com/blade/asm/ClassReader.java b/blade-core/src/main/java/org/objectweb/asm/ClassReader.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/ClassReader.java rename to blade-core/src/main/java/org/objectweb/asm/ClassReader.java index 3e8228c6c..76b1600ee 100644 --- a/blade-core/src/main/java/com/blade/asm/ClassReader.java +++ b/blade-core/src/main/java/org/objectweb/asm/ClassReader.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; import java.io.IOException; import java.io.InputStream; diff --git a/blade-core/src/main/java/com/blade/asm/ClassVisitor.java b/blade-core/src/main/java/org/objectweb/asm/ClassVisitor.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/ClassVisitor.java rename to blade-core/src/main/java/org/objectweb/asm/ClassVisitor.java index 153e307e4..107ada001 100644 --- a/blade-core/src/main/java/com/blade/asm/ClassVisitor.java +++ b/blade-core/src/main/java/org/objectweb/asm/ClassVisitor.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A visitor to visit a Java class. The methods of this class must be called in diff --git a/blade-core/src/main/java/com/blade/asm/ClassWriter.java b/blade-core/src/main/java/org/objectweb/asm/ClassWriter.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/ClassWriter.java rename to blade-core/src/main/java/org/objectweb/asm/ClassWriter.java index b23d69044..f4dd6c631 100644 --- a/blade-core/src/main/java/com/blade/asm/ClassWriter.java +++ b/blade-core/src/main/java/org/objectweb/asm/ClassWriter.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A {@link ClassVisitor} that generates classes in bytecode form. More diff --git a/blade-core/src/main/java/com/blade/asm/Context.java b/blade-core/src/main/java/org/objectweb/asm/Context.java similarity index 96% rename from blade-core/src/main/java/com/blade/asm/Context.java rename to blade-core/src/main/java/org/objectweb/asm/Context.java index 2ec67fe27..363b34cf8 100644 --- a/blade-core/src/main/java/com/blade/asm/Context.java +++ b/blade-core/src/main/java/org/objectweb/asm/Context.java @@ -28,7 +28,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * Information about a class being parsed in a {@link ClassReader}. diff --git a/blade-core/src/main/java/com/blade/asm/Edge.java b/blade-core/src/main/java/org/objectweb/asm/Edge.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/Edge.java rename to blade-core/src/main/java/org/objectweb/asm/Edge.java index 2c5ee185f..4e87cbaba 100644 --- a/blade-core/src/main/java/com/blade/asm/Edge.java +++ b/blade-core/src/main/java/org/objectweb/asm/Edge.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * An edge in the control flow graph of a method body. See {@link Label Label}. diff --git a/blade-core/src/main/java/com/blade/asm/FieldVisitor.java b/blade-core/src/main/java/org/objectweb/asm/FieldVisitor.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/FieldVisitor.java rename to blade-core/src/main/java/org/objectweb/asm/FieldVisitor.java index 026535ae7..2372e4c7f 100644 --- a/blade-core/src/main/java/com/blade/asm/FieldVisitor.java +++ b/blade-core/src/main/java/org/objectweb/asm/FieldVisitor.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A visitor to visit a Java field. The methods of this class must be called in diff --git a/blade-core/src/main/java/com/blade/asm/FieldWriter.java b/blade-core/src/main/java/org/objectweb/asm/FieldWriter.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/FieldWriter.java rename to blade-core/src/main/java/org/objectweb/asm/FieldWriter.java index 8b495bc39..84d92aae9 100644 --- a/blade-core/src/main/java/com/blade/asm/FieldWriter.java +++ b/blade-core/src/main/java/org/objectweb/asm/FieldWriter.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * An {@link FieldVisitor} that generates Java fields in bytecode form. diff --git a/blade-core/src/main/java/com/blade/asm/Frame.java b/blade-core/src/main/java/org/objectweb/asm/Frame.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/Frame.java rename to blade-core/src/main/java/org/objectweb/asm/Frame.java index 663b0e7fa..1f6106f66 100644 --- a/blade-core/src/main/java/com/blade/asm/Frame.java +++ b/blade-core/src/main/java/org/objectweb/asm/Frame.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * Information about the input and output stack map frames of a basic block. diff --git a/blade-core/src/main/java/com/blade/asm/Handle.java b/blade-core/src/main/java/org/objectweb/asm/Handle.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/Handle.java rename to blade-core/src/main/java/org/objectweb/asm/Handle.java index 1bd2ea985..ddc0368d6 100644 --- a/blade-core/src/main/java/com/blade/asm/Handle.java +++ b/blade-core/src/main/java/org/objectweb/asm/Handle.java @@ -28,7 +28,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A reference to a field or a method. diff --git a/blade-core/src/main/java/com/blade/asm/Handler.java b/blade-core/src/main/java/org/objectweb/asm/Handler.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/Handler.java rename to blade-core/src/main/java/org/objectweb/asm/Handler.java index f47439838..b24591d81 100644 --- a/blade-core/src/main/java/com/blade/asm/Handler.java +++ b/blade-core/src/main/java/org/objectweb/asm/Handler.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * Information about an exception handler block. diff --git a/blade-core/src/main/java/com/blade/asm/Item.java b/blade-core/src/main/java/org/objectweb/asm/Item.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/Item.java rename to blade-core/src/main/java/org/objectweb/asm/Item.java index 8d86ec0e6..917524dde 100644 --- a/blade-core/src/main/java/com/blade/asm/Item.java +++ b/blade-core/src/main/java/org/objectweb/asm/Item.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A constant pool item. Constant pool items can be created with the 'newXXX' diff --git a/blade-core/src/main/java/com/blade/asm/Label.java b/blade-core/src/main/java/org/objectweb/asm/Label.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/Label.java rename to blade-core/src/main/java/org/objectweb/asm/Label.java index b35c1a76c..6bca6fbe8 100644 --- a/blade-core/src/main/java/com/blade/asm/Label.java +++ b/blade-core/src/main/java/org/objectweb/asm/Label.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A label represents a position in the bytecode of a method. Labels are used diff --git a/blade-core/src/main/java/com/blade/asm/MethodVisitor.java b/blade-core/src/main/java/org/objectweb/asm/MethodVisitor.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/MethodVisitor.java rename to blade-core/src/main/java/org/objectweb/asm/MethodVisitor.java index a0340ea49..f0927e8be 100644 --- a/blade-core/src/main/java/com/blade/asm/MethodVisitor.java +++ b/blade-core/src/main/java/org/objectweb/asm/MethodVisitor.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A visitor to visit a Java method. The methods of this class must be called in diff --git a/blade-core/src/main/java/com/blade/asm/MethodWriter.java b/blade-core/src/main/java/org/objectweb/asm/MethodWriter.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/MethodWriter.java rename to blade-core/src/main/java/org/objectweb/asm/MethodWriter.java index 3d32d7686..5d30ddc0e 100644 --- a/blade-core/src/main/java/com/blade/asm/MethodWriter.java +++ b/blade-core/src/main/java/org/objectweb/asm/MethodWriter.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A {@link MethodVisitor} that generates methods in bytecode form. Each visit diff --git a/blade-core/src/main/java/com/blade/asm/Opcodes.java b/blade-core/src/main/java/org/objectweb/asm/Opcodes.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/Opcodes.java rename to blade-core/src/main/java/org/objectweb/asm/Opcodes.java index c82ec544b..e5c2b33fd 100644 --- a/blade-core/src/main/java/com/blade/asm/Opcodes.java +++ b/blade-core/src/main/java/org/objectweb/asm/Opcodes.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * Defines the JVM opcodes, access flags and array type codes. This interface diff --git a/blade-core/src/main/java/com/blade/asm/Type.java b/blade-core/src/main/java/org/objectweb/asm/Type.java similarity index 99% rename from blade-core/src/main/java/com/blade/asm/Type.java rename to blade-core/src/main/java/org/objectweb/asm/Type.java index f9488eb90..6561fea3f 100644 --- a/blade-core/src/main/java/com/blade/asm/Type.java +++ b/blade-core/src/main/java/org/objectweb/asm/Type.java @@ -27,7 +27,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; import java.lang.reflect.Constructor; import java.lang.reflect.Method; diff --git a/blade-core/src/main/java/com/blade/asm/TypePath.java b/blade-core/src/main/java/org/objectweb/asm/TypePath.java similarity index 96% rename from blade-core/src/main/java/com/blade/asm/TypePath.java rename to blade-core/src/main/java/org/objectweb/asm/TypePath.java index 15b0bbe78..d9c99b106 100644 --- a/blade-core/src/main/java/com/blade/asm/TypePath.java +++ b/blade-core/src/main/java/org/objectweb/asm/TypePath.java @@ -28,7 +28,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * The path to a type argument, wildcard bound, array element type, or static diff --git a/blade-core/src/main/java/com/blade/asm/TypeReference.java b/blade-core/src/main/java/org/objectweb/asm/TypeReference.java similarity index 97% rename from blade-core/src/main/java/com/blade/asm/TypeReference.java rename to blade-core/src/main/java/org/objectweb/asm/TypeReference.java index 23012377c..dff76c0b3 100644 --- a/blade-core/src/main/java/com/blade/asm/TypeReference.java +++ b/blade-core/src/main/java/org/objectweb/asm/TypeReference.java @@ -28,7 +28,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -package com.blade.asm; +package org.objectweb.asm; /** * A reference to a type appearing in a class, field or method declaration, or From 8f2bf1d0b80b50daf4535fff36a86d1ea3c603ff Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 1 Sep 2016 10:26:52 +0800 Subject: [PATCH 467/545] fix classreader bug --- blade-core/src/main/java/com/blade/Blade.java | 47 +- blade-core/src/main/java/com/blade/Const.java | 2 +- .../com/blade/config/ApplicationConfig.java | 19 +- .../com/blade/context/ApplicationContext.java | 2 + .../com/blade/context/DynamicClassReader.java | 12 +- .../blade/exception/EmbedServerException.java | 27 + .../java/com/blade/view/ModelAndView.java | 4 +- .../blade/view/handle/RouteViewHandler.java | 54 +- .../main/java/com/blade/web/DispatchKit.java | 94 ++-- .../java/com/blade/web/DispatcherHandler.java | 41 +- .../java/com/blade/web/http/Response.java | 490 +++++++++--------- .../web/http/wrapper/ServletResponse.java | 76 ++- pom.xml | 2 +- 13 files changed, 463 insertions(+), 407 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/exception/EmbedServerException.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 107251a87..1ec0dee00 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -25,11 +25,13 @@ import com.blade.config.BaseConfig; import com.blade.config.ConfigLoader; import com.blade.embedd.EmbedServer; +import com.blade.exception.EmbedServerException; import com.blade.interceptor.Interceptor; import com.blade.ioc.Ioc; import com.blade.ioc.SimpleIoc; import com.blade.kit.Assert; import com.blade.kit.Environment; +import com.blade.kit.StringKit; import com.blade.kit.reflect.ReflectKit; import com.blade.plugin.Plugin; import com.blade.route.Route; @@ -79,7 +81,7 @@ public final class Blade { private String contextPath = Const.DEFAULT_CONTEXTPATH; // enableServer - private boolean enableServer = false; + private Boolean enableServer = false; // plugins private Set> plugins; @@ -587,6 +589,35 @@ public Blade listen(int port) { this.port = port; return this; } + + public void start(Class applicationClass) { + Assert.notNull(applicationClass); + + this.loadAppConf(Const.APP_PROPERTIES); + + // init blade environment config + applicationConfig.setEnv(environment); + applicationConfig.setApplicationClass(applicationClass); + + if(StringKit.isBlank(applicationConfig.getBasePackage())){ + applicationConfig.setBasePackage(applicationClass.getPackage().getName()); + } + try { + Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); + if(null == embedClazz){ + embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); + } + if(null != embedClazz){ + EmbedServer embedServer = (EmbedServer) embedClazz.newInstance(); + embedServer.startup(port, contextPath); + this.enableServer = true; + } else { + throw new EmbedServerException("Not found EmbedServer"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } /** * @return Return blade config object @@ -736,18 +767,4 @@ public Set> plugins() { return this.plugins; } - public void start(Class embedServer) throws Exception { - this.loadAppConf(Const.APP_PROPERTIES); - // init blade environment config - this.config().setEnv(environment); - - embedServer.newInstance().startup(port, contextPath); - this.enableServer = true; - } - - public void start(EmbedServer embedServer) throws Exception { - embedServer.startup(port, contextPath); - this.enableServer = true; - } - } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index ae0039d71..f31699df9 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -24,7 +24,7 @@ public interface Const { // current blade version - String BLADE_VERSION = "1.6.5"; + String BLADE_VERSION = "1.6.6"; // default embedd server context path String DEFAULT_CONTEXTPATH = "/"; diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 2213463f6..49801385a 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -66,6 +66,8 @@ public class ApplicationConfig { private boolean isDev = true; private boolean isInit = false; + + private Class applicationClass; public ApplicationConfig() { staticFolders.add("/public"); @@ -95,10 +97,6 @@ public void setEnv(Environment environment) { if (StringKit.isNotBlank(basePackage)) { this.setBasePackage(basePackage); - this.addConfigPackages(basePackage + ".config"); - this.addIocPackages(basePackage + ".service.*"); - this.addRoutePackages(basePackage + ".controller"); - this.setInterceptorPackage(basePackage + ".interceptor"); } isInit = true; } @@ -121,6 +119,10 @@ public String getBasePackage() { public void setBasePackage(String basePackage) { this.basePackage = basePackage; + this.addConfigPackages(basePackage + ".config"); + this.addIocPackages(basePackage + ".service.*"); + this.addRoutePackages(basePackage + ".controller"); + this.setInterceptorPackage(basePackage + ".interceptor"); } public String[] getIocPackages() { @@ -204,4 +206,13 @@ public void setEncoding(String encoding) { public boolean isInit(){ return this.isInit; } + + public Class getApplicationClass() { + return applicationClass; + } + + public void setApplicationClass(Class applicationClass) { + this.applicationClass = applicationClass; + } + } diff --git a/blade-core/src/main/java/com/blade/context/ApplicationContext.java b/blade-core/src/main/java/com/blade/context/ApplicationContext.java index 4a7fd180c..155200dfe 100644 --- a/blade-core/src/main/java/com/blade/context/ApplicationContext.java +++ b/blade-core/src/main/java/com/blade/context/ApplicationContext.java @@ -14,7 +14,9 @@ public final class ApplicationContext { public static void init(Blade blade) throws BladeException{ try { + blade.bootstrap().init(blade); + blade.applicationConfig().setBasePackage(blade.bootstrap().getClass().getPackage().getName()); if(!blade.config().isInit()){ blade.loadAppConf(Const.APP_PROPERTIES); diff --git a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java index 01375cb31..7b5c3e9ee 100644 --- a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java +++ b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java @@ -15,6 +15,7 @@ */ package com.blade.context; +import com.blade.Blade; import com.blade.kit.resource.ClassPathClassReader; import com.blade.kit.resource.ClassReader; import com.blade.kit.resource.JarReaderImpl; @@ -25,15 +26,20 @@ * @author biezhi * @since 1.0 */ -public class DynamicClassReader { - +public final class DynamicClassReader { + private static boolean IS_JAR_CONTEXT = false; private DynamicClassReader() { } public static void init(){ - String rs = DynamicClassReader.class.getResource("").toString(); + /*String rs = DynamicClassReader.class.getResource("").toString(); + if(rs.indexOf(".jar!") != -1){ + IS_JAR_CONTEXT = true; + }*/ + Class clazz = Blade.$().config().getApplicationClass(); + String rs = clazz.getResource("").toString(); if(rs.indexOf(".jar!") != -1){ IS_JAR_CONTEXT = true; } diff --git a/blade-core/src/main/java/com/blade/exception/EmbedServerException.java b/blade-core/src/main/java/com/blade/exception/EmbedServerException.java new file mode 100644 index 000000000..6632f950e --- /dev/null +++ b/blade-core/src/main/java/com/blade/exception/EmbedServerException.java @@ -0,0 +1,27 @@ +package com.blade.exception; + +public class EmbedServerException extends BladeException { + + private static final long serialVersionUID = 1L; + + public EmbedServerException() { + super(); + } + + public EmbedServerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public EmbedServerException(String message, Throwable cause) { + super(message, cause); + } + + public EmbedServerException(String message) { + super(message); + } + + public EmbedServerException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/view/ModelAndView.java b/blade-core/src/main/java/com/blade/view/ModelAndView.java index 20b8b5ebb..27a1e122d 100644 --- a/blade-core/src/main/java/com/blade/view/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/view/ModelAndView.java @@ -15,6 +15,7 @@ */ package com.blade.view; +import java.util.HashMap; import java.util.Map; import com.blade.kit.CollectionKit; @@ -30,7 +31,7 @@ public class ModelAndView { /** * Data object, the object is placed in the attribute httprequest */ - private Map model; + private Map model = new HashMap(5); /** * View Page @@ -38,7 +39,6 @@ public class ModelAndView { private String view; public ModelAndView() { - } /** diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 9ad01ceff..e4dbb9a6d 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -2,10 +2,6 @@ import java.lang.reflect.Method; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.exception.BladeException; import com.blade.ioc.Ioc; import com.blade.kit.reflect.ReflectKit; import com.blade.route.Route; @@ -15,47 +11,35 @@ import com.blade.web.http.Response; public class RouteViewHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(RouteViewHandler.class); - + private Ioc ioc; - + public RouteViewHandler(Ioc ioc) { this.ioc = ioc; } - - public void handle(Request request, Response response, Route route) throws BladeException { + + public void handle(Request request, Response response, Route route) throws Exception { Method actionMethod = route.getAction(); Object target = route.getTarget(); - // execute int len = actionMethod.getParameterTypes().length; - try { - Object returnParam = null; - if (len > 0) { - Object[] args = MethodArgument.getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if (null != returnParam) { - Class returnType = returnParam.getClass(); - if (returnType == String.class) { - response.render(returnParam.toString()); - } else if (returnType == ModelAndView.class) { - ModelAndView modelAndView = (ModelAndView) returnParam; - response.render(modelAndView); - } + Object returnParam = null; + if (len > 0) { + Object[] args = MethodArgument.getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if (null != returnParam) { + Class returnType = returnParam.getClass(); + if (returnType == String.class) { + response.render(returnParam.toString()); + } else if (returnType == ModelAndView.class) { + ModelAndView modelAndView = (ModelAndView) returnParam; + response.render(modelAndView); } - } catch (BladeException e) { - throw e; - } catch (Exception e) { - LOGGER.error("route view error", e); - request.abort(); - DispatchKit.printError(e, 500, response); } - } public boolean intercept(Request request, Response response, Route route) { diff --git a/blade-core/src/main/java/com/blade/web/DispatchKit.java b/blade-core/src/main/java/com/blade/web/DispatchKit.java index 4351993d5..506e35b3c 100644 --- a/blade-core/src/main/java/com/blade/web/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/web/DispatchKit.java @@ -23,19 +23,22 @@ import com.blade.Blade; import com.blade.Const; import com.blade.kit.FileKit; +import com.blade.kit.IOKit; import com.blade.kit.StreamKit; import com.blade.kit.StringKit; import com.blade.web.http.HttpException; import com.blade.web.http.Response; public class DispatchKit { - + private static final Logger LOGGER = LoggerFactory.getLogger(DispatchKit.class); - - static final boolean isWeb = Blade.$().enableServer(); - + + static final boolean isWeb = !Blade.$().enableServer(); + + static final Class appClass = Blade.$().config().getApplicationClass(); + private static Boolean isDev = null; - + public static File getWebRoot(ServletContext sc) { String dir = sc.getRealPath("/"); if (dir == null) { @@ -74,31 +77,32 @@ public static void setFileDownloadHeader(HttpServletResponse response, String fi } catch (UnsupportedEncodingException e) { } } - + /** * Print Error Message + * * @param err * @param code * @param response */ - public static void printError(Throwable err, int code, Response response){ - if(null == isDev){ + public static void printError(Throwable err, int code, Response response) { + if (null == isDev) { isDev = Blade.$().isDev(); } try { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final PrintWriter writer = new PrintWriter(baos); - + final PrintWriter writer = new PrintWriter(baos); + // If the developer mode, the error output to the page - if(isDev){ + if (isDev) { writer.println(String.format(HTML, err.getClass() + " : " + err.getMessage())); writer.println(); err.printStackTrace(writer); writer.println(END); } else { - if(code == 404){ + if (code == 404) { String view404 = Blade.$().view404(); - if(StringKit.isNotBlank(view404)){ + if (StringKit.isNotBlank(view404)) { response.render(view404); return; } else { @@ -106,7 +110,7 @@ public static void printError(Throwable err, int code, Response response){ } } else { String view500 = Blade.$().view500(); - if(StringKit.isNotBlank(view500)){ + if (StringKit.isNotBlank(view500)) { response.render(view500); return; } else { @@ -115,26 +119,38 @@ public static void printError(Throwable err, int code, Response response){ } } writer.close(); - response.status(code); - InputStream body = new ByteArrayInputStream(baos.toByteArray()); - print(body, response.outputStream()); + response.status(code); + InputStream body = new ByteArrayInputStream(baos.toByteArray()); + print(body, response.writer()); } catch (IOException e) { e.printStackTrace(); } } - + /** * Print + * * @param body * @param out * @throws IOException */ - public static void print(InputStream body, OutputStream out) throws IOException { - StreamKit.io(body, out, true, true); + public static void print(InputStream in, OutputStream out) throws IOException { + StreamKit.io(in, out); + } + + public static void print(InputStream body, PrintWriter writer) throws IOException { + print(IOKit.toString(body), writer); } - + + public static void print(String content, PrintWriter writer) throws IOException { + writer.print(content); + writer.flush(); + writer.close(); + } + /** * Print static file + * * @param uri * @param realpath * @param httpResponse @@ -143,22 +159,22 @@ public static void printStatic(String uri, HttpServletRequest request, Response try { String realpath = ""; InputStream ins = null; - if(isWeb){ + if (isWeb) { realpath = request.getServletContext().getRealPath(uri); File file = new File(realpath); - if(FileKit.exist(file)){ - ins = new FileInputStream(file); - } - } else{ - ins = DispatchKit.class.getResourceAsStream(uri); + if (FileKit.exist(file)) { + ins = new FileInputStream(file); + } + } else { + ins = appClass.getResourceAsStream(uri); } - - if(null != ins){ - print(ins, response.outputStream()); - } else { - LOGGER.debug("request realpath is [{}]", realpath); - HttpException httpException = new HttpException(404, uri + " not found"); - DispatchKit.printError(httpException, 404, response); + + if (null != ins) { + print(ins, response.outputStream()); + } else { + LOGGER.debug("request realpath is [{}]", realpath); + HttpException httpException = new HttpException(404, uri + " not found"); + DispatchKit.printError(httpException, 404, response); } } catch (FileNotFoundException e) { DispatchKit.printError(e, 404, response); @@ -166,12 +182,12 @@ public static void printStatic(String uri, HttpServletRequest request, Response DispatchKit.printError(e, 500, response); } } - + private static final String HTML = "Blade Framework Error Page" + "" + "

%s

";
-	
-	
-	private static final String END = "
Blade-" + Const.BLADE_VERSION + "(Blade Framework
"; - + + private static final String END = "
Blade-" + Const.BLADE_VERSION + + "(Blade Framework
"; + } diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java index 8c9ffb0d7..4851344d7 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -15,6 +15,7 @@ */ package com.blade.web; +import java.io.IOException; import java.util.List; import javax.servlet.ServletContext; @@ -28,7 +29,6 @@ import com.blade.Const; import com.blade.context.ApplicationWebContext; import com.blade.exception.BladeException; -import com.blade.exception.NotFoundException; import com.blade.ioc.Ioc; import com.blade.kit.StringKit; import com.blade.route.Route; @@ -37,6 +37,7 @@ import com.blade.route.Routers; import com.blade.view.ModelAndView; import com.blade.view.handle.RouteViewHandler; +import com.blade.view.template.TemplateException; import com.blade.web.http.HttpStatus; import com.blade.web.http.Path; import com.blade.web.http.Request; @@ -94,19 +95,13 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo } LOGGER.info("Request : {}\t{}", method, uri); - + try { - // Create Request - Request request = new ServletRequest(httpRequest); - - // Init Context + Request request = new ServletRequest(httpRequest); ApplicationWebContext.init(servletContext, request, response); - Route route = routeMatcher.getRoute(method, uri); - - // If find it - if (route != null) { + if (null != route) { request.setRoute(route); // before inteceptor @@ -126,15 +121,19 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo render404(response, uri); } return; - } catch (NotFoundException e) { - LOGGER.warn(e.getMessage()); - DispatchKit.printError(e, 404, response); - } catch (BladeException e) { - LOGGER.error(e.getMessage()); + } catch (TemplateException e) { + LOGGER.error("Template error", e); + DispatchKit.printError(e, 500, response); + } catch (BladeException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); DispatchKit.printError(e, 500, response); - } catch (Exception e) { + }catch (Exception e) { + LOGGER.error(e.getMessage(), e); DispatchKit.printError(e, 500, response); - } + } return; } @@ -143,8 +142,10 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo * * @param response response object * @param uri 404 uri + * @throws IOException + * @throws TemplateException */ - private void render404(Response response, String uri) { + private void render404(Response response, String uri) throws Exception { String view404 = blade.view404(); if(StringKit.isNotBlank(view404)){ ModelAndView modelAndView = new ModelAndView(view404); @@ -181,15 +182,13 @@ private boolean invokeInterceptor(Request request, Response response, List clazz = route.getAction().getDeclaringClass(); target = ioc.getBean(clazz); route.setTarget(target); } - request.initPathParams(route.getPath()); // Init context diff --git a/blade-core/src/main/java/com/blade/web/http/Response.java b/blade-core/src/main/java/com/blade/web/http/Response.java index 738187b71..e338b2d0a 100644 --- a/blade-core/src/main/java/com/blade/web/http/Response.java +++ b/blade-core/src/main/java/com/blade/web/http/Response.java @@ -1,241 +1,249 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; - -import java.io.IOException; -import java.io.OutputStream; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import com.blade.view.ModelAndView; - -/** - * HTTP Response - * - * @author biezhi - * @since 1.0 - */ -public interface Response { - - /** - * @return Return HttpServletResponse - */ - HttpServletResponse raw(); - - /** - * @return Return HTTP Status - */ - int status(); - - /** - * Setting Response Status - * - * @param status status code - * @return Return Response - */ - Response status(int status); - - /** - * @return Setting Response Status is BadRequest and Return Response - */ - Response badRequest(); - - /** - * @return Setting Response Status is unauthorized and Return Response - */ - Response unauthorized(); - - /** - * @return Setting Response Status is notFound and Return Response - */ - Response notFound(); - - /** - * @return Setting Response Status is conflict and Return Response - */ - Response conflict(); - - /** - * @return Return Response contentType - */ - String contentType(); - - /** - * Setting Response ContentType - * - * @param contentType content type - * @return Return Response - */ - Response contentType(String contentType); - - /** - * Get header - * - * @param name Header Name - * @return Return Response - */ - String header(String name); - - /** - * Setting header - * - * @param name Header Name - * @param value Header Value - * @return Return Response - */ - Response header(String name, String value); - - /** - * Setting Cookie - * - * @param cookie Cookie Object - * @return Return Response - */ - Response cookie(Cookie cookie); - - /** - * Setting Cookie - * - * @param name Cookie Name - * @param value Cookie Value - * @return Return Response - */ - Response cookie(String name, String value); - - /** - * Setting Cookie - * - * @param name Cookie Name - * @param value Cookie Value - * @param maxAge Period of validity - * @return Return Response - */ - Response cookie(String name, String value, int maxAge); - - /** - * Setting Cookie - * - * @param name Cookie Name - * @param value Cookie Value - * @param maxAge Period of validity - * @param secured Is SSL - * @return Return Response - */ - Response cookie(String name, String value, int maxAge, boolean secured); - - /** - * Setting Cookie - * - * @param path Cookie Domain Path - * @param name Cookie Name - * @param value Cookie Value - * @param maxAge Period of validity - * @param secured Is SSL - * @return Return Response - */ - Response cookie(String path, String name, String value, int maxAge, boolean secured); - - /** - * Remove Cookie - * - * @param cookie Cookie Object - * @return Return Response - */ - Response removeCookie(Cookie cookie); - - /** - * Rmove Cookie By Name - * - * @param name Cookie Name - * @return Return Response - */ - Response removeCookie(String name); - - /** - * Render by text - * - * @param text text content - * @return Return Response - */ - Response text(String text); - - /** - * Render by html - * - * @param html html content - * @return Return Response - */ - Response html(String html); - - /** - * Render by json - * - * @param json json content - * @return Return Response - */ - Response json(String json); - - /** - * Render by xml - * - * @param xml xml content - * @return Return Response - */ - Response xml(String xml); - - /** - * @return Return OutputStream - * @throws IOException IOException - */ - OutputStream outputStream() throws IOException; - - /** - * Render view - * - * @param view view page - * @return Return Response - */ - Response render(String view) ; - - /** - * Render view And Setting Data - * - * @param modelAndView ModelAndView object - * @return Return Response - */ - Response render(ModelAndView modelAndView) ; - - /** - * Redirect to Path - * - * @param path location path - */ - void redirect(String path); - - /** - * Go to Path, Under contextpath - * - * @param path redirect location - */ - void go(String path); - - /** - * @return Return Response is Write - */ - boolean isWritten(); - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import com.blade.view.ModelAndView; +import com.blade.view.template.TemplateException; + +/** + * HTTP Response + * + * @author biezhi + * @since 1.0 + */ +public interface Response { + + /** + * @return Return HttpServletResponse + */ + HttpServletResponse raw(); + + /** + * @return Return HTTP Status + */ + int status(); + + /** + * Setting Response Status + * + * @param status status code + * @return Return Response + */ + Response status(int status); + + /** + * @return Setting Response Status is BadRequest and Return Response + */ + Response badRequest(); + + /** + * @return Setting Response Status is unauthorized and Return Response + */ + Response unauthorized(); + + /** + * @return Setting Response Status is notFound and Return Response + */ + Response notFound(); + + /** + * @return Setting Response Status is conflict and Return Response + */ + Response conflict(); + + /** + * @return Return Response contentType + */ + String contentType(); + + /** + * Setting Response ContentType + * + * @param contentType content type + * @return Return Response + */ + Response contentType(String contentType); + + /** + * Get header + * + * @param name Header Name + * @return Return Response + */ + String header(String name); + + /** + * Setting header + * + * @param name Header Name + * @param value Header Value + * @return Return Response + */ + Response header(String name, String value); + + /** + * Setting Cookie + * + * @param cookie Cookie Object + * @return Return Response + */ + Response cookie(Cookie cookie); + + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @return Return Response + */ + Response cookie(String name, String value); + + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @return Return Response + */ + Response cookie(String name, String value, int maxAge); + + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @param secured Is SSL + * @return Return Response + */ + Response cookie(String name, String value, int maxAge, boolean secured); + + /** + * Setting Cookie + * + * @param path Cookie Domain Path + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @param secured Is SSL + * @return Return Response + */ + Response cookie(String path, String name, String value, int maxAge, boolean secured); + + /** + * Remove Cookie + * + * @param cookie Cookie Object + * @return Return Response + */ + Response removeCookie(Cookie cookie); + + /** + * Rmove Cookie By Name + * + * @param name Cookie Name + * @return Return Response + */ + Response removeCookie(String name); + + /** + * Render by text + * + * @param text text content + * @return Return Response + */ + Response text(String text); + + /** + * Render by html + * + * @param html html content + * @return Return Response + */ + Response html(String html); + + /** + * Render by json + * + * @param json json content + * @return Return Response + */ + Response json(String json); + + /** + * Render by xml + * + * @param xml xml content + * @return Return Response + */ + Response xml(String xml); + + /** + * @return Return OutputStream + * @throws IOException IOException + */ + OutputStream outputStream() throws IOException; + + /** + * @return Return ResponseWriter Stream + * @throws IOException + */ + PrintWriter writer() throws IOException; + + /** + * Render view + * + * @param view view page + * @return Return Response + */ + Response render(String view) throws TemplateException, IOException; + + /** + * Render view And Setting Data + * + * @param modelAndView ModelAndView object + * @return Return Response + */ + Response render(ModelAndView modelAndView) throws TemplateException, IOException; + + /** + * Redirect to Path + * + * @param path location path + */ + void redirect(String path); + + /** + * Go to Path, Under contextpath + * + * @param path redirect location + */ + void go(String path); + + /** + * @return Return Response is Write + */ + boolean isWritten(); + +} diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index f667ce7c1..dd6e3acab 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -27,6 +27,8 @@ import com.blade.kit.Assert; import com.blade.view.ModelAndView; import com.blade.view.template.TemplateEngine; +import com.blade.view.template.TemplateException; +import com.blade.web.DispatchKit; import com.blade.web.http.HttpStatus; import com.blade.web.http.Path; import com.blade.web.http.Request; @@ -174,14 +176,13 @@ public Response removeCookie(String name) { response.addCookie(cookie); return this; } - - + @Override public Response text(String text) { try { response.setHeader("Cache-Control", "no-cache"); response.setContentType("text/plain;charset=utf-8"); - response.getWriter().print(text); + DispatchKit.print(text, response.getWriter()); this.written = true; return this; } catch (IOException e) { @@ -196,11 +197,8 @@ public Response html(String html) { response.setHeader("Cache-Control", "no-cache"); response.setContentType("text/html;charset=utf-8"); - PrintWriter out = response.getWriter(); - out.print(html); - out.flush(); - out.close(); - + PrintWriter writer = response.getWriter(); + DispatchKit.print(html, writer); this.written = true; return this; } catch (UnsupportedEncodingException e1) { @@ -223,11 +221,8 @@ public Response json(String json) { } try { response.setHeader("Cache-Control", "no-cache"); - PrintWriter out = response.getWriter(); - out.print(json); - out.flush(); - out.close(); - + PrintWriter writer = response.getWriter(); + DispatchKit.print(json, writer); this.written = true; return this; } catch (UnsupportedEncodingException e1) { @@ -243,12 +238,8 @@ public Response xml(String xml) { try { response.setHeader("Cache-Control", "no-cache"); response.setContentType("text/xml;charset=utf-8"); - - PrintWriter out = response.getWriter(); - out.print(xml); - out.flush(); - out.close(); - + PrintWriter writer = response.getWriter(); + DispatchKit.print(xml, writer); this.written = true; return this; } catch (UnsupportedEncodingException e1) { @@ -264,37 +255,32 @@ public Response xml(String xml) { public ServletOutputStream outputStream() throws IOException { return response.getOutputStream(); } + + @Override + public PrintWriter writer() throws IOException { + return response.getWriter(); + } @Override - public Response render(String view) { - try { - Assert.notBlank(view, "view not is null"); - - String viewPath = Path.cleanPath(view); - ModelAndView modelAndView = new ModelAndView(viewPath); - render.render(modelAndView, response.getWriter()); - return this; - } catch (IOException e) { - e.printStackTrace(); - } - return null; + public Response render(String view) throws TemplateException, IOException{ + Assert.notBlank(view, "view not is null"); + + String viewPath = Path.cleanPath(view); + ModelAndView modelAndView = new ModelAndView(viewPath); + render.render(modelAndView, response.getWriter()); + return this; } @Override - public Response render(ModelAndView modelAndView) { - try { - Assert.notNull(modelAndView, "ModelAndView not is null!"); - Assert.notBlank(modelAndView.getView(), "view not is null"); - - String viewPath = Path.cleanPath(modelAndView.getView()); - modelAndView.setView(viewPath); - - render.render(modelAndView, response.getWriter()); - return this; - } catch (IOException e) { - e.printStackTrace(); - } - return null; + public Response render(ModelAndView modelAndView) throws TemplateException, IOException { + Assert.notNull(modelAndView, "ModelAndView not is null!"); + Assert.notBlank(modelAndView.getView(), "view not is null"); + + String viewPath = Path.cleanPath(modelAndView.getView()); + modelAndView.setView(viewPath); + + render.render(modelAndView, response.getWriter()); + return this; } @Override diff --git a/pom.xml b/pom.xml index 111ee0824..3d22e5e4b 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.7.21 1.7.21 - 1.6.5 + 1.6.6 1.3.2 1.0.0 0.0.3 From 6a830071a364a5d91034e3db44b112115b9974af Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 1 Sep 2016 10:52:47 +0800 Subject: [PATCH 468/545] add json view parser --- .../main/java/com/blade/annotation/JSON.java | 33 ++ .../com/blade/annotation/RestController.java | 44 ++ .../java/com/blade/ioc/IocApplication.java | 2 + .../java/com/blade/route/RouteBuilder.java | 476 +++++++++--------- .../blade/view/handle/RouteViewHandler.java | 21 +- .../blade/view/parser/DefaultJSONParser.java | 12 + .../com/blade/view/parser/JSONParser.java | 7 + .../java/com/blade/view/parser/JSONView.java | 18 + 8 files changed, 377 insertions(+), 236 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/annotation/JSON.java create mode 100644 blade-core/src/main/java/com/blade/annotation/RestController.java create mode 100644 blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java create mode 100644 blade-core/src/main/java/com/blade/view/parser/JSONParser.java create mode 100644 blade-core/src/main/java/com/blade/view/parser/JSONView.java diff --git a/blade-core/src/main/java/com/blade/annotation/JSON.java b/blade-core/src/main/java/com/blade/annotation/JSON.java new file mode 100644 index 000000000..0881b3320 --- /dev/null +++ b/blade-core/src/main/java/com/blade/annotation/JSON.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Return JSON Params + * + * @author biezhi + * @since 1.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface JSON { + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/RestController.java b/blade-core/src/main/java/com/blade/annotation/RestController.java new file mode 100644 index 000000000..ae96002bc --- /dev/null +++ b/blade-core/src/main/java/com/blade/annotation/RestController.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Route class notes, identifying whether a class is routed + * + * @author biezhi + * @since 1.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RestController { + + /** + * @return namespace + */ + String value() default "/"; + + /** + * @return route suffix + */ + String suffix() default ""; + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index c993188c5..e2429e3fa 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -25,6 +25,7 @@ import com.blade.Blade; import com.blade.annotation.Controller; +import com.blade.annotation.RestController; import com.blade.config.BaseConfig; import com.blade.context.DynamicClassReader; import com.blade.interceptor.Interceptor; @@ -125,6 +126,7 @@ private List loadControllers() { for (String packageName : routePackages) { // Scan all Controoler controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); + controllers.addAll(classReader.getClassByAnnotation(packageName, RestController.class, true)); } } return controllers; diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index cf3745d9a..317dce201 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -1,231 +1,247 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import java.lang.reflect.Method; -import java.util.Set; - -import com.blade.Blade; -import com.blade.annotation.Controller; -import com.blade.annotation.Intercept; -import com.blade.annotation.Route; -import com.blade.context.DynamicClassReader; -import com.blade.interceptor.Interceptor; -import com.blade.kit.CollectionKit; -import com.blade.kit.StringKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -/** - * Route builder - * - * @author biezhi - * @since 1.0 - */ -public class RouteBuilder { - - /** - * Class reader, used to scan the class specified in the rules - */ - private ClassReader classReader; - - private Routers routers; - - private String[] routePackages; - - private String interceptorPackage; - - public RouteBuilder(Routers routers) { - this.routers = routers; - this.classReader = DynamicClassReader.getClassReader(); - } - - /** - * Start building route - */ - public void building() { - - this.routePackages = Blade.$().config().getRoutePackages(); - this.interceptorPackage = Blade.$().config().getInterceptorPackage(); - - // Route - if(null != routePackages && routePackages.length > 0){ - this.buildRoute(routePackages); - } - - // Inteceptor - if(StringKit.isNotBlank(interceptorPackage)){ - this.buildInterceptor(interceptorPackage); - } - - } - - /** - * Build interceptor - * - * @param interceptorPackages add the interceptor package - */ - private void buildInterceptor(String... interceptorPackages){ - - // Scan all Interceptor - Set classes = null; - - // Traversal Interceptor - for(String packageName : interceptorPackages){ - - // Scan all Interceptor - classes = classReader.getClass(packageName, Interceptor.class, false); - if(CollectionKit.isNotEmpty(classes)){ - for(ClassInfo classInfo : classes){ - Class interceptorClazz = classInfo.getClazz(); - addInterceptor(interceptorClazz); - } - } - } - } - - /** - * Build Route - * - * @param routePackages route packets to add - */ - private void buildRoute(String... routePackages){ - Set classes = null; - // Traverse route - for(String packageName : routePackages){ - // Scan all Controoler - classes = classReader.getClassByAnnotation(packageName, Controller.class, true); - if(CollectionKit.isNotEmpty(classes)){ - for(ClassInfo classInfo : classes){ - Class pathClazz = classInfo.getClazz(); - addRouter(pathClazz); - } - } - } - - } - - /** - * Parse Interceptor - * - * @param interceptor resolve the interceptor class - */ - public void addInterceptor(final Class interceptor){ - - boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); - - if(null == interceptor || !hasInterface){ - return; - } - -// ioc.addBean(interceptor); - - Intercept intercept = interceptor.getAnnotation(Intercept.class); - String partten = "/.*"; - if(null != intercept){ - partten = intercept.value(); - } - - try { - Method before = interceptor.getMethod("before", Request.class, Response.class); - Method after = interceptor.getMethod("after", Request.class, Response.class); - buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); - buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - - } - - /** - * Parse all routing in a controller - * - * @param controller resolve the routing class - */ - public void addRouter(final Class router){ - - Method[] methods = router.getMethods(); - if(null == methods || methods.length == 0){ - return; - } - - final String nameSpace = router.getAnnotation(Controller.class).value(); - - final String suffix = router.getAnnotation(Controller.class).suffix(); - - for (Method method : methods) { - Route mapping = method.getAnnotation(Route.class); - //route method - if (null != mapping) { - // build multiple route - HttpMethod methodType = mapping.method(); - String[] paths = mapping.value(); - if(null != paths && paths.length > 0){ - for(String value : paths){ - String pathV = getRoutePath(value, nameSpace, suffix); - buildRoute(router, method, pathV, methodType); - } - } - } - } - } - - private String getRoutePath(String value, String nameSpace, String suffix){ - String path = value.startsWith("/") ? value : "/" + value; - - nameSpace = nameSpace.startsWith("/") ? nameSpace : "/" + nameSpace; - path = nameSpace + path; - - path = path.replaceAll("[/]+", "/"); - - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - - path = path + suffix; - - return path; - } - - /** - * Build a route - * - * @param target route target execution class - * @param execMethod route execution method - * @param path route path - * @param method route httpmethod - */ - private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - - /** - * Build a route - * - * @param path route path - * @param target route target execution class - * @param execMethod route execution method - * @param method route httpmethod - */ - private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import java.lang.reflect.Method; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.annotation.Controller; +import com.blade.annotation.Intercept; +import com.blade.annotation.RestController; +import com.blade.annotation.Route; +import com.blade.context.DynamicClassReader; +import com.blade.interceptor.Interceptor; +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * Route builder + * + * @author biezhi + * @since 1.0 + */ +public class RouteBuilder { + + private static final Logger LOGGER = LoggerFactory.getLogger(RouteBuilder.class); + + /** + * Class reader, used to scan the class specified in the rules + */ + private ClassReader classReader; + + private Routers routers; + + private String[] routePackages; + + private String interceptorPackage; + + public RouteBuilder(Routers routers) { + this.routers = routers; + this.classReader = DynamicClassReader.getClassReader(); + } + + /** + * Start building route + */ + public void building() { + + this.routePackages = Blade.$().config().getRoutePackages(); + this.interceptorPackage = Blade.$().config().getInterceptorPackage(); + + // Route + if(null != routePackages && routePackages.length > 0){ + this.buildRoute(routePackages); + } + + // Inteceptor + if(StringKit.isNotBlank(interceptorPackage)){ + this.buildInterceptor(interceptorPackage); + } + + } + + /** + * Build interceptor + * + * @param interceptorPackages add the interceptor package + */ + private void buildInterceptor(String... interceptorPackages){ + + // Scan all Interceptor + Set classes = null; + + // Traversal Interceptor + for(String packageName : interceptorPackages){ + + // Scan all Interceptor + classes = classReader.getClass(packageName, Interceptor.class, false); + if(CollectionKit.isNotEmpty(classes)){ + for(ClassInfo classInfo : classes){ + Class interceptorClazz = classInfo.getClazz(); + addInterceptor(interceptorClazz); + } + } + } + } + + /** + * Build Route + * + * @param routePackages route packets to add + */ + private void buildRoute(String... routePackages){ + Set classes = null; + // Traverse route + for(String packageName : routePackages){ + // Scan all Controoler + classes = classReader.getClassByAnnotation(packageName, Controller.class, true); + if(CollectionKit.isNotEmpty(classes)){ + for(ClassInfo classInfo : classes){ + Class pathClazz = classInfo.getClazz(); + addRouter(pathClazz); + } + } + } + + } + + /** + * Parse Interceptor + * + * @param interceptor resolve the interceptor class + */ + public void addInterceptor(final Class interceptor){ + + boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); + + if(null == interceptor || !hasInterface){ + return; + } + + Intercept intercept = interceptor.getAnnotation(Intercept.class); + String partten = "/.*"; + if(null != intercept){ + partten = intercept.value(); + } + + try { + Method before = interceptor.getMethod("before", Request.class, Response.class); + Method after = interceptor.getMethod("after", Request.class, Response.class); + buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); + buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + + } + + /** + * Parse all routing in a controller + * + * @param controller resolve the routing class + */ + public void addRouter(final Class router){ + + Method[] methods = router.getMethods(); + if(null == methods || methods.length == 0){ + return; + } + String nameSpace = null, suffix = null; + + if(null != router.getAnnotation(Controller.class)){ + nameSpace = router.getAnnotation(Controller.class).value(); + suffix = router.getAnnotation(Controller.class).suffix(); + } + + if(null != router.getAnnotation(RestController.class)){ + nameSpace = router.getAnnotation(RestController.class).value(); + suffix = router.getAnnotation(RestController.class).suffix(); + } + + if(null == nameSpace && null == suffix){ + LOGGER.warn("Route [{}] not controller annotation", router.getName()); + return; + } + + for (Method method : methods) { + Route mapping = method.getAnnotation(Route.class); + //route method + if (null != mapping) { + // build multiple route + HttpMethod methodType = mapping.method(); + String[] paths = mapping.value(); + if(null != paths && paths.length > 0){ + for(String value : paths){ + String pathV = getRoutePath(value, nameSpace, suffix); + buildRoute(router, method, pathV, methodType); + } + } + } + } + } + + private String getRoutePath(String value, String nameSpace, String suffix){ + String path = value.startsWith("/") ? value : "/" + value; + + nameSpace = nameSpace.startsWith("/") ? nameSpace : "/" + nameSpace; + path = nameSpace + path; + + path = path.replaceAll("[/]+", "/"); + + path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + + path = path + suffix; + + return path; + } + + /** + * Build a route + * + * @param target route target execution class + * @param execMethod route execution method + * @param path route path + * @param method route httpmethod + */ + private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + + /** + * Build a route + * + * @param path route path + * @param target route target execution class + * @param execMethod route execution method + * @param method route httpmethod + */ + private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index e4dbb9a6d..5a68bae69 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -2,10 +2,13 @@ import java.lang.reflect.Method; +import com.blade.annotation.JSON; +import com.blade.annotation.RestController; import com.blade.ioc.Ioc; import com.blade.kit.reflect.ReflectKit; import com.blade.route.Route; import com.blade.view.ModelAndView; +import com.blade.view.parser.JSONView; import com.blade.web.DispatchKit; import com.blade.web.http.Request; import com.blade.web.http.Response; @@ -21,7 +24,7 @@ public RouteViewHandler(Ioc ioc) { public void handle(Request request, Response response, Route route) throws Exception { Method actionMethod = route.getAction(); Object target = route.getTarget(); - + int len = actionMethod.getParameterTypes().length; Object returnParam = null; if (len > 0) { @@ -33,11 +36,17 @@ public void handle(Request request, Response response, Route route) throws Excep if (null != returnParam) { Class returnType = returnParam.getClass(); - if (returnType == String.class) { - response.render(returnParam.toString()); - } else if (returnType == ModelAndView.class) { - ModelAndView modelAndView = (ModelAndView) returnParam; - response.render(modelAndView); + RestController restController = target.getClass().getAnnotation(RestController.class); + JSON json = actionMethod.getAnnotation(JSON.class); + if(null != restController || null != json){ + response.json(JSONView.toJSONString(returnParam)); + } else{ + if (returnType == String.class) { + response.render(returnParam.toString()); + } else if (returnType == ModelAndView.class) { + ModelAndView modelAndView = (ModelAndView) returnParam; + response.render(modelAndView); + } } } } diff --git a/blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java b/blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java new file mode 100644 index 000000000..f753b4a0c --- /dev/null +++ b/blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java @@ -0,0 +1,12 @@ +package com.blade.view.parser; + +import com.blade.kit.json.JSONKit; + +public class DefaultJSONParser implements JSONParser { + + @Override + public String toJSONSting(Object object) { + return JSONKit.toJSONString(object); + } + +} diff --git a/blade-core/src/main/java/com/blade/view/parser/JSONParser.java b/blade-core/src/main/java/com/blade/view/parser/JSONParser.java new file mode 100644 index 000000000..d54881e21 --- /dev/null +++ b/blade-core/src/main/java/com/blade/view/parser/JSONParser.java @@ -0,0 +1,7 @@ +package com.blade.view.parser; + +public interface JSONParser { + + String toJSONSting(Object object); + +} diff --git a/blade-core/src/main/java/com/blade/view/parser/JSONView.java b/blade-core/src/main/java/com/blade/view/parser/JSONView.java new file mode 100644 index 000000000..9ec80757a --- /dev/null +++ b/blade-core/src/main/java/com/blade/view/parser/JSONView.java @@ -0,0 +1,18 @@ +package com.blade.view.parser; + +public final class JSONView { + + private JSONView() { + } + + private static JSONParser JSON_PARSER = new DefaultJSONParser(); + + public static String toJSONString(Object object){ + return JSON_PARSER.toJSONSting(object); + } + + public static void setJSONParser(JSONParser jsonParser){ + JSON_PARSER = jsonParser; + } + +} From 34264d6f4968b30a3494eb012fc651edc9efcbfc Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 1 Sep 2016 11:50:28 +0800 Subject: [PATCH 469/545] fix reader chinese garbled --- blade-core/src/main/java/com/blade/Blade.java | 8 ++++++++ blade-core/src/main/java/com/blade/Const.java | 2 +- .../src/main/java/com/blade/kit/Environment.java | 13 ++++++++----- pom.xml | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 1ec0dee00..b27d58b4a 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -460,6 +460,14 @@ public Blade viewEngin(TemplateEngine templateEngine) { return this; } + + /** + * @return Return Current TemplateEngine + */ + public TemplateEngine viewEngin() { + return this.templateEngine; + } + /** * Setting the frame static file folder * diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index f31699df9..8ac85266c 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -24,7 +24,7 @@ public interface Const { // current blade version - String BLADE_VERSION = "1.6.6"; + String BLADE_VERSION = "1.6.6-alpha"; // default embedd server context path String DEFAULT_CONTEXTPATH = "/"; diff --git a/blade-kit/src/main/java/com/blade/kit/Environment.java b/blade-kit/src/main/java/com/blade/kit/Environment.java index 5f89a94c4..facfbdb16 100644 --- a/blade-kit/src/main/java/com/blade/kit/Environment.java +++ b/blade-kit/src/main/java/com/blade/kit/Environment.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -51,11 +52,13 @@ public Environment(String confPath){ private Map loadMap(String confPath){ Map envMap = new HashMap(20); Properties config = new Properties(); - confPath = confPath.startsWith("/") ? confPath : "/" + confPath; - InputStream in = this.getClass().getResourceAsStream(confPath); + + InputStreamReader inr = null; try { - if(null != in){ - config.load(in); + InputStream inputStream = Environment.class.getClassLoader().getResourceAsStream(confPath); + if(null != inputStream){ + inr = new InputStreamReader(inputStream, "UTF-8"); + config.load(inr); // parse properties file Set> set = config.entrySet(); if(CollectionKit.isNotEmpty(set)){ @@ -77,7 +80,7 @@ private Map loadMap(String confPath){ } catch (IOException e) { LOGGER.error("Load environment config error", e); } finally { - IOKit.closeQuietly(in); + IOKit.closeQuietly(inr); } return envMap; } diff --git a/pom.xml b/pom.xml index 3d22e5e4b..c2413c04f 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.7.21 1.7.21 - 1.6.6 + 1.6.6-alpha 1.3.2 1.0.0 0.0.3 From 2b83baec2f28a706fbacb6288df121dfd63cca69 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 1 Sep 2016 18:04:07 +0800 Subject: [PATCH 470/545] fix some bug --- .../main/java/com/blade/config/ApplicationConfig.java | 10 +++++----- .../java/com/blade/context/ApplicationContext.java | 1 - blade-kit/src/main/java/com/blade/kit/Environment.java | 3 ++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 49801385a..79190ed88 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -83,19 +83,19 @@ public void setEnv(Environment environment) { this.view500 = environment.getString("app.view.500"); this.view404 = environment.getString("app.view.404"); - String httpFilters = environment.getString("http.filters"); + String statics = environment.getString("app.statics"); String basePackage = environment.getString("app.base-package"); Integer port = environment.getInt("server.port"); if (null != port) { Blade.$().listen(port); } - - if (StringKit.isNotBlank(httpFilters)) { - this.setStaticFolders(httpFilters.split(",")); + + if (StringKit.isNotBlank(statics)) { + this.setStaticFolders(statics.split(",")); } - if (StringKit.isNotBlank(basePackage)) { + if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { this.setBasePackage(basePackage); } isInit = true; diff --git a/blade-core/src/main/java/com/blade/context/ApplicationContext.java b/blade-core/src/main/java/com/blade/context/ApplicationContext.java index 155200dfe..a6a6bc420 100644 --- a/blade-core/src/main/java/com/blade/context/ApplicationContext.java +++ b/blade-core/src/main/java/com/blade/context/ApplicationContext.java @@ -16,7 +16,6 @@ public static void init(Blade blade) throws BladeException{ try { blade.bootstrap().init(blade); - blade.applicationConfig().setBasePackage(blade.bootstrap().getClass().getPackage().getName()); if(!blade.config().isInit()){ blade.loadAppConf(Const.APP_PROPERTIES); diff --git a/blade-kit/src/main/java/com/blade/kit/Environment.java b/blade-kit/src/main/java/com/blade/kit/Environment.java index facfbdb16..4d74973fc 100644 --- a/blade-kit/src/main/java/com/blade/kit/Environment.java +++ b/blade-kit/src/main/java/com/blade/kit/Environment.java @@ -110,7 +110,8 @@ public Map getEnvMap(){ } public String getString(String key) { - return envMap.get(key); + String value = envMap.get(key); + return null != value ? value.trim() : null; } public String getString(String key, String defaultValue) { From 25f3c67828bafa0c2846982673279aa91a214225 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 1 Sep 2016 18:10:36 +0800 Subject: [PATCH 471/545] upgrade blade to 1.6.6-alpha --- README.md | 4 ++-- README_CN.md | 39 +++++++++++++++++---------------------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index ab3fb5296..22b9892f0 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.5 + 1.6.6-alpha com.bladejava @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.5' +compile 'com.bladejava:blade-core:1.6.6-alpha' compile 'com.bladejava:blade-embed-jetty:0.0.3' ``` diff --git a/README_CN.md b/README_CN.md index 5f73f0156..0cc24e7da 100644 --- a/README_CN.md +++ b/README_CN.md @@ -38,19 +38,19 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 com.bladejava blade-core - 1.6.4 + 1.6.6-alpha com.bladejava blade-embed-jetty - 0.0.2 + 0.0.3 ``` 或者 `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.3' +compile 'com.bladejava:blade-core:1.6.6-alpha' compile 'com.bladejava:blade-startup:0.0.1' ``` @@ -58,11 +58,10 @@ compile 'com.bladejava:blade-startup:0.0.1' ```java public static void main(String[] args) { - Blade blade = me(); - blade.get("/", (request, response) -> { + $().get("/", (request, response) -> { response.html("

Hello blade!

"); }); - blade.start(EmbedJettyServer.class); + $().start(EmbedJettyServer.class); } ``` @@ -72,12 +71,11 @@ public static void main(String[] args) { ```java public static void main(String[] args) { - Blade blade = me(); - blade.get("/user/21", getxxx); - blade.post("/save", postxxx); - blade.delete("/del/21", deletexxx); - blade.put("/put", putxxx); - blade.start(EmbedJettyServer.class); + $().get("/user/21", getxxx); + $().post("/save", postxxx); + $().delete("/del/21", deletexxx); + $().put("/put", putxxx); + $().start(EmbedJettyServer.class); } ``` @@ -85,20 +83,19 @@ public static void main(String[] args) { ```java public static void main(String[] args) { - Blade blade = me(); - blade.get("/user/:uid", (request, response) -> { + $().get("/user/:uid", (request, response) -> { Integer uid = request.paramAsInt("uid"); response.text("uid : " + uid); }); - blade.get("/users/:uid/post/:pid", (request, response) -> { + $().get("/users/:uid/post/:pid", (request, response) -> { Integer uid = request.paramAsInt("uid"); Integer pid = request.paramAsInt("pid"); String msg = "uid = " + uid + ", pid = " + pid; response.text(msg); }); - blade.start(EmbedJettyServer.class); + $().start(EmbedJettyServer.class); } ``` @@ -106,12 +103,11 @@ public static void main(String[] args) { ```java public static void main(String[] args) { - Blade blade = me(); - blade.get("/user", (request, response) -> { + $().get("/user", (request, response) -> { Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); }); - blade.start(EmbedJettyServer.class); + $().start(EmbedJettyServer.class); } ``` @@ -149,11 +145,10 @@ POST /upload_img UploadRoute.upload_img ```java public static void main(String[] args) { - Blade blade = me(); - blade.before("/.*", (request, response) -> { + $().before("/.*", (request, response) -> { System.out.println("before..."); }); - blade.start(EmbedJettyServer.class); + $().start(EmbedJettyServer.class); } ``` From 13a67c90063f3ad735b50f0ff8612c38ca3de95f Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 1 Sep 2016 19:04:52 +0800 Subject: [PATCH 472/545] fix read interceptor is null --- .../src/main/java/com/blade/ioc/IocApplication.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index e2429e3fa..b1959dc0d 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -25,6 +25,7 @@ import com.blade.Blade; import com.blade.annotation.Controller; +import com.blade.annotation.Intercept; import com.blade.annotation.RestController; import com.blade.config.BaseConfig; import com.blade.context.DynamicClassReader; @@ -137,7 +138,14 @@ private List loadInterceptors() { String interceptorPackage = blade.config().getInterceptorPackage(); if (StringKit.isNotBlank(interceptorPackage)) { interceptors = new ArrayList(10); - interceptors.addAll(classReader.getClass(interceptorPackage, Interceptor.class, false)); + Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); + if(null != intes){ + for(ClassInfo classInfo : intes){ + if(null != classInfo.getClazz().getInterfaces() && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)){ + interceptors.add(classInfo); + } + } + } } return interceptors; } From 63113d61aefbe61112be53467b82892762d0c224 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 1 Sep 2016 19:11:00 +0800 Subject: [PATCH 473/545] upgrade --- .../java/com/blade/kit/HttpRequestTest.java | 33 ----------- .../src/test/java/com/blade/kit/JSONTest.java | 59 ------------------- .../test/java/com/blade/kit/StringTest.java | 36 ----------- .../src/test/java/com/blade/kit/TaskTest.java | 35 ----------- .../src/test/java/com/blade/kit/User.java | 28 --------- 5 files changed, 191 deletions(-) delete mode 100644 blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java delete mode 100644 blade-kit/src/test/java/com/blade/kit/JSONTest.java delete mode 100644 blade-kit/src/test/java/com/blade/kit/StringTest.java delete mode 100644 blade-kit/src/test/java/com/blade/kit/TaskTest.java delete mode 100644 blade-kit/src/test/java/com/blade/kit/User.java diff --git a/blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java b/blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java deleted file mode 100644 index 974cfbb40..000000000 --- a/blade-kit/src/test/java/com/blade/kit/HttpRequestTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.blade.kit; - -import java.io.File; - -import com.blade.kit.http.HttpRequest; - -public class HttpRequestTest { - - public static void main(String[] args) { - - // 发送一个GET请求并获取内容 - String body = HttpRequest.get("http://bladejava.com").body(); - System.out.println(body); - - // 发送一个带heder的请求 - String res = HttpRequest.get("http://bladejava.com").accept("application/json") - .userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0").body(); - System.out.println(res); - - // 发送一个POST请求 - HttpRequest.post("http://www.example.com").part("id", 20).part("name", "jack").body(); - - // 带认证的请求 - int response = HttpRequest.get("http://google.com").basic("username", "p4ssw0rd").code(); - System.out.println(response); - - // 下载一个图片 - File file = new File("F:/a.png"); - HttpRequest.get("http://img.blog.csdn.net/20150601232126808").receive(file); - - } - -} diff --git a/blade-kit/src/test/java/com/blade/kit/JSONTest.java b/blade-kit/src/test/java/com/blade/kit/JSONTest.java deleted file mode 100644 index de991dec7..000000000 --- a/blade-kit/src/test/java/com/blade/kit/JSONTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.blade.kit; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.blade.kit.json.JSON; -import com.blade.kit.json.JSONArray; -import com.blade.kit.json.JSONHelper; -import com.blade.kit.json.JSONKit; -import com.blade.kit.json.JSONObject; -import com.blade.kit.json.JSONValue; - -public class JSONTest { - - public static void main(String[] args) { - //[{"text": "首页","href": "/"},{"text": "博客","href": "blog"},{"text": "关于","href": "about"},{"text": "联系","href": "contact"}] - String json = "[{\"text\": \"博客\",\"href\": \"blog\"}]"; - - // 下面构造两个map、一个list和一个Employee对象 - Map map1 = new HashMap(); - map1.put("name", "Alexia"); - map1.put("sex", "female"); - map1.put("age", "23"); - - List> list = new ArrayList>(); - Map map = new HashMap(); - - map.put("abc", "123456"); - map.put("def", "hmm"); - list.add(map); - - String string = JSONKit.toJSONString(list); - System.out.println(string); - - List list2 = JSON.parse(json).asArray().values(); - System.out.println(list2); - - JSONObject obj1 = new JSONObject(); - obj1.put("name", "jack"); - - System.out.println(obj1); - - JSONArray obj2 = new JSONArray(); - obj2.add("123"); - - System.out.println(obj2); - - User u1 = new User(); - u1.setAge(22); -// u1.setName("rose"); - - System.out.println(JSONHelper.toJSONValue(u1).toString()); - -// System.out.println(JSONKit.toJSONString(u1)); - } - -} diff --git a/blade-kit/src/test/java/com/blade/kit/StringTest.java b/blade-kit/src/test/java/com/blade/kit/StringTest.java deleted file mode 100644 index f86998ce3..000000000 --- a/blade-kit/src/test/java/com/blade/kit/StringTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.blade.kit; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.blade.kit.StringKit; - - -public class StringTest { - - public static void main(String[] args) { - - //判断是否为空 - String str = "hello"; - System.out.println(StringKit.isNotEmpty(str)); - - //分割字符串 - String[] arr = StringKit.split("1,2,3", ","); - System.out.println(Arrays.toString(arr)); - - //生成5个随机字符串 - System.out.println(StringKit.random(5)); - - //将字符串20转换为long类型,如果为null或者空则给一个默认值10 - System.out.println(StringKit.toLong("20", 10)); - - List list = new ArrayList(); - list.add(22); - list.add(30); - //将集合用指定字符分隔 - String listString = StringKit.join(list, "|"); - System.out.println(listString); - } - -} diff --git a/blade-kit/src/test/java/com/blade/kit/TaskTest.java b/blade-kit/src/test/java/com/blade/kit/TaskTest.java deleted file mode 100644 index 56b8d192a..000000000 --- a/blade-kit/src/test/java/com/blade/kit/TaskTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.blade.kit; - -import java.util.Date; -import java.util.concurrent.TimeUnit; - -import com.blade.kit.TaskKit; - - -public class TaskTest { - - public static void main(String[] args) { - TaskKit.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - System.out.println("每隔两秒执行一次"); - } - }, 2); - - TaskKit.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - System.out.println("在指定的延时之后开始以固定的频率来运行任务。后续任务的启动时间不受前次任务延时影响。"); - } - }, 10, 3, TimeUnit.SECONDS); - - TaskKit.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - System.out.println("在指定的时间点启动,两次任务间保持固定的时间间隔"); - } - }, new Date(), 3, TimeUnit.SECONDS); - - } - -} diff --git a/blade-kit/src/test/java/com/blade/kit/User.java b/blade-kit/src/test/java/com/blade/kit/User.java deleted file mode 100644 index 7dfc118d4..000000000 --- a/blade-kit/src/test/java/com/blade/kit/User.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.blade.kit; - -public class User { - - private String name; - private long age; - - public User() { - // TODO Auto-generated constructor stub - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public long getAge() { - return age; - } - - public void setAge(long age) { - this.age = age; - } - -} \ No newline at end of file From b8876d4b5103f468e6c3424694341c83cdced267 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 1 Sep 2016 21:38:45 +0800 Subject: [PATCH 474/545] fix jdk1.6 build error --- .../src/main/java/com/blade/asm/AsmKit.java | 183 ++++++----- .../com/blade/view/handle/MethodArgument.java | 285 +++++++++--------- 2 files changed, 236 insertions(+), 232 deletions(-) diff --git a/blade-core/src/main/java/com/blade/asm/AsmKit.java b/blade-core/src/main/java/com/blade/asm/AsmKit.java index 7f91709c3..2dbe01d72 100644 --- a/blade-core/src/main/java/com/blade/asm/AsmKit.java +++ b/blade-core/src/main/java/com/blade/asm/AsmKit.java @@ -1,92 +1,91 @@ -package com.blade.asm; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -public final class AsmKit { - - /** - * - *

- * 比较参数类型是否一致 - *

- * - * @param types - * asm的类型({@link Type}) - * @param clazzes - * java 类型({@link Class}) - * @return - */ - private static boolean sameType(Type[] types, Class[] clazzes) { - // 个数不同 - if (types.length != clazzes.length) { - return false; - } - - for (int i = 0; i < types.length; i++) { - if (!Type.getType(clazzes[i]).equals(types[i])) { - return false; - } - } - return true; - } - - /** - * - *

- * 获取方法的参数名 - *

- * - * @param m - * @return - */ - public static String[] getMethodParamNames(final Method m) { - final String[] paramNames = new String[m.getParameterTypes().length]; - final String n = m.getDeclaringClass().getName(); - ClassReader cr = null; - try { - cr = new ClassReader(n); - } catch (IOException e) { - throw new RuntimeException(e); - } - cr.accept(new ClassVisitor(Opcodes.ASM4) { - @Override - public MethodVisitor visitMethod(final int access, final String name, final String desc, - final String signature, final String[] exceptions) { - final Type[] args = Type.getArgumentTypes(desc); - // 方法名相同并且参数个数相同 - if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { - return super.visitMethod(access, name, desc, signature, exceptions); - } - MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); - return new MethodVisitor(Opcodes.ASM4, v) { - @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, - int index) { - int i = index - 1; - // 如果是静态方法,则第一就是参数 - // 如果不是静态方法,则第一个是"this",然后才是方法的参数 - if (Modifier.isStatic(m.getModifiers())) { - i = index; - } - if (i >= 0 && i < paramNames.length) { - paramNames[i] = name; - } - super.visitLocalVariable(name, desc, signature, start, end, index); - } - - }; - } - }, 0); - return paramNames; - } - -} +package com.blade.asm; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +public final class AsmKit { + + /** + * + *

+ * 比较参数类型是否一致 + *

+ * + * @param types + * asm的类型({@link Type}) + * @param clazzes + * java 类型({@link Class}) + * @return + */ + private static boolean sameType(Type[] types, Class[] clazzes) { + // 个数不同 + if (types.length != clazzes.length) { + return false; + } + + for (int i = 0; i < types.length; i++) { + if (!Type.getType(clazzes[i]).equals(types[i])) { + return false; + } + } + return true; + } + + /** + * + *

+ * 获取方法的参数名 + *

+ * + * @param m + * @return + */ + public static String[] getMethodParamNames(final Method m) { + final String[] paramNames = new String[m.getParameterTypes().length]; + final String n = m.getDeclaringClass().getName(); + ClassReader cr = null; + try { + cr = new ClassReader(n); + } catch (IOException e) { + throw new RuntimeException(e); + } + cr.accept(new ClassVisitor(Opcodes.ASM5) { + @Override + public MethodVisitor visitMethod(final int access, final String name, final String desc, + final String signature, final String[] exceptions) { + final Type[] args = Type.getArgumentTypes(desc); + // 方法名相同并且参数个数相同 + if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { + return super.visitMethod(access, name, desc, signature, exceptions); + } + MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); + return new MethodVisitor(Opcodes.ASM5, v) { + @Override + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, + int index) { + int i = index - 1; + // 如果是静态方法,则第一就是参数 + // 如果不是静态方法,则第一个是"this",然后才是方法的参数 + if (Modifier.isStatic(m.getModifiers())) { + i = index; + } + if (i >= 0 && i < paramNames.length) { + paramNames[i] = name; + } + super.visitLocalVariable(name, desc, signature, start, end, index); + } + }; + } + }, 0); + return paramNames; + } + +} diff --git a/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java index 7e330245f..d5461e060 100644 --- a/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java @@ -1,140 +1,145 @@ -package com.blade.view.handle; - -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; - -import com.blade.annotation.PathVariable; -import com.blade.annotation.RequestParam; -import com.blade.asm.AsmKit; -import com.blade.exception.BladeException; -import com.blade.exception.NotFoundException; -import com.blade.kit.StringKit; -import com.blade.view.ModelAndView; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.multipart.FileItem; - -public final class MethodArgument { - - public static Object[] getArgs(Request request, Response response, Method actionMethod) throws BladeException{ - Parameter[] parameters = actionMethod.getParameters(); - Object[] args = new Object[parameters.length]; - - try { - actionMethod.setAccessible(true); - String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); - - for (int i = 0, len = parameters.length; i < len; i++) { - - Class argType = parameters[i].getType(); - if (argType.getName().equals(Request.class.getName())) { - args[i] = request; - continue; - } - - if (argType.getName().equals(Response.class.getName())) { - args[i] = response; - continue; - } - - if (argType.getName().equals(ModelAndView.class.getName())) { - args[i] = new ModelAndView(); - continue; - } - - if(argType.getName().equals(FileItem.class.getName())){ - args[i] = new ModelAndView(); - continue; - } - - RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); - if (null != requestParam) { - String paramName = requestParam.value(); - String val = request.query(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.query(paramName); - } else { - if (StringKit.isBlank(val)) { - throw new NotFoundException("request param [" + paramName + "] is null"); - } - } - args[i] = getRequestParam(argType, val, requestParam.defaultValue()); - continue; - } - - PathVariable pathVariable = parameters[i].getAnnotation(PathVariable.class); - if (null != pathVariable) { - String paramName = pathVariable.value(); - String val = request.param(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.param(paramName); - } else { - if (StringKit.isBlank(val)) { - throw new NotFoundException("path param [" + paramName + "] is null"); - } - } - args[i] = getRequestParam(argType, val, null); - continue; - } - } - return args; - } catch (BladeException e) { - throw e; - } - } - - private static Object getRequestParam(Class parameterType, String val, String defaultValue) { - Object result = null; - if (parameterType.equals(String.class)) { - if (StringKit.isNotBlank(val)) { - result = val; - } else { - if (null != defaultValue) { - result = defaultValue; - } - } - } else if (parameterType.equals(Integer.class)) { - if (StringKit.isNotBlank(val)) { - result = Integer.parseInt(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Integer.parseInt(defaultValue); - } - } - } else if (parameterType.equals(int.class)) { - if (StringKit.isNotBlank(val)) { - result = Integer.parseInt(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Integer.parseInt(defaultValue); - } else { - result = 0; - } - } - } else if (parameterType.equals(Long.class)) { - if (StringKit.isNotBlank(val)) { - result = Long.parseLong(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Long.parseLong(defaultValue); - } - } - } else if (parameterType.equals(long.class)) { - if (StringKit.isNotBlank(val)) { - result = Long.parseLong(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Long.parseLong(defaultValue); - } else { - result = 0L; - } - } - } - return result; - } - -} +package com.blade.view.handle; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import com.blade.annotation.PathVariable; +import com.blade.annotation.RequestParam; +import com.blade.asm.AsmKit; +import com.blade.exception.BladeException; +import com.blade.exception.NotFoundException; +import com.blade.kit.StringKit; +import com.blade.view.ModelAndView; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.multipart.FileItem; + +public final class MethodArgument { + + public static Object[] getArgs(Request request, Response response, Method actionMethod) throws BladeException{ + Class[] parameters = actionMethod.getParameterTypes(); + Annotation[][] paramterAnnotations = actionMethod.getParameterAnnotations(); + + Object[] args = new Object[parameters.length]; + + try { + actionMethod.setAccessible(true); + String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); + + for (int i = 0, len = parameters.length; i < len; i++) { + + Class argType = parameters[i]; + if (argType.getName().equals(Request.class.getName())) { + args[i] = request; + continue; + } + + if (argType.getName().equals(Response.class.getName())) { + args[i] = response; + continue; + } + + if (argType.getName().equals(ModelAndView.class.getName())) { + args[i] = new ModelAndView(); + continue; + } + + if(argType.getName().equals(FileItem.class.getName())){ + args[i] = new ModelAndView(); + continue; + } + + Annotation annotation = paramterAnnotations[i][0]; + if(null != annotation){ + if(annotation.annotationType().equals(RequestParam.class)){ + RequestParam requestParam = (RequestParam) annotation; + String paramName = requestParam.value(); + String val = request.query(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.query(paramName); + } else { + if (StringKit.isBlank(val)) { + throw new NotFoundException("request param [" + paramName + "] is null"); + } + } + args[i] = getRequestParam(argType, val, requestParam.defaultValue()); + continue; + } + + if(annotation.annotationType().equals(PathVariable.class)){ + PathVariable pathVariable = (PathVariable) annotation; + String paramName = pathVariable.value(); + String val = request.param(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.param(paramName); + } else { + if (StringKit.isBlank(val)) { + throw new NotFoundException("path param [" + paramName + "] is null"); + } + } + args[i] = getRequestParam(argType, val, null); + continue; + } + } + } + return args; + } catch (BladeException e) { + throw e; + } + } + + private static Object getRequestParam(Class parameterType, String val, String defaultValue) { + Object result = null; + if (parameterType.equals(String.class)) { + if (StringKit.isNotBlank(val)) { + result = val; + } else { + if (null != defaultValue) { + result = defaultValue; + } + } + } else if (parameterType.equals(Integer.class)) { + if (StringKit.isNotBlank(val)) { + result = Integer.parseInt(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Integer.parseInt(defaultValue); + } + } + } else if (parameterType.equals(int.class)) { + if (StringKit.isNotBlank(val)) { + result = Integer.parseInt(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Integer.parseInt(defaultValue); + } else { + result = 0; + } + } + } else if (parameterType.equals(Long.class)) { + if (StringKit.isNotBlank(val)) { + result = Long.parseLong(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Long.parseLong(defaultValue); + } + } + } else if (parameterType.equals(long.class)) { + if (StringKit.isNotBlank(val)) { + result = Long.parseLong(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Long.parseLong(defaultValue); + } else { + result = 0L; + } + } + } + return result; + } + +} From f1c763d0fa70bdfefa140a94a6aa6aa646c2e7a2 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 1 Sep 2016 21:57:28 +0800 Subject: [PATCH 475/545] => add comment --- blade-core/README.md | 3 - blade-core/src/main/java/com/blade/Blade.java | 1554 ++++++++--------- .../src/main/java/com/blade/Bootstrap.java | 78 +- blade-core/src/main/java/com/blade/Const.java | 108 +- .../java/com/blade/annotation/Controller.java | 86 +- .../java/com/blade/annotation/Intercept.java | 78 +- .../main/java/com/blade/annotation/JSON.java | 64 +- .../com/blade/annotation/PathVariable.java | 53 +- .../com/blade/annotation/RequestParam.java | 59 +- .../com/blade/annotation/RestController.java | 88 +- .../main/java/com/blade/annotation/Route.java | 116 +- .../src/main/java/com/blade/asm/AsmKit.java | 21 + .../com/blade/config/ApplicationConfig.java | 436 ++--- .../java/com/blade/config/BaseConfig.java | 35 +- .../java/com/blade/config/ConfigLoader.java | 178 +- .../com/blade/context/ApplicationContext.java | 95 +- .../blade/context/ApplicationWebContext.java | 212 +-- .../com/blade/context/DynamicClassReader.java | 106 +- .../java/com/blade/embedd/EmbedServer.java | 68 +- .../com/blade/exception/BladeException.java | 65 +- .../com/blade/exception/ConfigException.java | 65 +- .../blade/exception/EmbedServerException.java | 65 +- .../exception/MethodInvokeException.java | 66 +- .../blade/exception/NotFoundException.java | 65 +- .../com/blade/interceptor/Interceptor.java | 64 +- .../main/java/com/blade/ioc/BeanDefine.java | 138 +- .../src/main/java/com/blade/ioc/Ioc.java | 106 +- .../src/main/java/com/blade/ioc/IocKit.java | 158 +- .../main/java/com/blade/ioc/SimpleIoc.java | 446 ++--- .../com/blade/ioc/annotation/Component.java | 70 +- .../java/com/blade/ioc/annotation/Inject.java | 2 +- .../com/blade/ioc/annotation/Service.java | 70 +- .../com/blade/ioc/injector/FieldInjector.java | 106 +- .../java/com/blade/ioc/injector/Injector.java | 50 +- .../blade/ioc/loader/IocAnnotationLoader.java | 6 + .../java/com/blade/ioc/loader/IocLoader.java | 52 +- .../main/java/com/blade/plugin/Plugin.java | 70 +- .../src/main/java/com/blade/route/Route.java | 278 +-- .../java/com/blade/route/RouteBuilder.java | 492 +++--- .../java/com/blade/route/RouteException.java | 2 +- .../main/java/com/blade/route/RouteGroup.java | 152 +- .../java/com/blade/route/RouteHandler.java | 62 +- .../java/com/blade/route/RouteMatcher.java | 352 ++-- .../main/java/com/blade/route/Routers.java | 366 ++-- .../route/loader/AbstractFileRouteLoader.java | 444 ++--- .../loader/ClassPathControllerLoader.java | 170 +- .../route/loader/ClassPathRouteLoader.java | 2 +- .../blade/route/loader/ControllerLoader.java | 2 +- .../route/loader/FileSystemRouteLoader.java | 2 +- .../com/blade/route/loader/RouteLoader.java | 2 +- .../java/com/blade/view/ModelAndView.java | 244 +-- .../com/blade/view/handle/MethodArgument.java | 15 + .../blade/view/handle/RouteViewHandler.java | 199 ++- .../blade/view/parser/DefaultJSONParser.java | 45 +- .../com/blade/view/parser/JSONParser.java | 35 +- .../java/com/blade/view/parser/JSONView.java | 57 +- .../blade/view/template/DefaultEngine.java | 156 +- .../com/blade/view/template/JspEngine.java | 156 +- .../blade/view/template/TemplateEngine.java | 64 +- .../view/template/TemplateException.java | 88 +- .../java/com/blade/web/DispatcherHandler.java | 406 ++--- .../java/com/blade/web/DispatcherServlet.java | 2 +- .../java/com/blade/web/StaticFileFilter.java | 97 +- .../java/com/blade/web/http/HttpMethod.java | 2 +- .../java/com/blade/web/http/HttpStatus.java | 92 +- .../main/java/com/blade/web/http/Path.java | 200 +-- .../main/java/com/blade/web/http/Request.java | 722 ++++---- .../java/com/blade/web/http/Response.java | 498 +++--- .../web/http/wrapper/ServletRequest.java | 1156 ++++++------ .../web/http/wrapper/ServletResponse.java | 622 +++---- .../com/blade/web/http/wrapper/Session.java | 2 +- .../com/blade/web/multipart/FileItem.java | 156 +- .../com/blade/web/multipart/Multipart.java | 654 +++---- .../web/multipart/MultipartException.java | 2 +- .../blade/web/multipart/MultipartHandler.java | 2 +- 75 files changed, 6693 insertions(+), 6407 deletions(-) delete mode 100644 blade-core/README.md diff --git a/blade-core/README.md b/blade-core/README.md deleted file mode 100644 index 9d3e67164..000000000 --- a/blade-core/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# blade-core - -`blade`框架核心库,是整个web运行的基础服务。 \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index b27d58b4a..5697bee43 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -1,778 +1,778 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.io.InputStream; -import java.text.ParseException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.blade.config.ApplicationConfig; -import com.blade.config.BaseConfig; -import com.blade.config.ConfigLoader; -import com.blade.embedd.EmbedServer; -import com.blade.exception.EmbedServerException; -import com.blade.interceptor.Interceptor; -import com.blade.ioc.Ioc; -import com.blade.ioc.SimpleIoc; -import com.blade.kit.Assert; -import com.blade.kit.Environment; -import com.blade.kit.StringKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.plugin.Plugin; -import com.blade.route.Route; -import com.blade.route.RouteBuilder; -import com.blade.route.RouteException; -import com.blade.route.RouteGroup; -import com.blade.route.RouteHandler; -import com.blade.route.Routers; -import com.blade.route.loader.ClassPathRouteLoader; -import com.blade.view.template.DefaultEngine; -import com.blade.view.template.TemplateEngine; -import com.blade.web.http.HttpMethod; - -/** - * Blade Core Class - * - * @author biezhi - * @since 1.0 - */ -public final class Blade { - - // blade initialize - private boolean isInit = false; - - // blade bootstrap config class - private Bootstrap bootstrap = null; - - // global configuration Object - private ApplicationConfig applicationConfig = null; - - // ioc container - private Ioc ioc = new SimpleIoc(); - - // default render is jspRender - private TemplateEngine templateEngine = null; - - // routes - private Routers routers = new Routers(); - - // routebuilder - private RouteBuilder routeBuilder; - - // jetty start port - private int port = Const.DEFAULT_PORT; - - // default context path - private String contextPath = Const.DEFAULT_CONTEXTPATH; - - // enableServer - private Boolean enableServer = false; - - // plugins - private Set> plugins; - - // global environment - private Environment environment; - - // config loader - private ConfigLoader configLoader; - - private Blade() { - this.environment = new Environment(); - this.applicationConfig = new ApplicationConfig(); - this.templateEngine = new DefaultEngine(); - this.plugins = new HashSet>(); - this.routeBuilder = new RouteBuilder(this.routers); - this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); - } - - static final class BladeHolder { - private static final Blade ME = new Blade(); - } - - /** - * @return Single case method returns Blade object - */ - @Deprecated - public static final Blade me() { - return BladeHolder.ME; - } - - /** - * - * @param appConf - * @return - */ - @Deprecated - public static final Blade me(String confPath) { - Blade blade = BladeHolder.ME; - blade.environment.add(confPath); - return blade; - } - - /** - * @return Single case method returns Blade object - */ - public static final Blade $() { - return BladeHolder.ME; - } - - /** - * @param confPath - * @return - */ - public static final Blade $(String confPath) { - Blade blade = BladeHolder.ME; - blade.environment.add(confPath); - return blade; - } - - /** - * Set Blade initialize - * - * @param isInit - * initialize - */ - public void init() { - if (!this.isInit) { - this.isInit = true; - } - } - - /** - * @return return route manager - */ - public Routers routers() { - return routers; - } - - /** - * @return return RouteBuilder - */ - public RouteBuilder routeBuilder() { - return routeBuilder; - } - - /** - * @return return ConfigLoader - */ - public ConfigLoader configLoader() { - return configLoader; - } - - /** - * @return return blade ioc container - */ - public Ioc ioc() { - return ioc; - } - - /** - * Setting a ioc container - * - * @param container - * ioc object - * @return return blade - */ - public Blade container(Ioc ioc) { - Assert.notNull(ioc); - this.ioc = ioc; - this.configLoader.setIoc(ioc); - return this; - } - - /** - * Setting Properties configuration file File path based on classpath - * - * @param confPath - * properties file name - * @return return blade - */ - public Blade loadAppConf(String confPath) { - Assert.notBlank(confPath); - environment.add(confPath); - return this; - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackage(String packageName) { - return this.addRoutePackages(packageName); - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackages(String... packages) { - Assert.notNull(packages); - applicationConfig.addRoutePackages(packages); - return this; - } - - /** - * - * @param basePackage - * @return - */ - public Blade basePackage(String basePackage) { - Assert.notBlank(basePackage); - applicationConfig.setBasePackage(basePackage); - applicationConfig.addIocPackages(basePackage + ".service.*"); - applicationConfig.addRoutePackages(basePackage + ".controller"); - applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); - return this; - } - - /** - * Setting the path where the interceptor, e.g:com.bladejava.interceptor - * - * @param packageName - * interceptor packagename - * @return return blade - */ - public Blade interceptor(String packageName) { - Assert.notBlank(packageName); - applicationConfig.setInterceptorPackage(packageName); - return this; - } - - /** - * Setting Ioc packages, e.g:com.bladejava.service - * - * @param packages - * All need to do into the package, can be introduced into a - * number of - * @return return blade - */ - public Blade ioc(String... packages) { - Assert.notNull(packages); - applicationConfig.addIocPackages(packages); - return this; - } - - /** - * Add a route - * - * @param path - * route path - * @param target - * Target object for routing - * @param method - * The method name of the route (at the same time, the HttpMethod - * is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @return return blade - */ - public Blade route(String path, Class clazz, String method) { - routers.route(path, clazz, method); - return this; - } - - /** - * Register a functional route - * - * @param path - * route url - * @param clazz - * route processing class - * @param method - * route processing method name - * @param httpMethod - * HttpMethod Type, GET/POST/... - * @return Blade return blade - */ - public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { - routers.route(path, clazz, method, httpMethod); - return this; - } - - /** - * Add a route list - * - * @param routes - * route list - * @return return blade - */ - public Blade routes(List routes) { - Assert.notEmpty(routes, "Routes not is empty!"); - routers.addRoutes(routes); - return this; - } - - /** - * Register a GET request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade get(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.GET); - return this; - } - - /** - * Register a POST request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade post(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.POST); - return this; - } - - /** - * Register a DELETE request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade delete(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.DELETE); - return this; - } - - /** - * Register a PUT request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade put(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.PUT); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade all(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade any(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Route Group. e.g blade.group('/users').get().post() - * - * @param g - * @return return blade - */ - public RouteGroup group(String prefix) { - Assert.notNull(prefix, "Route group prefix not is null"); - return new RouteGroup(this, prefix); - } - - /** - * Register a pre routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade before(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.BEFORE); - return this; - } - - /** - * Register a after routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade after(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.AFTER); - return this; - } - - /** - * Setting Render Engin, Default is JspRender - * - * @param templateEngine - * Render engine object - * @return return blade - */ - public Blade viewEngin(TemplateEngine templateEngine) { - Assert.notNull(templateEngine); - this.templateEngine = templateEngine; - return this; - } - - - /** - * @return Return Current TemplateEngine - */ - public TemplateEngine viewEngin() { - return this.templateEngine; - } - - /** - * Setting the frame static file folder - * - * @param folders - * List of directories to filter, e.g: "/public,/static,/images" - * @return return blade - */ - public Blade staticFolder(final String... folders) { - Assert.notNull(folders); - applicationConfig.setStaticFolders(folders); - return this; - } - - /** - * Dynamically set the global initialization class, the embedded Jetty boot - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Bootstrap bootstrap) { - Assert.notNull(bootstrap); - this.bootstrap = bootstrap; - return this; - } - - /** - * Dynamically set global initialization class - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Class bootstrap) { - Assert.notNull(bootstrap); - try { - Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); - ioc.addBean(Bootstrap.class.getName(), object); - this.bootstrap = object; - } catch (Exception e) { - e.printStackTrace(); - } - return this; - } - - /** - * add interceptor - * - * @param interceptor interceptor class - * @return return blade obj - */ - public Blade addInterceptor(Class interceptor) { - routeBuilder.addInterceptor(interceptor); - return this; - } - - /** - * add config - * - * @param config config class - * @return return blade obj - */ - public Blade addConfig(Class config) { - configLoader.addConfig(config); - return this; - } - - /** - * Setting 404 view page - * - * @param view404 - * 404 view page - * @return return blade - */ - public Blade view404(final String view404) { - Assert.notBlank(view404); - applicationConfig.setView404(view404); - return this; - } - - /** - * Setting 500 view page - * - * @param view500 - * 500 view page - * @return return blade - */ - public Blade view500(final String view500) { - Assert.notBlank(view500); - applicationConfig.setView500(view500); - return this; - } - - /** - * Setting blade web root path - * - * @param webRoot - * web root path - * @return return blade - */ - public Blade webRoot(final String webRoot) { - Assert.notBlank(webRoot); - applicationConfig.setWebRoot(webRoot); - return this; - } - - /** - * Setting blade run mode - * - * @param isDev - * is dev mode - * @return return blade - */ - public Blade isDev(boolean isDev) { - applicationConfig.setDev(isDev); - return this; - } - - /** - * Setting jetty listen port - * - * @param port - * port, default is 9000 - * @return return blade - */ - public Blade listen(int port) { - this.port = port; - return this; - } - - public void start(Class applicationClass) { - Assert.notNull(applicationClass); - - this.loadAppConf(Const.APP_PROPERTIES); - - // init blade environment config - applicationConfig.setEnv(environment); - applicationConfig.setApplicationClass(applicationClass); - - if(StringKit.isBlank(applicationConfig.getBasePackage())){ - applicationConfig.setBasePackage(applicationClass.getPackage().getName()); - } - try { - Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); - if(null == embedClazz){ - embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); - } - if(null != embedClazz){ - EmbedServer embedServer = (EmbedServer) embedClazz.newInstance(); - embedServer.startup(port, contextPath); - this.enableServer = true; - } else { - throw new EmbedServerException("Not found EmbedServer"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * @return Return blade config object - */ - public ApplicationConfig applicationConfig() { - return applicationConfig; - } - - /** - * @return Return blade config object - */ - public ApplicationConfig config() { - return applicationConfig; - } - - /** - * @return Return Blade Environment - */ - public Environment environment() { - return environment; - } - - /** - * @return Return blade encoding, default is UTF-8 - */ - public String encoding() { - return applicationConfig.getEncoding(); - } - - /** - * @return Return 404 view - */ - public String view404() { - return applicationConfig.getView404(); - } - - /** - * @return Return 500 view - */ - public String view500() { - return applicationConfig.getView500(); - } - - /** - * @return Return blade web root path - */ - public String webRoot() { - return applicationConfig.getWebRoot(); - } - - /** - * @return Return is dev mode - */ - public boolean isDev() { - return applicationConfig.isDev(); - } - - /** - * @return Return static resource directory - */ - public Set staticFolder() { - return applicationConfig.getStaticFolders(); - } - - /** - * @return Return bootstrap object - */ - public Bootstrap bootstrap() { - return this.bootstrap; - } - - /** - * @return Return current templateEngine - */ - public TemplateEngine templateEngine() { - return this.templateEngine; - } - - /** - * return register plugin object - * - * @param plugin - * plugin class - * @return return blade - */ - public Blade plugin(Class plugin) { - Assert.notNull(plugin); - plugins.add(plugin); - return this; - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @return return blade - */ - public Blade routeConf(String basePackage) { - return routeConf(basePackage, "route.conf"); - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @param conf - * Configuration file path, the configuration file must be in - * classpath - * @return return blade - */ - public Blade routeConf(String basePackage, String conf) { - try { - Assert.notBlank(basePackage); - Assert.notBlank(conf); - InputStream ins = Blade.class.getResourceAsStream("/" + conf); - ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); - routesLoader.setBasePackage(basePackage); - List routes = routesLoader.load(); - routers.addRoutes(routes); - } catch (RouteException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - return this; - } - - /** - * @return Return blade is initialize - */ - public boolean isInit() { - return isInit; - } - - public Blade enableServer(boolean enableServer) { - this.enableServer = enableServer; - return this; - } - - public boolean enableServer() { - return this.enableServer; - } - - public Set> plugins() { - return this.plugins; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +import java.io.InputStream; +import java.text.ParseException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.blade.config.ApplicationConfig; +import com.blade.config.BaseConfig; +import com.blade.config.ConfigLoader; +import com.blade.embedd.EmbedServer; +import com.blade.exception.EmbedServerException; +import com.blade.interceptor.Interceptor; +import com.blade.ioc.Ioc; +import com.blade.ioc.SimpleIoc; +import com.blade.kit.Assert; +import com.blade.kit.Environment; +import com.blade.kit.StringKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.plugin.Plugin; +import com.blade.route.Route; +import com.blade.route.RouteBuilder; +import com.blade.route.RouteException; +import com.blade.route.RouteGroup; +import com.blade.route.RouteHandler; +import com.blade.route.Routers; +import com.blade.route.loader.ClassPathRouteLoader; +import com.blade.view.template.DefaultEngine; +import com.blade.view.template.TemplateEngine; +import com.blade.web.http.HttpMethod; + +/** + * Blade Core Class + * + * @author biezhi + * @since 1.6.6 + */ +public final class Blade { + + // blade initialize + private boolean isInit = false; + + // blade bootstrap config class + private Bootstrap bootstrap = null; + + // global configuration Object + private ApplicationConfig applicationConfig = null; + + // ioc container + private Ioc ioc = new SimpleIoc(); + + // default render is jspRender + private TemplateEngine templateEngine = null; + + // routes + private Routers routers = new Routers(); + + // routebuilder + private RouteBuilder routeBuilder; + + // jetty start port + private int port = Const.DEFAULT_PORT; + + // default context path + private String contextPath = Const.DEFAULT_CONTEXTPATH; + + // enableServer + private Boolean enableServer = false; + + // plugins + private Set> plugins; + + // global environment + private Environment environment; + + // config loader + private ConfigLoader configLoader; + + private Blade() { + this.environment = new Environment(); + this.applicationConfig = new ApplicationConfig(); + this.templateEngine = new DefaultEngine(); + this.plugins = new HashSet>(); + this.routeBuilder = new RouteBuilder(this.routers); + this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); + } + + static final class BladeHolder { + private static final Blade ME = new Blade(); + } + + /** + * @return Single case method returns Blade object + */ + @Deprecated + public static final Blade me() { + return BladeHolder.ME; + } + + /** + * + * @param appConf + * @return + */ + @Deprecated + public static final Blade me(String confPath) { + Blade blade = BladeHolder.ME; + blade.environment.add(confPath); + return blade; + } + + /** + * @return Single case method returns Blade object + */ + public static final Blade $() { + return BladeHolder.ME; + } + + /** + * @param confPath + * @return + */ + public static final Blade $(String confPath) { + Blade blade = BladeHolder.ME; + blade.environment.add(confPath); + return blade; + } + + /** + * Set Blade initialize + * + * @param isInit + * initialize + */ + public void init() { + if (!this.isInit) { + this.isInit = true; + } + } + + /** + * @return return route manager + */ + public Routers routers() { + return routers; + } + + /** + * @return return RouteBuilder + */ + public RouteBuilder routeBuilder() { + return routeBuilder; + } + + /** + * @return return ConfigLoader + */ + public ConfigLoader configLoader() { + return configLoader; + } + + /** + * @return return blade ioc container + */ + public Ioc ioc() { + return ioc; + } + + /** + * Setting a ioc container + * + * @param container + * ioc object + * @return return blade + */ + public Blade container(Ioc ioc) { + Assert.notNull(ioc); + this.ioc = ioc; + this.configLoader.setIoc(ioc); + return this; + } + + /** + * Setting Properties configuration file File path based on classpath + * + * @param confPath + * properties file name + * @return return blade + */ + public Blade loadAppConf(String confPath) { + Assert.notBlank(confPath); + environment.add(confPath); + return this; + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackage(String packageName) { + return this.addRoutePackages(packageName); + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackages(String... packages) { + Assert.notNull(packages); + applicationConfig.addRoutePackages(packages); + return this; + } + + /** + * + * @param basePackage + * @return + */ + public Blade basePackage(String basePackage) { + Assert.notBlank(basePackage); + applicationConfig.setBasePackage(basePackage); + applicationConfig.addIocPackages(basePackage + ".service.*"); + applicationConfig.addRoutePackages(basePackage + ".controller"); + applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); + return this; + } + + /** + * Setting the path where the interceptor, e.g:com.bladejava.interceptor + * + * @param packageName + * interceptor packagename + * @return return blade + */ + public Blade interceptor(String packageName) { + Assert.notBlank(packageName); + applicationConfig.setInterceptorPackage(packageName); + return this; + } + + /** + * Setting Ioc packages, e.g:com.bladejava.service + * + * @param packages + * All need to do into the package, can be introduced into a + * number of + * @return return blade + */ + public Blade ioc(String... packages) { + Assert.notNull(packages); + applicationConfig.addIocPackages(packages); + return this; + } + + /** + * Add a route + * + * @param path + * route path + * @param target + * Target object for routing + * @param method + * The method name of the route (at the same time, the HttpMethod + * is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade + */ + public Blade route(String path, Class clazz, String method) { + routers.route(path, clazz, method); + return this; + } + + /** + * Register a functional route + * + * @param path + * route url + * @param clazz + * route processing class + * @param method + * route processing method name + * @param httpMethod + * HttpMethod Type, GET/POST/... + * @return Blade return blade + */ + public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { + routers.route(path, clazz, method, httpMethod); + return this; + } + + /** + * Add a route list + * + * @param routes + * route list + * @return return blade + */ + public Blade routes(List routes) { + Assert.notEmpty(routes, "Routes not is empty!"); + routers.addRoutes(routes); + return this; + } + + /** + * Register a GET request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade get(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.GET); + return this; + } + + /** + * Register a POST request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade post(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.POST); + return this; + } + + /** + * Register a DELETE request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade delete(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.DELETE); + return this; + } + + /** + * Register a PUT request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade put(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.PUT); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade all(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade any(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Route Group. e.g blade.group('/users').get().post() + * + * @param g + * @return return blade + */ + public RouteGroup group(String prefix) { + Assert.notNull(prefix, "Route group prefix not is null"); + return new RouteGroup(this, prefix); + } + + /** + * Register a pre routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade before(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.BEFORE); + return this; + } + + /** + * Register a after routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade after(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.AFTER); + return this; + } + + /** + * Setting Render Engin, Default is JspRender + * + * @param templateEngine + * Render engine object + * @return return blade + */ + public Blade viewEngin(TemplateEngine templateEngine) { + Assert.notNull(templateEngine); + this.templateEngine = templateEngine; + return this; + } + + + /** + * @return Return Current TemplateEngine + */ + public TemplateEngine viewEngin() { + return this.templateEngine; + } + + /** + * Setting the frame static file folder + * + * @param folders + * List of directories to filter, e.g: "/public,/static,/images" + * @return return blade + */ + public Blade staticFolder(final String... folders) { + Assert.notNull(folders); + applicationConfig.setStaticFolders(folders); + return this; + } + + /** + * Dynamically set the global initialization class, the embedded Jetty boot + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Bootstrap bootstrap) { + Assert.notNull(bootstrap); + this.bootstrap = bootstrap; + return this; + } + + /** + * Dynamically set global initialization class + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Class bootstrap) { + Assert.notNull(bootstrap); + try { + Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); + ioc.addBean(Bootstrap.class.getName(), object); + this.bootstrap = object; + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + /** + * add interceptor + * + * @param interceptor interceptor class + * @return return blade obj + */ + public Blade addInterceptor(Class interceptor) { + routeBuilder.addInterceptor(interceptor); + return this; + } + + /** + * add config + * + * @param config config class + * @return return blade obj + */ + public Blade addConfig(Class config) { + configLoader.addConfig(config); + return this; + } + + /** + * Setting 404 view page + * + * @param view404 + * 404 view page + * @return return blade + */ + public Blade view404(final String view404) { + Assert.notBlank(view404); + applicationConfig.setView404(view404); + return this; + } + + /** + * Setting 500 view page + * + * @param view500 + * 500 view page + * @return return blade + */ + public Blade view500(final String view500) { + Assert.notBlank(view500); + applicationConfig.setView500(view500); + return this; + } + + /** + * Setting blade web root path + * + * @param webRoot + * web root path + * @return return blade + */ + public Blade webRoot(final String webRoot) { + Assert.notBlank(webRoot); + applicationConfig.setWebRoot(webRoot); + return this; + } + + /** + * Setting blade run mode + * + * @param isDev + * is dev mode + * @return return blade + */ + public Blade isDev(boolean isDev) { + applicationConfig.setDev(isDev); + return this; + } + + /** + * Setting jetty listen port + * + * @param port + * port, default is 9000 + * @return return blade + */ + public Blade listen(int port) { + this.port = port; + return this; + } + + public void start(Class applicationClass) { + Assert.notNull(applicationClass); + + this.loadAppConf(Const.APP_PROPERTIES); + + // init blade environment config + applicationConfig.setEnv(environment); + applicationConfig.setApplicationClass(applicationClass); + + if(StringKit.isBlank(applicationConfig.getBasePackage())){ + applicationConfig.setBasePackage(applicationClass.getPackage().getName()); + } + try { + Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); + if(null == embedClazz){ + embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); + } + if(null != embedClazz){ + EmbedServer embedServer = (EmbedServer) embedClazz.newInstance(); + embedServer.startup(port, contextPath); + this.enableServer = true; + } else { + throw new EmbedServerException("Not found EmbedServer"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * @return Return blade config object + */ + public ApplicationConfig applicationConfig() { + return applicationConfig; + } + + /** + * @return Return blade config object + */ + public ApplicationConfig config() { + return applicationConfig; + } + + /** + * @return Return Blade Environment + */ + public Environment environment() { + return environment; + } + + /** + * @return Return blade encoding, default is UTF-8 + */ + public String encoding() { + return applicationConfig.getEncoding(); + } + + /** + * @return Return 404 view + */ + public String view404() { + return applicationConfig.getView404(); + } + + /** + * @return Return 500 view + */ + public String view500() { + return applicationConfig.getView500(); + } + + /** + * @return Return blade web root path + */ + public String webRoot() { + return applicationConfig.getWebRoot(); + } + + /** + * @return Return is dev mode + */ + public boolean isDev() { + return applicationConfig.isDev(); + } + + /** + * @return Return static resource directory + */ + public Set staticFolder() { + return applicationConfig.getStaticFolders(); + } + + /** + * @return Return bootstrap object + */ + public Bootstrap bootstrap() { + return this.bootstrap; + } + + /** + * @return Return current templateEngine + */ + public TemplateEngine templateEngine() { + return this.templateEngine; + } + + /** + * return register plugin object + * + * @param plugin + * plugin class + * @return return blade + */ + public Blade plugin(Class plugin) { + Assert.notNull(plugin); + plugins.add(plugin); + return this; + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @return return blade + */ + public Blade routeConf(String basePackage) { + return routeConf(basePackage, "route.conf"); + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @param conf + * Configuration file path, the configuration file must be in + * classpath + * @return return blade + */ + public Blade routeConf(String basePackage, String conf) { + try { + Assert.notBlank(basePackage); + Assert.notBlank(conf); + InputStream ins = Blade.class.getResourceAsStream("/" + conf); + ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); + routesLoader.setBasePackage(basePackage); + List routes = routesLoader.load(); + routers.addRoutes(routes); + } catch (RouteException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return this; + } + + /** + * @return Return blade is initialize + */ + public boolean isInit() { + return isInit; + } + + public Blade enableServer(boolean enableServer) { + this.enableServer = enableServer; + return this; + } + + public boolean enableServer() { + return this.enableServer; + } + + public Set> plugins() { + return this.plugins; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/Bootstrap.java b/blade-core/src/main/java/com/blade/Bootstrap.java index d82d8cc7e..af17162db 100644 --- a/blade-core/src/main/java/com/blade/Bootstrap.java +++ b/blade-core/src/main/java/com/blade/Bootstrap.java @@ -1,39 +1,39 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -/** - * Blade global initialization class, you can do some operations at the start of the application - * - * @author biezhi - * @since 1.0 - */ -public abstract class Bootstrap { - - /** - * Initialization method, do some initialization operation when the application starts - * @param blade blade global object - */ - public abstract void init(Blade blade); - - /** - * After initialization configuration - * @param blade blade global object - */ - public void contextInitialized(){ - // - } -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +/** + * Blade global initialization class, you can do some operations at the start of the application + * + * @author biezhi + * @since 1.6.6 + */ +public abstract class Bootstrap { + + /** + * Initialization method, do some initialization operation when the application starts + * @param blade blade global object + */ + public abstract void init(Blade blade); + + /** + * After initialization configuration + * @param blade blade global object + */ + public void contextInitialized(){ + // + } +} diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 8ac85266c..b7cde1bfe 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -1,54 +1,54 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -/** - * Const Interface - * - * @author biezhi - * @since 1.0 - */ -public interface Const { - - // current blade version - String BLADE_VERSION = "1.6.6-alpha"; - - // default embedd server context path - String DEFAULT_CONTEXTPATH = "/"; - - // Server 500 error HTML - String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; - - // Server 404 error HTML - String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; - - // Default jetty server port - int DEFAULT_PORT = 9000; - - // Request ThreadPoll context key - String BLADE_EXECUTOR = "blade-req-executor"; - - /**************** - * blade properties - * **************/ - String BLADE_ROUTE = "blade.route"; - String BLADE_IOC = "blade.ioc"; - String BLADE_VIEW_404 = "blade.view404"; - String BLADE_VIEW_500 = "blade.view500"; - String BLADE_DEV = "blade.dev"; - String APP_PROPERTIES = "app.properties"; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +/** + * Const Interface + * + * @author biezhi + * @since 1.6.6 + */ +public interface Const { + + // current blade version + String BLADE_VERSION = "1.6.6-alpha"; + + // default embedd server context path + String DEFAULT_CONTEXTPATH = "/"; + + // Server 500 error HTML + String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; + + // Server 404 error HTML + String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; + + // Default jetty server port + int DEFAULT_PORT = 9000; + + // Request ThreadPoll context key + String BLADE_EXECUTOR = "blade-req-executor"; + + /**************** + * blade properties + * **************/ + String BLADE_ROUTE = "blade.route"; + String BLADE_IOC = "blade.ioc"; + String BLADE_VIEW_404 = "blade.view404"; + String BLADE_VIEW_500 = "blade.view500"; + String BLADE_DEV = "blade.dev"; + String APP_PROPERTIES = "app.properties"; + +} diff --git a/blade-core/src/main/java/com/blade/annotation/Controller.java b/blade-core/src/main/java/com/blade/annotation/Controller.java index 947ff8ca1..92b76f8ae 100644 --- a/blade-core/src/main/java/com/blade/annotation/Controller.java +++ b/blade-core/src/main/java/com/blade/annotation/Controller.java @@ -1,44 +1,44 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Route class notes, identifying whether a class is routed - * - * @author biezhi - * @since 1.0 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Controller{ - - /** - * @return namespace - */ - String value() default "/"; - - /** - * @return route suffix - */ - String suffix() default ""; - +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Route class notes, identifying whether a class is routed + * + * @author biezhi + * @since 1.6.6 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Controller{ + + /** + * @return namespace + */ + String value() default "/"; + + /** + * @return route suffix + */ + String suffix() default ""; + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/Intercept.java b/blade-core/src/main/java/com/blade/annotation/Intercept.java index f4f7afde7..06824cdaa 100644 --- a/blade-core/src/main/java/com/blade/annotation/Intercept.java +++ b/blade-core/src/main/java/com/blade/annotation/Intercept.java @@ -1,40 +1,40 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Interceptor notes, written in the class - * e.g: - *
- * {@link Intercept}
- * public class BaseInterceptor {...}
- * 
- * @author biezhi - * @since 1.0 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Intercept{ - - String value() default "/.*"; - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Interceptor notes, written in the class + * e.g: + *
+ * {@link Intercept}
+ * public class BaseInterceptor {...}
+ * 
+ * @author biezhi + * @since 1.5 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Intercept{ + + String value() default "/.*"; + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/JSON.java b/blade-core/src/main/java/com/blade/annotation/JSON.java index 0881b3320..f88895ed7 100644 --- a/blade-core/src/main/java/com/blade/annotation/JSON.java +++ b/blade-core/src/main/java/com/blade/annotation/JSON.java @@ -1,33 +1,33 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Return JSON Params - * - * @author biezhi - * @since 1.0 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface JSON { - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Return JSON Params + * + * @author biezhi + * @since 1.6.6 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface JSON { + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/PathVariable.java b/blade-core/src/main/java/com/blade/annotation/PathVariable.java index dc6f04f3d..4cef70d77 100644 --- a/blade-core/src/main/java/com/blade/annotation/PathVariable.java +++ b/blade-core/src/main/java/com/blade/annotation/PathVariable.java @@ -1,16 +1,37 @@ -package com.blade.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.PARAMETER) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface PathVariable { - - String value() default ""; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Request Path Parameter Annotation + * + * @author biezhi + * @since 1.6.6 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface PathVariable { + + String value() default ""; + +} diff --git a/blade-core/src/main/java/com/blade/annotation/RequestParam.java b/blade-core/src/main/java/com/blade/annotation/RequestParam.java index ebb7167d6..4d34a3c85 100644 --- a/blade-core/src/main/java/com/blade/annotation/RequestParam.java +++ b/blade-core/src/main/java/com/blade/annotation/RequestParam.java @@ -1,20 +1,41 @@ -package com.blade.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.PARAMETER) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface RequestParam { - - String value() default ""; - - boolean required() default true; - - String defaultValue() default ""; - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Request Query ParmeterAnnotation + * + * @author biezhi + * @since 1.6.6 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RequestParam { + + String value() default ""; + + boolean required() default true; + + String defaultValue() default ""; + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/RestController.java b/blade-core/src/main/java/com/blade/annotation/RestController.java index ae96002bc..ef6bd479c 100644 --- a/blade-core/src/main/java/com/blade/annotation/RestController.java +++ b/blade-core/src/main/java/com/blade/annotation/RestController.java @@ -1,44 +1,46 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Route class notes, identifying whether a class is routed - * - * @author biezhi - * @since 1.0 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface RestController { - - /** - * @return namespace - */ - String value() default "/"; - - /** - * @return route suffix - */ - String suffix() default ""; - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Return JSON Data to client. + * + * The controller all methods have this attr. + * + * @author biezhi + * @since 1.5 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RestController { + + /** + * @return namespace + */ + String value() default "/"; + + /** + * @return route suffix + */ + String suffix() default ""; + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/Route.java b/blade-core/src/main/java/com/blade/annotation/Route.java index a009f9c16..4836178ae 100644 --- a/blade-core/src/main/java/com/blade/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/annotation/Route.java @@ -1,59 +1,59 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.blade.web.http.HttpMethod; - -/** - * Methods defined on the route notes - * - Restful routes: -
-	==========================================================================================
-	verb    path                   action          used for
-	==========================================================================================
-	GET     /users                 index 	       display a list of all books
-	GET     /users/new_form        new_form        return an HTML form for creating a new book
-	POST    /users                 create 	       create a new book
-	GET     /users/id              show            display a specific book
-	GET     /users/id/edit_form    edit_form       return an HTML form for editing a books
-	PUT     /users/id              update          update a specific book
-	DELETE 	/users/id              destroy         delete a specific book
-	
- - * @author biezhi - * @since 1.0 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface Route { - - /** - * @return Request url - */ - String[] value() default {"/"}; - - /** - * @return Request HttpMethod - */ - HttpMethod method() default HttpMethod.ALL; - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.blade.web.http.HttpMethod; + +/** + * Methods defined on the route notes + * + Restful routes: +
+	==========================================================================================
+	verb    path                   action          used for
+	==========================================================================================
+	GET     /users                 index 	       display a list of all books
+	GET     /users/new_form        new_form        return an HTML form for creating a new book
+	POST    /users                 create 	       create a new book
+	GET     /users/id              show            display a specific book
+	GET     /users/id/edit_form    edit_form       return an HTML form for editing a books
+	PUT     /users/id              update          update a specific book
+	DELETE 	/users/id              destroy         delete a specific book
+	
+ + * @author biezhi + * @since 1.5 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Route { + + /** + * @return Request url + */ + String[] value() default {"/"}; + + /** + * @return Request HttpMethod + */ + HttpMethod method() default HttpMethod.ALL; + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/asm/AsmKit.java b/blade-core/src/main/java/com/blade/asm/AsmKit.java index 2dbe01d72..8f5b59019 100644 --- a/blade-core/src/main/java/com/blade/asm/AsmKit.java +++ b/blade-core/src/main/java/com/blade/asm/AsmKit.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.asm; import java.io.IOException; @@ -11,6 +26,12 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; +/** + * ASM Tools + * + * @author biezhi + * @since 1.6.6 + */ public final class AsmKit { /** diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 79190ed88..30d7138d0 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -1,218 +1,218 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import com.blade.Blade; -import com.blade.kit.Environment; -import com.blade.kit.StringKit; - -/** - * Blade Config Class - * - * @author biezhi - * @since 1.0 - * - */ -public class ApplicationConfig { - - // Storage of all routing packets - private Set routePackages = new HashSet(); - - // Store all IOC packages - private Set iocPackages = new HashSet(); - - // Strore all config packages - private Set configPackages = new HashSet(); - - // Store all filter directories - private Set staticFolders = new HashSet(); - - // Base package - private String basePackage; - - // Interceptor package - private String interceptorPackage; - - // Encoding - private String encoding = "utf-8"; - - // web root path - private String webRoot; - - // 404 view page - private String view404; - - // 500 view page - private String view500; - - // Is dev mode - private boolean isDev = true; - - private boolean isInit = false; - - private Class applicationClass; - - public ApplicationConfig() { - staticFolders.add("/public"); - staticFolders.add("/assets"); - staticFolders.add("/static"); - } - - public void setEnv(Environment environment) { - if (null != environment && !isInit) { - this.isDev = environment.getBoolean("app.dev", true); - this.encoding = environment.getString("http.encoding", "UTF-8"); - this.addIocPackages(environment.getString("app.ioc")); - this.view500 = environment.getString("app.view.500"); - this.view404 = environment.getString("app.view.404"); - - String statics = environment.getString("app.statics"); - String basePackage = environment.getString("app.base-package"); - Integer port = environment.getInt("server.port"); - - if (null != port) { - Blade.$().listen(port); - } - - if (StringKit.isNotBlank(statics)) { - this.setStaticFolders(statics.split(",")); - } - - if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { - this.setBasePackage(basePackage); - } - isInit = true; - } - } - - public String[] getRoutePackages() { - String[] routeArr = new String[routePackages.size()]; - return routePackages.toArray(routeArr); - } - - public void addRoutePackages(String... packages) { - if (null != packages && packages.length > 0) { - routePackages.addAll(Arrays.asList(packages)); - } - } - - public String getBasePackage() { - return basePackage; - } - - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - this.addConfigPackages(basePackage + ".config"); - this.addIocPackages(basePackage + ".service.*"); - this.addRoutePackages(basePackage + ".controller"); - this.setInterceptorPackage(basePackage + ".interceptor"); - } - - public String[] getIocPackages() { - String[] iocArr = new String[iocPackages.size()]; - return iocPackages.toArray(iocArr); - } - - public String[] getConfigPackages() { - String[] configArr = new String[configPackages.size()]; - return configPackages.toArray(configArr); - } - - public void addIocPackages(String... packages) { - if (null != packages && packages.length > 0) { - iocPackages.addAll(Arrays.asList(packages)); - } - } - - public void addConfigPackages(String... packages) { - if (null != packages && packages.length > 0) { - configPackages.addAll(Arrays.asList(packages)); - } - } - - public String getInterceptorPackage() { - return interceptorPackage; - } - - public void setInterceptorPackage(String interceptorPackage) { - this.interceptorPackage = interceptorPackage; - } - - public Set getStaticFolders() { - return staticFolders; - } - - public void setStaticFolders(String... packages) { - staticFolders.addAll(Arrays.asList(packages)); - } - - public String getView404() { - return view404; - } - - public void setView404(String view404) { - this.view404 = view404; - } - - public String getView500() { - return view500; - } - - public void setView500(String view500) { - this.view500 = view500; - } - - public String getWebRoot() { - return webRoot; - } - - public void setWebRoot(String webRoot) { - this.webRoot = webRoot; - } - - public boolean isDev() { - return isDev; - } - - public void setDev(boolean isDev) { - this.isDev = isDev; - } - - public String getEncoding() { - return encoding; - } - - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - public boolean isInit(){ - return this.isInit; - } - - public Class getApplicationClass() { - return applicationClass; - } - - public void setApplicationClass(Class applicationClass) { - this.applicationClass = applicationClass; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import com.blade.Blade; +import com.blade.kit.Environment; +import com.blade.kit.StringKit; + +/** + * Blade Application Config Class + * + * @author biezhi + * @since 1.6.6 + * + */ +public class ApplicationConfig { + + // Storage of all routing packets + private Set routePackages = new HashSet(); + + // Store all IOC packages + private Set iocPackages = new HashSet(); + + // Strore all config packages + private Set configPackages = new HashSet(); + + // Store all filter directories + private Set staticFolders = new HashSet(); + + // Base package + private String basePackage; + + // Interceptor package + private String interceptorPackage; + + // Encoding + private String encoding = "utf-8"; + + // web root path + private String webRoot; + + // 404 view page + private String view404; + + // 500 view page + private String view500; + + // Is dev mode + private boolean isDev = true; + + private boolean isInit = false; + + private Class applicationClass; + + public ApplicationConfig() { + staticFolders.add("/public"); + staticFolders.add("/assets"); + staticFolders.add("/static"); + } + + public void setEnv(Environment environment) { + if (null != environment && !isInit) { + this.isDev = environment.getBoolean("app.dev", true); + this.encoding = environment.getString("http.encoding", "UTF-8"); + this.addIocPackages(environment.getString("app.ioc")); + this.view500 = environment.getString("app.view.500"); + this.view404 = environment.getString("app.view.404"); + + String statics = environment.getString("app.statics"); + String basePackage = environment.getString("app.base-package"); + Integer port = environment.getInt("server.port"); + + if (null != port) { + Blade.$().listen(port); + } + + if (StringKit.isNotBlank(statics)) { + this.setStaticFolders(statics.split(",")); + } + + if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { + this.setBasePackage(basePackage); + } + isInit = true; + } + } + + public String[] getRoutePackages() { + String[] routeArr = new String[routePackages.size()]; + return routePackages.toArray(routeArr); + } + + public void addRoutePackages(String... packages) { + if (null != packages && packages.length > 0) { + routePackages.addAll(Arrays.asList(packages)); + } + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + this.addConfigPackages(basePackage + ".config"); + this.addIocPackages(basePackage + ".service.*"); + this.addRoutePackages(basePackage + ".controller"); + this.setInterceptorPackage(basePackage + ".interceptor"); + } + + public String[] getIocPackages() { + String[] iocArr = new String[iocPackages.size()]; + return iocPackages.toArray(iocArr); + } + + public String[] getConfigPackages() { + String[] configArr = new String[configPackages.size()]; + return configPackages.toArray(configArr); + } + + public void addIocPackages(String... packages) { + if (null != packages && packages.length > 0) { + iocPackages.addAll(Arrays.asList(packages)); + } + } + + public void addConfigPackages(String... packages) { + if (null != packages && packages.length > 0) { + configPackages.addAll(Arrays.asList(packages)); + } + } + + public String getInterceptorPackage() { + return interceptorPackage; + } + + public void setInterceptorPackage(String interceptorPackage) { + this.interceptorPackage = interceptorPackage; + } + + public Set getStaticFolders() { + return staticFolders; + } + + public void setStaticFolders(String... packages) { + staticFolders.addAll(Arrays.asList(packages)); + } + + public String getView404() { + return view404; + } + + public void setView404(String view404) { + this.view404 = view404; + } + + public String getView500() { + return view500; + } + + public void setView500(String view500) { + this.view500 = view500; + } + + public String getWebRoot() { + return webRoot; + } + + public void setWebRoot(String webRoot) { + this.webRoot = webRoot; + } + + public boolean isDev() { + return isDev; + } + + public void setDev(boolean isDev) { + this.isDev = isDev; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public boolean isInit(){ + return this.isInit; + } + + public Class getApplicationClass() { + return applicationClass; + } + + public void setApplicationClass(Class applicationClass) { + this.applicationClass = applicationClass; + } + +} diff --git a/blade-core/src/main/java/com/blade/config/BaseConfig.java b/blade-core/src/main/java/com/blade/config/BaseConfig.java index b78fd53c2..873bb6c62 100644 --- a/blade-core/src/main/java/com/blade/config/BaseConfig.java +++ b/blade-core/src/main/java/com/blade/config/BaseConfig.java @@ -1,7 +1,28 @@ -package com.blade.config; - -public interface BaseConfig { - - void config(ApplicationConfig applicationConfig); - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +/** + * BaseConfig Interface, Implements Object can be auto execute. + * + * @author biezhi + * @since 1.6.6 + */ +public interface BaseConfig { + + void config(ApplicationConfig applicationConfig); + +} diff --git a/blade-core/src/main/java/com/blade/config/ConfigLoader.java b/blade-core/src/main/java/com/blade/config/ConfigLoader.java index f949aa567..e2c0b100b 100644 --- a/blade-core/src/main/java/com/blade/config/ConfigLoader.java +++ b/blade-core/src/main/java/com/blade/config/ConfigLoader.java @@ -1,89 +1,89 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.lang.reflect.Modifier; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.context.DynamicClassReader; -import com.blade.exception.ConfigException; -import com.blade.ioc.Ioc; -import com.blade.ioc.annotation.Component; -import com.blade.kit.CollectionKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; - -/** - * ConfigLoader - * - * @author biezhi - * @since 1.0 - */ -public class ConfigLoader { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); - - private ClassReader classReader; - private Ioc ioc; - private ApplicationConfig applicationConfig; - - public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { - this.ioc = ioc; - this.classReader = DynamicClassReader.getClassReader(); - this.applicationConfig = applicationConfig; - } - - public void setIoc(Ioc ioc){ - this.ioc = ioc; - } - - @SuppressWarnings("unchecked") - public void loadConfig() { - String[] configPackages = Blade.$().config().getConfigPackages(); - if (null != configPackages && configPackages.length > 0) { - // Scan package all class - try { - for (String packageName : configPackages) { - Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); - if (CollectionKit.isNotEmpty(classes)) { - for (ClassInfo classInfo : classes) { - boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); - if(hasInterface){ - addConfig((Class) classInfo.getClazz()); - } - } - } - } - } catch (ConfigException e) { - LOGGER.error("load config error", e); - } - } - } - - public void addConfig(Class clazz) throws ConfigException { - if (!Modifier.isAbstract(clazz.getModifiers())) { - Object bean = ioc.addBean(clazz); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(applicationConfig); - } - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.lang.reflect.Modifier; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.context.DynamicClassReader; +import com.blade.exception.ConfigException; +import com.blade.ioc.Ioc; +import com.blade.ioc.annotation.Component; +import com.blade.kit.CollectionKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; + +/** + * ConfigLoader + * + * @author biezhi + * @since 1.6.6 + */ +public class ConfigLoader { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); + + private ClassReader classReader; + private Ioc ioc; + private ApplicationConfig applicationConfig; + + public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { + this.ioc = ioc; + this.classReader = DynamicClassReader.getClassReader(); + this.applicationConfig = applicationConfig; + } + + public void setIoc(Ioc ioc){ + this.ioc = ioc; + } + + @SuppressWarnings("unchecked") + public void loadConfig() { + String[] configPackages = Blade.$().config().getConfigPackages(); + if (null != configPackages && configPackages.length > 0) { + // Scan package all class + try { + for (String packageName : configPackages) { + Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); + if (CollectionKit.isNotEmpty(classes)) { + for (ClassInfo classInfo : classes) { + boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); + if(hasInterface){ + addConfig((Class) classInfo.getClazz()); + } + } + } + } + } catch (ConfigException e) { + LOGGER.error("load config error", e); + } + } + } + + public void addConfig(Class clazz) throws ConfigException { + if (!Modifier.isAbstract(clazz.getModifiers())) { + Object bean = ioc.addBean(clazz); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(applicationConfig); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/context/ApplicationContext.java b/blade-core/src/main/java/com/blade/context/ApplicationContext.java index a6a6bc420..c527b5df7 100644 --- a/blade-core/src/main/java/com/blade/context/ApplicationContext.java +++ b/blade-core/src/main/java/com/blade/context/ApplicationContext.java @@ -1,37 +1,58 @@ -package com.blade.context; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.exception.BladeException; -import com.blade.ioc.IocApplication; - -public final class ApplicationContext { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContext.class); - - public static void init(Blade blade) throws BladeException{ - try { - - blade.bootstrap().init(blade); - - if(!blade.config().isInit()){ - blade.loadAppConf(Const.APP_PROPERTIES); - blade.config().setEnv(blade.environment()); - } - - // initialization ioc - IocApplication iocApplication = new IocApplication(); - iocApplication.initBeans(); - - blade.init(); - blade.bootstrap().contextInitialized(); - } catch (Exception e) { - LOGGER.error("ApplicationContext init error", e); - } - - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.exception.BladeException; +import com.blade.ioc.IocApplication; + +/** + * Blade ApplicationContext, init context + * + * @author biezhi + * @since 1.6.6 + */ +public final class ApplicationContext { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContext.class); + + public static void init(Blade blade) throws BladeException{ + try { + + blade.bootstrap().init(blade); + + if(!blade.config().isInit()){ + blade.loadAppConf(Const.APP_PROPERTIES); + blade.config().setEnv(blade.environment()); + } + + // initialization ioc + IocApplication iocApplication = new IocApplication(); + iocApplication.initBeans(); + + blade.init(); + blade.bootstrap().contextInitialized(); + } catch (Exception e) { + LOGGER.error("ApplicationContext init error", e); + } + + } + +} diff --git a/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java b/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java index 548d4c628..c0e894064 100644 --- a/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java +++ b/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java @@ -1,107 +1,107 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.context; - -import javax.servlet.ServletContext; - -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.wrapper.Session; - -/** - * BladeWebContext - * - * @author biezhi - * @since 1.0 - */ -public class ApplicationWebContext { - - /** - * BladeWebContext object for the current thread - */ - private static ThreadLocal ctx = new ThreadLocal(); - - /** - * ServletContext Object that is created when the application is initialized - */ - private ServletContext context; - - /** - * Request - */ - private Request request; - - /** - * Response - */ - private Response response; - - private ApplicationWebContext(){} - - public static ApplicationWebContext me(){ - return ctx.get(); - } - - public static void init(ServletContext context) { - ApplicationWebContext bladeWebContext = new ApplicationWebContext(); - bladeWebContext.context = context; - ctx.set(bladeWebContext); - } - - public static void init(ServletContext context, Request request, Response response) { - ApplicationWebContext bladeWebContext = new ApplicationWebContext(); - bladeWebContext.context = context; - bladeWebContext.request = request; - bladeWebContext.response = response; - ctx.set(bladeWebContext); - } - - /** - * 移除当前线程的Request、Response对象 - */ - public static void remove(){ - ctx.remove(); - } - - public static Request request() { - return me().request; - } - - public static Response response() { - return me().response; - } - - public static Session session() { - return request().session(); - } - - public static ServletContext servletContext() { - return me().context; - } - - public ServletContext getContext() { - return context; - } - - public Request getRequest() { - return request; - } - - public Response getResponse() { - return response; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import javax.servlet.ServletContext; + +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.Session; + +/** + * BladeWebContext + * + * @author biezhi + * @since 1.6.6 + */ +public class ApplicationWebContext { + + /** + * BladeWebContext object for the current thread + */ + private static ThreadLocal ctx = new ThreadLocal(); + + /** + * ServletContext Object that is created when the application is initialized + */ + private ServletContext context; + + /** + * Request + */ + private Request request; + + /** + * Response + */ + private Response response; + + private ApplicationWebContext(){} + + public static ApplicationWebContext me(){ + return ctx.get(); + } + + public static void init(ServletContext context) { + ApplicationWebContext bladeWebContext = new ApplicationWebContext(); + bladeWebContext.context = context; + ctx.set(bladeWebContext); + } + + public static void init(ServletContext context, Request request, Response response) { + ApplicationWebContext bladeWebContext = new ApplicationWebContext(); + bladeWebContext.context = context; + bladeWebContext.request = request; + bladeWebContext.response = response; + ctx.set(bladeWebContext); + } + + /** + * 移除当前线程的Request、Response对象 + */ + public static void remove(){ + ctx.remove(); + } + + public static Request request() { + return me().request; + } + + public static Response response() { + return me().response; + } + + public static Session session() { + return request().session(); + } + + public static ServletContext servletContext() { + return me().context; + } + + public ServletContext getContext() { + return context; + } + + public Request getRequest() { + return request; + } + + public Response getResponse() { + return response; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java index 7b5c3e9ee..2bde845a8 100644 --- a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java +++ b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java @@ -1,55 +1,51 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; - -import com.blade.Blade; -import com.blade.kit.resource.ClassPathClassReader; -import com.blade.kit.resource.ClassReader; -import com.blade.kit.resource.JarReaderImpl; - -/** - * 动态根据环境获取ClassReader - * - * @author biezhi - * @since 1.0 - */ -public final class DynamicClassReader { - - private static boolean IS_JAR_CONTEXT = false; - - private DynamicClassReader() { - } - - public static void init(){ - /*String rs = DynamicClassReader.class.getResource("").toString(); - if(rs.indexOf(".jar!") != -1){ - IS_JAR_CONTEXT = true; - }*/ - Class clazz = Blade.$().config().getApplicationClass(); - String rs = clazz.getResource("").toString(); - if(rs.indexOf(".jar!") != -1){ - IS_JAR_CONTEXT = true; - } - } - - public static ClassReader getClassReader(){ - if(IS_JAR_CONTEXT){ - return new JarReaderImpl(); - } - return new ClassPathClassReader(); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import com.blade.Blade; +import com.blade.kit.resource.ClassPathClassReader; +import com.blade.kit.resource.ClassReader; +import com.blade.kit.resource.JarReaderImpl; + +/** + * Get ClassReader by JAR or folder + * + * @author biezhi + * @since 1.6.6 + */ +public final class DynamicClassReader { + + private static boolean IS_JAR_CONTEXT = false; + + private DynamicClassReader() { + } + + public static void init(){ + Class clazz = Blade.$().config().getApplicationClass(); + String rs = clazz.getResource("").toString(); + if(rs.indexOf(".jar!") != -1){ + IS_JAR_CONTEXT = true; + } + } + + public static ClassReader getClassReader(){ + if(IS_JAR_CONTEXT){ + return new JarReaderImpl(); + } + return new ClassPathClassReader(); + } + +} diff --git a/blade-core/src/main/java/com/blade/embedd/EmbedServer.java b/blade-core/src/main/java/com/blade/embedd/EmbedServer.java index 64891ddc3..898e83180 100644 --- a/blade-core/src/main/java/com/blade/embedd/EmbedServer.java +++ b/blade-core/src/main/java/com/blade/embedd/EmbedServer.java @@ -1,34 +1,34 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.embedd; - -/** - * Jetty Server - * - * @author biezhi - * @since 1.0 - */ -public interface EmbedServer { - - void startup(int port) throws Exception; - - void startup(int port, String contextPath) throws Exception; - - void startup(int port, String contextPath, String webRoot) throws Exception; - - void stop() throws Exception; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.embedd; + +/** + * Jetty Server + * + * @author biezhi + * @since 1.6.6 + */ +public interface EmbedServer { + + void startup(int port) throws Exception; + + void startup(int port, String contextPath) throws Exception; + + void startup(int port, String contextPath, String webRoot) throws Exception; + + void stop() throws Exception; + +} diff --git a/blade-core/src/main/java/com/blade/exception/BladeException.java b/blade-core/src/main/java/com/blade/exception/BladeException.java index b197c8d3f..89c937509 100644 --- a/blade-core/src/main/java/com/blade/exception/BladeException.java +++ b/blade-core/src/main/java/com/blade/exception/BladeException.java @@ -1,27 +1,38 @@ -package com.blade.exception; - -public class BladeException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - public BladeException() { - super(); - } - - public BladeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } - - public BladeException(String message, Throwable cause) { - super(message, cause); - } - - public BladeException(String message) { - super(message); - } - - public BladeException(Throwable cause) { - super(cause); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.exception; + +public class BladeException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public BladeException() { + super(); + } + + public BladeException(String message, Throwable cause) { + super(message, cause); + } + + public BladeException(String message) { + super(message); + } + + public BladeException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/exception/ConfigException.java b/blade-core/src/main/java/com/blade/exception/ConfigException.java index 7cf03f86a..6f0098a33 100644 --- a/blade-core/src/main/java/com/blade/exception/ConfigException.java +++ b/blade-core/src/main/java/com/blade/exception/ConfigException.java @@ -1,27 +1,38 @@ -package com.blade.exception; - -public class ConfigException extends BladeException { - - private static final long serialVersionUID = 1L; - - public ConfigException() { - super(); - } - - public ConfigException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } - - public ConfigException(String message, Throwable cause) { - super(message, cause); - } - - public ConfigException(String message) { - super(message); - } - - public ConfigException(Throwable cause) { - super(cause); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.exception; + +public class ConfigException extends BladeException { + + private static final long serialVersionUID = 1L; + + public ConfigException() { + super(); + } + + public ConfigException(String message, Throwable cause) { + super(message, cause); + } + + public ConfigException(String message) { + super(message); + } + + public ConfigException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/exception/EmbedServerException.java b/blade-core/src/main/java/com/blade/exception/EmbedServerException.java index 6632f950e..47c5cede1 100644 --- a/blade-core/src/main/java/com/blade/exception/EmbedServerException.java +++ b/blade-core/src/main/java/com/blade/exception/EmbedServerException.java @@ -1,27 +1,38 @@ -package com.blade.exception; - -public class EmbedServerException extends BladeException { - - private static final long serialVersionUID = 1L; - - public EmbedServerException() { - super(); - } - - public EmbedServerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } - - public EmbedServerException(String message, Throwable cause) { - super(message, cause); - } - - public EmbedServerException(String message) { - super(message); - } - - public EmbedServerException(Throwable cause) { - super(cause); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.exception; + +public class EmbedServerException extends BladeException { + + private static final long serialVersionUID = 1L; + + public EmbedServerException() { + super(); + } + + public EmbedServerException(String message, Throwable cause) { + super(message, cause); + } + + public EmbedServerException(String message) { + super(message); + } + + public EmbedServerException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/exception/MethodInvokeException.java b/blade-core/src/main/java/com/blade/exception/MethodInvokeException.java index 897356736..17d3b2571 100644 --- a/blade-core/src/main/java/com/blade/exception/MethodInvokeException.java +++ b/blade-core/src/main/java/com/blade/exception/MethodInvokeException.java @@ -1,28 +1,38 @@ -package com.blade.exception; - -public class MethodInvokeException extends BladeException { - - private static final long serialVersionUID = 1L; - - public MethodInvokeException() { - super(); - } - - public MethodInvokeException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } - - public MethodInvokeException(String message, Throwable cause) { - super(message, cause); - } - - public MethodInvokeException(String message) { - super(message); - } - - public MethodInvokeException(Throwable cause) { - super(cause); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.exception; + +public class MethodInvokeException extends BladeException { + + private static final long serialVersionUID = 1L; + + public MethodInvokeException() { + super(); + } + + public MethodInvokeException(String message, Throwable cause) { + super(message, cause); + } + + public MethodInvokeException(String message) { + super(message); + } + + public MethodInvokeException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/exception/NotFoundException.java b/blade-core/src/main/java/com/blade/exception/NotFoundException.java index 265113846..6a1dd5091 100644 --- a/blade-core/src/main/java/com/blade/exception/NotFoundException.java +++ b/blade-core/src/main/java/com/blade/exception/NotFoundException.java @@ -1,27 +1,38 @@ -package com.blade.exception; - -public class NotFoundException extends BladeException { - - private static final long serialVersionUID = 1L; - - public NotFoundException() { - super(); - } - - public NotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } - - public NotFoundException(String message, Throwable cause) { - super(message, cause); - } - - public NotFoundException(String message) { - super(message); - } - - public NotFoundException(Throwable cause) { - super(cause); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.exception; + +public class NotFoundException extends BladeException { + + private static final long serialVersionUID = 1L; + + public NotFoundException() { + super(); + } + + public NotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public NotFoundException(String message) { + super(message); + } + + public NotFoundException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/interceptor/Interceptor.java b/blade-core/src/main/java/com/blade/interceptor/Interceptor.java index 67a7be4fd..18550ef63 100644 --- a/blade-core/src/main/java/com/blade/interceptor/Interceptor.java +++ b/blade-core/src/main/java/com/blade/interceptor/Interceptor.java @@ -1,33 +1,33 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.interceptor; - -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -/** - * Interceptor, In the routing block before and after the execution. - * - * @author biezhi - * @since 1.0 - */ -public interface Interceptor { - - boolean before(Request request, Response response); - - boolean after(Request request, Response response); - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.interceptor; + +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * Interceptor, In the routing block before and after the execution. + * + * @author biezhi + * @since 1.5 + */ +public interface Interceptor { + + boolean before(Request request, Response response); + + boolean after(Request request, Response response); + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/BeanDefine.java b/blade-core/src/main/java/com/blade/ioc/BeanDefine.java index 8383d89ff..ce8d725e5 100644 --- a/blade-core/src/main/java/com/blade/ioc/BeanDefine.java +++ b/blade-core/src/main/java/com/blade/ioc/BeanDefine.java @@ -1,70 +1,70 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -/** - * Bean Define, IOC to define a target - * - * @author biezhi - * @since 1.0 - */ -public class BeanDefine { - - private Object bean; - private Class type; - private boolean isSignle; - - public BeanDefine(Object bean) { - this(bean, bean.getClass()); - } - - public BeanDefine(Object bean, Class type) { - this.bean = bean; - this.type = type; - this.isSignle = true; - } - - public BeanDefine(Object bean, Class type, boolean isSingle) { - this.bean = bean; - this.type = type; - this.isSignle = isSingle; - } - - public Object getBean() { - return bean; - } - - public void setBean(Object bean) { - this.bean = bean; - } - - public Class getType() { - return type; - } - - public void setType(Class type) { - this.type = type; - } - - public boolean isSignle() { - return isSignle; - } - - public void setSignle(boolean isSignle) { - this.isSignle = isSignle; - } - +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +/** + * Bean Define, IOC to define a target + * + * @author biezhi + * @since 1.5 + */ +public class BeanDefine { + + private Object bean; + private Class type; + private boolean isSignle; + + public BeanDefine(Object bean) { + this(bean, bean.getClass()); + } + + public BeanDefine(Object bean, Class type) { + this.bean = bean; + this.type = type; + this.isSignle = true; + } + + public BeanDefine(Object bean, Class type, boolean isSingle) { + this.bean = bean; + this.type = type; + this.isSignle = isSingle; + } + + public Object getBean() { + return bean; + } + + public void setBean(Object bean) { + this.bean = bean; + } + + public Class getType() { + return type; + } + + public void setType(Class type) { + this.type = type; + } + + public boolean isSignle() { + return isSignle; + } + + public void setSignle(boolean isSignle) { + this.isSignle = isSignle; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/Ioc.java b/blade-core/src/main/java/com/blade/ioc/Ioc.java index e7ad38193..93b2ad4c5 100644 --- a/blade-core/src/main/java/com/blade/ioc/Ioc.java +++ b/blade-core/src/main/java/com/blade/ioc/Ioc.java @@ -1,53 +1,53 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.util.List; -import java.util.Set; - -import com.blade.ioc.loader.IocLoader; - -/** - * IOC container, it provides an interface for registration and bean. - * - * @author biezhi - * @since 1.0 - */ -public interface Ioc { - - void load(IocLoader iocLoader); - - void addBean(Object bean); - - Object addBean(Class type); - - void addBean(String name, Object bean); - - void setBean(Class type, Object proxyBean); - - Object getBean(String name); - - T getBean(Class type); - - List getBeanDefines(); - - List getBeans(); - - Set getBeanNames(); - - void clearAll(); - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.util.List; +import java.util.Set; + +import com.blade.ioc.loader.IocLoader; + +/** + * IOC container, it provides an interface for registration and bean. + * + * @author biezhi + * @since 1.5 + */ +public interface Ioc { + + void load(IocLoader iocLoader); + + void addBean(Object bean); + + Object addBean(Class type); + + void addBean(String name, Object bean); + + void setBean(Class type, Object proxyBean); + + Object getBean(String name); + + T getBean(Class type); + + List getBeanDefines(); + + List getBeans(); + + Set getBeanNames(); + + void clearAll(); + +} diff --git a/blade-core/src/main/java/com/blade/ioc/IocKit.java b/blade-core/src/main/java/com/blade/ioc/IocKit.java index 00a498633..880ed705f 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocKit.java +++ b/blade-core/src/main/java/com/blade/ioc/IocKit.java @@ -1,80 +1,80 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import com.blade.ioc.annotation.InjectWith; -import com.blade.ioc.injector.FieldInjector; -import com.blade.kit.reflect.ClassDefine; - -/** - * IocKit, get Bean - * - * @author biezhi - * @since 1.0 - */ -public class IocKit { - - /** - * Get @Inject Annotated field - * - * @param ioc ioc container - * @param classDefine classDefine - * @return return FieldInjector - */ - public static List getInjectFields(Ioc ioc, ClassDefine classDefine) { - List injectors = new ArrayList(8); - for (Field field : classDefine.getDeclaredFields()) { - for (Annotation annotation : field.getAnnotations()) { - InjectWith with = annotation.annotationType().getAnnotation(InjectWith.class); - if (with != null) { - injectors.add(new FieldInjector(ioc, field)); - } - } - } - if (injectors.size() == 0) { - return Collections.emptyList(); - } - return injectors; - } - - /** - * Get bean according to BeanDefine - * - * @param ioc ioc container - * @param beanDefine beandefine object - * @return bean object - */ - public static Object getBean(BeanDefine beanDefine) { - Object bean = beanDefine.getBean(); - return bean; - } - - public static void injection(Ioc ioc, BeanDefine beanDefine) { - ClassDefine classDefine = ClassDefine.create(beanDefine.getType()); - List fieldInjectors = IocKit.getInjectFields(ioc, classDefine); - Object bean = beanDefine.getBean(); - for (FieldInjector fieldInjector : fieldInjectors) { - fieldInjector.injection(bean); - } - } - +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.blade.ioc.annotation.InjectWith; +import com.blade.ioc.injector.FieldInjector; +import com.blade.kit.reflect.ClassDefine; + +/** + * IocKit, get Bean + * + * @author biezhi + * @since 1.5 + */ +public class IocKit { + + /** + * Get @Inject Annotated field + * + * @param ioc ioc container + * @param classDefine classDefine + * @return return FieldInjector + */ + public static List getInjectFields(Ioc ioc, ClassDefine classDefine) { + List injectors = new ArrayList(8); + for (Field field : classDefine.getDeclaredFields()) { + for (Annotation annotation : field.getAnnotations()) { + InjectWith with = annotation.annotationType().getAnnotation(InjectWith.class); + if (with != null) { + injectors.add(new FieldInjector(ioc, field)); + } + } + } + if (injectors.size() == 0) { + return Collections.emptyList(); + } + return injectors; + } + + /** + * Get bean according to BeanDefine + * + * @param ioc ioc container + * @param beanDefine beandefine object + * @return bean object + */ + public static Object getBean(BeanDefine beanDefine) { + Object bean = beanDefine.getBean(); + return bean; + } + + public static void injection(Ioc ioc, BeanDefine beanDefine) { + ClassDefine classDefine = ClassDefine.create(beanDefine.getType()); + List fieldInjectors = IocKit.getInjectFields(ioc, classDefine); + Object bean = beanDefine.getBean(); + for (FieldInjector fieldInjector : fieldInjectors) { + fieldInjector.injection(bean); + } + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java index c7dbb05a8..985b8e2c0 100644 --- a/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java +++ b/blade-core/src/main/java/com/blade/ioc/SimpleIoc.java @@ -1,224 +1,224 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.ioc.loader.IocLoader; -import com.blade.kit.Assert; - -/** - * The default IOC container implementation - * - * @author biezhi - * @since 1.0 - */ -public class SimpleIoc implements Ioc { - - private static final Logger LOGGER = LoggerFactory.getLogger(Ioc.class); - - private final Map pool = new HashMap(); - - /** - * ioc loader - */ - @Override - public void load(IocLoader loader) { - loader.load(this); - } - - /** - * Add user-defined objects - */ - @Override - public void addBean(Object bean) { - Assert.notNull(bean); - addBean(bean.getClass().getName(), bean); - } - - /** - * Add user-defined objects - */ - public void addBean(Class beanClass, Object bean) { - Assert.notNull(beanClass); - addBean(beanClass.getName(), bean); - } - - /** - * Add user-defined objects - */ - public void addBean(String name, Object bean) { - Assert.notNull(bean); - BeanDefine beanDefine = new BeanDefine(bean); - addBean(name, beanDefine); - - // add interface - Class[] interfaces = beanDefine.getType().getInterfaces(); - if(interfaces.length > 0){ - for(Class interfaceClazz : interfaces){ - this.addBean(interfaceClazz.getName(), beanDefine); - } - } - } - - /** - * Update BeanDefine - */ - public void setBean(Class type, Object proxyBean) { - Assert.notNull(proxyBean); - - BeanDefine beanDefine = pool.get(type.getName()); - if(beanDefine != null){ - beanDefine.setBean(proxyBean); - } else { - beanDefine = new BeanDefine(proxyBean, type); - } - pool.put(type.getName(), beanDefine); - } - - /** - * Add user-defined objects - */ - public void addBean(String name, BeanDefine beanDefine) { - - Assert.notNull(name); - Assert.notNull(beanDefine); - -// LOGGER.debug("addBean: {}", name); - - if (pool.put(name, beanDefine) != null) { - LOGGER.warn("Duplicated Bean: {}", name); - } - - } - - /** - * Register @Component marked objects - */ - @Override - public Object addBean(Class type) { - return addBean(type, true); - } - - /** - * Register @Component marked objects - */ - public Object addBean(Class type, boolean singleton) { - Assert.notNull(type); - return addBean(type.getName(), type, singleton); - } - - /** - * Register @Component marked objects - */ - public Object addBean(String name, Class beanClass, boolean singleton) { - - Assert.notNull(name); - Assert.notNull(beanClass); - Assert.isFalse(beanClass.isInterface(), "Must not be interface: %s", beanClass.getName()); - Assert.isFalse(Modifier.isAbstract(beanClass.getModifiers()), "Must not be abstract class: %s", beanClass.getName()); - -// LOGGER.debug("addBean: {} = {}", name, beanClass.getName()); - - BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton); - - if (pool.put(name, beanDefine) != null) { - LOGGER.warn("Duplicated Bean: {}", name); - } - - // add interface - Class[] interfaces = beanClass.getInterfaces(); - if(interfaces.length > 0){ - for(Class interfaceClazz : interfaces){ - if(null != this.getBean(interfaceClazz)){ - break; - } - this.addBean(interfaceClazz.getName(), beanDefine); - } - } - - return beanDefine.getBean(); - } - - public BeanDefine getBeanDefine(Class beanClass, boolean singleton) { - try { - Object object = beanClass.newInstance(); - return new BeanDefine(object, beanClass, singleton); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public T getBean(Class type) { - Object bean = this.getBean(type.getName()); - try { - return type.cast(bean); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Object getBean(String name) { - BeanDefine beanDefine = pool.get(name); - if (beanDefine == null) { - return null; - } - return IocKit.getBean(beanDefine); - } - - @Override - public List getBeanDefines() { - return new ArrayList(pool.values()); - } - - @Override - public List getBeans() { - Set beanNames = this.getBeanNames(); - List beans = new ArrayList(beanNames.size()); - for(String beanName : beanNames){ - Object bean = this.getBean(beanName); - if(null != bean){ - beans.add(bean); - } - } - return beans; - } - - @Override - public Set getBeanNames() { - return pool.keySet(); - } - - @Override - public void clearAll() { - pool.clear(); - } - +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.ioc.loader.IocLoader; +import com.blade.kit.Assert; + +/** + * The default IOC container implementation + * + * @author biezhi + * @since 1.5 + */ +public class SimpleIoc implements Ioc { + + private static final Logger LOGGER = LoggerFactory.getLogger(Ioc.class); + + private final Map pool = new HashMap(); + + /** + * ioc loader + */ + @Override + public void load(IocLoader loader) { + loader.load(this); + } + + /** + * Add user-defined objects + */ + @Override + public void addBean(Object bean) { + Assert.notNull(bean); + addBean(bean.getClass().getName(), bean); + } + + /** + * Add user-defined objects + */ + public void addBean(Class beanClass, Object bean) { + Assert.notNull(beanClass); + addBean(beanClass.getName(), bean); + } + + /** + * Add user-defined objects + */ + public void addBean(String name, Object bean) { + Assert.notNull(bean); + BeanDefine beanDefine = new BeanDefine(bean); + addBean(name, beanDefine); + + // add interface + Class[] interfaces = beanDefine.getType().getInterfaces(); + if(interfaces.length > 0){ + for(Class interfaceClazz : interfaces){ + this.addBean(interfaceClazz.getName(), beanDefine); + } + } + } + + /** + * Update BeanDefine + */ + public void setBean(Class type, Object proxyBean) { + Assert.notNull(proxyBean); + + BeanDefine beanDefine = pool.get(type.getName()); + if(beanDefine != null){ + beanDefine.setBean(proxyBean); + } else { + beanDefine = new BeanDefine(proxyBean, type); + } + pool.put(type.getName(), beanDefine); + } + + /** + * Add user-defined objects + */ + public void addBean(String name, BeanDefine beanDefine) { + + Assert.notNull(name); + Assert.notNull(beanDefine); + +// LOGGER.debug("addBean: {}", name); + + if (pool.put(name, beanDefine) != null) { + LOGGER.warn("Duplicated Bean: {}", name); + } + + } + + /** + * Register @Component marked objects + */ + @Override + public Object addBean(Class type) { + return addBean(type, true); + } + + /** + * Register @Component marked objects + */ + public Object addBean(Class type, boolean singleton) { + Assert.notNull(type); + return addBean(type.getName(), type, singleton); + } + + /** + * Register @Component marked objects + */ + public Object addBean(String name, Class beanClass, boolean singleton) { + + Assert.notNull(name); + Assert.notNull(beanClass); + Assert.isFalse(beanClass.isInterface(), "Must not be interface: %s", beanClass.getName()); + Assert.isFalse(Modifier.isAbstract(beanClass.getModifiers()), "Must not be abstract class: %s", beanClass.getName()); + +// LOGGER.debug("addBean: {} = {}", name, beanClass.getName()); + + BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton); + + if (pool.put(name, beanDefine) != null) { + LOGGER.warn("Duplicated Bean: {}", name); + } + + // add interface + Class[] interfaces = beanClass.getInterfaces(); + if(interfaces.length > 0){ + for(Class interfaceClazz : interfaces){ + if(null != this.getBean(interfaceClazz)){ + break; + } + this.addBean(interfaceClazz.getName(), beanDefine); + } + } + + return beanDefine.getBean(); + } + + public BeanDefine getBeanDefine(Class beanClass, boolean singleton) { + try { + Object object = beanClass.newInstance(); + return new BeanDefine(object, beanClass, singleton); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public T getBean(Class type) { + Object bean = this.getBean(type.getName()); + try { + return type.cast(bean); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Object getBean(String name) { + BeanDefine beanDefine = pool.get(name); + if (beanDefine == null) { + return null; + } + return IocKit.getBean(beanDefine); + } + + @Override + public List getBeanDefines() { + return new ArrayList(pool.values()); + } + + @Override + public List getBeans() { + Set beanNames = this.getBeanNames(); + List beans = new ArrayList(beanNames.size()); + for(String beanName : beanNames){ + Object bean = this.getBean(beanName); + if(null != bean){ + beans.add(bean); + } + } + return beans; + } + + @Override + public Set getBeanNames() { + return pool.keySet(); + } + + @Override + public void clearAll() { + pool.clear(); + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/annotation/Component.java b/blade-core/src/main/java/com/blade/ioc/annotation/Component.java index 5c0e50fbf..912ffaa82 100644 --- a/blade-core/src/main/java/com/blade/ioc/annotation/Component.java +++ b/blade-core/src/main/java/com/blade/ioc/annotation/Component.java @@ -1,36 +1,36 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Bean annotations can be injected - * - * @author biezhi - * @since 1.0 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Component{ - - String value() default ""; - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Bean annotations can be injected + * + * @author biezhi + * @since 1.5 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Component{ + + String value() default ""; + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/annotation/Inject.java b/blade-core/src/main/java/com/blade/ioc/annotation/Inject.java index edb4d3eb6..2b3c4bcfc 100644 --- a/blade-core/src/main/java/com/blade/ioc/annotation/Inject.java +++ b/blade-core/src/main/java/com/blade/ioc/annotation/Inject.java @@ -26,7 +26,7 @@ * Automatic injection * * @author biezhi - * @since 1.0 + * @since 1.5 */ @Target(ElementType.FIELD) @InjectWith(FieldInjector.class) diff --git a/blade-core/src/main/java/com/blade/ioc/annotation/Service.java b/blade-core/src/main/java/com/blade/ioc/annotation/Service.java index 9a69d551d..f890cf8a1 100644 --- a/blade-core/src/main/java/com/blade/ioc/annotation/Service.java +++ b/blade-core/src/main/java/com/blade/ioc/annotation/Service.java @@ -1,36 +1,36 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Bean annotations can be injected - * - * @author biezhi - * @since 1.0 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Service{ - - String value() default ""; - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Bean annotations can be injected + * + * @author biezhi + * @since 1.5 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Service{ + + String value() default ""; + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java b/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java index e52865289..00883c038 100644 --- a/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java +++ b/blade-core/src/main/java/com/blade/ioc/injector/FieldInjector.java @@ -1,51 +1,57 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.injector; - -import java.lang.reflect.Field; - -import com.blade.ioc.Ioc; - -public class FieldInjector implements Injector { - - private Ioc ioc; - - private Field field; - - public FieldInjector(Ioc ioc, Field field) { - this.ioc = ioc; - this.field = field; - } - - @Override - public void injection(Object bean) { - try { - Class fieldType = field.getType(); - Object value = ioc.getBean(fieldType); - if (value == null) { - throw new IllegalStateException("Can't inject bean: " + fieldType.getName() + " for field: " + field); - } - field.setAccessible(true); - field.set(bean, value); - } catch (SecurityException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.injector; + +import java.lang.reflect.Field; + +import com.blade.ioc.Ioc; + +/** + * Bean Field Injector + * + * @author biezhi + * @since 1.5 + */ +public class FieldInjector implements Injector { + + private Ioc ioc; + + private Field field; + + public FieldInjector(Ioc ioc, Field field) { + this.ioc = ioc; + this.field = field; + } + + @Override + public void injection(Object bean) { + try { + Class fieldType = field.getType(); + Object value = ioc.getBean(fieldType); + if (value == null) { + throw new IllegalStateException("Can't inject bean: " + fieldType.getName() + " for field: " + field); + } + field.setAccessible(true); + field.set(bean, value); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/injector/Injector.java b/blade-core/src/main/java/com/blade/ioc/injector/Injector.java index ff7c0db23..1f7a891bb 100644 --- a/blade-core/src/main/java/com/blade/ioc/injector/Injector.java +++ b/blade-core/src/main/java/com/blade/ioc/injector/Injector.java @@ -1,22 +1,28 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.injector; - -public interface Injector { - - void injection(Object bean); - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.injector; + +/** + * Bean Injector interface + * + * @author biezhi + * @since 1.5 + */ +public interface Injector { + + void injection(Object bean); + +} diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java index 6741abe9c..266ca2be1 100644 --- a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java @@ -28,6 +28,12 @@ import com.blade.kit.resource.ClassInfo; import com.blade.kit.resource.ClassReader; +/** + * Ioc annotation loader + * + * @author biezhi + * @since 1.5 + */ public final class IocAnnotationLoader implements IocLoader { private Collection classes; diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java index f07aefbce..36d4d3858 100644 --- a/blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocLoader.java @@ -1,24 +1,30 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.loader; - -import com.blade.ioc.SimpleIoc; - -public interface IocLoader { - - void load(SimpleIoc ioc); - +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.loader; + +import com.blade.ioc.SimpleIoc; + +/** + * Ioc loader interface + * + * @author biezhi + * @since 1.5 + */ +public interface IocLoader { + + void load(SimpleIoc ioc); + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/plugin/Plugin.java b/blade-core/src/main/java/com/blade/plugin/Plugin.java index b9d71e4fb..a41d47dd5 100644 --- a/blade-core/src/main/java/com/blade/plugin/Plugin.java +++ b/blade-core/src/main/java/com/blade/plugin/Plugin.java @@ -1,35 +1,35 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.plugin; - -/** - * Plugin Interface - * - * @author biezhi - * @since 1.0 - */ -public interface Plugin { - - /** - * Start Plugin - */ - void start(); - - /** - * Destroy, release resources - */ - void destroy(); -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.plugin; + +/** + * Plugin Interface + * + * @author biezhi + * @since 1.5 + */ +public interface Plugin { + + /** + * Start Plugin + */ + void start(); + + /** + * Destroy, release resources + */ + void destroy(); +} diff --git a/blade-core/src/main/java/com/blade/route/Route.java b/blade-core/src/main/java/com/blade/route/Route.java index 9b528f3de..efe758df2 100644 --- a/blade-core/src/main/java/com/blade/route/Route.java +++ b/blade-core/src/main/java/com/blade/route/Route.java @@ -1,139 +1,139 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import java.lang.reflect.Method; - -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Path; - -/** - * Route Bean - * - * @author biezhi - * @since 1.0 - */ -public class Route { - - /** - * HTTP Request Method - */ - private HttpMethod httpMethod; - - /** - * Route path - */ - private String path; - - /** - * Logical controller object - */ - private Object target; - - /** - * Controller Class Type - */ - private Class targetType; - - /** - * Implementation logic controller method - */ - private Method action; - - public Route() { - } - - public Route(HttpMethod httpMethod, String path, Object target, Class targetType, Method action) { - super(); - this.httpMethod = httpMethod; - this.path = Path.fixPath(path); - this.target = target; - this.targetType = targetType; - this.action = action; - } - - public HttpMethod getHttpMethod() { - return httpMethod; - } - - public void setHttpMethod(HttpMethod httpMethod) { - this.httpMethod = httpMethod; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public Object getTarget() { - return target; - } - - public void setTarget(Object target) { - this.target = target; - } - - public Method getAction() { - return action; - } - - public void setAction(Method action) { - this.action = action; - } - - public Class getTargetType() { - return targetType; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((action == null) ? 0 : action.hashCode()); - result = prime * result + ((httpMethod == null) ? 0 : httpMethod.hashCode()); - result = prime * result + ((path == null) ? 0 : path.hashCode()); - result = prime * result + ((target == null) ? 0 : target.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Route other = (Route) obj; - if (httpMethod != other.httpMethod) - return false; - if (path == null) { - if (other.path != null) - return false; - } else if (!path.equals(other.path)) - return false; - return true; - } - - @Override - public String toString() { - return httpMethod + "\t" + path; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import java.lang.reflect.Method; + +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Path; + +/** + * Route Bean + * + * @author biezhi + * @since 1.5 + */ +public class Route { + + /** + * HTTP Request Method + */ + private HttpMethod httpMethod; + + /** + * Route path + */ + private String path; + + /** + * Logical controller object + */ + private Object target; + + /** + * Controller Class Type + */ + private Class targetType; + + /** + * Implementation logic controller method + */ + private Method action; + + public Route() { + } + + public Route(HttpMethod httpMethod, String path, Object target, Class targetType, Method action) { + super(); + this.httpMethod = httpMethod; + this.path = Path.fixPath(path); + this.target = target; + this.targetType = targetType; + this.action = action; + } + + public HttpMethod getHttpMethod() { + return httpMethod; + } + + public void setHttpMethod(HttpMethod httpMethod) { + this.httpMethod = httpMethod; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Object getTarget() { + return target; + } + + public void setTarget(Object target) { + this.target = target; + } + + public Method getAction() { + return action; + } + + public void setAction(Method action) { + this.action = action; + } + + public Class getTargetType() { + return targetType; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((action == null) ? 0 : action.hashCode()); + result = prime * result + ((httpMethod == null) ? 0 : httpMethod.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + ((target == null) ? 0 : target.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Route other = (Route) obj; + if (httpMethod != other.httpMethod) + return false; + if (path == null) { + if (other.path != null) + return false; + } else if (!path.equals(other.path)) + return false; + return true; + } + + @Override + public String toString() { + return httpMethod + "\t" + path; + } + +} diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/route/RouteBuilder.java index 317dce201..455ff64e5 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/route/RouteBuilder.java @@ -1,247 +1,247 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import java.lang.reflect.Method; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.annotation.Controller; -import com.blade.annotation.Intercept; -import com.blade.annotation.RestController; -import com.blade.annotation.Route; -import com.blade.context.DynamicClassReader; -import com.blade.interceptor.Interceptor; -import com.blade.kit.CollectionKit; -import com.blade.kit.StringKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -/** - * Route builder - * - * @author biezhi - * @since 1.0 - */ -public class RouteBuilder { - - private static final Logger LOGGER = LoggerFactory.getLogger(RouteBuilder.class); - - /** - * Class reader, used to scan the class specified in the rules - */ - private ClassReader classReader; - - private Routers routers; - - private String[] routePackages; - - private String interceptorPackage; - - public RouteBuilder(Routers routers) { - this.routers = routers; - this.classReader = DynamicClassReader.getClassReader(); - } - - /** - * Start building route - */ - public void building() { - - this.routePackages = Blade.$().config().getRoutePackages(); - this.interceptorPackage = Blade.$().config().getInterceptorPackage(); - - // Route - if(null != routePackages && routePackages.length > 0){ - this.buildRoute(routePackages); - } - - // Inteceptor - if(StringKit.isNotBlank(interceptorPackage)){ - this.buildInterceptor(interceptorPackage); - } - - } - - /** - * Build interceptor - * - * @param interceptorPackages add the interceptor package - */ - private void buildInterceptor(String... interceptorPackages){ - - // Scan all Interceptor - Set classes = null; - - // Traversal Interceptor - for(String packageName : interceptorPackages){ - - // Scan all Interceptor - classes = classReader.getClass(packageName, Interceptor.class, false); - if(CollectionKit.isNotEmpty(classes)){ - for(ClassInfo classInfo : classes){ - Class interceptorClazz = classInfo.getClazz(); - addInterceptor(interceptorClazz); - } - } - } - } - - /** - * Build Route - * - * @param routePackages route packets to add - */ - private void buildRoute(String... routePackages){ - Set classes = null; - // Traverse route - for(String packageName : routePackages){ - // Scan all Controoler - classes = classReader.getClassByAnnotation(packageName, Controller.class, true); - if(CollectionKit.isNotEmpty(classes)){ - for(ClassInfo classInfo : classes){ - Class pathClazz = classInfo.getClazz(); - addRouter(pathClazz); - } - } - } - - } - - /** - * Parse Interceptor - * - * @param interceptor resolve the interceptor class - */ - public void addInterceptor(final Class interceptor){ - - boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); - - if(null == interceptor || !hasInterface){ - return; - } - - Intercept intercept = interceptor.getAnnotation(Intercept.class); - String partten = "/.*"; - if(null != intercept){ - partten = intercept.value(); - } - - try { - Method before = interceptor.getMethod("before", Request.class, Response.class); - Method after = interceptor.getMethod("after", Request.class, Response.class); - buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); - buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - - } - - /** - * Parse all routing in a controller - * - * @param controller resolve the routing class - */ - public void addRouter(final Class router){ - - Method[] methods = router.getMethods(); - if(null == methods || methods.length == 0){ - return; - } - String nameSpace = null, suffix = null; - - if(null != router.getAnnotation(Controller.class)){ - nameSpace = router.getAnnotation(Controller.class).value(); - suffix = router.getAnnotation(Controller.class).suffix(); - } - - if(null != router.getAnnotation(RestController.class)){ - nameSpace = router.getAnnotation(RestController.class).value(); - suffix = router.getAnnotation(RestController.class).suffix(); - } - - if(null == nameSpace && null == suffix){ - LOGGER.warn("Route [{}] not controller annotation", router.getName()); - return; - } - - for (Method method : methods) { - Route mapping = method.getAnnotation(Route.class); - //route method - if (null != mapping) { - // build multiple route - HttpMethod methodType = mapping.method(); - String[] paths = mapping.value(); - if(null != paths && paths.length > 0){ - for(String value : paths){ - String pathV = getRoutePath(value, nameSpace, suffix); - buildRoute(router, method, pathV, methodType); - } - } - } - } - } - - private String getRoutePath(String value, String nameSpace, String suffix){ - String path = value.startsWith("/") ? value : "/" + value; - - nameSpace = nameSpace.startsWith("/") ? nameSpace : "/" + nameSpace; - path = nameSpace + path; - - path = path.replaceAll("[/]+", "/"); - - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - - path = path + suffix; - - return path; - } - - /** - * Build a route - * - * @param target route target execution class - * @param execMethod route execution method - * @param path route path - * @param method route httpmethod - */ - private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - - /** - * Build a route - * - * @param path route path - * @param target route target execution class - * @param execMethod route execution method - * @param method route httpmethod - */ - private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import java.lang.reflect.Method; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.annotation.Controller; +import com.blade.annotation.Intercept; +import com.blade.annotation.RestController; +import com.blade.annotation.Route; +import com.blade.context.DynamicClassReader; +import com.blade.interceptor.Interceptor; +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * Route builder + * + * @author biezhi + * @since 1.5 + */ +public class RouteBuilder { + + private static final Logger LOGGER = LoggerFactory.getLogger(RouteBuilder.class); + + /** + * Class reader, used to scan the class specified in the rules + */ + private ClassReader classReader; + + private Routers routers; + + private String[] routePackages; + + private String interceptorPackage; + + public RouteBuilder(Routers routers) { + this.routers = routers; + this.classReader = DynamicClassReader.getClassReader(); + } + + /** + * Start building route + */ + public void building() { + + this.routePackages = Blade.$().config().getRoutePackages(); + this.interceptorPackage = Blade.$().config().getInterceptorPackage(); + + // Route + if(null != routePackages && routePackages.length > 0){ + this.buildRoute(routePackages); + } + + // Inteceptor + if(StringKit.isNotBlank(interceptorPackage)){ + this.buildInterceptor(interceptorPackage); + } + + } + + /** + * Build interceptor + * + * @param interceptorPackages add the interceptor package + */ + private void buildInterceptor(String... interceptorPackages){ + + // Scan all Interceptor + Set classes = null; + + // Traversal Interceptor + for(String packageName : interceptorPackages){ + + // Scan all Interceptor + classes = classReader.getClass(packageName, Interceptor.class, false); + if(CollectionKit.isNotEmpty(classes)){ + for(ClassInfo classInfo : classes){ + Class interceptorClazz = classInfo.getClazz(); + addInterceptor(interceptorClazz); + } + } + } + } + + /** + * Build Route + * + * @param routePackages route packets to add + */ + private void buildRoute(String... routePackages){ + Set classes = null; + // Traverse route + for(String packageName : routePackages){ + // Scan all Controoler + classes = classReader.getClassByAnnotation(packageName, Controller.class, true); + if(CollectionKit.isNotEmpty(classes)){ + for(ClassInfo classInfo : classes){ + Class pathClazz = classInfo.getClazz(); + addRouter(pathClazz); + } + } + } + + } + + /** + * Parse Interceptor + * + * @param interceptor resolve the interceptor class + */ + public void addInterceptor(final Class interceptor){ + + boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); + + if(null == interceptor || !hasInterface){ + return; + } + + Intercept intercept = interceptor.getAnnotation(Intercept.class); + String partten = "/.*"; + if(null != intercept){ + partten = intercept.value(); + } + + try { + Method before = interceptor.getMethod("before", Request.class, Response.class); + Method after = interceptor.getMethod("after", Request.class, Response.class); + buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); + buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + + } + + /** + * Parse all routing in a controller + * + * @param controller resolve the routing class + */ + public void addRouter(final Class router){ + + Method[] methods = router.getMethods(); + if(null == methods || methods.length == 0){ + return; + } + String nameSpace = null, suffix = null; + + if(null != router.getAnnotation(Controller.class)){ + nameSpace = router.getAnnotation(Controller.class).value(); + suffix = router.getAnnotation(Controller.class).suffix(); + } + + if(null != router.getAnnotation(RestController.class)){ + nameSpace = router.getAnnotation(RestController.class).value(); + suffix = router.getAnnotation(RestController.class).suffix(); + } + + if(null == nameSpace && null == suffix){ + LOGGER.warn("Route [{}] not controller annotation", router.getName()); + return; + } + + for (Method method : methods) { + Route mapping = method.getAnnotation(Route.class); + //route method + if (null != mapping) { + // build multiple route + HttpMethod methodType = mapping.method(); + String[] paths = mapping.value(); + if(null != paths && paths.length > 0){ + for(String value : paths){ + String pathV = getRoutePath(value, nameSpace, suffix); + buildRoute(router, method, pathV, methodType); + } + } + } + } + } + + private String getRoutePath(String value, String nameSpace, String suffix){ + String path = value.startsWith("/") ? value : "/" + value; + + nameSpace = nameSpace.startsWith("/") ? nameSpace : "/" + nameSpace; + path = nameSpace + path; + + path = path.replaceAll("[/]+", "/"); + + path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + + path = path + suffix; + + return path; + } + + /** + * Build a route + * + * @param target route target execution class + * @param execMethod route execution method + * @param path route path + * @param method route httpmethod + */ + private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + + /** + * Build a route + * + * @param path route path + * @param target route target execution class + * @param execMethod route execution method + * @param method route httpmethod + */ + private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/RouteException.java b/blade-core/src/main/java/com/blade/route/RouteException.java index 1242bebe7..c8d32d73d 100644 --- a/blade-core/src/main/java/com/blade/route/RouteException.java +++ b/blade-core/src/main/java/com/blade/route/RouteException.java @@ -19,7 +19,7 @@ * RouteException * * @author biezhi - * @since 1.0 + * @since 1.5 */ public class RouteException extends RuntimeException { diff --git a/blade-core/src/main/java/com/blade/route/RouteGroup.java b/blade-core/src/main/java/com/blade/route/RouteGroup.java index 75df3684b..18ffcd24d 100644 --- a/blade-core/src/main/java/com/blade/route/RouteGroup.java +++ b/blade-core/src/main/java/com/blade/route/RouteGroup.java @@ -1,76 +1,76 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import com.blade.Blade; - -/** - * Route Group. - * - * @author biezhi - * @since 1.0 - */ -public class RouteGroup { - - private Blade blade; - private String prefix; - - public RouteGroup(Blade blade, String prefix) { - this.blade = blade; - this.prefix = prefix; - } - - public RouteGroup get(RouteHandler routeHandler){ - blade.get(prefix, routeHandler); - return this; - } - - public RouteGroup get(String path, RouteHandler routeHandler){ - blade.get(prefix + path, routeHandler); - return this; - } - - public RouteGroup post(RouteHandler routeHandler){ - blade.post(prefix, routeHandler); - return this; - } - - public RouteGroup post(String path, RouteHandler routeHandler){ - blade.post(prefix + path, routeHandler); - return this; - } - - public RouteGroup delete(RouteHandler routeHandler){ - blade.delete(prefix, routeHandler); - return this; - } - - public RouteGroup delete(String path, RouteHandler routeHandler){ - blade.delete(prefix + path, routeHandler); - return this; - } - - public RouteGroup put(RouteHandler routeHandler){ - blade.put(prefix, routeHandler); - return this; - } - - public RouteGroup put(String path, RouteHandler routeHandler){ - blade.put(prefix + path, routeHandler); - return this; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import com.blade.Blade; + +/** + * Route Group. + * + * @author biezhi + * @since 1.5 + */ +public class RouteGroup { + + private Blade blade; + private String prefix; + + public RouteGroup(Blade blade, String prefix) { + this.blade = blade; + this.prefix = prefix; + } + + public RouteGroup get(RouteHandler routeHandler){ + blade.get(prefix, routeHandler); + return this; + } + + public RouteGroup get(String path, RouteHandler routeHandler){ + blade.get(prefix + path, routeHandler); + return this; + } + + public RouteGroup post(RouteHandler routeHandler){ + blade.post(prefix, routeHandler); + return this; + } + + public RouteGroup post(String path, RouteHandler routeHandler){ + blade.post(prefix + path, routeHandler); + return this; + } + + public RouteGroup delete(RouteHandler routeHandler){ + blade.delete(prefix, routeHandler); + return this; + } + + public RouteGroup delete(String path, RouteHandler routeHandler){ + blade.delete(prefix + path, routeHandler); + return this; + } + + public RouteGroup put(RouteHandler routeHandler){ + blade.put(prefix, routeHandler); + return this; + } + + public RouteGroup put(String path, RouteHandler routeHandler){ + blade.put(prefix + path, routeHandler); + return this; + } + +} diff --git a/blade-core/src/main/java/com/blade/route/RouteHandler.java b/blade-core/src/main/java/com/blade/route/RouteHandler.java index df6449587..9fc1c49aa 100644 --- a/blade-core/src/main/java/com/blade/route/RouteHandler.java +++ b/blade-core/src/main/java/com/blade/route/RouteHandler.java @@ -1,31 +1,31 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -/** - * Route Handler - * - * @author biezhi - * @since 1.0 - */ -public interface RouteHandler { - - public void handle(Request request, Response response); - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * Route Handler + * + * @author biezhi + * @since 1.5 + */ +public interface RouteHandler { + + public void handle(Request request, Response response); + +} diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/route/RouteMatcher.java index 3b3888279..4bb4edf61 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/route/RouteMatcher.java @@ -1,176 +1,176 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Path; - -/** - * Default Route Matcher - * - * @author biezhi - * @since 1.0 - */ -public class RouteMatcher { - -// private static final Logger LOGGER = Logger.getLogger(SampleRouteMatcher.class); - - // Storage URL and route - private Map routes = null; - private Map interceptors = null; - - // Storage Map Key - private Set routeKeys = null; - private List interceptorRoutes = new ArrayList(); - - public RouteMatcher(Routers routers) { - this.routes = routers.getRoutes(); - this.interceptors = routers.getInterceptors(); - this.routeKeys = routes.keySet(); - Collection inters = interceptors.values(); - if (null != inters && inters.size() > 0) { - this.interceptorRoutes.addAll(inters); - } - } - - /** - * Find a route - * @param httpMethod httpMethod - * @param path request path - * @return return route object - */ - public Route getRoute(String httpMethod, String path) { - String cleanPath = parsePath(path); - - String routeKey = path + "#" + httpMethod.toUpperCase(); - Route route = routes.get(routeKey); - if(null != route){ - return route; - } - route = routes.get(path + "#ALL"); - if(null != route){ - return route; - } - - List matchRoutes = new ArrayList(); - for(String key : routeKeys){ - String[] keyArr = key.split("#"); - HttpMethod routeMethod = HttpMethod.valueOf(keyArr[1]); - if (matchesPath(keyArr[0], cleanPath)) { - if (routeMethod == HttpMethod.ALL || HttpMethod.valueOf(httpMethod) == routeMethod) { - route = routes.get(key); - matchRoutes.add(route); - } - } - } - - // Priority matching principle - giveMatch(path, matchRoutes); - - return matchRoutes.size() > 0 ? matchRoutes.get(0) : null; - } - - /** - * Find all in before of the interceptor - * @param path request path - * @return return interceptor list - */ - public List getBefore(String path) { - - List befores = new ArrayList(); - String cleanPath = parsePath(path); - for (Route route : interceptorRoutes) { - if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.BEFORE){ - befores.add(route); - } - } - giveMatch(path, befores); - return befores; - } - - /** - * Find all in after of the interceptor - * @param path request path - * @return return interceptor list - */ - public List getAfter(String path) { - List afters = new ArrayList(); - String cleanPath = parsePath(path); - for (Route route : interceptorRoutes) { - if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.AFTER){ - afters.add(route); - } - } - giveMatch(path, afters); - return afters; - } - - /** - * Sort of path - * @param uri request uri - * @param routes route list - */ - private void giveMatch(final String uri, List routes) { - Collections.sort(routes, new Comparator() { - @Override - public int compare(Route o1, Route o2) { - if(o2.getPath().equals(uri)){ - return o2.getPath().indexOf(uri); - } - return -1; - } - }); - } - - /** - * Matching path - * - * @param routePath route path - * @param pathToMatch match path - * @return return match is success - */ - private boolean matchesPath(String routePath, String pathToMatch) { - routePath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); - return pathToMatch.matches("(?i)" + routePath); - } - - /** - * Parse Path - * - * @param path route path - * @return return parsed path - */ - private String parsePath(String path) { - path = Path.fixPath(path); - try { - URI uri = new URI(path); - return uri.getPath(); - } catch (URISyntaxException e) { - return null; - } - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Path; + +/** + * Default Route Matcher + * + * @author biezhi + * @since 1.5 + */ +public class RouteMatcher { + +// private static final Logger LOGGER = Logger.getLogger(SampleRouteMatcher.class); + + // Storage URL and route + private Map routes = null; + private Map interceptors = null; + + // Storage Map Key + private Set routeKeys = null; + private List interceptorRoutes = new ArrayList(); + + public RouteMatcher(Routers routers) { + this.routes = routers.getRoutes(); + this.interceptors = routers.getInterceptors(); + this.routeKeys = routes.keySet(); + Collection inters = interceptors.values(); + if (null != inters && inters.size() > 0) { + this.interceptorRoutes.addAll(inters); + } + } + + /** + * Find a route + * @param httpMethod httpMethod + * @param path request path + * @return return route object + */ + public Route getRoute(String httpMethod, String path) { + String cleanPath = parsePath(path); + + String routeKey = path + "#" + httpMethod.toUpperCase(); + Route route = routes.get(routeKey); + if(null != route){ + return route; + } + route = routes.get(path + "#ALL"); + if(null != route){ + return route; + } + + List matchRoutes = new ArrayList(); + for(String key : routeKeys){ + String[] keyArr = key.split("#"); + HttpMethod routeMethod = HttpMethod.valueOf(keyArr[1]); + if (matchesPath(keyArr[0], cleanPath)) { + if (routeMethod == HttpMethod.ALL || HttpMethod.valueOf(httpMethod) == routeMethod) { + route = routes.get(key); + matchRoutes.add(route); + } + } + } + + // Priority matching principle + giveMatch(path, matchRoutes); + + return matchRoutes.size() > 0 ? matchRoutes.get(0) : null; + } + + /** + * Find all in before of the interceptor + * @param path request path + * @return return interceptor list + */ + public List getBefore(String path) { + + List befores = new ArrayList(); + String cleanPath = parsePath(path); + for (Route route : interceptorRoutes) { + if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.BEFORE){ + befores.add(route); + } + } + giveMatch(path, befores); + return befores; + } + + /** + * Find all in after of the interceptor + * @param path request path + * @return return interceptor list + */ + public List getAfter(String path) { + List afters = new ArrayList(); + String cleanPath = parsePath(path); + for (Route route : interceptorRoutes) { + if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.AFTER){ + afters.add(route); + } + } + giveMatch(path, afters); + return afters; + } + + /** + * Sort of path + * @param uri request uri + * @param routes route list + */ + private void giveMatch(final String uri, List routes) { + Collections.sort(routes, new Comparator() { + @Override + public int compare(Route o1, Route o2) { + if(o2.getPath().equals(uri)){ + return o2.getPath().indexOf(uri); + } + return -1; + } + }); + } + + /** + * Matching path + * + * @param routePath route path + * @param pathToMatch match path + * @return return match is success + */ + private boolean matchesPath(String routePath, String pathToMatch) { + routePath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); + return pathToMatch.matches("(?i)" + routePath); + } + + /** + * Parse Path + * + * @param path route path + * @return return parsed path + */ + private String parsePath(String path) { + path = Path.fixPath(path); + try { + URI uri = new URI(path); + return uri.getPath(); + } catch (URISyntaxException e) { + return null; + } + } + +} diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 88c5f43a1..0ae0f213d 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -1,183 +1,183 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.kit.Assert; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -/** - * Registration, management route - * - * @author biezhi - * @since 1.0 - */ -public class Routers { - - private Logger LOGGER = LoggerFactory.getLogger(Routers.class); - - private Map routes = null; - - private Map interceptors = null; - - private static final String METHOD_NAME = "handle"; - - public Routers() { - this.routes = new HashMap(); - this.interceptors = new HashMap(); - } - - public Map getRoutes() { - return routes; - } - - public Map getInterceptors() { - return interceptors; - } - - public void addRoute(Route route) { - String path = route.getPath(); - HttpMethod httpMethod = route.getHttpMethod(); - String key = path + "#" + httpMethod.toString(); - - // existent - if (null != this.routes.get(key)) { - LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); - } - - if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ - if (null != this.interceptors.get(key)) { - LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); - } - this.interceptors.put(key, route); - LOGGER.debug("Add Interceptor: {}", route); - } else { - this.routes.put(key, route); - LOGGER.debug("Add Route: {}", route); - } - } - - public void addRoutes(List routes) { - Assert.notNull(routes); - for(Route route : routes){ - this.addRoute(route); - } - } - - public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, String methodName) throws NoSuchMethodException { - Class handleType = handler.getClass(); - Method method = handleType.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, handler, RouteHandler.class, method); - } - - public void addRoute(HttpMethod httpMethod, String path, Object controller, Class controllerType, Method method) { - - Assert.notNull(httpMethod); - Assert.notBlank(path); - Assert.notNull(method); - - String key = path + "#" + httpMethod.toString(); - // existent - if (null != this.routes.get(key)) { - LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); - } - - Route route = new Route(httpMethod, path, controller, controllerType, method); - if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ - if (null != this.interceptors.get(key)) { - LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); - } - this.interceptors.put(key, route); - LOGGER.info("Add Interceptor: {}", route); - } else { - this.routes.put(key, route); - LOGGER.info("Add Route: {}", route); - } - - } - - public void route(String path, RouteHandler handler, HttpMethod httpMethod) { - try { - addRoute(httpMethod, path, handler, METHOD_NAME); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) { - for(String path : paths){ - route(path, handler, httpMethod); - } - } - - public void route(String path, Class clazz, String methodName) { - - Assert.notNull(path, "Route path not is null!"); - Assert.notNull(clazz, "Class Type not is null!"); - Assert.notNull(methodName, "Method name not is null"); - - HttpMethod httpMethod = HttpMethod.ALL; - if(methodName.indexOf(":") != -1){ - String[] methodArr = methodName.split(":"); - httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); - methodName = methodArr[1]; - } - try { - Method method = clazz.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, null, clazz, method); - } catch (NoSuchMethodException e) { - try { - Method method = clazz.getMethod(methodName, Response.class, Request.class); - addRoute(httpMethod, path, null, clazz, method); - } catch (NoSuchMethodException e1) { - e1.printStackTrace(); - } catch (SecurityException e1) { - e1.printStackTrace(); - } - } catch (SecurityException e) { - e.printStackTrace(); - } - } - - public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) { - try { - Assert.notNull(path, "Route path not is null!"); - Assert.notNull(clazz, "Class Type not is null!"); - Assert.notNull(methodName, "Method name not is null"); - Assert.notNull(httpMethod, "Request Method not is null"); - Method method = clazz.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, null, clazz, method); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - } - - public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { - addRoute(httpMethod, path, null, clazz, method); - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * Registration, management route + * + * @author biezhi + * @since 1.5 + */ +public class Routers { + + private Logger LOGGER = LoggerFactory.getLogger(Routers.class); + + private Map routes = null; + + private Map interceptors = null; + + private static final String METHOD_NAME = "handle"; + + public Routers() { + this.routes = new HashMap(); + this.interceptors = new HashMap(); + } + + public Map getRoutes() { + return routes; + } + + public Map getInterceptors() { + return interceptors; + } + + public void addRoute(Route route) { + String path = route.getPath(); + HttpMethod httpMethod = route.getHttpMethod(); + String key = path + "#" + httpMethod.toString(); + + // existent + if (null != this.routes.get(key)) { + LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); + } + + if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ + if (null != this.interceptors.get(key)) { + LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); + } + this.interceptors.put(key, route); + LOGGER.debug("Add Interceptor: {}", route); + } else { + this.routes.put(key, route); + LOGGER.debug("Add Route: {}", route); + } + } + + public void addRoutes(List routes) { + Assert.notNull(routes); + for(Route route : routes){ + this.addRoute(route); + } + } + + public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, String methodName) throws NoSuchMethodException { + Class handleType = handler.getClass(); + Method method = handleType.getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, handler, RouteHandler.class, method); + } + + public void addRoute(HttpMethod httpMethod, String path, Object controller, Class controllerType, Method method) { + + Assert.notNull(httpMethod); + Assert.notBlank(path); + Assert.notNull(method); + + String key = path + "#" + httpMethod.toString(); + // existent + if (null != this.routes.get(key)) { + LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); + } + + Route route = new Route(httpMethod, path, controller, controllerType, method); + if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ + if (null != this.interceptors.get(key)) { + LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); + } + this.interceptors.put(key, route); + LOGGER.info("Add Interceptor: {}", route); + } else { + this.routes.put(key, route); + LOGGER.info("Add Route: {}", route); + } + + } + + public void route(String path, RouteHandler handler, HttpMethod httpMethod) { + try { + addRoute(httpMethod, path, handler, METHOD_NAME); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) { + for(String path : paths){ + route(path, handler, httpMethod); + } + } + + public void route(String path, Class clazz, String methodName) { + + Assert.notNull(path, "Route path not is null!"); + Assert.notNull(clazz, "Class Type not is null!"); + Assert.notNull(methodName, "Method name not is null"); + + HttpMethod httpMethod = HttpMethod.ALL; + if(methodName.indexOf(":") != -1){ + String[] methodArr = methodName.split(":"); + httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); + methodName = methodArr[1]; + } + try { + Method method = clazz.getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, null, clazz, method); + } catch (NoSuchMethodException e) { + try { + Method method = clazz.getMethod(methodName, Response.class, Request.class); + addRoute(httpMethod, path, null, clazz, method); + } catch (NoSuchMethodException e1) { + e1.printStackTrace(); + } catch (SecurityException e1) { + e1.printStackTrace(); + } + } catch (SecurityException e) { + e.printStackTrace(); + } + } + + public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) { + try { + Assert.notNull(path, "Route path not is null!"); + Assert.notNull(clazz, "Class Type not is null!"); + Assert.notNull(methodName, "Method name not is null"); + Assert.notNull(httpMethod, "Request Method not is null"); + Method method = clazz.getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, null, clazz, method); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + } + + public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { + addRoute(httpMethod, path, null, clazz, method); + } + +} diff --git a/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java index 403d50151..9546ba74a 100644 --- a/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java @@ -1,222 +1,222 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route.loader; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.Method; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -import com.blade.kit.IOKit; -import com.blade.route.Route; -import com.blade.route.RouteException; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -/** - * Abstract loader implementation - * - * @author biezhi - * @since 1.0 - */ -public abstract class AbstractFileRouteLoader implements RouteLoader { - - private ControllerLoader controllerLoader = new ClassPathControllerLoader(); - - protected abstract InputStream getInputStream() throws Exception; - - @Override - public List load() throws ParseException, RouteException { - InputStream inputStream = null; - try { - inputStream = getInputStream(); - } catch (Exception e) { - throw new RouteException("Loading the route config file error: " + e.getMessage(), e); - } - try { - return load(inputStream); - } catch (IOException e) { - throw new RouteException("Loading the route config file error: " + e.getMessage(), e); - } - } - - /** - * Load Route - * - * @param inputStream route inputstream - * @return return route list - * @throws ParseException parse exception - * @throws IOException io exception - */ - private List load(InputStream inputStream) throws ParseException, IOException { - int line = 0; - List routes = new ArrayList(); - BufferedReader in = null; - try { - in = new BufferedReader(new InputStreamReader(inputStream)); - String input; - while ( (input = in.readLine()) != null ) { - line++; - - input = input.trim(); - - if (!input.equals("") && !input.startsWith(".")) { - Route route = parse(input, line); - routes.add(route); - } - } - } finally { - IOKit.closeQuietly(in); - } - return routes; - } - - private Route parse(String input, int line) throws ParseException { - StringTokenizer st = new StringTokenizer(input, " \t"); - if (st.countTokens() != 3) { - throw new ParseException("Unrecognized format", line); - } - - // Verify HTTP request - String httpMethod = validateHttpMethod( st.nextToken().trim(), line ); - - String path = validatePath( st.nextToken().trim(), line ); - String controllerAndMethod = validateControllerAndMethod( st.nextToken().trim(), line ); - - int hashPos = controllerAndMethod.indexOf("."); - String controllerName = controllerAndMethod.substring(0, hashPos); - - // Acquisition controller method - String controllerMethod = controllerAndMethod.substring(hashPos + 1); - - return buildRoute(httpMethod, path, controllerName, controllerMethod); - } - - private String validateHttpMethod(String httpMethod, int line) throws ParseException { - if (!httpMethod.equalsIgnoreCase("GET") && - !httpMethod.equalsIgnoreCase("POST") && - !httpMethod.equalsIgnoreCase("PUT") && - !httpMethod.equalsIgnoreCase("DELETE")) { - throw new ParseException("Unrecognized HTTP method: " + httpMethod, line); - } - return httpMethod; - } - - private String validatePath(String path, int line) throws ParseException { - if (!path.startsWith("/")) { - throw new ParseException("Path must start with '/'", line); - } - - boolean openedKey = false; - for (int i=0; i < path.length(); i++) { - - boolean validChar = isValidCharForPath(path.charAt(i), openedKey); - if (!validChar) { - throw new ParseException(path, i); - } - - if (path.charAt(i) == '{') { - openedKey = true; - } - - if (path.charAt(i) == '}') { - openedKey = false; - } - } - return path; - } - - private boolean isValidCharForPath(char c, boolean openedKey) { - char[] invalidChars = { '?', '.', ' ' }; - for (char invalidChar : invalidChars) { - if (c == invalidChar) { - return false; - } - } - - if (openedKey) { - char[] moreInvalidChars = { '/', '{' }; - for (char invalidChar : moreInvalidChars) { - if (c == invalidChar) { - return false; - } - } - } - - return true; - } - - /** - * Verification controller method - * - * @param beanAndMethod controller and method, using. - * @param line line number - * @return return a string that is verified after the verification. - * @throws ParseException - */ - private String validateControllerAndMethod(String beanAndMethod, int line) throws ParseException { - int hashPos = beanAndMethod.indexOf("."); - if (hashPos == -1) { - throw new ParseException("Unrecognized format for '" + beanAndMethod + "'", line); - } - - return beanAndMethod; - } - - /** - * Construct a routing object - * - * @param httpMethod request httpMethod - * @param path route path - * @param controllerName controller name - * @param methodName method name - * @return return route object - * @throws RouteException - */ - private Route buildRoute(String httpMethod, String path, String controllerName, String methodName) throws RouteException { - Object controller = controllerLoader.load(controllerName); - Class controllerType = controller.getClass(); - Method method = getMethod(controllerType, methodName); - return new Route(HttpMethod.valueOf(httpMethod.toUpperCase()), path, controller, controllerType, method); - } - - private Method getMethod(Class controllerType, String methodName) throws RouteException { - try { - return controllerType.getMethod(methodName, Request.class, Response.class); - } catch (Exception e) { - throw new RouteException(e); - } - } - - public void setBasePackage(String basePackage) { - this.controllerLoader = new ClassPathControllerLoader(basePackage); - } - - public ControllerLoader getControllerLoader() { - return controllerLoader; - } - - public void setControllerLoader(ControllerLoader controllerLoader) { - this.controllerLoader = controllerLoader; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route.loader; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Method; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import com.blade.kit.IOKit; +import com.blade.route.Route; +import com.blade.route.RouteException; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * Abstract loader implementation + * + * @author biezhi + * @since 1.5 + */ +public abstract class AbstractFileRouteLoader implements RouteLoader { + + private ControllerLoader controllerLoader = new ClassPathControllerLoader(); + + protected abstract InputStream getInputStream() throws Exception; + + @Override + public List load() throws ParseException, RouteException { + InputStream inputStream = null; + try { + inputStream = getInputStream(); + } catch (Exception e) { + throw new RouteException("Loading the route config file error: " + e.getMessage(), e); + } + try { + return load(inputStream); + } catch (IOException e) { + throw new RouteException("Loading the route config file error: " + e.getMessage(), e); + } + } + + /** + * Load Route + * + * @param inputStream route inputstream + * @return return route list + * @throws ParseException parse exception + * @throws IOException io exception + */ + private List load(InputStream inputStream) throws ParseException, IOException { + int line = 0; + List routes = new ArrayList(); + BufferedReader in = null; + try { + in = new BufferedReader(new InputStreamReader(inputStream)); + String input; + while ( (input = in.readLine()) != null ) { + line++; + + input = input.trim(); + + if (!input.equals("") && !input.startsWith(".")) { + Route route = parse(input, line); + routes.add(route); + } + } + } finally { + IOKit.closeQuietly(in); + } + return routes; + } + + private Route parse(String input, int line) throws ParseException { + StringTokenizer st = new StringTokenizer(input, " \t"); + if (st.countTokens() != 3) { + throw new ParseException("Unrecognized format", line); + } + + // Verify HTTP request + String httpMethod = validateHttpMethod( st.nextToken().trim(), line ); + + String path = validatePath( st.nextToken().trim(), line ); + String controllerAndMethod = validateControllerAndMethod( st.nextToken().trim(), line ); + + int hashPos = controllerAndMethod.indexOf("."); + String controllerName = controllerAndMethod.substring(0, hashPos); + + // Acquisition controller method + String controllerMethod = controllerAndMethod.substring(hashPos + 1); + + return buildRoute(httpMethod, path, controllerName, controllerMethod); + } + + private String validateHttpMethod(String httpMethod, int line) throws ParseException { + if (!httpMethod.equalsIgnoreCase("GET") && + !httpMethod.equalsIgnoreCase("POST") && + !httpMethod.equalsIgnoreCase("PUT") && + !httpMethod.equalsIgnoreCase("DELETE")) { + throw new ParseException("Unrecognized HTTP method: " + httpMethod, line); + } + return httpMethod; + } + + private String validatePath(String path, int line) throws ParseException { + if (!path.startsWith("/")) { + throw new ParseException("Path must start with '/'", line); + } + + boolean openedKey = false; + for (int i=0; i < path.length(); i++) { + + boolean validChar = isValidCharForPath(path.charAt(i), openedKey); + if (!validChar) { + throw new ParseException(path, i); + } + + if (path.charAt(i) == '{') { + openedKey = true; + } + + if (path.charAt(i) == '}') { + openedKey = false; + } + } + return path; + } + + private boolean isValidCharForPath(char c, boolean openedKey) { + char[] invalidChars = { '?', '.', ' ' }; + for (char invalidChar : invalidChars) { + if (c == invalidChar) { + return false; + } + } + + if (openedKey) { + char[] moreInvalidChars = { '/', '{' }; + for (char invalidChar : moreInvalidChars) { + if (c == invalidChar) { + return false; + } + } + } + + return true; + } + + /** + * Verification controller method + * + * @param beanAndMethod controller and method, using. + * @param line line number + * @return return a string that is verified after the verification. + * @throws ParseException + */ + private String validateControllerAndMethod(String beanAndMethod, int line) throws ParseException { + int hashPos = beanAndMethod.indexOf("."); + if (hashPos == -1) { + throw new ParseException("Unrecognized format for '" + beanAndMethod + "'", line); + } + + return beanAndMethod; + } + + /** + * Construct a routing object + * + * @param httpMethod request httpMethod + * @param path route path + * @param controllerName controller name + * @param methodName method name + * @return return route object + * @throws RouteException + */ + private Route buildRoute(String httpMethod, String path, String controllerName, String methodName) throws RouteException { + Object controller = controllerLoader.load(controllerName); + Class controllerType = controller.getClass(); + Method method = getMethod(controllerType, methodName); + return new Route(HttpMethod.valueOf(httpMethod.toUpperCase()), path, controller, controllerType, method); + } + + private Method getMethod(Class controllerType, String methodName) throws RouteException { + try { + return controllerType.getMethod(methodName, Request.class, Response.class); + } catch (Exception e) { + throw new RouteException(e); + } + } + + public void setBasePackage(String basePackage) { + this.controllerLoader = new ClassPathControllerLoader(basePackage); + } + + public ControllerLoader getControllerLoader() { + return controllerLoader; + } + + public void setControllerLoader(ControllerLoader controllerLoader) { + this.controllerLoader = controllerLoader; + } + +} diff --git a/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java index 954206102..e474fc289 100644 --- a/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java @@ -1,85 +1,85 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route.loader; - -import com.blade.Blade; -import com.blade.ioc.Ioc; -import com.blade.route.RouteException; - -/** - * ClassPath controller of loader - * - * @author biezhi - * @since 1.0 - */ -public class ClassPathControllerLoader implements ControllerLoader { - - private String basePackage; - - private ClassLoader classLoader = ClassPathControllerLoader.class.getClassLoader(); - - private Ioc ioc = Blade.$().ioc(); - - public ClassPathControllerLoader() { - this(""); - } - - public ClassPathControllerLoader(String basePackage) { - this.basePackage = basePackage; - - if (this.basePackage != null && !"".equals(this.basePackage)) { - if (!this.basePackage.endsWith(".")) { - this.basePackage += "."; - } - } - } - - @Override - public Object load(String controllerName) throws RouteException { - String className = basePackage + controllerName; - - try { - // Load controller instance - Class controllerClass = classLoader.loadClass(className); - - Object controller = ioc.getBean(controllerClass); - if(null == controller){ - ioc.addBean(controllerClass); - controller = ioc.getBean(controllerClass); - } - return controller; - } catch (Exception e) { - throw new RouteException(e); - } - } - - public String getBasePackage() { - return basePackage; - } - - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - } - - public ClassLoader getClassLoader() { - return classLoader; - } - - public void setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route.loader; + +import com.blade.Blade; +import com.blade.ioc.Ioc; +import com.blade.route.RouteException; + +/** + * ClassPath controller of loader + * + * @author biezhi + * @since 1.5 + */ +public class ClassPathControllerLoader implements ControllerLoader { + + private String basePackage; + + private ClassLoader classLoader = ClassPathControllerLoader.class.getClassLoader(); + + private Ioc ioc = Blade.$().ioc(); + + public ClassPathControllerLoader() { + this(""); + } + + public ClassPathControllerLoader(String basePackage) { + this.basePackage = basePackage; + + if (this.basePackage != null && !"".equals(this.basePackage)) { + if (!this.basePackage.endsWith(".")) { + this.basePackage += "."; + } + } + } + + @Override + public Object load(String controllerName) throws RouteException { + String className = basePackage + controllerName; + + try { + // Load controller instance + Class controllerClass = classLoader.loadClass(className); + + Object controller = ioc.getBean(controllerClass); + if(null == controller){ + ioc.addBean(controllerClass); + controller = ioc.getBean(controllerClass); + } + return controller; + } catch (Exception e) { + throw new RouteException(e); + } + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + +} diff --git a/blade-core/src/main/java/com/blade/route/loader/ClassPathRouteLoader.java b/blade-core/src/main/java/com/blade/route/loader/ClassPathRouteLoader.java index 9a1478016..6fce418e0 100644 --- a/blade-core/src/main/java/com/blade/route/loader/ClassPathRouteLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/ClassPathRouteLoader.java @@ -23,7 +23,7 @@ * Route loader based on ClassPath * * @author biezhi - * @since 1.0 + * @since 1.5 */ public class ClassPathRouteLoader extends AbstractFileRouteLoader { diff --git a/blade-core/src/main/java/com/blade/route/loader/ControllerLoader.java b/blade-core/src/main/java/com/blade/route/loader/ControllerLoader.java index 93c6f3c61..dc7fab22b 100644 --- a/blade-core/src/main/java/com/blade/route/loader/ControllerLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/ControllerLoader.java @@ -21,7 +21,7 @@ * Controller loading interface * * @author biezhi - * @since 1.0 + * @since 1.5 */ public interface ControllerLoader { diff --git a/blade-core/src/main/java/com/blade/route/loader/FileSystemRouteLoader.java b/blade-core/src/main/java/com/blade/route/loader/FileSystemRouteLoader.java index c97a1acd0..0a1061994 100644 --- a/blade-core/src/main/java/com/blade/route/loader/FileSystemRouteLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/FileSystemRouteLoader.java @@ -23,7 +23,7 @@ * The file system based on Routing * * @author biezhi - * @since 1.0 + * @since 1.5 */ public class FileSystemRouteLoader extends AbstractFileRouteLoader { diff --git a/blade-core/src/main/java/com/blade/route/loader/RouteLoader.java b/blade-core/src/main/java/com/blade/route/loader/RouteLoader.java index d518de82c..1134189ff 100644 --- a/blade-core/src/main/java/com/blade/route/loader/RouteLoader.java +++ b/blade-core/src/main/java/com/blade/route/loader/RouteLoader.java @@ -25,7 +25,7 @@ * Route loader * * @author biezhi - * @since 1.0 + * @since 1.5 */ public interface RouteLoader { diff --git a/blade-core/src/main/java/com/blade/view/ModelAndView.java b/blade-core/src/main/java/com/blade/view/ModelAndView.java index 27a1e122d..664f68f98 100644 --- a/blade-core/src/main/java/com/blade/view/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/view/ModelAndView.java @@ -1,123 +1,123 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view; - -import java.util.HashMap; -import java.util.Map; - -import com.blade.kit.CollectionKit; - -/** - * ModelAndView, Using templates and data - * - * @author biezhi - * @since 1.0 - */ -public class ModelAndView { - - /** - * Data object, the object is placed in the attribute httprequest - */ - private Map model = new HashMap(5); - - /** - * View Page - */ - private String view; - - public ModelAndView() { - } - - /** - * Create an empty view - * - * @param view view page - */ - public ModelAndView(String view) { - super(); - this.model = CollectionKit.newHashMap(); - this.view = view; - } - - /** - * Create a model view object with data - * - * @param model model data - * @param view view page - */ - public ModelAndView(Map model, String view) { - super(); - this.model = model; - this.view = view; - } - - /** - * Add data to model - * - * @param key key - * @param value value - */ - public void add(String key, Object value){ - this.model.put(key, value); - } - - /** - * Remove model data - * - * @param key key - */ - public void remove(String key){ - this.model.remove(key); - } - - /** - * - * @return Return view page - */ - public String getView() { - return view; - } - - /** - * Setting view page - * - * @param view view page - */ - public void setView(String view) { - this.view = view; - } - - /** - * @return Return model map - */ - public Map getModel() { - return model; - } - - /** - * Setting model - * - * @param model Storage data map - */ - public void setModel(Map model) { - this.model = model; - } - - @Override - public String toString() { - return "view = " + view + ", model = " + model; - } +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view; + +import java.util.HashMap; +import java.util.Map; + +import com.blade.kit.CollectionKit; + +/** + * ModelAndView, Using templates and data + * + * @author biezhi + * @since 1.5 + */ +public class ModelAndView { + + /** + * Data object, the object is placed in the attribute httprequest + */ + private Map model = new HashMap(5); + + /** + * View Page + */ + private String view; + + public ModelAndView() { + } + + /** + * Create an empty view + * + * @param view view page + */ + public ModelAndView(String view) { + super(); + this.model = CollectionKit.newHashMap(); + this.view = view; + } + + /** + * Create a model view object with data + * + * @param model model data + * @param view view page + */ + public ModelAndView(Map model, String view) { + super(); + this.model = model; + this.view = view; + } + + /** + * Add data to model + * + * @param key key + * @param value value + */ + public void add(String key, Object value){ + this.model.put(key, value); + } + + /** + * Remove model data + * + * @param key key + */ + public void remove(String key){ + this.model.remove(key); + } + + /** + * + * @return Return view page + */ + public String getView() { + return view; + } + + /** + * Setting view page + * + * @param view view page + */ + public void setView(String view) { + this.view = view; + } + + /** + * @return Return model map + */ + public Map getModel() { + return model; + } + + /** + * Setting model + * + * @param model Storage data map + */ + public void setModel(Map model) { + this.model = model; + } + + @Override + public String toString() { + return "view = " + view + ", model = " + model; + } } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java index d5461e060..468ca92b2 100644 --- a/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view.handle; import java.lang.annotation.Annotation; diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 5a68bae69..49e116d0a 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -1,92 +1,107 @@ -package com.blade.view.handle; - -import java.lang.reflect.Method; - -import com.blade.annotation.JSON; -import com.blade.annotation.RestController; -import com.blade.ioc.Ioc; -import com.blade.kit.reflect.ReflectKit; -import com.blade.route.Route; -import com.blade.view.ModelAndView; -import com.blade.view.parser.JSONView; -import com.blade.web.DispatchKit; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -public class RouteViewHandler { - - private Ioc ioc; - - public RouteViewHandler(Ioc ioc) { - this.ioc = ioc; - } - - public void handle(Request request, Response response, Route route) throws Exception { - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - - int len = actionMethod.getParameterTypes().length; - Object returnParam = null; - if (len > 0) { - Object[] args = MethodArgument.getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if (null != returnParam) { - Class returnType = returnParam.getClass(); - RestController restController = target.getClass().getAnnotation(RestController.class); - JSON json = actionMethod.getAnnotation(JSON.class); - if(null != restController || null != json){ - response.json(JSONView.toJSONString(returnParam)); - } else{ - if (returnType == String.class) { - response.render(returnParam.toString()); - } else if (returnType == ModelAndView.class) { - ModelAndView modelAndView = (ModelAndView) returnParam; - response.render(modelAndView); - } - } - } - } - - public boolean intercept(Request request, Response response, Route route) { - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - - if (null == target) { - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - - // execute - int len = actionMethod.getParameterTypes().length; - actionMethod.setAccessible(true); - try { - Object returnParam = null; - if (len > 0) { - Object[] args = MethodArgument.getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if (null != returnParam) { - Class returnType = returnParam.getClass(); - if (returnType == Boolean.class || returnType == boolean.class) { - return (Boolean) returnParam; - } - } - - return true; - - } catch (Exception e) { - request.abort(); - DispatchKit.printError(e, 500, response); - } - return false; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view.handle; + +import java.lang.reflect.Method; + +import com.blade.annotation.JSON; +import com.blade.annotation.RestController; +import com.blade.ioc.Ioc; +import com.blade.kit.reflect.ReflectKit; +import com.blade.route.Route; +import com.blade.view.ModelAndView; +import com.blade.view.parser.JSONView; +import com.blade.web.DispatchKit; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +public class RouteViewHandler { + + private Ioc ioc; + + public RouteViewHandler(Ioc ioc) { + this.ioc = ioc; + } + + public void handle(Request request, Response response, Route route) throws Exception { + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + int len = actionMethod.getParameterTypes().length; + Object returnParam = null; + if (len > 0) { + Object[] args = MethodArgument.getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if (null != returnParam) { + Class returnType = returnParam.getClass(); + RestController restController = target.getClass().getAnnotation(RestController.class); + JSON json = actionMethod.getAnnotation(JSON.class); + if(null != restController || null != json){ + response.json(JSONView.toJSONString(returnParam)); + } else{ + if (returnType == String.class) { + response.render(returnParam.toString()); + } else if (returnType == ModelAndView.class) { + ModelAndView modelAndView = (ModelAndView) returnParam; + response.render(modelAndView); + } + } + } + } + + public boolean intercept(Request request, Response response, Route route) { + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + if (null == target) { + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + + // execute + int len = actionMethod.getParameterTypes().length; + actionMethod.setAccessible(true); + try { + Object returnParam = null; + if (len > 0) { + Object[] args = MethodArgument.getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if (null != returnParam) { + Class returnType = returnParam.getClass(); + if (returnType == Boolean.class || returnType == boolean.class) { + return (Boolean) returnParam; + } + } + + return true; + + } catch (Exception e) { + request.abort(); + DispatchKit.printError(e, 500, response); + } + return false; + } + +} diff --git a/blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java b/blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java index f753b4a0c..f9e9942fe 100644 --- a/blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java +++ b/blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java @@ -1,12 +1,33 @@ -package com.blade.view.parser; - -import com.blade.kit.json.JSONKit; - -public class DefaultJSONParser implements JSONParser { - - @Override - public String toJSONSting(Object object) { - return JSONKit.toJSONString(object); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view.parser; + +import com.blade.kit.json.JSONKit; + +/** + * Default json parser implment + * + * @author biezhi + * @since 1.6.6 + */ +public class DefaultJSONParser implements JSONParser { + + @Override + public String toJSONSting(Object object) { + return JSONKit.toJSONString(object); + } + +} diff --git a/blade-core/src/main/java/com/blade/view/parser/JSONParser.java b/blade-core/src/main/java/com/blade/view/parser/JSONParser.java index d54881e21..0e92935cd 100644 --- a/blade-core/src/main/java/com/blade/view/parser/JSONParser.java +++ b/blade-core/src/main/java/com/blade/view/parser/JSONParser.java @@ -1,7 +1,28 @@ -package com.blade.view.parser; - -public interface JSONParser { - - String toJSONSting(Object object); - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view.parser; + +/** + * Route render json parser + * + * @author biezhi + * @since 1.6.6 + */ +public interface JSONParser { + + String toJSONSting(Object object); + +} diff --git a/blade-core/src/main/java/com/blade/view/parser/JSONView.java b/blade-core/src/main/java/com/blade/view/parser/JSONView.java index 9ec80757a..b4518818a 100644 --- a/blade-core/src/main/java/com/blade/view/parser/JSONView.java +++ b/blade-core/src/main/java/com/blade/view/parser/JSONView.java @@ -1,18 +1,39 @@ -package com.blade.view.parser; - -public final class JSONView { - - private JSONView() { - } - - private static JSONParser JSON_PARSER = new DefaultJSONParser(); - - public static String toJSONString(Object object){ - return JSON_PARSER.toJSONSting(object); - } - - public static void setJSONParser(JSONParser jsonParser){ - JSON_PARSER = jsonParser; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view.parser; + +/** + * Custom JSON Parser, eg:FastJSON + * + * @author biezhi + * @since 1.6.6 + */ +public final class JSONView { + + private JSONView() { + } + + private static JSONParser JSON_PARSER = new DefaultJSONParser(); + + public static String toJSONString(Object object){ + return JSON_PARSER.toJSONSting(object); + } + + public static void setJSONParser(JSONParser jsonParser){ + JSON_PARSER = jsonParser; + } + +} diff --git a/blade-core/src/main/java/com/blade/view/template/DefaultEngine.java b/blade-core/src/main/java/com/blade/view/template/DefaultEngine.java index f79d85a8d..826b56f7d 100644 --- a/blade-core/src/main/java/com/blade/view/template/DefaultEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/DefaultEngine.java @@ -1,78 +1,78 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; - -import java.io.IOException; -import java.io.Writer; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.context.ApplicationWebContext; -import com.blade.view.ModelAndView; - - -/** - * JSP Render, Default Render - * - * @author biezhi - * @since 1.0 - */ -public final class DefaultEngine implements TemplateEngine { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultEngine.class); - - private String viewPath = "/WEB-INF/"; - - public DefaultEngine() { - } - - public DefaultEngine(String viewPath) { - this.viewPath = viewPath; - } - - @Override - public void render(ModelAndView modelAndView, Writer writer) { - HttpServletRequest servletRequest = ApplicationWebContext.request().raw(); - HttpServletResponse servletResponse = ApplicationWebContext.response().raw(); - - try { - Map model = modelAndView.getModel(); - String realPath = viewPath + modelAndView.getView(); - - if (null != model && !model.isEmpty()) { - Set keys = model.keySet(); - for (String key : keys) { - servletRequest.setAttribute(key, model.get(key)); - } - } - servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); - } catch (ServletException e) { - e.printStackTrace(); - LOGGER.error("", e); - } catch (IOException e) { - e.printStackTrace(); - LOGGER.error("", e); - } - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.ApplicationWebContext; +import com.blade.view.ModelAndView; + + +/** + * JSP Render, Default Render + * + * @author biezhi + * @since 1.6.6 + */ +public final class DefaultEngine implements TemplateEngine { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultEngine.class); + + private String viewPath = "/"; + + public DefaultEngine() { + } + + public DefaultEngine(String viewPath) { + this.viewPath = viewPath; + } + + @Override + public void render(ModelAndView modelAndView, Writer writer) { + HttpServletRequest servletRequest = ApplicationWebContext.request().raw(); + HttpServletResponse servletResponse = ApplicationWebContext.response().raw(); + + try { + Map model = modelAndView.getModel(); + String realPath = viewPath + modelAndView.getView(); + + if (null != model && !model.isEmpty()) { + Set keys = model.keySet(); + for (String key : keys) { + servletRequest.setAttribute(key, model.get(key)); + } + } + servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); + } catch (ServletException e) { + e.printStackTrace(); + LOGGER.error("", e); + } catch (IOException e) { + e.printStackTrace(); + LOGGER.error("", e); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/view/template/JspEngine.java index 259c9ebe9..3832dbc4d 100644 --- a/blade-core/src/main/java/com/blade/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/JspEngine.java @@ -1,78 +1,78 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; - -import java.io.IOException; -import java.io.Writer; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.context.ApplicationWebContext; -import com.blade.view.ModelAndView; - - -/** - * JSP Render, Default Render - * - * @author biezhi - * @since 1.0 - */ -public final class JspEngine implements TemplateEngine { - - private static final Logger LOGGER = LoggerFactory.getLogger(JspEngine.class); - - private String viewPath = "/WEB-INF/"; - - public JspEngine() { - } - - public JspEngine(String viewPath) { - this.viewPath = viewPath; - } - - @Override - public void render(ModelAndView modelAndView, Writer writer) { - HttpServletRequest servletRequest = ApplicationWebContext.request().raw(); - HttpServletResponse servletResponse = ApplicationWebContext.response().raw(); - - try { - Map model = modelAndView.getModel(); - String realPath = viewPath + modelAndView.getView(); - - if (null != model && !model.isEmpty()) { - Set keys = model.keySet(); - for (String key : keys) { - servletRequest.setAttribute(key, model.get(key)); - } - } - servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); - } catch (ServletException e) { - e.printStackTrace(); - LOGGER.error("", e); - } catch (IOException e) { - e.printStackTrace(); - LOGGER.error("", e); - } - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.ApplicationWebContext; +import com.blade.view.ModelAndView; + + +/** + * JSP Render, Default Render + * + * @author biezhi + * @since 1.5 + */ +public final class JspEngine implements TemplateEngine { + + private static final Logger LOGGER = LoggerFactory.getLogger(JspEngine.class); + + private String viewPath = "/WEB-INF/"; + + public JspEngine() { + } + + public JspEngine(String viewPath) { + this.viewPath = viewPath; + } + + @Override + public void render(ModelAndView modelAndView, Writer writer) { + HttpServletRequest servletRequest = ApplicationWebContext.request().raw(); + HttpServletResponse servletResponse = ApplicationWebContext.response().raw(); + + try { + Map model = modelAndView.getModel(); + String realPath = viewPath + modelAndView.getView(); + + if (null != model && !model.isEmpty()) { + Set keys = model.keySet(); + for (String key : keys) { + servletRequest.setAttribute(key, model.get(key)); + } + } + servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); + } catch (ServletException e) { + e.printStackTrace(); + LOGGER.error("", e); + } catch (IOException e) { + e.printStackTrace(); + LOGGER.error("", e); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java b/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java index 465fd438e..7b8a03c66 100644 --- a/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java @@ -1,32 +1,32 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; - -import java.io.Writer; - -import com.blade.view.ModelAndView; - -/** - * TemplateEngine Interface, For view layer to display data - * - * @author biezhi - * @since 1.0 - */ -public interface TemplateEngine { - - public void render(ModelAndView modelAndView, Writer writer) throws TemplateException; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; + +import java.io.Writer; + +import com.blade.view.ModelAndView; + +/** + * TemplateEngine Interface, For view layer to display data + * + * @author biezhi + * @since 1.5 + */ +public interface TemplateEngine { + + void render(ModelAndView modelAndView, Writer writer) throws TemplateException; + +} diff --git a/blade-core/src/main/java/com/blade/view/template/TemplateException.java b/blade-core/src/main/java/com/blade/view/template/TemplateException.java index 517d6f0b0..d9f784289 100644 --- a/blade-core/src/main/java/com/blade/view/template/TemplateException.java +++ b/blade-core/src/main/java/com/blade/view/template/TemplateException.java @@ -1,44 +1,44 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; - -/** - * TemplateException - * - * @author biezhi - * @since 1.0 - */ -public class TemplateException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - public TemplateException() { - super(); - } - - public TemplateException(String message, Throwable cause) { - super(message, cause); - } - - public TemplateException(String message) { - super(message); - } - - public TemplateException(Throwable cause) { - super(cause); - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; + +/** + * TemplateException + * + * @author biezhi + * @since 1.5 + */ +public class TemplateException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public TemplateException() { + super(); + } + + public TemplateException(String message, Throwable cause) { + super(message, cause); + } + + public TemplateException(String message) { + super(message); + } + + public TemplateException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java index 4851344d7..520b85423 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -1,204 +1,204 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; - -import java.io.IOException; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.context.ApplicationWebContext; -import com.blade.exception.BladeException; -import com.blade.ioc.Ioc; -import com.blade.kit.StringKit; -import com.blade.route.Route; -import com.blade.route.RouteHandler; -import com.blade.route.RouteMatcher; -import com.blade.route.Routers; -import com.blade.view.ModelAndView; -import com.blade.view.handle.RouteViewHandler; -import com.blade.view.template.TemplateException; -import com.blade.web.http.HttpStatus; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.wrapper.ServletRequest; -import com.blade.web.http.wrapper.ServletResponse; - -/** - * Synchronous request processor - * - * @author biezhi - * @since 1.0 - */ -public class DispatcherHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); - - private Ioc ioc; - - private Blade blade; - - private ServletContext servletContext; - - private RouteMatcher routeMatcher; - - private StaticFileFilter staticFileFilter; - - private RouteViewHandler routeViewHandler; - - public DispatcherHandler(ServletContext servletContext, Routers routers) { - this.servletContext = servletContext; - this.blade = Blade.$(); - this.ioc = blade.ioc(); - this.routeMatcher = new RouteMatcher(routers); - this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); - this.routeViewHandler = new RouteViewHandler(this.ioc); - } - - public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ - - // http method, GET/POST ... - String method = httpRequest.getMethod(); - - // reuqest uri - String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - - // Create Response - Response response = new ServletResponse(httpResponse, blade.templateEngine());; - - // If it is static, the resource is handed over to the filter - if(staticFileFilter.isStatic(uri)){ - LOGGER.debug("Request : {}\t{}", method, uri); - DispatchKit.printStatic(uri, httpRequest, response); - return; - } - - LOGGER.info("Request : {}\t{}", method, uri); - - try { - - Request request = new ServletRequest(httpRequest); - ApplicationWebContext.init(servletContext, request, response); - Route route = routeMatcher.getRoute(method, uri); - if (null != route) { - request.setRoute(route); - - // before inteceptor - List befores = routeMatcher.getBefore(uri); - boolean result = invokeInterceptor(request, response, befores); - if(result){ - // execute - this.routeHandle(request, response, route); - if(!request.isAbort()){ - // after inteceptor - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - } - } - } else { - // Not found - render404(response, uri); - } - return; - } catch (TemplateException e) { - LOGGER.error("Template error", e); - DispatchKit.printError(e, 500, response); - } catch (BladeException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - }catch (Exception e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } - return; - } - - /** - * 404 view render - * - * @param response response object - * @param uri 404 uri - * @throws IOException - * @throws TemplateException - */ - private void render404(Response response, String uri) throws Exception { - String view404 = blade.view404(); - if(StringKit.isNotBlank(view404)){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", uri); - response.render( modelAndView ); - } else { - response.status(HttpStatus.NOT_FOUND); - response.html(String.format(Const.VIEW_NOTFOUND, uri)); - } - } - - /** - * Methods to perform the interceptor - * - * @param request request object - * @param response response object - * @param interceptors execute the interceptor list - * @return Return execute is ok - */ - private boolean invokeInterceptor(Request request, Response response, List interceptors) { - for(Route route : interceptors){ - boolean flag = routeViewHandler.intercept(request, response, route); - if(!flag){ - return false; - } - } - return true; - } - - /** - * Actual routing method execution - * - * @param request request object - * @param response response object - * @param route route object - */ - private void routeHandle(Request request, Response response, Route route) throws Exception{ - Object target = route.getTarget(); - if(null == target){ - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - request.initPathParams(route.getPath()); - - // Init context - ApplicationWebContext.init(servletContext, request, response); - if(route.getTargetType() == RouteHandler.class){ - RouteHandler routeHandler = (RouteHandler) target; - routeHandler.handle(request, response); - } else { - routeViewHandler.handle(request, response, route); - } - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.context.ApplicationWebContext; +import com.blade.exception.BladeException; +import com.blade.ioc.Ioc; +import com.blade.kit.StringKit; +import com.blade.route.Route; +import com.blade.route.RouteHandler; +import com.blade.route.RouteMatcher; +import com.blade.route.Routers; +import com.blade.view.ModelAndView; +import com.blade.view.handle.RouteViewHandler; +import com.blade.view.template.TemplateException; +import com.blade.web.http.HttpStatus; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.ServletRequest; +import com.blade.web.http.wrapper.ServletResponse; + +/** + * Synchronous request processor + * + * @author biezhi + * @since 1.5 + */ +public class DispatcherHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); + + private Ioc ioc; + + private Blade blade; + + private ServletContext servletContext; + + private RouteMatcher routeMatcher; + + private StaticFileFilter staticFileFilter; + + private RouteViewHandler routeViewHandler; + + public DispatcherHandler(ServletContext servletContext, Routers routers) { + this.servletContext = servletContext; + this.blade = Blade.$(); + this.ioc = blade.ioc(); + this.routeMatcher = new RouteMatcher(routers); + this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); + this.routeViewHandler = new RouteViewHandler(this.ioc); + } + + public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ + + // http method, GET/POST ... + String method = httpRequest.getMethod(); + + // reuqest uri + String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); + + // Create Response + Response response = new ServletResponse(httpResponse, blade.templateEngine());; + + // If it is static, the resource is handed over to the filter + if(staticFileFilter.isStatic(uri)){ + LOGGER.debug("Request : {}\t{}", method, uri); + DispatchKit.printStatic(uri, httpRequest, response); + return; + } + + LOGGER.info("Request : {}\t{}", method, uri); + + try { + + Request request = new ServletRequest(httpRequest); + ApplicationWebContext.init(servletContext, request, response); + Route route = routeMatcher.getRoute(method, uri); + if (null != route) { + request.setRoute(route); + + // before inteceptor + List befores = routeMatcher.getBefore(uri); + boolean result = invokeInterceptor(request, response, befores); + if(result){ + // execute + this.routeHandle(request, response, route); + if(!request.isAbort()){ + // after inteceptor + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + } + } + } else { + // Not found + render404(response, uri); + } + return; + } catch (TemplateException e) { + LOGGER.error("Template error", e); + DispatchKit.printError(e, 500, response); + } catch (BladeException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + }catch (Exception e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } + return; + } + + /** + * 404 view render + * + * @param response response object + * @param uri 404 uri + * @throws IOException + * @throws TemplateException + */ + private void render404(Response response, String uri) throws Exception { + String view404 = blade.view404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(Const.VIEW_NOTFOUND, uri)); + } + } + + /** + * Methods to perform the interceptor + * + * @param request request object + * @param response response object + * @param interceptors execute the interceptor list + * @return Return execute is ok + */ + private boolean invokeInterceptor(Request request, Response response, List interceptors) { + for(Route route : interceptors){ + boolean flag = routeViewHandler.intercept(request, response, route); + if(!flag){ + return false; + } + } + return true; + } + + /** + * Actual routing method execution + * + * @param request request object + * @param response response object + * @param route route object + */ + private void routeHandle(Request request, Response response, Route route) throws Exception{ + Object target = route.getTarget(); + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + request.initPathParams(route.getPath()); + + // Init context + ApplicationWebContext.init(servletContext, request, response); + if(route.getTargetType() == RouteHandler.class){ + RouteHandler routeHandler = (RouteHandler) target; + routeHandler.handle(request, response); + } else { + routeViewHandler.handle(request, response, route); + } + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 36aba1b42..9a5fe21a1 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -39,7 +39,7 @@ * Blade Core DispatcherServlet * * @author biezhi - * @since 1.0 + * @since 1.5 */ public class DispatcherServlet extends HttpServlet { diff --git a/blade-core/src/main/java/com/blade/web/StaticFileFilter.java b/blade-core/src/main/java/com/blade/web/StaticFileFilter.java index 9c8ca4e26..78529fa44 100644 --- a/blade-core/src/main/java/com/blade/web/StaticFileFilter.java +++ b/blade-core/src/main/java/com/blade/web/StaticFileFilter.java @@ -1,41 +1,56 @@ -package com.blade.web; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class StaticFileFilter { - - private Set prefixList; - private Map cache; - - public StaticFileFilter(Set prefixList) { - this.prefixList = prefixList; - this.cache = new HashMap(128); - } - - public boolean isStatic(String path){ - if (cache != null) { - Boolean found = cache.get(path); - if (found != null) { - return found == Boolean.TRUE; - } - } - - for(String prefix : prefixList){ - if(path.startsWith(prefix)){ - if (cache != null) { - cache.put(path, Boolean.TRUE); - } - return true; - } - } - - if (cache != null) { - cache.put(path, Boolean.FALSE); - } - - return false; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.web; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class StaticFileFilter { + + private Set prefixList; + private Map cache; + + public StaticFileFilter(Set prefixList) { + this.prefixList = prefixList; + this.cache = new HashMap(128); + } + + public boolean isStatic(String path){ + if (cache != null) { + Boolean found = cache.get(path); + if (found != null) { + return found == Boolean.TRUE; + } + } + + for(String prefix : prefixList){ + if(path.startsWith(prefix)){ + if (cache != null) { + cache.put(path, Boolean.TRUE); + } + return true; + } + } + + if (cache != null) { + cache.put(path, Boolean.FALSE); + } + + return false; + } + +} diff --git a/blade-core/src/main/java/com/blade/web/http/HttpMethod.java b/blade-core/src/main/java/com/blade/web/http/HttpMethod.java index 421c2c0ce..ac32cf7dc 100644 --- a/blade-core/src/main/java/com/blade/web/http/HttpMethod.java +++ b/blade-core/src/main/java/com/blade/web/http/HttpMethod.java @@ -19,7 +19,7 @@ * HTTP Request Method * * @author biezhi - * @since 1.0 + * @since 1.5 */ public enum HttpMethod { ALL, GET, POST, PUT, PATCH, DELETE, HEAD, TRACE, CONNECT, OPTIONS, BEFORE, AFTER diff --git a/blade-core/src/main/java/com/blade/web/http/HttpStatus.java b/blade-core/src/main/java/com/blade/web/http/HttpStatus.java index 15525b457..b2eaa07a8 100644 --- a/blade-core/src/main/java/com/blade/web/http/HttpStatus.java +++ b/blade-core/src/main/java/com/blade/web/http/HttpStatus.java @@ -1,46 +1,46 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; - -/** - * HTTP Status - * - * @author biezhi - * @since 1.0 - */ -public final class HttpStatus { - - public static final int OK = 200; - public static final int CREATED = 201; - public static final int ACCEPTED = 202; - public static final int PARTIAL_INFO = 203; - public static final int NO_RESPONSE = 204; - public static final int MOVED = 301; - public static final int FOUND = 302; - public static final int METHOD = 303; - public static final int NOT_MODIFIED = 304; - public static final int BAD_REQUEST = 400; - public static final int UNAUTHORIZED = 401; - public static final int PAYMENT_REQUIRED = 402; - public static final int FORBIDDEN = 403; - public static final int NOT_FOUND = 404; - public static final int CONFLICT = 409; - public static final int INTERNAL_ERROR = 500; - public static final int NOT_IMPLEMENTED = 501; - public static final int OVERLOADED = 502; - public static final int GATEWAY_TIMEOUT = 503; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; + +/** + * HTTP Status + * + * @author biezhi + * @since 1.5 + */ +public final class HttpStatus { + + public static final int OK = 200; + public static final int CREATED = 201; + public static final int ACCEPTED = 202; + public static final int PARTIAL_INFO = 203; + public static final int NO_RESPONSE = 204; + public static final int MOVED = 301; + public static final int FOUND = 302; + public static final int METHOD = 303; + public static final int NOT_MODIFIED = 304; + public static final int BAD_REQUEST = 400; + public static final int UNAUTHORIZED = 401; + public static final int PAYMENT_REQUIRED = 402; + public static final int FORBIDDEN = 403; + public static final int NOT_FOUND = 404; + public static final int CONFLICT = 409; + public static final int INTERNAL_ERROR = 500; + public static final int NOT_IMPLEMENTED = 501; + public static final int OVERLOADED = 502; + public static final int GATEWAY_TIMEOUT = 503; + +} diff --git a/blade-core/src/main/java/com/blade/web/http/Path.java b/blade-core/src/main/java/com/blade/web/http/Path.java index fe28a2690..6c1442238 100644 --- a/blade-core/src/main/java/com/blade/web/http/Path.java +++ b/blade-core/src/main/java/com/blade/web/http/Path.java @@ -1,100 +1,100 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.List; - -import com.blade.kit.CollectionKit; -import com.blade.kit.StringKit; - -/** - * Path URL - * - * @author biezhi - * @since 1.0 - */ -public final class Path { - - public static final String VAR_REGEXP = ":(\\w+)"; - public static final String VAR_REPLACE = "([^#/?]+)"; - - public static final String ALL_PATHS = "/*"; - private static final String SLASH = "/"; - - public static String getRelativePath(String path, String contextPath) { - - path = path.substring(contextPath.length()); - - if (path.length() > 0) { - path = path.substring(1); - } - - if (!path.startsWith(SLASH)) { - path = SLASH + path; - } - - try { - path = URLDecoder.decode(path, "UTF-8"); - } catch (UnsupportedEncodingException ex) { - } - return path; - } - - public static List convertRouteToList(String route) { - String[] pathArray = StringKit.split(route, "/"); - if(null != pathArray && pathArray.length > 0){ - List path = CollectionKit.newArrayList(); - for (String p : pathArray) { - if (p.length() > 0) { - path.add(p); - } - } - return path; - } - return CollectionKit.newArrayList(0); - } - - public static boolean isParam(String routePart) { - return routePart.startsWith(":"); - } - - public static boolean isSplat(String routePart) { - return routePart.equals("*"); - } - - public static String fixPath(String path) { - if (path == null) { - return "/"; - } - if (!path.startsWith("/")) { - path = "/" + path; - } - if (path.length() > 1 && path.endsWith("/")) { - path = path.substring(0, path.length() - 1); - } - return path; - } - - public static String cleanPath(String path){ - if (path == null) { - return null; - } - return path.replaceAll("[/]+", "/"); - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.List; + +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; + +/** + * Path URL + * + * @author biezhi + * @since 1.5 + */ +public final class Path { + + public static final String VAR_REGEXP = ":(\\w+)"; + public static final String VAR_REPLACE = "([^#/?]+)"; + + public static final String ALL_PATHS = "/*"; + private static final String SLASH = "/"; + + public static String getRelativePath(String path, String contextPath) { + + path = path.substring(contextPath.length()); + + if (path.length() > 0) { + path = path.substring(1); + } + + if (!path.startsWith(SLASH)) { + path = SLASH + path; + } + + try { + path = URLDecoder.decode(path, "UTF-8"); + } catch (UnsupportedEncodingException ex) { + } + return path; + } + + public static List convertRouteToList(String route) { + String[] pathArray = StringKit.split(route, "/"); + if(null != pathArray && pathArray.length > 0){ + List path = CollectionKit.newArrayList(); + for (String p : pathArray) { + if (p.length() > 0) { + path.add(p); + } + } + return path; + } + return CollectionKit.newArrayList(0); + } + + public static boolean isParam(String routePart) { + return routePart.startsWith(":"); + } + + public static boolean isSplat(String routePart) { + return routePart.equals("*"); + } + + public static String fixPath(String path) { + if (path == null) { + return "/"; + } + if (!path.startsWith("/")) { + path = "/" + path; + } + if (path.length() > 1 && path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + return path; + } + + public static String cleanPath(String path){ + if (path == null) { + return null; + } + return path.replaceAll("[/]+", "/"); + } + +} diff --git a/blade-core/src/main/java/com/blade/web/http/Request.java b/blade-core/src/main/java/com/blade/web/http/Request.java index 66f5ccc93..365fd8659 100644 --- a/blade-core/src/main/java/com/blade/web/http/Request.java +++ b/blade-core/src/main/java/com/blade/web/http/Request.java @@ -1,362 +1,362 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; - -import java.io.InputStream; -import java.io.Serializable; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletContext; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; - -import com.blade.route.Route; -import com.blade.web.http.wrapper.Session; -import com.blade.web.multipart.FileItem; - -/** - * HTTP Request - * - * @author biezhi - * @since 1.0 - */ -public interface Request { - - /** - * @return Return HttpServletRequest - */ - HttpServletRequest raw(); - - /** - * URL parameters on the initial route, e.g:/user/23 - * @param routePath Route URL - */ - void initPathParams(String routePath); - - /** - * @return Return client request host - */ - String host(); - - /** - * @return Return request URL - */ - String url(); - - /** - * @return Return request URI - */ - String uri(); - - /** - * @return Return UA - */ - String userAgent(); - - /** - * @return Return PathInfo - */ - String pathInfo(); - - /** - * @return Return protocol - */ - String protocol(); - - /** - * @return Return servletPath - */ - String servletPath(); - - /** - * @return Return contextPath - */ - String contextPath(); - - /** - * @return Return ServletContext - */ - ServletContext context(); - - /** - * @return Return parameters on the path Map - */ - Map pathParams(); - - /** - * Get a URL parameter - * @param name Parameter name - * @return Return parameter value - */ - String param(String name); - - /** - * Get a URL parameter, and returns defaultValue if it is NULL - * @param name Parameter name - * @param defaultValue Default Value - * @return Return parameter value - */ - String param(String name, String defaultValue); - - /** - * Return a URL parameter for a Int type - * @param name Parameter name - * @return Return Int parameter value - */ - Integer paramAsInt(String name); - - /** - * Return a URL parameter for a Long type - * @param name Parameter name - * @return Return Long parameter value - */ - Long paramAsLong(String name); - - /** - * Return a URL parameter for a Boolean type - * @param name Parameter name - * @return Return Boolean parameter value - */ - Boolean paramAsBool(String name); - - /** - * @return Return query string - */ - String queryString(); - - /** - * @return Return request query Map - */ - Map querys(); - - /** - * Get a request parameter - * - * @param name Parameter name - * @return Return request parameter value - */ - String query(String name); - - /** - * Get a request parameter, if NULL is returned to defaultValue - * - * @param name Parameter name - * @param defaultValue Default value - * @return Return request parameter values - */ - String query(String name, String defaultValue); - - /** - * Returns a request parameter for a Int type - * - * @param name Parameter name - * @return Return Int parameter values - */ - Integer queryAsInt(String name); - - /** - * Returns a request parameter for a Long type - * - * @param name Parameter name - * @return Return Long parameter values - */ - Long queryAsLong(String name); - - /** - * Returns a request parameter for a Boolean type - * - * @param name Parameter name - * @return Return Boolean parameter values - */ - Boolean queryAsBool(String name); - - /** - * Returns a request parameter for a Float type - * - * @param name Parameter name - * @return Return Float parameter values - */ - Float queryAsFloat(String name); - - /** - * Returns a request parameter for a Double type - * - * @param name Parameter name - * @return Return Double parameter values - */ - Double queryAsDouble(String name); - - /** - * @return Return request method - */ - String method(); - - /** - * @return Return HttpMethod - */ - HttpMethod httpMethod(); - - /** - * @return Return server remote address - */ - String address(); - - /** - * @return Return current session - */ - Session session(); - - /** - * Return to the current or create a session - * @param create create session - * @return Return session - */ - Session session(boolean create); - - /** - * @return Return contentType - */ - String contentType(); - - /** - * @return Return Server Port - */ - int port(); - - /** - * @return Return whether to use the SSL connection - */ - boolean isSecure(); - - /** - * @return Return current request is a AJAX request - */ - boolean isAjax(); - - /** - * @return Return Cookie Map - */ - Map cookies(); - - /** - * Get String Cookie Value - * - * @param name cookie name - * @return Return Cookie Value - */ - String cookie(String name); - - /** - * Get Cookie - * - * @param name cookie name - * @return Return Cookie - */ - Cookie cookieRaw(String name); - - /** - * @return Return header information Map - */ - Map headers(); - - /** - * Get header information - * - * @param name Parameter name - * @return Return header information - */ - String header(String name); - - /** - * Setting request encoding - * - * @param encoding coded string - */ - void encoding(String encoding); - - /** - * Setting Request Attribute - * - * @param name Parameter name - * @param value Parameter Value - */ - void attribute(String name, Object value); - - /** - * Get a Request Attribute - * @param name Parameter name - * @return Return parameter value - */ - T attribute(String name); - - /** - * @return Return all Attribute in Request - */ - Set attributes(); - - /** - * @return Return the requested file list - */ - FileItem[] files(); - - /** - * @return Return request body - */ - BodyParser body(); - - /** - * Serialized form data, converted to the javabean - * - * @param slug bean slug, e.g: , the slug is person - * @param clazz bean type - * @return Return converted Bean Object - */ - T model(String slug, Class clazz); - - /** - * Setting route, execute request for use - * - * @param route route object - */ - void setRoute(Route route); - - /** - * @return Return Route of the current request - */ - Route route(); - - /** - * Abort current request - */ - void abort(); - - /** - * @return Return is abort request - */ - boolean isAbort(); - - /** - * Request body interface - * @author biezhi - */ - interface BodyParser { - String asString(); - InputStream asInputStream(); - byte[] asByte(); - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; + +import java.io.InputStream; +import java.io.Serializable; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletContext; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; + +import com.blade.route.Route; +import com.blade.web.http.wrapper.Session; +import com.blade.web.multipart.FileItem; + +/** + * HTTP Request + * + * @author biezhi + * @since 1.5 + */ +public interface Request { + + /** + * @return Return HttpServletRequest + */ + HttpServletRequest raw(); + + /** + * URL parameters on the initial route, e.g:/user/23 + * @param routePath Route URL + */ + void initPathParams(String routePath); + + /** + * @return Return client request host + */ + String host(); + + /** + * @return Return request URL + */ + String url(); + + /** + * @return Return request URI + */ + String uri(); + + /** + * @return Return UA + */ + String userAgent(); + + /** + * @return Return PathInfo + */ + String pathInfo(); + + /** + * @return Return protocol + */ + String protocol(); + + /** + * @return Return servletPath + */ + String servletPath(); + + /** + * @return Return contextPath + */ + String contextPath(); + + /** + * @return Return ServletContext + */ + ServletContext context(); + + /** + * @return Return parameters on the path Map + */ + Map pathParams(); + + /** + * Get a URL parameter + * @param name Parameter name + * @return Return parameter value + */ + String param(String name); + + /** + * Get a URL parameter, and returns defaultValue if it is NULL + * @param name Parameter name + * @param defaultValue Default Value + * @return Return parameter value + */ + String param(String name, String defaultValue); + + /** + * Return a URL parameter for a Int type + * @param name Parameter name + * @return Return Int parameter value + */ + Integer paramAsInt(String name); + + /** + * Return a URL parameter for a Long type + * @param name Parameter name + * @return Return Long parameter value + */ + Long paramAsLong(String name); + + /** + * Return a URL parameter for a Boolean type + * @param name Parameter name + * @return Return Boolean parameter value + */ + Boolean paramAsBool(String name); + + /** + * @return Return query string + */ + String queryString(); + + /** + * @return Return request query Map + */ + Map querys(); + + /** + * Get a request parameter + * + * @param name Parameter name + * @return Return request parameter value + */ + String query(String name); + + /** + * Get a request parameter, if NULL is returned to defaultValue + * + * @param name Parameter name + * @param defaultValue Default value + * @return Return request parameter values + */ + String query(String name, String defaultValue); + + /** + * Returns a request parameter for a Int type + * + * @param name Parameter name + * @return Return Int parameter values + */ + Integer queryAsInt(String name); + + /** + * Returns a request parameter for a Long type + * + * @param name Parameter name + * @return Return Long parameter values + */ + Long queryAsLong(String name); + + /** + * Returns a request parameter for a Boolean type + * + * @param name Parameter name + * @return Return Boolean parameter values + */ + Boolean queryAsBool(String name); + + /** + * Returns a request parameter for a Float type + * + * @param name Parameter name + * @return Return Float parameter values + */ + Float queryAsFloat(String name); + + /** + * Returns a request parameter for a Double type + * + * @param name Parameter name + * @return Return Double parameter values + */ + Double queryAsDouble(String name); + + /** + * @return Return request method + */ + String method(); + + /** + * @return Return HttpMethod + */ + HttpMethod httpMethod(); + + /** + * @return Return server remote address + */ + String address(); + + /** + * @return Return current session + */ + Session session(); + + /** + * Return to the current or create a session + * @param create create session + * @return Return session + */ + Session session(boolean create); + + /** + * @return Return contentType + */ + String contentType(); + + /** + * @return Return Server Port + */ + int port(); + + /** + * @return Return whether to use the SSL connection + */ + boolean isSecure(); + + /** + * @return Return current request is a AJAX request + */ + boolean isAjax(); + + /** + * @return Return Cookie Map + */ + Map cookies(); + + /** + * Get String Cookie Value + * + * @param name cookie name + * @return Return Cookie Value + */ + String cookie(String name); + + /** + * Get Cookie + * + * @param name cookie name + * @return Return Cookie + */ + Cookie cookieRaw(String name); + + /** + * @return Return header information Map + */ + Map headers(); + + /** + * Get header information + * + * @param name Parameter name + * @return Return header information + */ + String header(String name); + + /** + * Setting request encoding + * + * @param encoding coded string + */ + void encoding(String encoding); + + /** + * Setting Request Attribute + * + * @param name Parameter name + * @param value Parameter Value + */ + void attribute(String name, Object value); + + /** + * Get a Request Attribute + * @param name Parameter name + * @return Return parameter value + */ + T attribute(String name); + + /** + * @return Return all Attribute in Request + */ + Set attributes(); + + /** + * @return Return the requested file list + */ + FileItem[] files(); + + /** + * @return Return request body + */ + BodyParser body(); + + /** + * Serialized form data, converted to the javabean + * + * @param slug bean slug, e.g: , the slug is person + * @param clazz bean type + * @return Return converted Bean Object + */ + T model(String slug, Class clazz); + + /** + * Setting route, execute request for use + * + * @param route route object + */ + void setRoute(Route route); + + /** + * @return Return Route of the current request + */ + Route route(); + + /** + * Abort current request + */ + void abort(); + + /** + * @return Return is abort request + */ + boolean isAbort(); + + /** + * Request body interface + * @author biezhi + */ + interface BodyParser { + String asString(); + InputStream asInputStream(); + byte[] asByte(); + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/http/Response.java b/blade-core/src/main/java/com/blade/web/http/Response.java index e338b2d0a..f22b7497e 100644 --- a/blade-core/src/main/java/com/blade/web/http/Response.java +++ b/blade-core/src/main/java/com/blade/web/http/Response.java @@ -1,249 +1,249 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import com.blade.view.ModelAndView; -import com.blade.view.template.TemplateException; - -/** - * HTTP Response - * - * @author biezhi - * @since 1.0 - */ -public interface Response { - - /** - * @return Return HttpServletResponse - */ - HttpServletResponse raw(); - - /** - * @return Return HTTP Status - */ - int status(); - - /** - * Setting Response Status - * - * @param status status code - * @return Return Response - */ - Response status(int status); - - /** - * @return Setting Response Status is BadRequest and Return Response - */ - Response badRequest(); - - /** - * @return Setting Response Status is unauthorized and Return Response - */ - Response unauthorized(); - - /** - * @return Setting Response Status is notFound and Return Response - */ - Response notFound(); - - /** - * @return Setting Response Status is conflict and Return Response - */ - Response conflict(); - - /** - * @return Return Response contentType - */ - String contentType(); - - /** - * Setting Response ContentType - * - * @param contentType content type - * @return Return Response - */ - Response contentType(String contentType); - - /** - * Get header - * - * @param name Header Name - * @return Return Response - */ - String header(String name); - - /** - * Setting header - * - * @param name Header Name - * @param value Header Value - * @return Return Response - */ - Response header(String name, String value); - - /** - * Setting Cookie - * - * @param cookie Cookie Object - * @return Return Response - */ - Response cookie(Cookie cookie); - - /** - * Setting Cookie - * - * @param name Cookie Name - * @param value Cookie Value - * @return Return Response - */ - Response cookie(String name, String value); - - /** - * Setting Cookie - * - * @param name Cookie Name - * @param value Cookie Value - * @param maxAge Period of validity - * @return Return Response - */ - Response cookie(String name, String value, int maxAge); - - /** - * Setting Cookie - * - * @param name Cookie Name - * @param value Cookie Value - * @param maxAge Period of validity - * @param secured Is SSL - * @return Return Response - */ - Response cookie(String name, String value, int maxAge, boolean secured); - - /** - * Setting Cookie - * - * @param path Cookie Domain Path - * @param name Cookie Name - * @param value Cookie Value - * @param maxAge Period of validity - * @param secured Is SSL - * @return Return Response - */ - Response cookie(String path, String name, String value, int maxAge, boolean secured); - - /** - * Remove Cookie - * - * @param cookie Cookie Object - * @return Return Response - */ - Response removeCookie(Cookie cookie); - - /** - * Rmove Cookie By Name - * - * @param name Cookie Name - * @return Return Response - */ - Response removeCookie(String name); - - /** - * Render by text - * - * @param text text content - * @return Return Response - */ - Response text(String text); - - /** - * Render by html - * - * @param html html content - * @return Return Response - */ - Response html(String html); - - /** - * Render by json - * - * @param json json content - * @return Return Response - */ - Response json(String json); - - /** - * Render by xml - * - * @param xml xml content - * @return Return Response - */ - Response xml(String xml); - - /** - * @return Return OutputStream - * @throws IOException IOException - */ - OutputStream outputStream() throws IOException; - - /** - * @return Return ResponseWriter Stream - * @throws IOException - */ - PrintWriter writer() throws IOException; - - /** - * Render view - * - * @param view view page - * @return Return Response - */ - Response render(String view) throws TemplateException, IOException; - - /** - * Render view And Setting Data - * - * @param modelAndView ModelAndView object - * @return Return Response - */ - Response render(ModelAndView modelAndView) throws TemplateException, IOException; - - /** - * Redirect to Path - * - * @param path location path - */ - void redirect(String path); - - /** - * Go to Path, Under contextpath - * - * @param path redirect location - */ - void go(String path); - - /** - * @return Return Response is Write - */ - boolean isWritten(); - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import com.blade.view.ModelAndView; +import com.blade.view.template.TemplateException; + +/** + * HTTP Response + * + * @author biezhi + * @since 1.5 + */ +public interface Response { + + /** + * @return Return HttpServletResponse + */ + HttpServletResponse raw(); + + /** + * @return Return HTTP Status + */ + int status(); + + /** + * Setting Response Status + * + * @param status status code + * @return Return Response + */ + Response status(int status); + + /** + * @return Setting Response Status is BadRequest and Return Response + */ + Response badRequest(); + + /** + * @return Setting Response Status is unauthorized and Return Response + */ + Response unauthorized(); + + /** + * @return Setting Response Status is notFound and Return Response + */ + Response notFound(); + + /** + * @return Setting Response Status is conflict and Return Response + */ + Response conflict(); + + /** + * @return Return Response contentType + */ + String contentType(); + + /** + * Setting Response ContentType + * + * @param contentType content type + * @return Return Response + */ + Response contentType(String contentType); + + /** + * Get header + * + * @param name Header Name + * @return Return Response + */ + String header(String name); + + /** + * Setting header + * + * @param name Header Name + * @param value Header Value + * @return Return Response + */ + Response header(String name, String value); + + /** + * Setting Cookie + * + * @param cookie Cookie Object + * @return Return Response + */ + Response cookie(Cookie cookie); + + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @return Return Response + */ + Response cookie(String name, String value); + + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @return Return Response + */ + Response cookie(String name, String value, int maxAge); + + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @param secured Is SSL + * @return Return Response + */ + Response cookie(String name, String value, int maxAge, boolean secured); + + /** + * Setting Cookie + * + * @param path Cookie Domain Path + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @param secured Is SSL + * @return Return Response + */ + Response cookie(String path, String name, String value, int maxAge, boolean secured); + + /** + * Remove Cookie + * + * @param cookie Cookie Object + * @return Return Response + */ + Response removeCookie(Cookie cookie); + + /** + * Rmove Cookie By Name + * + * @param name Cookie Name + * @return Return Response + */ + Response removeCookie(String name); + + /** + * Render by text + * + * @param text text content + * @return Return Response + */ + Response text(String text); + + /** + * Render by html + * + * @param html html content + * @return Return Response + */ + Response html(String html); + + /** + * Render by json + * + * @param json json content + * @return Return Response + */ + Response json(String json); + + /** + * Render by xml + * + * @param xml xml content + * @return Return Response + */ + Response xml(String xml); + + /** + * @return Return OutputStream + * @throws IOException IOException + */ + OutputStream outputStream() throws IOException; + + /** + * @return Return ResponseWriter Stream + * @throws IOException + */ + PrintWriter writer() throws IOException; + + /** + * Render view + * + * @param view view page + * @return Return Response + */ + Response render(String view) throws TemplateException, IOException; + + /** + * Render view And Setting Data + * + * @param modelAndView ModelAndView object + * @return Return Response + */ + Response render(ModelAndView modelAndView) throws TemplateException, IOException; + + /** + * Redirect to Path + * + * @param path location path + */ + void redirect(String path); + + /** + * Go to Path, Under contextpath + * + * @param path redirect location + */ + void go(String path); + + /** + * @return Return Response is Write + */ + boolean isWritten(); + +} diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java index 7329bd031..3edbac986 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java @@ -1,579 +1,579 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http.wrapper; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.ServletContext; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import com.blade.kit.IOKit; -import com.blade.kit.ObjectKit; -import com.blade.kit.StringKit; -import com.blade.route.Route; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.multipart.FileItem; -import com.blade.web.multipart.Multipart; -import com.blade.web.multipart.MultipartException; -import com.blade.web.multipart.MultipartHandler; - -/** - * ServletRequest - * - * @author biezhi - * @since 1.0 - */ -public class ServletRequest implements Request { - - private static final String USER_AGENT = "user-agent"; - - protected Route route; - - private HttpServletRequest request; - - protected Map pathParams = null; - - private Map multipartParams = null; - - private List files = null; - - private Session session = null; - - private boolean isAbort = false; - - public ServletRequest(HttpServletRequest request) throws MultipartException, IOException { - this.request = request; - this.pathParams = new HashMap(); - this.multipartParams = new HashMap(); - this.files = new ArrayList(); - init(); - } - - public ServletRequest init() throws IOException, MultipartException { - // retrieve multipart/form-data parameters - if (Multipart.isMultipartContent(request)) { - Multipart multipart = new Multipart(); - multipart.parse(request, new MultipartHandler() { - - @Override - public void handleFormItem(String name, String value) { - multipartParams.put( name, value ); - } - - @Override - public void handleFileItem(String name, FileItem fileItem) { - files.add(fileItem); - } - - }); - } - return this; - } - - private String join(String[] arr) { - String ret = ""; - for (String item : arr) { - ret += "," + item; - } - if (ret.length() > 0) { - ret = ret.substring(1); - } - return ret; - } - - @Override - public void initPathParams(String routePath) { - pathParams.clear(); - - List variables = getPathParam(routePath); - String regexPath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); - - String uri = Path.getRelativePath(uri(), contextPath()); - - Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(uri); - - if(matcher.matches()){ - // start index at 1 as group(0) always stands for the entire expression - for (int i=1, len = variables.size(); i <= len; i++) { - String value = matcher.group(i); - pathParams.put(variables.get(i-1), value); - } - } - } - - private List getPathParam(String routePath) { - List variables = new ArrayList(); - Matcher matcher = Pattern.compile(Path.VAR_REGEXP).matcher(routePath); - while (matcher.find()) { - variables.add(matcher.group(1)); - } - return variables; - } - - @Override - public HttpServletRequest raw() { - return request; - } - - @Override - public String host() { - return request.getServerName(); - } - - @Override - public String url() { - return request.getRequestURL().toString(); - } - - @Override - public String uri() { - return Path.fixPath(request.getRequestURI()); - } - - @Override - public String userAgent() { - return request.getHeader(USER_AGENT); - } - - @Override - public String pathInfo() { - return request.getPathInfo(); - } - - @Override - public String protocol() { - return request.getProtocol(); - } - - @Override - public String servletPath() { - return request.getServletPath(); - } - - @Override - public String contextPath() { - return request.getContextPath(); - } - - @Override - public ServletContext context() { - return request.getServletContext(); - } - - @Override - public Map pathParams() { - return pathParams; - } - - @Override - public String param(String name) { - return pathParams.get(name); - } - - @Override - public String param(String name, String defaultValue) { - String val = pathParams.get(name); - if(null == val){ - val = defaultValue; - } - return val; - } - - @Override - public Integer paramAsInt(String name) { - String value = param(name); - if (StringKit.isNotBlank(value)) { - return Integer.parseInt(value); - } - return null; - } - - @Override - public Long paramAsLong(String name) { - String value = param(name); - if (StringKit.isNotBlank(value)) { - return Long.parseLong(value); - } - return null; - } - - @Override - public Boolean paramAsBool(String name) { - String value = param(name); - if (StringKit.isNotBlank(value)) { - return Boolean.parseBoolean(value); - } - return null; - } - - @Override - public String queryString() { - return request.getQueryString(); - } - - @Override - public Map querys() { - Map params = new HashMap(); - - Map requestParams = request.getParameterMap(); - for (Map.Entry entry : requestParams.entrySet()) { - params.put( entry.getKey(), join(entry.getValue()) ); - } - params.putAll(multipartParams); - return Collections.unmodifiableMap(params); - } - - @Override - public String query(String name) { - String[] param = request.getParameterValues(name); - String val = null; - if (param != null) { - val = join(param); - } else { - val = multipartParams.get(name); - } - return val; - } - - @Override - public String query(String name, String defaultValue) { - String[] param = request.getParameterValues(name); - String val = null; - if (param != null) { - val = join(param); - } else { - val = multipartParams.get(name); - } - if(null == val){ - val = defaultValue; - } - return val; - } - - @Override - public Integer queryAsInt(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { - return Integer.parseInt(value); - } - return null; - } - - @Override - public Long queryAsLong(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { - return Long.parseLong(value); - } - return null; - } - - @Override - public Boolean queryAsBool(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isBoolean(value)) { - return Boolean.parseBoolean(value); - } - return null; - } - - @Override - public Float queryAsFloat(String name) { - String value = query(name); - if (StringKit.isNotBlank(value)) { - try { - return Float.parseFloat(value); - } catch (NumberFormatException e) { - } - } - return null; - } - - @Override - public Double queryAsDouble(String name) { - String value = query(name); - if (StringKit.isNotBlank(value)) { - try { - return Double.parseDouble(value); - } catch (NumberFormatException e) { - } - } - return null; - } - - @Override - public String method() { - return request.getMethod(); - } - - @Override - public HttpMethod httpMethod() { - return HttpMethod.valueOf(request.getMethod().toUpperCase()); - } - - @Override - public String address() { - return request.getRemoteAddr(); - } - - @Override - public Session session() { - if (session == null) { - session = new Session(request.getSession()); - } - return session; - } - - @Override - public Session session(boolean create) { - if (session == null) { - HttpSession httpSession = request.getSession(create); - if (httpSession != null) { - session = new Session(httpSession); - } - } - return session; - } - - @Override - public void attribute(String name, Object value) { - request.setAttribute(name, value); - } - - @SuppressWarnings("unchecked") - @Override - public T attribute(String name) { - Object object = request.getAttribute(name); - if(null != object){ - return (T) object; - } - return null; - } - - @Override - public Set attributes() { - Set attrList = new HashSet(); - Enumeration attributes = (Enumeration) request.getAttributeNames(); - while (attributes.hasMoreElements()) { - attrList.add(attributes.nextElement()); - } - return attrList; - } - - @Override - public String contentType() { - return request.getContentType(); - } - - @Override - public int port() { - return request.getServerPort(); - } - - @Override - public boolean isSecure() { - return request.isSecure(); - } - - @Override - public boolean isAjax() { - if (request.getHeader("x-requested-with") == null) { - return false; - } - return "XMLHttpRequest".equals(request.getHeader("x-requested-with")); - } - - @Override - public Map cookies() { - javax.servlet.http.Cookie[] servletCookies = request.getCookies(); - - Map cookies = new HashMap(); - for (javax.servlet.http.Cookie c : servletCookies) { - cookies.put( c.getName(), map(c) ); - } - - return Collections.unmodifiableMap(cookies); - } - - private Cookie map(Cookie servletCookie) { - Cookie cookie = new Cookie(servletCookie.getName(), servletCookie.getValue()); - cookie.setMaxAge(servletCookie.getMaxAge()); - cookie.setHttpOnly(servletCookie.isHttpOnly()); - String path = servletCookie.getPath(); - if(null != path){ - cookie.setPath(path); - } - String domain = servletCookie.getDomain(); - if(null != domain){ - cookie.setDomain(domain); - } - cookie.setSecure(servletCookie.getSecure()); - return cookie; - } - - @Override - public String cookie(String name) { - Cookie cookie = cookieRaw(name); - if(null != cookie){ - return cookie.getValue(); - } - return null; - } - - @Override - public Cookie cookieRaw(String name) { - javax.servlet.http.Cookie[] servletCookies = request.getCookies(); - - if (servletCookies == null) { - return null; - } - - for (javax.servlet.http.Cookie c : servletCookies) { - if (c.getName().equals(name)) { - return map(c); - } - } - return null; - } - - @Override - public Map headers() { - Enumeration servletHeaders = request.getHeaderNames(); - Map headers = new HashMap(); - while(servletHeaders.hasMoreElements()) { - String headerName = servletHeaders.nextElement(); - headers.put(headerName, request.getHeader(headerName)); - } - return headers; - } - - @Override - public String header(String name) { - return request.getHeader(name); - } - - @Override - public void encoding(String encoding) { - try { - request.setCharacterEncoding(encoding); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - - @Override - public void setRoute(Route route) { - this.route = route; - initPathParams(route.getPath()); - } - - @Override - public Route route() { - return this.route; - } - - @Override - public void abort() { - this.isAbort = true; - } - - @Override - public boolean isAbort() { - return this.isAbort; - } - - @Override - public T model(String slug, Class clazz) { - if(StringKit.isNotBlank(slug) && null != clazz){ - return ObjectKit.model(slug, clazz, querys()); - } - return null; - } - - @Override - public FileItem[] files() { - FileItem[] fileParts = new FileItem[files.size()]; - for (int i=0; i < files.size(); i++) { - fileParts[i] = files.get(i); - } - return fileParts; - } - - @Override - public BodyParser body() { - return new BodyParser() { - @Override - public String asString() { - try { - BufferedReader reader = new BufferedReader( new InputStreamReader(request.getInputStream()) ); - StringBuilder sb = new StringBuilder(); - String line = reader.readLine(); - while (line != null) { - sb.append(line + "\n"); - line = reader.readLine(); - } - reader.close(); - String data = sb.toString(); - - return data; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public InputStream asInputStream() { - try { - return request.getInputStream(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public byte[] asByte() { - try { - return IOKit.toByteArray(request.getInputStream()); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - }; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http.wrapper; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.ServletContext; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import com.blade.kit.IOKit; +import com.blade.kit.ObjectKit; +import com.blade.kit.StringKit; +import com.blade.route.Route; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.multipart.FileItem; +import com.blade.web.multipart.Multipart; +import com.blade.web.multipart.MultipartException; +import com.blade.web.multipart.MultipartHandler; + +/** + * ServletRequest + * + * @author biezhi + * @since 1.5 + */ +public class ServletRequest implements Request { + + private static final String USER_AGENT = "user-agent"; + + protected Route route; + + private HttpServletRequest request; + + protected Map pathParams = null; + + private Map multipartParams = null; + + private List files = null; + + private Session session = null; + + private boolean isAbort = false; + + public ServletRequest(HttpServletRequest request) throws MultipartException, IOException { + this.request = request; + this.pathParams = new HashMap(); + this.multipartParams = new HashMap(); + this.files = new ArrayList(); + init(); + } + + public ServletRequest init() throws IOException, MultipartException { + // retrieve multipart/form-data parameters + if (Multipart.isMultipartContent(request)) { + Multipart multipart = new Multipart(); + multipart.parse(request, new MultipartHandler() { + + @Override + public void handleFormItem(String name, String value) { + multipartParams.put( name, value ); + } + + @Override + public void handleFileItem(String name, FileItem fileItem) { + files.add(fileItem); + } + + }); + } + return this; + } + + private String join(String[] arr) { + String ret = ""; + for (String item : arr) { + ret += "," + item; + } + if (ret.length() > 0) { + ret = ret.substring(1); + } + return ret; + } + + @Override + public void initPathParams(String routePath) { + pathParams.clear(); + + List variables = getPathParam(routePath); + String regexPath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); + + String uri = Path.getRelativePath(uri(), contextPath()); + + Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(uri); + + if(matcher.matches()){ + // start index at 1 as group(0) always stands for the entire expression + for (int i=1, len = variables.size(); i <= len; i++) { + String value = matcher.group(i); + pathParams.put(variables.get(i-1), value); + } + } + } + + private List getPathParam(String routePath) { + List variables = new ArrayList(); + Matcher matcher = Pattern.compile(Path.VAR_REGEXP).matcher(routePath); + while (matcher.find()) { + variables.add(matcher.group(1)); + } + return variables; + } + + @Override + public HttpServletRequest raw() { + return request; + } + + @Override + public String host() { + return request.getServerName(); + } + + @Override + public String url() { + return request.getRequestURL().toString(); + } + + @Override + public String uri() { + return Path.fixPath(request.getRequestURI()); + } + + @Override + public String userAgent() { + return request.getHeader(USER_AGENT); + } + + @Override + public String pathInfo() { + return request.getPathInfo(); + } + + @Override + public String protocol() { + return request.getProtocol(); + } + + @Override + public String servletPath() { + return request.getServletPath(); + } + + @Override + public String contextPath() { + return request.getContextPath(); + } + + @Override + public ServletContext context() { + return request.getServletContext(); + } + + @Override + public Map pathParams() { + return pathParams; + } + + @Override + public String param(String name) { + return pathParams.get(name); + } + + @Override + public String param(String name, String defaultValue) { + String val = pathParams.get(name); + if(null == val){ + val = defaultValue; + } + return val; + } + + @Override + public Integer paramAsInt(String name) { + String value = param(name); + if (StringKit.isNotBlank(value)) { + return Integer.parseInt(value); + } + return null; + } + + @Override + public Long paramAsLong(String name) { + String value = param(name); + if (StringKit.isNotBlank(value)) { + return Long.parseLong(value); + } + return null; + } + + @Override + public Boolean paramAsBool(String name) { + String value = param(name); + if (StringKit.isNotBlank(value)) { + return Boolean.parseBoolean(value); + } + return null; + } + + @Override + public String queryString() { + return request.getQueryString(); + } + + @Override + public Map querys() { + Map params = new HashMap(); + + Map requestParams = request.getParameterMap(); + for (Map.Entry entry : requestParams.entrySet()) { + params.put( entry.getKey(), join(entry.getValue()) ); + } + params.putAll(multipartParams); + return Collections.unmodifiableMap(params); + } + + @Override + public String query(String name) { + String[] param = request.getParameterValues(name); + String val = null; + if (param != null) { + val = join(param); + } else { + val = multipartParams.get(name); + } + return val; + } + + @Override + public String query(String name, String defaultValue) { + String[] param = request.getParameterValues(name); + String val = null; + if (param != null) { + val = join(param); + } else { + val = multipartParams.get(name); + } + if(null == val){ + val = defaultValue; + } + return val; + } + + @Override + public Integer queryAsInt(String name) { + String value = query(name); + if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { + return Integer.parseInt(value); + } + return null; + } + + @Override + public Long queryAsLong(String name) { + String value = query(name); + if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { + return Long.parseLong(value); + } + return null; + } + + @Override + public Boolean queryAsBool(String name) { + String value = query(name); + if (StringKit.isNotBlank(value) && StringKit.isBoolean(value)) { + return Boolean.parseBoolean(value); + } + return null; + } + + @Override + public Float queryAsFloat(String name) { + String value = query(name); + if (StringKit.isNotBlank(value)) { + try { + return Float.parseFloat(value); + } catch (NumberFormatException e) { + } + } + return null; + } + + @Override + public Double queryAsDouble(String name) { + String value = query(name); + if (StringKit.isNotBlank(value)) { + try { + return Double.parseDouble(value); + } catch (NumberFormatException e) { + } + } + return null; + } + + @Override + public String method() { + return request.getMethod(); + } + + @Override + public HttpMethod httpMethod() { + return HttpMethod.valueOf(request.getMethod().toUpperCase()); + } + + @Override + public String address() { + return request.getRemoteAddr(); + } + + @Override + public Session session() { + if (session == null) { + session = new Session(request.getSession()); + } + return session; + } + + @Override + public Session session(boolean create) { + if (session == null) { + HttpSession httpSession = request.getSession(create); + if (httpSession != null) { + session = new Session(httpSession); + } + } + return session; + } + + @Override + public void attribute(String name, Object value) { + request.setAttribute(name, value); + } + + @SuppressWarnings("unchecked") + @Override + public T attribute(String name) { + Object object = request.getAttribute(name); + if(null != object){ + return (T) object; + } + return null; + } + + @Override + public Set attributes() { + Set attrList = new HashSet(); + Enumeration attributes = (Enumeration) request.getAttributeNames(); + while (attributes.hasMoreElements()) { + attrList.add(attributes.nextElement()); + } + return attrList; + } + + @Override + public String contentType() { + return request.getContentType(); + } + + @Override + public int port() { + return request.getServerPort(); + } + + @Override + public boolean isSecure() { + return request.isSecure(); + } + + @Override + public boolean isAjax() { + if (request.getHeader("x-requested-with") == null) { + return false; + } + return "XMLHttpRequest".equals(request.getHeader("x-requested-with")); + } + + @Override + public Map cookies() { + javax.servlet.http.Cookie[] servletCookies = request.getCookies(); + + Map cookies = new HashMap(); + for (javax.servlet.http.Cookie c : servletCookies) { + cookies.put( c.getName(), map(c) ); + } + + return Collections.unmodifiableMap(cookies); + } + + private Cookie map(Cookie servletCookie) { + Cookie cookie = new Cookie(servletCookie.getName(), servletCookie.getValue()); + cookie.setMaxAge(servletCookie.getMaxAge()); + cookie.setHttpOnly(servletCookie.isHttpOnly()); + String path = servletCookie.getPath(); + if(null != path){ + cookie.setPath(path); + } + String domain = servletCookie.getDomain(); + if(null != domain){ + cookie.setDomain(domain); + } + cookie.setSecure(servletCookie.getSecure()); + return cookie; + } + + @Override + public String cookie(String name) { + Cookie cookie = cookieRaw(name); + if(null != cookie){ + return cookie.getValue(); + } + return null; + } + + @Override + public Cookie cookieRaw(String name) { + javax.servlet.http.Cookie[] servletCookies = request.getCookies(); + + if (servletCookies == null) { + return null; + } + + for (javax.servlet.http.Cookie c : servletCookies) { + if (c.getName().equals(name)) { + return map(c); + } + } + return null; + } + + @Override + public Map headers() { + Enumeration servletHeaders = request.getHeaderNames(); + Map headers = new HashMap(); + while(servletHeaders.hasMoreElements()) { + String headerName = servletHeaders.nextElement(); + headers.put(headerName, request.getHeader(headerName)); + } + return headers; + } + + @Override + public String header(String name) { + return request.getHeader(name); + } + + @Override + public void encoding(String encoding) { + try { + request.setCharacterEncoding(encoding); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + @Override + public void setRoute(Route route) { + this.route = route; + initPathParams(route.getPath()); + } + + @Override + public Route route() { + return this.route; + } + + @Override + public void abort() { + this.isAbort = true; + } + + @Override + public boolean isAbort() { + return this.isAbort; + } + + @Override + public T model(String slug, Class clazz) { + if(StringKit.isNotBlank(slug) && null != clazz){ + return ObjectKit.model(slug, clazz, querys()); + } + return null; + } + + @Override + public FileItem[] files() { + FileItem[] fileParts = new FileItem[files.size()]; + for (int i=0; i < files.size(); i++) { + fileParts[i] = files.get(i); + } + return fileParts; + } + + @Override + public BodyParser body() { + return new BodyParser() { + @Override + public String asString() { + try { + BufferedReader reader = new BufferedReader( new InputStreamReader(request.getInputStream()) ); + StringBuilder sb = new StringBuilder(); + String line = reader.readLine(); + while (line != null) { + sb.append(line + "\n"); + line = reader.readLine(); + } + reader.close(); + String data = sb.toString(); + + return data; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public InputStream asInputStream() { + try { + return request.getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public byte[] asByte() { + try { + return IOKit.toByteArray(request.getInputStream()); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + }; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index dd6e3acab..fd7c63c4c 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -1,311 +1,311 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http.wrapper; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import com.blade.context.ApplicationWebContext; -import com.blade.kit.Assert; -import com.blade.view.ModelAndView; -import com.blade.view.template.TemplateEngine; -import com.blade.view.template.TemplateException; -import com.blade.web.DispatchKit; -import com.blade.web.http.HttpStatus; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -/** - * ServletResponse - * - * @author biezhi - * @since 1.0 - */ -public class ServletResponse implements Response { - - private HttpServletResponse response; - - private boolean written = false; - - private TemplateEngine render; - - public ServletResponse(HttpServletResponse response, TemplateEngine render) { - this.response = response; - this.render = render; - } - - @Override - public HttpServletResponse raw() { - return response; - } - - @Override - public int status() { - return response.getStatus(); - } - - @Override - public Response status(int status) { - response.setStatus(status); - return this; - } - - @Override - public Response badRequest() { - response.setStatus(HttpStatus.BAD_REQUEST); - return this; - } - - @Override - public Response unauthorized() { - response.setStatus(HttpStatus.UNAUTHORIZED); - return this; - } - - @Override - public Response notFound() { - response.setStatus(HttpStatus.NOT_FOUND); - return this; - } - - @Override - public Response conflict() { - response.setStatus(HttpStatus.CONFLICT); - return this; - } - - @Override - public String contentType() { - return response.getContentType(); - } - - @Override - public Response contentType(String contentType) { - response.setContentType(contentType); - return this; - } - - @Override - public String header(String name) { - return response.getHeader(name); - } - - @Override - public Response header(String name, String value) { - response.setHeader(name, value); - return this; - } - - @Override - public Response cookie(Cookie cookie) { - response.addCookie(cookie); - return this; - } - - @Override - public Response cookie(String name, String value) { - return cookie(name, value); - } - - @Override - public Response cookie(String name, String value, int maxAge) { - return cookie(name, value, maxAge, false); - } - - @Override - public Response cookie(String name, String value, int maxAge, boolean secured) { - return cookie(null, name, value, maxAge, secured); - } - - @Override - public Response cookie(String path, String name, String value, int maxAge, boolean secured) { - Cookie cookie = new Cookie(name, value); - if(null != path){ - cookie.setPath(path); - } - cookie.setMaxAge(maxAge); - cookie.setSecure(secured); - response.addCookie(cookie); - return this; - } - - @Override - public Response removeCookie(Cookie cookie) { - cookie.setMaxAge(0); - response.addCookie(map(cookie)); - return this; - } - - javax.servlet.http.Cookie map(Cookie cookie) { - javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); - servletCookie.setMaxAge(cookie.getMaxAge()); - if (cookie.getPath() != null) { - servletCookie.setPath(cookie.getPath()); - } - if (cookie.getDomain() != null) { - servletCookie.setDomain(cookie.getDomain()); - } - servletCookie.setHttpOnly(cookie.isHttpOnly()); - servletCookie.setSecure(cookie.getSecure()); - return servletCookie; - } - - @Override - public Response removeCookie(String name) { - Cookie cookie = new Cookie(name, ""); - cookie.setMaxAge(0); - response.addCookie(cookie); - return this; - } - - @Override - public Response text(String text) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/plain;charset=utf-8"); - DispatchKit.print(text, response.getWriter()); - this.written = true; - return this; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Response html(String html) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/html;charset=utf-8"); - - PrintWriter writer = response.getWriter(); - DispatchKit.print(html, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public Response json(String json) { - Request request = ApplicationWebContext.request(); - String userAgent = request.userAgent(); - if (userAgent.contains("MSIE")) { - response.setContentType("text/html;charset=utf-8"); - } else { - response.setContentType("application/json;charset=utf-8"); - } - try { - response.setHeader("Cache-Control", "no-cache"); - PrintWriter writer = response.getWriter(); - DispatchKit.print(json, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Response xml(String xml) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/xml;charset=utf-8"); - PrintWriter writer = response.getWriter(); - DispatchKit.print(xml, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public ServletOutputStream outputStream() throws IOException { - return response.getOutputStream(); - } - - @Override - public PrintWriter writer() throws IOException { - return response.getWriter(); - } - - @Override - public Response render(String view) throws TemplateException, IOException{ - Assert.notBlank(view, "view not is null"); - - String viewPath = Path.cleanPath(view); - ModelAndView modelAndView = new ModelAndView(viewPath); - render.render(modelAndView, response.getWriter()); - return this; - } - - @Override - public Response render(ModelAndView modelAndView) throws TemplateException, IOException { - Assert.notNull(modelAndView, "ModelAndView not is null!"); - Assert.notBlank(modelAndView.getView(), "view not is null"); - - String viewPath = Path.cleanPath(modelAndView.getView()); - modelAndView.setView(viewPath); - - render.render(modelAndView, response.getWriter()); - return this; - } - - @Override - public void redirect(String path) { - try { - response.sendRedirect(path); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void go(String path) { - try { - String ctx = ApplicationWebContext.servletContext().getContextPath(); - String location = Path.fixPath(ctx + path); - response.sendRedirect(location); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public boolean isWritten() { - return written; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http.wrapper; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import com.blade.context.ApplicationWebContext; +import com.blade.kit.Assert; +import com.blade.view.ModelAndView; +import com.blade.view.template.TemplateEngine; +import com.blade.view.template.TemplateException; +import com.blade.web.DispatchKit; +import com.blade.web.http.HttpStatus; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * ServletResponse + * + * @author biezhi + * @since 1.5 + */ +public class ServletResponse implements Response { + + private HttpServletResponse response; + + private boolean written = false; + + private TemplateEngine render; + + public ServletResponse(HttpServletResponse response, TemplateEngine render) { + this.response = response; + this.render = render; + } + + @Override + public HttpServletResponse raw() { + return response; + } + + @Override + public int status() { + return response.getStatus(); + } + + @Override + public Response status(int status) { + response.setStatus(status); + return this; + } + + @Override + public Response badRequest() { + response.setStatus(HttpStatus.BAD_REQUEST); + return this; + } + + @Override + public Response unauthorized() { + response.setStatus(HttpStatus.UNAUTHORIZED); + return this; + } + + @Override + public Response notFound() { + response.setStatus(HttpStatus.NOT_FOUND); + return this; + } + + @Override + public Response conflict() { + response.setStatus(HttpStatus.CONFLICT); + return this; + } + + @Override + public String contentType() { + return response.getContentType(); + } + + @Override + public Response contentType(String contentType) { + response.setContentType(contentType); + return this; + } + + @Override + public String header(String name) { + return response.getHeader(name); + } + + @Override + public Response header(String name, String value) { + response.setHeader(name, value); + return this; + } + + @Override + public Response cookie(Cookie cookie) { + response.addCookie(cookie); + return this; + } + + @Override + public Response cookie(String name, String value) { + return cookie(name, value); + } + + @Override + public Response cookie(String name, String value, int maxAge) { + return cookie(name, value, maxAge, false); + } + + @Override + public Response cookie(String name, String value, int maxAge, boolean secured) { + return cookie(null, name, value, maxAge, secured); + } + + @Override + public Response cookie(String path, String name, String value, int maxAge, boolean secured) { + Cookie cookie = new Cookie(name, value); + if(null != path){ + cookie.setPath(path); + } + cookie.setMaxAge(maxAge); + cookie.setSecure(secured); + response.addCookie(cookie); + return this; + } + + @Override + public Response removeCookie(Cookie cookie) { + cookie.setMaxAge(0); + response.addCookie(map(cookie)); + return this; + } + + javax.servlet.http.Cookie map(Cookie cookie) { + javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); + servletCookie.setMaxAge(cookie.getMaxAge()); + if (cookie.getPath() != null) { + servletCookie.setPath(cookie.getPath()); + } + if (cookie.getDomain() != null) { + servletCookie.setDomain(cookie.getDomain()); + } + servletCookie.setHttpOnly(cookie.isHttpOnly()); + servletCookie.setSecure(cookie.getSecure()); + return servletCookie; + } + + @Override + public Response removeCookie(String name) { + Cookie cookie = new Cookie(name, ""); + cookie.setMaxAge(0); + response.addCookie(cookie); + return this; + } + + @Override + public Response text(String text) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/plain;charset=utf-8"); + DispatchKit.print(text, response.getWriter()); + this.written = true; + return this; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Response html(String html) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/html;charset=utf-8"); + + PrintWriter writer = response.getWriter(); + DispatchKit.print(html, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public Response json(String json) { + Request request = ApplicationWebContext.request(); + String userAgent = request.userAgent(); + if (userAgent.contains("MSIE")) { + response.setContentType("text/html;charset=utf-8"); + } else { + response.setContentType("application/json;charset=utf-8"); + } + try { + response.setHeader("Cache-Control", "no-cache"); + PrintWriter writer = response.getWriter(); + DispatchKit.print(json, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Response xml(String xml) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/xml;charset=utf-8"); + PrintWriter writer = response.getWriter(); + DispatchKit.print(xml, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public ServletOutputStream outputStream() throws IOException { + return response.getOutputStream(); + } + + @Override + public PrintWriter writer() throws IOException { + return response.getWriter(); + } + + @Override + public Response render(String view) throws TemplateException, IOException{ + Assert.notBlank(view, "view not is null"); + + String viewPath = Path.cleanPath(view); + ModelAndView modelAndView = new ModelAndView(viewPath); + render.render(modelAndView, response.getWriter()); + return this; + } + + @Override + public Response render(ModelAndView modelAndView) throws TemplateException, IOException { + Assert.notNull(modelAndView, "ModelAndView not is null!"); + Assert.notBlank(modelAndView.getView(), "view not is null"); + + String viewPath = Path.cleanPath(modelAndView.getView()); + modelAndView.setView(viewPath); + + render.render(modelAndView, response.getWriter()); + return this; + } + + @Override + public void redirect(String path) { + try { + response.sendRedirect(path); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void go(String path) { + try { + String ctx = ApplicationWebContext.servletContext().getContextPath(); + String location = Path.fixPath(ctx + path); + response.sendRedirect(location); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public boolean isWritten() { + return written; + } + +} diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java b/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java index aa51f7591..e1358bc5f 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java @@ -25,7 +25,7 @@ * HttpSession Wrapper * * @author biezhi - * @since 1.0 + * @since 1.5 */ public class Session { diff --git a/blade-core/src/main/java/com/blade/web/multipart/FileItem.java b/blade-core/src/main/java/com/blade/web/multipart/FileItem.java index 3b82b8fc7..2d24ed72f 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/FileItem.java +++ b/blade-core/src/main/java/com/blade/web/multipart/FileItem.java @@ -1,78 +1,78 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.multipart; - -import java.io.File; -import java.util.HashMap; -import java.util.Map; - -/** - * HTTP multipart/form-data Request - * - * @author biezhi - * @since 1.0 - */ -public class FileItem { - - private String name; - - private String fileName; - - private String contentType; - - private long contentLength; - - private File file; - - private Map headers; - - public FileItem(String fieldName, String fileName, String contentType, long contentLength, File file, Map headers) { - - this.fileName = fileName; - this.contentType = contentType; - this.contentLength = contentLength; - this.file = file; - this.headers = headers; - if (headers == null) { - this.headers = new HashMap(); - } - } - - public String getName() { - return name; - } - - public String getFileName() { - return fileName; - } - - public String getContentType() { - return contentType; - } - - public long getContentLength() { - return contentLength; - } - - public File getFile() { - return file; - } - - public Map getHeaders() { - return headers; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.multipart; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +/** + * HTTP multipart/form-data Request + * + * @author biezhi + * @since 1.5 + */ +public class FileItem { + + private String name; + + private String fileName; + + private String contentType; + + private long contentLength; + + private File file; + + private Map headers; + + public FileItem(String fieldName, String fileName, String contentType, long contentLength, File file, Map headers) { + + this.fileName = fileName; + this.contentType = contentType; + this.contentLength = contentLength; + this.file = file; + this.headers = headers; + if (headers == null) { + this.headers = new HashMap(); + } + } + + public String getName() { + return name; + } + + public String getFileName() { + return fileName; + } + + public String getContentType() { + return contentType; + } + + public long getContentLength() { + return contentLength; + } + + public File getFile() { + return file; + } + + public Map getHeaders() { + return headers; + } + +} diff --git a/blade-core/src/main/java/com/blade/web/multipart/Multipart.java b/blade-core/src/main/java/com/blade/web/multipart/Multipart.java index 3e33c72f3..24a6671e4 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/Multipart.java +++ b/blade-core/src/main/java/com/blade/web/multipart/Multipart.java @@ -1,327 +1,327 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.multipart; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; - -import com.blade.kit.IOKit; - -/** - * Multipart - * - * @author biezhi - * @since 1.0 - */ -public class Multipart { - - public static final String CONTENT_TYPE = "Content-Type"; - - public static final String CONTENT_DISPOSITION = "Content-Disposition"; - - public static final String CONTENT_LENGTH = "Content-Length"; - - public static final String FORM_DATA = "form-data"; - - public static final String ATTACHMENT = "attachment"; - - public static final String MULTIPART = "multipart/"; - - public static final String MULTIPART_MIXED = "multipart/mixed"; - - public static boolean isMultipartContent(HttpServletRequest request) { - if (!"post".equals(request.getMethod().toLowerCase())) { - return false; - } - - String contentType = request.getContentType(); - if (contentType == null) { - return false; - } - if (contentType.toLowerCase().startsWith(MULTIPART)) { - return true; - } - - return false; - } - - public void parse(HttpServletRequest request, MultipartHandler partHandler) throws IOException, MultipartException { - if (!isMultipartContent(request)) { - throw new MultipartException("Not a multipart content. The HTTP method should be 'POST' and the " + - "Content-Type 'multipart/form-data' or 'multipart/mixed'."); - } - - InputStream inputStream = request.getInputStream(); - - String contentType = request.getContentType(); - String charEncoding = request.getCharacterEncoding(); - - byte[] boundary = getBoundary(contentType); - if (boundary == null) { - throw new MultipartException("the request was rejected because no multipart boundary was found"); - } - - // create a multipart reader - MultipartReader multipartReader = new MultipartReader(inputStream, boundary); - multipartReader.setHeaderEncoding(charEncoding); - - String currentFieldName = null; - boolean skipPreamble = true; - - for (;;) { - boolean nextPart; - if (skipPreamble) { - nextPart = multipartReader.skipPreamble(); - } else { - nextPart = multipartReader.readBoundary(); - } - if (!nextPart) { - if (currentFieldName == null) { - // outer multipart terminated -> no more data - return; - } - // inner multipart terminated -> return to parsing the outer - multipartReader.setBoundary(boundary); - currentFieldName = null; - continue; - } - - String headersString = multipartReader.readHeaders(); - Map headers = getHeadersMap(headersString); - - if (currentFieldName == null) { - - // we're parsing the outer multipart - String fieldName = getFieldName( headers.get(CONTENT_DISPOSITION) ); - if (fieldName != null) { - - String partContentType = headers.get(CONTENT_TYPE); - if (partContentType != null && partContentType.toLowerCase().startsWith(MULTIPART_MIXED)) { - - // multiple files associated with this field name - currentFieldName = fieldName; - multipartReader.setBoundary( getBoundary(partContentType)); - skipPreamble = true; - - continue; - } - - String fileName = getFileName( headers.get(CONTENT_DISPOSITION) ); - if (fileName == null) { - // call the part handler - String value = IOKit.toString(multipartReader.newInputStream()); - partHandler.handleFormItem(fieldName, value); - } else { - - // create the temp file - File tempFile = createTempFile(multipartReader); - - // call the part handler - FileItem fileItem = new FileItem(fieldName, fileName, partContentType, tempFile.length(), tempFile, headers); - partHandler.handleFileItem(fieldName, fileItem); - } - - continue; - } - } else { - String fileName = getFileName( headers.get(CONTENT_DISPOSITION) ); - String partContentType = headers.get(CONTENT_TYPE); - if (fileName != null) { - - // create the temp file - File tempFile = createTempFile(multipartReader); - - // call the part handler - FileItem fileItem = new FileItem(currentFieldName, fileName, partContentType, tempFile.length(), - tempFile, headers); - partHandler.handleFileItem(currentFieldName, fileItem); - continue; - } - } - multipartReader.discardBodyData(); - } - - } - - private File createTempFile(MultipartReader multipartReader) throws IOException { - File tempFile = File.createTempFile("com.blade.file_", null); - FileOutputStream outputStream = null; - try { - outputStream = new FileOutputStream(tempFile); - copy( multipartReader.newInputStream(), outputStream ); - } finally { - if (outputStream != null) { - try { outputStream.close(); } catch (Exception e) {} - } - } - - return tempFile; - } - - private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; - private static final int EOF = -1; - - private long copy(InputStream input, OutputStream output) throws IOException { - long count = 0; - int n = 0; - byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; - while (EOF != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; - } - - protected Map getHeadersMap(String headerPart) { - final int len = headerPart.length(); - final Map headers = new HashMap(); - - int start = 0; - for (;;) { - int end = parseEndOfLine(headerPart, start); - if (start == end) { - break; - } - String header = headerPart.substring(start, end); - start = end + 2; - while (start < len) { - int nonWs = start; - while (nonWs < len) { - char c = headerPart.charAt(nonWs); - if (c != ' ' && c != '\t') { - break; - } - ++nonWs; - } - if (nonWs == start) { - break; - } - // continuation line found - end = parseEndOfLine(headerPart, nonWs); - header += " " + headerPart.substring(nonWs, end); - start = end + 2; - } - - // parse header line - final int colonOffset = header.indexOf(':'); - if (colonOffset == -1) { - // this header line is malformed, skip it. - continue; - } - String headerName = header.substring(0, colonOffset).trim(); - String headerValue = header.substring(header.indexOf(':') + 1).trim(); - - if (headers.containsKey(headerName)) { - headers.put( headerName, headers.get(headerName) + "," + headerValue ); - } else { - headers.put(headerName, headerValue); - } - } - - return headers; - } - - private int parseEndOfLine(String headerPart, int end) { - int index = end; - for (;;) { - int offset = headerPart.indexOf('\r', index); - if (offset == -1 || offset + 1 >= headerPart.length()) { - throw new IllegalStateException("Expected headers to be terminated by an empty line."); - } - if (headerPart.charAt(offset + 1) == '\n') { - return offset; - } - index = offset + 1; - } - } - - private String getFieldName(String contentDisposition) { - String fieldName = null; - - if (contentDisposition != null && contentDisposition.toLowerCase().startsWith(FORM_DATA)) { - ParameterParser parser = new ParameterParser(); - parser.setLowerCaseNames(true); - - // parameter parser can handle null input - Map params = parser.parse(contentDisposition, ';'); - fieldName = (String) params.get("name"); - if (fieldName != null) { - fieldName = fieldName.trim(); - } - } - - return fieldName; - } - - protected byte[] getBoundary(String contentType) { - ParameterParser parser = new ParameterParser(); - parser.setLowerCaseNames(true); - // Parameter parser can handle null input - Map params = parser.parse(contentType, new char[] {';', ','}); - String boundaryStr = (String) params.get("boundary"); - - if (boundaryStr == null) { - return null; - } - - byte[] boundary; - try { - boundary = boundaryStr.getBytes("ISO-8859-1"); - } catch (UnsupportedEncodingException e) { - boundary = boundaryStr.getBytes(); - } - return boundary; - } - - private String getFileName(String contentDisposition) { - String fileName = null; - - if (contentDisposition != null) { - String cdl = contentDisposition.toLowerCase(); - - if (cdl.startsWith(FORM_DATA) || cdl.startsWith(ATTACHMENT)) { - - ParameterParser parser = new ParameterParser(); - parser.setLowerCaseNames(true); - - // parameter parser can handle null input - Map params = parser.parse(contentDisposition, ';'); - if (params.containsKey("filename")) { - fileName = (String) params.get("filename"); - if (fileName != null) { - fileName = fileName.trim(); - } else { - // even if there is no value, the parameter is present, - // so we return an empty file name rather than no file - // name. - fileName = ""; - } - } - } - } - - return fileName; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.multipart; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import com.blade.kit.IOKit; + +/** + * Multipart + * + * @author biezhi + * @since 1.5 + */ +public class Multipart { + + public static final String CONTENT_TYPE = "Content-Type"; + + public static final String CONTENT_DISPOSITION = "Content-Disposition"; + + public static final String CONTENT_LENGTH = "Content-Length"; + + public static final String FORM_DATA = "form-data"; + + public static final String ATTACHMENT = "attachment"; + + public static final String MULTIPART = "multipart/"; + + public static final String MULTIPART_MIXED = "multipart/mixed"; + + public static boolean isMultipartContent(HttpServletRequest request) { + if (!"post".equals(request.getMethod().toLowerCase())) { + return false; + } + + String contentType = request.getContentType(); + if (contentType == null) { + return false; + } + if (contentType.toLowerCase().startsWith(MULTIPART)) { + return true; + } + + return false; + } + + public void parse(HttpServletRequest request, MultipartHandler partHandler) throws IOException, MultipartException { + if (!isMultipartContent(request)) { + throw new MultipartException("Not a multipart content. The HTTP method should be 'POST' and the " + + "Content-Type 'multipart/form-data' or 'multipart/mixed'."); + } + + InputStream inputStream = request.getInputStream(); + + String contentType = request.getContentType(); + String charEncoding = request.getCharacterEncoding(); + + byte[] boundary = getBoundary(contentType); + if (boundary == null) { + throw new MultipartException("the request was rejected because no multipart boundary was found"); + } + + // create a multipart reader + MultipartReader multipartReader = new MultipartReader(inputStream, boundary); + multipartReader.setHeaderEncoding(charEncoding); + + String currentFieldName = null; + boolean skipPreamble = true; + + for (;;) { + boolean nextPart; + if (skipPreamble) { + nextPart = multipartReader.skipPreamble(); + } else { + nextPart = multipartReader.readBoundary(); + } + if (!nextPart) { + if (currentFieldName == null) { + // outer multipart terminated -> no more data + return; + } + // inner multipart terminated -> return to parsing the outer + multipartReader.setBoundary(boundary); + currentFieldName = null; + continue; + } + + String headersString = multipartReader.readHeaders(); + Map headers = getHeadersMap(headersString); + + if (currentFieldName == null) { + + // we're parsing the outer multipart + String fieldName = getFieldName( headers.get(CONTENT_DISPOSITION) ); + if (fieldName != null) { + + String partContentType = headers.get(CONTENT_TYPE); + if (partContentType != null && partContentType.toLowerCase().startsWith(MULTIPART_MIXED)) { + + // multiple files associated with this field name + currentFieldName = fieldName; + multipartReader.setBoundary( getBoundary(partContentType)); + skipPreamble = true; + + continue; + } + + String fileName = getFileName( headers.get(CONTENT_DISPOSITION) ); + if (fileName == null) { + // call the part handler + String value = IOKit.toString(multipartReader.newInputStream()); + partHandler.handleFormItem(fieldName, value); + } else { + + // create the temp file + File tempFile = createTempFile(multipartReader); + + // call the part handler + FileItem fileItem = new FileItem(fieldName, fileName, partContentType, tempFile.length(), tempFile, headers); + partHandler.handleFileItem(fieldName, fileItem); + } + + continue; + } + } else { + String fileName = getFileName( headers.get(CONTENT_DISPOSITION) ); + String partContentType = headers.get(CONTENT_TYPE); + if (fileName != null) { + + // create the temp file + File tempFile = createTempFile(multipartReader); + + // call the part handler + FileItem fileItem = new FileItem(currentFieldName, fileName, partContentType, tempFile.length(), + tempFile, headers); + partHandler.handleFileItem(currentFieldName, fileItem); + continue; + } + } + multipartReader.discardBodyData(); + } + + } + + private File createTempFile(MultipartReader multipartReader) throws IOException { + File tempFile = File.createTempFile("com.blade.file_", null); + FileOutputStream outputStream = null; + try { + outputStream = new FileOutputStream(tempFile); + copy( multipartReader.newInputStream(), outputStream ); + } finally { + if (outputStream != null) { + try { outputStream.close(); } catch (Exception e) {} + } + } + + return tempFile; + } + + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + private static final int EOF = -1; + + private long copy(InputStream input, OutputStream output) throws IOException { + long count = 0; + int n = 0; + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + protected Map getHeadersMap(String headerPart) { + final int len = headerPart.length(); + final Map headers = new HashMap(); + + int start = 0; + for (;;) { + int end = parseEndOfLine(headerPart, start); + if (start == end) { + break; + } + String header = headerPart.substring(start, end); + start = end + 2; + while (start < len) { + int nonWs = start; + while (nonWs < len) { + char c = headerPart.charAt(nonWs); + if (c != ' ' && c != '\t') { + break; + } + ++nonWs; + } + if (nonWs == start) { + break; + } + // continuation line found + end = parseEndOfLine(headerPart, nonWs); + header += " " + headerPart.substring(nonWs, end); + start = end + 2; + } + + // parse header line + final int colonOffset = header.indexOf(':'); + if (colonOffset == -1) { + // this header line is malformed, skip it. + continue; + } + String headerName = header.substring(0, colonOffset).trim(); + String headerValue = header.substring(header.indexOf(':') + 1).trim(); + + if (headers.containsKey(headerName)) { + headers.put( headerName, headers.get(headerName) + "," + headerValue ); + } else { + headers.put(headerName, headerValue); + } + } + + return headers; + } + + private int parseEndOfLine(String headerPart, int end) { + int index = end; + for (;;) { + int offset = headerPart.indexOf('\r', index); + if (offset == -1 || offset + 1 >= headerPart.length()) { + throw new IllegalStateException("Expected headers to be terminated by an empty line."); + } + if (headerPart.charAt(offset + 1) == '\n') { + return offset; + } + index = offset + 1; + } + } + + private String getFieldName(String contentDisposition) { + String fieldName = null; + + if (contentDisposition != null && contentDisposition.toLowerCase().startsWith(FORM_DATA)) { + ParameterParser parser = new ParameterParser(); + parser.setLowerCaseNames(true); + + // parameter parser can handle null input + Map params = parser.parse(contentDisposition, ';'); + fieldName = (String) params.get("name"); + if (fieldName != null) { + fieldName = fieldName.trim(); + } + } + + return fieldName; + } + + protected byte[] getBoundary(String contentType) { + ParameterParser parser = new ParameterParser(); + parser.setLowerCaseNames(true); + // Parameter parser can handle null input + Map params = parser.parse(contentType, new char[] {';', ','}); + String boundaryStr = (String) params.get("boundary"); + + if (boundaryStr == null) { + return null; + } + + byte[] boundary; + try { + boundary = boundaryStr.getBytes("ISO-8859-1"); + } catch (UnsupportedEncodingException e) { + boundary = boundaryStr.getBytes(); + } + return boundary; + } + + private String getFileName(String contentDisposition) { + String fileName = null; + + if (contentDisposition != null) { + String cdl = contentDisposition.toLowerCase(); + + if (cdl.startsWith(FORM_DATA) || cdl.startsWith(ATTACHMENT)) { + + ParameterParser parser = new ParameterParser(); + parser.setLowerCaseNames(true); + + // parameter parser can handle null input + Map params = parser.parse(contentDisposition, ';'); + if (params.containsKey("filename")) { + fileName = (String) params.get("filename"); + if (fileName != null) { + fileName = fileName.trim(); + } else { + // even if there is no value, the parameter is present, + // so we return an empty file name rather than no file + // name. + fileName = ""; + } + } + } + } + + return fileName; + } + +} diff --git a/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java b/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java index 9fdc1ebc6..a4a251fac 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java +++ b/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java @@ -20,7 +20,7 @@ * MultipartException * * @author biezhi - * @since 1.0 + * @since 1.5 */ public class MultipartException extends Exception { diff --git a/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java b/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java index f564ccb41..6e8b68d27 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java +++ b/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java @@ -19,7 +19,7 @@ * MultipartHandler * * @author biezhi - * @since 1.0 + * @since 1.5 */ public interface MultipartHandler { From 711f69c7fb797b72f51e6e6eb839d544d0a369b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5nice?= Date: Thu, 1 Sep 2016 23:07:02 +0800 Subject: [PATCH 476/545] Update README_CN.md --- README_CN.md | 66 ++++++++++++++++------------------------------------ 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/README_CN.md b/README_CN.md index 0cc24e7da..3f73845fb 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,32 +1,35 @@ [![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) +[开始使用](https://bladejava.com/docs)  |  [示例项目](https://github.com/blade-samples)  |  [贡献代码](https://bladejava.com/docs/appendix/contribute)  |  [捐赠](#)  |  [FAQ](https://bladejava.com/docs/faqs) |  [English](https://github.com/biezhi/blade/blob/master/README.md) + [![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) [![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) [![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) -[English](https://github.com/biezhi/blade/blob/master/README.md) - ## Blade是什么? -Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计。 -如果你喜欢,欢迎 [Star and Fork](https://github.com/biezhi/blade), 谢谢! +Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁的代码,优雅的设计。 + +如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush:! ## 特性 -* [x] 轻量级。代码简洁,结构清晰,更容易开发 +* [x] 轻量级, 代码简洁,结构清晰,更容易开发 * [x] 模块化(你可以选择使用哪些组件) * [x] 插件扩展机制 * [x] Restful风格的路由接口 * [x] 多种配置文件支持(当前支持properties、json和硬编码) -* [x] 内置Jetty服务,模板引擎支持 -* [x] 支持JDK1.6或者更高版本 +* [x] 多种模板引擎支持 +* [x] 更方便的启动和部署 +* [x] 支持JDK1.6或者更高版本(JDK8写起来更爽) ## 概述 * 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 -* 优雅的:`blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 +* 优雅的:`Blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 +* 易部署:支持 `maven` 打成 `jar` 包直接运行。 ## 快速入门 @@ -51,7 +54,7 @@ Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计 ```sh compile 'com.bladejava:blade-core:1.6.6-alpha' -compile 'com.bladejava:blade-startup:0.0.1' +compile 'com.bladejava:blade-embed-jetty:0.0.3' ``` 编写 `Main`函数: @@ -60,8 +63,7 @@ compile 'com.bladejava:blade-startup:0.0.1' public static void main(String[] args) { $().get("/", (request, response) -> { response.html("

Hello blade!

"); - }); - $().start(EmbedJettyServer.class); + }).start(Application.class); } ``` @@ -75,7 +77,6 @@ public static void main(String[] args) { $().post("/save", postxxx); $().delete("/del/21", deletexxx); $().put("/put", putxxx); - $().start(EmbedJettyServer.class); } ``` @@ -95,7 +96,7 @@ public static void main(String[] args) { response.text(msg); }); - $().start(EmbedJettyServer.class); + $().start(Application.class); } ``` @@ -106,8 +107,7 @@ public static void main(String[] args) { $().get("/user", (request, response) -> { Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); - }); - $().start(EmbedJettyServer.class); + }).start(Application.class); } ``` @@ -147,43 +147,18 @@ POST /upload_img UploadRoute.upload_img public static void main(String[] args) { $().before("/.*", (request, response) -> { System.out.println("before..."); - }); - $().start(EmbedJettyServer.class); + }).start(Application.class); } ``` -## DSL数据库操作 - -```java -// query -List posts = - AR.find("where title like ? order by id desc limit ?,?", title, page, count).list(Post.class); - -// save -String insertSql = "insert into t_post (title, content, view_count, create_time) values (?,?,?,?)"; -AR.update(insertSql, title, content, 0, new Date()).commit(); -// update -AR.update("update t_post set title = ? and content = ? where id = ?",title, content, id).commit(); - -// delete -AR.update("delete from t_post where id = ?",id).commit() -``` - -OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: +这一切看起来多么的简单,不过上面的功能可是冰山一角,查看文档和示例项目有更多惊喜: + [hello工程](https://github.com/blade-samples/hello) -+ [论坛程序](http://java-china.org) -+ [API文档](http://bladejava.com/apidocs) -+ [使用指南](http://bladejava.com/docs) -+ [相关案例](https://github.com/blade-samples) -+ [版本查询](LAST_VERSION.md) - -### 计划 ++ [论坛程序](https://github.com/junicorn/java-china) ++ [文档服务](https://github.com/biezhi/grice) ++ [更多例子](https://github.com/blade-samples) -- 1. 添加测试代码 -- 2. 优化基础代码 -- 3. 优化并发能力 ## 更新日志 @@ -212,4 +187,3 @@ OK,这一切看起来多么的简单,查阅使用指南更多现成的例子 ## 开源协议 请查看 [Apache License](LICENSE) - From 710dd4100564f9da8c142f9835249894baf011e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=88=B5nice?= Date: Thu, 1 Sep 2016 23:08:28 +0800 Subject: [PATCH 477/545] => update readme --- README_CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_CN.md b/README_CN.md index 3f73845fb..dc4b2be65 100644 --- a/README_CN.md +++ b/README_CN.md @@ -12,7 +12,7 @@ Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁的代码,优雅的设计。 -如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush:! +如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush: ## 特性 From 118b18334b91c66776ed9cca3a149cece8319841 Mon Sep 17 00:00:00 2001 From: biezhi Date: Thu, 1 Sep 2016 23:16:18 +0800 Subject: [PATCH 478/545] => update readme --- README.md | 379 +++++++++++++++++++++++------------------------ README_CN.md | 404 ++++++++++++++++++++++++--------------------------- 2 files changed, 372 insertions(+), 411 deletions(-) diff --git a/README.md b/README.md index 22b9892f0..966ff2836 100644 --- a/README.md +++ b/README.md @@ -1,196 +1,183 @@ - -[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) - -[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - -[中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) - -## What Is Blade? - -Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. -If you like it, please [star and fork it](https://github.com/biezhi/blade). Thank you! - -## Features - -* [x] Lightweight: the code is simple and the structure is clear -* [x] Modular (you can choose which components to use) -* [x] Supports plug-in extension mechanism -* [x] RESTful style routing interface -* [x] Supports multiple configuration files (currently properties, json and coding) -* [x] Embedded jetty server and template engine support -* [x] Supports JDK 1.6 and up - -## Overview - -* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. -* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. - -## Get Start - -To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : - -Grab via `Maven`: - -```xml - - com.bladejava - blade-core - 1.6.6-alpha - - - com.bladejava - blade-embed-jetty - 0.0.3 - -``` -or `Gradle`: -```sh -compile 'com.bladejava:blade-core:1.6.6-alpha' -compile 'com.bladejava:blade-embed-jetty:0.0.3' -``` - -Create `Main` method like this: - -```java -public class App { - - public static void main(String[] args) { - $().get("/", (request, response) -> { - response.html("

Hello blade!

"); - }); - $().start(EmbedJettyServer.class); - } -} -``` - -Run it and point your browser to [http://localhost:9000](http://localhost:9000). There you go, you've just created your first Blade app! - -## API Example - -```java -public static void main(String[] args) { - $().get("/user/21", getxxx); - $().post("/save", postxxx); - $().delete("/del/21", deletexxx); - $().put("/put", putxxx); - $().start(EmbedJettyServer.class); -} -``` - -## REST URL Parameters - -```java -public static void main(String[] args) { - $().get("/user/:uid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - response.text("uid : " + uid); - }); - - $().get("/users/:uid/post/:pid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - Integer pid = request.paramAsInt("pid"); - String msg = "uid = " + uid + ", pid = " + pid; - response.text(msg); - }); - - $().start(EmbedJettyServer.class); -} -``` - -## Form URL Parameters - -```java -public static void main(String[] args) { - $().get("/user", (request, response) -> { - Integer uid = request.queryAsInt("uid"); - response.text("uid : " + uid); - }); - $().start(EmbedJettyServer.class); -} -``` - -## Upload File - -```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; - File file = fileItem.getFile(); - - String fileRealPath = "your upload file path!"; - - nioTransferCopy(file, fileRealPath); - } -} -``` - -## Route Config File - -`route.conf` - -```sh -GET / IndexRoute.home -GET /signin IndexRoute.show_signin -POST /signin IndexRoute.signin -GET /signout IndexRoute.signout -POST /upload_img UploadRoute.upload_img -``` - -## Route Intercept - -```java -public static void main(String[] args) { - $().before("/.*", (request, response) -> { - System.out.println("before..."); - }); - $().start(EmbedJettyServer.class); -} -``` - -You may refer to these examples for additional guidance: - -+ [Hello Blade](https://github.com/blade-samples/hello) -+ [BBS WebSite](http://java-china.org) -+ [API Doc](http://bladejava.com/apidocs) -+ [User Guide](http://bladejava.com/docs) -+ [Version Changes](LAST_VERSION.md) -+ [Examples](https://github.com/blade-samples) - -## Plan - -- 1. Add the test code -- 2. Optimize the code base -- 3. Optimization of concurrent ability - -## Update - -[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## Contact - -- Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me@gmail.com - -## Contributor - -Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! - -- [mfarid](https://github.com/mfarid) -- [daimajia](https://github.com/daimajia) -- [shenjie1993](https://github.com/shenjie1993) -- [sumory](https://github.com/sumory) -- [udaykadaboina](https://github.com/udaykadaboina) -- [SyedWasiHaider](https://github.com/SyedWasiHaider) -- [Awakens](https://github.com/Awakens) -- [shellac](https://github.com/shellac) -- [SudarAbisheck](https://github.com/SudarAbisheck) - -## Licenses - -Please see [Apache License](LICENSE) + +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) + +[Quick Start](https://bladejava.com/docs)  |  [Demo Project](https://github.com/blade-samples)  |  [Contribute](https://bladejava.com/docs/appendix/contribute)  |  [Donate]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) + +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + + +## What Is Blade? + +Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. +If you like it, please [star and fork it](https://github.com/biezhi/blade). Thank you! + +## Features + +* [x] Lightweight: the code is simple and the structure is clear +* [x] Modular (you can choose which components to use) +* [x] Supports plug-in extension mechanism +* [x] RESTful style routing interface +* [x] Supports multiple configuration files (currently properties, json and coding) +* [x] Embedded jetty server and template engine support +* [x] Supports JDK 1.6 and up + +## Overview + +* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. +* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. + +## Get Start + +To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : + +Grab via `Maven`: + +```xml + + com.bladejava + blade-core + 1.6.6-alpha + + + com.bladejava + blade-embed-jetty + 0.0.3 + +``` +or `Gradle`: +```sh +compile 'com.bladejava:blade-core:1.6.6-alpha' +compile 'com.bladejava:blade-embed-jetty:0.0.3' +``` + +Create `Main` method like this: + +```java +public static void main(String[] args) { + $().get("/", (request, response) -> { + response.html("

Hello blade!

"); + }).start(Application.class); +} +``` + +Run it and point your browser to [http://localhost:9000](http://localhost:9000). There you go, you've just created your first Blade app! + +## API Example + +```java +public static void main(String[] args) { + $().get("/user/21", getxxx); + $().post("/save", postxxx); + $().delete("/del/21", deletexxx); + $().put("/put", putxxx); +} +``` + +## REST URL Parameters + +```java +public static void main(String[] args) { + $().get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + $().get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + $().start(Application.class); +} +``` + +## Form URL Parameters + +```java +public static void main(String[] args) { + $().get("/user", (request, response) -> { + Integer uid = request.queryAsInt("uid"); + response.text("uid : " + uid); + }).start(Application.class); +} +``` + +## Upload File + +```java +public void upload_img(Request request, Response response){ + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## Route Config File + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## Route Intercept + +```java +public static void main(String[] args) { + $().before("/.*", (request, response) -> { + System.out.println("before..."); + }).start(Application.class); +} +``` + +You may refer to these examples for additional guidance: + ++ [Hello Blade](https://github.com/blade-samples/hello) ++ [BBS WebSite](https://github.com/junicorn/java-china) ++ [Doc Service](https://github.com/biezhi/grice) ++ [More Examples](https://github.com/blade-samples) + + +## Update + +[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## Contact + +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me@gmail.com + +## Contributor + +Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! + +- [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) + +## Licenses + +Please see [Apache License](LICENSE) diff --git a/README_CN.md b/README_CN.md index 0cc24e7da..6c177bc4d 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,215 +1,189 @@ - -[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) - -[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) - -[English](https://github.com/biezhi/blade/blob/master/README.md) - -## Blade是什么? - -Blade 是一个轻量级的MVC框架. 它拥有简洁的代码,优雅的设计。 -如果你喜欢,欢迎 [Star and Fork](https://github.com/biezhi/blade), 谢谢! - -## 特性 - -* [x] 轻量级。代码简洁,结构清晰,更容易开发 -* [x] 模块化(你可以选择使用哪些组件) -* [x] 插件扩展机制 -* [x] Restful风格的路由接口 -* [x] 多种配置文件支持(当前支持properties、json和硬编码) -* [x] 内置Jetty服务,模板引擎支持 -* [x] 支持JDK1.6或者更高版本 - -## 概述 - -* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 -* 优雅的:`blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 - -## 快速入门 - -开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : - -`Maven` 配置: - -```xml - - com.bladejava - blade-core - 1.6.6-alpha - - - com.bladejava - blade-embed-jetty - 0.0.3 - -``` - -或者 `Gradle`: - -```sh -compile 'com.bladejava:blade-core:1.6.6-alpha' -compile 'com.bladejava:blade-startup:0.0.1' -``` - -编写 `Main`函数: - -```java -public static void main(String[] args) { - $().get("/", (request, response) -> { - response.html("

Hello blade!

"); - }); - $().start(EmbedJettyServer.class); -} -``` - -用浏览器打开 http://localhost:9001 这样就可以看到第一个Blade应用了! - -## API示例 - -```java -public static void main(String[] args) { - $().get("/user/21", getxxx); - $().post("/save", postxxx); - $().delete("/del/21", deletexxx); - $().put("/put", putxxx); - $().start(EmbedJettyServer.class); -} -``` - -## REST URL参数获取 - -```java -public static void main(String[] args) { - $().get("/user/:uid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - response.text("uid : " + uid); - }); - - $().get("/users/:uid/post/:pid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - Integer pid = request.paramAsInt("pid"); - String msg = "uid = " + uid + ", pid = " + pid; - response.text(msg); - }); - - $().start(EmbedJettyServer.class); -} -``` - -## 表单参数获取 - -```java -public static void main(String[] args) { - $().get("/user", (request, response) -> { - Integer uid = request.queryAsInt("uid"); - response.text("uid : " + uid); - }); - $().start(EmbedJettyServer.class); -} -``` - -## 上传文件 - -```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; - File file = fileItem.getFile(); - - String fileRealPath = "your upload file path!"; - - nioTransferCopy(file, fileRealPath); - } -} -``` - -## 配置文件路由 - -`route.conf` - -```sh -GET / IndexRoute.home -GET /signin IndexRoute.show_signin -POST /signin IndexRoute.signin -GET /signout IndexRoute.signout -POST /upload_img UploadRoute.upload_img -``` - -## 路由拦截 - -```java -public static void main(String[] args) { - $().before("/.*", (request, response) -> { - System.out.println("before..."); - }); - $().start(EmbedJettyServer.class); -} -``` - -## DSL数据库操作 - -```java -// query -List posts = - AR.find("where title like ? order by id desc limit ?,?", title, page, count).list(Post.class); - -// save -String insertSql = "insert into t_post (title, content, view_count, create_time) values (?,?,?,?)"; -AR.update(insertSql, title, content, 0, new Date()).commit(); - -// update -AR.update("update t_post set title = ? and content = ? where id = ?",title, content, id).commit(); - -// delete -AR.update("delete from t_post where id = ?",id).commit() -``` - -OK,这一切看起来多么的简单,查阅使用指南更多现成的例子供你参考: - -+ [hello工程](https://github.com/blade-samples/hello) -+ [论坛程序](http://java-china.org) -+ [API文档](http://bladejava.com/apidocs) -+ [使用指南](http://bladejava.com/docs) -+ [相关案例](https://github.com/blade-samples) -+ [版本查询](LAST_VERSION.md) - -### 计划 - -- 1. 添加测试代码 -- 2. 优化基础代码 -- 3. 优化并发能力 - -## 更新日志 - -[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## 联系我 - -- Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me#gmail.com -- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) - -## 贡献 - -非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! - -- [mfarid](https://github.com/mfarid) -- [daimajia](https://github.com/daimajia) -- [shenjie1993](https://github.com/shenjie1993) -- [sumory](https://github.com/sumory) -- [udaykadaboina](https://github.com/udaykadaboina) -- [SyedWasiHaider](https://github.com/SyedWasiHaider) -- [Awakens](https://github.com/Awakens) -- [shellac](https://github.com/shellac) -- [SudarAbisheck](https://github.com/SudarAbisheck) - -## 开源协议 - -请查看 [Apache License](LICENSE) - + +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) + +[开始使用](https://bladejava.com/docs)  |  [示例项目](https://github.com/blade-samples)  |  [贡献代码](https://bladejava.com/docs/appendix/contribute)  |  [捐赠]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [English](https://github.com/biezhi/blade/blob/master/README.md) + +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) + +## Blade是什么? + +Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁的代码,优雅的设计。 + +如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush: + +## 特性 + +* [x] 轻量级, 代码简洁,结构清晰,更容易开发 +* [x] 模块化(你可以选择使用哪些组件) +* [x] 插件扩展机制 +* [x] Restful风格的路由接口 +* [x] 多种配置文件支持(当前支持properties、json和硬编码) +* [x] 多种模板引擎支持 +* [x] 更方便的启动和部署 +* [x] 支持JDK1.6或者更高版本(JDK8写起来更爽) + +## 概述 + +* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 +* 优雅的:`Blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 +* 易部署:支持 `maven` 打成 `jar` 包直接运行。 + +## 快速入门 + +开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : + +`Maven` 配置: + +```xml + + com.bladejava + blade-core + 1.6.6-alpha + + + com.bladejava + blade-embed-jetty + 0.0.3 + +``` + +或者 `Gradle`: + +```sh +compile 'com.bladejava:blade-core:1.6.6-alpha' +compile 'com.bladejava:blade-embed-jetty:0.0.3' +``` + +编写 `Main`函数: + +```java +public static void main(String[] args) { + $().get("/", (request, response) -> { + response.html("

Hello blade!

"); + }).start(Application.class); +} +``` + +用浏览器打开 http://localhost:9000 这样就可以看到第一个Blade应用了! + +## API示例 + +```java +public static void main(String[] args) { + $().get("/user/21", getxxx); + $().post("/save", postxxx); + $().delete("/del/21", deletexxx); + $().put("/put", putxxx); +} +``` + +## REST URL参数获取 + +```java +public static void main(String[] args) { + $().get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + $().get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + $().start(Application.class); +} +``` + +## 表单参数获取 + +```java +public static void main(String[] args) { + $().get("/user", (request, response) -> { + Integer uid = request.queryAsInt("uid"); + response.text("uid : " + uid); + }).start(Application.class); +} +``` + +## 上传文件 + +```java +public void upload_img(Request request, Response response){ + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## 配置文件路由 + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## 路由拦截 + +```java +public static void main(String[] args) { + $().before("/.*", (request, response) -> { + System.out.println("before..."); + }).start(Application.class); +} +``` + + +这一切看起来多么的简单,不过上面的功能可是冰山一角,查看文档和示例项目有更多惊喜: + ++ [hello工程](https://github.com/blade-samples/hello) ++ [论坛程序](https://github.com/junicorn/java-china) ++ [文档服务](https://github.com/biezhi/grice) ++ [更多例子](https://github.com/blade-samples) + + +## 更新日志 + +[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## 联系我 + +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me#gmail.com +- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) + +## 贡献 + +非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! + +- [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) + +## 开源协议 + +请查看 [Apache License](LICENSE) From ef26c7e0c6dc67b7d7052ef11c76dead811afe19 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 2 Sep 2016 09:49:07 +0800 Subject: [PATCH 479/545] => remove redundant design and add config order --- blade-core/src/main/java/com/blade/Blade.java | 1534 ++++++++--------- .../java/com/blade/{web => }/BladeBanner.java | 4 +- blade-core/src/main/java/com/blade/Const.java | 108 +- .../java/com/blade/annotation/Intercept.java | 79 +- .../JSONView.java => annotation/Order.java} | 75 +- .../com/blade/comparator/OrderComparator.java | 23 + .../java/com/blade/ioc/IocApplication.java | 38 +- .../java/com/blade/view/ViewSettings.java | 80 + .../blade/view/handle/RouteViewHandler.java | 215 +-- .../java/com/blade/web/DispatcherHandler.java | 410 ++--- .../java/com/blade/web/DispatcherServlet.java | 307 ++-- .../main/java/com/blade/kit/Environment.java | 1 - pom.xml | 182 +- 13 files changed, 1575 insertions(+), 1481 deletions(-) rename blade-core/src/main/java/com/blade/{web => }/BladeBanner.java (86%) rename blade-core/src/main/java/com/blade/{view/parser/JSONView.java => annotation/Order.java} (57%) create mode 100644 blade-core/src/main/java/com/blade/comparator/OrderComparator.java create mode 100644 blade-core/src/main/java/com/blade/view/ViewSettings.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 5697bee43..110ce5a26 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -1,778 +1,758 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.io.InputStream; -import java.text.ParseException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.blade.config.ApplicationConfig; -import com.blade.config.BaseConfig; -import com.blade.config.ConfigLoader; -import com.blade.embedd.EmbedServer; -import com.blade.exception.EmbedServerException; -import com.blade.interceptor.Interceptor; -import com.blade.ioc.Ioc; -import com.blade.ioc.SimpleIoc; -import com.blade.kit.Assert; -import com.blade.kit.Environment; -import com.blade.kit.StringKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.plugin.Plugin; -import com.blade.route.Route; -import com.blade.route.RouteBuilder; -import com.blade.route.RouteException; -import com.blade.route.RouteGroup; -import com.blade.route.RouteHandler; -import com.blade.route.Routers; -import com.blade.route.loader.ClassPathRouteLoader; -import com.blade.view.template.DefaultEngine; -import com.blade.view.template.TemplateEngine; -import com.blade.web.http.HttpMethod; - -/** - * Blade Core Class - * - * @author biezhi - * @since 1.6.6 - */ -public final class Blade { - - // blade initialize - private boolean isInit = false; - - // blade bootstrap config class - private Bootstrap bootstrap = null; - - // global configuration Object - private ApplicationConfig applicationConfig = null; - - // ioc container - private Ioc ioc = new SimpleIoc(); - - // default render is jspRender - private TemplateEngine templateEngine = null; - - // routes - private Routers routers = new Routers(); - - // routebuilder - private RouteBuilder routeBuilder; - - // jetty start port - private int port = Const.DEFAULT_PORT; - - // default context path - private String contextPath = Const.DEFAULT_CONTEXTPATH; - - // enableServer - private Boolean enableServer = false; - - // plugins - private Set> plugins; - - // global environment - private Environment environment; - - // config loader - private ConfigLoader configLoader; - - private Blade() { - this.environment = new Environment(); - this.applicationConfig = new ApplicationConfig(); - this.templateEngine = new DefaultEngine(); - this.plugins = new HashSet>(); - this.routeBuilder = new RouteBuilder(this.routers); - this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); - } - - static final class BladeHolder { - private static final Blade ME = new Blade(); - } - - /** - * @return Single case method returns Blade object - */ - @Deprecated - public static final Blade me() { - return BladeHolder.ME; - } - - /** - * - * @param appConf - * @return - */ - @Deprecated - public static final Blade me(String confPath) { - Blade blade = BladeHolder.ME; - blade.environment.add(confPath); - return blade; - } - - /** - * @return Single case method returns Blade object - */ - public static final Blade $() { - return BladeHolder.ME; - } - - /** - * @param confPath - * @return - */ - public static final Blade $(String confPath) { - Blade blade = BladeHolder.ME; - blade.environment.add(confPath); - return blade; - } - - /** - * Set Blade initialize - * - * @param isInit - * initialize - */ - public void init() { - if (!this.isInit) { - this.isInit = true; - } - } - - /** - * @return return route manager - */ - public Routers routers() { - return routers; - } - - /** - * @return return RouteBuilder - */ - public RouteBuilder routeBuilder() { - return routeBuilder; - } - - /** - * @return return ConfigLoader - */ - public ConfigLoader configLoader() { - return configLoader; - } - - /** - * @return return blade ioc container - */ - public Ioc ioc() { - return ioc; - } - - /** - * Setting a ioc container - * - * @param container - * ioc object - * @return return blade - */ - public Blade container(Ioc ioc) { - Assert.notNull(ioc); - this.ioc = ioc; - this.configLoader.setIoc(ioc); - return this; - } - - /** - * Setting Properties configuration file File path based on classpath - * - * @param confPath - * properties file name - * @return return blade - */ - public Blade loadAppConf(String confPath) { - Assert.notBlank(confPath); - environment.add(confPath); - return this; - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackage(String packageName) { - return this.addRoutePackages(packageName); - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackages(String... packages) { - Assert.notNull(packages); - applicationConfig.addRoutePackages(packages); - return this; - } - - /** - * - * @param basePackage - * @return - */ - public Blade basePackage(String basePackage) { - Assert.notBlank(basePackage); - applicationConfig.setBasePackage(basePackage); - applicationConfig.addIocPackages(basePackage + ".service.*"); - applicationConfig.addRoutePackages(basePackage + ".controller"); - applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); - return this; - } - - /** - * Setting the path where the interceptor, e.g:com.bladejava.interceptor - * - * @param packageName - * interceptor packagename - * @return return blade - */ - public Blade interceptor(String packageName) { - Assert.notBlank(packageName); - applicationConfig.setInterceptorPackage(packageName); - return this; - } - - /** - * Setting Ioc packages, e.g:com.bladejava.service - * - * @param packages - * All need to do into the package, can be introduced into a - * number of - * @return return blade - */ - public Blade ioc(String... packages) { - Assert.notNull(packages); - applicationConfig.addIocPackages(packages); - return this; - } - - /** - * Add a route - * - * @param path - * route path - * @param target - * Target object for routing - * @param method - * The method name of the route (at the same time, the HttpMethod - * is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @return return blade - */ - public Blade route(String path, Class clazz, String method) { - routers.route(path, clazz, method); - return this; - } - - /** - * Register a functional route - * - * @param path - * route url - * @param clazz - * route processing class - * @param method - * route processing method name - * @param httpMethod - * HttpMethod Type, GET/POST/... - * @return Blade return blade - */ - public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { - routers.route(path, clazz, method, httpMethod); - return this; - } - - /** - * Add a route list - * - * @param routes - * route list - * @return return blade - */ - public Blade routes(List routes) { - Assert.notEmpty(routes, "Routes not is empty!"); - routers.addRoutes(routes); - return this; - } - - /** - * Register a GET request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade get(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.GET); - return this; - } - - /** - * Register a POST request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade post(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.POST); - return this; - } - - /** - * Register a DELETE request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade delete(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.DELETE); - return this; - } - - /** - * Register a PUT request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade put(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.PUT); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade all(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade any(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Route Group. e.g blade.group('/users').get().post() - * - * @param g - * @return return blade - */ - public RouteGroup group(String prefix) { - Assert.notNull(prefix, "Route group prefix not is null"); - return new RouteGroup(this, prefix); - } - - /** - * Register a pre routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade before(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.BEFORE); - return this; - } - - /** - * Register a after routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade after(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.AFTER); - return this; - } - - /** - * Setting Render Engin, Default is JspRender - * - * @param templateEngine - * Render engine object - * @return return blade - */ - public Blade viewEngin(TemplateEngine templateEngine) { - Assert.notNull(templateEngine); - this.templateEngine = templateEngine; - return this; - } - - - /** - * @return Return Current TemplateEngine - */ - public TemplateEngine viewEngin() { - return this.templateEngine; - } - - /** - * Setting the frame static file folder - * - * @param folders - * List of directories to filter, e.g: "/public,/static,/images" - * @return return blade - */ - public Blade staticFolder(final String... folders) { - Assert.notNull(folders); - applicationConfig.setStaticFolders(folders); - return this; - } - - /** - * Dynamically set the global initialization class, the embedded Jetty boot - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Bootstrap bootstrap) { - Assert.notNull(bootstrap); - this.bootstrap = bootstrap; - return this; - } - - /** - * Dynamically set global initialization class - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Class bootstrap) { - Assert.notNull(bootstrap); - try { - Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); - ioc.addBean(Bootstrap.class.getName(), object); - this.bootstrap = object; - } catch (Exception e) { - e.printStackTrace(); - } - return this; - } - - /** - * add interceptor - * - * @param interceptor interceptor class - * @return return blade obj - */ - public Blade addInterceptor(Class interceptor) { - routeBuilder.addInterceptor(interceptor); - return this; - } - - /** - * add config - * - * @param config config class - * @return return blade obj - */ - public Blade addConfig(Class config) { - configLoader.addConfig(config); - return this; - } - - /** - * Setting 404 view page - * - * @param view404 - * 404 view page - * @return return blade - */ - public Blade view404(final String view404) { - Assert.notBlank(view404); - applicationConfig.setView404(view404); - return this; - } - - /** - * Setting 500 view page - * - * @param view500 - * 500 view page - * @return return blade - */ - public Blade view500(final String view500) { - Assert.notBlank(view500); - applicationConfig.setView500(view500); - return this; - } - - /** - * Setting blade web root path - * - * @param webRoot - * web root path - * @return return blade - */ - public Blade webRoot(final String webRoot) { - Assert.notBlank(webRoot); - applicationConfig.setWebRoot(webRoot); - return this; - } - - /** - * Setting blade run mode - * - * @param isDev - * is dev mode - * @return return blade - */ - public Blade isDev(boolean isDev) { - applicationConfig.setDev(isDev); - return this; - } - - /** - * Setting jetty listen port - * - * @param port - * port, default is 9000 - * @return return blade - */ - public Blade listen(int port) { - this.port = port; - return this; - } - - public void start(Class applicationClass) { - Assert.notNull(applicationClass); - - this.loadAppConf(Const.APP_PROPERTIES); - - // init blade environment config - applicationConfig.setEnv(environment); - applicationConfig.setApplicationClass(applicationClass); - - if(StringKit.isBlank(applicationConfig.getBasePackage())){ - applicationConfig.setBasePackage(applicationClass.getPackage().getName()); - } - try { - Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); - if(null == embedClazz){ - embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); - } - if(null != embedClazz){ - EmbedServer embedServer = (EmbedServer) embedClazz.newInstance(); - embedServer.startup(port, contextPath); - this.enableServer = true; - } else { - throw new EmbedServerException("Not found EmbedServer"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * @return Return blade config object - */ - public ApplicationConfig applicationConfig() { - return applicationConfig; - } - - /** - * @return Return blade config object - */ - public ApplicationConfig config() { - return applicationConfig; - } - - /** - * @return Return Blade Environment - */ - public Environment environment() { - return environment; - } - - /** - * @return Return blade encoding, default is UTF-8 - */ - public String encoding() { - return applicationConfig.getEncoding(); - } - - /** - * @return Return 404 view - */ - public String view404() { - return applicationConfig.getView404(); - } - - /** - * @return Return 500 view - */ - public String view500() { - return applicationConfig.getView500(); - } - - /** - * @return Return blade web root path - */ - public String webRoot() { - return applicationConfig.getWebRoot(); - } - - /** - * @return Return is dev mode - */ - public boolean isDev() { - return applicationConfig.isDev(); - } - - /** - * @return Return static resource directory - */ - public Set staticFolder() { - return applicationConfig.getStaticFolders(); - } - - /** - * @return Return bootstrap object - */ - public Bootstrap bootstrap() { - return this.bootstrap; - } - - /** - * @return Return current templateEngine - */ - public TemplateEngine templateEngine() { - return this.templateEngine; - } - - /** - * return register plugin object - * - * @param plugin - * plugin class - * @return return blade - */ - public Blade plugin(Class plugin) { - Assert.notNull(plugin); - plugins.add(plugin); - return this; - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @return return blade - */ - public Blade routeConf(String basePackage) { - return routeConf(basePackage, "route.conf"); - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @param conf - * Configuration file path, the configuration file must be in - * classpath - * @return return blade - */ - public Blade routeConf(String basePackage, String conf) { - try { - Assert.notBlank(basePackage); - Assert.notBlank(conf); - InputStream ins = Blade.class.getResourceAsStream("/" + conf); - ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); - routesLoader.setBasePackage(basePackage); - List routes = routesLoader.load(); - routers.addRoutes(routes); - } catch (RouteException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - return this; - } - - /** - * @return Return blade is initialize - */ - public boolean isInit() { - return isInit; - } - - public Blade enableServer(boolean enableServer) { - this.enableServer = enableServer; - return this; - } - - public boolean enableServer() { - return this.enableServer; - } - - public Set> plugins() { - return this.plugins; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +import java.io.InputStream; +import java.text.ParseException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.blade.config.ApplicationConfig; +import com.blade.config.BaseConfig; +import com.blade.config.ConfigLoader; +import com.blade.embedd.EmbedServer; +import com.blade.exception.EmbedServerException; +import com.blade.interceptor.Interceptor; +import com.blade.ioc.Ioc; +import com.blade.ioc.SimpleIoc; +import com.blade.kit.Assert; +import com.blade.kit.Environment; +import com.blade.kit.StringKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.plugin.Plugin; +import com.blade.route.Route; +import com.blade.route.RouteBuilder; +import com.blade.route.RouteException; +import com.blade.route.RouteGroup; +import com.blade.route.RouteHandler; +import com.blade.route.Routers; +import com.blade.route.loader.ClassPathRouteLoader; +import com.blade.web.http.HttpMethod; + +/** + * Blade Core Class + * + * @author biezhi + * @since 1.6.6 + */ +public final class Blade { + + // blade initialize + private boolean isInit = false; + + // blade bootstrap config class + private Bootstrap bootstrap = null; + + // global configuration Object + private ApplicationConfig applicationConfig = null; + + // ioc container + private Ioc ioc = new SimpleIoc(); + + // routes + private Routers routers = new Routers(); + + // routebuilder + private RouteBuilder routeBuilder; + + // jetty start port + private int port = Const.DEFAULT_PORT; + + // default context path + private String contextPath = Const.DEFAULT_CONTEXTPATH; + + // enableServer + private Boolean enableServer = false; + + // plugins + private Set> plugins; + + // global environment + private Environment environment; + + // config loader + private ConfigLoader configLoader; + + private Blade() { + this.environment = new Environment(); + this.applicationConfig = new ApplicationConfig(); + this.plugins = new HashSet>(); + this.routeBuilder = new RouteBuilder(this.routers); + this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); + } + + static final class BladeHolder { + private static final Blade $ = new Blade(); + } + + /** + * @return Single case method returns Blade object + */ + @Deprecated + public static final Blade me() { + return BladeHolder.$; + } + + /** + * + * @param appConf + * @return + */ + @Deprecated + public static final Blade me(String confPath) { + Blade blade = BladeHolder.$; + blade.environment.add(confPath); + return blade; + } + + /** + * @return Single case method returns Blade object + */ + public static final Blade $() { + return BladeHolder.$; + } + + /** + * @param confPath + * @return + */ + public static final Blade $(String confPath) { + Assert.notEmpty(confPath); + Blade blade = BladeHolder.$; + blade.environment.add(confPath); + return blade; + } + + /** + * Set Blade initialize + * + * @param isInit + * initialize + */ + public void init() { + if (!this.isInit) { + this.isInit = true; + } + } + + /** + * @return return route manager + */ + public Routers routers() { + return routers; + } + + /** + * @return return RouteBuilder + */ + public RouteBuilder routeBuilder() { + return routeBuilder; + } + + /** + * @return return ConfigLoader + */ + public ConfigLoader configLoader() { + return configLoader; + } + + /** + * @return return blade ioc container + */ + public Ioc ioc() { + return ioc; + } + + /** + * Setting a ioc container + * + * @param container + * ioc object + * @return return blade + */ + public Blade container(Ioc ioc) { + Assert.notNull(ioc); + this.ioc = ioc; + this.configLoader.setIoc(ioc); + return this; + } + + /** + * Setting Properties configuration file File path based on classpath + * + * @param confPath + * properties file name + * @return return blade + */ + public Blade loadAppConf(String confPath) { + Assert.notBlank(confPath); + environment.add(confPath); + return this; + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackage(String packageName) { + return this.addRoutePackages(packageName); + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackages(String... packages) { + Assert.notNull(packages); + applicationConfig.addRoutePackages(packages); + return this; + } + + /** + * + * @param basePackage + * @return + */ + public Blade basePackage(String basePackage) { + Assert.notBlank(basePackage); + applicationConfig.setBasePackage(basePackage); + applicationConfig.addIocPackages(basePackage + ".service.*"); + applicationConfig.addRoutePackages(basePackage + ".controller"); + applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); + return this; + } + + /** + * Setting the path where the interceptor, e.g:com.bladejava.interceptor + * + * @param packageName + * interceptor packagename + * @return return blade + */ + public Blade interceptor(String packageName) { + Assert.notBlank(packageName); + applicationConfig.setInterceptorPackage(packageName); + return this; + } + + /** + * Setting Ioc packages, e.g:com.bladejava.service + * + * @param packages + * All need to do into the package, can be introduced into a + * number of + * @return return blade + */ + public Blade ioc(String... packages) { + Assert.notNull(packages); + applicationConfig.addIocPackages(packages); + return this; + } + + /** + * Add a route + * + * @param path + * route path + * @param target + * Target object for routing + * @param method + * The method name of the route (at the same time, the HttpMethod + * is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade + */ + public Blade route(String path, Class clazz, String method) { + routers.route(path, clazz, method); + return this; + } + + /** + * Register a functional route + * + * @param path + * route url + * @param clazz + * route processing class + * @param method + * route processing method name + * @param httpMethod + * HttpMethod Type, GET/POST/... + * @return Blade return blade + */ + public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { + routers.route(path, clazz, method, httpMethod); + return this; + } + + /** + * Add a route list + * + * @param routes + * route list + * @return return blade + */ + public Blade routes(List routes) { + Assert.notEmpty(routes, "Routes not is empty!"); + routers.addRoutes(routes); + return this; + } + + /** + * Register a GET request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade get(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.GET); + return this; + } + + /** + * Register a POST request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade post(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.POST); + return this; + } + + /** + * Register a DELETE request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade delete(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.DELETE); + return this; + } + + /** + * Register a PUT request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade put(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.PUT); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade all(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade any(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Route Group. e.g blade.group('/users').get().post() + * + * @param g + * @return return blade + */ + public RouteGroup group(String prefix) { + Assert.notNull(prefix, "Route group prefix not is null"); + return new RouteGroup(this, prefix); + } + + /** + * Register a pre routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade before(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.BEFORE); + return this; + } + + /** + * Register a after routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade after(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.AFTER); + return this; + } + + /** + * Setting the frame static file folder + * + * @param folders + * List of directories to filter, e.g: "/public,/static,/images" + * @return return blade + */ + public Blade staticFolder(final String... folders) { + Assert.notNull(folders); + applicationConfig.setStaticFolders(folders); + return this; + } + + /** + * Dynamically set the global initialization class, the embedded Jetty boot + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Bootstrap bootstrap) { + Assert.notNull(bootstrap); + this.bootstrap = bootstrap; + return this; + } + + /** + * Dynamically set global initialization class + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Class bootstrap) { + Assert.notNull(bootstrap); + try { + Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); + ioc.addBean(Bootstrap.class.getName(), object); + this.bootstrap = object; + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + /** + * add interceptor + * + * @param interceptor interceptor class + * @return return blade obj + */ + public Blade addInterceptor(Class interceptor) { + routeBuilder.addInterceptor(interceptor); + return this; + } + + /** + * add config + * + * @param config config class + * @return return blade obj + */ + public Blade addConfig(Class config) { + configLoader.addConfig(config); + return this; + } + + /** + * Setting 404 view page + * + * @param view404 + * 404 view page + * @return return blade + */ + public Blade view404(final String view404) { + Assert.notBlank(view404); + applicationConfig.setView404(view404); + return this; + } + + /** + * Setting 500 view page + * + * @param view500 + * 500 view page + * @return return blade + */ + public Blade view500(final String view500) { + Assert.notBlank(view500); + applicationConfig.setView500(view500); + return this; + } + + /** + * Setting blade web root path + * + * @param webRoot + * web root path + * @return return blade + */ + public Blade webRoot(final String webRoot) { + Assert.notBlank(webRoot); + applicationConfig.setWebRoot(webRoot); + return this; + } + + /** + * Setting blade run mode + * + * @param isDev + * is dev mode + * @return return blade + */ + public Blade isDev(boolean isDev) { + applicationConfig.setDev(isDev); + return this; + } + + /** + * Setting jetty listen port + * + * @param port + * port, default is 9000 + * @return return blade + */ + public Blade listen(int port) { + this.port = port; + return this; + } + + /** + * start web server + */ + public void start() { + this.start(null); + } + + /** + * start web server + * @param applicationClass your app root package starter + */ + public void start(Class applicationClass) { + + this.loadAppConf(Const.APP_PROPERTIES); + + // init blade environment config + applicationConfig.setEnv(environment); + + if(null != applicationClass){ + applicationConfig.setApplicationClass(applicationClass); + if(StringKit.isBlank(applicationConfig.getBasePackage())){ + applicationConfig.setBasePackage(applicationClass.getPackage().getName()); + } + } + + try { + Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); + if(null == embedClazz){ + embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); + } + if(null != embedClazz){ + EmbedServer embedServer = (EmbedServer) embedClazz.newInstance(); + embedServer.startup(port, contextPath); + this.enableServer = true; + } else { + throw new EmbedServerException("Not found EmbedServer"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * @return Return blade config object + */ + public ApplicationConfig applicationConfig() { + return applicationConfig; + } + + /** + * @return Return blade config object + */ + public ApplicationConfig config() { + return applicationConfig; + } + + /** + * @return Return Blade Environment + */ + public Environment environment() { + return environment; + } + + /** + * @return Return blade encoding, default is UTF-8 + */ + public String encoding() { + return applicationConfig.getEncoding(); + } + + /** + * @return Return 404 view + */ + public String view404() { + return applicationConfig.getView404(); + } + + /** + * @return Return 500 view + */ + public String view500() { + return applicationConfig.getView500(); + } + + /** + * @return Return blade web root path + */ + public String webRoot() { + return applicationConfig.getWebRoot(); + } + + /** + * @return Return is dev mode + */ + public boolean isDev() { + return applicationConfig.isDev(); + } + + /** + * @return Return static resource directory + */ + public Set staticFolder() { + return applicationConfig.getStaticFolders(); + } + + /** + * @return Return bootstrap object + */ + public Bootstrap bootstrap() { + return this.bootstrap; + } + + /** + * return register plugin object + * + * @param plugin + * plugin class + * @return return blade + */ + public Blade plugin(Class plugin) { + Assert.notNull(plugin); + plugins.add(plugin); + return this; + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @return return blade + */ + public Blade routeConf(String basePackage) { + return routeConf(basePackage, "route.conf"); + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @param conf + * Configuration file path, the configuration file must be in + * classpath + * @return return blade + */ + public Blade routeConf(String basePackage, String conf) { + try { + Assert.notBlank(basePackage); + Assert.notBlank(conf); + InputStream ins = Blade.class.getResourceAsStream("/" + conf); + ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); + routesLoader.setBasePackage(basePackage); + List routes = routesLoader.load(); + routers.addRoutes(routes); + } catch (RouteException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return this; + } + + /** + * @return Return blade is initialize + */ + public boolean isInit() { + return isInit; + } + + public Blade enableServer(boolean enableServer) { + this.enableServer = enableServer; + return this; + } + + public boolean enableServer() { + return this.enableServer; + } + + public Set> plugins() { + return this.plugins; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/BladeBanner.java b/blade-core/src/main/java/com/blade/BladeBanner.java similarity index 86% rename from blade-core/src/main/java/com/blade/web/BladeBanner.java rename to blade-core/src/main/java/com/blade/BladeBanner.java index 868a83733..a63b8b507 100644 --- a/blade-core/src/main/java/com/blade/web/BladeBanner.java +++ b/blade-core/src/main/java/com/blade/BladeBanner.java @@ -1,10 +1,8 @@ -package com.blade.web; +package com.blade; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.blade.Const; - public class BladeBanner { private static final Logger LOGGER = LoggerFactory.getLogger(BladeBanner.class); diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index b7cde1bfe..fa0994807 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -1,54 +1,54 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -/** - * Const Interface - * - * @author biezhi - * @since 1.6.6 - */ -public interface Const { - - // current blade version - String BLADE_VERSION = "1.6.6-alpha"; - - // default embedd server context path - String DEFAULT_CONTEXTPATH = "/"; - - // Server 500 error HTML - String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; - - // Server 404 error HTML - String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; - - // Default jetty server port - int DEFAULT_PORT = 9000; - - // Request ThreadPoll context key - String BLADE_EXECUTOR = "blade-req-executor"; - - /**************** - * blade properties - * **************/ - String BLADE_ROUTE = "blade.route"; - String BLADE_IOC = "blade.ioc"; - String BLADE_VIEW_404 = "blade.view404"; - String BLADE_VIEW_500 = "blade.view500"; - String BLADE_DEV = "blade.dev"; - String APP_PROPERTIES = "app.properties"; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +/** + * Const Interface + * + * @author biezhi + * @since 1.6.6 + */ +public interface Const { + + // current blade version + String BLADE_VERSION = "1.6.6-beta"; + + // default embedd server context path + String DEFAULT_CONTEXTPATH = "/"; + + // Server 500 error HTML + String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; + + // Server 404 error HTML + String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; + + // Default jetty server port + int DEFAULT_PORT = 9000; + + // Request ThreadPoll context key + String BLADE_EXECUTOR = "blade-req-executor"; + + /**************** + * blade properties + * **************/ + String BLADE_ROUTE = "blade.route"; + String BLADE_IOC = "blade.ioc"; + String BLADE_VIEW_404 = "blade.view404"; + String BLADE_VIEW_500 = "blade.view500"; + String BLADE_DEV = "blade.dev"; + String APP_PROPERTIES = "app.properties"; + +} diff --git a/blade-core/src/main/java/com/blade/annotation/Intercept.java b/blade-core/src/main/java/com/blade/annotation/Intercept.java index 06824cdaa..6edf2b221 100644 --- a/blade-core/src/main/java/com/blade/annotation/Intercept.java +++ b/blade-core/src/main/java/com/blade/annotation/Intercept.java @@ -1,40 +1,41 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Interceptor notes, written in the class - * e.g: - *
- * {@link Intercept}
- * public class BaseInterceptor {...}
- * 
- * @author biezhi - * @since 1.5 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Intercept{ - - String value() default "/.*"; - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Interceptor notes, written in the class + * e.g: + *
+ * {@link Intercept}
+ * public class BaseInterceptor {...}
+ * 
+ * @author biezhi + * @since 1.5 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Intercept{ + + String value() default "/.*"; + + int sort() default 0; } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/view/parser/JSONView.java b/blade-core/src/main/java/com/blade/annotation/Order.java similarity index 57% rename from blade-core/src/main/java/com/blade/view/parser/JSONView.java rename to blade-core/src/main/java/com/blade/annotation/Order.java index b4518818a..4bb6c395d 100644 --- a/blade-core/src/main/java/com/blade/view/parser/JSONView.java +++ b/blade-core/src/main/java/com/blade/annotation/Order.java @@ -1,39 +1,36 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view.parser; - -/** - * Custom JSON Parser, eg:FastJSON - * - * @author biezhi - * @since 1.6.6 - */ -public final class JSONView { - - private JSONView() { - } - - private static JSONParser JSON_PARSER = new DefaultJSONParser(); - - public static String toJSONString(Object object){ - return JSON_PARSER.toJSONSting(object); - } - - public static void setJSONParser(JSONParser jsonParser){ - JSON_PARSER = jsonParser; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Order By + * + * @author biezhi + * @since 1.6.6 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Order{ + + int sort() default 0; + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/comparator/OrderComparator.java b/blade-core/src/main/java/com/blade/comparator/OrderComparator.java new file mode 100644 index 000000000..e571780ba --- /dev/null +++ b/blade-core/src/main/java/com/blade/comparator/OrderComparator.java @@ -0,0 +1,23 @@ +package com.blade.comparator; + +import java.util.Comparator; + +import com.blade.annotation.Order; +import com.blade.kit.resource.ClassInfo; + +public class OrderComparator implements Comparator { + + @Override + public int compare(ClassInfo c1, ClassInfo c2) { + Order o1 = c1.getClazz().getAnnotation(Order.class); + Order o2 = c2.getClazz().getAnnotation(Order.class); + if (null == o1 || null == o2) + return 0; + if (o1.sort() > o2.sort()) + return 1; + if (o1.sort() < o2.sort()) + return -1; + return 0; + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index b1959dc0d..0dcf22bbc 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -17,6 +17,7 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -27,6 +28,7 @@ import com.blade.annotation.Controller; import com.blade.annotation.Intercept; import com.blade.annotation.RestController; +import com.blade.comparator.OrderComparator; import com.blade.config.BaseConfig; import com.blade.context.DynamicClassReader; import com.blade.interceptor.Interceptor; @@ -54,12 +56,20 @@ public class IocApplication { */ private ClassReader classReader = null; private Blade blade; + private OrderComparator orderComparator; public IocApplication() { this.blade = Blade.$(); this.classReader = DynamicClassReader.getClassReader(); + this.orderComparator = new OrderComparator(); } + /** + * load config beans + * + * @return + * @throws Exception + */ private List loadCondigs() throws Exception { List configs = null; String[] configPackages = blade.config().getConfigPackages(); @@ -69,19 +79,20 @@ private List loadCondigs() throws Exception { Set configClasses = classReader.getClassByAnnotation(packageName, Component.class, false); if (null != configClasses) { for (ClassInfo classInfo : configClasses) { - if (classInfo.getClazz().getSuperclass().getName() - .equals("com.blade.aop.AbstractMethodInterceptor")) { - aopInterceptors.add(classInfo.newInstance()); - } Class[] interfaces = classInfo.getClazz().getInterfaces(); for (Class in : interfaces) { if (in.equals(BaseConfig.class)) { configs.add(classInfo); } } + if (classInfo.getClazz().getSuperclass().getName() + .equals("com.blade.aop.AbstractMethodInterceptor")) { + aopInterceptors.add(classInfo.newInstance()); + } } } } + Collections.sort(configs, orderComparator); } return configs; } @@ -139,12 +150,14 @@ private List loadInterceptors() { if (StringKit.isNotBlank(interceptorPackage)) { interceptors = new ArrayList(10); Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); - if(null != intes){ - for(ClassInfo classInfo : intes){ - if(null != classInfo.getClazz().getInterfaces() && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)){ + if (null != intes) { + for (ClassInfo classInfo : intes) { + if (null != classInfo.getClazz().getInterfaces() + && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)) { interceptors.add(classInfo); } } + Collections.sort(interceptors, orderComparator); } } return interceptors; @@ -157,20 +170,18 @@ public void initBeans() throws Exception { // web List inteceptors = this.loadInterceptors(); - // 先获取所有被容器托管的Class, 再依次注入 - Ioc ioc = blade.ioc(); RouteBuilder routeBuilder = blade.routeBuilder(); - // 1. 初始化service + // 1. init service if (null != services) { for (ClassInfo classInfo : services) { ioc.addBean(classInfo.getClazz()); } } - // 2. 初始化配置文件 + // 2. init configs if (null != configs) { for (ClassInfo classInfo : configs) { Object bean = ioc.addBean(classInfo.getClazz()); @@ -179,7 +190,7 @@ public void initBeans() throws Exception { } } - // 3. 初始化controller + // 3. init controller if (null != controllers) { for (ClassInfo classInfo : controllers) { ioc.addBean(classInfo.getClazz()); @@ -187,7 +198,7 @@ public void initBeans() throws Exception { } } - // 4. 初始化interceptor + // 4. init interceptor if (null != inteceptors) { for (ClassInfo classInfo : inteceptors) { ioc.addBean(classInfo.getClazz()); @@ -204,7 +215,6 @@ public void initBeans() throws Exception { IocKit.injection(ioc, beanDefine); } } - } public static List getAopInterceptors() { diff --git a/blade-core/src/main/java/com/blade/view/ViewSettings.java b/blade-core/src/main/java/com/blade/view/ViewSettings.java new file mode 100644 index 000000000..3b31b67b5 --- /dev/null +++ b/blade-core/src/main/java/com/blade/view/ViewSettings.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view; + +import com.blade.kit.Assert; +import com.blade.view.parser.DefaultJSONParser; +import com.blade.view.parser.JSONParser; +import com.blade.view.template.DefaultEngine; +import com.blade.view.template.TemplateEngine; + +/** + * ViewSettings + * + * @author biezhi + * @since 1.6.6 + */ +public final class ViewSettings { + + private JSONParser jsonParser = new DefaultJSONParser(); + private TemplateEngine templateEngine = new DefaultEngine(); + + private ViewSettings() { + } + + static final class ViewSettingsHolder { + private static final ViewSettings $ = new ViewSettings(); + } + + public static ViewSettings $() { + return ViewSettingsHolder.$; + } + + public ViewSettings JSONParser(JSONParser jsonParser) { + Assert.notNull(jsonParser); + this.jsonParser = jsonParser; + return this; + } + + public JSONParser JSONParser() { + return this.jsonParser; + } + + public String toJSONString(Object object) { + return jsonParser.toJSONSting(object); + } + + /** + * Setting Render Engin, Default is static file render + * + * @param templateEngine + * Render engine object + * @return return blade + */ + public ViewSettings templateEngine(TemplateEngine templateEngine) { + Assert.notNull(templateEngine); + this.templateEngine = templateEngine; + return this; + } + + /** + * @return Return Current TemplateEngine + */ + public TemplateEngine templateEngine() { + return this.templateEngine; + } + +} diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 49e116d0a..969510ee3 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -1,107 +1,108 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view.handle; - -import java.lang.reflect.Method; - -import com.blade.annotation.JSON; -import com.blade.annotation.RestController; -import com.blade.ioc.Ioc; -import com.blade.kit.reflect.ReflectKit; -import com.blade.route.Route; -import com.blade.view.ModelAndView; -import com.blade.view.parser.JSONView; -import com.blade.web.DispatchKit; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -public class RouteViewHandler { - - private Ioc ioc; - - public RouteViewHandler(Ioc ioc) { - this.ioc = ioc; - } - - public void handle(Request request, Response response, Route route) throws Exception { - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - - int len = actionMethod.getParameterTypes().length; - Object returnParam = null; - if (len > 0) { - Object[] args = MethodArgument.getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if (null != returnParam) { - Class returnType = returnParam.getClass(); - RestController restController = target.getClass().getAnnotation(RestController.class); - JSON json = actionMethod.getAnnotation(JSON.class); - if(null != restController || null != json){ - response.json(JSONView.toJSONString(returnParam)); - } else{ - if (returnType == String.class) { - response.render(returnParam.toString()); - } else if (returnType == ModelAndView.class) { - ModelAndView modelAndView = (ModelAndView) returnParam; - response.render(modelAndView); - } - } - } - } - - public boolean intercept(Request request, Response response, Route route) { - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - - if (null == target) { - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - - // execute - int len = actionMethod.getParameterTypes().length; - actionMethod.setAccessible(true); - try { - Object returnParam = null; - if (len > 0) { - Object[] args = MethodArgument.getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if (null != returnParam) { - Class returnType = returnParam.getClass(); - if (returnType == Boolean.class || returnType == boolean.class) { - return (Boolean) returnParam; - } - } - - return true; - - } catch (Exception e) { - request.abort(); - DispatchKit.printError(e, 500, response); - } - return false; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view.handle; + +import java.lang.reflect.Method; + +import com.blade.annotation.JSON; +import com.blade.annotation.RestController; +import com.blade.ioc.Ioc; +import com.blade.kit.reflect.ReflectKit; +import com.blade.route.Route; +import com.blade.view.ModelAndView; +import com.blade.view.ViewSettings; +import com.blade.web.DispatchKit; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +public class RouteViewHandler { + + private Ioc ioc; + private ViewSettings viewSettings; + public RouteViewHandler(Ioc ioc) { + this.ioc = ioc; + this.viewSettings = ViewSettings.$(); + } + + public void handle(Request request, Response response, Route route) throws Exception { + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + int len = actionMethod.getParameterTypes().length; + Object returnParam = null; + if (len > 0) { + Object[] args = MethodArgument.getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if (null != returnParam) { + Class returnType = returnParam.getClass(); + RestController restController = target.getClass().getAnnotation(RestController.class); + JSON json = actionMethod.getAnnotation(JSON.class); + if(null != restController || null != json){ + response.json(viewSettings.toJSONString(returnParam)); + } else{ + if (returnType == String.class) { + response.render(returnParam.toString()); + } else if (returnType == ModelAndView.class) { + ModelAndView modelAndView = (ModelAndView) returnParam; + response.render(modelAndView); + } + } + } + } + + public boolean intercept(Request request, Response response, Route route) { + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + if (null == target) { + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + + // execute + int len = actionMethod.getParameterTypes().length; + actionMethod.setAccessible(true); + try { + Object returnParam = null; + if (len > 0) { + Object[] args = MethodArgument.getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if (null != returnParam) { + Class returnType = returnParam.getClass(); + if (returnType == Boolean.class || returnType == boolean.class) { + return (Boolean) returnParam; + } + } + + return true; + + } catch (Exception e) { + request.abort(); + DispatchKit.printError(e, 500, response); + } + return false; + } + +} diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java index 520b85423..c87877099 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -1,204 +1,208 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; - -import java.io.IOException; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.context.ApplicationWebContext; -import com.blade.exception.BladeException; -import com.blade.ioc.Ioc; -import com.blade.kit.StringKit; -import com.blade.route.Route; -import com.blade.route.RouteHandler; -import com.blade.route.RouteMatcher; -import com.blade.route.Routers; -import com.blade.view.ModelAndView; -import com.blade.view.handle.RouteViewHandler; -import com.blade.view.template.TemplateException; -import com.blade.web.http.HttpStatus; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.wrapper.ServletRequest; -import com.blade.web.http.wrapper.ServletResponse; - -/** - * Synchronous request processor - * - * @author biezhi - * @since 1.5 - */ -public class DispatcherHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); - - private Ioc ioc; - - private Blade blade; - - private ServletContext servletContext; - - private RouteMatcher routeMatcher; - - private StaticFileFilter staticFileFilter; - - private RouteViewHandler routeViewHandler; - - public DispatcherHandler(ServletContext servletContext, Routers routers) { - this.servletContext = servletContext; - this.blade = Blade.$(); - this.ioc = blade.ioc(); - this.routeMatcher = new RouteMatcher(routers); - this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); - this.routeViewHandler = new RouteViewHandler(this.ioc); - } - - public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ - - // http method, GET/POST ... - String method = httpRequest.getMethod(); - - // reuqest uri - String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - - // Create Response - Response response = new ServletResponse(httpResponse, blade.templateEngine());; - - // If it is static, the resource is handed over to the filter - if(staticFileFilter.isStatic(uri)){ - LOGGER.debug("Request : {}\t{}", method, uri); - DispatchKit.printStatic(uri, httpRequest, response); - return; - } - - LOGGER.info("Request : {}\t{}", method, uri); - - try { - - Request request = new ServletRequest(httpRequest); - ApplicationWebContext.init(servletContext, request, response); - Route route = routeMatcher.getRoute(method, uri); - if (null != route) { - request.setRoute(route); - - // before inteceptor - List befores = routeMatcher.getBefore(uri); - boolean result = invokeInterceptor(request, response, befores); - if(result){ - // execute - this.routeHandle(request, response, route); - if(!request.isAbort()){ - // after inteceptor - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - } - } - } else { - // Not found - render404(response, uri); - } - return; - } catch (TemplateException e) { - LOGGER.error("Template error", e); - DispatchKit.printError(e, 500, response); - } catch (BladeException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - }catch (Exception e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } - return; - } - - /** - * 404 view render - * - * @param response response object - * @param uri 404 uri - * @throws IOException - * @throws TemplateException - */ - private void render404(Response response, String uri) throws Exception { - String view404 = blade.view404(); - if(StringKit.isNotBlank(view404)){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", uri); - response.render( modelAndView ); - } else { - response.status(HttpStatus.NOT_FOUND); - response.html(String.format(Const.VIEW_NOTFOUND, uri)); - } - } - - /** - * Methods to perform the interceptor - * - * @param request request object - * @param response response object - * @param interceptors execute the interceptor list - * @return Return execute is ok - */ - private boolean invokeInterceptor(Request request, Response response, List interceptors) { - for(Route route : interceptors){ - boolean flag = routeViewHandler.intercept(request, response, route); - if(!flag){ - return false; - } - } - return true; - } - - /** - * Actual routing method execution - * - * @param request request object - * @param response response object - * @param route route object - */ - private void routeHandle(Request request, Response response, Route route) throws Exception{ - Object target = route.getTarget(); - if(null == target){ - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - request.initPathParams(route.getPath()); - - // Init context - ApplicationWebContext.init(servletContext, request, response); - if(route.getTargetType() == RouteHandler.class){ - RouteHandler routeHandler = (RouteHandler) target; - routeHandler.handle(request, response); - } else { - routeViewHandler.handle(request, response, route); - } - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.context.ApplicationWebContext; +import com.blade.exception.BladeException; +import com.blade.ioc.Ioc; +import com.blade.kit.StringKit; +import com.blade.route.Route; +import com.blade.route.RouteHandler; +import com.blade.route.RouteMatcher; +import com.blade.route.Routers; +import com.blade.view.ModelAndView; +import com.blade.view.ViewSettings; +import com.blade.view.handle.RouteViewHandler; +import com.blade.view.template.TemplateException; +import com.blade.web.http.HttpStatus; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.http.wrapper.ServletRequest; +import com.blade.web.http.wrapper.ServletResponse; + +/** + * Synchronous request processor + * + * @author biezhi + * @since 1.5 + */ +public class DispatcherHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); + + private Ioc ioc; + + private Blade blade; + + private ServletContext servletContext; + + private RouteMatcher routeMatcher; + + private StaticFileFilter staticFileFilter; + + private RouteViewHandler routeViewHandler; + + private ViewSettings viewSettings; + + public DispatcherHandler(ServletContext servletContext, Routers routers) { + this.servletContext = servletContext; + this.blade = Blade.$(); + this.ioc = blade.ioc(); + this.routeMatcher = new RouteMatcher(routers); + this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); + this.routeViewHandler = new RouteViewHandler(this.ioc); + this.viewSettings = ViewSettings.$(); + } + + public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ + + // http method, GET/POST ... + String method = httpRequest.getMethod(); + + // reuqest uri + String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); + + // Create Response + Response response = new ServletResponse(httpResponse, viewSettings.templateEngine());; + + // If it is static, the resource is handed over to the filter + if(staticFileFilter.isStatic(uri)){ + LOGGER.debug("Request : {}\t{}", method, uri); + DispatchKit.printStatic(uri, httpRequest, response); + return; + } + + LOGGER.info("Request : {}\t{}", method, uri); + + try { + + Request request = new ServletRequest(httpRequest); + ApplicationWebContext.init(servletContext, request, response); + Route route = routeMatcher.getRoute(method, uri); + if (null != route) { + request.setRoute(route); + + // before inteceptor + List befores = routeMatcher.getBefore(uri); + boolean result = invokeInterceptor(request, response, befores); + if(result){ + // execute + this.routeHandle(request, response, route); + if(!request.isAbort()){ + // after inteceptor + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + } + } + } else { + // Not found + render404(response, uri); + } + return; + } catch (TemplateException e) { + LOGGER.error("Template error", e); + DispatchKit.printError(e, 500, response); + } catch (BladeException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + }catch (Exception e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } + return; + } + + /** + * 404 view render + * + * @param response response object + * @param uri 404 uri + * @throws IOException + * @throws TemplateException + */ + private void render404(Response response, String uri) throws Exception { + String view404 = blade.view404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(Const.VIEW_NOTFOUND, uri)); + } + } + + /** + * Methods to perform the interceptor + * + * @param request request object + * @param response response object + * @param interceptors execute the interceptor list + * @return Return execute is ok + */ + private boolean invokeInterceptor(Request request, Response response, List interceptors) { + for(Route route : interceptors){ + boolean flag = routeViewHandler.intercept(request, response, route); + if(!flag){ + return false; + } + } + return true; + } + + /** + * Actual routing method execution + * + * @param request request object + * @param response response object + * @param route route object + */ + private void routeHandle(Request request, Response response, Route route) throws Exception{ + Object target = route.getTarget(); + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + request.initPathParams(route.getPath()); + + // Init context + ApplicationWebContext.init(servletContext, request, response); + if(route.getTargetType() == RouteHandler.class){ + RouteHandler routeHandler = (RouteHandler) target; + routeHandler.handle(request, response); + } else { + routeViewHandler.handle(request, response, route); + } + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 9a5fe21a1..21c240751 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -1,153 +1,154 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; - -import java.io.IOException; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Bootstrap; -import com.blade.context.ApplicationContext; -import com.blade.context.ApplicationWebContext; -import com.blade.context.DynamicClassReader; -import com.blade.kit.StringKit; -import com.blade.kit.SystemKit; - -/** - * Blade Core DispatcherServlet - * - * @author biezhi - * @since 1.5 - */ -public class DispatcherServlet extends HttpServlet { - - private static final long serialVersionUID = -2607425162473178733L; - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); - - private Blade blade = Blade.$(); - - private Bootstrap bootstrap; - - private ServletContext servletContext; - - private DispatcherHandler dispatcherHandler; - - public DispatcherServlet() { - } - - public DispatcherServlet(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - blade.init(); - } - - @Override - public void init(ServletConfig config) throws ServletException { - servletContext = config.getServletContext(); - if(!blade.isInit()){ - - LOGGER.info("jdk.version = {}", SystemKit.getJavaInfo().getVersion()); - LOGGER.info("user.dir = {}", System.getProperty("user.dir")); - LOGGER.info("java.io.tmpdir = {}", System.getProperty("java.io.tmpdir")); - LOGGER.info("user.timezone = {}", System.getProperty("user.timezone")); - LOGGER.info("file.encoding = {}", System.getProperty("file.encoding")); - - DynamicClassReader.init(); - - long initStart = System.currentTimeMillis(); - - blade.webRoot(DispatchKit.getWebRoot(servletContext).getPath()); - - ApplicationWebContext.init(servletContext); - - LOGGER.info("blade.webroot = {}", blade.webRoot()); - - this.bootstrap = blade.bootstrap(); - - if(null == bootstrap){ - String bootStrapClassName = config.getInitParameter("bootstrap"); - if(StringKit.isNotBlank(bootStrapClassName)){ - this.bootstrap = getBootstrap(bootStrapClassName); - } else { - this.bootstrap = new Bootstrap() { - @Override - public void init(Blade blade) { - } - }; - } - blade.app(this.bootstrap); - } - - ApplicationContext.init(blade); - - LOGGER.info("blade.isDev = {}", blade.isDev()); - - dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); - - new BladeBanner().print(); - - String appName = blade.environment().getString("app.name", "Blade"); - - LOGGER.info(appName + " initialize successfully, Time elapsed: {} ms.", System.currentTimeMillis() - initStart); - } - } - - @Override - protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { - httpRequest.setCharacterEncoding(blade.encoding()); - httpResponse.setCharacterEncoding(blade.encoding()); - dispatcherHandler.handle(httpRequest, httpResponse); - } - - @Override - public void destroy() { - super.destroy(); - } - - /** - * Get global initialization object, the application of the initialization - * - * @param botstrapClassName botstrap class name - * @return return bootstrap object - * @throws ServletException - */ - @SuppressWarnings("unchecked") - private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { - Bootstrap bootstrapClass = null; - try { - if(null != botstrapClassName){ - Class applicationClass = (Class) Class.forName(botstrapClassName); - if(null != applicationClass){ - bootstrapClass = applicationClass.newInstance(); - } - } else { - throw new ServletException("bootstrapClass is null !"); - } - } catch (Exception e) { - throw new ServletException(e); - } - return bootstrapClass; - } -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.BladeBanner; +import com.blade.Bootstrap; +import com.blade.context.ApplicationContext; +import com.blade.context.ApplicationWebContext; +import com.blade.context.DynamicClassReader; +import com.blade.kit.StringKit; +import com.blade.kit.SystemKit; + +/** + * Blade Core DispatcherServlet + * + * @author biezhi + * @since 1.5 + */ +public class DispatcherServlet extends HttpServlet { + + private static final long serialVersionUID = -2607425162473178733L; + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); + + private Blade blade = Blade.$(); + + private Bootstrap bootstrap; + + private ServletContext servletContext; + + private DispatcherHandler dispatcherHandler; + + public DispatcherServlet() { + } + + public DispatcherServlet(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + blade.init(); + } + + @Override + public void init(ServletConfig config) throws ServletException { + servletContext = config.getServletContext(); + if(!blade.isInit()){ + + LOGGER.info("jdk.version = {}", SystemKit.getJavaInfo().getVersion()); + LOGGER.info("user.dir = {}", System.getProperty("user.dir")); + LOGGER.info("java.io.tmpdir = {}", System.getProperty("java.io.tmpdir")); + LOGGER.info("user.timezone = {}", System.getProperty("user.timezone")); + LOGGER.info("file.encoding = {}", System.getProperty("file.encoding")); + + DynamicClassReader.init(); + + long initStart = System.currentTimeMillis(); + + blade.webRoot(DispatchKit.getWebRoot(servletContext).getPath()); + + ApplicationWebContext.init(servletContext); + + LOGGER.info("blade.webroot = {}", blade.webRoot()); + + this.bootstrap = blade.bootstrap(); + + if(null == bootstrap){ + String bootStrapClassName = config.getInitParameter("bootstrap"); + if(StringKit.isNotBlank(bootStrapClassName)){ + this.bootstrap = getBootstrap(bootStrapClassName); + } else { + this.bootstrap = new Bootstrap() { + @Override + public void init(Blade blade) { + } + }; + } + blade.app(this.bootstrap); + } + + ApplicationContext.init(blade); + + LOGGER.info("blade.isDev = {}", blade.isDev()); + + dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); + + new BladeBanner().print(); + + String appName = blade.environment().getString("app.name", "Blade"); + + LOGGER.info("{} initialize successfully, Time elapsed: {} ms.", appName, System.currentTimeMillis() - initStart); + } + } + + @Override + protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { + httpRequest.setCharacterEncoding(blade.encoding()); + httpResponse.setCharacterEncoding(blade.encoding()); + dispatcherHandler.handle(httpRequest, httpResponse); + } + + @Override + public void destroy() { + super.destroy(); + } + + /** + * Get global initialization object, the application of the initialization + * + * @param botstrapClassName botstrap class name + * @return return bootstrap object + * @throws ServletException + */ + @SuppressWarnings("unchecked") + private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { + Bootstrap bootstrapClass = null; + try { + if(null != botstrapClassName){ + Class applicationClass = (Class) Class.forName(botstrapClassName); + if(null != applicationClass){ + bootstrapClass = applicationClass.newInstance(); + } + } else { + throw new ServletException("bootstrapClass is null !"); + } + } catch (Exception e) { + throw new ServletException(e); + } + return bootstrapClass; + } +} diff --git a/blade-kit/src/main/java/com/blade/kit/Environment.java b/blade-kit/src/main/java/com/blade/kit/Environment.java index 4d74973fc..9870b776f 100644 --- a/blade-kit/src/main/java/com/blade/kit/Environment.java +++ b/blade-kit/src/main/java/com/blade/kit/Environment.java @@ -28,7 +28,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; - /** * Environment * diff --git a/pom.xml b/pom.xml index c2413c04f..0f5cac164 100644 --- a/pom.xml +++ b/pom.xml @@ -1,92 +1,92 @@ - - - 4.0.0 - - com.bladejava - blade - 1.0 - pom - - blade - https://github.com/biezhi/blade - - - 1.6 - 1.6 - UTF-8 - - 3.0.1 - 4.12 - 1.7.21 - 1.7.21 - - 1.6.6-alpha - 1.3.2 - 1.0.0 - 0.0.3 - - - - - blade-kit - blade-core - blade-embed-jetty - blade-auth - blade-aop - - - - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - - - - - org.slf4j - slf4j-api - ${slf4j-api.version} - - - - org.slf4j - slf4j-log4j12 - ${slf4j-log4j12.version} - - - - junit - junit - ${junit.version} - test - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.6 - 1.6 - UTF-8 - - - - - + + + 4.0.0 + + com.bladejava + blade + 1.0 + pom + + blade + https://github.com/biezhi/blade + + + 1.6 + 1.6 + UTF-8 + + 3.0.1 + 4.12 + 1.7.21 + 1.7.21 + + 1.6.6-beta + 1.3.2 + 1.0.0 + 0.0.3 + + + + + blade-kit + blade-core + blade-embed-jetty + blade-auth + blade-aop + + + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + + + org.slf4j + slf4j-api + ${slf4j-api.version} + + + + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} + + + + junit + junit + ${junit.version} + test + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + UTF-8 + + + + + \ No newline at end of file From 424ec60e8cbeee19b253ed35ea1281f3d6bf6b96 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 2 Sep 2016 09:50:05 +0800 Subject: [PATCH 480/545] => remove order default sort value --- blade-core/src/main/java/com/blade/annotation/Order.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-core/src/main/java/com/blade/annotation/Order.java b/blade-core/src/main/java/com/blade/annotation/Order.java index 4bb6c395d..9f1b85335 100644 --- a/blade-core/src/main/java/com/blade/annotation/Order.java +++ b/blade-core/src/main/java/com/blade/annotation/Order.java @@ -31,6 +31,6 @@ @Documented public @interface Order{ - int sort() default 0; + int sort(); } \ No newline at end of file From 2c2932e62b34a8c8245165bb5749ff6dd0285254 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 2 Sep 2016 11:16:28 +0800 Subject: [PATCH 481/545] => fix anonymous classes not found Class --- .../main/java/com/blade/plugin/AopPlugin.java | 6 +- blade-core/src/main/java/com/blade/Blade.java | 2 +- .../src/main/java/com/blade/asm/AsmKit.java | 223 +++--- .../com/blade/config/ApplicationConfig.java | 436 ++++++------ .../com/blade/context/DynamicClassReader.java | 108 +-- .../java/com/blade/ioc/IocApplication.java | 9 +- .../blade/ioc/loader/IocAnnotationLoader.java | 154 ++--- .../main/java/com/blade/plugin/Plugin.java | 70 +- .../com/blade/view/handle/MethodArgument.java | 321 ++++----- .../blade/view/handle/RouteViewHandler.java | 9 +- .../java/com/blade/web/DispatcherHandler.java | 8 +- .../java/com/blade/web/http/Response.java | 504 +++++++------- .../web/http/wrapper/ServletResponse.java | 651 +++++++++--------- pom.xml | 2 +- 14 files changed, 1269 insertions(+), 1234 deletions(-) diff --git a/blade-aop/src/main/java/com/blade/plugin/AopPlugin.java b/blade-aop/src/main/java/com/blade/plugin/AopPlugin.java index 07d728216..63071e219 100644 --- a/blade-aop/src/main/java/com/blade/plugin/AopPlugin.java +++ b/blade-aop/src/main/java/com/blade/plugin/AopPlugin.java @@ -11,13 +11,13 @@ public class AopPlugin implements Plugin { private static final Logger LOGGER = LoggerFactory.getLogger(AopPlugin.class); @Override - public void start() { + public void startup() { LOGGER.info("Set Ioc container is {}", ProxyIocImpl.class.getName()); Blade.$().container(new ProxyIocImpl()); } - + @Override - public void destroy() { + public void shutdown() { } diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 110ce5a26..f07cccc0f 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -669,7 +669,7 @@ public String webRoot() { public boolean isDev() { return applicationConfig.isDev(); } - + /** * @return Return static resource directory */ diff --git a/blade-core/src/main/java/com/blade/asm/AsmKit.java b/blade-core/src/main/java/com/blade/asm/AsmKit.java index 8f5b59019..a96121d91 100644 --- a/blade-core/src/main/java/com/blade/asm/AsmKit.java +++ b/blade-core/src/main/java/com/blade/asm/AsmKit.java @@ -1,112 +1,111 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.asm; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * ASM Tools - * - * @author biezhi - * @since 1.6.6 - */ -public final class AsmKit { - - /** - * - *

- * 比较参数类型是否一致 - *

- * - * @param types - * asm的类型({@link Type}) - * @param clazzes - * java 类型({@link Class}) - * @return - */ - private static boolean sameType(Type[] types, Class[] clazzes) { - // 个数不同 - if (types.length != clazzes.length) { - return false; - } - - for (int i = 0; i < types.length; i++) { - if (!Type.getType(clazzes[i]).equals(types[i])) { - return false; - } - } - return true; - } - - /** - * - *

- * 获取方法的参数名 - *

- * - * @param m - * @return - */ - public static String[] getMethodParamNames(final Method m) { - final String[] paramNames = new String[m.getParameterTypes().length]; - final String n = m.getDeclaringClass().getName(); - ClassReader cr = null; - try { - cr = new ClassReader(n); - } catch (IOException e) { - throw new RuntimeException(e); - } - cr.accept(new ClassVisitor(Opcodes.ASM5) { - @Override - public MethodVisitor visitMethod(final int access, final String name, final String desc, - final String signature, final String[] exceptions) { - final Type[] args = Type.getArgumentTypes(desc); - // 方法名相同并且参数个数相同 - if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { - return super.visitMethod(access, name, desc, signature, exceptions); - } - MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); - return new MethodVisitor(Opcodes.ASM5, v) { - @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, - int index) { - int i = index - 1; - // 如果是静态方法,则第一就是参数 - // 如果不是静态方法,则第一个是"this",然后才是方法的参数 - if (Modifier.isStatic(m.getModifiers())) { - i = index; - } - if (i >= 0 && i < paramNames.length) { - paramNames[i] = name; - } - super.visitLocalVariable(name, desc, signature, start, end, index); - } - }; - } - }, 0); - return paramNames; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.asm; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * ASM Tools + * + * @author biezhi + * @since 1.6.6 + */ +public final class AsmKit { + + /** + * + *

+ * 比较参数类型是否一致 + *

+ * + * @param types + * asm的类型({@link Type}) + * @param clazzes + * java 类型({@link Class}) + * @return + */ + private static boolean sameType(Type[] types, Class[] clazzes) { + // 个数不同 + if (types.length != clazzes.length) { + return false; + } + for (int i = 0; i < types.length; i++) { + if (!Type.getType(clazzes[i]).equals(types[i])) { + return false; + } + } + return true; + } + + /** + * + *

+ * 获取方法的参数名 + *

+ * + * @param m + * @return + */ + public static String[] getMethodParamNames(final Method m) throws IOException { + final String[] paramNames = new String[m.getParameterTypes().length]; + final String n = m.getDeclaringClass().getName(); + ClassReader cr = null; + try { + cr = new ClassReader(n); + } catch (IOException e) { + return null; + } + cr.accept(new ClassVisitor(Opcodes.ASM5) { + @Override + public MethodVisitor visitMethod(final int access, final String name, final String desc, + final String signature, final String[] exceptions) { + final Type[] args = Type.getArgumentTypes(desc); + // 方法名相同并且参数个数相同 + if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { + return super.visitMethod(access, name, desc, signature, exceptions); + } + MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); + return new MethodVisitor(Opcodes.ASM5, v) { + @Override + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, + int index) { + int i = index - 1; + // 如果是静态方法,则第一就是参数 + // 如果不是静态方法,则第一个是"this",然后才是方法的参数 + if (Modifier.isStatic(m.getModifiers())) { + i = index; + } + if (i >= 0 && i < paramNames.length) { + paramNames[i] = name; + } + super.visitLocalVariable(name, desc, signature, start, end, index); + } + }; + } + }, 0); + return paramNames; + } + +} diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 30d7138d0..21fe71760 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -1,218 +1,218 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import com.blade.Blade; -import com.blade.kit.Environment; -import com.blade.kit.StringKit; - -/** - * Blade Application Config Class - * - * @author biezhi - * @since 1.6.6 - * - */ -public class ApplicationConfig { - - // Storage of all routing packets - private Set routePackages = new HashSet(); - - // Store all IOC packages - private Set iocPackages = new HashSet(); - - // Strore all config packages - private Set configPackages = new HashSet(); - - // Store all filter directories - private Set staticFolders = new HashSet(); - - // Base package - private String basePackage; - - // Interceptor package - private String interceptorPackage; - - // Encoding - private String encoding = "utf-8"; - - // web root path - private String webRoot; - - // 404 view page - private String view404; - - // 500 view page - private String view500; - - // Is dev mode - private boolean isDev = true; - - private boolean isInit = false; - - private Class applicationClass; - - public ApplicationConfig() { - staticFolders.add("/public"); - staticFolders.add("/assets"); - staticFolders.add("/static"); - } - - public void setEnv(Environment environment) { - if (null != environment && !isInit) { - this.isDev = environment.getBoolean("app.dev", true); - this.encoding = environment.getString("http.encoding", "UTF-8"); - this.addIocPackages(environment.getString("app.ioc")); - this.view500 = environment.getString("app.view.500"); - this.view404 = environment.getString("app.view.404"); - - String statics = environment.getString("app.statics"); - String basePackage = environment.getString("app.base-package"); - Integer port = environment.getInt("server.port"); - - if (null != port) { - Blade.$().listen(port); - } - - if (StringKit.isNotBlank(statics)) { - this.setStaticFolders(statics.split(",")); - } - - if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { - this.setBasePackage(basePackage); - } - isInit = true; - } - } - - public String[] getRoutePackages() { - String[] routeArr = new String[routePackages.size()]; - return routePackages.toArray(routeArr); - } - - public void addRoutePackages(String... packages) { - if (null != packages && packages.length > 0) { - routePackages.addAll(Arrays.asList(packages)); - } - } - - public String getBasePackage() { - return basePackage; - } - - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - this.addConfigPackages(basePackage + ".config"); - this.addIocPackages(basePackage + ".service.*"); - this.addRoutePackages(basePackage + ".controller"); - this.setInterceptorPackage(basePackage + ".interceptor"); - } - - public String[] getIocPackages() { - String[] iocArr = new String[iocPackages.size()]; - return iocPackages.toArray(iocArr); - } - - public String[] getConfigPackages() { - String[] configArr = new String[configPackages.size()]; - return configPackages.toArray(configArr); - } - - public void addIocPackages(String... packages) { - if (null != packages && packages.length > 0) { - iocPackages.addAll(Arrays.asList(packages)); - } - } - - public void addConfigPackages(String... packages) { - if (null != packages && packages.length > 0) { - configPackages.addAll(Arrays.asList(packages)); - } - } - - public String getInterceptorPackage() { - return interceptorPackage; - } - - public void setInterceptorPackage(String interceptorPackage) { - this.interceptorPackage = interceptorPackage; - } - - public Set getStaticFolders() { - return staticFolders; - } - - public void setStaticFolders(String... packages) { - staticFolders.addAll(Arrays.asList(packages)); - } - - public String getView404() { - return view404; - } - - public void setView404(String view404) { - this.view404 = view404; - } - - public String getView500() { - return view500; - } - - public void setView500(String view500) { - this.view500 = view500; - } - - public String getWebRoot() { - return webRoot; - } - - public void setWebRoot(String webRoot) { - this.webRoot = webRoot; - } - - public boolean isDev() { - return isDev; - } - - public void setDev(boolean isDev) { - this.isDev = isDev; - } - - public String getEncoding() { - return encoding; - } - - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - public boolean isInit(){ - return this.isInit; - } - - public Class getApplicationClass() { - return applicationClass; - } - - public void setApplicationClass(Class applicationClass) { - this.applicationClass = applicationClass; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import com.blade.Blade; +import com.blade.kit.Environment; +import com.blade.kit.StringKit; + +/** + * Blade Application Config Class + * + * @author biezhi + * @since 1.6.6 + * + */ +public class ApplicationConfig { + + // Storage of all routing packets + private Set routePackages = new HashSet(); + + // Store all IOC packages + private Set iocPackages = new HashSet(); + + // Strore all config packages + private Set configPackages = new HashSet(); + + // Store all filter directories + private Set staticFolders = new HashSet(); + + // Base package + private String basePackage; + + // Interceptor package + private String interceptorPackage; + + // Encoding + private String encoding = "utf-8"; + + // web root path + private String webRoot; + + // 404 view page + private String view404; + + // 500 view page + private String view500; + + // Is dev mode + private boolean isDev = true; + + private boolean isInit = false; + + private Class applicationClass; + + public ApplicationConfig() { + staticFolders.add("/public"); + staticFolders.add("/assets"); + staticFolders.add("/static"); + } + + public void setEnv(Environment environment) { + if (null != environment && !isInit) { + this.isDev = environment.getBoolean("app.dev", true); + this.encoding = environment.getString("http.encoding", "UTF-8"); + this.addIocPackages(environment.getString("app.ioc")); + this.view500 = environment.getString("app.view.500"); + this.view404 = environment.getString("app.view.404"); + + String statics = environment.getString("app.statics"); + String basePackage = environment.getString("app.base-package"); + Integer port = environment.getInt("server.port"); + + if (null != port) { + Blade.$().listen(port); + } + + if (StringKit.isNotBlank(statics)) { + this.setStaticFolders(statics.split(",")); + } + + if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { + this.setBasePackage(basePackage); + } + isInit = true; + } + } + + public String[] getRoutePackages() { + String[] routeArr = new String[routePackages.size()]; + return routePackages.toArray(routeArr); + } + + public void addRoutePackages(String... packages) { + if (null != packages && packages.length > 0) { + routePackages.addAll(Arrays.asList(packages)); + } + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + this.addConfigPackages(basePackage + ".config"); + this.addIocPackages(basePackage + ".service.*"); + this.addRoutePackages(basePackage + ".controller"); + this.setInterceptorPackage(basePackage + ".interceptor"); + } + + public String[] getIocPackages() { + String[] iocArr = new String[iocPackages.size()]; + return iocPackages.toArray(iocArr); + } + + public String[] getConfigPackages() { + String[] configArr = new String[configPackages.size()]; + return configPackages.toArray(configArr); + } + + public void addIocPackages(String... packages) { + if (null != packages && packages.length > 0) { + iocPackages.addAll(Arrays.asList(packages)); + } + } + + public void addConfigPackages(String... packages) { + if (null != packages && packages.length > 0) { + configPackages.addAll(Arrays.asList(packages)); + } + } + + public String getInterceptorPackage() { + return interceptorPackage; + } + + public void setInterceptorPackage(String interceptorPackage) { + this.interceptorPackage = interceptorPackage; + } + + public Set getStaticFolders() { + return staticFolders; + } + + public void setStaticFolders(String... packages) { + staticFolders.addAll(Arrays.asList(packages)); + } + + public String getView404() { + return view404; + } + + public void setView404(String view404) { + this.view404 = view404; + } + + public String getView500() { + return view500; + } + + public void setView500(String view500) { + this.view500 = view500; + } + + public String getWebRoot() { + return webRoot; + } + + public void setWebRoot(String webRoot) { + this.webRoot = webRoot; + } + + public boolean isDev() { + return isDev; + } + + public void setDev(boolean isDev) { + this.isDev = isDev; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public boolean isInit(){ + return this.isInit; + } + + public Class getApplicationClass() { + return applicationClass; + } + + public void setApplicationClass(Class applicationClass) { + this.applicationClass = applicationClass; + } + +} diff --git a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java index 2bde845a8..94a3db870 100644 --- a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java +++ b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java @@ -1,51 +1,57 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; - -import com.blade.Blade; -import com.blade.kit.resource.ClassPathClassReader; -import com.blade.kit.resource.ClassReader; -import com.blade.kit.resource.JarReaderImpl; - -/** - * Get ClassReader by JAR or folder - * - * @author biezhi - * @since 1.6.6 - */ -public final class DynamicClassReader { - - private static boolean IS_JAR_CONTEXT = false; - - private DynamicClassReader() { - } - - public static void init(){ - Class clazz = Blade.$().config().getApplicationClass(); - String rs = clazz.getResource("").toString(); - if(rs.indexOf(".jar!") != -1){ - IS_JAR_CONTEXT = true; - } - } - - public static ClassReader getClassReader(){ - if(IS_JAR_CONTEXT){ - return new JarReaderImpl(); - } - return new ClassPathClassReader(); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import com.blade.Blade; +import com.blade.kit.resource.ClassPathClassReader; +import com.blade.kit.resource.ClassReader; +import com.blade.kit.resource.JarReaderImpl; + +/** + * Get ClassReader by JAR or folder + * + * @author biezhi + * @since 1.6.6 + */ +public final class DynamicClassReader { + + private static boolean IS_JAR_CONTEXT = false; + + private static ClassReader CLASS_READER = null; + + private DynamicClassReader() { + } + + public static void init(){ + Class clazz = Blade.$().config().getApplicationClass(); + String rs = clazz.getResource("").toString(); + if(rs.indexOf(".jar!") != -1){ + IS_JAR_CONTEXT = true; + } + } + + public static ClassReader getClassReader(){ + if(null != CLASS_READER){ + return CLASS_READER; + } + if(IS_JAR_CONTEXT){ + CLASS_READER = new JarReaderImpl(); + } + CLASS_READER = new ClassPathClassReader(); + return CLASS_READER; + } + +} diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 0dcf22bbc..5f1d308c0 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -189,7 +189,12 @@ public void initBeans() throws Exception { baseConfig.config(blade.applicationConfig()); } } - + + Set resources = blade.applicationConfig().getStaticFolders(); + for(String resource : resources){ + LOGGER.debug("Add Resource: {}", resource); + } + // 3. init controller if (null != controllers) { for (ClassInfo classInfo : controllers) { @@ -207,7 +212,7 @@ public void initBeans() throws Exception { } LOGGER.info("Add Object: {}", ioc.getBeans()); - + // injection List beanDefines = ioc.getBeanDefines(); if (null != beanDefines) { diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java index 266ca2be1..4a713976f 100644 --- a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java @@ -1,78 +1,76 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.loader; - -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import com.blade.context.DynamicClassReader; -import com.blade.ioc.SimpleIoc; -import com.blade.ioc.annotation.Component; -import com.blade.kit.CollectionKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; - -/** - * Ioc annotation loader - * - * @author biezhi - * @since 1.5 - */ -public final class IocAnnotationLoader implements IocLoader { - - private Collection classes; - - private ClassReader classReader = DynamicClassReader.getClassReader(); - - - - public IocAnnotationLoader(String... packageNames) { - List> annotations = new ArrayList>(1); - annotations.add(Component.class); - this.classes = finder(Arrays.asList(packageNames), annotations, true); - } - - private Collection finder(List packageNames, List> annotations, boolean recursive){ - Collection classes = CollectionKit.newArrayList(); - for(String packageName : packageNames){ - for(Class annotation : annotations){ - classes.addAll(classReader.getClassByAnnotation(packageName, annotation, recursive)); - } - } - return classes; - } - - public IocAnnotationLoader(Collection classes) { - this.classes = classes; - } - - @Override - public void load(SimpleIoc ioc) { - for (ClassInfo classInfo : classes) { - Class cls = classInfo.getClazz(); - Component anno = cls.getAnnotation(Component.class); - if (anno != null) { - String name = anno.value().equals("") ? cls.getName() : anno.value(); - ioc.addBean(name, cls, true); - } - } - // free - classes = null; - } -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc.loader; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import com.blade.context.DynamicClassReader; +import com.blade.ioc.SimpleIoc; +import com.blade.ioc.annotation.Component; +import com.blade.kit.CollectionKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; + +/** + * Ioc annotation loader + * + * @author biezhi + * @since 1.5 + */ +public final class IocAnnotationLoader implements IocLoader { + + private Collection classes; + + private ClassReader classReader = DynamicClassReader.getClassReader(); + + public IocAnnotationLoader(String... packageNames) { + List> annotations = new ArrayList>(1); + annotations.add(Component.class); + this.classes = finder(Arrays.asList(packageNames), annotations, true); + } + + private Collection finder(List packageNames, List> annotations, boolean recursive){ + Collection classes = CollectionKit.newArrayList(); + for(String packageName : packageNames){ + for(Class annotation : annotations){ + classes.addAll(classReader.getClassByAnnotation(packageName, annotation, recursive)); + } + } + return classes; + } + + public IocAnnotationLoader(Collection classes) { + this.classes = classes; + } + + @Override + public void load(SimpleIoc ioc) { + for (ClassInfo classInfo : classes) { + Class cls = classInfo.getClazz(); + Component anno = cls.getAnnotation(Component.class); + if (anno != null) { + String name = anno.value().equals("") ? cls.getName() : anno.value(); + ioc.addBean(name, cls, true); + } + } + // free + classes = null; + } +} diff --git a/blade-core/src/main/java/com/blade/plugin/Plugin.java b/blade-core/src/main/java/com/blade/plugin/Plugin.java index a41d47dd5..aac6866d8 100644 --- a/blade-core/src/main/java/com/blade/plugin/Plugin.java +++ b/blade-core/src/main/java/com/blade/plugin/Plugin.java @@ -1,35 +1,35 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.plugin; - -/** - * Plugin Interface - * - * @author biezhi - * @since 1.5 - */ -public interface Plugin { - - /** - * Start Plugin - */ - void start(); - - /** - * Destroy, release resources - */ - void destroy(); -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.plugin; + +/** + * Plugin Interface + * + * @author biezhi + * @since 1.5 + */ +public interface Plugin { + + /** + * Start Plugin + */ + void startup(); + + /** + * Destroy, release resources + */ + void shutdown(); +} diff --git a/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java index 468ca92b2..156347fcc 100644 --- a/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java @@ -1,160 +1,161 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view.handle; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - -import com.blade.annotation.PathVariable; -import com.blade.annotation.RequestParam; -import com.blade.asm.AsmKit; -import com.blade.exception.BladeException; -import com.blade.exception.NotFoundException; -import com.blade.kit.StringKit; -import com.blade.view.ModelAndView; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.multipart.FileItem; - -public final class MethodArgument { - - public static Object[] getArgs(Request request, Response response, Method actionMethod) throws BladeException{ - Class[] parameters = actionMethod.getParameterTypes(); - Annotation[][] paramterAnnotations = actionMethod.getParameterAnnotations(); - - Object[] args = new Object[parameters.length]; - - try { - actionMethod.setAccessible(true); - String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); - - for (int i = 0, len = parameters.length; i < len; i++) { - - Class argType = parameters[i]; - if (argType.getName().equals(Request.class.getName())) { - args[i] = request; - continue; - } - - if (argType.getName().equals(Response.class.getName())) { - args[i] = response; - continue; - } - - if (argType.getName().equals(ModelAndView.class.getName())) { - args[i] = new ModelAndView(); - continue; - } - - if(argType.getName().equals(FileItem.class.getName())){ - args[i] = new ModelAndView(); - continue; - } - - Annotation annotation = paramterAnnotations[i][0]; - if(null != annotation){ - if(annotation.annotationType().equals(RequestParam.class)){ - RequestParam requestParam = (RequestParam) annotation; - String paramName = requestParam.value(); - String val = request.query(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.query(paramName); - } else { - if (StringKit.isBlank(val)) { - throw new NotFoundException("request param [" + paramName + "] is null"); - } - } - args[i] = getRequestParam(argType, val, requestParam.defaultValue()); - continue; - } - - if(annotation.annotationType().equals(PathVariable.class)){ - PathVariable pathVariable = (PathVariable) annotation; - String paramName = pathVariable.value(); - String val = request.param(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.param(paramName); - } else { - if (StringKit.isBlank(val)) { - throw new NotFoundException("path param [" + paramName + "] is null"); - } - } - args[i] = getRequestParam(argType, val, null); - continue; - } - } - } - return args; - } catch (BladeException e) { - throw e; - } - } - - private static Object getRequestParam(Class parameterType, String val, String defaultValue) { - Object result = null; - if (parameterType.equals(String.class)) { - if (StringKit.isNotBlank(val)) { - result = val; - } else { - if (null != defaultValue) { - result = defaultValue; - } - } - } else if (parameterType.equals(Integer.class)) { - if (StringKit.isNotBlank(val)) { - result = Integer.parseInt(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Integer.parseInt(defaultValue); - } - } - } else if (parameterType.equals(int.class)) { - if (StringKit.isNotBlank(val)) { - result = Integer.parseInt(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Integer.parseInt(defaultValue); - } else { - result = 0; - } - } - } else if (parameterType.equals(Long.class)) { - if (StringKit.isNotBlank(val)) { - result = Long.parseLong(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Long.parseLong(defaultValue); - } - } - } else if (parameterType.equals(long.class)) { - if (StringKit.isNotBlank(val)) { - result = Long.parseLong(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Long.parseLong(defaultValue); - } else { - result = 0L; - } - } - } - return result; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.view.handle; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import com.blade.annotation.PathVariable; +import com.blade.annotation.RequestParam; +import com.blade.asm.AsmKit; +import com.blade.exception.BladeException; +import com.blade.exception.NotFoundException; +import com.blade.kit.StringKit; +import com.blade.view.ModelAndView; +import com.blade.web.http.Request; +import com.blade.web.http.Response; +import com.blade.web.multipart.FileItem; + +public final class MethodArgument { + + public static Object[] getArgs(Request request, Response response, Method actionMethod) throws Exception{ + Class[] parameters = actionMethod.getParameterTypes(); + Annotation[][] paramterAnnotations = actionMethod.getParameterAnnotations(); + + Object[] args = new Object[parameters.length]; + + try { + actionMethod.setAccessible(true); + String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); + + for (int i = 0, len = parameters.length; i < len; i++) { + + Class argType = parameters[i]; + if (argType.getName().equals(Request.class.getName())) { + args[i] = request; + continue; + } + + if (argType.getName().equals(Response.class.getName())) { + args[i] = response; + continue; + } + + if (argType.getName().equals(ModelAndView.class.getName())) { + args[i] = new ModelAndView(); + continue; + } + + if(argType.getName().equals(FileItem.class.getName())){ + args[i] = new ModelAndView(); + continue; + } + + Annotation annotation = paramterAnnotations[i][0]; + + if(null != annotation){ + if(annotation.annotationType().equals(RequestParam.class)){ + RequestParam requestParam = (RequestParam) annotation; + String paramName = requestParam.value(); + String val = request.query(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.query(paramName); + } else { + if (StringKit.isBlank(val)) { + throw new NotFoundException("request param [" + paramName + "] is null"); + } + } + args[i] = getRequestParam(argType, val, requestParam.defaultValue()); + continue; + } + + if(annotation.annotationType().equals(PathVariable.class)){ + PathVariable pathVariable = (PathVariable) annotation; + String paramName = pathVariable.value(); + String val = request.param(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.param(paramName); + } else { + if (StringKit.isBlank(val)) { + throw new NotFoundException("path param [" + paramName + "] is null"); + } + } + args[i] = getRequestParam(argType, val, null); + continue; + } + } + } + return args; + } catch (BladeException e) { + throw e; + } + } + + private static Object getRequestParam(Class parameterType, String val, String defaultValue) { + Object result = null; + if (parameterType.equals(String.class)) { + if (StringKit.isNotBlank(val)) { + result = val; + } else { + if (null != defaultValue) { + result = defaultValue; + } + } + } else if (parameterType.equals(Integer.class)) { + if (StringKit.isNotBlank(val)) { + result = Integer.parseInt(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Integer.parseInt(defaultValue); + } + } + } else if (parameterType.equals(int.class)) { + if (StringKit.isNotBlank(val)) { + result = Integer.parseInt(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Integer.parseInt(defaultValue); + } else { + result = 0; + } + } + } else if (parameterType.equals(Long.class)) { + if (StringKit.isNotBlank(val)) { + result = Long.parseLong(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Long.parseLong(defaultValue); + } + } + } else if (parameterType.equals(long.class)) { + if (StringKit.isNotBlank(val)) { + result = Long.parseLong(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Long.parseLong(defaultValue); + } else { + result = 0L; + } + } + } + return result; + } + +} diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java index 969510ee3..f8b0ad30c 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java @@ -24,7 +24,6 @@ import com.blade.route.Route; import com.blade.view.ModelAndView; import com.blade.view.ViewSettings; -import com.blade.web.DispatchKit; import com.blade.web.http.Request; import com.blade.web.http.Response; @@ -67,7 +66,7 @@ public void handle(Request request, Response response, Route route) throws Excep } } - public boolean intercept(Request request, Response response, Route route) { + public boolean intercept(Request request, Response response, Route route) throws Exception { Method actionMethod = route.getAction(); Object target = route.getTarget(); @@ -95,14 +94,10 @@ public boolean intercept(Request request, Response response, Route route) { return (Boolean) returnParam; } } - return true; - } catch (Exception e) { - request.abort(); - DispatchKit.printError(e, 500, response); + throw e; } - return false; } } diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java index c87877099..062fa690e 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherHandler.java @@ -36,7 +36,6 @@ import com.blade.route.RouteMatcher; import com.blade.route.Routers; import com.blade.view.ModelAndView; -import com.blade.view.ViewSettings; import com.blade.view.handle.RouteViewHandler; import com.blade.view.template.TemplateException; import com.blade.web.http.HttpStatus; @@ -68,8 +67,6 @@ public class DispatcherHandler { private RouteViewHandler routeViewHandler; - private ViewSettings viewSettings; - public DispatcherHandler(ServletContext servletContext, Routers routers) { this.servletContext = servletContext; this.blade = Blade.$(); @@ -77,7 +74,6 @@ public DispatcherHandler(ServletContext servletContext, Routers routers) { this.routeMatcher = new RouteMatcher(routers); this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); this.routeViewHandler = new RouteViewHandler(this.ioc); - this.viewSettings = ViewSettings.$(); } public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ @@ -89,7 +85,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); // Create Response - Response response = new ServletResponse(httpResponse, viewSettings.templateEngine());; + Response response = new ServletResponse(httpResponse);; // If it is static, the resource is handed over to the filter if(staticFileFilter.isStatic(uri)){ @@ -169,7 +165,7 @@ private void render404(Response response, String uri) throws Exception { * @param interceptors execute the interceptor list * @return Return execute is ok */ - private boolean invokeInterceptor(Request request, Response response, List interceptors) { + private boolean invokeInterceptor(Request request, Response response, List interceptors) throws Exception { for(Route route : interceptors){ boolean flag = routeViewHandler.intercept(request, response, route); if(!flag){ diff --git a/blade-core/src/main/java/com/blade/web/http/Response.java b/blade-core/src/main/java/com/blade/web/http/Response.java index f22b7497e..00743f980 100644 --- a/blade-core/src/main/java/com/blade/web/http/Response.java +++ b/blade-core/src/main/java/com/blade/web/http/Response.java @@ -1,249 +1,255 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import com.blade.view.ModelAndView; -import com.blade.view.template.TemplateException; - -/** - * HTTP Response - * - * @author biezhi - * @since 1.5 - */ -public interface Response { - - /** - * @return Return HttpServletResponse - */ - HttpServletResponse raw(); - - /** - * @return Return HTTP Status - */ - int status(); - - /** - * Setting Response Status - * - * @param status status code - * @return Return Response - */ - Response status(int status); - - /** - * @return Setting Response Status is BadRequest and Return Response - */ - Response badRequest(); - - /** - * @return Setting Response Status is unauthorized and Return Response - */ - Response unauthorized(); - - /** - * @return Setting Response Status is notFound and Return Response - */ - Response notFound(); - - /** - * @return Setting Response Status is conflict and Return Response - */ - Response conflict(); - - /** - * @return Return Response contentType - */ - String contentType(); - - /** - * Setting Response ContentType - * - * @param contentType content type - * @return Return Response - */ - Response contentType(String contentType); - - /** - * Get header - * - * @param name Header Name - * @return Return Response - */ - String header(String name); - - /** - * Setting header - * - * @param name Header Name - * @param value Header Value - * @return Return Response - */ - Response header(String name, String value); - - /** - * Setting Cookie - * - * @param cookie Cookie Object - * @return Return Response - */ - Response cookie(Cookie cookie); - - /** - * Setting Cookie - * - * @param name Cookie Name - * @param value Cookie Value - * @return Return Response - */ - Response cookie(String name, String value); - - /** - * Setting Cookie - * - * @param name Cookie Name - * @param value Cookie Value - * @param maxAge Period of validity - * @return Return Response - */ - Response cookie(String name, String value, int maxAge); - - /** - * Setting Cookie - * - * @param name Cookie Name - * @param value Cookie Value - * @param maxAge Period of validity - * @param secured Is SSL - * @return Return Response - */ - Response cookie(String name, String value, int maxAge, boolean secured); - - /** - * Setting Cookie - * - * @param path Cookie Domain Path - * @param name Cookie Name - * @param value Cookie Value - * @param maxAge Period of validity - * @param secured Is SSL - * @return Return Response - */ - Response cookie(String path, String name, String value, int maxAge, boolean secured); - - /** - * Remove Cookie - * - * @param cookie Cookie Object - * @return Return Response - */ - Response removeCookie(Cookie cookie); - - /** - * Rmove Cookie By Name - * - * @param name Cookie Name - * @return Return Response - */ - Response removeCookie(String name); - - /** - * Render by text - * - * @param text text content - * @return Return Response - */ - Response text(String text); - - /** - * Render by html - * - * @param html html content - * @return Return Response - */ - Response html(String html); - - /** - * Render by json - * - * @param json json content - * @return Return Response - */ - Response json(String json); - - /** - * Render by xml - * - * @param xml xml content - * @return Return Response - */ - Response xml(String xml); - - /** - * @return Return OutputStream - * @throws IOException IOException - */ - OutputStream outputStream() throws IOException; - - /** - * @return Return ResponseWriter Stream - * @throws IOException - */ - PrintWriter writer() throws IOException; - - /** - * Render view - * - * @param view view page - * @return Return Response - */ - Response render(String view) throws TemplateException, IOException; - - /** - * Render view And Setting Data - * - * @param modelAndView ModelAndView object - * @return Return Response - */ - Response render(ModelAndView modelAndView) throws TemplateException, IOException; - - /** - * Redirect to Path - * - * @param path location path - */ - void redirect(String path); - - /** - * Go to Path, Under contextpath - * - * @param path redirect location - */ - void go(String path); - - /** - * @return Return Response is Write - */ - boolean isWritten(); - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import com.blade.view.ModelAndView; + +/** + * HTTP Response + * + * @author biezhi + * @since 1.5 + */ +public interface Response { + + /** + * @return Return HttpServletResponse + */ + HttpServletResponse raw(); + + /** + * @return Return HTTP Status + */ + int status(); + + /** + * Setting Response Status + * + * @param status status code + * @return Return Response + */ + Response status(int status); + + /** + * @return Setting Response Status is BadRequest and Return Response + */ + Response badRequest(); + + /** + * @return Setting Response Status is unauthorized and Return Response + */ + Response unauthorized(); + + /** + * @return Setting Response Status is notFound and Return Response + */ + Response notFound(); + + /** + * @return Setting Response Status is conflict and Return Response + */ + Response conflict(); + + /** + * @return Return Response contentType + */ + String contentType(); + + /** + * Setting Response ContentType + * + * @param contentType content type + * @return Return Response + */ + Response contentType(String contentType); + + /** + * Get header + * + * @param name Header Name + * @return Return Response + */ + String header(String name); + + /** + * Setting header + * + * @param name Header Name + * @param value Header Value + * @return Return Response + */ + Response header(String name, String value); + + /** + * Setting Cookie + * + * @param cookie Cookie Object + * @return Return Response + */ + Response cookie(Cookie cookie); + + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @return Return Response + */ + Response cookie(String name, String value); + + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @return Return Response + */ + Response cookie(String name, String value, int maxAge); + + /** + * Setting Cookie + * + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @param secured Is SSL + * @return Return Response + */ + Response cookie(String name, String value, int maxAge, boolean secured); + + /** + * Setting Cookie + * + * @param path Cookie Domain Path + * @param name Cookie Name + * @param value Cookie Value + * @param maxAge Period of validity + * @param secured Is SSL + * @return Return Response + */ + Response cookie(String path, String name, String value, int maxAge, boolean secured); + + /** + * Remove Cookie + * + * @param cookie Cookie Object + * @return Return Response + */ + Response removeCookie(Cookie cookie); + + /** + * Rmove Cookie By Name + * + * @param name Cookie Name + * @return Return Response + */ + Response removeCookie(String name); + + /** + * Render by text + * + * @param text text content + * @return Return Response + */ + Response text(String text); + + /** + * Render by html + * + * @param html html content + * @return Return Response + */ + Response html(String html); + + /** + * Render by json + * + * @param json json content + * @return Return Response + */ + Response json(String json); + + /** + * Render by json + * @param bean + * @return + */ + Response json(Object bean); + + /** + * Render by xml + * + * @param xml xml content + * @return Return Response + */ + Response xml(String xml); + + /** + * @return Return OutputStream + * @throws IOException IOException + */ + OutputStream outputStream() throws IOException; + + /** + * @return Return ResponseWriter Stream + * @throws IOException + */ + PrintWriter writer() throws IOException; + + /** + * Render view + * + * @param view view page + * @return Return Response + */ + Response render(String view); + + /** + * Render view And Setting Data + * + * @param modelAndView ModelAndView object + * @return Return Response + */ + Response render(ModelAndView modelAndView); + + /** + * Redirect to Path + * + * @param path location path + */ + void redirect(String path); + + /** + * Go to Path, Under contextpath + * + * @param path redirect location + */ + void go(String path); + + /** + * @return Return Response is Write + */ + boolean isWritten(); + +} diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java index fd7c63c4c..8e90abe20 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java @@ -1,311 +1,340 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http.wrapper; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import com.blade.context.ApplicationWebContext; -import com.blade.kit.Assert; -import com.blade.view.ModelAndView; -import com.blade.view.template.TemplateEngine; -import com.blade.view.template.TemplateException; -import com.blade.web.DispatchKit; -import com.blade.web.http.HttpStatus; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -/** - * ServletResponse - * - * @author biezhi - * @since 1.5 - */ -public class ServletResponse implements Response { - - private HttpServletResponse response; - - private boolean written = false; - - private TemplateEngine render; - - public ServletResponse(HttpServletResponse response, TemplateEngine render) { - this.response = response; - this.render = render; - } - - @Override - public HttpServletResponse raw() { - return response; - } - - @Override - public int status() { - return response.getStatus(); - } - - @Override - public Response status(int status) { - response.setStatus(status); - return this; - } - - @Override - public Response badRequest() { - response.setStatus(HttpStatus.BAD_REQUEST); - return this; - } - - @Override - public Response unauthorized() { - response.setStatus(HttpStatus.UNAUTHORIZED); - return this; - } - - @Override - public Response notFound() { - response.setStatus(HttpStatus.NOT_FOUND); - return this; - } - - @Override - public Response conflict() { - response.setStatus(HttpStatus.CONFLICT); - return this; - } - - @Override - public String contentType() { - return response.getContentType(); - } - - @Override - public Response contentType(String contentType) { - response.setContentType(contentType); - return this; - } - - @Override - public String header(String name) { - return response.getHeader(name); - } - - @Override - public Response header(String name, String value) { - response.setHeader(name, value); - return this; - } - - @Override - public Response cookie(Cookie cookie) { - response.addCookie(cookie); - return this; - } - - @Override - public Response cookie(String name, String value) { - return cookie(name, value); - } - - @Override - public Response cookie(String name, String value, int maxAge) { - return cookie(name, value, maxAge, false); - } - - @Override - public Response cookie(String name, String value, int maxAge, boolean secured) { - return cookie(null, name, value, maxAge, secured); - } - - @Override - public Response cookie(String path, String name, String value, int maxAge, boolean secured) { - Cookie cookie = new Cookie(name, value); - if(null != path){ - cookie.setPath(path); - } - cookie.setMaxAge(maxAge); - cookie.setSecure(secured); - response.addCookie(cookie); - return this; - } - - @Override - public Response removeCookie(Cookie cookie) { - cookie.setMaxAge(0); - response.addCookie(map(cookie)); - return this; - } - - javax.servlet.http.Cookie map(Cookie cookie) { - javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); - servletCookie.setMaxAge(cookie.getMaxAge()); - if (cookie.getPath() != null) { - servletCookie.setPath(cookie.getPath()); - } - if (cookie.getDomain() != null) { - servletCookie.setDomain(cookie.getDomain()); - } - servletCookie.setHttpOnly(cookie.isHttpOnly()); - servletCookie.setSecure(cookie.getSecure()); - return servletCookie; - } - - @Override - public Response removeCookie(String name) { - Cookie cookie = new Cookie(name, ""); - cookie.setMaxAge(0); - response.addCookie(cookie); - return this; - } - - @Override - public Response text(String text) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/plain;charset=utf-8"); - DispatchKit.print(text, response.getWriter()); - this.written = true; - return this; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Response html(String html) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/html;charset=utf-8"); - - PrintWriter writer = response.getWriter(); - DispatchKit.print(html, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public Response json(String json) { - Request request = ApplicationWebContext.request(); - String userAgent = request.userAgent(); - if (userAgent.contains("MSIE")) { - response.setContentType("text/html;charset=utf-8"); - } else { - response.setContentType("application/json;charset=utf-8"); - } - try { - response.setHeader("Cache-Control", "no-cache"); - PrintWriter writer = response.getWriter(); - DispatchKit.print(json, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Response xml(String xml) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/xml;charset=utf-8"); - PrintWriter writer = response.getWriter(); - DispatchKit.print(xml, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public ServletOutputStream outputStream() throws IOException { - return response.getOutputStream(); - } - - @Override - public PrintWriter writer() throws IOException { - return response.getWriter(); - } - - @Override - public Response render(String view) throws TemplateException, IOException{ - Assert.notBlank(view, "view not is null"); - - String viewPath = Path.cleanPath(view); - ModelAndView modelAndView = new ModelAndView(viewPath); - render.render(modelAndView, response.getWriter()); - return this; - } - - @Override - public Response render(ModelAndView modelAndView) throws TemplateException, IOException { - Assert.notNull(modelAndView, "ModelAndView not is null!"); - Assert.notBlank(modelAndView.getView(), "view not is null"); - - String viewPath = Path.cleanPath(modelAndView.getView()); - modelAndView.setView(viewPath); - - render.render(modelAndView, response.getWriter()); - return this; - } - - @Override - public void redirect(String path) { - try { - response.sendRedirect(path); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void go(String path) { - try { - String ctx = ApplicationWebContext.servletContext().getContextPath(); - String location = Path.fixPath(ctx + path); - response.sendRedirect(location); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public boolean isWritten() { - return written; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.web.http.wrapper; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.ApplicationWebContext; +import com.blade.kit.Assert; +import com.blade.view.ModelAndView; +import com.blade.view.ViewSettings; +import com.blade.view.parser.JSONParser; +import com.blade.view.template.TemplateEngine; +import com.blade.view.template.TemplateException; +import com.blade.web.DispatchKit; +import com.blade.web.http.HttpStatus; +import com.blade.web.http.Path; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * ServletResponse + * + * @author biezhi + * @since 1.5 + */ +public class ServletResponse implements Response { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServletResponse.class); + + private HttpServletResponse response; + + private boolean written = false; + + private ViewSettings viewSettings; + + private TemplateEngine templateEngine; + + private JSONParser jsonParser; + + public ServletResponse(HttpServletResponse response) { + this.response = response; + this.viewSettings = ViewSettings.$(); + this.templateEngine = viewSettings.templateEngine(); + this.jsonParser = viewSettings.JSONParser(); + } + + @Override + public HttpServletResponse raw() { + return response; + } + + @Override + public int status() { + return response.getStatus(); + } + + @Override + public Response status(int status) { + response.setStatus(status); + return this; + } + + @Override + public Response badRequest() { + response.setStatus(HttpStatus.BAD_REQUEST); + return this; + } + + @Override + public Response unauthorized() { + response.setStatus(HttpStatus.UNAUTHORIZED); + return this; + } + + @Override + public Response notFound() { + response.setStatus(HttpStatus.NOT_FOUND); + return this; + } + + @Override + public Response conflict() { + response.setStatus(HttpStatus.CONFLICT); + return this; + } + + @Override + public String contentType() { + return response.getContentType(); + } + + @Override + public Response contentType(String contentType) { + response.setContentType(contentType); + return this; + } + + @Override + public String header(String name) { + return response.getHeader(name); + } + + @Override + public Response header(String name, String value) { + response.setHeader(name, value); + return this; + } + + @Override + public Response cookie(Cookie cookie) { + response.addCookie(cookie); + return this; + } + + @Override + public Response cookie(String name, String value) { + return cookie(name, value); + } + + @Override + public Response cookie(String name, String value, int maxAge) { + return cookie(name, value, maxAge, false); + } + + @Override + public Response cookie(String name, String value, int maxAge, boolean secured) { + return cookie(null, name, value, maxAge, secured); + } + + @Override + public Response cookie(String path, String name, String value, int maxAge, boolean secured) { + Cookie cookie = new Cookie(name, value); + if(null != path){ + cookie.setPath(path); + } + cookie.setMaxAge(maxAge); + cookie.setSecure(secured); + response.addCookie(cookie); + return this; + } + + @Override + public Response removeCookie(Cookie cookie) { + cookie.setMaxAge(0); + response.addCookie(map(cookie)); + return this; + } + + javax.servlet.http.Cookie map(Cookie cookie) { + javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); + servletCookie.setMaxAge(cookie.getMaxAge()); + if (cookie.getPath() != null) { + servletCookie.setPath(cookie.getPath()); + } + if (cookie.getDomain() != null) { + servletCookie.setDomain(cookie.getDomain()); + } + servletCookie.setHttpOnly(cookie.isHttpOnly()); + servletCookie.setSecure(cookie.getSecure()); + return servletCookie; + } + + @Override + public Response removeCookie(String name) { + Cookie cookie = new Cookie(name, ""); + cookie.setMaxAge(0); + response.addCookie(cookie); + return this; + } + + @Override + public Response text(String text) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/plain;charset=utf-8"); + DispatchKit.print(text, response.getWriter()); + this.written = true; + return this; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Response html(String html) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/html;charset=utf-8"); + + PrintWriter writer = response.getWriter(); + DispatchKit.print(html, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public Response json(String json) { + Request request = ApplicationWebContext.request(); + String userAgent = request.userAgent(); + if (userAgent.contains("MSIE")) { + response.setContentType("text/html;charset=utf-8"); + } else { + response.setContentType("application/json;charset=utf-8"); + } + try { + response.setHeader("Cache-Control", "no-cache"); + PrintWriter writer = response.getWriter(); + DispatchKit.print(json, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Response json(Object bean) { + return this.json(jsonParser.toJSONSting(bean)); + } + + @Override + public Response xml(String xml) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/xml;charset=utf-8"); + PrintWriter writer = response.getWriter(); + DispatchKit.print(xml, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public ServletOutputStream outputStream() throws IOException { + return response.getOutputStream(); + } + + @Override + public PrintWriter writer() throws IOException { + return response.getWriter(); + } + + @Override + public Response render(String view){ + Assert.notBlank(view, "view not is null"); + + String viewPath = Path.cleanPath(view); + ModelAndView modelAndView = new ModelAndView(viewPath); + try { + templateEngine.render(modelAndView, response.getWriter()); + } catch (TemplateException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return this; + } + + @Override + public Response render(ModelAndView modelAndView) { + Assert.notNull(modelAndView, "ModelAndView not is null!"); + Assert.notBlank(modelAndView.getView(), "view not is null"); + + String viewPath = Path.cleanPath(modelAndView.getView()); + modelAndView.setView(viewPath); + try { + templateEngine.render(modelAndView, response.getWriter()); + } catch (TemplateException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return this; + } + + @Override + public void redirect(String path) { + try { + response.sendRedirect(path); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void go(String path) { + try { + String ctx = ApplicationWebContext.servletContext().getContextPath(); + String location = Path.fixPath(ctx + path); + response.sendRedirect(location); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public boolean isWritten() { + return written; + } + +} diff --git a/pom.xml b/pom.xml index 0f5cac164..4721e814a 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ 1.7.21 1.6.6-beta - 1.3.2 + 1.3.3 1.0.0 0.0.3 From d03b91375ee0f5fc432abed2a582d055dc7dc27c Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 2 Sep 2016 13:53:02 +0800 Subject: [PATCH 482/545] => fix jsp engine --- blade-core/src/main/java/com/blade/Blade.java | 7 +- .../com/blade/config/ApplicationConfig.java | 32 ++-- .../java/com/blade/ioc/IocApplication.java | 7 +- .../java/com/blade/view/ViewSettings.java | 7 + .../com/blade/view/template/JspEngine.java | 147 ++++++++---------- .../com/blade/embedd/EmbedJettyServer.java | 37 +++-- blade-kit/pom.xml | 112 +++++++------ pom.xml | 2 +- 8 files changed, 176 insertions(+), 175 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index f07cccc0f..e5b702c07 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -445,13 +445,12 @@ public Blade after(String path, RouteHandler handler) { /** * Setting the frame static file folder * - * @param folders + * @param resources * List of directories to filter, e.g: "/public,/static,/images" * @return return blade */ - public Blade staticFolder(final String... folders) { - Assert.notNull(folders); - applicationConfig.setStaticFolders(folders); + public Blade addResources(final String... resources) { + applicationConfig.addResources(resources); return this; } diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 21fe71760..76cfef457 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -19,7 +19,11 @@ import java.util.HashSet; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.Blade; +import com.blade.kit.Assert; import com.blade.kit.Environment; import com.blade.kit.StringKit; @@ -32,17 +36,19 @@ */ public class ApplicationConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfig.class); + // Storage of all routing packets - private Set routePackages = new HashSet(); + private Set routePackages = new HashSet(8); // Store all IOC packages - private Set iocPackages = new HashSet(); + private Set iocPackages = new HashSet(8); // Strore all config packages - private Set configPackages = new HashSet(); + private Set configPackages = new HashSet(2); // Store all filter directories - private Set staticFolders = new HashSet(); + private Set staticFolders = new HashSet(5); // Base package private String basePackage; @@ -58,7 +64,7 @@ public class ApplicationConfig { // 404 view page private String view404; - + // 500 view page private String view500; @@ -70,9 +76,7 @@ public class ApplicationConfig { private Class applicationClass; public ApplicationConfig() { - staticFolders.add("/public"); - staticFolders.add("/assets"); - staticFolders.add("/static"); + this.addResources("/public", "/assets", "/static"); } public void setEnv(Environment environment) { @@ -92,9 +96,9 @@ public void setEnv(Environment environment) { } if (StringKit.isNotBlank(statics)) { - this.setStaticFolders(statics.split(",")); + this.addResources(statics.split(",")); } - + if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { this.setBasePackage(basePackage); } @@ -159,8 +163,12 @@ public Set getStaticFolders() { return staticFolders; } - public void setStaticFolders(String... packages) { - staticFolders.addAll(Arrays.asList(packages)); + public void addResources(String... resources) { + Assert.notNull(resources); + for(String resource : resources){ + LOGGER.debug("Add Resource: {}", resource); + } + staticFolders.addAll(Arrays.asList(resources)); } public String getView404() { diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 5f1d308c0..d133cf58a 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -190,11 +190,6 @@ public void initBeans() throws Exception { } } - Set resources = blade.applicationConfig().getStaticFolders(); - for(String resource : resources){ - LOGGER.debug("Add Resource: {}", resource); - } - // 3. init controller if (null != controllers) { for (ClassInfo classInfo : controllers) { @@ -210,7 +205,7 @@ public void initBeans() throws Exception { routeBuilder.addInterceptor(classInfo.getClazz()); } } - + LOGGER.info("Add Object: {}", ioc.getBeans()); // injection diff --git a/blade-core/src/main/java/com/blade/view/ViewSettings.java b/blade-core/src/main/java/com/blade/view/ViewSettings.java index 3b31b67b5..730b39fec 100644 --- a/blade-core/src/main/java/com/blade/view/ViewSettings.java +++ b/blade-core/src/main/java/com/blade/view/ViewSettings.java @@ -15,6 +15,9 @@ */ package com.blade.view; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.kit.Assert; import com.blade.view.parser.DefaultJSONParser; import com.blade.view.parser.JSONParser; @@ -29,6 +32,8 @@ */ public final class ViewSettings { + private static final Logger LOGGER = LoggerFactory.getLogger(ViewSettings.class); + private JSONParser jsonParser = new DefaultJSONParser(); private TemplateEngine templateEngine = new DefaultEngine(); @@ -45,6 +50,7 @@ static final class ViewSettingsHolder { public ViewSettings JSONParser(JSONParser jsonParser) { Assert.notNull(jsonParser); + LOGGER.debug("Switch JSONParser With [{}]", jsonParser); this.jsonParser = jsonParser; return this; } @@ -66,6 +72,7 @@ public String toJSONString(Object object) { */ public ViewSettings templateEngine(TemplateEngine templateEngine) { Assert.notNull(templateEngine); + LOGGER.debug("Switch TemplateEngine With [{}]", templateEngine); this.templateEngine = templateEngine; return this; } diff --git a/blade-core/src/main/java/com/blade/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/view/template/JspEngine.java index 3832dbc4d..abe2269cb 100644 --- a/blade-core/src/main/java/com/blade/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/JspEngine.java @@ -1,78 +1,69 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; - -import java.io.IOException; -import java.io.Writer; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.context.ApplicationWebContext; -import com.blade.view.ModelAndView; - - -/** - * JSP Render, Default Render - * - * @author biezhi - * @since 1.5 - */ -public final class JspEngine implements TemplateEngine { - - private static final Logger LOGGER = LoggerFactory.getLogger(JspEngine.class); - - private String viewPath = "/WEB-INF/"; - - public JspEngine() { - } - - public JspEngine(String viewPath) { - this.viewPath = viewPath; - } - - @Override - public void render(ModelAndView modelAndView, Writer writer) { - HttpServletRequest servletRequest = ApplicationWebContext.request().raw(); - HttpServletResponse servletResponse = ApplicationWebContext.response().raw(); - - try { - Map model = modelAndView.getModel(); - String realPath = viewPath + modelAndView.getView(); - - if (null != model && !model.isEmpty()) { - Set keys = model.keySet(); - for (String key : keys) { - servletRequest.setAttribute(key, model.get(key)); - } - } - servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); - } catch (ServletException e) { - e.printStackTrace(); - LOGGER.error("", e); - } catch (IOException e) { - e.printStackTrace(); - LOGGER.error("", e); - } - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.view.template; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.blade.context.ApplicationWebContext; +import com.blade.view.ModelAndView; + + +/** + * JSP Render, Default Render + * + * @author biezhi + * @since 1.5 + */ +public final class JspEngine implements TemplateEngine { + + private String viewPath = "/views/"; + + public JspEngine() { + } + + public JspEngine(String viewPath) { + this.viewPath = viewPath; + } + + @Override + public void render(ModelAndView modelAndView, Writer writer) throws TemplateException { + HttpServletRequest request = ApplicationWebContext.request().raw(); + HttpServletResponse response = ApplicationWebContext.response().raw(); + try { + Map model = modelAndView.getModel(); + String realPath = viewPath + modelAndView.getView(); + if (null != model && !model.isEmpty()) { + Set keys = model.keySet(); + for (String key : keys) { + request.setAttribute(key, model.get(key)); + } + } + request.getRequestDispatcher(realPath).forward(request, response); + } catch (ServletException e) { + throw new TemplateException(e); + } catch (IOException e) { + throw new TemplateException(e); + } + } + +} diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index db0c77495..3fb7820a9 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -1,18 +1,23 @@ package com.blade.embedd; +import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.eclipse.jetty.webapp.WebAppContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.blade.Blade; import com.blade.Const; import com.blade.kit.Environment; +import com.blade.kit.StringKit; import com.blade.web.DispatcherServlet; +import static com.blade.Blade.$; public class EmbedJettyServer implements EmbedServer { @@ -22,14 +27,14 @@ public class EmbedJettyServer implements EmbedServer { private org.eclipse.jetty.server.Server server; - private ServletContextHandler context; + private WebAppContext webAppContext; private Environment environment = null; public EmbedJettyServer() { - Blade.$().loadAppConf("jetty.properties"); - environment = Blade.$().environment(); - Blade.$().enableServer(true); + $().loadAppConf("jetty.properties"); + environment = $().environment(); + $().enableServer(true); } @Override @@ -57,15 +62,14 @@ public void startup(int port, String contextPath, String webRoot) throws Excepti // 设置在JVM退出时关闭Jetty的钩子。 server.setStopAtShutdown(true); - context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath(contextPath); + webAppContext = new WebAppContext(); + webAppContext.setContextPath(contextPath); - /*if(StringKit.isNotBlank(webRoot)){ - context.setResourceBase(webRoot); - } else{ - context.setResourceBase(getClass().getResource("").getPath()); - }*/ - context.setResourceBase("."); + if(StringKit.isBlank(webRoot)){ + webRoot = Blade.$().config().getApplicationClass().getResource("/").getPath(); + } + + webAppContext.setResourceBase(webRoot); int securePort = environment.getInt("server.jetty.http.secure-port", 8443); int outputBufferSize = environment.getInt("server.jetty.http.output-buffersize", 32768); @@ -92,8 +96,11 @@ public void startup(int port, String contextPath, String webRoot) throws Excepti servletHolder.setAsyncSupported(false); servletHolder.setInitOrder(1); - context.addServlet(servletHolder, "/"); - server.setHandler(this.context); + webAppContext.addServlet(servletHolder, "/"); + + HandlerList handlers = new HandlerList(); + handlers.setHandlers(new Handler[] { webAppContext, new DefaultHandler() }); + server.setHandler(handlers); server.start(); LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); diff --git a/blade-kit/pom.xml b/blade-kit/pom.xml index 207801348..14e24bf78 100644 --- a/blade-kit/pom.xml +++ b/blade-kit/pom.xml @@ -1,59 +1,53 @@ - - - 4.0.0 - - com.bladejava - blade - 1.0 - - - blade-kit - jar - ${blade-kit.version} - blade-kit - https://github.com/biezhi/blade/tree/master/blade-kit - - - - - org.slf4j - slf4j-api - - - - junit - junit - - - - org.ow2.asm - asm - 5.1 - - - - dom4j - dom4j - 1.6.1 - provided - - - - jaxen - jaxen - 1.1.6 - provided - - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - - - + + + 4.0.0 + + com.bladejava + blade + 1.0 + + + blade-kit + jar + ${blade-kit.version} + blade-kit + https://github.com/biezhi/blade/tree/master/blade-kit + + + + + org.slf4j + slf4j-api + + + + junit + junit + + + + dom4j + dom4j + 1.6.1 + provided + + + + jaxen + jaxen + 1.1.6 + provided + + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + + + diff --git a/pom.xml b/pom.xml index 4721e814a..b607f2058 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 1.6.6-beta 1.3.3 1.0.0 - 0.0.3 + 0.0.4 From 9ed9820e1557b76fd90c36eb8c3730b357f0ea2e Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 2 Sep 2016 13:58:21 +0800 Subject: [PATCH 483/545] => update readme --- LAST_VERSION.md | 7 +- README.md | 366 +++++++++++++++++++++++----------------------- README_CN.md | 378 ++++++++++++++++++++++++------------------------ 3 files changed, 376 insertions(+), 375 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 05580996a..963d0fe5a 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -16,6 +16,7 @@ ``` + 和`dependencies`相同级别 @@ -24,7 +25,7 @@     com.bladejava     blade-kit -    1.3.1 +    1.3.3 ``` @@ -33,7 +34,7 @@     com.bladejava     blade-core -    1.6.4 +    1.6.6-beta ``` @@ -42,7 +43,7 @@     com.bladejava     blade-embed-jetty -    0.0.2 +    0.0.4 ``` diff --git a/README.md b/README.md index 966ff2836..855018a09 100644 --- a/README.md +++ b/README.md @@ -1,183 +1,183 @@ - -[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) - -[Quick Start](https://bladejava.com/docs)  |  [Demo Project](https://github.com/blade-samples)  |  [Contribute](https://bladejava.com/docs/appendix/contribute)  |  [Donate]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) - -[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - - -## What Is Blade? - -Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. -If you like it, please [star and fork it](https://github.com/biezhi/blade). Thank you! - -## Features - -* [x] Lightweight: the code is simple and the structure is clear -* [x] Modular (you can choose which components to use) -* [x] Supports plug-in extension mechanism -* [x] RESTful style routing interface -* [x] Supports multiple configuration files (currently properties, json and coding) -* [x] Embedded jetty server and template engine support -* [x] Supports JDK 1.6 and up - -## Overview - -* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. -* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. - -## Get Start - -To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : - -Grab via `Maven`: - -```xml - - com.bladejava - blade-core - 1.6.6-alpha - - - com.bladejava - blade-embed-jetty - 0.0.3 - -``` -or `Gradle`: -```sh -compile 'com.bladejava:blade-core:1.6.6-alpha' -compile 'com.bladejava:blade-embed-jetty:0.0.3' -``` - -Create `Main` method like this: - -```java -public static void main(String[] args) { - $().get("/", (request, response) -> { - response.html("

Hello blade!

"); - }).start(Application.class); -} -``` - -Run it and point your browser to [http://localhost:9000](http://localhost:9000). There you go, you've just created your first Blade app! - -## API Example - -```java -public static void main(String[] args) { - $().get("/user/21", getxxx); - $().post("/save", postxxx); - $().delete("/del/21", deletexxx); - $().put("/put", putxxx); -} -``` - -## REST URL Parameters - -```java -public static void main(String[] args) { - $().get("/user/:uid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - response.text("uid : " + uid); - }); - - $().get("/users/:uid/post/:pid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - Integer pid = request.paramAsInt("pid"); - String msg = "uid = " + uid + ", pid = " + pid; - response.text(msg); - }); - - $().start(Application.class); -} -``` - -## Form URL Parameters - -```java -public static void main(String[] args) { - $().get("/user", (request, response) -> { - Integer uid = request.queryAsInt("uid"); - response.text("uid : " + uid); - }).start(Application.class); -} -``` - -## Upload File - -```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; - File file = fileItem.getFile(); - - String fileRealPath = "your upload file path!"; - - nioTransferCopy(file, fileRealPath); - } -} -``` - -## Route Config File - -`route.conf` - -```sh -GET / IndexRoute.home -GET /signin IndexRoute.show_signin -POST /signin IndexRoute.signin -GET /signout IndexRoute.signout -POST /upload_img UploadRoute.upload_img -``` - -## Route Intercept - -```java -public static void main(String[] args) { - $().before("/.*", (request, response) -> { - System.out.println("before..."); - }).start(Application.class); -} -``` - -You may refer to these examples for additional guidance: - -+ [Hello Blade](https://github.com/blade-samples/hello) -+ [BBS WebSite](https://github.com/junicorn/java-china) -+ [Doc Service](https://github.com/biezhi/grice) -+ [More Examples](https://github.com/blade-samples) - - -## Update - -[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## Contact - -- Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me@gmail.com - -## Contributor - -Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! - -- [mfarid](https://github.com/mfarid) -- [daimajia](https://github.com/daimajia) -- [shenjie1993](https://github.com/shenjie1993) -- [sumory](https://github.com/sumory) -- [udaykadaboina](https://github.com/udaykadaboina) -- [SyedWasiHaider](https://github.com/SyedWasiHaider) -- [Awakens](https://github.com/Awakens) -- [shellac](https://github.com/shellac) -- [SudarAbisheck](https://github.com/SudarAbisheck) - -## Licenses - -Please see [Apache License](LICENSE) + +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) + +[Quick Start](https://bladejava.com/docs)  |  [Demo Project](https://github.com/blade-samples)  |  [Contribute](https://bladejava.com/docs/appendix/contribute)  |  [Donate]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) + +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + + +## What Is Blade? + +Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. +If you like it, please [star and fork it](https://github.com/biezhi/blade). Thank you! + +## Features + +* [x] Lightweight: the code is simple and the structure is clear +* [x] Modular (you can choose which components to use) +* [x] Supports plug-in extension mechanism +* [x] RESTful style routing interface +* [x] Supports multiple configuration files (currently properties, json and coding) +* [x] Embedded jetty server and template engine support +* [x] Supports JDK 1.6 and up + +## Overview + +* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. +* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. + +## Get Start + +To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : + +Grab via `Maven`: + +```xml + + com.bladejava + blade-core + 1.6.6-beta + + + com.bladejava + blade-embed-jetty + 0.0.4 + +``` +or `Gradle`: +```sh +compile 'com.bladejava:blade-core:1.6.6-beta' +compile 'com.bladejava:blade-embed-jetty:0.0.4' +``` + +Create `Main` method like this: + +```java +public static void main(String[] args) { + $().get("/", (request, response) -> { + response.html("

Hello blade!

"); + }).start(Application.class); +} +``` + +Run it and point your browser to [http://localhost:9000](http://localhost:9000). There you go, you've just created your first Blade app! + +## API Example + +```java +public static void main(String[] args) { + $().get("/user/21", getxxx); + $().post("/save", postxxx); + $().delete("/del/21", deletexxx); + $().put("/put", putxxx); +} +``` + +## REST URL Parameters + +```java +public static void main(String[] args) { + $().get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + $().get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + $().start(Application.class); +} +``` + +## Form URL Parameters + +```java +public static void main(String[] args) { + $().get("/user", (request, response) -> { + Integer uid = request.queryAsInt("uid"); + response.text("uid : " + uid); + }).start(Application.class); +} +``` + +## Upload File + +```java +public void upload_img(Request request, Response response){ + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## Route Config File + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## Route Intercept + +```java +public static void main(String[] args) { + $().before("/.*", (request, response) -> { + System.out.println("before..."); + }).start(Application.class); +} +``` + +You may refer to these examples for additional guidance: + ++ [Hello Blade](https://github.com/blade-samples/hello) ++ [BBS WebSite](https://github.com/junicorn/java-china) ++ [Doc Service](https://github.com/biezhi/grice) ++ [More Examples](https://github.com/blade-samples) + + +## Update + +[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## Contact + +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me@gmail.com + +## Contributor + +Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! + +- [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) + +## Licenses + +Please see [Apache License](LICENSE) diff --git a/README_CN.md b/README_CN.md index 6c177bc4d..34ccccb32 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,189 +1,189 @@ - -[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) - -[开始使用](https://bladejava.com/docs)  |  [示例项目](https://github.com/blade-samples)  |  [贡献代码](https://bladejava.com/docs/appendix/contribute)  |  [捐赠]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [English](https://github.com/biezhi/blade/blob/master/README.md) - -[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) - -## Blade是什么? - -Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁的代码,优雅的设计。 - -如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush: - -## 特性 - -* [x] 轻量级, 代码简洁,结构清晰,更容易开发 -* [x] 模块化(你可以选择使用哪些组件) -* [x] 插件扩展机制 -* [x] Restful风格的路由接口 -* [x] 多种配置文件支持(当前支持properties、json和硬编码) -* [x] 多种模板引擎支持 -* [x] 更方便的启动和部署 -* [x] 支持JDK1.6或者更高版本(JDK8写起来更爽) - -## 概述 - -* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 -* 优雅的:`Blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 -* 易部署:支持 `maven` 打成 `jar` 包直接运行。 - -## 快速入门 - -开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : - -`Maven` 配置: - -```xml - - com.bladejava - blade-core - 1.6.6-alpha - - - com.bladejava - blade-embed-jetty - 0.0.3 - -``` - -或者 `Gradle`: - -```sh -compile 'com.bladejava:blade-core:1.6.6-alpha' -compile 'com.bladejava:blade-embed-jetty:0.0.3' -``` - -编写 `Main`函数: - -```java -public static void main(String[] args) { - $().get("/", (request, response) -> { - response.html("

Hello blade!

"); - }).start(Application.class); -} -``` - -用浏览器打开 http://localhost:9000 这样就可以看到第一个Blade应用了! - -## API示例 - -```java -public static void main(String[] args) { - $().get("/user/21", getxxx); - $().post("/save", postxxx); - $().delete("/del/21", deletexxx); - $().put("/put", putxxx); -} -``` - -## REST URL参数获取 - -```java -public static void main(String[] args) { - $().get("/user/:uid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - response.text("uid : " + uid); - }); - - $().get("/users/:uid/post/:pid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - Integer pid = request.paramAsInt("pid"); - String msg = "uid = " + uid + ", pid = " + pid; - response.text(msg); - }); - - $().start(Application.class); -} -``` - -## 表单参数获取 - -```java -public static void main(String[] args) { - $().get("/user", (request, response) -> { - Integer uid = request.queryAsInt("uid"); - response.text("uid : " + uid); - }).start(Application.class); -} -``` - -## 上传文件 - -```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; - File file = fileItem.getFile(); - - String fileRealPath = "your upload file path!"; - - nioTransferCopy(file, fileRealPath); - } -} -``` - -## 配置文件路由 - -`route.conf` - -```sh -GET / IndexRoute.home -GET /signin IndexRoute.show_signin -POST /signin IndexRoute.signin -GET /signout IndexRoute.signout -POST /upload_img UploadRoute.upload_img -``` - -## 路由拦截 - -```java -public static void main(String[] args) { - $().before("/.*", (request, response) -> { - System.out.println("before..."); - }).start(Application.class); -} -``` - - -这一切看起来多么的简单,不过上面的功能可是冰山一角,查看文档和示例项目有更多惊喜: - -+ [hello工程](https://github.com/blade-samples/hello) -+ [论坛程序](https://github.com/junicorn/java-china) -+ [文档服务](https://github.com/biezhi/grice) -+ [更多例子](https://github.com/blade-samples) - - -## 更新日志 - -[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## 联系我 - -- Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me#gmail.com -- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) - -## 贡献 - -非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! - -- [mfarid](https://github.com/mfarid) -- [daimajia](https://github.com/daimajia) -- [shenjie1993](https://github.com/shenjie1993) -- [sumory](https://github.com/sumory) -- [udaykadaboina](https://github.com/udaykadaboina) -- [SyedWasiHaider](https://github.com/SyedWasiHaider) -- [Awakens](https://github.com/Awakens) -- [shellac](https://github.com/shellac) -- [SudarAbisheck](https://github.com/SudarAbisheck) - -## 开源协议 - -请查看 [Apache License](LICENSE) + +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) + +[开始使用](https://bladejava.com/docs)  |  [示例项目](https://github.com/blade-samples)  |  [贡献代码](https://bladejava.com/docs/appendix/contribute)  |  [捐赠]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [English](https://github.com/biezhi/blade/blob/master/README.md) + +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) + +## Blade是什么? + +Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁的代码,优雅的设计。 + +如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush: + +## 特性 + +* [x] 轻量级, 代码简洁,结构清晰,更容易开发 +* [x] 模块化(你可以选择使用哪些组件) +* [x] 插件扩展机制 +* [x] Restful风格的路由接口 +* [x] 多种配置文件支持(当前支持properties、json和硬编码) +* [x] 多种模板引擎支持 +* [x] 更方便的启动和部署 +* [x] 支持JDK1.6或者更高版本(JDK8写起来更爽) + +## 概述 + +* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 +* 优雅的:`Blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 +* 易部署:支持 `maven` 打成 `jar` 包直接运行。 + +## 快速入门 + +开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : + +`Maven` 配置: + +```xml + + com.bladejava + blade-core + 1.6.6-beta + + + com.bladejava + blade-embed-jetty + 0.0.4 + +``` + +或者 `Gradle`: + +```sh +compile 'com.bladejava:blade-core:1.6.6-beta' +compile 'com.bladejava:blade-embed-jetty:0.0.4' +``` + +编写 `Main`函数: + +```java +public static void main(String[] args) { + $().get("/", (request, response) -> { + response.html("

Hello blade!

"); + }).start(Application.class); +} +``` + +用浏览器打开 http://localhost:9000 这样就可以看到第一个Blade应用了! + +## API示例 + +```java +public static void main(String[] args) { + $().get("/user/21", getxxx); + $().post("/save", postxxx); + $().delete("/del/21", deletexxx); + $().put("/put", putxxx); +} +``` + +## REST URL参数获取 + +```java +public static void main(String[] args) { + $().get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + $().get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + $().start(Application.class); +} +``` + +## 表单参数获取 + +```java +public static void main(String[] args) { + $().get("/user", (request, response) -> { + Integer uid = request.queryAsInt("uid"); + response.text("uid : " + uid); + }).start(Application.class); +} +``` + +## 上传文件 + +```java +public void upload_img(Request request, Response response){ + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## 配置文件路由 + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## 路由拦截 + +```java +public static void main(String[] args) { + $().before("/.*", (request, response) -> { + System.out.println("before..."); + }).start(Application.class); +} +``` + + +这一切看起来多么的简单,不过上面的功能可是冰山一角,查看文档和示例项目有更多惊喜: + ++ [hello工程](https://github.com/blade-samples/hello) ++ [论坛程序](https://github.com/junicorn/java-china) ++ [文档服务](https://github.com/biezhi/grice) ++ [更多例子](https://github.com/blade-samples) + + +## 更新日志 + +[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## 联系我 + +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me#gmail.com +- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) + +## 贡献 + +非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! + +- [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) + +## 开源协议 + +请查看 [Apache License](LICENSE) From f30c67e2c142c0e72da1b9536f9b3d2171051b81 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 2 Sep 2016 17:26:10 +0800 Subject: [PATCH 484/545] => fix config route parameter bug --- blade-core/src/main/java/com/blade/Blade.java | 18 +- .../com/blade/context/DynamicClassReader.java | 19 +- .../java/com/blade/embedd/EmbedServer.java | 70 ++-- .../main/java/com/blade/route/Routers.java | 375 +++++++++--------- .../com/blade/view/template/JspEngine.java | 24 +- .../main/java/com/blade/web/DispatchKit.java | 51 ++- .../java/com/blade/web/DispatcherServlet.java | 27 +- .../com/blade/embedd/EmbedJettyServer.java | 29 +- 8 files changed, 340 insertions(+), 273 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index e5b702c07..9afcfe819 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -87,6 +87,9 @@ public final class Blade { // config loader private ConfigLoader configLoader; + // embed server + private EmbedServer embedServer; + private Blade() { this.environment = new Environment(); this.applicationConfig = new ApplicationConfig(); @@ -602,8 +605,8 @@ public void start(Class applicationClass) { embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); } if(null != embedClazz){ - EmbedServer embedServer = (EmbedServer) embedClazz.newInstance(); - embedServer.startup(port, contextPath); + this.embedServer = (EmbedServer) embedClazz.newInstance(); + this.embedServer.startup(port, contextPath); this.enableServer = true; } else { throw new EmbedServerException("Not found EmbedServer"); @@ -612,7 +615,14 @@ public void start(Class applicationClass) { e.printStackTrace(); } } - + + /** + * @return Return EmbedServer + */ + public EmbedServer embedServer() { + return this.embedServer; + } + /** * @return Return blade config object */ @@ -753,5 +763,5 @@ public boolean enableServer() { public Set> plugins() { return this.plugins; } - + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java index 94a3db870..c4381d9cc 100644 --- a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java +++ b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java @@ -15,6 +15,9 @@ */ package com.blade.context; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.Blade; import com.blade.kit.resource.ClassPathClassReader; import com.blade.kit.resource.ClassReader; @@ -28,7 +31,7 @@ */ public final class DynamicClassReader { - private static boolean IS_JAR_CONTEXT = false; + private static final Logger LOGGER = LoggerFactory.getLogger(DynamicClassReader.class); private static ClassReader CLASS_READER = null; @@ -38,19 +41,15 @@ private DynamicClassReader() { public static void init(){ Class clazz = Blade.$().config().getApplicationClass(); String rs = clazz.getResource("").toString(); - if(rs.indexOf(".jar!") != -1){ - IS_JAR_CONTEXT = true; + if(rs.indexOf(".jar") != -1){ + CLASS_READER = new JarReaderImpl(); + LOGGER.debug("{}", CLASS_READER); + } else{ + CLASS_READER = new ClassPathClassReader(); } } public static ClassReader getClassReader(){ - if(null != CLASS_READER){ - return CLASS_READER; - } - if(IS_JAR_CONTEXT){ - CLASS_READER = new JarReaderImpl(); - } - CLASS_READER = new ClassPathClassReader(); return CLASS_READER; } diff --git a/blade-core/src/main/java/com/blade/embedd/EmbedServer.java b/blade-core/src/main/java/com/blade/embedd/EmbedServer.java index 898e83180..6439cf741 100644 --- a/blade-core/src/main/java/com/blade/embedd/EmbedServer.java +++ b/blade-core/src/main/java/com/blade/embedd/EmbedServer.java @@ -1,34 +1,36 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.embedd; - -/** - * Jetty Server - * - * @author biezhi - * @since 1.6.6 - */ -public interface EmbedServer { - - void startup(int port) throws Exception; - - void startup(int port, String contextPath) throws Exception; - - void startup(int port, String contextPath, String webRoot) throws Exception; - - void stop() throws Exception; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.embedd; + +/** + * Jetty Server + * + * @author biezhi + * @since 1.6.6 + */ +public interface EmbedServer { + + void startup(int port) throws Exception; + + void startup(int port, String contextPath) throws Exception; + + void startup(int port, String contextPath, String webRoot) throws Exception; + + void stop() throws Exception; + + void setWebRoot(String webRoot); + +} diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/route/Routers.java index 0ae0f213d..d3b01200a 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/route/Routers.java @@ -1,183 +1,192 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; - -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.kit.Assert; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Request; -import com.blade.web.http.Response; - -/** - * Registration, management route - * - * @author biezhi - * @since 1.5 - */ -public class Routers { - - private Logger LOGGER = LoggerFactory.getLogger(Routers.class); - - private Map routes = null; - - private Map interceptors = null; - - private static final String METHOD_NAME = "handle"; - - public Routers() { - this.routes = new HashMap(); - this.interceptors = new HashMap(); - } - - public Map getRoutes() { - return routes; - } - - public Map getInterceptors() { - return interceptors; - } - - public void addRoute(Route route) { - String path = route.getPath(); - HttpMethod httpMethod = route.getHttpMethod(); - String key = path + "#" + httpMethod.toString(); - - // existent - if (null != this.routes.get(key)) { - LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); - } - - if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ - if (null != this.interceptors.get(key)) { - LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); - } - this.interceptors.put(key, route); - LOGGER.debug("Add Interceptor: {}", route); - } else { - this.routes.put(key, route); - LOGGER.debug("Add Route: {}", route); - } - } - - public void addRoutes(List routes) { - Assert.notNull(routes); - for(Route route : routes){ - this.addRoute(route); - } - } - - public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, String methodName) throws NoSuchMethodException { - Class handleType = handler.getClass(); - Method method = handleType.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, handler, RouteHandler.class, method); - } - - public void addRoute(HttpMethod httpMethod, String path, Object controller, Class controllerType, Method method) { - - Assert.notNull(httpMethod); - Assert.notBlank(path); - Assert.notNull(method); - - String key = path + "#" + httpMethod.toString(); - // existent - if (null != this.routes.get(key)) { - LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); - } - - Route route = new Route(httpMethod, path, controller, controllerType, method); - if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ - if (null != this.interceptors.get(key)) { - LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); - } - this.interceptors.put(key, route); - LOGGER.info("Add Interceptor: {}", route); - } else { - this.routes.put(key, route); - LOGGER.info("Add Route: {}", route); - } - - } - - public void route(String path, RouteHandler handler, HttpMethod httpMethod) { - try { - addRoute(httpMethod, path, handler, METHOD_NAME); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) { - for(String path : paths){ - route(path, handler, httpMethod); - } - } - - public void route(String path, Class clazz, String methodName) { - - Assert.notNull(path, "Route path not is null!"); - Assert.notNull(clazz, "Class Type not is null!"); - Assert.notNull(methodName, "Method name not is null"); - - HttpMethod httpMethod = HttpMethod.ALL; - if(methodName.indexOf(":") != -1){ - String[] methodArr = methodName.split(":"); - httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); - methodName = methodArr[1]; - } - try { - Method method = clazz.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, null, clazz, method); - } catch (NoSuchMethodException e) { - try { - Method method = clazz.getMethod(methodName, Response.class, Request.class); - addRoute(httpMethod, path, null, clazz, method); - } catch (NoSuchMethodException e1) { - e1.printStackTrace(); - } catch (SecurityException e1) { - e1.printStackTrace(); - } - } catch (SecurityException e) { - e.printStackTrace(); - } - } - - public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) { - try { - Assert.notNull(path, "Route path not is null!"); - Assert.notNull(clazz, "Class Type not is null!"); - Assert.notNull(methodName, "Method name not is null"); - Assert.notNull(httpMethod, "Request Method not is null"); - Method method = clazz.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, null, clazz, method); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - } - - public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { - addRoute(httpMethod, path, null, clazz, method); - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.route; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.kit.reflect.ReflectKit; +import com.blade.web.http.HttpMethod; +import com.blade.web.http.Request; +import com.blade.web.http.Response; + +/** + * Registration, management route + * + * @author biezhi + * @since 1.5 + */ +public class Routers { + + private static final Logger LOGGER = LoggerFactory.getLogger(Routers.class); + + private Map routes = null; + + private Map interceptors = null; + + private static final String METHOD_NAME = "handle"; + + public Routers() { + this.routes = new HashMap(); + this.interceptors = new HashMap(); + } + + public Map getRoutes() { + return routes; + } + + public Map getInterceptors() { + return interceptors; + } + + public void addRoute(Route route) { + String path = route.getPath(); + HttpMethod httpMethod = route.getHttpMethod(); + String key = path + "#" + httpMethod.toString(); + + // existent + if (null != this.routes.get(key)) { + LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); + } + + if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ + if (null != this.interceptors.get(key)) { + LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); + } + this.interceptors.put(key, route); + LOGGER.debug("Add Interceptor => {}", route); + } else { + this.routes.put(key, route); + LOGGER.debug("Add Route => {}", route); + } + } + + public void addRoutes(List routes) { + Assert.notNull(routes); + for(Route route : routes){ + this.addRoute(route); + } + } + + public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, String methodName) throws NoSuchMethodException { + Class handleType = handler.getClass(); + Method method = handleType.getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, handler, RouteHandler.class, method); + } + + public void addRoute(HttpMethod httpMethod, String path, Object controller, Class controllerType, Method method) { + + Assert.notNull(httpMethod); + Assert.notBlank(path); + Assert.notNull(method); + + String key = path + "#" + httpMethod.toString(); + // existent + if (null != this.routes.get(key)) { + LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); + } + + Route route = new Route(httpMethod, path, controller, controllerType, method); + if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ + if (null != this.interceptors.get(key)) { + LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); + } + this.interceptors.put(key, route); + LOGGER.info("Add Interceptor: {}", route); + } else { + this.routes.put(key, route); + LOGGER.info("Add Route => {}", route); + } + + } + + public void route(String path, RouteHandler handler, HttpMethod httpMethod) { + try { + addRoute(httpMethod, path, handler, METHOD_NAME); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) { + for(String path : paths){ + route(path, handler, httpMethod); + } + } + + private Map classMethosPool = new HashMap(8); + + public void route(String path, Class clazz, String methodName) { + + Assert.notNull(path, "Route path not is null!"); + Assert.notNull(clazz, "Class Type not is null!"); + Assert.notNull(methodName, "Method name not is null"); + + HttpMethod httpMethod = HttpMethod.ALL; + if(methodName.indexOf(":") != -1){ + String[] methodArr = methodName.split(":"); + httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); + methodName = methodArr[1]; + } + try { + + Method[] methods = classMethosPool.get(clazz.getName()); + if(null == methods){ + methods = clazz.getMethods(); + classMethosPool.put(clazz.getName(), methods); + } + if(null != methods){ + for(Method method : methods){ + if(method.getName().equals(methodName)){ + addRoute(httpMethod, path, ReflectKit.newInstance(clazz), clazz, method); + } + } + } + } catch (SecurityException e) { + LOGGER.error(e.getMessage(), e); + } catch (InstantiationException e) { + LOGGER.error(e.getMessage(), e); + } catch (IllegalAccessException e) { + LOGGER.error(e.getMessage(), e); + } + } + + public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) { + try { + Assert.notNull(path, "Route path not is null!"); + Assert.notNull(clazz, "Class Type not is null!"); + Assert.notNull(methodName, "Method name not is null"); + Assert.notNull(httpMethod, "Request Method not is null"); + Method method = clazz.getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, null, clazz, method); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + } + + public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { + addRoute(httpMethod, path, null, clazz, method); + } + +} diff --git a/blade-core/src/main/java/com/blade/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/view/template/JspEngine.java index abe2269cb..b3f660e0d 100644 --- a/blade-core/src/main/java/com/blade/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/view/template/JspEngine.java @@ -37,6 +37,7 @@ public final class JspEngine implements TemplateEngine { private String viewPath = "/views/"; + private String suffix = ".jsp"; public JspEngine() { } @@ -45,14 +46,31 @@ public JspEngine(String viewPath) { this.viewPath = viewPath; } + public String getViewPath() { + return viewPath; + } + + public void setViewPath(String viewPath) { + this.viewPath = viewPath; + } + + public String getSuffix() { + return suffix; + } + + public void setSuffix(String suffix) { + this.suffix = suffix; + } + @Override public void render(ModelAndView modelAndView, Writer writer) throws TemplateException { HttpServletRequest request = ApplicationWebContext.request().raw(); HttpServletResponse response = ApplicationWebContext.response().raw(); try { Map model = modelAndView.getModel(); - String realPath = viewPath + modelAndView.getView(); - if (null != model && !model.isEmpty()) { + String realPath = viewPath + modelAndView.getView() + suffix; + + if (!model.isEmpty()) { Set keys = model.keySet(); for (String key : keys) { request.setAttribute(key, model.get(key)); @@ -63,6 +81,8 @@ public void render(ModelAndView modelAndView, Writer writer) throws TemplateExce throw new TemplateException(e); } catch (IOException e) { throw new TemplateException(e); + } catch (Exception e) { + throw new TemplateException(e); } } diff --git a/blade-core/src/main/java/com/blade/web/DispatchKit.java b/blade-core/src/main/java/com/blade/web/DispatchKit.java index 506e35b3c..415886447 100644 --- a/blade-core/src/main/java/com/blade/web/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/web/DispatchKit.java @@ -28,32 +28,53 @@ import com.blade.kit.StringKit; import com.blade.web.http.HttpException; import com.blade.web.http.Response; +import static com.blade.Blade.$; public class DispatchKit { private static final Logger LOGGER = LoggerFactory.getLogger(DispatchKit.class); - static final boolean isWeb = !Blade.$().enableServer(); + static final boolean isWeb = !$().enableServer(); - static final Class appClass = Blade.$().config().getApplicationClass(); + static final Class appClass = $().config().getApplicationClass(); private static Boolean isDev = null; - - public static File getWebRoot(ServletContext sc) { - String dir = sc.getRealPath("/"); - if (dir == null) { - try { - URL url = sc.getResource("/"); - if (url != null && "file".equals(url.getProtocol())) { - dir = URLDecoder.decode(url.getFile(), "utf-8"); - } else { - throw new IllegalStateException("Can't get webroot dir, url = " + url); + + public static String getPath(Class clazz) { + URL url = clazz.getProtectionDomain().getCodeSource().getLocation(); + String filePath = null; + try { + filePath = URLDecoder.decode(url.getPath(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } + if (filePath.endsWith(".jar")) { + filePath = "jar:file:" + filePath + "!/"; + return filePath; + } + File file = new File(filePath); + filePath = file.getAbsolutePath(); + return filePath; + } + + public static String getWebRoot(ServletContext sc) { + if(isWeb){ + String dir = sc.getRealPath("/"); + if (dir == null) { + try { + URL url = sc.getResource("/"); + if (url != null && "file".equals(url.getProtocol())) { + dir = URLDecoder.decode(url.getFile(), "utf-8"); + } else { + throw new IllegalStateException("Can't get webroot dir, url = " + url); + } + } catch (IOException e) { + throw new IllegalStateException(e); } - } catch (IOException e) { - throw new IllegalStateException(e); } + return dir; } - return new File(dir); + return getPath(appClass); } public static void setNoCache(HttpServletResponse response) { diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index 21c240751..dccf21fbb 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -33,6 +33,7 @@ import com.blade.context.ApplicationContext; import com.blade.context.ApplicationWebContext; import com.blade.context.DynamicClassReader; +import com.blade.embedd.EmbedServer; import com.blade.kit.StringKit; import com.blade.kit.SystemKit; @@ -69,21 +70,27 @@ public void init(ServletConfig config) throws ServletException { servletContext = config.getServletContext(); if(!blade.isInit()){ - LOGGER.info("jdk.version = {}", SystemKit.getJavaInfo().getVersion()); - LOGGER.info("user.dir = {}", System.getProperty("user.dir")); - LOGGER.info("java.io.tmpdir = {}", System.getProperty("java.io.tmpdir")); - LOGGER.info("user.timezone = {}", System.getProperty("user.timezone")); - LOGGER.info("file.encoding = {}", System.getProperty("file.encoding")); - - DynamicClassReader.init(); + LOGGER.info("jdk.version\t=> {}", SystemKit.getJavaInfo().getVersion()); + LOGGER.info("user.dir\t=> {}", System.getProperty("user.dir")); + LOGGER.info("java.io.tmpdir\t=> {}", System.getProperty("java.io.tmpdir")); + LOGGER.info("user.timezone\t=> {}", System.getProperty("user.timezone")); + LOGGER.info("file.encodin\t=> {}", System.getProperty("file.encoding")); long initStart = System.currentTimeMillis(); - blade.webRoot(DispatchKit.getWebRoot(servletContext).getPath()); + String webRoot = DispatchKit.getWebRoot(servletContext); + + blade.webRoot(webRoot); + EmbedServer embedServer = blade.embedServer(); + if(null != embedServer){ + embedServer.setWebRoot(webRoot); + } - ApplicationWebContext.init(servletContext); + LOGGER.info("blade.webroot\t=> {}", webRoot); - LOGGER.info("blade.webroot = {}", blade.webRoot()); + DynamicClassReader.init(); + + ApplicationWebContext.init(servletContext); this.bootstrap = blade.bootstrap(); diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index 3fb7820a9..a2c96e96a 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -1,5 +1,7 @@ package com.blade.embedd; +import static com.blade.Blade.$; + import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; @@ -12,12 +14,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.blade.Blade; import com.blade.Const; import com.blade.kit.Environment; -import com.blade.kit.StringKit; import com.blade.web.DispatcherServlet; -import static com.blade.Blade.$; public class EmbedJettyServer implements EmbedServer { @@ -32,6 +31,7 @@ public class EmbedJettyServer implements EmbedServer { private Environment environment = null; public EmbedJettyServer() { + System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); $().loadAppConf("jetty.properties"); environment = $().environment(); $().enableServer(true); @@ -47,6 +47,11 @@ public void startup(int port, String contextPath) throws Exception { this.startup(port, contextPath, null); } + @Override + public void setWebRoot(String webRoot) { + webAppContext.setResourceBase(webRoot); + } + @Override public void startup(int port, String contextPath, String webRoot) throws Exception { this.port = port; @@ -54,23 +59,21 @@ public void startup(int port, String contextPath, String webRoot) throws Excepti // Setup Threadpool QueuedThreadPool threadPool = new QueuedThreadPool(); - int maxThreads = environment.getInt("server.jetty.max-threads", 100); + int minThreads = environment.getInt("server.jetty.min-threads", 100); + int maxThreads = environment.getInt("server.jetty.max-threads", 500); + threadPool.setMinThreads(minThreads); threadPool.setMaxThreads(maxThreads); server = new org.eclipse.jetty.server.Server(threadPool); + // 设置在JVM退出时关闭Jetty的钩子。 server.setStopAtShutdown(true); webAppContext = new WebAppContext(); webAppContext.setContextPath(contextPath); - - if(StringKit.isBlank(webRoot)){ - webRoot = Blade.$().config().getApplicationClass().getResource("/").getPath(); - } - - webAppContext.setResourceBase(webRoot); - + webAppContext.setResourceBase(""); + int securePort = environment.getInt("server.jetty.http.secure-port", 8443); int outputBufferSize = environment.getInt("server.jetty.http.output-buffersize", 32768); int requestHeaderSize = environment.getInt("server.jetty.http.request-headersize", 8192); @@ -111,8 +114,4 @@ public void stop() throws Exception { server.stop(); } - public void waitForInterrupt() throws InterruptedException { - server.join(); - } - } \ No newline at end of file From 46e7ae374f910d6cff71dca3c30d87bffac8d486 Mon Sep 17 00:00:00 2001 From: biezhi Date: Fri, 2 Sep 2016 17:57:22 +0800 Subject: [PATCH 485/545] => fix user.dir console print dislocation --- blade-core/src/main/java/com/blade/web/DispatcherServlet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java index dccf21fbb..df644ae9e 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/web/DispatcherServlet.java @@ -71,7 +71,7 @@ public void init(ServletConfig config) throws ServletException { if(!blade.isInit()){ LOGGER.info("jdk.version\t=> {}", SystemKit.getJavaInfo().getVersion()); - LOGGER.info("user.dir\t=> {}", System.getProperty("user.dir")); + LOGGER.info("user.dir\t\t=> {}", System.getProperty("user.dir")); LOGGER.info("java.io.tmpdir\t=> {}", System.getProperty("java.io.tmpdir")); LOGGER.info("user.timezone\t=> {}", System.getProperty("user.timezone")); LOGGER.info("file.encodin\t=> {}", System.getProperty("file.encoding")); From 8ad7c48bd48ecd3c586594447629b73fa07f5e01 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 3 Sep 2016 20:47:58 +0800 Subject: [PATCH 486/545] =?UTF-8?q?=E2=9C=84=20rename=20web=20to=20mvc=20a?= =?UTF-8?q?nd=20add=20banner=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LAST_VERSION.md | 170 ++++---- README.md | 366 ++++++++--------- README_CN.md | 378 +++++++++--------- .../java/com/blade/auth/CSRFTokenManager.java | 6 +- blade-core/src/main/java/com/blade/Blade.java | 18 +- .../src/main/java/com/blade/BladeBanner.java | 23 -- .../main/java/com/blade/annotation/Route.java | 2 +- .../main/java/com/blade/banner/Banner.java | 22 + .../java/com/blade/banner/BannerStarter.java | 31 ++ .../java/com/blade/banner/BladeBanner.java | 38 ++ .../blade/context/ApplicationWebContext.java | 6 +- .../com/blade/interceptor/package-info.java | 4 - .../java/com/blade/ioc/IocApplication.java | 4 +- .../com/blade/{web => mvc}/DispatchKit.java | 7 +- .../blade/{web => mvc}/DispatcherHandler.java | 28 +- .../blade/{web => mvc}/DispatcherServlet.java | 6 +- .../blade/{web => mvc}/StaticFileFilter.java | 2 +- .../{web => mvc}/http/HttpException.java | 2 +- .../blade/{web => mvc}/http/HttpMethod.java | 2 +- .../blade/{web => mvc}/http/HttpStatus.java | 2 +- .../com/blade/{web => mvc}/http/Path.java | 2 +- .../com/blade/{web => mvc}/http/Request.java | 8 +- .../com/blade/{web => mvc}/http/Response.java | 4 +- .../blade/{web => mvc}/http/package-info.java | 2 +- .../http/wrapper/ServletRequest.java | 18 +- .../http/wrapper/ServletResponse.java | 22 +- .../{web => mvc}/http/wrapper/Session.java | 2 +- .../blade/mvc/http/wrapper/package-info.java | 4 + .../{ => mvc}/interceptor/Interceptor.java | 6 +- .../blade/mvc/interceptor/package-info.java | 4 + .../{web => mvc}/multipart/FileItem.java | 2 +- .../{web => mvc}/multipart/Multipart.java | 2 +- .../multipart/MultipartException.java | 2 +- .../multipart/MultipartHandler.java | 2 +- .../multipart/MultipartReader.java | 2 +- .../multipart/ParameterParser.java | 2 +- .../blade/{web => mvc}/multipart/Streams.java | 2 +- .../com/blade/mvc/multipart/package-info.java | 4 + .../com/blade/{web => mvc}/package-info.java | 2 +- .../java/com/blade/{ => mvc}/route/Route.java | 6 +- .../blade/{ => mvc}/route/RouteBuilder.java | 10 +- .../blade/{ => mvc}/route/RouteException.java | 2 +- .../com/blade/{ => mvc}/route/RouteGroup.java | 2 +- .../blade/{ => mvc}/route/RouteHandler.java | 6 +- .../blade/{ => mvc}/route/RouteMatcher.java | 6 +- .../com/blade/{ => mvc}/route/Routers.java | 8 +- .../route/loader/AbstractFileRouteLoader.java | 12 +- .../loader/ClassPathControllerLoader.java | 4 +- .../route/loader/ClassPathRouteLoader.java | 2 +- .../route/loader/ControllerLoader.java | 4 +- .../route/loader/FileSystemRouteLoader.java | 2 +- .../{ => mvc}/route/loader/RouteLoader.java | 6 +- .../com/blade/mvc/route/package-info.java | 4 + .../blade/{ => mvc}/view/ModelAndView.java | 2 +- .../com/blade/{ => mvc}/view/ModelMap.java | 4 +- .../blade/{ => mvc}/view/ViewSettings.java | 10 +- .../{ => mvc}/view/handle/MethodArgument.java | 10 +- .../view/handle/RouteViewHandler.java | 12 +- .../view/parser/DefaultJSONParser.java | 2 +- .../{ => mvc}/view/parser/JSONParser.java | 2 +- .../view/template/DefaultEngine.java | 4 +- .../{ => mvc}/view/template/JspEngine.java | 4 +- .../view/template/TemplateEngine.java | 4 +- .../view/template/TemplateException.java | 2 +- .../blade/mvc/view/template/package-info.java | 4 + .../java/com/blade/route/package-info.java | 4 - .../com/blade/view/template/package-info.java | 4 - .../blade/web/http/wrapper/package-info.java | 4 - .../com/blade/web/multipart/package-info.java | 4 - .../com/blade/embedd/EmbedJettyServer.java | 2 +- pom.xml | 2 +- 71 files changed, 716 insertions(+), 647 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/BladeBanner.java create mode 100644 blade-core/src/main/java/com/blade/banner/Banner.java create mode 100644 blade-core/src/main/java/com/blade/banner/BannerStarter.java create mode 100644 blade-core/src/main/java/com/blade/banner/BladeBanner.java delete mode 100644 blade-core/src/main/java/com/blade/interceptor/package-info.java rename blade-core/src/main/java/com/blade/{web => mvc}/DispatchKit.java (95%) rename blade-core/src/main/java/com/blade/{web => mvc}/DispatcherHandler.java (88%) rename blade-core/src/main/java/com/blade/{web => mvc}/DispatcherServlet.java (95%) rename blade-core/src/main/java/com/blade/{web => mvc}/StaticFileFilter.java (98%) rename blade-core/src/main/java/com/blade/{web => mvc}/http/HttpException.java (93%) rename blade-core/src/main/java/com/blade/{web => mvc}/http/HttpMethod.java (96%) rename blade-core/src/main/java/com/blade/{web => mvc}/http/HttpStatus.java (98%) rename blade-core/src/main/java/com/blade/{web => mvc}/http/Path.java (98%) rename blade-core/src/main/java/com/blade/{web => mvc}/http/Request.java (97%) rename blade-core/src/main/java/com/blade/{web => mvc}/http/Response.java (93%) rename blade-core/src/main/java/com/blade/{web => mvc}/http/package-info.java (54%) rename blade-core/src/main/java/com/blade/{web => mvc}/http/wrapper/ServletRequest.java (97%) rename blade-core/src/main/java/com/blade/{web => mvc}/http/wrapper/ServletResponse.java (91%) rename blade-core/src/main/java/com/blade/{web => mvc}/http/wrapper/Session.java (98%) create mode 100644 blade-core/src/main/java/com/blade/mvc/http/wrapper/package-info.java rename blade-core/src/main/java/com/blade/{ => mvc}/interceptor/Interceptor.java (89%) create mode 100644 blade-core/src/main/java/com/blade/mvc/interceptor/package-info.java rename blade-core/src/main/java/com/blade/{web => mvc}/multipart/FileItem.java (98%) rename blade-core/src/main/java/com/blade/{web => mvc}/multipart/Multipart.java (99%) rename blade-core/src/main/java/com/blade/{web => mvc}/multipart/MultipartException.java (97%) rename blade-core/src/main/java/com/blade/{web => mvc}/multipart/MultipartHandler.java (96%) rename blade-core/src/main/java/com/blade/{web => mvc}/multipart/MultipartReader.java (99%) rename blade-core/src/main/java/com/blade/{web => mvc}/multipart/ParameterParser.java (99%) rename blade-core/src/main/java/com/blade/{web => mvc}/multipart/Streams.java (99%) create mode 100644 blade-core/src/main/java/com/blade/mvc/multipart/package-info.java rename blade-core/src/main/java/com/blade/{web => mvc}/package-info.java (54%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/Route.java (96%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/RouteBuilder.java (97%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/RouteException.java (97%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/RouteGroup.java (98%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/RouteHandler.java (89%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/RouteMatcher.java (97%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/Routers.java (94%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/loader/AbstractFileRouteLoader.java (96%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/loader/ClassPathControllerLoader.java (96%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/loader/ClassPathRouteLoader.java (97%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/loader/ControllerLoader.java (91%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/loader/FileSystemRouteLoader.java (97%) rename blade-core/src/main/java/com/blade/{ => mvc}/route/loader/RouteLoader.java (88%) create mode 100644 blade-core/src/main/java/com/blade/mvc/route/package-info.java rename blade-core/src/main/java/com/blade/{ => mvc}/view/ModelAndView.java (98%) rename blade-core/src/main/java/com/blade/{ => mvc}/view/ModelMap.java (85%) rename blade-core/src/main/java/com/blade/{ => mvc}/view/ViewSettings.java (87%) rename blade-core/src/main/java/com/blade/{ => mvc}/view/handle/MethodArgument.java (93%) rename blade-core/src/main/java/com/blade/{ => mvc}/view/handle/RouteViewHandler.java (90%) rename blade-core/src/main/java/com/blade/{ => mvc}/view/parser/DefaultJSONParser.java (96%) rename blade-core/src/main/java/com/blade/{ => mvc}/view/parser/JSONParser.java (95%) rename blade-core/src/main/java/com/blade/{ => mvc}/view/template/DefaultEngine.java (96%) rename blade-core/src/main/java/com/blade/{ => mvc}/view/template/JspEngine.java (93%) rename blade-core/src/main/java/com/blade/{ => mvc}/view/template/TemplateEngine.java (92%) rename blade-core/src/main/java/com/blade/{ => mvc}/view/template/TemplateException.java (96%) create mode 100644 blade-core/src/main/java/com/blade/mvc/view/template/package-info.java delete mode 100644 blade-core/src/main/java/com/blade/route/package-info.java delete mode 100644 blade-core/src/main/java/com/blade/view/template/package-info.java delete mode 100644 blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java delete mode 100644 blade-core/src/main/java/com/blade/web/multipart/package-info.java diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 963d0fe5a..f5302eacd 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -1,85 +1,85 @@ -# blade last version - -如果在maven仓库中下载不到最新版本的依赖,请添加maven snapshots仓库 - -```xml - - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - -``` - -和`dependencies`相同级别 - - -## [blade-kit](http://search.maven.org/#search%7Cga%7C1%7Cblade-kit) -```xml - -    com.bladejava -    blade-kit -    1.3.3 - -``` - -## [blade-core](http://search.maven.org/#search%7Cga%7C1%7Cblade-core) -```xml - -    com.bladejava -    blade-core -    1.6.6-beta - -``` - -## [blade-embed-jetty](http://search.maven.org/#search%7Cga%7C1%7Cblade-embed-jetty) -```xml - -    com.bladejava -    blade-embed-jetty -    0.0.4 - -``` - -## [blade-jdbc](http://search.maven.org/#search%7Cga%7C1%7Cblade-jdbc) -```xml - -    com.bladejava -    blade-jdbc -    0.1.2 - -``` - -## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache) -```xml - -    com.bladejava -    blade-cache -    1.2.3 - -``` - -## [blade-redis](http://search.maven.org/#search%7Cga%7C1%7Cblade-redis) -```xml - -    com.bladejava -    blade-redis -    1.2.3 - -``` - -## [blade-patchca](http://search.maven.org/#search%7Cga%7C1%7Cblade-patchca) -```xml - -    com.bladejava -    blade-patchca -    1.0.2 - -``` - +# blade last version + +如果在maven仓库中下载不到最新版本的依赖,请添加maven snapshots仓库 + +```xml + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + +``` + +和`dependencies`相同级别 + + +## [blade-kit](http://search.maven.org/#search%7Cga%7C1%7Cblade-kit) +```xml + +    com.bladejava +    blade-kit +    1.3.3 + +``` + +## [blade-core](http://search.maven.org/#search%7Cga%7C1%7Cblade-core) +```xml + +    com.bladejava +    blade-core +    1.6.6 + +``` + +## [blade-embed-jetty](http://search.maven.org/#search%7Cga%7C1%7Cblade-embed-jetty) +```xml + +    com.bladejava +    blade-embed-jetty +    0.0.4 + +``` + +## [blade-jdbc](http://search.maven.org/#search%7Cga%7C1%7Cblade-jdbc) +```xml + +    com.bladejava +    blade-jdbc +    0.1.2 + +``` + +## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache) +```xml + +    com.bladejava +    blade-cache +    1.2.3 + +``` + +## [blade-redis](http://search.maven.org/#search%7Cga%7C1%7Cblade-redis) +```xml + +    com.bladejava +    blade-redis +    1.2.3 + +``` + +## [blade-patchca](http://search.maven.org/#search%7Cga%7C1%7Cblade-patchca) +```xml + +    com.bladejava +    blade-patchca +    1.0.2 + +``` + diff --git a/README.md b/README.md index 855018a09..0fbc8796b 100644 --- a/README.md +++ b/README.md @@ -1,183 +1,183 @@ - -[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) - -[Quick Start](https://bladejava.com/docs)  |  [Demo Project](https://github.com/blade-samples)  |  [Contribute](https://bladejava.com/docs/appendix/contribute)  |  [Donate]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) - -[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - - -## What Is Blade? - -Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. -If you like it, please [star and fork it](https://github.com/biezhi/blade). Thank you! - -## Features - -* [x] Lightweight: the code is simple and the structure is clear -* [x] Modular (you can choose which components to use) -* [x] Supports plug-in extension mechanism -* [x] RESTful style routing interface -* [x] Supports multiple configuration files (currently properties, json and coding) -* [x] Embedded jetty server and template engine support -* [x] Supports JDK 1.6 and up - -## Overview - -* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. -* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. - -## Get Start - -To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : - -Grab via `Maven`: - -```xml - - com.bladejava - blade-core - 1.6.6-beta - - - com.bladejava - blade-embed-jetty - 0.0.4 - -``` -or `Gradle`: -```sh -compile 'com.bladejava:blade-core:1.6.6-beta' -compile 'com.bladejava:blade-embed-jetty:0.0.4' -``` - -Create `Main` method like this: - -```java -public static void main(String[] args) { - $().get("/", (request, response) -> { - response.html("

Hello blade!

"); - }).start(Application.class); -} -``` - -Run it and point your browser to [http://localhost:9000](http://localhost:9000). There you go, you've just created your first Blade app! - -## API Example - -```java -public static void main(String[] args) { - $().get("/user/21", getxxx); - $().post("/save", postxxx); - $().delete("/del/21", deletexxx); - $().put("/put", putxxx); -} -``` - -## REST URL Parameters - -```java -public static void main(String[] args) { - $().get("/user/:uid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - response.text("uid : " + uid); - }); - - $().get("/users/:uid/post/:pid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - Integer pid = request.paramAsInt("pid"); - String msg = "uid = " + uid + ", pid = " + pid; - response.text(msg); - }); - - $().start(Application.class); -} -``` - -## Form URL Parameters - -```java -public static void main(String[] args) { - $().get("/user", (request, response) -> { - Integer uid = request.queryAsInt("uid"); - response.text("uid : " + uid); - }).start(Application.class); -} -``` - -## Upload File - -```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; - File file = fileItem.getFile(); - - String fileRealPath = "your upload file path!"; - - nioTransferCopy(file, fileRealPath); - } -} -``` - -## Route Config File - -`route.conf` - -```sh -GET / IndexRoute.home -GET /signin IndexRoute.show_signin -POST /signin IndexRoute.signin -GET /signout IndexRoute.signout -POST /upload_img UploadRoute.upload_img -``` - -## Route Intercept - -```java -public static void main(String[] args) { - $().before("/.*", (request, response) -> { - System.out.println("before..."); - }).start(Application.class); -} -``` - -You may refer to these examples for additional guidance: - -+ [Hello Blade](https://github.com/blade-samples/hello) -+ [BBS WebSite](https://github.com/junicorn/java-china) -+ [Doc Service](https://github.com/biezhi/grice) -+ [More Examples](https://github.com/blade-samples) - - -## Update - -[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## Contact - -- Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me@gmail.com - -## Contributor - -Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! - -- [mfarid](https://github.com/mfarid) -- [daimajia](https://github.com/daimajia) -- [shenjie1993](https://github.com/shenjie1993) -- [sumory](https://github.com/sumory) -- [udaykadaboina](https://github.com/udaykadaboina) -- [SyedWasiHaider](https://github.com/SyedWasiHaider) -- [Awakens](https://github.com/Awakens) -- [shellac](https://github.com/shellac) -- [SudarAbisheck](https://github.com/SudarAbisheck) - -## Licenses - -Please see [Apache License](LICENSE) + +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) + +[Quick Start](https://bladejava.com/docs)  |  [Demo Project](https://github.com/blade-samples)  |  [Contribute](https://bladejava.com/docs/appendix/contribute)  |  [Donate]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) + +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + + +## What Is Blade? + +Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. +If you like it, please [star and fork it](https://github.com/biezhi/blade). Thank you! + +## Features + +* [x] Lightweight: the code is simple and the structure is clear +* [x] Modular (you can choose which components to use) +* [x] Supports plug-in extension mechanism +* [x] RESTful style routing interface +* [x] Supports multiple configuration files (currently properties, json and coding) +* [x] Embedded jetty server and template engine support +* [x] Supports JDK 1.6 and up + +## Overview + +* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. +* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. + +## Get Start + +To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : + +Grab via `Maven`: + +```xml + + com.bladejava + blade-core + 1.6.6 + + + com.bladejava + blade-embed-jetty + 0.0.4 + +``` +or `Gradle`: +```sh +compile 'com.bladejava:blade-core:1.6.6-beta' +compile 'com.bladejava:blade-embed-jetty:0.0.4' +``` + +Create `Main` method like this: + +```java +public static void main(String[] args) { + $().get("/", (request, response) -> { + response.html("

Hello blade!

"); + }).start(Application.class); +} +``` + +Run it and point your browser to [http://localhost:9000](http://localhost:9000). There you go, you've just created your first Blade app! + +## API Example + +```java +public static void main(String[] args) { + $().get("/user/21", getxxx); + $().post("/save", postxxx); + $().delete("/del/21", deletexxx); + $().put("/put", putxxx); +} +``` + +## REST URL Parameters + +```java +public static void main(String[] args) { + $().get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + $().get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + $().start(Application.class); +} +``` + +## Form URL Parameters + +```java +public static void main(String[] args) { + $().get("/user", (request, response) -> { + Integer uid = request.queryAsInt("uid"); + response.text("uid : " + uid); + }).start(Application.class); +} +``` + +## Upload File + +```java +public void upload_img(Request request, Response response){ + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## Route Config File + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## Route Intercept + +```java +public static void main(String[] args) { + $().before("/.*", (request, response) -> { + System.out.println("before..."); + }).start(Application.class); +} +``` + +You may refer to these examples for additional guidance: + ++ [Hello Blade](https://github.com/blade-samples/hello) ++ [BBS WebSite](https://github.com/junicorn/java-china) ++ [Doc Service](https://github.com/biezhi/grice) ++ [More Examples](https://github.com/blade-samples) + + +## Update + +[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## Contact + +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me@gmail.com + +## Contributor + +Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! + +- [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) + +## Licenses + +Please see [Apache License](LICENSE) diff --git a/README_CN.md b/README_CN.md index 34ccccb32..fcd020169 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,189 +1,189 @@ - -[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) - -[开始使用](https://bladejava.com/docs)  |  [示例项目](https://github.com/blade-samples)  |  [贡献代码](https://bladejava.com/docs/appendix/contribute)  |  [捐赠]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [English](https://github.com/biezhi/blade/blob/master/README.md) - -[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) - -## Blade是什么? - -Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁的代码,优雅的设计。 - -如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush: - -## 特性 - -* [x] 轻量级, 代码简洁,结构清晰,更容易开发 -* [x] 模块化(你可以选择使用哪些组件) -* [x] 插件扩展机制 -* [x] Restful风格的路由接口 -* [x] 多种配置文件支持(当前支持properties、json和硬编码) -* [x] 多种模板引擎支持 -* [x] 更方便的启动和部署 -* [x] 支持JDK1.6或者更高版本(JDK8写起来更爽) - -## 概述 - -* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 -* 优雅的:`Blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 -* 易部署:支持 `maven` 打成 `jar` 包直接运行。 - -## 快速入门 - -开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : - -`Maven` 配置: - -```xml - - com.bladejava - blade-core - 1.6.6-beta - - - com.bladejava - blade-embed-jetty - 0.0.4 - -``` - -或者 `Gradle`: - -```sh -compile 'com.bladejava:blade-core:1.6.6-beta' -compile 'com.bladejava:blade-embed-jetty:0.0.4' -``` - -编写 `Main`函数: - -```java -public static void main(String[] args) { - $().get("/", (request, response) -> { - response.html("

Hello blade!

"); - }).start(Application.class); -} -``` - -用浏览器打开 http://localhost:9000 这样就可以看到第一个Blade应用了! - -## API示例 - -```java -public static void main(String[] args) { - $().get("/user/21", getxxx); - $().post("/save", postxxx); - $().delete("/del/21", deletexxx); - $().put("/put", putxxx); -} -``` - -## REST URL参数获取 - -```java -public static void main(String[] args) { - $().get("/user/:uid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - response.text("uid : " + uid); - }); - - $().get("/users/:uid/post/:pid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - Integer pid = request.paramAsInt("pid"); - String msg = "uid = " + uid + ", pid = " + pid; - response.text(msg); - }); - - $().start(Application.class); -} -``` - -## 表单参数获取 - -```java -public static void main(String[] args) { - $().get("/user", (request, response) -> { - Integer uid = request.queryAsInt("uid"); - response.text("uid : " + uid); - }).start(Application.class); -} -``` - -## 上传文件 - -```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; - File file = fileItem.getFile(); - - String fileRealPath = "your upload file path!"; - - nioTransferCopy(file, fileRealPath); - } -} -``` - -## 配置文件路由 - -`route.conf` - -```sh -GET / IndexRoute.home -GET /signin IndexRoute.show_signin -POST /signin IndexRoute.signin -GET /signout IndexRoute.signout -POST /upload_img UploadRoute.upload_img -``` - -## 路由拦截 - -```java -public static void main(String[] args) { - $().before("/.*", (request, response) -> { - System.out.println("before..."); - }).start(Application.class); -} -``` - - -这一切看起来多么的简单,不过上面的功能可是冰山一角,查看文档和示例项目有更多惊喜: - -+ [hello工程](https://github.com/blade-samples/hello) -+ [论坛程序](https://github.com/junicorn/java-china) -+ [文档服务](https://github.com/biezhi/grice) -+ [更多例子](https://github.com/blade-samples) - - -## 更新日志 - -[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## 联系我 - -- Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me#gmail.com -- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) - -## 贡献 - -非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! - -- [mfarid](https://github.com/mfarid) -- [daimajia](https://github.com/daimajia) -- [shenjie1993](https://github.com/shenjie1993) -- [sumory](https://github.com/sumory) -- [udaykadaboina](https://github.com/udaykadaboina) -- [SyedWasiHaider](https://github.com/SyedWasiHaider) -- [Awakens](https://github.com/Awakens) -- [shellac](https://github.com/shellac) -- [SudarAbisheck](https://github.com/SudarAbisheck) - -## 开源协议 - -请查看 [Apache License](LICENSE) + +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) + +[开始使用](https://bladejava.com/docs)  |  [示例项目](https://github.com/blade-samples)  |  [贡献代码](https://bladejava.com/docs/appendix/contribute)  |  [捐赠]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [English](https://github.com/biezhi/blade/blob/master/README.md) + +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) + +## Blade是什么? + +Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁的代码,优雅的设计。 + +如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush: + +## 特性 + +* [x] 轻量级, 代码简洁,结构清晰,更容易开发 +* [x] 模块化(你可以选择使用哪些组件) +* [x] 插件扩展机制 +* [x] Restful风格的路由接口 +* [x] 多种配置文件支持(当前支持properties、json和硬编码) +* [x] 多种模板引擎支持 +* [x] 更方便的启动和部署 +* [x] 支持JDK1.6或者更高版本(JDK8写起来更爽) + +## 概述 + +* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 +* 优雅的:`Blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 +* 易部署:支持 `maven` 打成 `jar` 包直接运行。 + +## 快速入门 + +开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : + +`Maven` 配置: + +```xml + + com.bladejava + blade-core + 1.6.6 + + + com.bladejava + blade-embed-jetty + 0.0.4 + +``` + +或者 `Gradle`: + +```sh +compile 'com.bladejava:blade-core:1.6.6-beta' +compile 'com.bladejava:blade-embed-jetty:0.0.4' +``` + +编写 `Main`函数: + +```java +public static void main(String[] args) { + $().get("/", (request, response) -> { + response.html("

Hello blade!

"); + }).start(Application.class); +} +``` + +用浏览器打开 http://localhost:9000 这样就可以看到第一个Blade应用了! + +## API示例 + +```java +public static void main(String[] args) { + $().get("/user/21", getxxx); + $().post("/save", postxxx); + $().delete("/del/21", deletexxx); + $().put("/put", putxxx); +} +``` + +## REST URL参数获取 + +```java +public static void main(String[] args) { + $().get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + $().get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + $().start(Application.class); +} +``` + +## 表单参数获取 + +```java +public static void main(String[] args) { + $().get("/user", (request, response) -> { + Integer uid = request.queryAsInt("uid"); + response.text("uid : " + uid); + }).start(Application.class); +} +``` + +## 上传文件 + +```java +public void upload_img(Request request, Response response){ + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## 配置文件路由 + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## 路由拦截 + +```java +public static void main(String[] args) { + $().before("/.*", (request, response) -> { + System.out.println("before..."); + }).start(Application.class); +} +``` + + +这一切看起来多么的简单,不过上面的功能可是冰山一角,查看文档和示例项目有更多惊喜: + ++ [hello工程](https://github.com/blade-samples/hello) ++ [论坛程序](https://github.com/junicorn/java-china) ++ [文档服务](https://github.com/biezhi/grice) ++ [更多例子](https://github.com/blade-samples) + + +## 更新日志 + +[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## 联系我 + +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me#gmail.com +- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) + +## 贡献 + +非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! + +- [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) + +## 开源协议 + +请查看 [Apache License](LICENSE) diff --git a/blade-auth/src/main/java/com/blade/auth/CSRFTokenManager.java b/blade-auth/src/main/java/com/blade/auth/CSRFTokenManager.java index fa609c17c..a16a41c68 100644 --- a/blade-auth/src/main/java/com/blade/auth/CSRFTokenManager.java +++ b/blade-auth/src/main/java/com/blade/auth/CSRFTokenManager.java @@ -20,9 +20,9 @@ import com.blade.kit.HashidKit; import com.blade.kit.StringKit; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.wrapper.Session; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.http.wrapper.Session; /** * CSRF token Manager diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 9afcfe819..c16e60b52 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -26,22 +26,22 @@ import com.blade.config.ConfigLoader; import com.blade.embedd.EmbedServer; import com.blade.exception.EmbedServerException; -import com.blade.interceptor.Interceptor; import com.blade.ioc.Ioc; import com.blade.ioc.SimpleIoc; import com.blade.kit.Assert; import com.blade.kit.Environment; import com.blade.kit.StringKit; import com.blade.kit.reflect.ReflectKit; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.interceptor.Interceptor; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteBuilder; +import com.blade.mvc.route.RouteException; +import com.blade.mvc.route.RouteGroup; +import com.blade.mvc.route.RouteHandler; +import com.blade.mvc.route.Routers; +import com.blade.mvc.route.loader.ClassPathRouteLoader; import com.blade.plugin.Plugin; -import com.blade.route.Route; -import com.blade.route.RouteBuilder; -import com.blade.route.RouteException; -import com.blade.route.RouteGroup; -import com.blade.route.RouteHandler; -import com.blade.route.Routers; -import com.blade.route.loader.ClassPathRouteLoader; -import com.blade.web.http.HttpMethod; /** * Blade Core Class diff --git a/blade-core/src/main/java/com/blade/BladeBanner.java b/blade-core/src/main/java/com/blade/BladeBanner.java deleted file mode 100644 index a63b8b507..000000000 --- a/blade-core/src/main/java/com/blade/BladeBanner.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.blade; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BladeBanner { - - private static final Logger LOGGER = LoggerFactory.getLogger(BladeBanner.class); - - private static final String[] banner = { - " __, _, _, __, __,", - " |_) | /_\\ | \\ |_", - " |_) | , | | |_/ |", - " ~ ~~~ ~ ~ ~ ~~~" - }; - - public void print() { - for (String s : banner) { - LOGGER.info('\t' + s); - } - LOGGER.info("\t :: Blade :: (v" + Const.BLADE_VERSION + ")\r\n"); - } -} diff --git a/blade-core/src/main/java/com/blade/annotation/Route.java b/blade-core/src/main/java/com/blade/annotation/Route.java index 4836178ae..ef0eab3f4 100644 --- a/blade-core/src/main/java/com/blade/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/annotation/Route.java @@ -20,7 +20,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import com.blade.web.http.HttpMethod; +import com.blade.mvc.http.HttpMethod; /** * Methods defined on the route notes diff --git a/blade-core/src/main/java/com/blade/banner/Banner.java b/blade-core/src/main/java/com/blade/banner/Banner.java new file mode 100644 index 000000000..addc8407c --- /dev/null +++ b/blade-core/src/main/java/com/blade/banner/Banner.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.banner; + +public interface Banner { + + String startText(); + +} diff --git a/blade-core/src/main/java/com/blade/banner/BannerStarter.java b/blade-core/src/main/java/com/blade/banner/BannerStarter.java new file mode 100644 index 000000000..4f5932e6a --- /dev/null +++ b/blade-core/src/main/java/com/blade/banner/BannerStarter.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.banner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class BannerStarter { + + private static final Logger LOGGER = LoggerFactory.getLogger(BannerStarter.class); + + private static Banner banner = new BladeBanner(); + + public static void printStart(){ + LOGGER.info(banner.startText()); + } + +} diff --git a/blade-core/src/main/java/com/blade/banner/BladeBanner.java b/blade-core/src/main/java/com/blade/banner/BladeBanner.java new file mode 100644 index 000000000..6da393aaa --- /dev/null +++ b/blade-core/src/main/java/com/blade/banner/BladeBanner.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.banner; + +import com.blade.Const; + +public class BladeBanner implements Banner { + + private static final String[] banner = { + " __, _, _, __, __,", + " |_) | /_\\ | \\ |_", + " |_) | , | | |_/ |", + " ~ ~~~ ~ ~ ~ ~~~" + }; + + @Override + public String startText() { + StringBuffer text = new StringBuffer(); + for (String s : banner) { + text.append('\t' + s); + } + text.append("\t :: Blade :: (v" + Const.BLADE_VERSION + ")\r\n"); + return text.toString(); + } +} diff --git a/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java b/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java index c0e894064..cafeb6460 100644 --- a/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java +++ b/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java @@ -17,9 +17,9 @@ import javax.servlet.ServletContext; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.wrapper.Session; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.http.wrapper.Session; /** * BladeWebContext diff --git a/blade-core/src/main/java/com/blade/interceptor/package-info.java b/blade-core/src/main/java/com/blade/interceptor/package-info.java deleted file mode 100644 index 0a1ac0a52..000000000 --- a/blade-core/src/main/java/com/blade/interceptor/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Blade Interceptor - */ -package com.blade.interceptor; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index d133cf58a..1ef79e474 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -31,13 +31,13 @@ import com.blade.comparator.OrderComparator; import com.blade.config.BaseConfig; import com.blade.context.DynamicClassReader; -import com.blade.interceptor.Interceptor; import com.blade.ioc.annotation.Component; import com.blade.ioc.annotation.Service; import com.blade.kit.StringKit; import com.blade.kit.resource.ClassInfo; import com.blade.kit.resource.ClassReader; -import com.blade.route.RouteBuilder; +import com.blade.mvc.interceptor.Interceptor; +import com.blade.mvc.route.RouteBuilder; /** * IOC container, used to initialize the IOC object diff --git a/blade-core/src/main/java/com/blade/web/DispatchKit.java b/blade-core/src/main/java/com/blade/mvc/DispatchKit.java similarity index 95% rename from blade-core/src/main/java/com/blade/web/DispatchKit.java rename to blade-core/src/main/java/com/blade/mvc/DispatchKit.java index 415886447..5c895b781 100644 --- a/blade-core/src/main/java/com/blade/web/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatchKit.java @@ -1,4 +1,4 @@ -package com.blade.web; +package com.blade.mvc; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -26,8 +26,9 @@ import com.blade.kit.IOKit; import com.blade.kit.StreamKit; import com.blade.kit.StringKit; -import com.blade.web.http.HttpException; -import com.blade.web.http.Response; +import com.blade.mvc.http.HttpException; +import com.blade.mvc.http.Response; + import static com.blade.Blade.$; public class DispatchKit { diff --git a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java similarity index 88% rename from blade-core/src/main/java/com/blade/web/DispatcherHandler.java rename to blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index 062fa690e..f82e32176 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web; +package com.blade.mvc; import java.io.IOException; import java.util.List; @@ -31,19 +31,19 @@ import com.blade.exception.BladeException; import com.blade.ioc.Ioc; import com.blade.kit.StringKit; -import com.blade.route.Route; -import com.blade.route.RouteHandler; -import com.blade.route.RouteMatcher; -import com.blade.route.Routers; -import com.blade.view.ModelAndView; -import com.blade.view.handle.RouteViewHandler; -import com.blade.view.template.TemplateException; -import com.blade.web.http.HttpStatus; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.http.wrapper.ServletRequest; -import com.blade.web.http.wrapper.ServletResponse; +import com.blade.mvc.http.HttpStatus; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.http.wrapper.ServletRequest; +import com.blade.mvc.http.wrapper.ServletResponse; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteHandler; +import com.blade.mvc.route.RouteMatcher; +import com.blade.mvc.route.Routers; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.handle.RouteViewHandler; +import com.blade.mvc.view.template.TemplateException; /** * Synchronous request processor diff --git a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java similarity index 95% rename from blade-core/src/main/java/com/blade/web/DispatcherServlet.java rename to blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java index df644ae9e..facb9ac9d 100644 --- a/blade-core/src/main/java/com/blade/web/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web; +package com.blade.mvc; import java.io.IOException; @@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory; import com.blade.Blade; -import com.blade.BladeBanner; import com.blade.Bootstrap; +import com.blade.banner.BannerStarter; import com.blade.context.ApplicationContext; import com.blade.context.ApplicationWebContext; import com.blade.context.DynamicClassReader; @@ -114,7 +114,7 @@ public void init(Blade blade) { dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); - new BladeBanner().print(); + BannerStarter.printStart(); String appName = blade.environment().getString("app.name", "Blade"); diff --git a/blade-core/src/main/java/com/blade/web/StaticFileFilter.java b/blade-core/src/main/java/com/blade/mvc/StaticFileFilter.java similarity index 98% rename from blade-core/src/main/java/com/blade/web/StaticFileFilter.java rename to blade-core/src/main/java/com/blade/mvc/StaticFileFilter.java index 78529fa44..5a383b54d 100644 --- a/blade-core/src/main/java/com/blade/web/StaticFileFilter.java +++ b/blade-core/src/main/java/com/blade/mvc/StaticFileFilter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web; +package com.blade.mvc; import java.util.HashMap; import java.util.Map; diff --git a/blade-core/src/main/java/com/blade/web/http/HttpException.java b/blade-core/src/main/java/com/blade/mvc/http/HttpException.java similarity index 93% rename from blade-core/src/main/java/com/blade/web/http/HttpException.java rename to blade-core/src/main/java/com/blade/mvc/http/HttpException.java index 4790416ff..e5c5144ab 100644 --- a/blade-core/src/main/java/com/blade/web/http/HttpException.java +++ b/blade-core/src/main/java/com/blade/mvc/http/HttpException.java @@ -1,4 +1,4 @@ -package com.blade.web.http; +package com.blade.mvc.http; import java.io.IOException; diff --git a/blade-core/src/main/java/com/blade/web/http/HttpMethod.java b/blade-core/src/main/java/com/blade/mvc/http/HttpMethod.java similarity index 96% rename from blade-core/src/main/java/com/blade/web/http/HttpMethod.java rename to blade-core/src/main/java/com/blade/mvc/http/HttpMethod.java index ac32cf7dc..8a9a75799 100644 --- a/blade-core/src/main/java/com/blade/web/http/HttpMethod.java +++ b/blade-core/src/main/java/com/blade/mvc/http/HttpMethod.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.http; +package com.blade.mvc.http; /** * HTTP Request Method diff --git a/blade-core/src/main/java/com/blade/web/http/HttpStatus.java b/blade-core/src/main/java/com/blade/mvc/http/HttpStatus.java similarity index 98% rename from blade-core/src/main/java/com/blade/web/http/HttpStatus.java rename to blade-core/src/main/java/com/blade/mvc/http/HttpStatus.java index b2eaa07a8..8422318c1 100644 --- a/blade-core/src/main/java/com/blade/web/http/HttpStatus.java +++ b/blade-core/src/main/java/com/blade/mvc/http/HttpStatus.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.http; +package com.blade.mvc.http; /** * HTTP Status diff --git a/blade-core/src/main/java/com/blade/web/http/Path.java b/blade-core/src/main/java/com/blade/mvc/http/Path.java similarity index 98% rename from blade-core/src/main/java/com/blade/web/http/Path.java rename to blade-core/src/main/java/com/blade/mvc/http/Path.java index 6c1442238..e1ec7b187 100644 --- a/blade-core/src/main/java/com/blade/web/http/Path.java +++ b/blade-core/src/main/java/com/blade/mvc/http/Path.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.http; +package com.blade.mvc.http; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; diff --git a/blade-core/src/main/java/com/blade/web/http/Request.java b/blade-core/src/main/java/com/blade/mvc/http/Request.java similarity index 97% rename from blade-core/src/main/java/com/blade/web/http/Request.java rename to blade-core/src/main/java/com/blade/mvc/http/Request.java index 365fd8659..d2f3bb382 100644 --- a/blade-core/src/main/java/com/blade/web/http/Request.java +++ b/blade-core/src/main/java/com/blade/mvc/http/Request.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.http; +package com.blade.mvc.http; import java.io.InputStream; import java.io.Serializable; @@ -24,9 +24,9 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; -import com.blade.route.Route; -import com.blade.web.http.wrapper.Session; -import com.blade.web.multipart.FileItem; +import com.blade.mvc.http.wrapper.Session; +import com.blade.mvc.multipart.FileItem; +import com.blade.mvc.route.Route; /** * HTTP Request diff --git a/blade-core/src/main/java/com/blade/web/http/Response.java b/blade-core/src/main/java/com/blade/mvc/http/Response.java similarity index 93% rename from blade-core/src/main/java/com/blade/web/http/Response.java rename to blade-core/src/main/java/com/blade/mvc/http/Response.java index 00743f980..2de72b48a 100644 --- a/blade-core/src/main/java/com/blade/web/http/Response.java +++ b/blade-core/src/main/java/com/blade/mvc/http/Response.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.http; +package com.blade.mvc.http; import java.io.IOException; import java.io.OutputStream; @@ -22,7 +22,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; -import com.blade.view.ModelAndView; +import com.blade.mvc.view.ModelAndView; /** * HTTP Response diff --git a/blade-core/src/main/java/com/blade/web/http/package-info.java b/blade-core/src/main/java/com/blade/mvc/http/package-info.java similarity index 54% rename from blade-core/src/main/java/com/blade/web/http/package-info.java rename to blade-core/src/main/java/com/blade/mvc/http/package-info.java index 2e04b8f99..1910acdfe 100644 --- a/blade-core/src/main/java/com/blade/web/http/package-info.java +++ b/blade-core/src/main/java/com/blade/mvc/http/package-info.java @@ -1,4 +1,4 @@ /** * Request And Response */ -package com.blade.web.http; \ No newline at end of file +package com.blade.mvc.http; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java similarity index 97% rename from blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java rename to blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java index 3edbac986..556179fa4 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.http.wrapper; +package com.blade.mvc.http.wrapper; import java.io.BufferedReader; import java.io.IOException; @@ -40,14 +40,14 @@ import com.blade.kit.IOKit; import com.blade.kit.ObjectKit; import com.blade.kit.StringKit; -import com.blade.route.Route; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.multipart.FileItem; -import com.blade.web.multipart.Multipart; -import com.blade.web.multipart.MultipartException; -import com.blade.web.multipart.MultipartHandler; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.multipart.FileItem; +import com.blade.mvc.multipart.Multipart; +import com.blade.mvc.multipart.MultipartException; +import com.blade.mvc.multipart.MultipartHandler; +import com.blade.mvc.route.Route; /** * ServletRequest diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java similarity index 91% rename from blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java rename to blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java index 8e90abe20..d5978f887 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.http.wrapper; +package com.blade.mvc.http.wrapper; import java.io.IOException; import java.io.PrintWriter; @@ -28,16 +28,16 @@ import com.blade.context.ApplicationWebContext; import com.blade.kit.Assert; -import com.blade.view.ModelAndView; -import com.blade.view.ViewSettings; -import com.blade.view.parser.JSONParser; -import com.blade.view.template.TemplateEngine; -import com.blade.view.template.TemplateException; -import com.blade.web.DispatchKit; -import com.blade.web.http.HttpStatus; -import com.blade.web.http.Path; -import com.blade.web.http.Request; -import com.blade.web.http.Response; +import com.blade.mvc.DispatchKit; +import com.blade.mvc.http.HttpStatus; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; +import com.blade.mvc.view.parser.JSONParser; +import com.blade.mvc.view.template.TemplateEngine; +import com.blade.mvc.view.template.TemplateException; /** * ServletResponse diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/Session.java similarity index 98% rename from blade-core/src/main/java/com/blade/web/http/wrapper/Session.java rename to blade-core/src/main/java/com/blade/mvc/http/wrapper/Session.java index e1358bc5f..3ad5d5409 100644 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/Session.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/Session.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.http.wrapper; +package com.blade.mvc.http.wrapper; import java.util.Enumeration; import java.util.Set; diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/package-info.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/package-info.java new file mode 100644 index 000000000..f4c0c1203 --- /dev/null +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/package-info.java @@ -0,0 +1,4 @@ +/** + * Servlet Wrapper + */ +package com.blade.mvc.http.wrapper; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/interceptor/Interceptor.java b/blade-core/src/main/java/com/blade/mvc/interceptor/Interceptor.java similarity index 89% rename from blade-core/src/main/java/com/blade/interceptor/Interceptor.java rename to blade-core/src/main/java/com/blade/mvc/interceptor/Interceptor.java index 18550ef63..0d8a52724 100644 --- a/blade-core/src/main/java/com/blade/interceptor/Interceptor.java +++ b/blade-core/src/main/java/com/blade/mvc/interceptor/Interceptor.java @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.interceptor; +package com.blade.mvc.interceptor; -import com.blade.web.http.Request; -import com.blade.web.http.Response; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; /** * Interceptor, In the routing block before and after the execution. diff --git a/blade-core/src/main/java/com/blade/mvc/interceptor/package-info.java b/blade-core/src/main/java/com/blade/mvc/interceptor/package-info.java new file mode 100644 index 000000000..c4eac9118 --- /dev/null +++ b/blade-core/src/main/java/com/blade/mvc/interceptor/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade Interceptor + */ +package com.blade.mvc.interceptor; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/multipart/FileItem.java b/blade-core/src/main/java/com/blade/mvc/multipart/FileItem.java similarity index 98% rename from blade-core/src/main/java/com/blade/web/multipart/FileItem.java rename to blade-core/src/main/java/com/blade/mvc/multipart/FileItem.java index 2d24ed72f..a25b0ffe4 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/FileItem.java +++ b/blade-core/src/main/java/com/blade/mvc/multipart/FileItem.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.multipart; +package com.blade.mvc.multipart; import java.io.File; import java.util.HashMap; diff --git a/blade-core/src/main/java/com/blade/web/multipart/Multipart.java b/blade-core/src/main/java/com/blade/mvc/multipart/Multipart.java similarity index 99% rename from blade-core/src/main/java/com/blade/web/multipart/Multipart.java rename to blade-core/src/main/java/com/blade/mvc/multipart/Multipart.java index 24a6671e4..a8a669986 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/Multipart.java +++ b/blade-core/src/main/java/com/blade/mvc/multipart/Multipart.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.multipart; +package com.blade.mvc.multipart; import java.io.File; import java.io.FileOutputStream; diff --git a/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java b/blade-core/src/main/java/com/blade/mvc/multipart/MultipartException.java similarity index 97% rename from blade-core/src/main/java/com/blade/web/multipart/MultipartException.java rename to blade-core/src/main/java/com/blade/mvc/multipart/MultipartException.java index a4a251fac..5244857bd 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/MultipartException.java +++ b/blade-core/src/main/java/com/blade/mvc/multipart/MultipartException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.multipart; +package com.blade.mvc.multipart; /** * diff --git a/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java b/blade-core/src/main/java/com/blade/mvc/multipart/MultipartHandler.java similarity index 96% rename from blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java rename to blade-core/src/main/java/com/blade/mvc/multipart/MultipartHandler.java index 6e8b68d27..0cb021e1d 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/MultipartHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/multipart/MultipartHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.web.multipart; +package com.blade.mvc.multipart; /** * MultipartHandler diff --git a/blade-core/src/main/java/com/blade/web/multipart/MultipartReader.java b/blade-core/src/main/java/com/blade/mvc/multipart/MultipartReader.java similarity index 99% rename from blade-core/src/main/java/com/blade/web/multipart/MultipartReader.java rename to blade-core/src/main/java/com/blade/mvc/multipart/MultipartReader.java index 31fe33c59..0214d0b92 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/MultipartReader.java +++ b/blade-core/src/main/java/com/blade/mvc/multipart/MultipartReader.java @@ -10,7 +10,7 @@ * 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.blade.web.multipart; +package com.blade.mvc.multipart; import java.io.ByteArrayOutputStream; import java.io.Closeable; diff --git a/blade-core/src/main/java/com/blade/web/multipart/ParameterParser.java b/blade-core/src/main/java/com/blade/mvc/multipart/ParameterParser.java similarity index 99% rename from blade-core/src/main/java/com/blade/web/multipart/ParameterParser.java rename to blade-core/src/main/java/com/blade/mvc/multipart/ParameterParser.java index a92bcab65..1fe0b3f72 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/ParameterParser.java +++ b/blade-core/src/main/java/com/blade/mvc/multipart/ParameterParser.java @@ -10,7 +10,7 @@ * 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.blade.web.multipart; +package com.blade.mvc.multipart; import java.util.HashMap; import java.util.Map; diff --git a/blade-core/src/main/java/com/blade/web/multipart/Streams.java b/blade-core/src/main/java/com/blade/mvc/multipart/Streams.java similarity index 99% rename from blade-core/src/main/java/com/blade/web/multipart/Streams.java rename to blade-core/src/main/java/com/blade/mvc/multipart/Streams.java index 09b3875e1..ffffdd9e2 100644 --- a/blade-core/src/main/java/com/blade/web/multipart/Streams.java +++ b/blade-core/src/main/java/com/blade/mvc/multipart/Streams.java @@ -10,7 +10,7 @@ * 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.blade.web.multipart; +package com.blade.mvc.multipart; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/blade-core/src/main/java/com/blade/mvc/multipart/package-info.java b/blade-core/src/main/java/com/blade/mvc/multipart/package-info.java new file mode 100644 index 000000000..b8d5dba81 --- /dev/null +++ b/blade-core/src/main/java/com/blade/mvc/multipart/package-info.java @@ -0,0 +1,4 @@ +/** + * Servlet Multipart + */ +package com.blade.mvc.multipart; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/package-info.java b/blade-core/src/main/java/com/blade/mvc/package-info.java similarity index 54% rename from blade-core/src/main/java/com/blade/web/package-info.java rename to blade-core/src/main/java/com/blade/mvc/package-info.java index e3539aed1..5c3d64b65 100644 --- a/blade-core/src/main/java/com/blade/web/package-info.java +++ b/blade-core/src/main/java/com/blade/mvc/package-info.java @@ -1,4 +1,4 @@ /** * Blade Web Core */ -package com.blade.web; \ No newline at end of file +package com.blade.mvc; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/Route.java b/blade-core/src/main/java/com/blade/mvc/route/Route.java similarity index 96% rename from blade-core/src/main/java/com/blade/route/Route.java rename to blade-core/src/main/java/com/blade/mvc/route/Route.java index efe758df2..64287b4b6 100644 --- a/blade-core/src/main/java/com/blade/route/Route.java +++ b/blade-core/src/main/java/com/blade/mvc/route/Route.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route; +package com.blade.mvc.route; import java.lang.reflect.Method; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Path; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Path; /** * Route Bean diff --git a/blade-core/src/main/java/com/blade/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java similarity index 97% rename from blade-core/src/main/java/com/blade/route/RouteBuilder.java rename to blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java index 455ff64e5..032319eb5 100644 --- a/blade-core/src/main/java/com/blade/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route; +package com.blade.mvc.route; import java.lang.reflect.Method; import java.util.Set; @@ -27,15 +27,15 @@ import com.blade.annotation.RestController; import com.blade.annotation.Route; import com.blade.context.DynamicClassReader; -import com.blade.interceptor.Interceptor; import com.blade.kit.CollectionKit; import com.blade.kit.StringKit; import com.blade.kit.reflect.ReflectKit; import com.blade.kit.resource.ClassInfo; import com.blade.kit.resource.ClassReader; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Request; -import com.blade.web.http.Response; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.interceptor.Interceptor; /** * Route builder diff --git a/blade-core/src/main/java/com/blade/route/RouteException.java b/blade-core/src/main/java/com/blade/mvc/route/RouteException.java similarity index 97% rename from blade-core/src/main/java/com/blade/route/RouteException.java rename to blade-core/src/main/java/com/blade/mvc/route/RouteException.java index c8d32d73d..ff85e4349 100644 --- a/blade-core/src/main/java/com/blade/route/RouteException.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route; +package com.blade.mvc.route; /** * RouteException diff --git a/blade-core/src/main/java/com/blade/route/RouteGroup.java b/blade-core/src/main/java/com/blade/mvc/route/RouteGroup.java similarity index 98% rename from blade-core/src/main/java/com/blade/route/RouteGroup.java rename to blade-core/src/main/java/com/blade/mvc/route/RouteGroup.java index 18ffcd24d..8f0939e68 100644 --- a/blade-core/src/main/java/com/blade/route/RouteGroup.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteGroup.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route; +package com.blade.mvc.route; import com.blade.Blade; diff --git a/blade-core/src/main/java/com/blade/route/RouteHandler.java b/blade-core/src/main/java/com/blade/mvc/route/RouteHandler.java similarity index 89% rename from blade-core/src/main/java/com/blade/route/RouteHandler.java rename to blade-core/src/main/java/com/blade/mvc/route/RouteHandler.java index 9fc1c49aa..ccbb00031 100644 --- a/blade-core/src/main/java/com/blade/route/RouteHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteHandler.java @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route; +package com.blade.mvc.route; -import com.blade.web.http.Request; -import com.blade.web.http.Response; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; /** * Route Handler diff --git a/blade-core/src/main/java/com/blade/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java similarity index 97% rename from blade-core/src/main/java/com/blade/route/RouteMatcher.java rename to blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java index 4bb4edf61..9713d4fcb 100644 --- a/blade-core/src/main/java/com/blade/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route; +package com.blade.mvc.route; import java.net.URI; import java.net.URISyntaxException; @@ -25,8 +25,8 @@ import java.util.Map; import java.util.Set; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Path; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Path; /** * Default Route Matcher diff --git a/blade-core/src/main/java/com/blade/route/Routers.java b/blade-core/src/main/java/com/blade/mvc/route/Routers.java similarity index 94% rename from blade-core/src/main/java/com/blade/route/Routers.java rename to blade-core/src/main/java/com/blade/mvc/route/Routers.java index d3b01200a..e2c52cca6 100644 --- a/blade-core/src/main/java/com/blade/route/Routers.java +++ b/blade-core/src/main/java/com/blade/mvc/route/Routers.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route; +package com.blade.mvc.route; import java.lang.reflect.Method; import java.util.HashMap; @@ -25,9 +25,9 @@ import com.blade.kit.Assert; import com.blade.kit.reflect.ReflectKit; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Request; -import com.blade.web.http.Response; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; /** * Registration, management route diff --git a/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/AbstractFileRouteLoader.java similarity index 96% rename from blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java rename to blade-core/src/main/java/com/blade/mvc/route/loader/AbstractFileRouteLoader.java index 9546ba74a..8bcf82b36 100644 --- a/blade-core/src/main/java/com/blade/route/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/AbstractFileRouteLoader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route.loader; +package com.blade.mvc.route.loader; import java.io.BufferedReader; import java.io.IOException; @@ -26,11 +26,11 @@ import java.util.StringTokenizer; import com.blade.kit.IOKit; -import com.blade.route.Route; -import com.blade.route.RouteException; -import com.blade.web.http.HttpMethod; -import com.blade.web.http.Request; -import com.blade.web.http.Response; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteException; /** * Abstract loader implementation diff --git a/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java similarity index 96% rename from blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java rename to blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java index e474fc289..8b93ae5eb 100644 --- a/blade-core/src/main/java/com/blade/route/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route.loader; +package com.blade.mvc.route.loader; import com.blade.Blade; import com.blade.ioc.Ioc; -import com.blade.route.RouteException; +import com.blade.mvc.route.RouteException; /** * ClassPath controller of loader diff --git a/blade-core/src/main/java/com/blade/route/loader/ClassPathRouteLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathRouteLoader.java similarity index 97% rename from blade-core/src/main/java/com/blade/route/loader/ClassPathRouteLoader.java rename to blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathRouteLoader.java index 6fce418e0..90bb7a555 100644 --- a/blade-core/src/main/java/com/blade/route/loader/ClassPathRouteLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathRouteLoader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route.loader; +package com.blade.mvc.route.loader; import java.io.File; import java.io.FileInputStream; diff --git a/blade-core/src/main/java/com/blade/route/loader/ControllerLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/ControllerLoader.java similarity index 91% rename from blade-core/src/main/java/com/blade/route/loader/ControllerLoader.java rename to blade-core/src/main/java/com/blade/mvc/route/loader/ControllerLoader.java index dc7fab22b..56d2928ad 100644 --- a/blade-core/src/main/java/com/blade/route/loader/ControllerLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/ControllerLoader.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route.loader; +package com.blade.mvc.route.loader; -import com.blade.route.RouteException; +import com.blade.mvc.route.RouteException; /** * Controller loading interface diff --git a/blade-core/src/main/java/com/blade/route/loader/FileSystemRouteLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/FileSystemRouteLoader.java similarity index 97% rename from blade-core/src/main/java/com/blade/route/loader/FileSystemRouteLoader.java rename to blade-core/src/main/java/com/blade/mvc/route/loader/FileSystemRouteLoader.java index 0a1061994..81b37391d 100644 --- a/blade-core/src/main/java/com/blade/route/loader/FileSystemRouteLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/FileSystemRouteLoader.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route.loader; +package com.blade.mvc.route.loader; import java.io.File; import java.io.FileInputStream; diff --git a/blade-core/src/main/java/com/blade/route/loader/RouteLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/RouteLoader.java similarity index 88% rename from blade-core/src/main/java/com/blade/route/loader/RouteLoader.java rename to blade-core/src/main/java/com/blade/mvc/route/loader/RouteLoader.java index 1134189ff..2b57d37a7 100644 --- a/blade-core/src/main/java/com/blade/route/loader/RouteLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/RouteLoader.java @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.route.loader; +package com.blade.mvc.route.loader; import java.text.ParseException; import java.util.List; -import com.blade.route.Route; -import com.blade.route.RouteException; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteException; /** * Route loader diff --git a/blade-core/src/main/java/com/blade/mvc/route/package-info.java b/blade-core/src/main/java/com/blade/mvc/route/package-info.java new file mode 100644 index 000000000..17a9be773 --- /dev/null +++ b/blade-core/src/main/java/com/blade/mvc/route/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade Route + */ +package com.blade.mvc.route; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/view/ModelAndView.java b/blade-core/src/main/java/com/blade/mvc/view/ModelAndView.java similarity index 98% rename from blade-core/src/main/java/com/blade/view/ModelAndView.java rename to blade-core/src/main/java/com/blade/mvc/view/ModelAndView.java index 664f68f98..d6206fa87 100644 --- a/blade-core/src/main/java/com/blade/view/ModelAndView.java +++ b/blade-core/src/main/java/com/blade/mvc/view/ModelAndView.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view; +package com.blade.mvc.view; import java.util.HashMap; import java.util.Map; diff --git a/blade-core/src/main/java/com/blade/view/ModelMap.java b/blade-core/src/main/java/com/blade/mvc/view/ModelMap.java similarity index 85% rename from blade-core/src/main/java/com/blade/view/ModelMap.java rename to blade-core/src/main/java/com/blade/mvc/view/ModelMap.java index a5a009551..e25cbc902 100644 --- a/blade-core/src/main/java/com/blade/view/ModelMap.java +++ b/blade-core/src/main/java/com/blade/mvc/view/ModelMap.java @@ -1,7 +1,7 @@ -package com.blade.view; +package com.blade.mvc.view; import com.blade.kit.Assert; -import com.blade.web.http.Request; +import com.blade.mvc.http.Request; public class ModelMap { diff --git a/blade-core/src/main/java/com/blade/view/ViewSettings.java b/blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java similarity index 87% rename from blade-core/src/main/java/com/blade/view/ViewSettings.java rename to blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java index 730b39fec..dd2b6c1b4 100644 --- a/blade-core/src/main/java/com/blade/view/ViewSettings.java +++ b/blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view; +package com.blade.mvc.view; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.blade.kit.Assert; -import com.blade.view.parser.DefaultJSONParser; -import com.blade.view.parser.JSONParser; -import com.blade.view.template.DefaultEngine; -import com.blade.view.template.TemplateEngine; +import com.blade.mvc.view.parser.DefaultJSONParser; +import com.blade.mvc.view.parser.JSONParser; +import com.blade.mvc.view.template.DefaultEngine; +import com.blade.mvc.view.template.TemplateEngine; /** * ViewSettings diff --git a/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java similarity index 93% rename from blade-core/src/main/java/com/blade/view/handle/MethodArgument.java rename to blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java index 156347fcc..a3e72ff0e 100644 --- a/blade-core/src/main/java/com/blade/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view.handle; +package com.blade.mvc.view.handle; import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -24,10 +24,10 @@ import com.blade.exception.BladeException; import com.blade.exception.NotFoundException; import com.blade.kit.StringKit; -import com.blade.view.ModelAndView; -import com.blade.web.http.Request; -import com.blade.web.http.Response; -import com.blade.web.multipart.FileItem; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.multipart.FileItem; +import com.blade.mvc.view.ModelAndView; public final class MethodArgument { diff --git a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/mvc/view/handle/RouteViewHandler.java similarity index 90% rename from blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java rename to blade-core/src/main/java/com/blade/mvc/view/handle/RouteViewHandler.java index f8b0ad30c..3b5903f4f 100644 --- a/blade-core/src/main/java/com/blade/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/view/handle/RouteViewHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view.handle; +package com.blade.mvc.view.handle; import java.lang.reflect.Method; @@ -21,11 +21,11 @@ import com.blade.annotation.RestController; import com.blade.ioc.Ioc; import com.blade.kit.reflect.ReflectKit; -import com.blade.route.Route; -import com.blade.view.ModelAndView; -import com.blade.view.ViewSettings; -import com.blade.web.http.Request; -import com.blade.web.http.Response; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.route.Route; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; public class RouteViewHandler { diff --git a/blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java b/blade-core/src/main/java/com/blade/mvc/view/parser/DefaultJSONParser.java similarity index 96% rename from blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java rename to blade-core/src/main/java/com/blade/mvc/view/parser/DefaultJSONParser.java index f9e9942fe..27fab881f 100644 --- a/blade-core/src/main/java/com/blade/view/parser/DefaultJSONParser.java +++ b/blade-core/src/main/java/com/blade/mvc/view/parser/DefaultJSONParser.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view.parser; +package com.blade.mvc.view.parser; import com.blade.kit.json.JSONKit; diff --git a/blade-core/src/main/java/com/blade/view/parser/JSONParser.java b/blade-core/src/main/java/com/blade/mvc/view/parser/JSONParser.java similarity index 95% rename from blade-core/src/main/java/com/blade/view/parser/JSONParser.java rename to blade-core/src/main/java/com/blade/mvc/view/parser/JSONParser.java index 0e92935cd..0151685ce 100644 --- a/blade-core/src/main/java/com/blade/view/parser/JSONParser.java +++ b/blade-core/src/main/java/com/blade/mvc/view/parser/JSONParser.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view.parser; +package com.blade.mvc.view.parser; /** * Route render json parser diff --git a/blade-core/src/main/java/com/blade/view/template/DefaultEngine.java b/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java similarity index 96% rename from blade-core/src/main/java/com/blade/view/template/DefaultEngine.java rename to blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java index 826b56f7d..dcf73bd88 100644 --- a/blade-core/src/main/java/com/blade/view/template/DefaultEngine.java +++ b/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view.template; +package com.blade.mvc.view.template; import java.io.IOException; import java.io.Writer; @@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory; import com.blade.context.ApplicationWebContext; -import com.blade.view.ModelAndView; +import com.blade.mvc.view.ModelAndView; /** diff --git a/blade-core/src/main/java/com/blade/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java similarity index 93% rename from blade-core/src/main/java/com/blade/view/template/JspEngine.java rename to blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java index b3f660e0d..c06806441 100644 --- a/blade-core/src/main/java/com/blade/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view.template; +package com.blade.mvc.view.template; import java.io.IOException; import java.io.Writer; @@ -25,7 +25,7 @@ import javax.servlet.http.HttpServletResponse; import com.blade.context.ApplicationWebContext; -import com.blade.view.ModelAndView; +import com.blade.mvc.view.ModelAndView; /** diff --git a/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java b/blade-core/src/main/java/com/blade/mvc/view/template/TemplateEngine.java similarity index 92% rename from blade-core/src/main/java/com/blade/view/template/TemplateEngine.java rename to blade-core/src/main/java/com/blade/mvc/view/template/TemplateEngine.java index 7b8a03c66..d5a6b27c1 100644 --- a/blade-core/src/main/java/com/blade/view/template/TemplateEngine.java +++ b/blade-core/src/main/java/com/blade/mvc/view/template/TemplateEngine.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view.template; +package com.blade.mvc.view.template; import java.io.Writer; -import com.blade.view.ModelAndView; +import com.blade.mvc.view.ModelAndView; /** * TemplateEngine Interface, For view layer to display data diff --git a/blade-core/src/main/java/com/blade/view/template/TemplateException.java b/blade-core/src/main/java/com/blade/mvc/view/template/TemplateException.java similarity index 96% rename from blade-core/src/main/java/com/blade/view/template/TemplateException.java rename to blade-core/src/main/java/com/blade/mvc/view/template/TemplateException.java index d9f784289..dfcccb9ea 100644 --- a/blade-core/src/main/java/com/blade/view/template/TemplateException.java +++ b/blade-core/src/main/java/com/blade/mvc/view/template/TemplateException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.view.template; +package com.blade.mvc.view.template; /** * TemplateException diff --git a/blade-core/src/main/java/com/blade/mvc/view/template/package-info.java b/blade-core/src/main/java/com/blade/mvc/view/template/package-info.java new file mode 100644 index 000000000..349821df7 --- /dev/null +++ b/blade-core/src/main/java/com/blade/mvc/view/template/package-info.java @@ -0,0 +1,4 @@ +/** + * Blade Render + */ +package com.blade.mvc.view.template; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/route/package-info.java b/blade-core/src/main/java/com/blade/route/package-info.java deleted file mode 100644 index e4a44e705..000000000 --- a/blade-core/src/main/java/com/blade/route/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Blade Route - */ -package com.blade.route; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/view/template/package-info.java b/blade-core/src/main/java/com/blade/view/template/package-info.java deleted file mode 100644 index deeda47f3..000000000 --- a/blade-core/src/main/java/com/blade/view/template/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Blade Render - */ -package com.blade.view.template; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java b/blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java deleted file mode 100644 index 6c29f9ebd..000000000 --- a/blade-core/src/main/java/com/blade/web/http/wrapper/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Servlet Wrapper - */ -package com.blade.web.http.wrapper; \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/web/multipart/package-info.java b/blade-core/src/main/java/com/blade/web/multipart/package-info.java deleted file mode 100644 index c60ec9c24..000000000 --- a/blade-core/src/main/java/com/blade/web/multipart/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Servlet Multipart - */ -package com.blade.web.multipart; \ No newline at end of file diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index a2c96e96a..e5f13fb9f 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -16,7 +16,7 @@ import com.blade.Const; import com.blade.kit.Environment; -import com.blade.web.DispatcherServlet; +import com.blade.mvc.DispatcherServlet; public class EmbedJettyServer implements EmbedServer { diff --git a/pom.xml b/pom.xml index b607f2058..dd88a9e12 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.7.21 1.7.21 - 1.6.6-beta + 1.6.6 1.3.3 1.0.0 0.0.4 From 0af93757299ef2608e1df6d969045db5fda62ebc Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 3 Sep 2016 20:49:42 +0800 Subject: [PATCH 487/545] =?UTF-8?q?=E2=9C=84=20update=20travis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 407ba9d05..3015bb3e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,3 +5,4 @@ jdk: - openjdk6 after_success: - mvn cobertura:cobertura coveralls:report + From 7dc33ba80eaef4f3ae44bef7923197d885acc5ba Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 3 Sep 2016 20:51:14 +0800 Subject: [PATCH 488/545] =?UTF-8?q?=E2=9C=84=20update=20gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 0ea2344df..d80cd146d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,12 @@ -bin -target -.settings -.project +# Maven # +target/ + +# IDEA # +.idea/ +*.iml + +# Eclipse # +.settings/ .classpath +.project +bin/ From a08c207c3bce196b3e158e1faf964be8fdc67bbb Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 3 Sep 2016 20:56:14 +0800 Subject: [PATCH 489/545] =?UTF-8?q?=E2=9C=84=20update=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- README_CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0fbc8796b..ba14aa3ba 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ## What Is Blade? Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. -If you like it, please [star and fork it](https://github.com/biezhi/blade). Thank you! +If you like it, please [star](https://github.com/biezhi/blade/stargazers) / [fork](https://github.com/biezhi/blade). Thx :blush: ## Features diff --git a/README_CN.md b/README_CN.md index fcd020169..b5015d4b4 100644 --- a/README_CN.md +++ b/README_CN.md @@ -12,7 +12,7 @@ Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁的代码,优雅的设计。 -如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush: +如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade/stargazers) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush: ## 特性 From f528d51c4932085bf1d7955f3a48d103005554f5 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 3 Sep 2016 23:34:57 +0800 Subject: [PATCH 490/545] =?UTF-8?q?=E2=9C=84=20update=20update=5Flog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UPDATE_LOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 0d42d4fc7..0e90a9140 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,5 +1,16 @@ # Blade 更新日志 +### v1.6.6 + 1. 支持内置jetty服务器启动 + 2. 支持@JSON和@RestController + 3. 支持自定义Banner启动 + 4. 支持AOP + 5. 自动查找基础包路径 + 6. 增强方法参数自动匹配 + 7. 支持可扩展配置, 将启动类和配置分离 + 8. 修复异常提示不全 + 9. 重构代码结构 + ### v1.6.3 1. 简化`blade-kit`配置类 2. 修改 `@Path` 为 `@Controller` From 7e3acd0fc53b06b621651a0e8aca8f60c5817843 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 3 Sep 2016 23:35:30 +0800 Subject: [PATCH 491/545] =?UTF-8?q?=E2=9C=84=20update=20license?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE | 1 - 1 file changed, 1 deletion(-) diff --git a/LICENSE b/LICENSE index 9b5e4019d..753842b67 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,3 @@ - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ From 6764583435f2a3adc58099a08cc3580daadb5c2e Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 4 Sep 2016 00:54:18 +0800 Subject: [PATCH 492/545] =?UTF-8?q?=E2=9C=84=20update=20last=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LAST_VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index f5302eacd..fbe9119c3 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -79,7 +79,7 @@     com.bladejava     blade-patchca -    1.0.2 +    1.0.4 ``` From 568644395ec78f15f0fcfa4a379ccee10af9c69c Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 4 Sep 2016 01:55:13 +0800 Subject: [PATCH 493/545] =?UTF-8?q?=E2=9C=84=20add=20blade-starter=20and?= =?UTF-8?q?=20update=20folder=20struct?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/Const.java | 108 +-- .../java/com/blade/banner/BannerStarter.java | 12 +- .../java/com/blade/banner/BladeBanner.java | 76 +- .../com/blade/config/ApplicationConfig.java | 452 ++++++------ .../com/blade/context/DynamicClassReader.java | 119 +-- .../java/com/blade/{asm => kit}/AsmKit.java | 222 +++--- .../com/blade/{mvc => kit}/DispatchKit.java | 430 +++++------ .../java/com/blade/mvc/DispatcherHandler.java | 407 +++++------ .../java/com/blade/mvc/DispatcherServlet.java | 323 ++++----- .../mvc/http/wrapper/ServletResponse.java | 680 +++++++++--------- .../blade/mvc/view/handle/MethodArgument.java | 322 ++++----- .../com/blade/kit/{IpKit.java => IPKit.java} | 168 ++--- .../java/com/blade/kit/base/ConfigLoader.java | 154 ++++ blade-starter/pom.xml | 105 +++ pom.xml | 179 +++-- 15 files changed, 2010 insertions(+), 1747 deletions(-) rename blade-core/src/main/java/com/blade/{asm => kit}/AsmKit.java (95%) rename blade-core/src/main/java/com/blade/{mvc => kit}/DispatchKit.java (95%) rename blade-kit/src/main/java/com/blade/kit/{IpKit.java => IPKit.java} (96%) create mode 100644 blade-kit/src/main/java/com/blade/kit/base/ConfigLoader.java create mode 100644 blade-starter/pom.xml diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index fa0994807..639ed20b9 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -1,54 +1,54 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -/** - * Const Interface - * - * @author biezhi - * @since 1.6.6 - */ -public interface Const { - - // current blade version - String BLADE_VERSION = "1.6.6-beta"; - - // default embedd server context path - String DEFAULT_CONTEXTPATH = "/"; - - // Server 500 error HTML - String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; - - // Server 404 error HTML - String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; - - // Default jetty server port - int DEFAULT_PORT = 9000; - - // Request ThreadPoll context key - String BLADE_EXECUTOR = "blade-req-executor"; - - /**************** - * blade properties - * **************/ - String BLADE_ROUTE = "blade.route"; - String BLADE_IOC = "blade.ioc"; - String BLADE_VIEW_404 = "blade.view404"; - String BLADE_VIEW_500 = "blade.view500"; - String BLADE_DEV = "blade.dev"; - String APP_PROPERTIES = "app.properties"; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +/** + * Const Interface + * + * @author biezhi + * @since 1.6.6 + */ +public interface Const { + + // current blade version + String BLADE_VERSION = "1.6.6"; + + // default embedd server context path + String DEFAULT_CONTEXTPATH = "/"; + + // Server 500 error HTML + String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; + + // Server 404 error HTML + String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; + + // Default jetty server port + int DEFAULT_PORT = 9000; + + // Request ThreadPoll context key + String BLADE_EXECUTOR = "blade-req-executor"; + + /**************** + * blade properties + * **************/ + String BLADE_ROUTE = "blade.route"; + String BLADE_IOC = "blade.ioc"; + String BLADE_VIEW_404 = "blade.view404"; + String BLADE_VIEW_500 = "blade.view500"; + String BLADE_DEV = "blade.dev"; + String APP_PROPERTIES = "app.properties"; + +} diff --git a/blade-core/src/main/java/com/blade/banner/BannerStarter.java b/blade-core/src/main/java/com/blade/banner/BannerStarter.java index 4f5932e6a..529be89e2 100644 --- a/blade-core/src/main/java/com/blade/banner/BannerStarter.java +++ b/blade-core/src/main/java/com/blade/banner/BannerStarter.java @@ -15,17 +15,15 @@ */ package com.blade.banner; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public final class BannerStarter { - - private static final Logger LOGGER = LoggerFactory.getLogger(BannerStarter.class); - private static Banner banner = new BladeBanner(); + private static Banner BANNER = new BladeBanner(); public static void printStart(){ - LOGGER.info(banner.startText()); + System.out.println(BANNER.startText()); } + public static void banner(Banner banner){ + BANNER = banner; + } } diff --git a/blade-core/src/main/java/com/blade/banner/BladeBanner.java b/blade-core/src/main/java/com/blade/banner/BladeBanner.java index 6da393aaa..bfc441876 100644 --- a/blade-core/src/main/java/com/blade/banner/BladeBanner.java +++ b/blade-core/src/main/java/com/blade/banner/BladeBanner.java @@ -1,38 +1,38 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.banner; - -import com.blade.Const; - -public class BladeBanner implements Banner { - - private static final String[] banner = { - " __, _, _, __, __,", - " |_) | /_\\ | \\ |_", - " |_) | , | | |_/ |", - " ~ ~~~ ~ ~ ~ ~~~" - }; - - @Override - public String startText() { - StringBuffer text = new StringBuffer(); - for (String s : banner) { - text.append('\t' + s); - } - text.append("\t :: Blade :: (v" + Const.BLADE_VERSION + ")\r\n"); - return text.toString(); - } -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.banner; + +import com.blade.Const; + +public class BladeBanner implements Banner { + + private static final String[] banner = { + " __, _, _, __, __,", + " |_) | /_\\ | \\ |_", + " |_) | , | | |_/ |", + " ~ ~~~ ~ ~ ~ ~~~" + }; + + @Override + public String startText() { + StringBuffer text = new StringBuffer(); + for (String s : banner) { + text.append("\r\n\t\t" + s); + } + text.append("\r\n\t\t :: Blade :: (v" + Const.BLADE_VERSION + ")\r\n"); + return text.toString(); + } +} diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 76cfef457..499bd1935 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -1,226 +1,226 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.kit.Assert; -import com.blade.kit.Environment; -import com.blade.kit.StringKit; - -/** - * Blade Application Config Class - * - * @author biezhi - * @since 1.6.6 - * - */ -public class ApplicationConfig { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfig.class); - - // Storage of all routing packets - private Set routePackages = new HashSet(8); - - // Store all IOC packages - private Set iocPackages = new HashSet(8); - - // Strore all config packages - private Set configPackages = new HashSet(2); - - // Store all filter directories - private Set staticFolders = new HashSet(5); - - // Base package - private String basePackage; - - // Interceptor package - private String interceptorPackage; - - // Encoding - private String encoding = "utf-8"; - - // web root path - private String webRoot; - - // 404 view page - private String view404; - - // 500 view page - private String view500; - - // Is dev mode - private boolean isDev = true; - - private boolean isInit = false; - - private Class applicationClass; - - public ApplicationConfig() { - this.addResources("/public", "/assets", "/static"); - } - - public void setEnv(Environment environment) { - if (null != environment && !isInit) { - this.isDev = environment.getBoolean("app.dev", true); - this.encoding = environment.getString("http.encoding", "UTF-8"); - this.addIocPackages(environment.getString("app.ioc")); - this.view500 = environment.getString("app.view.500"); - this.view404 = environment.getString("app.view.404"); - - String statics = environment.getString("app.statics"); - String basePackage = environment.getString("app.base-package"); - Integer port = environment.getInt("server.port"); - - if (null != port) { - Blade.$().listen(port); - } - - if (StringKit.isNotBlank(statics)) { - this.addResources(statics.split(",")); - } - - if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { - this.setBasePackage(basePackage); - } - isInit = true; - } - } - - public String[] getRoutePackages() { - String[] routeArr = new String[routePackages.size()]; - return routePackages.toArray(routeArr); - } - - public void addRoutePackages(String... packages) { - if (null != packages && packages.length > 0) { - routePackages.addAll(Arrays.asList(packages)); - } - } - - public String getBasePackage() { - return basePackage; - } - - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - this.addConfigPackages(basePackage + ".config"); - this.addIocPackages(basePackage + ".service.*"); - this.addRoutePackages(basePackage + ".controller"); - this.setInterceptorPackage(basePackage + ".interceptor"); - } - - public String[] getIocPackages() { - String[] iocArr = new String[iocPackages.size()]; - return iocPackages.toArray(iocArr); - } - - public String[] getConfigPackages() { - String[] configArr = new String[configPackages.size()]; - return configPackages.toArray(configArr); - } - - public void addIocPackages(String... packages) { - if (null != packages && packages.length > 0) { - iocPackages.addAll(Arrays.asList(packages)); - } - } - - public void addConfigPackages(String... packages) { - if (null != packages && packages.length > 0) { - configPackages.addAll(Arrays.asList(packages)); - } - } - - public String getInterceptorPackage() { - return interceptorPackage; - } - - public void setInterceptorPackage(String interceptorPackage) { - this.interceptorPackage = interceptorPackage; - } - - public Set getStaticFolders() { - return staticFolders; - } - - public void addResources(String... resources) { - Assert.notNull(resources); - for(String resource : resources){ - LOGGER.debug("Add Resource: {}", resource); - } - staticFolders.addAll(Arrays.asList(resources)); - } - - public String getView404() { - return view404; - } - - public void setView404(String view404) { - this.view404 = view404; - } - - public String getView500() { - return view500; - } - - public void setView500(String view500) { - this.view500 = view500; - } - - public String getWebRoot() { - return webRoot; - } - - public void setWebRoot(String webRoot) { - this.webRoot = webRoot; - } - - public boolean isDev() { - return isDev; - } - - public void setDev(boolean isDev) { - this.isDev = isDev; - } - - public String getEncoding() { - return encoding; - } - - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - public boolean isInit(){ - return this.isInit; - } - - public Class getApplicationClass() { - return applicationClass; - } - - public void setApplicationClass(Class applicationClass) { - this.applicationClass = applicationClass; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.kit.Assert; +import com.blade.kit.Environment; +import com.blade.kit.StringKit; + +/** + * Blade Application Config Class + * + * @author biezhi + * @since 1.6.6 + * + */ +public class ApplicationConfig { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfig.class); + + // Storage of all routing packets + private Set routePackages = new HashSet(8); + + // Store all IOC packages + private Set iocPackages = new HashSet(8); + + // Strore all config packages + private Set configPackages = new HashSet(2); + + // Store all filter directories + private Set staticFolders = new HashSet(5); + + // Base package + private String basePackage; + + // Interceptor package + private String interceptorPackage; + + // Encoding + private String encoding = "utf-8"; + + // web root path + private String webRoot = ""; + + // 404 view page + private String view404 = "404.html"; + + // 500 view page + private String view500 = "500.html"; + + // Is dev mode + private boolean isDev = true; + + private boolean isInit = false; + + private Class applicationClass; + + public ApplicationConfig() { + this.addResources("/public", "/assets", "/static"); + } + + public void setEnv(Environment environment) { + if (null != environment && !isInit) { + this.isDev = environment.getBoolean("app.dev", true); + this.encoding = environment.getString("http.encoding", "UTF-8"); + this.addIocPackages(environment.getString("app.ioc")); + this.view500 = environment.getString("app.view.500"); + this.view404 = environment.getString("app.view.404"); + + String statics = environment.getString("app.statics"); + String basePackage = environment.getString("app.base-package"); + Integer port = environment.getInt("server.port"); + + if (null != port) { + Blade.$().listen(port); + } + + if (StringKit.isNotBlank(statics)) { + this.addResources(statics.split(",")); + } + + if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { + this.setBasePackage(basePackage); + } + isInit = true; + } + } + + public String[] getRoutePackages() { + String[] routeArr = new String[routePackages.size()]; + return routePackages.toArray(routeArr); + } + + public void addRoutePackages(String... packages) { + if (null != packages && packages.length > 0) { + routePackages.addAll(Arrays.asList(packages)); + } + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + this.addConfigPackages(basePackage + ".config"); + this.addIocPackages(basePackage + ".service.*"); + this.addRoutePackages(basePackage + ".controller"); + this.setInterceptorPackage(basePackage + ".interceptor"); + } + + public String[] getIocPackages() { + String[] iocArr = new String[iocPackages.size()]; + return iocPackages.toArray(iocArr); + } + + public String[] getConfigPackages() { + String[] configArr = new String[configPackages.size()]; + return configPackages.toArray(configArr); + } + + public void addIocPackages(String... packages) { + if (null != packages && packages.length > 0) { + iocPackages.addAll(Arrays.asList(packages)); + } + } + + public void addConfigPackages(String... packages) { + if (null != packages && packages.length > 0) { + configPackages.addAll(Arrays.asList(packages)); + } + } + + public String getInterceptorPackage() { + return interceptorPackage; + } + + public void setInterceptorPackage(String interceptorPackage) { + this.interceptorPackage = interceptorPackage; + } + + public Set getStaticFolders() { + return staticFolders; + } + + public void addResources(String... resources) { + Assert.notNull(resources); + for(String resource : resources){ + LOGGER.debug("Add Resource: {}", resource); + } + staticFolders.addAll(Arrays.asList(resources)); + } + + public String getView404() { + return view404; + } + + public void setView404(String view404) { + this.view404 = view404; + } + + public String getView500() { + return view500; + } + + public void setView500(String view500) { + this.view500 = view500; + } + + public String getWebRoot() { + return webRoot; + } + + public void setWebRoot(String webRoot) { + this.webRoot = webRoot; + } + + public boolean isDev() { + return isDev; + } + + public void setDev(boolean isDev) { + this.isDev = isDev; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public boolean isInit(){ + return this.isInit; + } + + public Class getApplicationClass() { + return applicationClass; + } + + public void setApplicationClass(Class applicationClass) { + this.applicationClass = applicationClass; + } + +} diff --git a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java index c4381d9cc..85993143b 100644 --- a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java +++ b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java @@ -1,56 +1,63 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.kit.resource.ClassPathClassReader; -import com.blade.kit.resource.ClassReader; -import com.blade.kit.resource.JarReaderImpl; - -/** - * Get ClassReader by JAR or folder - * - * @author biezhi - * @since 1.6.6 - */ -public final class DynamicClassReader { - - private static final Logger LOGGER = LoggerFactory.getLogger(DynamicClassReader.class); - - private static ClassReader CLASS_READER = null; - - private DynamicClassReader() { - } - - public static void init(){ - Class clazz = Blade.$().config().getApplicationClass(); - String rs = clazz.getResource("").toString(); - if(rs.indexOf(".jar") != -1){ - CLASS_READER = new JarReaderImpl(); - LOGGER.debug("{}", CLASS_READER); - } else{ - CLASS_READER = new ClassPathClassReader(); - } - } - - public static ClassReader getClassReader(){ - return CLASS_READER; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.kit.resource.ClassPathClassReader; +import com.blade.kit.resource.ClassReader; +import com.blade.kit.resource.JarReaderImpl; + +/** + * Get ClassReader by JAR or folder + * + * @author biezhi + * @since 1.6.6 + */ +public final class DynamicClassReader { + + private static final Logger LOGGER = LoggerFactory.getLogger(DynamicClassReader.class); + + private static ClassReader CLASS_READER = null; + + private static boolean isJarContext = false; + + private DynamicClassReader() { + } + + public static void init(){ + Class clazz = Blade.$().config().getApplicationClass(); + String rs = clazz.getResource("").toString(); + if(rs.indexOf(".jar") != -1){ + CLASS_READER = new JarReaderImpl(); + isJarContext = true; + LOGGER.debug("{}", CLASS_READER); + } else{ + CLASS_READER = new ClassPathClassReader(); + } + } + + public static ClassReader getClassReader(){ + return CLASS_READER; + } + + public static boolean isJarContext() { + return isJarContext; + } + +} diff --git a/blade-core/src/main/java/com/blade/asm/AsmKit.java b/blade-core/src/main/java/com/blade/kit/AsmKit.java similarity index 95% rename from blade-core/src/main/java/com/blade/asm/AsmKit.java rename to blade-core/src/main/java/com/blade/kit/AsmKit.java index a96121d91..ddb94e92b 100644 --- a/blade-core/src/main/java/com/blade/asm/AsmKit.java +++ b/blade-core/src/main/java/com/blade/kit/AsmKit.java @@ -1,111 +1,111 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.asm; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * ASM Tools - * - * @author biezhi - * @since 1.6.6 - */ -public final class AsmKit { - - /** - * - *

- * 比较参数类型是否一致 - *

- * - * @param types - * asm的类型({@link Type}) - * @param clazzes - * java 类型({@link Class}) - * @return - */ - private static boolean sameType(Type[] types, Class[] clazzes) { - // 个数不同 - if (types.length != clazzes.length) { - return false; - } - for (int i = 0; i < types.length; i++) { - if (!Type.getType(clazzes[i]).equals(types[i])) { - return false; - } - } - return true; - } - - /** - * - *

- * 获取方法的参数名 - *

- * - * @param m - * @return - */ - public static String[] getMethodParamNames(final Method m) throws IOException { - final String[] paramNames = new String[m.getParameterTypes().length]; - final String n = m.getDeclaringClass().getName(); - ClassReader cr = null; - try { - cr = new ClassReader(n); - } catch (IOException e) { - return null; - } - cr.accept(new ClassVisitor(Opcodes.ASM5) { - @Override - public MethodVisitor visitMethod(final int access, final String name, final String desc, - final String signature, final String[] exceptions) { - final Type[] args = Type.getArgumentTypes(desc); - // 方法名相同并且参数个数相同 - if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { - return super.visitMethod(access, name, desc, signature, exceptions); - } - MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); - return new MethodVisitor(Opcodes.ASM5, v) { - @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, - int index) { - int i = index - 1; - // 如果是静态方法,则第一就是参数 - // 如果不是静态方法,则第一个是"this",然后才是方法的参数 - if (Modifier.isStatic(m.getModifiers())) { - i = index; - } - if (i >= 0 && i < paramNames.length) { - paramNames[i] = name; - } - super.visitLocalVariable(name, desc, signature, start, end, index); - } - }; - } - }, 0); - return paramNames; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * ASM Tools + * + * @author biezhi + * @since 1.6.6 + */ +public final class AsmKit { + + /** + * + *

+ * 比较参数类型是否一致 + *

+ * + * @param types + * asm的类型({@link Type}) + * @param clazzes + * java 类型({@link Class}) + * @return + */ + private static boolean sameType(Type[] types, Class[] clazzes) { + // 个数不同 + if (types.length != clazzes.length) { + return false; + } + for (int i = 0; i < types.length; i++) { + if (!Type.getType(clazzes[i]).equals(types[i])) { + return false; + } + } + return true; + } + + /** + * + *

+ * 获取方法的参数名 + *

+ * + * @param m + * @return + */ + public static String[] getMethodParamNames(final Method m) throws IOException { + final String[] paramNames = new String[m.getParameterTypes().length]; + final String n = m.getDeclaringClass().getName(); + ClassReader cr = null; + try { + cr = new ClassReader(n); + } catch (IOException e) { + return null; + } + cr.accept(new ClassVisitor(Opcodes.ASM5) { + @Override + public MethodVisitor visitMethod(final int access, final String name, final String desc, + final String signature, final String[] exceptions) { + final Type[] args = Type.getArgumentTypes(desc); + // 方法名相同并且参数个数相同 + if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { + return super.visitMethod(access, name, desc, signature, exceptions); + } + MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); + return new MethodVisitor(Opcodes.ASM5, v) { + @Override + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, + int index) { + int i = index - 1; + // 如果是静态方法,则第一就是参数 + // 如果不是静态方法,则第一个是"this",然后才是方法的参数 + if (Modifier.isStatic(m.getModifiers())) { + i = index; + } + if (i >= 0 && i < paramNames.length) { + paramNames[i] = name; + } + super.visitLocalVariable(name, desc, signature, start, end, index); + } + }; + } + }, 0); + return paramNames; + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/DispatchKit.java b/blade-core/src/main/java/com/blade/kit/DispatchKit.java similarity index 95% rename from blade-core/src/main/java/com/blade/mvc/DispatchKit.java rename to blade-core/src/main/java/com/blade/kit/DispatchKit.java index 5c895b781..7aa3dfa91 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/kit/DispatchKit.java @@ -1,215 +1,215 @@ -package com.blade.mvc; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLDecoder; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.kit.FileKit; -import com.blade.kit.IOKit; -import com.blade.kit.StreamKit; -import com.blade.kit.StringKit; -import com.blade.mvc.http.HttpException; -import com.blade.mvc.http.Response; - -import static com.blade.Blade.$; - -public class DispatchKit { - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatchKit.class); - - static final boolean isWeb = !$().enableServer(); - - static final Class appClass = $().config().getApplicationClass(); - - private static Boolean isDev = null; - - public static String getPath(Class clazz) { - URL url = clazz.getProtectionDomain().getCodeSource().getLocation(); - String filePath = null; - try { - filePath = URLDecoder.decode(url.getPath(), "utf-8"); - } catch (Exception e) { - e.printStackTrace(); - } - if (filePath.endsWith(".jar")) { - filePath = "jar:file:" + filePath + "!/"; - return filePath; - } - File file = new File(filePath); - filePath = file.getAbsolutePath(); - return filePath; - } - - public static String getWebRoot(ServletContext sc) { - if(isWeb){ - String dir = sc.getRealPath("/"); - if (dir == null) { - try { - URL url = sc.getResource("/"); - if (url != null && "file".equals(url.getProtocol())) { - dir = URLDecoder.decode(url.getFile(), "utf-8"); - } else { - throw new IllegalStateException("Can't get webroot dir, url = " + url); - } - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - return dir; - } - return getPath(appClass); - } - - public static void setNoCache(HttpServletResponse response) { - // Http 1.0 header - response.setHeader("Buffer", "false"); - response.setHeader("Pragma", "no-cache"); - response.setDateHeader("Expires", 1L); - // Http 1.1 header - response.setHeader("Cache-Control", "no-cache, no-store, max-age=0"); - } - - public static void setFileDownloadHeader(HttpServletResponse response, String fileName, String contentType) { - if (contentType == null) { - contentType = "application/x-download"; - } - response.setContentType(contentType); - // 中文文件名支持 - try { - String encodedfileName = new String(fileName.getBytes(), "ISO8859-1"); - response.setHeader("Content-Disposition", "attachment; filename=" + encodedfileName); - } catch (UnsupportedEncodingException e) { - } - } - - /** - * Print Error Message - * - * @param err - * @param code - * @param response - */ - public static void printError(Throwable err, int code, Response response) { - if (null == isDev) { - isDev = Blade.$().isDev(); - } - try { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final PrintWriter writer = new PrintWriter(baos); - - // If the developer mode, the error output to the page - if (isDev) { - writer.println(String.format(HTML, err.getClass() + " : " + err.getMessage())); - writer.println(); - err.printStackTrace(writer); - writer.println(END); - } else { - if (code == 404) { - String view404 = Blade.$().view404(); - if (StringKit.isNotBlank(view404)) { - response.render(view404); - return; - } else { - writer.write(err.getMessage()); - } - } else { - String view500 = Blade.$().view500(); - if (StringKit.isNotBlank(view500)) { - response.render(view500); - return; - } else { - writer.write(Const.INTERNAL_ERROR); - } - } - } - writer.close(); - response.status(code); - InputStream body = new ByteArrayInputStream(baos.toByteArray()); - print(body, response.writer()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Print - * - * @param body - * @param out - * @throws IOException - */ - public static void print(InputStream in, OutputStream out) throws IOException { - StreamKit.io(in, out); - } - - public static void print(InputStream body, PrintWriter writer) throws IOException { - print(IOKit.toString(body), writer); - } - - public static void print(String content, PrintWriter writer) throws IOException { - writer.print(content); - writer.flush(); - writer.close(); - } - - /** - * Print static file - * - * @param uri - * @param realpath - * @param httpResponse - */ - public static void printStatic(String uri, HttpServletRequest request, Response response) { - try { - String realpath = ""; - InputStream ins = null; - if (isWeb) { - realpath = request.getServletContext().getRealPath(uri); - File file = new File(realpath); - if (FileKit.exist(file)) { - ins = new FileInputStream(file); - } - } else { - ins = appClass.getResourceAsStream(uri); - } - - if (null != ins) { - print(ins, response.outputStream()); - } else { - LOGGER.debug("request realpath is [{}]", realpath); - HttpException httpException = new HttpException(404, uri + " not found"); - DispatchKit.printError(httpException, 404, response); - } - } catch (FileNotFoundException e) { - DispatchKit.printError(e, 404, response); - } catch (IOException e) { - DispatchKit.printError(e, 500, response); - } - } - - private static final String HTML = "Blade Framework Error Page" - + "" - + "

%s

";
-
-	private static final String END = "
Blade-" + Const.BLADE_VERSION - + "(Blade Framework
"; - -} +package com.blade.kit; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.kit.FileKit; +import com.blade.kit.IOKit; +import com.blade.kit.StreamKit; +import com.blade.kit.StringKit; +import com.blade.mvc.http.HttpException; +import com.blade.mvc.http.Response; + +import static com.blade.Blade.$; + +public class DispatchKit { + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatchKit.class); + + static final boolean isWeb = !$().enableServer(); + + static final Class appClass = $().config().getApplicationClass(); + + private static Boolean isDev = null; + + public static String getPath(Class clazz) { + URL url = clazz.getProtectionDomain().getCodeSource().getLocation(); + String filePath = null; + try { + filePath = URLDecoder.decode(url.getPath(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } + if (filePath.endsWith(".jar")) { + filePath = "jar:file:" + filePath + "!/"; + return filePath; + } + File file = new File(filePath); + filePath = file.getAbsolutePath(); + return filePath; + } + + public static String getWebRoot(ServletContext sc) { + if(isWeb){ + String dir = sc.getRealPath("/"); + if (dir == null) { + try { + URL url = sc.getResource("/"); + if (url != null && "file".equals(url.getProtocol())) { + dir = URLDecoder.decode(url.getFile(), "utf-8"); + } else { + throw new IllegalStateException("Can't get webroot dir, url = " + url); + } + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + return dir; + } + return getPath(appClass); + } + + public static void setNoCache(HttpServletResponse response) { + // Http 1.0 header + response.setHeader("Buffer", "false"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 1L); + // Http 1.1 header + response.setHeader("Cache-Control", "no-cache, no-store, max-age=0"); + } + + public static void setFileDownloadHeader(HttpServletResponse response, String fileName, String contentType) { + if (contentType == null) { + contentType = "application/x-download"; + } + response.setContentType(contentType); + // 中文文件名支持 + try { + String encodedfileName = new String(fileName.getBytes(), "ISO8859-1"); + response.setHeader("Content-Disposition", "attachment; filename=" + encodedfileName); + } catch (UnsupportedEncodingException e) { + } + } + + /** + * Print Error Message + * + * @param err + * @param code + * @param response + */ + public static void printError(Throwable err, int code, Response response) { + if (null == isDev) { + isDev = Blade.$().isDev(); + } + try { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final PrintWriter writer = new PrintWriter(baos); + + // If the developer mode, the error output to the page + if (isDev) { + writer.println(String.format(HTML, err.getClass() + " : " + err.getMessage())); + writer.println(); + err.printStackTrace(writer); + writer.println(END); + } else { + if (code == 404) { + String view404 = Blade.$().view404(); + if (StringKit.isNotBlank(view404)) { + response.render(view404); + return; + } else { + writer.write(err.getMessage()); + } + } else { + String view500 = Blade.$().view500(); + if (StringKit.isNotBlank(view500)) { + response.render(view500); + return; + } else { + writer.write(Const.INTERNAL_ERROR); + } + } + } + writer.close(); + response.status(code); + InputStream body = new ByteArrayInputStream(baos.toByteArray()); + print(body, response.writer()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Print + * + * @param body + * @param out + * @throws IOException + */ + public static void print(InputStream in, OutputStream out) throws IOException { + StreamKit.io(in, out); + } + + public static void print(InputStream body, PrintWriter writer) throws IOException { + print(IOKit.toString(body), writer); + } + + public static void print(String content, PrintWriter writer) throws IOException { + writer.print(content); + writer.flush(); + writer.close(); + } + + /** + * Print static file + * + * @param uri + * @param realpath + * @param httpResponse + */ + public static void printStatic(String uri, HttpServletRequest request, Response response) { + try { + String realpath = ""; + InputStream ins = null; + if (isWeb) { + realpath = request.getServletContext().getRealPath(uri); + File file = new File(realpath); + if (FileKit.exist(file)) { + ins = new FileInputStream(file); + } + } else { + ins = appClass.getResourceAsStream(uri); + } + + if (null != ins) { + print(ins, response.outputStream()); + } else { + LOGGER.debug("request realpath is [{}]", realpath); + HttpException httpException = new HttpException(404, uri + " not found"); + DispatchKit.printError(httpException, 404, response); + } + } catch (FileNotFoundException e) { + DispatchKit.printError(e, 404, response); + } catch (IOException e) { + DispatchKit.printError(e, 500, response); + } + } + + private static final String HTML = "Blade Error Page" + + "" + + "

%s

";
+
+	private static final String END = "
Blade-" + Const.BLADE_VERSION + + "(Blade Framework
"; + +} diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index f82e32176..e67592af0 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -1,204 +1,205 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; - -import java.io.IOException; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.context.ApplicationWebContext; -import com.blade.exception.BladeException; -import com.blade.ioc.Ioc; -import com.blade.kit.StringKit; -import com.blade.mvc.http.HttpStatus; -import com.blade.mvc.http.Path; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.http.wrapper.ServletRequest; -import com.blade.mvc.http.wrapper.ServletResponse; -import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteHandler; -import com.blade.mvc.route.RouteMatcher; -import com.blade.mvc.route.Routers; -import com.blade.mvc.view.ModelAndView; -import com.blade.mvc.view.handle.RouteViewHandler; -import com.blade.mvc.view.template.TemplateException; - -/** - * Synchronous request processor - * - * @author biezhi - * @since 1.5 - */ -public class DispatcherHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); - - private Ioc ioc; - - private Blade blade; - - private ServletContext servletContext; - - private RouteMatcher routeMatcher; - - private StaticFileFilter staticFileFilter; - - private RouteViewHandler routeViewHandler; - - public DispatcherHandler(ServletContext servletContext, Routers routers) { - this.servletContext = servletContext; - this.blade = Blade.$(); - this.ioc = blade.ioc(); - this.routeMatcher = new RouteMatcher(routers); - this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); - this.routeViewHandler = new RouteViewHandler(this.ioc); - } - - public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ - - // http method, GET/POST ... - String method = httpRequest.getMethod(); - - // reuqest uri - String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - - // Create Response - Response response = new ServletResponse(httpResponse);; - - // If it is static, the resource is handed over to the filter - if(staticFileFilter.isStatic(uri)){ - LOGGER.debug("Request : {}\t{}", method, uri); - DispatchKit.printStatic(uri, httpRequest, response); - return; - } - - LOGGER.info("Request : {}\t{}", method, uri); - - try { - - Request request = new ServletRequest(httpRequest); - ApplicationWebContext.init(servletContext, request, response); - Route route = routeMatcher.getRoute(method, uri); - if (null != route) { - request.setRoute(route); - - // before inteceptor - List befores = routeMatcher.getBefore(uri); - boolean result = invokeInterceptor(request, response, befores); - if(result){ - // execute - this.routeHandle(request, response, route); - if(!request.isAbort()){ - // after inteceptor - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - } - } - } else { - // Not found - render404(response, uri); - } - return; - } catch (TemplateException e) { - LOGGER.error("Template error", e); - DispatchKit.printError(e, 500, response); - } catch (BladeException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - }catch (Exception e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } - return; - } - - /** - * 404 view render - * - * @param response response object - * @param uri 404 uri - * @throws IOException - * @throws TemplateException - */ - private void render404(Response response, String uri) throws Exception { - String view404 = blade.view404(); - if(StringKit.isNotBlank(view404)){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", uri); - response.render( modelAndView ); - } else { - response.status(HttpStatus.NOT_FOUND); - response.html(String.format(Const.VIEW_NOTFOUND, uri)); - } - } - - /** - * Methods to perform the interceptor - * - * @param request request object - * @param response response object - * @param interceptors execute the interceptor list - * @return Return execute is ok - */ - private boolean invokeInterceptor(Request request, Response response, List interceptors) throws Exception { - for(Route route : interceptors){ - boolean flag = routeViewHandler.intercept(request, response, route); - if(!flag){ - return false; - } - } - return true; - } - - /** - * Actual routing method execution - * - * @param request request object - * @param response response object - * @param route route object - */ - private void routeHandle(Request request, Response response, Route route) throws Exception{ - Object target = route.getTarget(); - if(null == target){ - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - request.initPathParams(route.getPath()); - - // Init context - ApplicationWebContext.init(servletContext, request, response); - if(route.getTargetType() == RouteHandler.class){ - RouteHandler routeHandler = (RouteHandler) target; - routeHandler.handle(request, response); - } else { - routeViewHandler.handle(request, response, route); - } - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.context.ApplicationWebContext; +import com.blade.exception.BladeException; +import com.blade.ioc.Ioc; +import com.blade.kit.DispatchKit; +import com.blade.kit.StringKit; +import com.blade.mvc.http.HttpStatus; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.http.wrapper.ServletRequest; +import com.blade.mvc.http.wrapper.ServletResponse; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteHandler; +import com.blade.mvc.route.RouteMatcher; +import com.blade.mvc.route.Routers; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.handle.RouteViewHandler; +import com.blade.mvc.view.template.TemplateException; + +/** + * Synchronous request processor + * + * @author biezhi + * @since 1.5 + */ +public class DispatcherHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); + + private Ioc ioc; + + private Blade blade; + + private ServletContext servletContext; + + private RouteMatcher routeMatcher; + + private StaticFileFilter staticFileFilter; + + private RouteViewHandler routeViewHandler; + + public DispatcherHandler(ServletContext servletContext, Routers routers) { + this.servletContext = servletContext; + this.blade = Blade.$(); + this.ioc = blade.ioc(); + this.routeMatcher = new RouteMatcher(routers); + this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); + this.routeViewHandler = new RouteViewHandler(this.ioc); + } + + public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ + + // http method, GET/POST ... + String method = httpRequest.getMethod(); + + // reuqest uri + String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); + + // Create Response + Response response = new ServletResponse(httpResponse);; + + // If it is static, the resource is handed over to the filter + if(staticFileFilter.isStatic(uri)){ + LOGGER.debug("Request : {}\t{}", method, uri); + DispatchKit.printStatic(uri, httpRequest, response); + return; + } + + LOGGER.info("Request : {}\t{}", method, uri); + + try { + + Request request = new ServletRequest(httpRequest); + ApplicationWebContext.init(servletContext, request, response); + Route route = routeMatcher.getRoute(method, uri); + if (null != route) { + request.setRoute(route); + + // before inteceptor + List befores = routeMatcher.getBefore(uri); + boolean result = invokeInterceptor(request, response, befores); + if(result){ + // execute + this.routeHandle(request, response, route); + if(!request.isAbort()){ + // after inteceptor + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + } + } + } else { + // Not found + render404(response, uri); + } + return; + } catch (TemplateException e) { + LOGGER.error("Template error", e); + DispatchKit.printError(e, 500, response); + } catch (BladeException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + }catch (Exception e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } + return; + } + + /** + * 404 view render + * + * @param response response object + * @param uri 404 uri + * @throws IOException + * @throws TemplateException + */ + private void render404(Response response, String uri) throws Exception { + String view404 = blade.view404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(Const.VIEW_NOTFOUND, uri)); + } + } + + /** + * Methods to perform the interceptor + * + * @param request request object + * @param response response object + * @param interceptors execute the interceptor list + * @return Return execute is ok + */ + private boolean invokeInterceptor(Request request, Response response, List interceptors) throws Exception { + for(Route route : interceptors){ + boolean flag = routeViewHandler.intercept(request, response, route); + if(!flag){ + return false; + } + } + return true; + } + + /** + * Actual routing method execution + * + * @param request request object + * @param response response object + * @param route route object + */ + private void routeHandle(Request request, Response response, Route route) throws Exception{ + Object target = route.getTarget(); + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + request.initPathParams(route.getPath()); + + // Init context + ApplicationWebContext.init(servletContext, request, response); + if(route.getTargetType() == RouteHandler.class){ + RouteHandler routeHandler = (RouteHandler) target; + routeHandler.handle(request, response); + } else { + routeViewHandler.handle(request, response, route); + } + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java index facb9ac9d..ad2ad98ad 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java @@ -1,161 +1,162 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; - -import java.io.IOException; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Bootstrap; -import com.blade.banner.BannerStarter; -import com.blade.context.ApplicationContext; -import com.blade.context.ApplicationWebContext; -import com.blade.context.DynamicClassReader; -import com.blade.embedd.EmbedServer; -import com.blade.kit.StringKit; -import com.blade.kit.SystemKit; - -/** - * Blade Core DispatcherServlet - * - * @author biezhi - * @since 1.5 - */ -public class DispatcherServlet extends HttpServlet { - - private static final long serialVersionUID = -2607425162473178733L; - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); - - private Blade blade = Blade.$(); - - private Bootstrap bootstrap; - - private ServletContext servletContext; - - private DispatcherHandler dispatcherHandler; - - public DispatcherServlet() { - } - - public DispatcherServlet(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - blade.init(); - } - - @Override - public void init(ServletConfig config) throws ServletException { - servletContext = config.getServletContext(); - if(!blade.isInit()){ - - LOGGER.info("jdk.version\t=> {}", SystemKit.getJavaInfo().getVersion()); - LOGGER.info("user.dir\t\t=> {}", System.getProperty("user.dir")); - LOGGER.info("java.io.tmpdir\t=> {}", System.getProperty("java.io.tmpdir")); - LOGGER.info("user.timezone\t=> {}", System.getProperty("user.timezone")); - LOGGER.info("file.encodin\t=> {}", System.getProperty("file.encoding")); - - long initStart = System.currentTimeMillis(); - - String webRoot = DispatchKit.getWebRoot(servletContext); - - blade.webRoot(webRoot); - EmbedServer embedServer = blade.embedServer(); - if(null != embedServer){ - embedServer.setWebRoot(webRoot); - } - - LOGGER.info("blade.webroot\t=> {}", webRoot); - - DynamicClassReader.init(); - - ApplicationWebContext.init(servletContext); - - this.bootstrap = blade.bootstrap(); - - if(null == bootstrap){ - String bootStrapClassName = config.getInitParameter("bootstrap"); - if(StringKit.isNotBlank(bootStrapClassName)){ - this.bootstrap = getBootstrap(bootStrapClassName); - } else { - this.bootstrap = new Bootstrap() { - @Override - public void init(Blade blade) { - } - }; - } - blade.app(this.bootstrap); - } - - ApplicationContext.init(blade); - - LOGGER.info("blade.isDev = {}", blade.isDev()); - - dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); - - BannerStarter.printStart(); - - String appName = blade.environment().getString("app.name", "Blade"); - - LOGGER.info("{} initialize successfully, Time elapsed: {} ms.", appName, System.currentTimeMillis() - initStart); - } - } - - @Override - protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { - httpRequest.setCharacterEncoding(blade.encoding()); - httpResponse.setCharacterEncoding(blade.encoding()); - dispatcherHandler.handle(httpRequest, httpResponse); - } - - @Override - public void destroy() { - super.destroy(); - } - - /** - * Get global initialization object, the application of the initialization - * - * @param botstrapClassName botstrap class name - * @return return bootstrap object - * @throws ServletException - */ - @SuppressWarnings("unchecked") - private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { - Bootstrap bootstrapClass = null; - try { - if(null != botstrapClassName){ - Class applicationClass = (Class) Class.forName(botstrapClassName); - if(null != applicationClass){ - bootstrapClass = applicationClass.newInstance(); - } - } else { - throw new ServletException("bootstrapClass is null !"); - } - } catch (Exception e) { - throw new ServletException(e); - } - return bootstrapClass; - } -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Bootstrap; +import com.blade.banner.BannerStarter; +import com.blade.context.ApplicationContext; +import com.blade.context.ApplicationWebContext; +import com.blade.context.DynamicClassReader; +import com.blade.embedd.EmbedServer; +import com.blade.kit.DispatchKit; +import com.blade.kit.StringKit; +import com.blade.kit.SystemKit; + +/** + * Blade Core DispatcherServlet + * + * @author biezhi + * @since 1.5 + */ +public class DispatcherServlet extends HttpServlet { + + private static final long serialVersionUID = -2607425162473178733L; + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); + + private Blade blade = Blade.$(); + + private Bootstrap bootstrap; + + private ServletContext servletContext; + + private DispatcherHandler dispatcherHandler; + + public DispatcherServlet() { + } + + public DispatcherServlet(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + blade.init(); + } + + @Override + public void init(ServletConfig config) throws ServletException { + servletContext = config.getServletContext(); + if(!blade.isInit()){ + + LOGGER.info("jdk.version\t=> {}", SystemKit.getJavaInfo().getVersion()); + LOGGER.info("user.dir\t\t=> {}", System.getProperty("user.dir")); + LOGGER.info("java.io.tmpdir\t=> {}", System.getProperty("java.io.tmpdir")); + LOGGER.info("user.timezone\t=> {}", System.getProperty("user.timezone")); + LOGGER.info("file.encodin\t=> {}", System.getProperty("file.encoding")); + + long initStart = System.currentTimeMillis(); + + String webRoot = DispatchKit.getWebRoot(servletContext); + + blade.webRoot(webRoot); + EmbedServer embedServer = blade.embedServer(); + if(null != embedServer){ + embedServer.setWebRoot(webRoot); + } + + LOGGER.info("blade.webroot\t=> {}", webRoot); + + DynamicClassReader.init(); + + ApplicationWebContext.init(servletContext); + + this.bootstrap = blade.bootstrap(); + + if(null == bootstrap){ + String bootStrapClassName = config.getInitParameter("bootstrap"); + if(StringKit.isNotBlank(bootStrapClassName)){ + this.bootstrap = getBootstrap(bootStrapClassName); + } else { + this.bootstrap = new Bootstrap() { + @Override + public void init(Blade blade) { + } + }; + } + blade.app(this.bootstrap); + } + + ApplicationContext.init(blade); + + LOGGER.info("blade.isDev = {}", blade.isDev()); + + dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); + + BannerStarter.printStart(); + + String appName = blade.environment().getString("app.name", "Blade"); + + LOGGER.info("{} initialize successfully, Time elapsed: {} ms.", appName, System.currentTimeMillis() - initStart); + } + } + + @Override + protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { + httpRequest.setCharacterEncoding(blade.encoding()); + httpResponse.setCharacterEncoding(blade.encoding()); + dispatcherHandler.handle(httpRequest, httpResponse); + } + + @Override + public void destroy() { + super.destroy(); + } + + /** + * Get global initialization object, the application of the initialization + * + * @param botstrapClassName botstrap class name + * @return return bootstrap object + * @throws ServletException + */ + @SuppressWarnings("unchecked") + private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { + Bootstrap bootstrapClass = null; + try { + if(null != botstrapClassName){ + Class applicationClass = (Class) Class.forName(botstrapClassName); + if(null != applicationClass){ + bootstrapClass = applicationClass.newInstance(); + } + } else { + throw new ServletException("bootstrapClass is null !"); + } + } catch (Exception e) { + throw new ServletException(e); + } + return bootstrapClass; + } +} diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java index d5978f887..393287cff 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java @@ -1,340 +1,340 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http.wrapper; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.context.ApplicationWebContext; -import com.blade.kit.Assert; -import com.blade.mvc.DispatchKit; -import com.blade.mvc.http.HttpStatus; -import com.blade.mvc.http.Path; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.view.ModelAndView; -import com.blade.mvc.view.ViewSettings; -import com.blade.mvc.view.parser.JSONParser; -import com.blade.mvc.view.template.TemplateEngine; -import com.blade.mvc.view.template.TemplateException; - -/** - * ServletResponse - * - * @author biezhi - * @since 1.5 - */ -public class ServletResponse implements Response { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServletResponse.class); - - private HttpServletResponse response; - - private boolean written = false; - - private ViewSettings viewSettings; - - private TemplateEngine templateEngine; - - private JSONParser jsonParser; - - public ServletResponse(HttpServletResponse response) { - this.response = response; - this.viewSettings = ViewSettings.$(); - this.templateEngine = viewSettings.templateEngine(); - this.jsonParser = viewSettings.JSONParser(); - } - - @Override - public HttpServletResponse raw() { - return response; - } - - @Override - public int status() { - return response.getStatus(); - } - - @Override - public Response status(int status) { - response.setStatus(status); - return this; - } - - @Override - public Response badRequest() { - response.setStatus(HttpStatus.BAD_REQUEST); - return this; - } - - @Override - public Response unauthorized() { - response.setStatus(HttpStatus.UNAUTHORIZED); - return this; - } - - @Override - public Response notFound() { - response.setStatus(HttpStatus.NOT_FOUND); - return this; - } - - @Override - public Response conflict() { - response.setStatus(HttpStatus.CONFLICT); - return this; - } - - @Override - public String contentType() { - return response.getContentType(); - } - - @Override - public Response contentType(String contentType) { - response.setContentType(contentType); - return this; - } - - @Override - public String header(String name) { - return response.getHeader(name); - } - - @Override - public Response header(String name, String value) { - response.setHeader(name, value); - return this; - } - - @Override - public Response cookie(Cookie cookie) { - response.addCookie(cookie); - return this; - } - - @Override - public Response cookie(String name, String value) { - return cookie(name, value); - } - - @Override - public Response cookie(String name, String value, int maxAge) { - return cookie(name, value, maxAge, false); - } - - @Override - public Response cookie(String name, String value, int maxAge, boolean secured) { - return cookie(null, name, value, maxAge, secured); - } - - @Override - public Response cookie(String path, String name, String value, int maxAge, boolean secured) { - Cookie cookie = new Cookie(name, value); - if(null != path){ - cookie.setPath(path); - } - cookie.setMaxAge(maxAge); - cookie.setSecure(secured); - response.addCookie(cookie); - return this; - } - - @Override - public Response removeCookie(Cookie cookie) { - cookie.setMaxAge(0); - response.addCookie(map(cookie)); - return this; - } - - javax.servlet.http.Cookie map(Cookie cookie) { - javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); - servletCookie.setMaxAge(cookie.getMaxAge()); - if (cookie.getPath() != null) { - servletCookie.setPath(cookie.getPath()); - } - if (cookie.getDomain() != null) { - servletCookie.setDomain(cookie.getDomain()); - } - servletCookie.setHttpOnly(cookie.isHttpOnly()); - servletCookie.setSecure(cookie.getSecure()); - return servletCookie; - } - - @Override - public Response removeCookie(String name) { - Cookie cookie = new Cookie(name, ""); - cookie.setMaxAge(0); - response.addCookie(cookie); - return this; - } - - @Override - public Response text(String text) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/plain;charset=utf-8"); - DispatchKit.print(text, response.getWriter()); - this.written = true; - return this; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Response html(String html) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/html;charset=utf-8"); - - PrintWriter writer = response.getWriter(); - DispatchKit.print(html, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public Response json(String json) { - Request request = ApplicationWebContext.request(); - String userAgent = request.userAgent(); - if (userAgent.contains("MSIE")) { - response.setContentType("text/html;charset=utf-8"); - } else { - response.setContentType("application/json;charset=utf-8"); - } - try { - response.setHeader("Cache-Control", "no-cache"); - PrintWriter writer = response.getWriter(); - DispatchKit.print(json, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Response json(Object bean) { - return this.json(jsonParser.toJSONSting(bean)); - } - - @Override - public Response xml(String xml) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/xml;charset=utf-8"); - PrintWriter writer = response.getWriter(); - DispatchKit.print(xml, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public ServletOutputStream outputStream() throws IOException { - return response.getOutputStream(); - } - - @Override - public PrintWriter writer() throws IOException { - return response.getWriter(); - } - - @Override - public Response render(String view){ - Assert.notBlank(view, "view not is null"); - - String viewPath = Path.cleanPath(view); - ModelAndView modelAndView = new ModelAndView(viewPath); - try { - templateEngine.render(modelAndView, response.getWriter()); - } catch (TemplateException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return this; - } - - @Override - public Response render(ModelAndView modelAndView) { - Assert.notNull(modelAndView, "ModelAndView not is null!"); - Assert.notBlank(modelAndView.getView(), "view not is null"); - - String viewPath = Path.cleanPath(modelAndView.getView()); - modelAndView.setView(viewPath); - try { - templateEngine.render(modelAndView, response.getWriter()); - } catch (TemplateException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return this; - } - - @Override - public void redirect(String path) { - try { - response.sendRedirect(path); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void go(String path) { - try { - String ctx = ApplicationWebContext.servletContext().getContextPath(); - String location = Path.fixPath(ctx + path); - response.sendRedirect(location); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public boolean isWritten() { - return written; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http.wrapper; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.ApplicationWebContext; +import com.blade.kit.Assert; +import com.blade.kit.DispatchKit; +import com.blade.mvc.http.HttpStatus; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; +import com.blade.mvc.view.parser.JSONParser; +import com.blade.mvc.view.template.TemplateEngine; +import com.blade.mvc.view.template.TemplateException; + +/** + * ServletResponse + * + * @author biezhi + * @since 1.5 + */ +public class ServletResponse implements Response { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServletResponse.class); + + private HttpServletResponse response; + + private boolean written = false; + + private ViewSettings viewSettings; + + private TemplateEngine templateEngine; + + private JSONParser jsonParser; + + public ServletResponse(HttpServletResponse response) { + this.response = response; + this.viewSettings = ViewSettings.$(); + this.templateEngine = viewSettings.templateEngine(); + this.jsonParser = viewSettings.JSONParser(); + } + + @Override + public HttpServletResponse raw() { + return response; + } + + @Override + public int status() { + return response.getStatus(); + } + + @Override + public Response status(int status) { + response.setStatus(status); + return this; + } + + @Override + public Response badRequest() { + response.setStatus(HttpStatus.BAD_REQUEST); + return this; + } + + @Override + public Response unauthorized() { + response.setStatus(HttpStatus.UNAUTHORIZED); + return this; + } + + @Override + public Response notFound() { + response.setStatus(HttpStatus.NOT_FOUND); + return this; + } + + @Override + public Response conflict() { + response.setStatus(HttpStatus.CONFLICT); + return this; + } + + @Override + public String contentType() { + return response.getContentType(); + } + + @Override + public Response contentType(String contentType) { + response.setContentType(contentType); + return this; + } + + @Override + public String header(String name) { + return response.getHeader(name); + } + + @Override + public Response header(String name, String value) { + response.setHeader(name, value); + return this; + } + + @Override + public Response cookie(Cookie cookie) { + response.addCookie(cookie); + return this; + } + + @Override + public Response cookie(String name, String value) { + return cookie(name, value); + } + + @Override + public Response cookie(String name, String value, int maxAge) { + return cookie(name, value, maxAge, false); + } + + @Override + public Response cookie(String name, String value, int maxAge, boolean secured) { + return cookie(null, name, value, maxAge, secured); + } + + @Override + public Response cookie(String path, String name, String value, int maxAge, boolean secured) { + Cookie cookie = new Cookie(name, value); + if(null != path){ + cookie.setPath(path); + } + cookie.setMaxAge(maxAge); + cookie.setSecure(secured); + response.addCookie(cookie); + return this; + } + + @Override + public Response removeCookie(Cookie cookie) { + cookie.setMaxAge(0); + response.addCookie(map(cookie)); + return this; + } + + javax.servlet.http.Cookie map(Cookie cookie) { + javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); + servletCookie.setMaxAge(cookie.getMaxAge()); + if (cookie.getPath() != null) { + servletCookie.setPath(cookie.getPath()); + } + if (cookie.getDomain() != null) { + servletCookie.setDomain(cookie.getDomain()); + } + servletCookie.setHttpOnly(cookie.isHttpOnly()); + servletCookie.setSecure(cookie.getSecure()); + return servletCookie; + } + + @Override + public Response removeCookie(String name) { + Cookie cookie = new Cookie(name, ""); + cookie.setMaxAge(0); + response.addCookie(cookie); + return this; + } + + @Override + public Response text(String text) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/plain;charset=utf-8"); + DispatchKit.print(text, response.getWriter()); + this.written = true; + return this; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Response html(String html) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/html;charset=utf-8"); + + PrintWriter writer = response.getWriter(); + DispatchKit.print(html, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public Response json(String json) { + Request request = ApplicationWebContext.request(); + String userAgent = request.userAgent(); + if (userAgent.contains("MSIE")) { + response.setContentType("text/html;charset=utf-8"); + } else { + response.setContentType("application/json;charset=utf-8"); + } + try { + response.setHeader("Cache-Control", "no-cache"); + PrintWriter writer = response.getWriter(); + DispatchKit.print(json, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Response json(Object bean) { + return this.json(jsonParser.toJSONSting(bean)); + } + + @Override + public Response xml(String xml) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/xml;charset=utf-8"); + PrintWriter writer = response.getWriter(); + DispatchKit.print(xml, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public ServletOutputStream outputStream() throws IOException { + return response.getOutputStream(); + } + + @Override + public PrintWriter writer() throws IOException { + return response.getWriter(); + } + + @Override + public Response render(String view){ + Assert.notBlank(view, "view not is null"); + + String viewPath = Path.cleanPath(view); + ModelAndView modelAndView = new ModelAndView(viewPath); + try { + templateEngine.render(modelAndView, response.getWriter()); + } catch (TemplateException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return this; + } + + @Override + public Response render(ModelAndView modelAndView) { + Assert.notNull(modelAndView, "ModelAndView not is null!"); + Assert.notBlank(modelAndView.getView(), "view not is null"); + + String viewPath = Path.cleanPath(modelAndView.getView()); + modelAndView.setView(viewPath); + try { + templateEngine.render(modelAndView, response.getWriter()); + } catch (TemplateException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return this; + } + + @Override + public void redirect(String path) { + try { + response.sendRedirect(path); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void go(String path) { + try { + String ctx = ApplicationWebContext.servletContext().getContextPath(); + String location = Path.fixPath(ctx + path); + response.sendRedirect(location); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public boolean isWritten() { + return written; + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java index a3e72ff0e..f2c586b87 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java @@ -1,161 +1,161 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.handle; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - -import com.blade.annotation.PathVariable; -import com.blade.annotation.RequestParam; -import com.blade.asm.AsmKit; -import com.blade.exception.BladeException; -import com.blade.exception.NotFoundException; -import com.blade.kit.StringKit; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.multipart.FileItem; -import com.blade.mvc.view.ModelAndView; - -public final class MethodArgument { - - public static Object[] getArgs(Request request, Response response, Method actionMethod) throws Exception{ - Class[] parameters = actionMethod.getParameterTypes(); - Annotation[][] paramterAnnotations = actionMethod.getParameterAnnotations(); - - Object[] args = new Object[parameters.length]; - - try { - actionMethod.setAccessible(true); - String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); - - for (int i = 0, len = parameters.length; i < len; i++) { - - Class argType = parameters[i]; - if (argType.getName().equals(Request.class.getName())) { - args[i] = request; - continue; - } - - if (argType.getName().equals(Response.class.getName())) { - args[i] = response; - continue; - } - - if (argType.getName().equals(ModelAndView.class.getName())) { - args[i] = new ModelAndView(); - continue; - } - - if(argType.getName().equals(FileItem.class.getName())){ - args[i] = new ModelAndView(); - continue; - } - - Annotation annotation = paramterAnnotations[i][0]; - - if(null != annotation){ - if(annotation.annotationType().equals(RequestParam.class)){ - RequestParam requestParam = (RequestParam) annotation; - String paramName = requestParam.value(); - String val = request.query(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.query(paramName); - } else { - if (StringKit.isBlank(val)) { - throw new NotFoundException("request param [" + paramName + "] is null"); - } - } - args[i] = getRequestParam(argType, val, requestParam.defaultValue()); - continue; - } - - if(annotation.annotationType().equals(PathVariable.class)){ - PathVariable pathVariable = (PathVariable) annotation; - String paramName = pathVariable.value(); - String val = request.param(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.param(paramName); - } else { - if (StringKit.isBlank(val)) { - throw new NotFoundException("path param [" + paramName + "] is null"); - } - } - args[i] = getRequestParam(argType, val, null); - continue; - } - } - } - return args; - } catch (BladeException e) { - throw e; - } - } - - private static Object getRequestParam(Class parameterType, String val, String defaultValue) { - Object result = null; - if (parameterType.equals(String.class)) { - if (StringKit.isNotBlank(val)) { - result = val; - } else { - if (null != defaultValue) { - result = defaultValue; - } - } - } else if (parameterType.equals(Integer.class)) { - if (StringKit.isNotBlank(val)) { - result = Integer.parseInt(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Integer.parseInt(defaultValue); - } - } - } else if (parameterType.equals(int.class)) { - if (StringKit.isNotBlank(val)) { - result = Integer.parseInt(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Integer.parseInt(defaultValue); - } else { - result = 0; - } - } - } else if (parameterType.equals(Long.class)) { - if (StringKit.isNotBlank(val)) { - result = Long.parseLong(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Long.parseLong(defaultValue); - } - } - } else if (parameterType.equals(long.class)) { - if (StringKit.isNotBlank(val)) { - result = Long.parseLong(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Long.parseLong(defaultValue); - } else { - result = 0L; - } - } - } - return result; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.handle; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import com.blade.annotation.PathVariable; +import com.blade.annotation.RequestParam; +import com.blade.exception.BladeException; +import com.blade.exception.NotFoundException; +import com.blade.kit.AsmKit; +import com.blade.kit.StringKit; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.multipart.FileItem; +import com.blade.mvc.view.ModelAndView; + +public final class MethodArgument { + + public static Object[] getArgs(Request request, Response response, Method actionMethod) throws Exception{ + Class[] parameters = actionMethod.getParameterTypes(); + Annotation[][] paramterAnnotations = actionMethod.getParameterAnnotations(); + + Object[] args = new Object[parameters.length]; + + try { + actionMethod.setAccessible(true); + String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); + + for (int i = 0, len = parameters.length; i < len; i++) { + + Class argType = parameters[i]; + if (argType.getName().equals(Request.class.getName())) { + args[i] = request; + continue; + } + + if (argType.getName().equals(Response.class.getName())) { + args[i] = response; + continue; + } + + if (argType.getName().equals(ModelAndView.class.getName())) { + args[i] = new ModelAndView(); + continue; + } + + if(argType.getName().equals(FileItem.class.getName())){ + args[i] = new ModelAndView(); + continue; + } + + Annotation annotation = paramterAnnotations[i][0]; + + if(null != annotation){ + if(annotation.annotationType().equals(RequestParam.class)){ + RequestParam requestParam = (RequestParam) annotation; + String paramName = requestParam.value(); + String val = request.query(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.query(paramName); + } else { + if (StringKit.isBlank(val)) { + throw new NotFoundException("request param [" + paramName + "] is null"); + } + } + args[i] = getRequestParam(argType, val, requestParam.defaultValue()); + continue; + } + + if(annotation.annotationType().equals(PathVariable.class)){ + PathVariable pathVariable = (PathVariable) annotation; + String paramName = pathVariable.value(); + String val = request.param(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.param(paramName); + } else { + if (StringKit.isBlank(val)) { + throw new NotFoundException("path param [" + paramName + "] is null"); + } + } + args[i] = getRequestParam(argType, val, null); + continue; + } + } + } + return args; + } catch (BladeException e) { + throw e; + } + } + + private static Object getRequestParam(Class parameterType, String val, String defaultValue) { + Object result = null; + if (parameterType.equals(String.class)) { + if (StringKit.isNotBlank(val)) { + result = val; + } else { + if (null != defaultValue) { + result = defaultValue; + } + } + } else if (parameterType.equals(Integer.class)) { + if (StringKit.isNotBlank(val)) { + result = Integer.parseInt(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Integer.parseInt(defaultValue); + } + } + } else if (parameterType.equals(int.class)) { + if (StringKit.isNotBlank(val)) { + result = Integer.parseInt(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Integer.parseInt(defaultValue); + } else { + result = 0; + } + } + } else if (parameterType.equals(Long.class)) { + if (StringKit.isNotBlank(val)) { + result = Long.parseLong(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Long.parseLong(defaultValue); + } + } + } else if (parameterType.equals(long.class)) { + if (StringKit.isNotBlank(val)) { + result = Long.parseLong(val); + } else { + if (StringKit.isNotBlank(defaultValue)) { + result = Long.parseLong(defaultValue); + } else { + result = 0L; + } + } + } + return result; + } + +} diff --git a/blade-kit/src/main/java/com/blade/kit/IpKit.java b/blade-kit/src/main/java/com/blade/kit/IPKit.java similarity index 96% rename from blade-kit/src/main/java/com/blade/kit/IpKit.java rename to blade-kit/src/main/java/com/blade/kit/IPKit.java index 0a51426ee..7d81ddad0 100644 --- a/blade-kit/src/main/java/com/blade/kit/IpKit.java +++ b/blade-kit/src/main/java/com/blade/kit/IPKit.java @@ -1,85 +1,85 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.Enumeration; - -import javax.servlet.http.HttpServletRequest; - -/** - * IP工具类 - * - * @author biezhi - * @since 1.0 - */ -public class IpKit { - - /** - * @param request - * IP - * @return IP Address - */ - public static String getIpAddrByRequest(HttpServletRequest request) { - String ip = request.getHeader("x-forwarded-for"); - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getHeader("Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getHeader("WL-Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { - ip = request.getRemoteAddr(); - } - return ip; - } - - /** - * @return 本机IP - * @throws SocketException - */ - public static String getRealIp() throws SocketException { - String localip = null;// 本地IP,如果没有配置外网IP则返回它 - String netip = null;// 外网IP - - Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces(); - InetAddress ip = null; - boolean finded = false;// 是否找到外网IP - while (netInterfaces.hasMoreElements() && !finded) { - NetworkInterface ni = netInterfaces.nextElement(); - Enumeration address = ni.getInetAddresses(); - while (address.hasMoreElements()) { - ip = address.nextElement(); - if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 外网IP - netip = ip.getHostAddress(); - finded = true; - break; - } else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 内网IP - localip = ip.getHostAddress(); - } - } - } - - if (netip != null && !"".equals(netip)) { - return netip; - } else { - return localip; - } - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Enumeration; + +import javax.servlet.http.HttpServletRequest; + +/** + * IP工具类 + * + * @author biezhi + * @since 1.0 + */ +public class IPKit { + + /** + * @param request + * IP + * @return IP Address + */ + public static String getIpAddrByRequest(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + return ip; + } + + /** + * @return 本机IP + * @throws SocketException + */ + public static String getRealIp() throws SocketException { + String localip = null;// 本地IP,如果没有配置外网IP则返回它 + String netip = null;// 外网IP + + Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces(); + InetAddress ip = null; + boolean finded = false;// 是否找到外网IP + while (netInterfaces.hasMoreElements() && !finded) { + NetworkInterface ni = netInterfaces.nextElement(); + Enumeration address = ni.getInetAddresses(); + while (address.hasMoreElements()) { + ip = address.nextElement(); + if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 外网IP + netip = ip.getHostAddress(); + finded = true; + break; + } else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 内网IP + localip = ip.getHostAddress(); + } + } + } + + if (netip != null && !"".equals(netip)) { + return netip; + } else { + return localip; + } + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/com/blade/kit/base/ConfigLoader.java b/blade-kit/src/main/java/com/blade/kit/base/ConfigLoader.java new file mode 100644 index 000000000..f9c778be9 --- /dev/null +++ b/blade-kit/src/main/java/com/blade/kit/base/ConfigLoader.java @@ -0,0 +1,154 @@ +package com.blade.kit.base; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.ServletContext; + +import com.blade.kit.IOKit; + +public class ConfigLoader { + + private final Map config; + + public ConfigLoader() { + config = new HashMap(32); + } + + public ConfigLoader load(Properties props) { + for (String key : props.stringPropertyNames()) { + String value = props.getProperty(key); + config.put(key, value); + } + return this; + } + + public ConfigLoader load(Map map) { + config.putAll(map); + return this; + } + + /** + * 从文件路径或者classpath路径中载入配置. + * @param location - 配置文件路径 + * @return this + */ + public ConfigLoader load(String location) { + if (location.startsWith("classpath:")) { + location = location.substring("classpath:".length()); + return loadClasspath(location); + } else if (location.startsWith("file:")) { + location = location.substring("file:".length()); + return load(new File(location)); + } else { + return load(new File(location)); + } + } + + // 从 URL 载入 + public ConfigLoader load(URL url) { + String location = url.getPath(); + try { + location = URLDecoder.decode(location, "utf-8"); + } catch (UnsupportedEncodingException e) { + } + + try { + return loadInputStream(url.openStream(), location); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + // 从 classpath 下面载入 + private ConfigLoader loadClasspath(String classpath) { + if (classpath.startsWith("/")) { + classpath = classpath.substring(1); + } + InputStream is = getDefault().getResourceAsStream(classpath); + return loadInputStream(is, classpath); + } + + // 从 File 载入 + public ConfigLoader load(File file) { + try { + return loadInputStream(new FileInputStream(file), file.getName()); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + // 载入 web 资源文件 + public ConfigLoader load(String location, ServletContext sc) { + if (location.startsWith("classpath:") || location.startsWith("file:")) { + return load(location); + } else { + if (location.startsWith("webroot:")) { + location = location.substring("webroot:".length()); + } + if (!location.startsWith("/")) { + location = "/" + location; + } + InputStream is = sc.getResourceAsStream(location); + return loadInputStream(is, location); + } + } + + private ConfigLoader loadInputStream(InputStream is, String location) { + if (is == null) { + throw new IllegalStateException("InputStream not found: " + location); + } + + location = location.toLowerCase(); + try { + Properties config = new Properties(); + config.load(is); + load(config); + return this; + } catch (IOException e) { + throw new IllegalStateException(e); + } finally { + IOKit.closeQuietly(is); + } + } + + public ConfigLoader loadSystemProperties() { + return load(System.getProperties()); + } + + public ConfigLoader loadSystemEnvs() { + return load(System.getenv()); + } + + /** + * Returns current thread's context class loader + */ + public static ClassLoader getDefault() { + ClassLoader loader = null; + try { + loader = Thread.currentThread().getContextClassLoader(); + } catch (Exception e) { + } + if (loader == null) { + loader = ConfigLoader.class.getClassLoader(); + if (loader == null) { + try { + // getClassLoader() returning null indicates the bootstrap ClassLoader + loader = ClassLoader.getSystemClassLoader(); + } catch (Exception e) { + // Cannot access system ClassLoader - oh well, maybe the caller can live with null... + } + } + } + return loader; + } + +} diff --git a/blade-starter/pom.xml b/blade-starter/pom.xml new file mode 100644 index 000000000..75aa9d796 --- /dev/null +++ b/blade-starter/pom.xml @@ -0,0 +1,105 @@ + + + + blade + com.bladejava + 1.0 + + + 4.0.0 + + blade-starter + pom + 0.0.1 + + + UTF-8 + + 1.6.6 + 1.0.0 + 0.1.2 + 0.0.6 + 0.0.4 + 0.0.4 + + + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + + com.bladejava + blade-core + ${blade-core.version} + + + com.bladejava + blade-template-jetbrick + ${blade-template-jetbrick.version} + + + com.bladejava + blade-template-velocity + ${blade-template-velocity.version} + + + com.bladejava + blade-embed-jetty + ${blade-embed-jetty.version} + + + com.bladejava + blade-aop + ${blade-aop.version} + + + com.bladejava + blade-jdbc + ${blade-jdbc.version} + + + + + + + ${artifactId}-${version} + + + src/main/java + false + + + src/main/resources + false + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.2 + + 1.6 + 1.6 + UTF-8 + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index dd88a9e12..51a471c38 100644 --- a/pom.xml +++ b/pom.xml @@ -1,92 +1,89 @@ - - - 4.0.0 - - com.bladejava - blade - 1.0 - pom - - blade - https://github.com/biezhi/blade - - - 1.6 - 1.6 - UTF-8 - - 3.0.1 - 4.12 - 1.7.21 - 1.7.21 - - 1.6.6 - 1.3.3 - 1.0.0 - 0.0.4 - - - - - blade-kit - blade-core - blade-embed-jetty - blade-auth - blade-aop - - - - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - - - - - org.slf4j - slf4j-api - ${slf4j-api.version} - - - - org.slf4j - slf4j-log4j12 - ${slf4j-log4j12.version} - - - - junit - junit - ${junit.version} - test - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.6 - 1.6 - UTF-8 - - - - - + + + 4.0.0 + + com.bladejava + blade + 1.0 + pom + + blade + https://github.com/biezhi/blade + + + 1.6 + 1.6 + UTF-8 + + 3.0.1 + 4.12 + 1.7.21 + 1.7.21 + + 1.6.6 + 1.3.3 + 1.0.0 + 0.0.4 + + + + + blade-kit + blade-core + blade-embed-jetty + blade-auth + blade-aop + blade-starter + + + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + + org.slf4j + slf4j-api + ${slf4j-api.version} + + + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} + + + junit + junit + ${junit.version} + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + UTF-8 + + + + + \ No newline at end of file From f483c180525d631085bca3475911444fb0d5cc7f Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 4 Sep 2016 14:27:26 +0800 Subject: [PATCH 494/545] =?UTF-8?q?=E2=9C=84=20fix=20request=20param=20def?= =?UTF-8?q?ault=20value=20and=20move=20annotation=20pos.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blade/aop/AbstractMethodInterceptor.java | 86 +- blade-core/src/main/java/com/blade/Blade.java | 1532 ++++++++--------- .../com/blade/context/DynamicClassReader.java | 2 +- .../java/com/blade/ioc/IocApplication.java | 446 ++--- .../{ => mvc}/annotation/Controller.java | 2 +- .../blade/{ => mvc}/annotation/Intercept.java | 80 +- .../com/blade/{ => mvc}/annotation/JSON.java | 2 +- .../{ => mvc}/annotation/PathVariable.java | 2 +- .../{ => mvc}/annotation/RequestParam.java | 2 +- .../{ => mvc}/annotation/RestController.java | 2 +- .../com/blade/{ => mvc}/annotation/Route.java | 2 +- .../com/blade/mvc/route/RouteBuilder.java | 8 +- .../blade/mvc/view/handle/MethodArgument.java | 69 +- .../mvc/view/handle/RouteViewHandler.java | 206 +-- 14 files changed, 1209 insertions(+), 1232 deletions(-) rename blade-core/src/main/java/com/blade/{ => mvc}/annotation/Controller.java (97%) rename blade-core/src/main/java/com/blade/{ => mvc}/annotation/Intercept.java (94%) rename blade-core/src/main/java/com/blade/{ => mvc}/annotation/JSON.java (96%) rename blade-core/src/main/java/com/blade/{ => mvc}/annotation/PathVariable.java (97%) rename blade-core/src/main/java/com/blade/{ => mvc}/annotation/RequestParam.java (97%) rename blade-core/src/main/java/com/blade/{ => mvc}/annotation/RestController.java (97%) rename blade-core/src/main/java/com/blade/{ => mvc}/annotation/Route.java (98%) diff --git a/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java b/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java index 8ebc025dd..339207050 100644 --- a/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java +++ b/blade-aop/src/main/java/com/blade/aop/AbstractMethodInterceptor.java @@ -1,40 +1,46 @@ -package com.blade.aop; - -import java.lang.reflect.Method; - -import com.blade.aop.annotation.Aop; - -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; - -public abstract class AbstractMethodInterceptor implements MethodInterceptor { - - public abstract Object doInvoke(Invocaction invocaction) throws Throwable; - - public void before(Invocaction invocaction) {} - - public void after(Invocaction invocaction) {} - - /** - * 切面逻辑 obj 代理对象实例 method 源对象的方法名 args 传递给方法的实际入参 proxyMethod - * 与源对象中的method相对应的代理对象中的方法 - */ - public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable { - // 执行源对象的method方法 - try { - String methodPrefix = method.getDeclaringClass().getAnnotation(Aop.class).methodPrefix(); - String methodName = method.getName(); - if(!"".equals(methodPrefix) && !methodName.startsWith(methodPrefix)){ - return proxy.invokeSuper(target, args); - } - Invocaction invocaction = new Invocaction(target, args, proxy); - before(invocaction); - Object returnValue = doInvoke(invocaction); - after(invocaction); - return returnValue; - } catch (Exception e) { - throw e; - } - } - -} +package com.blade.aop; + +import java.lang.reflect.Method; + +import com.blade.aop.annotation.Aop; + +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +public abstract class AbstractMethodInterceptor implements MethodInterceptor { + + public abstract Object doInvoke(Invocaction invocaction) throws Throwable; + + public void before(Invocaction invocaction) {} + + public void after(Invocaction invocaction) {} + + /** + * 切面逻辑 obj 代理对象实例 method 源对象的方法名 args 传递给方法的实际入参 proxyMethod + * 与源对象中的method相对应的代理对象中的方法 + */ + public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable { + // 执行源对象的method方法 + try { + Aop aop = method.getDeclaringClass().getAnnotation(Aop.class); + if(null != aop){ + String methodPrefix = aop.methodPrefix(); + String methodName = method.getName(); + if(!"".equals(methodPrefix) && !methodName.startsWith(methodPrefix)){ + return proxy.invokeSuper(target, args); + } + } else { + return proxy.invokeSuper(target, args); + } + + Invocaction invocaction = new Invocaction(target, args, proxy); + before(invocaction); + Object returnValue = doInvoke(invocaction); + after(invocaction); + return returnValue; + } catch (Exception e) { + throw e; + } + } + +} diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index c16e60b52..733d32001 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -1,767 +1,767 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.io.InputStream; -import java.text.ParseException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.blade.config.ApplicationConfig; -import com.blade.config.BaseConfig; -import com.blade.config.ConfigLoader; -import com.blade.embedd.EmbedServer; -import com.blade.exception.EmbedServerException; -import com.blade.ioc.Ioc; -import com.blade.ioc.SimpleIoc; -import com.blade.kit.Assert; -import com.blade.kit.Environment; -import com.blade.kit.StringKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.mvc.http.HttpMethod; -import com.blade.mvc.interceptor.Interceptor; -import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteBuilder; -import com.blade.mvc.route.RouteException; -import com.blade.mvc.route.RouteGroup; -import com.blade.mvc.route.RouteHandler; -import com.blade.mvc.route.Routers; -import com.blade.mvc.route.loader.ClassPathRouteLoader; -import com.blade.plugin.Plugin; - -/** - * Blade Core Class - * - * @author biezhi - * @since 1.6.6 - */ -public final class Blade { - - // blade initialize - private boolean isInit = false; - - // blade bootstrap config class - private Bootstrap bootstrap = null; - - // global configuration Object - private ApplicationConfig applicationConfig = null; - - // ioc container - private Ioc ioc = new SimpleIoc(); - - // routes - private Routers routers = new Routers(); - - // routebuilder - private RouteBuilder routeBuilder; - - // jetty start port - private int port = Const.DEFAULT_PORT; - - // default context path - private String contextPath = Const.DEFAULT_CONTEXTPATH; - - // enableServer - private Boolean enableServer = false; - - // plugins - private Set> plugins; - - // global environment - private Environment environment; - - // config loader - private ConfigLoader configLoader; - - // embed server - private EmbedServer embedServer; - - private Blade() { - this.environment = new Environment(); - this.applicationConfig = new ApplicationConfig(); - this.plugins = new HashSet>(); - this.routeBuilder = new RouteBuilder(this.routers); - this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); - } - - static final class BladeHolder { - private static final Blade $ = new Blade(); - } - - /** - * @return Single case method returns Blade object - */ - @Deprecated - public static final Blade me() { - return BladeHolder.$; - } - - /** - * - * @param appConf - * @return - */ - @Deprecated - public static final Blade me(String confPath) { - Blade blade = BladeHolder.$; - blade.environment.add(confPath); - return blade; - } - - /** - * @return Single case method returns Blade object - */ - public static final Blade $() { - return BladeHolder.$; - } - - /** - * @param confPath - * @return - */ - public static final Blade $(String confPath) { - Assert.notEmpty(confPath); - Blade blade = BladeHolder.$; - blade.environment.add(confPath); - return blade; - } - - /** - * Set Blade initialize - * - * @param isInit - * initialize - */ - public void init() { - if (!this.isInit) { - this.isInit = true; - } - } - - /** - * @return return route manager - */ - public Routers routers() { - return routers; - } - - /** - * @return return RouteBuilder - */ - public RouteBuilder routeBuilder() { - return routeBuilder; - } - - /** - * @return return ConfigLoader - */ - public ConfigLoader configLoader() { - return configLoader; - } - - /** - * @return return blade ioc container - */ - public Ioc ioc() { - return ioc; - } - - /** - * Setting a ioc container - * - * @param container - * ioc object - * @return return blade - */ - public Blade container(Ioc ioc) { - Assert.notNull(ioc); - this.ioc = ioc; - this.configLoader.setIoc(ioc); - return this; - } - - /** - * Setting Properties configuration file File path based on classpath - * - * @param confPath - * properties file name - * @return return blade - */ - public Blade loadAppConf(String confPath) { - Assert.notBlank(confPath); - environment.add(confPath); - return this; - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackage(String packageName) { - return this.addRoutePackages(packageName); - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackages(String... packages) { - Assert.notNull(packages); - applicationConfig.addRoutePackages(packages); - return this; - } - - /** - * - * @param basePackage - * @return - */ - public Blade basePackage(String basePackage) { - Assert.notBlank(basePackage); - applicationConfig.setBasePackage(basePackage); - applicationConfig.addIocPackages(basePackage + ".service.*"); - applicationConfig.addRoutePackages(basePackage + ".controller"); - applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); - return this; - } - - /** - * Setting the path where the interceptor, e.g:com.bladejava.interceptor - * - * @param packageName - * interceptor packagename - * @return return blade - */ - public Blade interceptor(String packageName) { - Assert.notBlank(packageName); - applicationConfig.setInterceptorPackage(packageName); - return this; - } - - /** - * Setting Ioc packages, e.g:com.bladejava.service - * - * @param packages - * All need to do into the package, can be introduced into a - * number of - * @return return blade - */ - public Blade ioc(String... packages) { - Assert.notNull(packages); - applicationConfig.addIocPackages(packages); - return this; - } - - /** - * Add a route - * - * @param path - * route path - * @param target - * Target object for routing - * @param method - * The method name of the route (at the same time, the HttpMethod - * is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @return return blade - */ - public Blade route(String path, Class clazz, String method) { - routers.route(path, clazz, method); - return this; - } - - /** - * Register a functional route - * - * @param path - * route url - * @param clazz - * route processing class - * @param method - * route processing method name - * @param httpMethod - * HttpMethod Type, GET/POST/... - * @return Blade return blade - */ - public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { - routers.route(path, clazz, method, httpMethod); - return this; - } - - /** - * Add a route list - * - * @param routes - * route list - * @return return blade - */ - public Blade routes(List routes) { - Assert.notEmpty(routes, "Routes not is empty!"); - routers.addRoutes(routes); - return this; - } - - /** - * Register a GET request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade get(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.GET); - return this; - } - - /** - * Register a POST request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade post(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.POST); - return this; - } - - /** - * Register a DELETE request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade delete(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.DELETE); - return this; - } - - /** - * Register a PUT request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade put(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.PUT); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade all(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade any(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Route Group. e.g blade.group('/users').get().post() - * - * @param g - * @return return blade - */ - public RouteGroup group(String prefix) { - Assert.notNull(prefix, "Route group prefix not is null"); - return new RouteGroup(this, prefix); - } - - /** - * Register a pre routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade before(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.BEFORE); - return this; - } - - /** - * Register a after routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade after(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.AFTER); - return this; - } - - /** - * Setting the frame static file folder - * - * @param resources - * List of directories to filter, e.g: "/public,/static,/images" - * @return return blade - */ - public Blade addResources(final String... resources) { - applicationConfig.addResources(resources); - return this; - } - - /** - * Dynamically set the global initialization class, the embedded Jetty boot - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Bootstrap bootstrap) { - Assert.notNull(bootstrap); - this.bootstrap = bootstrap; - return this; - } - - /** - * Dynamically set global initialization class - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Class bootstrap) { - Assert.notNull(bootstrap); - try { - Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); - ioc.addBean(Bootstrap.class.getName(), object); - this.bootstrap = object; - } catch (Exception e) { - e.printStackTrace(); - } - return this; - } - - /** - * add interceptor - * - * @param interceptor interceptor class - * @return return blade obj - */ - public Blade addInterceptor(Class interceptor) { - routeBuilder.addInterceptor(interceptor); - return this; - } - - /** - * add config - * - * @param config config class - * @return return blade obj - */ - public Blade addConfig(Class config) { - configLoader.addConfig(config); - return this; - } - - /** - * Setting 404 view page - * - * @param view404 - * 404 view page - * @return return blade - */ - public Blade view404(final String view404) { - Assert.notBlank(view404); - applicationConfig.setView404(view404); - return this; - } - - /** - * Setting 500 view page - * - * @param view500 - * 500 view page - * @return return blade - */ - public Blade view500(final String view500) { - Assert.notBlank(view500); - applicationConfig.setView500(view500); - return this; - } - - /** - * Setting blade web root path - * - * @param webRoot - * web root path - * @return return blade - */ - public Blade webRoot(final String webRoot) { - Assert.notBlank(webRoot); - applicationConfig.setWebRoot(webRoot); - return this; - } - - /** - * Setting blade run mode - * - * @param isDev - * is dev mode - * @return return blade - */ - public Blade isDev(boolean isDev) { - applicationConfig.setDev(isDev); - return this; - } - - /** - * Setting jetty listen port - * - * @param port - * port, default is 9000 - * @return return blade - */ - public Blade listen(int port) { - this.port = port; - return this; - } - - /** - * start web server - */ - public void start() { - this.start(null); - } - - /** - * start web server - * @param applicationClass your app root package starter - */ - public void start(Class applicationClass) { - - this.loadAppConf(Const.APP_PROPERTIES); - - // init blade environment config - applicationConfig.setEnv(environment); - - if(null != applicationClass){ - applicationConfig.setApplicationClass(applicationClass); - if(StringKit.isBlank(applicationConfig.getBasePackage())){ - applicationConfig.setBasePackage(applicationClass.getPackage().getName()); - } - } - - try { - Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); - if(null == embedClazz){ - embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); - } - if(null != embedClazz){ - this.embedServer = (EmbedServer) embedClazz.newInstance(); - this.embedServer.startup(port, contextPath); - this.enableServer = true; - } else { - throw new EmbedServerException("Not found EmbedServer"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * @return Return EmbedServer - */ - public EmbedServer embedServer() { - return this.embedServer; - } - - /** - * @return Return blade config object - */ - public ApplicationConfig applicationConfig() { - return applicationConfig; - } - - /** - * @return Return blade config object - */ - public ApplicationConfig config() { - return applicationConfig; - } - - /** - * @return Return Blade Environment - */ - public Environment environment() { - return environment; - } - - /** - * @return Return blade encoding, default is UTF-8 - */ - public String encoding() { - return applicationConfig.getEncoding(); - } - - /** - * @return Return 404 view - */ - public String view404() { - return applicationConfig.getView404(); - } - - /** - * @return Return 500 view - */ - public String view500() { - return applicationConfig.getView500(); - } - - /** - * @return Return blade web root path - */ - public String webRoot() { - return applicationConfig.getWebRoot(); - } - - /** - * @return Return is dev mode - */ - public boolean isDev() { - return applicationConfig.isDev(); - } - - /** - * @return Return static resource directory - */ - public Set staticFolder() { - return applicationConfig.getStaticFolders(); - } - - /** - * @return Return bootstrap object - */ - public Bootstrap bootstrap() { - return this.bootstrap; - } - - /** - * return register plugin object - * - * @param plugin - * plugin class - * @return return blade - */ - public Blade plugin(Class plugin) { - Assert.notNull(plugin); - plugins.add(plugin); - return this; - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @return return blade - */ - public Blade routeConf(String basePackage) { - return routeConf(basePackage, "route.conf"); - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @param conf - * Configuration file path, the configuration file must be in - * classpath - * @return return blade - */ - public Blade routeConf(String basePackage, String conf) { - try { - Assert.notBlank(basePackage); - Assert.notBlank(conf); - InputStream ins = Blade.class.getResourceAsStream("/" + conf); - ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); - routesLoader.setBasePackage(basePackage); - List routes = routesLoader.load(); - routers.addRoutes(routes); - } catch (RouteException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - return this; - } - - /** - * @return Return blade is initialize - */ - public boolean isInit() { - return isInit; - } - - public Blade enableServer(boolean enableServer) { - this.enableServer = enableServer; - return this; - } - - public boolean enableServer() { - return this.enableServer; - } - - public Set> plugins() { - return this.plugins; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +import java.io.InputStream; +import java.text.ParseException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.blade.config.ApplicationConfig; +import com.blade.config.BaseConfig; +import com.blade.config.ConfigLoader; +import com.blade.embedd.EmbedServer; +import com.blade.exception.EmbedServerException; +import com.blade.ioc.Ioc; +import com.blade.ioc.SimpleIoc; +import com.blade.kit.Assert; +import com.blade.kit.Environment; +import com.blade.kit.StringKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.interceptor.Interceptor; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteBuilder; +import com.blade.mvc.route.RouteException; +import com.blade.mvc.route.RouteGroup; +import com.blade.mvc.route.RouteHandler; +import com.blade.mvc.route.Routers; +import com.blade.mvc.route.loader.ClassPathRouteLoader; +import com.blade.plugin.Plugin; + +/** + * Blade Core Class + * + * @author biezhi + * @since 1.6.6 + */ +public final class Blade { + + // blade initialize + private boolean isInit = false; + + // blade bootstrap config class + private Bootstrap bootstrap = null; + + // global configuration Object + private ApplicationConfig applicationConfig = null; + + // ioc container + private Ioc ioc = new SimpleIoc(); + + // routes + private Routers routers = new Routers(); + + // routebuilder + private RouteBuilder routeBuilder; + + // jetty start port + private int port = Const.DEFAULT_PORT; + + // default context path + private String contextPath = Const.DEFAULT_CONTEXTPATH; + + // enableServer + private Boolean enableServer = false; + + // plugins + private Set> plugins; + + // global environment + private Environment environment; + + // config loader + private ConfigLoader configLoader; + + // embed server + private EmbedServer embedServer; + + private Blade() { + this.environment = new Environment(); + this.applicationConfig = new ApplicationConfig(); + this.plugins = new HashSet>(); + this.routeBuilder = new RouteBuilder(this.routers); + this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); + } + + static final class BladeHolder { + private static final Blade $ = new Blade(); + } + + /** + * @return Single case method returns Blade object + */ + @Deprecated + public static final Blade me() { + return BladeHolder.$; + } + + /** + * + * @param appConf + * @return + */ + @Deprecated + public static final Blade me(String confPath) { + Blade blade = BladeHolder.$; + blade.environment.add(confPath); + return blade; + } + + /** + * @return Single case method returns Blade object + */ + public static final Blade $() { + return BladeHolder.$; + } + + /** + * @param confPath + * @return + */ + public static final Blade $(String confPath) { + Assert.notEmpty(confPath); + Blade blade = BladeHolder.$; + blade.environment.add(confPath); + return blade; + } + + /** + * Set Blade initialize + * + * @param isInit + * initialize + */ + public void init() { + if (!this.isInit) { + this.isInit = true; + } + } + + /** + * @return return route manager + */ + public Routers routers() { + return routers; + } + + /** + * @return return RouteBuilder + */ + public RouteBuilder routeBuilder() { + return routeBuilder; + } + + /** + * @return return ConfigLoader + */ + public ConfigLoader configLoader() { + return configLoader; + } + + /** + * @return return blade ioc container + */ + public Ioc ioc() { + return ioc; + } + + /** + * Setting a ioc container + * + * @param container + * ioc object + * @return return blade + */ + public Blade container(Ioc ioc) { + Assert.notNull(ioc); + this.ioc = ioc; + this.configLoader.setIoc(ioc); + return this; + } + + /** + * Setting Properties configuration file File path based on classpath + * + * @param confPath + * properties file name + * @return return blade + */ + public Blade loadAppConf(String confPath) { + Assert.notBlank(confPath); + environment.add(confPath); + return this; + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackage(String packageName) { + return this.addRoutePackages(packageName); + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackages(String... packages) { + Assert.notNull(packages); + applicationConfig.addRoutePackages(packages); + return this; + } + + /** + * + * @param basePackage + * @return + */ + public Blade basePackage(String basePackage) { + Assert.notBlank(basePackage); + applicationConfig.setBasePackage(basePackage); + applicationConfig.addIocPackages(basePackage + ".service.*"); + applicationConfig.addRoutePackages(basePackage + ".controller"); + applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); + return this; + } + + /** + * Setting the path where the interceptor, e.g:com.bladejava.interceptor + * + * @param packageName + * interceptor packagename + * @return return blade + */ + public Blade interceptor(String packageName) { + Assert.notBlank(packageName); + applicationConfig.setInterceptorPackage(packageName); + return this; + } + + /** + * Setting Ioc packages, e.g:com.bladejava.service + * + * @param packages + * All need to do into the package, can be introduced into a + * number of + * @return return blade + */ + public Blade ioc(String... packages) { + Assert.notNull(packages); + applicationConfig.addIocPackages(packages); + return this; + } + + /** + * Add a route + * + * @param path + * route path + * @param target + * Target object for routing + * @param method + * The method name of the route (at the same time, the HttpMethod + * is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade + */ + public Blade route(String path, Class clazz, String method) { + routers.route(path, clazz, method); + return this; + } + + /** + * Register a functional route + * + * @param path + * route url + * @param clazz + * route processing class + * @param method + * route processing method name + * @param httpMethod + * HttpMethod Type, GET/POST/... + * @return Blade return blade + */ + public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { + routers.route(path, clazz, method, httpMethod); + return this; + } + + /** + * Add a route list + * + * @param routes + * route list + * @return return blade + */ + public Blade routes(List routes) { + Assert.notEmpty(routes, "Routes not is empty!"); + routers.addRoutes(routes); + return this; + } + + /** + * Register a GET request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade get(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.GET); + return this; + } + + /** + * Register a POST request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade post(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.POST); + return this; + } + + /** + * Register a DELETE request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade delete(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.DELETE); + return this; + } + + /** + * Register a PUT request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade put(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.PUT); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade all(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade any(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Route Group. e.g blade.group('/users').get().post() + * + * @param g + * @return return blade + */ + public RouteGroup group(String prefix) { + Assert.notNull(prefix, "Route group prefix not is null"); + return new RouteGroup(this, prefix); + } + + /** + * Register a pre routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade before(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.BEFORE); + return this; + } + + /** + * Register a after routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade after(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.AFTER); + return this; + } + + /** + * Setting the frame static file folder + * + * @param resources + * List of directories to filter, e.g: "/public,/static,/images" + * @return return blade + */ + public Blade addResources(final String... resources) { + applicationConfig.addResources(resources); + return this; + } + + /** + * Dynamically set the global initialization class, the embedded Jetty boot + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Bootstrap bootstrap) { + Assert.notNull(bootstrap); + this.bootstrap = bootstrap; + return this; + } + + /** + * Dynamically set global initialization class + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Class bootstrap) { + Assert.notNull(bootstrap); + try { + Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); + ioc.addBean(Bootstrap.class.getName(), object); + this.bootstrap = object; + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + /** + * add interceptor + * + * @param interceptor interceptor class + * @return return blade obj + */ + public Blade addInterceptor(Class interceptor) { + routeBuilder.addInterceptor(interceptor); + return this; + } + + /** + * add config + * + * @param config config class + * @return return blade obj + */ + public Blade addConfig(Class config) { + configLoader.addConfig(config); + return this; + } + + /** + * Setting 404 view page + * + * @param view404 + * 404 view page + * @return return blade + */ + public Blade view404(final String view404) { + Assert.notBlank(view404); + applicationConfig.setView404(view404); + return this; + } + + /** + * Setting 500 view page + * + * @param view500 + * 500 view page + * @return return blade + */ + public Blade view500(final String view500) { + Assert.notBlank(view500); + applicationConfig.setView500(view500); + return this; + } + + /** + * Setting blade web root path + * + * @param webRoot + * web root path + * @return return blade + */ + public Blade webRoot(final String webRoot) { + Assert.notBlank(webRoot); + applicationConfig.setWebRoot(webRoot); + return this; + } + + /** + * Setting blade run mode + * + * @param isDev + * is dev mode + * @return return blade + */ + public Blade isDev(boolean isDev) { + applicationConfig.setDev(isDev); + return this; + } + + /** + * Setting jetty listen port + * + * @param port + * port, default is 9000 + * @return return blade + */ + public Blade listen(int port) { + this.port = port; + return this; + } + + /** + * start web server + */ + public void start() { + this.start(null); + } + + /** + * start web server + * @param applicationClass your app root package starter + */ + public void start(Class applicationClass) { + + this.loadAppConf(Const.APP_PROPERTIES); + + // init blade environment config + applicationConfig.setEnv(environment); + + if(null != applicationClass){ + applicationConfig.setApplicationClass(applicationClass); + if(StringKit.isBlank(applicationConfig.getBasePackage())){ + applicationConfig.setBasePackage(applicationClass.getPackage().getName()); + } + } + + try { + Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); + if(null == embedClazz){ + embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); + } + if(null != embedClazz){ + this.embedServer = (EmbedServer) embedClazz.newInstance(); + this.embedServer.startup(port, contextPath); + this.enableServer = true; + } else { + throw new EmbedServerException("Not found EmbedServer"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * @return Return EmbedServer + */ + public EmbedServer embedServer() { + return this.embedServer; + } + + /** + * @return Return blade config object + */ + public ApplicationConfig applicationConfig() { + return applicationConfig; + } + + /** + * @return Return blade config object + */ + public ApplicationConfig config() { + return applicationConfig; + } + + /** + * @return Return Blade Environment + */ + public Environment environment() { + return environment; + } + + /** + * @return Return blade encoding, default is UTF-8 + */ + public String encoding() { + return applicationConfig.getEncoding(); + } + + /** + * @return Return 404 view + */ + public String view404() { + return applicationConfig.getView404(); + } + + /** + * @return Return 500 view + */ + public String view500() { + return applicationConfig.getView500(); + } + + /** + * @return Return blade web root path + */ + public String webRoot() { + return applicationConfig.getWebRoot(); + } + + /** + * @return Return is dev mode + */ + public boolean isDev() { + return applicationConfig.isDev(); + } + + /** + * @return Return static resource directory + */ + public Set staticFolder() { + return applicationConfig.getStaticFolders(); + } + + /** + * @return Return bootstrap object + */ + public Bootstrap bootstrap() { + return this.bootstrap; + } + + /** + * return register plugin object + * + * @param plugin + * plugin class + * @return return blade + */ + public Blade plugin(Class plugin) { + Assert.notNull(plugin); + plugins.add(plugin); + return this; + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @return return blade + */ + public Blade routeConf(String basePackage) { + return routeConf(basePackage, "route.conf"); + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @param conf + * Configuration file path, the configuration file must be in + * classpath + * @return return blade + */ + public Blade routeConf(String basePackage, String conf) { + try { + Assert.notBlank(basePackage); + Assert.notBlank(conf); + InputStream ins = Blade.class.getResourceAsStream("/" + conf); + ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); + routesLoader.setBasePackage(basePackage); + List routes = routesLoader.load(); + routers.addRoutes(routes); + } catch (RouteException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return this; + } + + /** + * @return Return blade is initialize + */ + public boolean isInit() { + return isInit; + } + + public Blade enableServer(boolean enableServer) { + this.enableServer = enableServer; + return this; + } + + public boolean enableServer() { + return this.enableServer; + } + + public Set> plugins() { + return this.plugins; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java index 85993143b..3b7168443 100644 --- a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java +++ b/blade-core/src/main/java/com/blade/context/DynamicClassReader.java @@ -60,4 +60,4 @@ public static boolean isJarContext() { return isJarContext; } -} +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 1ef79e474..ad3c7803e 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -1,224 +1,224 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.annotation.Controller; -import com.blade.annotation.Intercept; -import com.blade.annotation.RestController; -import com.blade.comparator.OrderComparator; -import com.blade.config.BaseConfig; -import com.blade.context.DynamicClassReader; -import com.blade.ioc.annotation.Component; -import com.blade.ioc.annotation.Service; -import com.blade.kit.StringKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; -import com.blade.mvc.interceptor.Interceptor; -import com.blade.mvc.route.RouteBuilder; - -/** - * IOC container, used to initialize the IOC object - * - * @author biezhi - * @since 1.0 - */ -public class IocApplication { - - private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); - - private static List aopInterceptors = new ArrayList(); - - /** - * Class to read object, load class - */ - private ClassReader classReader = null; - private Blade blade; - private OrderComparator orderComparator; - - public IocApplication() { - this.blade = Blade.$(); - this.classReader = DynamicClassReader.getClassReader(); - this.orderComparator = new OrderComparator(); - } - - /** - * load config beans - * - * @return - * @throws Exception - */ - private List loadCondigs() throws Exception { - List configs = null; - String[] configPackages = blade.config().getConfigPackages(); - if (null != configPackages && configPackages.length > 0) { - configs = new ArrayList(10); - for (String packageName : configPackages) { - Set configClasses = classReader.getClassByAnnotation(packageName, Component.class, false); - if (null != configClasses) { - for (ClassInfo classInfo : configClasses) { - Class[] interfaces = classInfo.getClazz().getInterfaces(); - for (Class in : interfaces) { - if (in.equals(BaseConfig.class)) { - configs.add(classInfo); - } - } - if (classInfo.getClazz().getSuperclass().getName() - .equals("com.blade.aop.AbstractMethodInterceptor")) { - aopInterceptors.add(classInfo.newInstance()); - } - } - } - } - Collections.sort(configs, orderComparator); - } - return configs; - } - - private List loadServices() throws Exception { - List services = null; - String[] configPackages = blade.config().getIocPackages(); - if (null != configPackages && configPackages.length > 0) { - services = new ArrayList(20); - for (String packageName : configPackages) { - if (StringKit.isBlank(packageName)) { - continue; - } - // Recursive scan - boolean recursive = false; - if (packageName.endsWith(".*")) { - packageName = packageName.substring(0, packageName.length() - 2); - recursive = true; - } - - // Scan package all class - Set iocClasses = classReader.getClass(packageName, recursive); - for (ClassInfo classInfo : iocClasses) { - Class clazz = classInfo.getClazz(); - if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { - Component component = clazz.getAnnotation(Component.class); - Service service = clazz.getAnnotation(Service.class); - if (null != service || null != component) { - services.add(classInfo); - } - } - } - } - } - return services; - } - - private List loadControllers() { - List controllers = null; - String[] routePackages = blade.config().getRoutePackages(); - if (null != routePackages && routePackages.length > 0) { - controllers = new ArrayList(); - for (String packageName : routePackages) { - // Scan all Controoler - controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); - controllers.addAll(classReader.getClassByAnnotation(packageName, RestController.class, true)); - } - } - return controllers; - } - - private List loadInterceptors() { - List interceptors = null; - String interceptorPackage = blade.config().getInterceptorPackage(); - if (StringKit.isNotBlank(interceptorPackage)) { - interceptors = new ArrayList(10); - Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); - if (null != intes) { - for (ClassInfo classInfo : intes) { - if (null != classInfo.getClazz().getInterfaces() - && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)) { - interceptors.add(classInfo); - } - } - Collections.sort(interceptors, orderComparator); - } - } - return interceptors; - } - - public void initBeans() throws Exception { - List services = this.loadServices(); - List configs = this.loadCondigs(); - List controllers = this.loadControllers(); - // web - List inteceptors = this.loadInterceptors(); - - Ioc ioc = blade.ioc(); - - RouteBuilder routeBuilder = blade.routeBuilder(); - - // 1. init service - if (null != services) { - for (ClassInfo classInfo : services) { - ioc.addBean(classInfo.getClazz()); - } - } - - // 2. init configs - if (null != configs) { - for (ClassInfo classInfo : configs) { - Object bean = ioc.addBean(classInfo.getClazz()); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(blade.applicationConfig()); - } - } - - // 3. init controller - if (null != controllers) { - for (ClassInfo classInfo : controllers) { - ioc.addBean(classInfo.getClazz()); - routeBuilder.addRouter(classInfo.getClazz()); - } - } - - // 4. init interceptor - if (null != inteceptors) { - for (ClassInfo classInfo : inteceptors) { - ioc.addBean(classInfo.getClazz()); - routeBuilder.addInterceptor(classInfo.getClazz()); - } - } - - LOGGER.info("Add Object: {}", ioc.getBeans()); - - // injection - List beanDefines = ioc.getBeanDefines(); - if (null != beanDefines) { - for (BeanDefine beanDefine : beanDefines) { - IocKit.injection(ioc, beanDefine); - } - } - } - - public static List getAopInterceptors() { - return aopInterceptors; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.comparator.OrderComparator; +import com.blade.config.BaseConfig; +import com.blade.context.DynamicClassReader; +import com.blade.ioc.annotation.Component; +import com.blade.ioc.annotation.Service; +import com.blade.kit.StringKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.mvc.annotation.Controller; +import com.blade.mvc.annotation.Intercept; +import com.blade.mvc.annotation.RestController; +import com.blade.mvc.interceptor.Interceptor; +import com.blade.mvc.route.RouteBuilder; + +/** + * IOC container, used to initialize the IOC object + * + * @author biezhi + * @since 1.0 + */ +public class IocApplication { + + private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); + + private static List aopInterceptors = new ArrayList(); + + /** + * Class to read object, load class + */ + private ClassReader classReader = null; + private Blade blade; + private OrderComparator orderComparator; + + public IocApplication() { + this.blade = Blade.$(); + this.classReader = DynamicClassReader.getClassReader(); + this.orderComparator = new OrderComparator(); + } + + /** + * load config beans + * + * @return + * @throws Exception + */ + private List loadCondigs() throws Exception { + List configs = null; + String[] configPackages = blade.config().getConfigPackages(); + if (null != configPackages && configPackages.length > 0) { + configs = new ArrayList(10); + for (String packageName : configPackages) { + Set configClasses = classReader.getClassByAnnotation(packageName, Component.class, false); + if (null != configClasses) { + for (ClassInfo classInfo : configClasses) { + Class[] interfaces = classInfo.getClazz().getInterfaces(); + for (Class in : interfaces) { + if (in.equals(BaseConfig.class)) { + configs.add(classInfo); + } + } + if (classInfo.getClazz().getSuperclass().getName() + .equals("com.blade.aop.AbstractMethodInterceptor")) { + aopInterceptors.add(classInfo.newInstance()); + } + } + } + } + Collections.sort(configs, orderComparator); + } + return configs; + } + + private List loadServices() throws Exception { + List services = null; + String[] configPackages = blade.config().getIocPackages(); + if (null != configPackages && configPackages.length > 0) { + services = new ArrayList(20); + for (String packageName : configPackages) { + if (StringKit.isBlank(packageName)) { + continue; + } + // Recursive scan + boolean recursive = false; + if (packageName.endsWith(".*")) { + packageName = packageName.substring(0, packageName.length() - 2); + recursive = true; + } + + // Scan package all class + Set iocClasses = classReader.getClass(packageName, recursive); + for (ClassInfo classInfo : iocClasses) { + Class clazz = classInfo.getClazz(); + if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { + Component component = clazz.getAnnotation(Component.class); + Service service = clazz.getAnnotation(Service.class); + if (null != service || null != component) { + services.add(classInfo); + } + } + } + } + } + return services; + } + + private List loadControllers() { + List controllers = null; + String[] routePackages = blade.config().getRoutePackages(); + if (null != routePackages && routePackages.length > 0) { + controllers = new ArrayList(); + for (String packageName : routePackages) { + // Scan all Controoler + controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); + controllers.addAll(classReader.getClassByAnnotation(packageName, RestController.class, true)); + } + } + return controllers; + } + + private List loadInterceptors() { + List interceptors = null; + String interceptorPackage = blade.config().getInterceptorPackage(); + if (StringKit.isNotBlank(interceptorPackage)) { + interceptors = new ArrayList(10); + Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); + if (null != intes) { + for (ClassInfo classInfo : intes) { + if (null != classInfo.getClazz().getInterfaces() + && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)) { + interceptors.add(classInfo); + } + } + Collections.sort(interceptors, orderComparator); + } + } + return interceptors; + } + + public void initBeans() throws Exception { + List services = this.loadServices(); + List configs = this.loadCondigs(); + List controllers = this.loadControllers(); + // web + List inteceptors = this.loadInterceptors(); + + Ioc ioc = blade.ioc(); + + RouteBuilder routeBuilder = blade.routeBuilder(); + + // 1. init service + if (null != services) { + for (ClassInfo classInfo : services) { + ioc.addBean(classInfo.getClazz()); + } + } + + // 2. init configs + if (null != configs) { + for (ClassInfo classInfo : configs) { + Object bean = ioc.addBean(classInfo.getClazz()); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(blade.applicationConfig()); + } + } + + // 3. init controller + if (null != controllers) { + for (ClassInfo classInfo : controllers) { + ioc.addBean(classInfo.getClazz()); + routeBuilder.addRouter(classInfo.getClazz()); + } + } + + // 4. init interceptor + if (null != inteceptors) { + for (ClassInfo classInfo : inteceptors) { + ioc.addBean(classInfo.getClazz()); + routeBuilder.addInterceptor(classInfo.getClazz()); + } + } + + LOGGER.info("Add Object: {}", ioc.getBeans()); + + // injection + List beanDefines = ioc.getBeanDefines(); + if (null != beanDefines) { + for (BeanDefine beanDefine : beanDefines) { + IocKit.injection(ioc, beanDefine); + } + } + } + + public static List getAopInterceptors() { + return aopInterceptors; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/Controller.java b/blade-core/src/main/java/com/blade/mvc/annotation/Controller.java similarity index 97% rename from blade-core/src/main/java/com/blade/annotation/Controller.java rename to blade-core/src/main/java/com/blade/mvc/annotation/Controller.java index 92b76f8ae..a66580bbb 100644 --- a/blade-core/src/main/java/com/blade/annotation/Controller.java +++ b/blade-core/src/main/java/com/blade/mvc/annotation/Controller.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.mvc.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/annotation/Intercept.java b/blade-core/src/main/java/com/blade/mvc/annotation/Intercept.java similarity index 94% rename from blade-core/src/main/java/com/blade/annotation/Intercept.java rename to blade-core/src/main/java/com/blade/mvc/annotation/Intercept.java index 6edf2b221..52bdeae56 100644 --- a/blade-core/src/main/java/com/blade/annotation/Intercept.java +++ b/blade-core/src/main/java/com/blade/mvc/annotation/Intercept.java @@ -1,41 +1,41 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Interceptor notes, written in the class - * e.g: - *
- * {@link Intercept}
- * public class BaseInterceptor {...}
- * 
- * @author biezhi - * @since 1.5 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Intercept{ - - String value() default "/.*"; - - int sort() default 0; +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Interceptor notes, written in the class + * e.g: + *
+ * {@link Intercept}
+ * public class BaseInterceptor {...}
+ * 
+ * @author biezhi + * @since 1.5 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Intercept{ + + String value() default "/.*"; + + int sort() default 0; } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/annotation/JSON.java b/blade-core/src/main/java/com/blade/mvc/annotation/JSON.java similarity index 96% rename from blade-core/src/main/java/com/blade/annotation/JSON.java rename to blade-core/src/main/java/com/blade/mvc/annotation/JSON.java index f88895ed7..6e171e242 100644 --- a/blade-core/src/main/java/com/blade/annotation/JSON.java +++ b/blade-core/src/main/java/com/blade/mvc/annotation/JSON.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.mvc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/annotation/PathVariable.java b/blade-core/src/main/java/com/blade/mvc/annotation/PathVariable.java similarity index 97% rename from blade-core/src/main/java/com/blade/annotation/PathVariable.java rename to blade-core/src/main/java/com/blade/mvc/annotation/PathVariable.java index 4cef70d77..15d0a549e 100644 --- a/blade-core/src/main/java/com/blade/annotation/PathVariable.java +++ b/blade-core/src/main/java/com/blade/mvc/annotation/PathVariable.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.mvc.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/blade-core/src/main/java/com/blade/annotation/RequestParam.java b/blade-core/src/main/java/com/blade/mvc/annotation/RequestParam.java similarity index 97% rename from blade-core/src/main/java/com/blade/annotation/RequestParam.java rename to blade-core/src/main/java/com/blade/mvc/annotation/RequestParam.java index 4d34a3c85..7e1a3eba7 100644 --- a/blade-core/src/main/java/com/blade/annotation/RequestParam.java +++ b/blade-core/src/main/java/com/blade/mvc/annotation/RequestParam.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.mvc.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/blade-core/src/main/java/com/blade/annotation/RestController.java b/blade-core/src/main/java/com/blade/mvc/annotation/RestController.java similarity index 97% rename from blade-core/src/main/java/com/blade/annotation/RestController.java rename to blade-core/src/main/java/com/blade/mvc/annotation/RestController.java index ef6bd479c..9c445ab1d 100644 --- a/blade-core/src/main/java/com/blade/annotation/RestController.java +++ b/blade-core/src/main/java/com/blade/mvc/annotation/RestController.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.mvc.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/annotation/Route.java b/blade-core/src/main/java/com/blade/mvc/annotation/Route.java similarity index 98% rename from blade-core/src/main/java/com/blade/annotation/Route.java rename to blade-core/src/main/java/com/blade/mvc/annotation/Route.java index ef0eab3f4..b0f8eb1ee 100644 --- a/blade-core/src/main/java/com/blade/annotation/Route.java +++ b/blade-core/src/main/java/com/blade/mvc/annotation/Route.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.annotation; +package com.blade.mvc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java index 032319eb5..e850f41ba 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java @@ -22,16 +22,16 @@ import org.slf4j.LoggerFactory; import com.blade.Blade; -import com.blade.annotation.Controller; -import com.blade.annotation.Intercept; -import com.blade.annotation.RestController; -import com.blade.annotation.Route; import com.blade.context.DynamicClassReader; import com.blade.kit.CollectionKit; import com.blade.kit.StringKit; import com.blade.kit.reflect.ReflectKit; import com.blade.kit.resource.ClassInfo; import com.blade.kit.resource.ClassReader; +import com.blade.mvc.annotation.Controller; +import com.blade.mvc.annotation.Intercept; +import com.blade.mvc.annotation.RestController; +import com.blade.mvc.annotation.Route; import com.blade.mvc.http.HttpMethod; import com.blade.mvc.http.Request; import com.blade.mvc.http.Response; diff --git a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java index f2c586b87..7ab0a5cc2 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java @@ -18,12 +18,12 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import com.blade.annotation.PathVariable; -import com.blade.annotation.RequestParam; import com.blade.exception.BladeException; import com.blade.exception.NotFoundException; import com.blade.kit.AsmKit; import com.blade.kit.StringKit; +import com.blade.mvc.annotation.PathVariable; +import com.blade.mvc.annotation.RequestParam; import com.blade.mvc.http.Request; import com.blade.mvc.http.Response; import com.blade.mvc.multipart.FileItem; @@ -75,12 +75,11 @@ public static Object[] getArgs(Request request, Response response, Method action if (StringKit.isBlank(paramName)) { paramName = paramaterNames[i]; val = request.query(paramName); - } else { - if (StringKit.isBlank(val)) { - throw new NotFoundException("request param [" + paramName + "] is null"); - } } - args[i] = getRequestParam(argType, val, requestParam.defaultValue()); + if (StringKit.isBlank(val)) { + val = requestParam.defaultValue(); + } + args[i] = getRequestParam(argType, val); continue; } @@ -88,16 +87,14 @@ public static Object[] getArgs(Request request, Response response, Method action PathVariable pathVariable = (PathVariable) annotation; String paramName = pathVariable.value(); String val = request.param(paramName); - if (StringKit.isBlank(paramName)) { paramName = paramaterNames[i]; val = request.param(paramName); - } else { - if (StringKit.isBlank(val)) { - throw new NotFoundException("path param [" + paramName + "] is null"); - } } - args[i] = getRequestParam(argType, val, null); + if (StringKit.isBlank(val)) { + throw new NotFoundException("path param [" + paramName + "] is null"); + } + args[i] = getRequestParam(argType, val); continue; } } @@ -108,51 +105,25 @@ public static Object[] getArgs(Request request, Response response, Method action } } - private static Object getRequestParam(Class parameterType, String val, String defaultValue) { + private static Object getRequestParam(Class parameterType, String val) { Object result = null; if (parameterType.equals(String.class)) { - if (StringKit.isNotBlank(val)) { - result = val; - } else { - if (null != defaultValue) { - result = defaultValue; - } - } + result = val; } else if (parameterType.equals(Integer.class)) { - if (StringKit.isNotBlank(val)) { - result = Integer.parseInt(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Integer.parseInt(defaultValue); - } - } + result = Integer.parseInt(val); } else if (parameterType.equals(int.class)) { - if (StringKit.isNotBlank(val)) { - result = Integer.parseInt(val); + if("".equals(val)){ + result = 0; } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Integer.parseInt(defaultValue); - } else { - result = 0; - } + result = Integer.parseInt(val); } } else if (parameterType.equals(Long.class)) { - if (StringKit.isNotBlank(val)) { - result = Long.parseLong(val); - } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Long.parseLong(defaultValue); - } - } + result = Long.parseLong(val); } else if (parameterType.equals(long.class)) { - if (StringKit.isNotBlank(val)) { - result = Long.parseLong(val); + if("".equals(val)){ + result = 0L; } else { - if (StringKit.isNotBlank(defaultValue)) { - result = Long.parseLong(defaultValue); - } else { - result = 0L; - } + result = Integer.parseInt(val); } } return result; diff --git a/blade-core/src/main/java/com/blade/mvc/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/mvc/view/handle/RouteViewHandler.java index 3b5903f4f..7eef5e5c3 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/view/handle/RouteViewHandler.java @@ -1,103 +1,103 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.handle; - -import java.lang.reflect.Method; - -import com.blade.annotation.JSON; -import com.blade.annotation.RestController; -import com.blade.ioc.Ioc; -import com.blade.kit.reflect.ReflectKit; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.route.Route; -import com.blade.mvc.view.ModelAndView; -import com.blade.mvc.view.ViewSettings; - -public class RouteViewHandler { - - private Ioc ioc; - private ViewSettings viewSettings; - public RouteViewHandler(Ioc ioc) { - this.ioc = ioc; - this.viewSettings = ViewSettings.$(); - } - - public void handle(Request request, Response response, Route route) throws Exception { - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - - int len = actionMethod.getParameterTypes().length; - Object returnParam = null; - if (len > 0) { - Object[] args = MethodArgument.getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if (null != returnParam) { - Class returnType = returnParam.getClass(); - RestController restController = target.getClass().getAnnotation(RestController.class); - JSON json = actionMethod.getAnnotation(JSON.class); - if(null != restController || null != json){ - response.json(viewSettings.toJSONString(returnParam)); - } else{ - if (returnType == String.class) { - response.render(returnParam.toString()); - } else if (returnType == ModelAndView.class) { - ModelAndView modelAndView = (ModelAndView) returnParam; - response.render(modelAndView); - } - } - } - } - - public boolean intercept(Request request, Response response, Route route) throws Exception { - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - - if (null == target) { - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - - // execute - int len = actionMethod.getParameterTypes().length; - actionMethod.setAccessible(true); - try { - Object returnParam = null; - if (len > 0) { - Object[] args = MethodArgument.getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if (null != returnParam) { - Class returnType = returnParam.getClass(); - if (returnType == Boolean.class || returnType == boolean.class) { - return (Boolean) returnParam; - } - } - return true; - } catch (Exception e) { - throw e; - } - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.handle; + +import java.lang.reflect.Method; + +import com.blade.ioc.Ioc; +import com.blade.kit.reflect.ReflectKit; +import com.blade.mvc.annotation.JSON; +import com.blade.mvc.annotation.RestController; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.route.Route; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; + +public class RouteViewHandler { + + private Ioc ioc; + private ViewSettings viewSettings; + public RouteViewHandler(Ioc ioc) { + this.ioc = ioc; + this.viewSettings = ViewSettings.$(); + } + + public void handle(Request request, Response response, Route route) throws Exception { + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + int len = actionMethod.getParameterTypes().length; + Object returnParam = null; + if (len > 0) { + Object[] args = MethodArgument.getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if (null != returnParam) { + Class returnType = returnParam.getClass(); + RestController restController = target.getClass().getAnnotation(RestController.class); + JSON json = actionMethod.getAnnotation(JSON.class); + if(null != restController || null != json){ + response.json(viewSettings.toJSONString(returnParam)); + } else{ + if (returnType == String.class) { + response.render(returnParam.toString()); + } else if (returnType == ModelAndView.class) { + ModelAndView modelAndView = (ModelAndView) returnParam; + response.render(modelAndView); + } + } + } + } + + public boolean intercept(Request request, Response response, Route route) throws Exception { + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + if (null == target) { + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + + // execute + int len = actionMethod.getParameterTypes().length; + actionMethod.setAccessible(true); + try { + Object returnParam = null; + if (len > 0) { + Object[] args = MethodArgument.getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if (null != returnParam) { + Class returnType = returnParam.getClass(); + if (returnType == Boolean.class || returnType == boolean.class) { + return (Boolean) returnParam; + } + } + return true; + } catch (Exception e) { + throw e; + } + } + +} From def43db289986cb2724c9137ae51a64ac7f226d1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 4 Sep 2016 14:56:58 +0800 Subject: [PATCH 495/545] =?UTF-8?q?=E2=9C=84=20move=20view=20404,500=20to?= =?UTF-8?q?=20ViewSettings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/Blade.java | 40 ---- .../com/blade/config/ApplicationConfig.java | 35 +--- .../main/java/com/blade/kit/DispatchKit.java | 5 +- .../java/com/blade/mvc/DispatcherHandler.java | 3 +- .../java/com/blade/mvc/view/ViewSettings.java | 194 ++++++++++-------- 5 files changed, 120 insertions(+), 157 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 733d32001..dae594386 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -511,32 +511,6 @@ public Blade addConfig(Class config) { return this; } - /** - * Setting 404 view page - * - * @param view404 - * 404 view page - * @return return blade - */ - public Blade view404(final String view404) { - Assert.notBlank(view404); - applicationConfig.setView404(view404); - return this; - } - - /** - * Setting 500 view page - * - * @param view500 - * 500 view page - * @return return blade - */ - public Blade view500(final String view500) { - Assert.notBlank(view500); - applicationConfig.setView500(view500); - return this; - } - /** * Setting blade web root path * @@ -651,20 +625,6 @@ public String encoding() { return applicationConfig.getEncoding(); } - /** - * @return Return 404 view - */ - public String view404() { - return applicationConfig.getView404(); - } - - /** - * @return Return 500 view - */ - public String view500() { - return applicationConfig.getView500(); - } - /** * @return Return blade web root path */ diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 499bd1935..2ecd39084 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -26,6 +26,7 @@ import com.blade.kit.Assert; import com.blade.kit.Environment; import com.blade.kit.StringKit; +import com.blade.mvc.view.ViewSettings; /** * Blade Application Config Class @@ -61,13 +62,7 @@ public class ApplicationConfig { // web root path private String webRoot = ""; - - // 404 view page - private String view404 = "404.html"; - // 500 view page - private String view500 = "500.html"; - // Is dev mode private boolean isDev = true; @@ -82,12 +77,14 @@ public ApplicationConfig() { public void setEnv(Environment environment) { if (null != environment && !isInit) { this.isDev = environment.getBoolean("app.dev", true); - this.encoding = environment.getString("http.encoding", "UTF-8"); + this.addIocPackages(environment.getString("app.ioc")); - this.view500 = environment.getString("app.view.500"); - this.view404 = environment.getString("app.view.404"); - - String statics = environment.getString("app.statics"); + + ViewSettings.$().setView500(environment.getString("mvc.view.500")); + ViewSettings.$().setView404(environment.getString("mvc.view.404")); + this.encoding = environment.getString("mvc.http.encoding", "UTF-8"); + String statics = environment.getString("mvc.statics"); + String basePackage = environment.getString("app.base-package"); Integer port = environment.getInt("server.port"); @@ -171,22 +168,6 @@ public void addResources(String... resources) { staticFolders.addAll(Arrays.asList(resources)); } - public String getView404() { - return view404; - } - - public void setView404(String view404) { - this.view404 = view404; - } - - public String getView500() { - return view500; - } - - public void setView500(String view500) { - this.view500 = view500; - } - public String getWebRoot() { return webRoot; } diff --git a/blade-core/src/main/java/com/blade/kit/DispatchKit.java b/blade-core/src/main/java/com/blade/kit/DispatchKit.java index 7aa3dfa91..be243c6bc 100644 --- a/blade-core/src/main/java/com/blade/kit/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/kit/DispatchKit.java @@ -28,6 +28,7 @@ import com.blade.kit.StringKit; import com.blade.mvc.http.HttpException; import com.blade.mvc.http.Response; +import com.blade.mvc.view.ViewSettings; import static com.blade.Blade.$; @@ -123,7 +124,7 @@ public static void printError(Throwable err, int code, Response response) { writer.println(END); } else { if (code == 404) { - String view404 = Blade.$().view404(); + String view404 = ViewSettings.$().getView404(); if (StringKit.isNotBlank(view404)) { response.render(view404); return; @@ -131,7 +132,7 @@ public static void printError(Throwable err, int code, Response response) { writer.write(err.getMessage()); } } else { - String view500 = Blade.$().view500(); + String view500 = ViewSettings.$().getView500(); if (StringKit.isNotBlank(view500)) { response.render(view500); return; diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index e67592af0..b10e6a6f1 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -43,6 +43,7 @@ import com.blade.mvc.route.RouteMatcher; import com.blade.mvc.route.Routers; import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; import com.blade.mvc.view.handle.RouteViewHandler; import com.blade.mvc.view.template.TemplateException; @@ -147,7 +148,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo * @throws TemplateException */ private void render404(Response response, String uri) throws Exception { - String view404 = blade.view404(); + String view404 = ViewSettings.$().getView404(); if(StringKit.isNotBlank(view404)){ ModelAndView modelAndView = new ModelAndView(view404); modelAndView.add("viewName", uri); diff --git a/blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java b/blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java index dd2b6c1b4..1bad311d1 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java +++ b/blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java @@ -1,87 +1,107 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.kit.Assert; -import com.blade.mvc.view.parser.DefaultJSONParser; -import com.blade.mvc.view.parser.JSONParser; -import com.blade.mvc.view.template.DefaultEngine; -import com.blade.mvc.view.template.TemplateEngine; - -/** - * ViewSettings - * - * @author biezhi - * @since 1.6.6 - */ -public final class ViewSettings { - - private static final Logger LOGGER = LoggerFactory.getLogger(ViewSettings.class); - - private JSONParser jsonParser = new DefaultJSONParser(); - private TemplateEngine templateEngine = new DefaultEngine(); - - private ViewSettings() { - } - - static final class ViewSettingsHolder { - private static final ViewSettings $ = new ViewSettings(); - } - - public static ViewSettings $() { - return ViewSettingsHolder.$; - } - - public ViewSettings JSONParser(JSONParser jsonParser) { - Assert.notNull(jsonParser); - LOGGER.debug("Switch JSONParser With [{}]", jsonParser); - this.jsonParser = jsonParser; - return this; - } - - public JSONParser JSONParser() { - return this.jsonParser; - } - - public String toJSONString(Object object) { - return jsonParser.toJSONSting(object); - } - - /** - * Setting Render Engin, Default is static file render - * - * @param templateEngine - * Render engine object - * @return return blade - */ - public ViewSettings templateEngine(TemplateEngine templateEngine) { - Assert.notNull(templateEngine); - LOGGER.debug("Switch TemplateEngine With [{}]", templateEngine); - this.templateEngine = templateEngine; - return this; - } - - /** - * @return Return Current TemplateEngine - */ - public TemplateEngine templateEngine() { - return this.templateEngine; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.mvc.view.parser.DefaultJSONParser; +import com.blade.mvc.view.parser.JSONParser; +import com.blade.mvc.view.template.DefaultEngine; +import com.blade.mvc.view.template.TemplateEngine; + +/** + * ViewSettings + * + * @author biezhi + * @since 1.6.6 + */ +public final class ViewSettings { + + private static final Logger LOGGER = LoggerFactory.getLogger(ViewSettings.class); + + private JSONParser jsonParser = new DefaultJSONParser(); + private TemplateEngine templateEngine = new DefaultEngine(); + private String view404 = "404.html"; + private String view500 = "500.html"; + + private ViewSettings() { + } + + static final class ViewSettingsHolder { + private static final ViewSettings $ = new ViewSettings(); + } + + public static ViewSettings $() { + return ViewSettingsHolder.$; + } + + public ViewSettings JSONParser(JSONParser jsonParser) { + Assert.notNull(jsonParser); + LOGGER.debug("Switch JSONParser With [{}]", jsonParser); + this.jsonParser = jsonParser; + return this; + } + + public JSONParser JSONParser() { + return this.jsonParser; + } + + public String toJSONString(Object object) { + return jsonParser.toJSONSting(object); + } + + /** + * Setting Render Engin, Default is static file render + * + * @param templateEngine + * Render engine object + * @return return blade + */ + public ViewSettings templateEngine(TemplateEngine templateEngine) { + Assert.notNull(templateEngine); + LOGGER.debug("Switch TemplateEngine With [{}]", templateEngine); + this.templateEngine = templateEngine; + return this; + } + + /** + * @return Return Current TemplateEngine + */ + public TemplateEngine templateEngine() { + return this.templateEngine; + } + + public String getView404() { + return view404; + } + + public ViewSettings setView404(String view404) { + this.view404 = view404; + return this; + } + + public String getView500() { + return view500; + } + + public ViewSettings setView500(String view500) { + this.view500 = view500; + return this; + } + +} From 7b4ac3f6f4a80dc0fd9b4124206f3381590746e1 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 5 Sep 2016 09:18:03 +0800 Subject: [PATCH 496/545] =?UTF-8?q?=E2=9C=84=20rename=20ApplicationWebCont?= =?UTF-8?q?ext=20to=20WebApplicationContext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/blade/config/ConfigLoader.java | 178 ++--- ...icClassReader.java => DynamicContext.java} | 124 ++-- ...ontext.java => WebApplicationContext.java} | 212 +++--- .../java/com/blade/ioc/IocApplication.java | 446 ++++++------ .../blade/ioc/loader/IocAnnotationLoader.java | 4 +- .../java/com/blade/mvc/DispatcherHandler.java | 410 +++++------ .../java/com/blade/mvc/DispatcherServlet.java | 324 ++++----- .../mvc/http/wrapper/ServletResponse.java | 680 +++++++++--------- .../com/blade/mvc/route/RouteBuilder.java | 492 ++++++------- .../mvc/view/template/DefaultEngine.java | 156 ++-- .../blade/mvc/view/template/JspEngine.java | 6 +- 11 files changed, 1516 insertions(+), 1516 deletions(-) rename blade-core/src/main/java/com/blade/context/{DynamicClassReader.java => DynamicContext.java} (91%) rename blade-core/src/main/java/com/blade/context/{ApplicationWebContext.java => WebApplicationContext.java} (83%) diff --git a/blade-core/src/main/java/com/blade/config/ConfigLoader.java b/blade-core/src/main/java/com/blade/config/ConfigLoader.java index e2c0b100b..f59e4c9d8 100644 --- a/blade-core/src/main/java/com/blade/config/ConfigLoader.java +++ b/blade-core/src/main/java/com/blade/config/ConfigLoader.java @@ -1,89 +1,89 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.lang.reflect.Modifier; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.context.DynamicClassReader; -import com.blade.exception.ConfigException; -import com.blade.ioc.Ioc; -import com.blade.ioc.annotation.Component; -import com.blade.kit.CollectionKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; - -/** - * ConfigLoader - * - * @author biezhi - * @since 1.6.6 - */ -public class ConfigLoader { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); - - private ClassReader classReader; - private Ioc ioc; - private ApplicationConfig applicationConfig; - - public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { - this.ioc = ioc; - this.classReader = DynamicClassReader.getClassReader(); - this.applicationConfig = applicationConfig; - } - - public void setIoc(Ioc ioc){ - this.ioc = ioc; - } - - @SuppressWarnings("unchecked") - public void loadConfig() { - String[] configPackages = Blade.$().config().getConfigPackages(); - if (null != configPackages && configPackages.length > 0) { - // Scan package all class - try { - for (String packageName : configPackages) { - Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); - if (CollectionKit.isNotEmpty(classes)) { - for (ClassInfo classInfo : classes) { - boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); - if(hasInterface){ - addConfig((Class) classInfo.getClazz()); - } - } - } - } - } catch (ConfigException e) { - LOGGER.error("load config error", e); - } - } - } - - public void addConfig(Class clazz) throws ConfigException { - if (!Modifier.isAbstract(clazz.getModifiers())) { - Object bean = ioc.addBean(clazz); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(applicationConfig); - } - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.lang.reflect.Modifier; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.context.DynamicContext; +import com.blade.exception.ConfigException; +import com.blade.ioc.Ioc; +import com.blade.ioc.annotation.Component; +import com.blade.kit.CollectionKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; + +/** + * ConfigLoader + * + * @author biezhi + * @since 1.6.6 + */ +public class ConfigLoader { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); + + private ClassReader classReader; + private Ioc ioc; + private ApplicationConfig applicationConfig; + + public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { + this.ioc = ioc; + this.classReader = DynamicContext.getClassReader(); + this.applicationConfig = applicationConfig; + } + + public void setIoc(Ioc ioc){ + this.ioc = ioc; + } + + @SuppressWarnings("unchecked") + public void loadConfig() { + String[] configPackages = Blade.$().config().getConfigPackages(); + if (null != configPackages && configPackages.length > 0) { + // Scan package all class + try { + for (String packageName : configPackages) { + Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); + if (CollectionKit.isNotEmpty(classes)) { + for (ClassInfo classInfo : classes) { + boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); + if(hasInterface){ + addConfig((Class) classInfo.getClazz()); + } + } + } + } + } catch (ConfigException e) { + LOGGER.error("load config error", e); + } + } + } + + public void addConfig(Class clazz) throws ConfigException { + if (!Modifier.isAbstract(clazz.getModifiers())) { + Object bean = ioc.addBean(clazz); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(applicationConfig); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java b/blade-core/src/main/java/com/blade/context/DynamicContext.java similarity index 91% rename from blade-core/src/main/java/com/blade/context/DynamicClassReader.java rename to blade-core/src/main/java/com/blade/context/DynamicContext.java index 3b7168443..71b856104 100644 --- a/blade-core/src/main/java/com/blade/context/DynamicClassReader.java +++ b/blade-core/src/main/java/com/blade/context/DynamicContext.java @@ -1,63 +1,63 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.kit.resource.ClassPathClassReader; -import com.blade.kit.resource.ClassReader; -import com.blade.kit.resource.JarReaderImpl; - -/** - * Get ClassReader by JAR or folder - * - * @author biezhi - * @since 1.6.6 - */ -public final class DynamicClassReader { - - private static final Logger LOGGER = LoggerFactory.getLogger(DynamicClassReader.class); - - private static ClassReader CLASS_READER = null; - - private static boolean isJarContext = false; - - private DynamicClassReader() { - } - - public static void init(){ - Class clazz = Blade.$().config().getApplicationClass(); - String rs = clazz.getResource("").toString(); - if(rs.indexOf(".jar") != -1){ - CLASS_READER = new JarReaderImpl(); - isJarContext = true; - LOGGER.debug("{}", CLASS_READER); - } else{ - CLASS_READER = new ClassPathClassReader(); - } - } - - public static ClassReader getClassReader(){ - return CLASS_READER; - } - - public static boolean isJarContext() { - return isJarContext; - } - +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.kit.resource.ClassPathClassReader; +import com.blade.kit.resource.ClassReader; +import com.blade.kit.resource.JarReaderImpl; + +/** + * Get ClassReader by JAR or folder + * + * @author biezhi + * @since 1.6.6 + */ +public final class DynamicContext { + + private static final Logger LOGGER = LoggerFactory.getLogger(DynamicContext.class); + + private static ClassReader CLASS_READER = null; + + private static boolean isJarContext = false; + + private DynamicContext() { + } + + public static void init(){ + Class clazz = Blade.$().config().getApplicationClass(); + String rs = clazz.getResource("").toString(); + if(rs.indexOf(".jar") != -1){ + CLASS_READER = new JarReaderImpl(); + isJarContext = true; + LOGGER.debug("{}", CLASS_READER); + } else{ + CLASS_READER = new ClassPathClassReader(); + } + } + + public static ClassReader getClassReader(){ + return CLASS_READER; + } + + public static boolean isJarContext() { + return isJarContext; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java b/blade-core/src/main/java/com/blade/context/WebApplicationContext.java similarity index 83% rename from blade-core/src/main/java/com/blade/context/ApplicationWebContext.java rename to blade-core/src/main/java/com/blade/context/WebApplicationContext.java index cafeb6460..981784dde 100644 --- a/blade-core/src/main/java/com/blade/context/ApplicationWebContext.java +++ b/blade-core/src/main/java/com/blade/context/WebApplicationContext.java @@ -1,107 +1,107 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.context; - -import javax.servlet.ServletContext; - -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.http.wrapper.Session; - -/** - * BladeWebContext - * - * @author biezhi - * @since 1.6.6 - */ -public class ApplicationWebContext { - - /** - * BladeWebContext object for the current thread - */ - private static ThreadLocal ctx = new ThreadLocal(); - - /** - * ServletContext Object that is created when the application is initialized - */ - private ServletContext context; - - /** - * Request - */ - private Request request; - - /** - * Response - */ - private Response response; - - private ApplicationWebContext(){} - - public static ApplicationWebContext me(){ - return ctx.get(); - } - - public static void init(ServletContext context) { - ApplicationWebContext bladeWebContext = new ApplicationWebContext(); - bladeWebContext.context = context; - ctx.set(bladeWebContext); - } - - public static void init(ServletContext context, Request request, Response response) { - ApplicationWebContext bladeWebContext = new ApplicationWebContext(); - bladeWebContext.context = context; - bladeWebContext.request = request; - bladeWebContext.response = response; - ctx.set(bladeWebContext); - } - - /** - * 移除当前线程的Request、Response对象 - */ - public static void remove(){ - ctx.remove(); - } - - public static Request request() { - return me().request; - } - - public static Response response() { - return me().response; - } - - public static Session session() { - return request().session(); - } - - public static ServletContext servletContext() { - return me().context; - } - - public ServletContext getContext() { - return context; - } - - public Request getRequest() { - return request; - } - - public Response getResponse() { - return response; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import javax.servlet.ServletContext; + +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.http.wrapper.Session; + +/** + * BladeWebContext + * + * @author biezhi + * @since 1.6.6 + */ +public class WebApplicationContext { + + /** + * BladeWebContext object for the current thread + */ + private static ThreadLocal ctx = new ThreadLocal(); + + /** + * ServletContext Object that is created when the application is initialized + */ + private ServletContext context; + + /** + * Request + */ + private Request request; + + /** + * Response + */ + private Response response; + + private WebApplicationContext(){} + + public static WebApplicationContext me(){ + return ctx.get(); + } + + public static void init(ServletContext context) { + WebApplicationContext bladeWebContext = new WebApplicationContext(); + bladeWebContext.context = context; + ctx.set(bladeWebContext); + } + + public static void init(ServletContext context, Request request, Response response) { + WebApplicationContext bladeWebContext = new WebApplicationContext(); + bladeWebContext.context = context; + bladeWebContext.request = request; + bladeWebContext.response = response; + ctx.set(bladeWebContext); + } + + /** + * 移除当前线程的Request、Response对象 + */ + public static void remove(){ + ctx.remove(); + } + + public static Request request() { + return me().request; + } + + public static Response response() { + return me().response; + } + + public static Session session() { + return request().session(); + } + + public static ServletContext servletContext() { + return me().context; + } + + public ServletContext getContext() { + return context; + } + + public Request getRequest() { + return request; + } + + public Response getResponse() { + return response; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index ad3c7803e..b44a88571 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -1,224 +1,224 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.comparator.OrderComparator; -import com.blade.config.BaseConfig; -import com.blade.context.DynamicClassReader; -import com.blade.ioc.annotation.Component; -import com.blade.ioc.annotation.Service; -import com.blade.kit.StringKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; -import com.blade.mvc.annotation.Controller; -import com.blade.mvc.annotation.Intercept; -import com.blade.mvc.annotation.RestController; -import com.blade.mvc.interceptor.Interceptor; -import com.blade.mvc.route.RouteBuilder; - -/** - * IOC container, used to initialize the IOC object - * - * @author biezhi - * @since 1.0 - */ -public class IocApplication { - - private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); - - private static List aopInterceptors = new ArrayList(); - - /** - * Class to read object, load class - */ - private ClassReader classReader = null; - private Blade blade; - private OrderComparator orderComparator; - - public IocApplication() { - this.blade = Blade.$(); - this.classReader = DynamicClassReader.getClassReader(); - this.orderComparator = new OrderComparator(); - } - - /** - * load config beans - * - * @return - * @throws Exception - */ - private List loadCondigs() throws Exception { - List configs = null; - String[] configPackages = blade.config().getConfigPackages(); - if (null != configPackages && configPackages.length > 0) { - configs = new ArrayList(10); - for (String packageName : configPackages) { - Set configClasses = classReader.getClassByAnnotation(packageName, Component.class, false); - if (null != configClasses) { - for (ClassInfo classInfo : configClasses) { - Class[] interfaces = classInfo.getClazz().getInterfaces(); - for (Class in : interfaces) { - if (in.equals(BaseConfig.class)) { - configs.add(classInfo); - } - } - if (classInfo.getClazz().getSuperclass().getName() - .equals("com.blade.aop.AbstractMethodInterceptor")) { - aopInterceptors.add(classInfo.newInstance()); - } - } - } - } - Collections.sort(configs, orderComparator); - } - return configs; - } - - private List loadServices() throws Exception { - List services = null; - String[] configPackages = blade.config().getIocPackages(); - if (null != configPackages && configPackages.length > 0) { - services = new ArrayList(20); - for (String packageName : configPackages) { - if (StringKit.isBlank(packageName)) { - continue; - } - // Recursive scan - boolean recursive = false; - if (packageName.endsWith(".*")) { - packageName = packageName.substring(0, packageName.length() - 2); - recursive = true; - } - - // Scan package all class - Set iocClasses = classReader.getClass(packageName, recursive); - for (ClassInfo classInfo : iocClasses) { - Class clazz = classInfo.getClazz(); - if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { - Component component = clazz.getAnnotation(Component.class); - Service service = clazz.getAnnotation(Service.class); - if (null != service || null != component) { - services.add(classInfo); - } - } - } - } - } - return services; - } - - private List loadControllers() { - List controllers = null; - String[] routePackages = blade.config().getRoutePackages(); - if (null != routePackages && routePackages.length > 0) { - controllers = new ArrayList(); - for (String packageName : routePackages) { - // Scan all Controoler - controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); - controllers.addAll(classReader.getClassByAnnotation(packageName, RestController.class, true)); - } - } - return controllers; - } - - private List loadInterceptors() { - List interceptors = null; - String interceptorPackage = blade.config().getInterceptorPackage(); - if (StringKit.isNotBlank(interceptorPackage)) { - interceptors = new ArrayList(10); - Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); - if (null != intes) { - for (ClassInfo classInfo : intes) { - if (null != classInfo.getClazz().getInterfaces() - && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)) { - interceptors.add(classInfo); - } - } - Collections.sort(interceptors, orderComparator); - } - } - return interceptors; - } - - public void initBeans() throws Exception { - List services = this.loadServices(); - List configs = this.loadCondigs(); - List controllers = this.loadControllers(); - // web - List inteceptors = this.loadInterceptors(); - - Ioc ioc = blade.ioc(); - - RouteBuilder routeBuilder = blade.routeBuilder(); - - // 1. init service - if (null != services) { - for (ClassInfo classInfo : services) { - ioc.addBean(classInfo.getClazz()); - } - } - - // 2. init configs - if (null != configs) { - for (ClassInfo classInfo : configs) { - Object bean = ioc.addBean(classInfo.getClazz()); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(blade.applicationConfig()); - } - } - - // 3. init controller - if (null != controllers) { - for (ClassInfo classInfo : controllers) { - ioc.addBean(classInfo.getClazz()); - routeBuilder.addRouter(classInfo.getClazz()); - } - } - - // 4. init interceptor - if (null != inteceptors) { - for (ClassInfo classInfo : inteceptors) { - ioc.addBean(classInfo.getClazz()); - routeBuilder.addInterceptor(classInfo.getClazz()); - } - } - - LOGGER.info("Add Object: {}", ioc.getBeans()); - - // injection - List beanDefines = ioc.getBeanDefines(); - if (null != beanDefines) { - for (BeanDefine beanDefine : beanDefines) { - IocKit.injection(ioc, beanDefine); - } - } - } - - public static List getAopInterceptors() { - return aopInterceptors; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.comparator.OrderComparator; +import com.blade.config.BaseConfig; +import com.blade.context.DynamicContext; +import com.blade.ioc.annotation.Component; +import com.blade.ioc.annotation.Service; +import com.blade.kit.StringKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.mvc.annotation.Controller; +import com.blade.mvc.annotation.Intercept; +import com.blade.mvc.annotation.RestController; +import com.blade.mvc.interceptor.Interceptor; +import com.blade.mvc.route.RouteBuilder; + +/** + * IOC container, used to initialize the IOC object + * + * @author biezhi + * @since 1.0 + */ +public class IocApplication { + + private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); + + private static List aopInterceptors = new ArrayList(); + + /** + * Class to read object, load class + */ + private ClassReader classReader = null; + private Blade blade; + private OrderComparator orderComparator; + + public IocApplication() { + this.blade = Blade.$(); + this.classReader = DynamicContext.getClassReader(); + this.orderComparator = new OrderComparator(); + } + + /** + * load config beans + * + * @return + * @throws Exception + */ + private List loadCondigs() throws Exception { + List configs = null; + String[] configPackages = blade.config().getConfigPackages(); + if (null != configPackages && configPackages.length > 0) { + configs = new ArrayList(10); + for (String packageName : configPackages) { + Set configClasses = classReader.getClassByAnnotation(packageName, Component.class, false); + if (null != configClasses) { + for (ClassInfo classInfo : configClasses) { + Class[] interfaces = classInfo.getClazz().getInterfaces(); + for (Class in : interfaces) { + if (in.equals(BaseConfig.class)) { + configs.add(classInfo); + } + } + if (classInfo.getClazz().getSuperclass().getName() + .equals("com.blade.aop.AbstractMethodInterceptor")) { + aopInterceptors.add(classInfo.newInstance()); + } + } + } + } + Collections.sort(configs, orderComparator); + } + return configs; + } + + private List loadServices() throws Exception { + List services = null; + String[] configPackages = blade.config().getIocPackages(); + if (null != configPackages && configPackages.length > 0) { + services = new ArrayList(20); + for (String packageName : configPackages) { + if (StringKit.isBlank(packageName)) { + continue; + } + // Recursive scan + boolean recursive = false; + if (packageName.endsWith(".*")) { + packageName = packageName.substring(0, packageName.length() - 2); + recursive = true; + } + + // Scan package all class + Set iocClasses = classReader.getClass(packageName, recursive); + for (ClassInfo classInfo : iocClasses) { + Class clazz = classInfo.getClazz(); + if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { + Component component = clazz.getAnnotation(Component.class); + Service service = clazz.getAnnotation(Service.class); + if (null != service || null != component) { + services.add(classInfo); + } + } + } + } + } + return services; + } + + private List loadControllers() { + List controllers = null; + String[] routePackages = blade.config().getRoutePackages(); + if (null != routePackages && routePackages.length > 0) { + controllers = new ArrayList(); + for (String packageName : routePackages) { + // Scan all Controoler + controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); + controllers.addAll(classReader.getClassByAnnotation(packageName, RestController.class, true)); + } + } + return controllers; + } + + private List loadInterceptors() { + List interceptors = null; + String interceptorPackage = blade.config().getInterceptorPackage(); + if (StringKit.isNotBlank(interceptorPackage)) { + interceptors = new ArrayList(10); + Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); + if (null != intes) { + for (ClassInfo classInfo : intes) { + if (null != classInfo.getClazz().getInterfaces() + && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)) { + interceptors.add(classInfo); + } + } + Collections.sort(interceptors, orderComparator); + } + } + return interceptors; + } + + public void initBeans() throws Exception { + List services = this.loadServices(); + List configs = this.loadCondigs(); + List controllers = this.loadControllers(); + // web + List inteceptors = this.loadInterceptors(); + + Ioc ioc = blade.ioc(); + + RouteBuilder routeBuilder = blade.routeBuilder(); + + // 1. init service + if (null != services) { + for (ClassInfo classInfo : services) { + ioc.addBean(classInfo.getClazz()); + } + } + + // 2. init configs + if (null != configs) { + for (ClassInfo classInfo : configs) { + Object bean = ioc.addBean(classInfo.getClazz()); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(blade.applicationConfig()); + } + } + + // 3. init controller + if (null != controllers) { + for (ClassInfo classInfo : controllers) { + ioc.addBean(classInfo.getClazz()); + routeBuilder.addRouter(classInfo.getClazz()); + } + } + + // 4. init interceptor + if (null != inteceptors) { + for (ClassInfo classInfo : inteceptors) { + ioc.addBean(classInfo.getClazz()); + routeBuilder.addInterceptor(classInfo.getClazz()); + } + } + + LOGGER.info("Add Object: {}", ioc.getBeans()); + + // injection + List beanDefines = ioc.getBeanDefines(); + if (null != beanDefines) { + for (BeanDefine beanDefine : beanDefines) { + IocKit.injection(ioc, beanDefine); + } + } + } + + public static List getAopInterceptors() { + return aopInterceptors; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java index 4a713976f..d51b53343 100644 --- a/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java +++ b/blade-core/src/main/java/com/blade/ioc/loader/IocAnnotationLoader.java @@ -21,7 +21,7 @@ import java.util.Collection; import java.util.List; -import com.blade.context.DynamicClassReader; +import com.blade.context.DynamicContext; import com.blade.ioc.SimpleIoc; import com.blade.ioc.annotation.Component; import com.blade.kit.CollectionKit; @@ -38,7 +38,7 @@ public final class IocAnnotationLoader implements IocLoader { private Collection classes; - private ClassReader classReader = DynamicClassReader.getClassReader(); + private ClassReader classReader = DynamicContext.getClassReader(); public IocAnnotationLoader(String... packageNames) { List> annotations = new ArrayList>(1); diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index b10e6a6f1..3668bacf8 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -1,206 +1,206 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; - -import java.io.IOException; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.context.ApplicationWebContext; -import com.blade.exception.BladeException; -import com.blade.ioc.Ioc; -import com.blade.kit.DispatchKit; -import com.blade.kit.StringKit; -import com.blade.mvc.http.HttpStatus; -import com.blade.mvc.http.Path; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.http.wrapper.ServletRequest; -import com.blade.mvc.http.wrapper.ServletResponse; -import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteHandler; -import com.blade.mvc.route.RouteMatcher; -import com.blade.mvc.route.Routers; -import com.blade.mvc.view.ModelAndView; -import com.blade.mvc.view.ViewSettings; -import com.blade.mvc.view.handle.RouteViewHandler; -import com.blade.mvc.view.template.TemplateException; - -/** - * Synchronous request processor - * - * @author biezhi - * @since 1.5 - */ -public class DispatcherHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); - - private Ioc ioc; - - private Blade blade; - - private ServletContext servletContext; - - private RouteMatcher routeMatcher; - - private StaticFileFilter staticFileFilter; - - private RouteViewHandler routeViewHandler; - - public DispatcherHandler(ServletContext servletContext, Routers routers) { - this.servletContext = servletContext; - this.blade = Blade.$(); - this.ioc = blade.ioc(); - this.routeMatcher = new RouteMatcher(routers); - this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); - this.routeViewHandler = new RouteViewHandler(this.ioc); - } - - public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ - - // http method, GET/POST ... - String method = httpRequest.getMethod(); - - // reuqest uri - String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - - // Create Response - Response response = new ServletResponse(httpResponse);; - - // If it is static, the resource is handed over to the filter - if(staticFileFilter.isStatic(uri)){ - LOGGER.debug("Request : {}\t{}", method, uri); - DispatchKit.printStatic(uri, httpRequest, response); - return; - } - - LOGGER.info("Request : {}\t{}", method, uri); - - try { - - Request request = new ServletRequest(httpRequest); - ApplicationWebContext.init(servletContext, request, response); - Route route = routeMatcher.getRoute(method, uri); - if (null != route) { - request.setRoute(route); - - // before inteceptor - List befores = routeMatcher.getBefore(uri); - boolean result = invokeInterceptor(request, response, befores); - if(result){ - // execute - this.routeHandle(request, response, route); - if(!request.isAbort()){ - // after inteceptor - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - } - } - } else { - // Not found - render404(response, uri); - } - return; - } catch (TemplateException e) { - LOGGER.error("Template error", e); - DispatchKit.printError(e, 500, response); - } catch (BladeException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - }catch (Exception e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } - return; - } - - /** - * 404 view render - * - * @param response response object - * @param uri 404 uri - * @throws IOException - * @throws TemplateException - */ - private void render404(Response response, String uri) throws Exception { - String view404 = ViewSettings.$().getView404(); - if(StringKit.isNotBlank(view404)){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", uri); - response.render( modelAndView ); - } else { - response.status(HttpStatus.NOT_FOUND); - response.html(String.format(Const.VIEW_NOTFOUND, uri)); - } - } - - /** - * Methods to perform the interceptor - * - * @param request request object - * @param response response object - * @param interceptors execute the interceptor list - * @return Return execute is ok - */ - private boolean invokeInterceptor(Request request, Response response, List interceptors) throws Exception { - for(Route route : interceptors){ - boolean flag = routeViewHandler.intercept(request, response, route); - if(!flag){ - return false; - } - } - return true; - } - - /** - * Actual routing method execution - * - * @param request request object - * @param response response object - * @param route route object - */ - private void routeHandle(Request request, Response response, Route route) throws Exception{ - Object target = route.getTarget(); - if(null == target){ - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - request.initPathParams(route.getPath()); - - // Init context - ApplicationWebContext.init(servletContext, request, response); - if(route.getTargetType() == RouteHandler.class){ - RouteHandler routeHandler = (RouteHandler) target; - routeHandler.handle(request, response); - } else { - routeViewHandler.handle(request, response, route); - } - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.context.WebApplicationContext; +import com.blade.exception.BladeException; +import com.blade.ioc.Ioc; +import com.blade.kit.DispatchKit; +import com.blade.kit.StringKit; +import com.blade.mvc.http.HttpStatus; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.http.wrapper.ServletRequest; +import com.blade.mvc.http.wrapper.ServletResponse; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteHandler; +import com.blade.mvc.route.RouteMatcher; +import com.blade.mvc.route.Routers; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; +import com.blade.mvc.view.handle.RouteViewHandler; +import com.blade.mvc.view.template.TemplateException; + +/** + * Synchronous request processor + * + * @author biezhi + * @since 1.5 + */ +public class DispatcherHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); + + private Ioc ioc; + + private Blade blade; + + private ServletContext servletContext; + + private RouteMatcher routeMatcher; + + private StaticFileFilter staticFileFilter; + + private RouteViewHandler routeViewHandler; + + public DispatcherHandler(ServletContext servletContext, Routers routers) { + this.servletContext = servletContext; + this.blade = Blade.$(); + this.ioc = blade.ioc(); + this.routeMatcher = new RouteMatcher(routers); + this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); + this.routeViewHandler = new RouteViewHandler(this.ioc); + } + + public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ + + // http method, GET/POST ... + String method = httpRequest.getMethod(); + + // reuqest uri + String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); + + // Create Response + Response response = new ServletResponse(httpResponse);; + + // If it is static, the resource is handed over to the filter + if(staticFileFilter.isStatic(uri)){ + LOGGER.debug("Request : {}\t{}", method, uri); + DispatchKit.printStatic(uri, httpRequest, response); + return; + } + + LOGGER.info("Request : {}\t{}", method, uri); + + try { + + Request request = new ServletRequest(httpRequest); + WebApplicationContext.init(servletContext, request, response); + Route route = routeMatcher.getRoute(method, uri); + if (null != route) { + request.setRoute(route); + + // before inteceptor + List befores = routeMatcher.getBefore(uri); + boolean result = invokeInterceptor(request, response, befores); + if(result){ + // execute + this.routeHandle(request, response, route); + if(!request.isAbort()){ + // after inteceptor + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + } + } + } else { + // Not found + render404(response, uri); + } + return; + } catch (TemplateException e) { + LOGGER.error("Template error", e); + DispatchKit.printError(e, 500, response); + } catch (BladeException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + }catch (Exception e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } + return; + } + + /** + * 404 view render + * + * @param response response object + * @param uri 404 uri + * @throws IOException + * @throws TemplateException + */ + private void render404(Response response, String uri) throws Exception { + String view404 = ViewSettings.$().getView404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(Const.VIEW_NOTFOUND, uri)); + } + } + + /** + * Methods to perform the interceptor + * + * @param request request object + * @param response response object + * @param interceptors execute the interceptor list + * @return Return execute is ok + */ + private boolean invokeInterceptor(Request request, Response response, List interceptors) throws Exception { + for(Route route : interceptors){ + boolean flag = routeViewHandler.intercept(request, response, route); + if(!flag){ + return false; + } + } + return true; + } + + /** + * Actual routing method execution + * + * @param request request object + * @param response response object + * @param route route object + */ + private void routeHandle(Request request, Response response, Route route) throws Exception{ + Object target = route.getTarget(); + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + request.initPathParams(route.getPath()); + + // Init context + WebApplicationContext.init(servletContext, request, response); + if(route.getTargetType() == RouteHandler.class){ + RouteHandler routeHandler = (RouteHandler) target; + routeHandler.handle(request, response); + } else { + routeViewHandler.handle(request, response, route); + } + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java index ad2ad98ad..f9a7e219a 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java @@ -1,162 +1,162 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; - -import java.io.IOException; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Bootstrap; -import com.blade.banner.BannerStarter; -import com.blade.context.ApplicationContext; -import com.blade.context.ApplicationWebContext; -import com.blade.context.DynamicClassReader; -import com.blade.embedd.EmbedServer; -import com.blade.kit.DispatchKit; -import com.blade.kit.StringKit; -import com.blade.kit.SystemKit; - -/** - * Blade Core DispatcherServlet - * - * @author biezhi - * @since 1.5 - */ -public class DispatcherServlet extends HttpServlet { - - private static final long serialVersionUID = -2607425162473178733L; - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); - - private Blade blade = Blade.$(); - - private Bootstrap bootstrap; - - private ServletContext servletContext; - - private DispatcherHandler dispatcherHandler; - - public DispatcherServlet() { - } - - public DispatcherServlet(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - blade.init(); - } - - @Override - public void init(ServletConfig config) throws ServletException { - servletContext = config.getServletContext(); - if(!blade.isInit()){ - - LOGGER.info("jdk.version\t=> {}", SystemKit.getJavaInfo().getVersion()); - LOGGER.info("user.dir\t\t=> {}", System.getProperty("user.dir")); - LOGGER.info("java.io.tmpdir\t=> {}", System.getProperty("java.io.tmpdir")); - LOGGER.info("user.timezone\t=> {}", System.getProperty("user.timezone")); - LOGGER.info("file.encodin\t=> {}", System.getProperty("file.encoding")); - - long initStart = System.currentTimeMillis(); - - String webRoot = DispatchKit.getWebRoot(servletContext); - - blade.webRoot(webRoot); - EmbedServer embedServer = blade.embedServer(); - if(null != embedServer){ - embedServer.setWebRoot(webRoot); - } - - LOGGER.info("blade.webroot\t=> {}", webRoot); - - DynamicClassReader.init(); - - ApplicationWebContext.init(servletContext); - - this.bootstrap = blade.bootstrap(); - - if(null == bootstrap){ - String bootStrapClassName = config.getInitParameter("bootstrap"); - if(StringKit.isNotBlank(bootStrapClassName)){ - this.bootstrap = getBootstrap(bootStrapClassName); - } else { - this.bootstrap = new Bootstrap() { - @Override - public void init(Blade blade) { - } - }; - } - blade.app(this.bootstrap); - } - - ApplicationContext.init(blade); - - LOGGER.info("blade.isDev = {}", blade.isDev()); - - dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); - - BannerStarter.printStart(); - - String appName = blade.environment().getString("app.name", "Blade"); - - LOGGER.info("{} initialize successfully, Time elapsed: {} ms.", appName, System.currentTimeMillis() - initStart); - } - } - - @Override - protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { - httpRequest.setCharacterEncoding(blade.encoding()); - httpResponse.setCharacterEncoding(blade.encoding()); - dispatcherHandler.handle(httpRequest, httpResponse); - } - - @Override - public void destroy() { - super.destroy(); - } - - /** - * Get global initialization object, the application of the initialization - * - * @param botstrapClassName botstrap class name - * @return return bootstrap object - * @throws ServletException - */ - @SuppressWarnings("unchecked") - private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { - Bootstrap bootstrapClass = null; - try { - if(null != botstrapClassName){ - Class applicationClass = (Class) Class.forName(botstrapClassName); - if(null != applicationClass){ - bootstrapClass = applicationClass.newInstance(); - } - } else { - throw new ServletException("bootstrapClass is null !"); - } - } catch (Exception e) { - throw new ServletException(e); - } - return bootstrapClass; - } -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Bootstrap; +import com.blade.banner.BannerStarter; +import com.blade.context.ApplicationContext; +import com.blade.context.WebApplicationContext; +import com.blade.context.DynamicContext; +import com.blade.embedd.EmbedServer; +import com.blade.kit.DispatchKit; +import com.blade.kit.StringKit; +import com.blade.kit.SystemKit; + +/** + * Blade Core DispatcherServlet + * + * @author biezhi + * @since 1.5 + */ +public class DispatcherServlet extends HttpServlet { + + private static final long serialVersionUID = -2607425162473178733L; + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); + + private Blade blade = Blade.$(); + + private Bootstrap bootstrap; + + private ServletContext servletContext; + + private DispatcherHandler dispatcherHandler; + + public DispatcherServlet() { + } + + public DispatcherServlet(Bootstrap bootstrap) { + this.bootstrap = bootstrap; + blade.init(); + } + + @Override + public void init(ServletConfig config) throws ServletException { + servletContext = config.getServletContext(); + if(!blade.isInit()){ + + LOGGER.info("jdk.version\t=> {}", SystemKit.getJavaInfo().getVersion()); + LOGGER.info("user.dir\t\t=> {}", System.getProperty("user.dir")); + LOGGER.info("java.io.tmpdir\t=> {}", System.getProperty("java.io.tmpdir")); + LOGGER.info("user.timezone\t=> {}", System.getProperty("user.timezone")); + LOGGER.info("file.encodin\t=> {}", System.getProperty("file.encoding")); + + long initStart = System.currentTimeMillis(); + + String webRoot = DispatchKit.getWebRoot(servletContext); + + blade.webRoot(webRoot); + EmbedServer embedServer = blade.embedServer(); + if(null != embedServer){ + embedServer.setWebRoot(webRoot); + } + + LOGGER.info("blade.webroot\t=> {}", webRoot); + + DynamicContext.init(); + + WebApplicationContext.init(servletContext); + + this.bootstrap = blade.bootstrap(); + + if(null == bootstrap){ + String bootStrapClassName = config.getInitParameter("bootstrap"); + if(StringKit.isNotBlank(bootStrapClassName)){ + this.bootstrap = getBootstrap(bootStrapClassName); + } else { + this.bootstrap = new Bootstrap() { + @Override + public void init(Blade blade) { + } + }; + } + blade.app(this.bootstrap); + } + + ApplicationContext.init(blade); + + LOGGER.info("blade.isDev = {}", blade.isDev()); + + dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); + + BannerStarter.printStart(); + + String appName = blade.environment().getString("app.name", "Blade"); + + LOGGER.info("{} initialize successfully, Time elapsed: {} ms.", appName, System.currentTimeMillis() - initStart); + } + } + + @Override + protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { + httpRequest.setCharacterEncoding(blade.encoding()); + httpResponse.setCharacterEncoding(blade.encoding()); + dispatcherHandler.handle(httpRequest, httpResponse); + } + + @Override + public void destroy() { + super.destroy(); + } + + /** + * Get global initialization object, the application of the initialization + * + * @param botstrapClassName botstrap class name + * @return return bootstrap object + * @throws ServletException + */ + @SuppressWarnings("unchecked") + private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { + Bootstrap bootstrapClass = null; + try { + if(null != botstrapClassName){ + Class applicationClass = (Class) Class.forName(botstrapClassName); + if(null != applicationClass){ + bootstrapClass = applicationClass.newInstance(); + } + } else { + throw new ServletException("bootstrapClass is null !"); + } + } catch (Exception e) { + throw new ServletException(e); + } + return bootstrapClass; + } +} diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java index 393287cff..817fc34f5 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java @@ -1,340 +1,340 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http.wrapper; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.context.ApplicationWebContext; -import com.blade.kit.Assert; -import com.blade.kit.DispatchKit; -import com.blade.mvc.http.HttpStatus; -import com.blade.mvc.http.Path; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.view.ModelAndView; -import com.blade.mvc.view.ViewSettings; -import com.blade.mvc.view.parser.JSONParser; -import com.blade.mvc.view.template.TemplateEngine; -import com.blade.mvc.view.template.TemplateException; - -/** - * ServletResponse - * - * @author biezhi - * @since 1.5 - */ -public class ServletResponse implements Response { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServletResponse.class); - - private HttpServletResponse response; - - private boolean written = false; - - private ViewSettings viewSettings; - - private TemplateEngine templateEngine; - - private JSONParser jsonParser; - - public ServletResponse(HttpServletResponse response) { - this.response = response; - this.viewSettings = ViewSettings.$(); - this.templateEngine = viewSettings.templateEngine(); - this.jsonParser = viewSettings.JSONParser(); - } - - @Override - public HttpServletResponse raw() { - return response; - } - - @Override - public int status() { - return response.getStatus(); - } - - @Override - public Response status(int status) { - response.setStatus(status); - return this; - } - - @Override - public Response badRequest() { - response.setStatus(HttpStatus.BAD_REQUEST); - return this; - } - - @Override - public Response unauthorized() { - response.setStatus(HttpStatus.UNAUTHORIZED); - return this; - } - - @Override - public Response notFound() { - response.setStatus(HttpStatus.NOT_FOUND); - return this; - } - - @Override - public Response conflict() { - response.setStatus(HttpStatus.CONFLICT); - return this; - } - - @Override - public String contentType() { - return response.getContentType(); - } - - @Override - public Response contentType(String contentType) { - response.setContentType(contentType); - return this; - } - - @Override - public String header(String name) { - return response.getHeader(name); - } - - @Override - public Response header(String name, String value) { - response.setHeader(name, value); - return this; - } - - @Override - public Response cookie(Cookie cookie) { - response.addCookie(cookie); - return this; - } - - @Override - public Response cookie(String name, String value) { - return cookie(name, value); - } - - @Override - public Response cookie(String name, String value, int maxAge) { - return cookie(name, value, maxAge, false); - } - - @Override - public Response cookie(String name, String value, int maxAge, boolean secured) { - return cookie(null, name, value, maxAge, secured); - } - - @Override - public Response cookie(String path, String name, String value, int maxAge, boolean secured) { - Cookie cookie = new Cookie(name, value); - if(null != path){ - cookie.setPath(path); - } - cookie.setMaxAge(maxAge); - cookie.setSecure(secured); - response.addCookie(cookie); - return this; - } - - @Override - public Response removeCookie(Cookie cookie) { - cookie.setMaxAge(0); - response.addCookie(map(cookie)); - return this; - } - - javax.servlet.http.Cookie map(Cookie cookie) { - javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); - servletCookie.setMaxAge(cookie.getMaxAge()); - if (cookie.getPath() != null) { - servletCookie.setPath(cookie.getPath()); - } - if (cookie.getDomain() != null) { - servletCookie.setDomain(cookie.getDomain()); - } - servletCookie.setHttpOnly(cookie.isHttpOnly()); - servletCookie.setSecure(cookie.getSecure()); - return servletCookie; - } - - @Override - public Response removeCookie(String name) { - Cookie cookie = new Cookie(name, ""); - cookie.setMaxAge(0); - response.addCookie(cookie); - return this; - } - - @Override - public Response text(String text) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/plain;charset=utf-8"); - DispatchKit.print(text, response.getWriter()); - this.written = true; - return this; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Response html(String html) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/html;charset=utf-8"); - - PrintWriter writer = response.getWriter(); - DispatchKit.print(html, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public Response json(String json) { - Request request = ApplicationWebContext.request(); - String userAgent = request.userAgent(); - if (userAgent.contains("MSIE")) { - response.setContentType("text/html;charset=utf-8"); - } else { - response.setContentType("application/json;charset=utf-8"); - } - try { - response.setHeader("Cache-Control", "no-cache"); - PrintWriter writer = response.getWriter(); - DispatchKit.print(json, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Response json(Object bean) { - return this.json(jsonParser.toJSONSting(bean)); - } - - @Override - public Response xml(String xml) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/xml;charset=utf-8"); - PrintWriter writer = response.getWriter(); - DispatchKit.print(xml, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public ServletOutputStream outputStream() throws IOException { - return response.getOutputStream(); - } - - @Override - public PrintWriter writer() throws IOException { - return response.getWriter(); - } - - @Override - public Response render(String view){ - Assert.notBlank(view, "view not is null"); - - String viewPath = Path.cleanPath(view); - ModelAndView modelAndView = new ModelAndView(viewPath); - try { - templateEngine.render(modelAndView, response.getWriter()); - } catch (TemplateException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return this; - } - - @Override - public Response render(ModelAndView modelAndView) { - Assert.notNull(modelAndView, "ModelAndView not is null!"); - Assert.notBlank(modelAndView.getView(), "view not is null"); - - String viewPath = Path.cleanPath(modelAndView.getView()); - modelAndView.setView(viewPath); - try { - templateEngine.render(modelAndView, response.getWriter()); - } catch (TemplateException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return this; - } - - @Override - public void redirect(String path) { - try { - response.sendRedirect(path); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void go(String path) { - try { - String ctx = ApplicationWebContext.servletContext().getContextPath(); - String location = Path.fixPath(ctx + path); - response.sendRedirect(location); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public boolean isWritten() { - return written; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http.wrapper; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.WebApplicationContext; +import com.blade.kit.Assert; +import com.blade.kit.DispatchKit; +import com.blade.mvc.http.HttpStatus; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; +import com.blade.mvc.view.parser.JSONParser; +import com.blade.mvc.view.template.TemplateEngine; +import com.blade.mvc.view.template.TemplateException; + +/** + * ServletResponse + * + * @author biezhi + * @since 1.5 + */ +public class ServletResponse implements Response { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServletResponse.class); + + private HttpServletResponse response; + + private boolean written = false; + + private ViewSettings viewSettings; + + private TemplateEngine templateEngine; + + private JSONParser jsonParser; + + public ServletResponse(HttpServletResponse response) { + this.response = response; + this.viewSettings = ViewSettings.$(); + this.templateEngine = viewSettings.templateEngine(); + this.jsonParser = viewSettings.JSONParser(); + } + + @Override + public HttpServletResponse raw() { + return response; + } + + @Override + public int status() { + return response.getStatus(); + } + + @Override + public Response status(int status) { + response.setStatus(status); + return this; + } + + @Override + public Response badRequest() { + response.setStatus(HttpStatus.BAD_REQUEST); + return this; + } + + @Override + public Response unauthorized() { + response.setStatus(HttpStatus.UNAUTHORIZED); + return this; + } + + @Override + public Response notFound() { + response.setStatus(HttpStatus.NOT_FOUND); + return this; + } + + @Override + public Response conflict() { + response.setStatus(HttpStatus.CONFLICT); + return this; + } + + @Override + public String contentType() { + return response.getContentType(); + } + + @Override + public Response contentType(String contentType) { + response.setContentType(contentType); + return this; + } + + @Override + public String header(String name) { + return response.getHeader(name); + } + + @Override + public Response header(String name, String value) { + response.setHeader(name, value); + return this; + } + + @Override + public Response cookie(Cookie cookie) { + response.addCookie(cookie); + return this; + } + + @Override + public Response cookie(String name, String value) { + return cookie(name, value); + } + + @Override + public Response cookie(String name, String value, int maxAge) { + return cookie(name, value, maxAge, false); + } + + @Override + public Response cookie(String name, String value, int maxAge, boolean secured) { + return cookie(null, name, value, maxAge, secured); + } + + @Override + public Response cookie(String path, String name, String value, int maxAge, boolean secured) { + Cookie cookie = new Cookie(name, value); + if(null != path){ + cookie.setPath(path); + } + cookie.setMaxAge(maxAge); + cookie.setSecure(secured); + response.addCookie(cookie); + return this; + } + + @Override + public Response removeCookie(Cookie cookie) { + cookie.setMaxAge(0); + response.addCookie(map(cookie)); + return this; + } + + javax.servlet.http.Cookie map(Cookie cookie) { + javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); + servletCookie.setMaxAge(cookie.getMaxAge()); + if (cookie.getPath() != null) { + servletCookie.setPath(cookie.getPath()); + } + if (cookie.getDomain() != null) { + servletCookie.setDomain(cookie.getDomain()); + } + servletCookie.setHttpOnly(cookie.isHttpOnly()); + servletCookie.setSecure(cookie.getSecure()); + return servletCookie; + } + + @Override + public Response removeCookie(String name) { + Cookie cookie = new Cookie(name, ""); + cookie.setMaxAge(0); + response.addCookie(cookie); + return this; + } + + @Override + public Response text(String text) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/plain;charset=utf-8"); + DispatchKit.print(text, response.getWriter()); + this.written = true; + return this; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Response html(String html) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/html;charset=utf-8"); + + PrintWriter writer = response.getWriter(); + DispatchKit.print(html, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public Response json(String json) { + Request request = WebApplicationContext.request(); + String userAgent = request.userAgent(); + if (userAgent.contains("MSIE")) { + response.setContentType("text/html;charset=utf-8"); + } else { + response.setContentType("application/json;charset=utf-8"); + } + try { + response.setHeader("Cache-Control", "no-cache"); + PrintWriter writer = response.getWriter(); + DispatchKit.print(json, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Response json(Object bean) { + return this.json(jsonParser.toJSONSting(bean)); + } + + @Override + public Response xml(String xml) { + try { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/xml;charset=utf-8"); + PrintWriter writer = response.getWriter(); + DispatchKit.print(xml, writer); + this.written = true; + return this; + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public ServletOutputStream outputStream() throws IOException { + return response.getOutputStream(); + } + + @Override + public PrintWriter writer() throws IOException { + return response.getWriter(); + } + + @Override + public Response render(String view){ + Assert.notBlank(view, "view not is null"); + + String viewPath = Path.cleanPath(view); + ModelAndView modelAndView = new ModelAndView(viewPath); + try { + templateEngine.render(modelAndView, response.getWriter()); + } catch (TemplateException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return this; + } + + @Override + public Response render(ModelAndView modelAndView) { + Assert.notNull(modelAndView, "ModelAndView not is null!"); + Assert.notBlank(modelAndView.getView(), "view not is null"); + + String viewPath = Path.cleanPath(modelAndView.getView()); + modelAndView.setView(viewPath); + try { + templateEngine.render(modelAndView, response.getWriter()); + } catch (TemplateException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return this; + } + + @Override + public void redirect(String path) { + try { + response.sendRedirect(path); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void go(String path) { + try { + String ctx = WebApplicationContext.servletContext().getContextPath(); + String location = Path.fixPath(ctx + path); + response.sendRedirect(location); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public boolean isWritten() { + return written; + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java index e850f41ba..e65ad9933 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java @@ -1,247 +1,247 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.route; - -import java.lang.reflect.Method; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.context.DynamicClassReader; -import com.blade.kit.CollectionKit; -import com.blade.kit.StringKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; -import com.blade.mvc.annotation.Controller; -import com.blade.mvc.annotation.Intercept; -import com.blade.mvc.annotation.RestController; -import com.blade.mvc.annotation.Route; -import com.blade.mvc.http.HttpMethod; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.interceptor.Interceptor; - -/** - * Route builder - * - * @author biezhi - * @since 1.5 - */ -public class RouteBuilder { - - private static final Logger LOGGER = LoggerFactory.getLogger(RouteBuilder.class); - - /** - * Class reader, used to scan the class specified in the rules - */ - private ClassReader classReader; - - private Routers routers; - - private String[] routePackages; - - private String interceptorPackage; - - public RouteBuilder(Routers routers) { - this.routers = routers; - this.classReader = DynamicClassReader.getClassReader(); - } - - /** - * Start building route - */ - public void building() { - - this.routePackages = Blade.$().config().getRoutePackages(); - this.interceptorPackage = Blade.$().config().getInterceptorPackage(); - - // Route - if(null != routePackages && routePackages.length > 0){ - this.buildRoute(routePackages); - } - - // Inteceptor - if(StringKit.isNotBlank(interceptorPackage)){ - this.buildInterceptor(interceptorPackage); - } - - } - - /** - * Build interceptor - * - * @param interceptorPackages add the interceptor package - */ - private void buildInterceptor(String... interceptorPackages){ - - // Scan all Interceptor - Set classes = null; - - // Traversal Interceptor - for(String packageName : interceptorPackages){ - - // Scan all Interceptor - classes = classReader.getClass(packageName, Interceptor.class, false); - if(CollectionKit.isNotEmpty(classes)){ - for(ClassInfo classInfo : classes){ - Class interceptorClazz = classInfo.getClazz(); - addInterceptor(interceptorClazz); - } - } - } - } - - /** - * Build Route - * - * @param routePackages route packets to add - */ - private void buildRoute(String... routePackages){ - Set classes = null; - // Traverse route - for(String packageName : routePackages){ - // Scan all Controoler - classes = classReader.getClassByAnnotation(packageName, Controller.class, true); - if(CollectionKit.isNotEmpty(classes)){ - for(ClassInfo classInfo : classes){ - Class pathClazz = classInfo.getClazz(); - addRouter(pathClazz); - } - } - } - - } - - /** - * Parse Interceptor - * - * @param interceptor resolve the interceptor class - */ - public void addInterceptor(final Class interceptor){ - - boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); - - if(null == interceptor || !hasInterface){ - return; - } - - Intercept intercept = interceptor.getAnnotation(Intercept.class); - String partten = "/.*"; - if(null != intercept){ - partten = intercept.value(); - } - - try { - Method before = interceptor.getMethod("before", Request.class, Response.class); - Method after = interceptor.getMethod("after", Request.class, Response.class); - buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); - buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - - } - - /** - * Parse all routing in a controller - * - * @param controller resolve the routing class - */ - public void addRouter(final Class router){ - - Method[] methods = router.getMethods(); - if(null == methods || methods.length == 0){ - return; - } - String nameSpace = null, suffix = null; - - if(null != router.getAnnotation(Controller.class)){ - nameSpace = router.getAnnotation(Controller.class).value(); - suffix = router.getAnnotation(Controller.class).suffix(); - } - - if(null != router.getAnnotation(RestController.class)){ - nameSpace = router.getAnnotation(RestController.class).value(); - suffix = router.getAnnotation(RestController.class).suffix(); - } - - if(null == nameSpace && null == suffix){ - LOGGER.warn("Route [{}] not controller annotation", router.getName()); - return; - } - - for (Method method : methods) { - Route mapping = method.getAnnotation(Route.class); - //route method - if (null != mapping) { - // build multiple route - HttpMethod methodType = mapping.method(); - String[] paths = mapping.value(); - if(null != paths && paths.length > 0){ - for(String value : paths){ - String pathV = getRoutePath(value, nameSpace, suffix); - buildRoute(router, method, pathV, methodType); - } - } - } - } - } - - private String getRoutePath(String value, String nameSpace, String suffix){ - String path = value.startsWith("/") ? value : "/" + value; - - nameSpace = nameSpace.startsWith("/") ? nameSpace : "/" + nameSpace; - path = nameSpace + path; - - path = path.replaceAll("[/]+", "/"); - - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - - path = path + suffix; - - return path; - } - - /** - * Build a route - * - * @param target route target execution class - * @param execMethod route execution method - * @param path route path - * @param method route httpmethod - */ - private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - - /** - * Build a route - * - * @param path route path - * @param target route target execution class - * @param execMethod route execution method - * @param method route httpmethod - */ - private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.route; + +import java.lang.reflect.Method; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.context.DynamicContext; +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.mvc.annotation.Controller; +import com.blade.mvc.annotation.Intercept; +import com.blade.mvc.annotation.RestController; +import com.blade.mvc.annotation.Route; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.interceptor.Interceptor; + +/** + * Route builder + * + * @author biezhi + * @since 1.5 + */ +public class RouteBuilder { + + private static final Logger LOGGER = LoggerFactory.getLogger(RouteBuilder.class); + + /** + * Class reader, used to scan the class specified in the rules + */ + private ClassReader classReader; + + private Routers routers; + + private String[] routePackages; + + private String interceptorPackage; + + public RouteBuilder(Routers routers) { + this.routers = routers; + this.classReader = DynamicContext.getClassReader(); + } + + /** + * Start building route + */ + public void building() { + + this.routePackages = Blade.$().config().getRoutePackages(); + this.interceptorPackage = Blade.$().config().getInterceptorPackage(); + + // Route + if(null != routePackages && routePackages.length > 0){ + this.buildRoute(routePackages); + } + + // Inteceptor + if(StringKit.isNotBlank(interceptorPackage)){ + this.buildInterceptor(interceptorPackage); + } + + } + + /** + * Build interceptor + * + * @param interceptorPackages add the interceptor package + */ + private void buildInterceptor(String... interceptorPackages){ + + // Scan all Interceptor + Set classes = null; + + // Traversal Interceptor + for(String packageName : interceptorPackages){ + + // Scan all Interceptor + classes = classReader.getClass(packageName, Interceptor.class, false); + if(CollectionKit.isNotEmpty(classes)){ + for(ClassInfo classInfo : classes){ + Class interceptorClazz = classInfo.getClazz(); + addInterceptor(interceptorClazz); + } + } + } + } + + /** + * Build Route + * + * @param routePackages route packets to add + */ + private void buildRoute(String... routePackages){ + Set classes = null; + // Traverse route + for(String packageName : routePackages){ + // Scan all Controoler + classes = classReader.getClassByAnnotation(packageName, Controller.class, true); + if(CollectionKit.isNotEmpty(classes)){ + for(ClassInfo classInfo : classes){ + Class pathClazz = classInfo.getClazz(); + addRouter(pathClazz); + } + } + } + + } + + /** + * Parse Interceptor + * + * @param interceptor resolve the interceptor class + */ + public void addInterceptor(final Class interceptor){ + + boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); + + if(null == interceptor || !hasInterface){ + return; + } + + Intercept intercept = interceptor.getAnnotation(Intercept.class); + String partten = "/.*"; + if(null != intercept){ + partten = intercept.value(); + } + + try { + Method before = interceptor.getMethod("before", Request.class, Response.class); + Method after = interceptor.getMethod("after", Request.class, Response.class); + buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); + buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + + } + + /** + * Parse all routing in a controller + * + * @param controller resolve the routing class + */ + public void addRouter(final Class router){ + + Method[] methods = router.getMethods(); + if(null == methods || methods.length == 0){ + return; + } + String nameSpace = null, suffix = null; + + if(null != router.getAnnotation(Controller.class)){ + nameSpace = router.getAnnotation(Controller.class).value(); + suffix = router.getAnnotation(Controller.class).suffix(); + } + + if(null != router.getAnnotation(RestController.class)){ + nameSpace = router.getAnnotation(RestController.class).value(); + suffix = router.getAnnotation(RestController.class).suffix(); + } + + if(null == nameSpace && null == suffix){ + LOGGER.warn("Route [{}] not controller annotation", router.getName()); + return; + } + + for (Method method : methods) { + Route mapping = method.getAnnotation(Route.class); + //route method + if (null != mapping) { + // build multiple route + HttpMethod methodType = mapping.method(); + String[] paths = mapping.value(); + if(null != paths && paths.length > 0){ + for(String value : paths){ + String pathV = getRoutePath(value, nameSpace, suffix); + buildRoute(router, method, pathV, methodType); + } + } + } + } + } + + private String getRoutePath(String value, String nameSpace, String suffix){ + String path = value.startsWith("/") ? value : "/" + value; + + nameSpace = nameSpace.startsWith("/") ? nameSpace : "/" + nameSpace; + path = nameSpace + path; + + path = path.replaceAll("[/]+", "/"); + + path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + + path = path + suffix; + + return path; + } + + /** + * Build a route + * + * @param target route target execution class + * @param execMethod route execution method + * @param path route path + * @param method route httpmethod + */ + private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + + /** + * Build a route + * + * @param path route path + * @param target route target execution class + * @param execMethod route execution method + * @param method route httpmethod + */ + private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java b/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java index dcf73bd88..88b4585ed 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java +++ b/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java @@ -1,78 +1,78 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.template; - -import java.io.IOException; -import java.io.Writer; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.context.ApplicationWebContext; -import com.blade.mvc.view.ModelAndView; - - -/** - * JSP Render, Default Render - * - * @author biezhi - * @since 1.6.6 - */ -public final class DefaultEngine implements TemplateEngine { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultEngine.class); - - private String viewPath = "/"; - - public DefaultEngine() { - } - - public DefaultEngine(String viewPath) { - this.viewPath = viewPath; - } - - @Override - public void render(ModelAndView modelAndView, Writer writer) { - HttpServletRequest servletRequest = ApplicationWebContext.request().raw(); - HttpServletResponse servletResponse = ApplicationWebContext.response().raw(); - - try { - Map model = modelAndView.getModel(); - String realPath = viewPath + modelAndView.getView(); - - if (null != model && !model.isEmpty()) { - Set keys = model.keySet(); - for (String key : keys) { - servletRequest.setAttribute(key, model.get(key)); - } - } - servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); - } catch (ServletException e) { - e.printStackTrace(); - LOGGER.error("", e); - } catch (IOException e) { - e.printStackTrace(); - LOGGER.error("", e); - } - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.template; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.WebApplicationContext; +import com.blade.mvc.view.ModelAndView; + + +/** + * JSP Render, Default Render + * + * @author biezhi + * @since 1.6.6 + */ +public final class DefaultEngine implements TemplateEngine { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultEngine.class); + + private String viewPath = "/"; + + public DefaultEngine() { + } + + public DefaultEngine(String viewPath) { + this.viewPath = viewPath; + } + + @Override + public void render(ModelAndView modelAndView, Writer writer) { + HttpServletRequest servletRequest = WebApplicationContext.request().raw(); + HttpServletResponse servletResponse = WebApplicationContext.response().raw(); + + try { + Map model = modelAndView.getModel(); + String realPath = viewPath + modelAndView.getView(); + + if (null != model && !model.isEmpty()) { + Set keys = model.keySet(); + for (String key : keys) { + servletRequest.setAttribute(key, model.get(key)); + } + } + servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); + } catch (ServletException e) { + e.printStackTrace(); + LOGGER.error("", e); + } catch (IOException e) { + e.printStackTrace(); + LOGGER.error("", e); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java index c06806441..9ba8ac37c 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java @@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.blade.context.ApplicationWebContext; +import com.blade.context.WebApplicationContext; import com.blade.mvc.view.ModelAndView; @@ -64,8 +64,8 @@ public void setSuffix(String suffix) { @Override public void render(ModelAndView modelAndView, Writer writer) throws TemplateException { - HttpServletRequest request = ApplicationWebContext.request().raw(); - HttpServletResponse response = ApplicationWebContext.response().raw(); + HttpServletRequest request = WebApplicationContext.request().raw(); + HttpServletResponse response = WebApplicationContext.response().raw(); try { Map model = modelAndView.getModel(); String realPath = viewPath + modelAndView.getView() + suffix; From 725bd3c2de8c064c9378a8a8f785846d9c537ab4 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 5 Sep 2016 18:09:40 +0800 Subject: [PATCH 497/545] =?UTF-8?q?=E2=9C=84=20update=20blade-jdbc=20versi?= =?UTF-8?q?on=20to=201.0.3-alpha?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LAST_VERSION.md | 170 ++++++++++++++++++++++++------------------------ 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index fbe9119c3..ac62fcac5 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -1,85 +1,85 @@ -# blade last version - -如果在maven仓库中下载不到最新版本的依赖,请添加maven snapshots仓库 - -```xml - - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - -``` - -和`dependencies`相同级别 - - -## [blade-kit](http://search.maven.org/#search%7Cga%7C1%7Cblade-kit) -```xml - -    com.bladejava -    blade-kit -    1.3.3 - -``` - -## [blade-core](http://search.maven.org/#search%7Cga%7C1%7Cblade-core) -```xml - -    com.bladejava -    blade-core -    1.6.6 - -``` - -## [blade-embed-jetty](http://search.maven.org/#search%7Cga%7C1%7Cblade-embed-jetty) -```xml - -    com.bladejava -    blade-embed-jetty -    0.0.4 - -``` - -## [blade-jdbc](http://search.maven.org/#search%7Cga%7C1%7Cblade-jdbc) -```xml - -    com.bladejava -    blade-jdbc -    0.1.2 - -``` - -## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache) -```xml - -    com.bladejava -    blade-cache -    1.2.3 - -``` - -## [blade-redis](http://search.maven.org/#search%7Cga%7C1%7Cblade-redis) -```xml - -    com.bladejava -    blade-redis -    1.2.3 - -``` - -## [blade-patchca](http://search.maven.org/#search%7Cga%7C1%7Cblade-patchca) -```xml - -    com.bladejava -    blade-patchca -    1.0.4 - -``` - +# blade last version + +如果在maven仓库中下载不到最新版本的依赖,请添加maven snapshots仓库 + +```xml + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + +``` + +和`dependencies`相同级别 + + +## [blade-kit](http://search.maven.org/#search%7Cga%7C1%7Cblade-kit) +```xml + +    com.bladejava +    blade-kit +    1.3.3 + +``` + +## [blade-core](http://search.maven.org/#search%7Cga%7C1%7Cblade-core) +```xml + +    com.bladejava +    blade-core +    1.6.6 + +``` + +## [blade-embed-jetty](http://search.maven.org/#search%7Cga%7C1%7Cblade-embed-jetty) +```xml + +    com.bladejava +    blade-embed-jetty +    0.0.4 + +``` + +## [blade-jdbc](http://search.maven.org/#search%7Cga%7C1%7Cblade-jdbc) +```xml + +    com.bladejava +    blade-jdbc +    0.1.3-alpha + +``` + +## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache) +```xml + +    com.bladejava +    blade-cache +    1.2.3 + +``` + +## [blade-redis](http://search.maven.org/#search%7Cga%7C1%7Cblade-redis) +```xml + +    com.bladejava +    blade-redis +    1.2.3 + +``` + +## [blade-patchca](http://search.maven.org/#search%7Cga%7C1%7Cblade-patchca) +```xml + +    com.bladejava +    blade-patchca +    1.0.4 + +``` + From 3f2d97b6631052984c674ea24f145790664f122e Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 5 Sep 2016 18:55:17 +0800 Subject: [PATCH 498/545] =?UTF-8?q?=E2=9C=84=20reset=20config=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/Blade.java | 1445 ++++++++--------- .../com/blade/config/ApplicationConfig.java | 414 ++--- .../java/com/blade/config/ConfigLoader.java | 2 +- .../com/blade/context/ApplicationContext.java | 116 +- .../com/blade/context/DynamicContext.java | 2 +- .../java/com/blade/ioc/IocApplication.java | 8 +- .../src/main/java/com/blade/kit/AsmKit.java | 240 +-- .../main/java/com/blade/kit/DispatchKit.java | 428 +++-- .../java/com/blade/mvc/DispatcherServlet.java | 2 +- .../com/blade/mvc/route/RouteBuilder.java | 4 +- .../com/blade/embedd/EmbedJettyServer.java | 20 +- .../main/java/com/blade/kit/Environment.java | 156 -- .../base/{ConfigLoader.java => Config.java} | 398 +++-- blade-starter/pom.xml | 212 +-- 14 files changed, 1696 insertions(+), 1751 deletions(-) delete mode 100644 blade-kit/src/main/java/com/blade/kit/Environment.java rename blade-kit/src/main/java/com/blade/kit/base/{ConfigLoader.java => Config.java} (53%) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index dae594386..445e19021 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -1,727 +1,720 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.io.InputStream; -import java.text.ParseException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.blade.config.ApplicationConfig; -import com.blade.config.BaseConfig; -import com.blade.config.ConfigLoader; -import com.blade.embedd.EmbedServer; -import com.blade.exception.EmbedServerException; -import com.blade.ioc.Ioc; -import com.blade.ioc.SimpleIoc; -import com.blade.kit.Assert; -import com.blade.kit.Environment; -import com.blade.kit.StringKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.mvc.http.HttpMethod; -import com.blade.mvc.interceptor.Interceptor; -import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteBuilder; -import com.blade.mvc.route.RouteException; -import com.blade.mvc.route.RouteGroup; -import com.blade.mvc.route.RouteHandler; -import com.blade.mvc.route.Routers; -import com.blade.mvc.route.loader.ClassPathRouteLoader; -import com.blade.plugin.Plugin; - -/** - * Blade Core Class - * - * @author biezhi - * @since 1.6.6 - */ -public final class Blade { - - // blade initialize - private boolean isInit = false; - - // blade bootstrap config class - private Bootstrap bootstrap = null; - - // global configuration Object - private ApplicationConfig applicationConfig = null; - - // ioc container - private Ioc ioc = new SimpleIoc(); - - // routes - private Routers routers = new Routers(); - - // routebuilder - private RouteBuilder routeBuilder; - - // jetty start port - private int port = Const.DEFAULT_PORT; - - // default context path - private String contextPath = Const.DEFAULT_CONTEXTPATH; - - // enableServer - private Boolean enableServer = false; - - // plugins - private Set> plugins; - - // global environment - private Environment environment; - - // config loader - private ConfigLoader configLoader; - - // embed server - private EmbedServer embedServer; - - private Blade() { - this.environment = new Environment(); - this.applicationConfig = new ApplicationConfig(); - this.plugins = new HashSet>(); - this.routeBuilder = new RouteBuilder(this.routers); - this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); - } - - static final class BladeHolder { - private static final Blade $ = new Blade(); - } - - /** - * @return Single case method returns Blade object - */ - @Deprecated - public static final Blade me() { - return BladeHolder.$; - } - - /** - * - * @param appConf - * @return - */ - @Deprecated - public static final Blade me(String confPath) { - Blade blade = BladeHolder.$; - blade.environment.add(confPath); - return blade; - } - - /** - * @return Single case method returns Blade object - */ - public static final Blade $() { - return BladeHolder.$; - } - - /** - * @param confPath - * @return - */ - public static final Blade $(String confPath) { - Assert.notEmpty(confPath); - Blade blade = BladeHolder.$; - blade.environment.add(confPath); - return blade; - } - - /** - * Set Blade initialize - * - * @param isInit - * initialize - */ - public void init() { - if (!this.isInit) { - this.isInit = true; - } - } - - /** - * @return return route manager - */ - public Routers routers() { - return routers; - } - - /** - * @return return RouteBuilder - */ - public RouteBuilder routeBuilder() { - return routeBuilder; - } - - /** - * @return return ConfigLoader - */ - public ConfigLoader configLoader() { - return configLoader; - } - - /** - * @return return blade ioc container - */ - public Ioc ioc() { - return ioc; - } - - /** - * Setting a ioc container - * - * @param container - * ioc object - * @return return blade - */ - public Blade container(Ioc ioc) { - Assert.notNull(ioc); - this.ioc = ioc; - this.configLoader.setIoc(ioc); - return this; - } - - /** - * Setting Properties configuration file File path based on classpath - * - * @param confPath - * properties file name - * @return return blade - */ - public Blade loadAppConf(String confPath) { - Assert.notBlank(confPath); - environment.add(confPath); - return this; - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackage(String packageName) { - return this.addRoutePackages(packageName); - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackages(String... packages) { - Assert.notNull(packages); - applicationConfig.addRoutePackages(packages); - return this; - } - - /** - * - * @param basePackage - * @return - */ - public Blade basePackage(String basePackage) { - Assert.notBlank(basePackage); - applicationConfig.setBasePackage(basePackage); - applicationConfig.addIocPackages(basePackage + ".service.*"); - applicationConfig.addRoutePackages(basePackage + ".controller"); - applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); - return this; - } - - /** - * Setting the path where the interceptor, e.g:com.bladejava.interceptor - * - * @param packageName - * interceptor packagename - * @return return blade - */ - public Blade interceptor(String packageName) { - Assert.notBlank(packageName); - applicationConfig.setInterceptorPackage(packageName); - return this; - } - - /** - * Setting Ioc packages, e.g:com.bladejava.service - * - * @param packages - * All need to do into the package, can be introduced into a - * number of - * @return return blade - */ - public Blade ioc(String... packages) { - Assert.notNull(packages); - applicationConfig.addIocPackages(packages); - return this; - } - - /** - * Add a route - * - * @param path - * route path - * @param target - * Target object for routing - * @param method - * The method name of the route (at the same time, the HttpMethod - * is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @return return blade - */ - public Blade route(String path, Class clazz, String method) { - routers.route(path, clazz, method); - return this; - } - - /** - * Register a functional route - * - * @param path - * route url - * @param clazz - * route processing class - * @param method - * route processing method name - * @param httpMethod - * HttpMethod Type, GET/POST/... - * @return Blade return blade - */ - public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { - routers.route(path, clazz, method, httpMethod); - return this; - } - - /** - * Add a route list - * - * @param routes - * route list - * @return return blade - */ - public Blade routes(List routes) { - Assert.notEmpty(routes, "Routes not is empty!"); - routers.addRoutes(routes); - return this; - } - - /** - * Register a GET request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade get(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.GET); - return this; - } - - /** - * Register a POST request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade post(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.POST); - return this; - } - - /** - * Register a DELETE request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade delete(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.DELETE); - return this; - } - - /** - * Register a PUT request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade put(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.PUT); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade all(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade any(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Route Group. e.g blade.group('/users').get().post() - * - * @param g - * @return return blade - */ - public RouteGroup group(String prefix) { - Assert.notNull(prefix, "Route group prefix not is null"); - return new RouteGroup(this, prefix); - } - - /** - * Register a pre routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade before(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.BEFORE); - return this; - } - - /** - * Register a after routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade after(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.AFTER); - return this; - } - - /** - * Setting the frame static file folder - * - * @param resources - * List of directories to filter, e.g: "/public,/static,/images" - * @return return blade - */ - public Blade addResources(final String... resources) { - applicationConfig.addResources(resources); - return this; - } - - /** - * Dynamically set the global initialization class, the embedded Jetty boot - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Bootstrap bootstrap) { - Assert.notNull(bootstrap); - this.bootstrap = bootstrap; - return this; - } - - /** - * Dynamically set global initialization class - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Class bootstrap) { - Assert.notNull(bootstrap); - try { - Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); - ioc.addBean(Bootstrap.class.getName(), object); - this.bootstrap = object; - } catch (Exception e) { - e.printStackTrace(); - } - return this; - } - - /** - * add interceptor - * - * @param interceptor interceptor class - * @return return blade obj - */ - public Blade addInterceptor(Class interceptor) { - routeBuilder.addInterceptor(interceptor); - return this; - } - - /** - * add config - * - * @param config config class - * @return return blade obj - */ - public Blade addConfig(Class config) { - configLoader.addConfig(config); - return this; - } - - /** - * Setting blade web root path - * - * @param webRoot - * web root path - * @return return blade - */ - public Blade webRoot(final String webRoot) { - Assert.notBlank(webRoot); - applicationConfig.setWebRoot(webRoot); - return this; - } - - /** - * Setting blade run mode - * - * @param isDev - * is dev mode - * @return return blade - */ - public Blade isDev(boolean isDev) { - applicationConfig.setDev(isDev); - return this; - } - - /** - * Setting jetty listen port - * - * @param port - * port, default is 9000 - * @return return blade - */ - public Blade listen(int port) { - this.port = port; - return this; - } - - /** - * start web server - */ - public void start() { - this.start(null); - } - - /** - * start web server - * @param applicationClass your app root package starter - */ - public void start(Class applicationClass) { - - this.loadAppConf(Const.APP_PROPERTIES); - - // init blade environment config - applicationConfig.setEnv(environment); - - if(null != applicationClass){ - applicationConfig.setApplicationClass(applicationClass); - if(StringKit.isBlank(applicationConfig.getBasePackage())){ - applicationConfig.setBasePackage(applicationClass.getPackage().getName()); - } - } - - try { - Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); - if(null == embedClazz){ - embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); - } - if(null != embedClazz){ - this.embedServer = (EmbedServer) embedClazz.newInstance(); - this.embedServer.startup(port, contextPath); - this.enableServer = true; - } else { - throw new EmbedServerException("Not found EmbedServer"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * @return Return EmbedServer - */ - public EmbedServer embedServer() { - return this.embedServer; - } - - /** - * @return Return blade config object - */ - public ApplicationConfig applicationConfig() { - return applicationConfig; - } - - /** - * @return Return blade config object - */ - public ApplicationConfig config() { - return applicationConfig; - } - - /** - * @return Return Blade Environment - */ - public Environment environment() { - return environment; - } - - /** - * @return Return blade encoding, default is UTF-8 - */ - public String encoding() { - return applicationConfig.getEncoding(); - } - - /** - * @return Return blade web root path - */ - public String webRoot() { - return applicationConfig.getWebRoot(); - } - - /** - * @return Return is dev mode - */ - public boolean isDev() { - return applicationConfig.isDev(); - } - - /** - * @return Return static resource directory - */ - public Set staticFolder() { - return applicationConfig.getStaticFolders(); - } - - /** - * @return Return bootstrap object - */ - public Bootstrap bootstrap() { - return this.bootstrap; - } - - /** - * return register plugin object - * - * @param plugin - * plugin class - * @return return blade - */ - public Blade plugin(Class plugin) { - Assert.notNull(plugin); - plugins.add(plugin); - return this; - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @return return blade - */ - public Blade routeConf(String basePackage) { - return routeConf(basePackage, "route.conf"); - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @param conf - * Configuration file path, the configuration file must be in - * classpath - * @return return blade - */ - public Blade routeConf(String basePackage, String conf) { - try { - Assert.notBlank(basePackage); - Assert.notBlank(conf); - InputStream ins = Blade.class.getResourceAsStream("/" + conf); - ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); - routesLoader.setBasePackage(basePackage); - List routes = routesLoader.load(); - routers.addRoutes(routes); - } catch (RouteException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - return this; - } - - /** - * @return Return blade is initialize - */ - public boolean isInit() { - return isInit; - } - - public Blade enableServer(boolean enableServer) { - this.enableServer = enableServer; - return this; - } - - public boolean enableServer() { - return this.enableServer; - } - - public Set> plugins() { - return this.plugins; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +import java.io.InputStream; +import java.text.ParseException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.blade.config.ApplicationConfig; +import com.blade.config.BaseConfig; +import com.blade.config.ConfigLoader; +import com.blade.embedd.EmbedServer; +import com.blade.exception.EmbedServerException; +import com.blade.ioc.Ioc; +import com.blade.ioc.SimpleIoc; +import com.blade.kit.Assert; +import com.blade.kit.StringKit; +import com.blade.kit.base.Config; +import com.blade.kit.reflect.ReflectKit; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.interceptor.Interceptor; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteBuilder; +import com.blade.mvc.route.RouteException; +import com.blade.mvc.route.RouteGroup; +import com.blade.mvc.route.RouteHandler; +import com.blade.mvc.route.Routers; +import com.blade.mvc.route.loader.ClassPathRouteLoader; +import com.blade.plugin.Plugin; + +/** + * Blade Core Class + * + * @author biezhi + * @since 1.6.6 + */ +public final class Blade { + + // blade initialize + private boolean isInit = false; + + // blade bootstrap config class + private Bootstrap bootstrap = null; + + // global configuration Object + private ApplicationConfig applicationConfig = null; + + // ioc container + private Ioc ioc = new SimpleIoc(); + + // routes + private Routers routers = new Routers(); + + // routebuilder + private RouteBuilder routeBuilder; + + // jetty start port + private int port = Const.DEFAULT_PORT; + + // default context path + private String contextPath = Const.DEFAULT_CONTEXTPATH; + + // enableServer + private Boolean enableServer = false; + + // plugins + private Set> plugins; + + // global config + private Config config; + + // config loader + private ConfigLoader configLoader; + + // embed server + private EmbedServer embedServer; + + private Blade() { + this.config = new Config(); + this.applicationConfig = new ApplicationConfig(); + this.plugins = new HashSet>(); + this.routeBuilder = new RouteBuilder(this.routers); + this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); + } + + static final class BladeHolder { + private static final Blade $ = new Blade(); + } + + /** + * @return Single case method returns Blade object + */ + @Deprecated + public static final Blade me() { + return BladeHolder.$; + } + + /** + * + * @param location + * @return + */ + @Deprecated + public static final Blade me(String location) { + Blade blade = BladeHolder.$; + blade.config.add(location); + return blade; + } + + /** + * @return Single case method returns Blade object + */ + public static final Blade $() { + return BladeHolder.$; + } + + /** + * @param confPath + * @return + */ + public static final Blade $(String location) { + Assert.notEmpty(location); + Blade blade = BladeHolder.$; + blade.config.add(location); + return blade; + } + + /** + * Set Blade initialize + * + * @param isInit + * initialize + */ + public void init() { + if (!this.isInit) { + this.isInit = true; + } + } + + /** + * @return return route manager + */ + public Routers routers() { + return routers; + } + + /** + * @return return RouteBuilder + */ + public RouteBuilder routeBuilder() { + return routeBuilder; + } + + /** + * @return return ConfigLoader + */ + public ConfigLoader configLoader() { + return configLoader; + } + + /** + * @return return blade ioc container + */ + public Ioc ioc() { + return ioc; + } + + /** + * Setting a ioc container + * + * @param container + * ioc object + * @return return blade + */ + public Blade container(Ioc ioc) { + Assert.notNull(ioc); + this.ioc = ioc; + this.configLoader.setIoc(ioc); + return this; + } + + /** + * Setting Properties configuration file File path based on classpath + * + * @param location properties file name + * @return return blade + */ + public Blade loadAppConf(String location) { + Assert.notBlank(location); + config.add(location); + return this; + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackage(String packageName) { + return this.addRoutePackages(packageName); + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackages(String... packages) { + Assert.notNull(packages); + applicationConfig.addRoutePackages(packages); + return this; + } + + /** + * + * @param basePackage + * @return + */ + public Blade basePackage(String basePackage) { + Assert.notBlank(basePackage); + applicationConfig.setBasePackage(basePackage); + applicationConfig.addIocPackages(basePackage + ".service.*"); + applicationConfig.addRoutePackages(basePackage + ".controller"); + applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); + return this; + } + + /** + * Setting the path where the interceptor, e.g:com.bladejava.interceptor + * + * @param packageName + * interceptor packagename + * @return return blade + */ + public Blade interceptor(String packageName) { + Assert.notBlank(packageName); + applicationConfig.setInterceptorPackage(packageName); + return this; + } + + /** + * Setting Ioc packages, e.g:com.bladejava.service + * + * @param packages + * All need to do into the package, can be introduced into a + * number of + * @return return blade + */ + public Blade ioc(String... packages) { + Assert.notNull(packages); + applicationConfig.addIocPackages(packages); + return this; + } + + /** + * Add a route + * + * @param path + * route path + * @param target + * Target object for routing + * @param method + * The method name of the route (at the same time, the HttpMethod + * is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade + */ + public Blade route(String path, Class clazz, String method) { + routers.route(path, clazz, method); + return this; + } + + /** + * Register a functional route + * + * @param path + * route url + * @param clazz + * route processing class + * @param method + * route processing method name + * @param httpMethod + * HttpMethod Type, GET/POST/... + * @return Blade return blade + */ + public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { + routers.route(path, clazz, method, httpMethod); + return this; + } + + /** + * Add a route list + * + * @param routes + * route list + * @return return blade + */ + public Blade routes(List routes) { + Assert.notEmpty(routes, "Routes not is empty!"); + routers.addRoutes(routes); + return this; + } + + /** + * Register a GET request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade get(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.GET); + return this; + } + + /** + * Register a POST request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade post(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.POST); + return this; + } + + /** + * Register a DELETE request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade delete(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.DELETE); + return this; + } + + /** + * Register a PUT request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade put(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.PUT); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade all(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade any(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Route Group. e.g blade.group('/users').get().post() + * + * @param g + * @return return blade + */ + public RouteGroup group(String prefix) { + Assert.notNull(prefix, "Route group prefix not is null"); + return new RouteGroup(this, prefix); + } + + /** + * Register a pre routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade before(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.BEFORE); + return this; + } + + /** + * Register a after routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade after(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.AFTER); + return this; + } + + /** + * Setting the frame static file folder + * + * @param resources + * List of directories to filter, e.g: "/public,/static,/images" + * @return return blade + */ + public Blade addResources(final String... resources) { + applicationConfig.addResources(resources); + return this; + } + + /** + * Dynamically set the global initialization class, the embedded Jetty boot + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Bootstrap bootstrap) { + Assert.notNull(bootstrap); + this.bootstrap = bootstrap; + return this; + } + + /** + * Dynamically set global initialization class + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Class bootstrap) { + Assert.notNull(bootstrap); + try { + Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); + ioc.addBean(Bootstrap.class.getName(), object); + this.bootstrap = object; + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + /** + * add interceptor + * + * @param interceptor interceptor class + * @return return blade obj + */ + public Blade addInterceptor(Class interceptor) { + routeBuilder.addInterceptor(interceptor); + return this; + } + + /** + * add config + * + * @param config config class + * @return return blade obj + */ + public Blade addConfig(Class config) { + configLoader.addConfig(config); + return this; + } + + /** + * Setting blade web root path + * + * @param webRoot + * web root path + * @return return blade + */ + public Blade webRoot(final String webRoot) { + Assert.notBlank(webRoot); + applicationConfig.setWebRoot(webRoot); + return this; + } + + /** + * Setting blade run mode + * + * @param isDev + * is dev mode + * @return return blade + */ + public Blade isDev(boolean isDev) { + applicationConfig.setDev(isDev); + return this; + } + + /** + * Setting jetty listen port + * + * @param port + * port, default is 9000 + * @return return blade + */ + public Blade listen(int port) { + this.port = port; + return this; + } + + /** + * start web server + */ + public void start() { + this.start(null); + } + + /** + * start web server + * + * @param applicationClass your app root package starter + */ + public void start(Class applicationClass) { + + this.loadAppConf(Const.APP_PROPERTIES); + + // init blade environment config + applicationConfig.setEnv(config); + + if(null != applicationClass){ + applicationConfig.setApplicationClass(applicationClass); + if(StringKit.isBlank(applicationConfig.getBasePackage())){ + applicationConfig.setBasePackage(applicationClass.getPackage().getName()); + } + } + + try { + Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); + if(null == embedClazz){ + embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); + } + if(null != embedClazz){ + this.embedServer = (EmbedServer) embedClazz.newInstance(); + this.embedServer.startup(port, contextPath); + this.enableServer = true; + } else { + throw new EmbedServerException("Not found EmbedServer"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * @return Return EmbedServer + */ + public EmbedServer embedServer() { + return this.embedServer; + } + + /** + * @return Return blade config object + */ + public ApplicationConfig applicationConfig() { + return applicationConfig; + } + + /** + * @return Return blade config object + */ + public Config config() { + return this.config; + } + + /** + * @return Return blade encoding, default is UTF-8 + */ + public String encoding() { + return applicationConfig.getEncoding(); + } + + /** + * @return Return blade web root path + */ + public String webRoot() { + return applicationConfig.getWebRoot(); + } + + /** + * @return Return is dev mode + */ + public boolean isDev() { + return applicationConfig.isDev(); + } + + /** + * @return Return static resource directory + */ + public Set staticFolder() { + return applicationConfig.getStaticFolders(); + } + + /** + * @return Return bootstrap object + */ + public Bootstrap bootstrap() { + return this.bootstrap; + } + + /** + * return register plugin object + * + * @param plugin + * plugin class + * @return return blade + */ + public Blade plugin(Class plugin) { + Assert.notNull(plugin); + plugins.add(plugin); + return this; + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @return return blade + */ + public Blade routeConf(String basePackage) { + return routeConf(basePackage, "route.conf"); + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @param conf + * Configuration file path, the configuration file must be in + * classpath + * @return return blade + */ + public Blade routeConf(String basePackage, String conf) { + try { + Assert.notBlank(basePackage); + Assert.notBlank(conf); + InputStream ins = Blade.class.getResourceAsStream("/" + conf); + ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); + routesLoader.setBasePackage(basePackage); + List routes = routesLoader.load(); + routers.addRoutes(routes); + } catch (RouteException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return this; + } + + /** + * @return Return blade is initialize + */ + public boolean isInit() { + return isInit; + } + + public Blade enableServer(boolean enableServer) { + this.enableServer = enableServer; + return this; + } + + public boolean enableServer() { + return this.enableServer; + } + + public Set> plugins() { + return this.plugins; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 2ecd39084..82a6609f1 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -1,207 +1,207 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.kit.Assert; -import com.blade.kit.Environment; -import com.blade.kit.StringKit; -import com.blade.mvc.view.ViewSettings; - -/** - * Blade Application Config Class - * - * @author biezhi - * @since 1.6.6 - * - */ -public class ApplicationConfig { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfig.class); - - // Storage of all routing packets - private Set routePackages = new HashSet(8); - - // Store all IOC packages - private Set iocPackages = new HashSet(8); - - // Strore all config packages - private Set configPackages = new HashSet(2); - - // Store all filter directories - private Set staticFolders = new HashSet(5); - - // Base package - private String basePackage; - - // Interceptor package - private String interceptorPackage; - - // Encoding - private String encoding = "utf-8"; - - // web root path - private String webRoot = ""; - - // Is dev mode - private boolean isDev = true; - - private boolean isInit = false; - - private Class applicationClass; - - public ApplicationConfig() { - this.addResources("/public", "/assets", "/static"); - } - - public void setEnv(Environment environment) { - if (null != environment && !isInit) { - this.isDev = environment.getBoolean("app.dev", true); - - this.addIocPackages(environment.getString("app.ioc")); - - ViewSettings.$().setView500(environment.getString("mvc.view.500")); - ViewSettings.$().setView404(environment.getString("mvc.view.404")); - this.encoding = environment.getString("mvc.http.encoding", "UTF-8"); - String statics = environment.getString("mvc.statics"); - - String basePackage = environment.getString("app.base-package"); - Integer port = environment.getInt("server.port"); - - if (null != port) { - Blade.$().listen(port); - } - - if (StringKit.isNotBlank(statics)) { - this.addResources(statics.split(",")); - } - - if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { - this.setBasePackage(basePackage); - } - isInit = true; - } - } - - public String[] getRoutePackages() { - String[] routeArr = new String[routePackages.size()]; - return routePackages.toArray(routeArr); - } - - public void addRoutePackages(String... packages) { - if (null != packages && packages.length > 0) { - routePackages.addAll(Arrays.asList(packages)); - } - } - - public String getBasePackage() { - return basePackage; - } - - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - this.addConfigPackages(basePackage + ".config"); - this.addIocPackages(basePackage + ".service.*"); - this.addRoutePackages(basePackage + ".controller"); - this.setInterceptorPackage(basePackage + ".interceptor"); - } - - public String[] getIocPackages() { - String[] iocArr = new String[iocPackages.size()]; - return iocPackages.toArray(iocArr); - } - - public String[] getConfigPackages() { - String[] configArr = new String[configPackages.size()]; - return configPackages.toArray(configArr); - } - - public void addIocPackages(String... packages) { - if (null != packages && packages.length > 0) { - iocPackages.addAll(Arrays.asList(packages)); - } - } - - public void addConfigPackages(String... packages) { - if (null != packages && packages.length > 0) { - configPackages.addAll(Arrays.asList(packages)); - } - } - - public String getInterceptorPackage() { - return interceptorPackage; - } - - public void setInterceptorPackage(String interceptorPackage) { - this.interceptorPackage = interceptorPackage; - } - - public Set getStaticFolders() { - return staticFolders; - } - - public void addResources(String... resources) { - Assert.notNull(resources); - for(String resource : resources){ - LOGGER.debug("Add Resource: {}", resource); - } - staticFolders.addAll(Arrays.asList(resources)); - } - - public String getWebRoot() { - return webRoot; - } - - public void setWebRoot(String webRoot) { - this.webRoot = webRoot; - } - - public boolean isDev() { - return isDev; - } - - public void setDev(boolean isDev) { - this.isDev = isDev; - } - - public String getEncoding() { - return encoding; - } - - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - public boolean isInit(){ - return this.isInit; - } - - public Class getApplicationClass() { - return applicationClass; - } - - public void setApplicationClass(Class applicationClass) { - this.applicationClass = applicationClass; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.kit.Assert; +import com.blade.kit.StringKit; +import com.blade.kit.base.Config; +import com.blade.mvc.view.ViewSettings; + +/** + * Blade Application Config Class + * + * @author biezhi + * @since 1.6.6 + * + */ +public class ApplicationConfig { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfig.class); + + // Storage of all routing packets + private Set routePackages = new HashSet(8); + + // Store all IOC packages + private Set iocPackages = new HashSet(8); + + // Strore all config packages + private Set configPackages = new HashSet(2); + + // Store all filter directories + private Set staticFolders = new HashSet(5); + + // Base package + private String basePackage; + + // Interceptor package + private String interceptorPackage; + + // Encoding + private String encoding = "utf-8"; + + // web root path + private String webRoot = ""; + + // Is dev mode + private boolean isDev = true; + + private boolean isInit = false; + + private Class applicationClass; + + public ApplicationConfig() { + this.addResources("/public", "/assets", "/static"); + } + + public void setEnv(Config config) { + if (null != config && !isInit) { + this.isDev = config.getBoolean("app.dev", true); + + this.addIocPackages(config.get("app.ioc")); + + ViewSettings.$().setView500(config.get("mvc.view.500")); + ViewSettings.$().setView404(config.get("mvc.view.404")); + this.encoding = config.get("mvc.http.encoding", "UTF-8"); + String statics = config.get("mvc.statics"); + + String basePackage = config.get("app.base-package"); + Integer port = config.getInt("server.port"); + + if (null != port) { + Blade.$().listen(port); + } + + if (StringKit.isNotBlank(statics)) { + this.addResources(statics.split(",")); + } + + if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { + this.setBasePackage(basePackage); + } + isInit = true; + } + } + + public String[] getRoutePackages() { + String[] routeArr = new String[routePackages.size()]; + return routePackages.toArray(routeArr); + } + + public void addRoutePackages(String... packages) { + if (null != packages && packages.length > 0) { + routePackages.addAll(Arrays.asList(packages)); + } + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + this.addConfigPackages(basePackage + ".config"); + this.addIocPackages(basePackage + ".service.*"); + this.addRoutePackages(basePackage + ".controller"); + this.setInterceptorPackage(basePackage + ".interceptor"); + } + + public String[] getIocPackages() { + String[] iocArr = new String[iocPackages.size()]; + return iocPackages.toArray(iocArr); + } + + public String[] getConfigPackages() { + String[] configArr = new String[configPackages.size()]; + return configPackages.toArray(configArr); + } + + public void addIocPackages(String... packages) { + if (null != packages && packages.length > 0) { + iocPackages.addAll(Arrays.asList(packages)); + } + } + + public void addConfigPackages(String... packages) { + if (null != packages && packages.length > 0) { + configPackages.addAll(Arrays.asList(packages)); + } + } + + public String getInterceptorPackage() { + return interceptorPackage; + } + + public void setInterceptorPackage(String interceptorPackage) { + this.interceptorPackage = interceptorPackage; + } + + public Set getStaticFolders() { + return staticFolders; + } + + public void addResources(String... resources) { + Assert.notNull(resources); + for(String resource : resources){ + LOGGER.debug("Add Resource: {}", resource); + } + staticFolders.addAll(Arrays.asList(resources)); + } + + public String getWebRoot() { + return webRoot; + } + + public void setWebRoot(String webRoot) { + this.webRoot = webRoot; + } + + public boolean isDev() { + return isDev; + } + + public void setDev(boolean isDev) { + this.isDev = isDev; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public boolean isInit(){ + return this.isInit; + } + + public Class getApplicationClass() { + return applicationClass; + } + + public void setApplicationClass(Class applicationClass) { + this.applicationClass = applicationClass; + } + +} diff --git a/blade-core/src/main/java/com/blade/config/ConfigLoader.java b/blade-core/src/main/java/com/blade/config/ConfigLoader.java index f59e4c9d8..91652746e 100644 --- a/blade-core/src/main/java/com/blade/config/ConfigLoader.java +++ b/blade-core/src/main/java/com/blade/config/ConfigLoader.java @@ -57,7 +57,7 @@ public void setIoc(Ioc ioc){ @SuppressWarnings("unchecked") public void loadConfig() { - String[] configPackages = Blade.$().config().getConfigPackages(); + String[] configPackages = Blade.$().applicationConfig().getConfigPackages(); if (null != configPackages && configPackages.length > 0) { // Scan package all class try { diff --git a/blade-core/src/main/java/com/blade/context/ApplicationContext.java b/blade-core/src/main/java/com/blade/context/ApplicationContext.java index c527b5df7..9787cb06a 100644 --- a/blade-core/src/main/java/com/blade/context/ApplicationContext.java +++ b/blade-core/src/main/java/com/blade/context/ApplicationContext.java @@ -1,58 +1,58 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.exception.BladeException; -import com.blade.ioc.IocApplication; - -/** - * Blade ApplicationContext, init context - * - * @author biezhi - * @since 1.6.6 - */ -public final class ApplicationContext { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContext.class); - - public static void init(Blade blade) throws BladeException{ - try { - - blade.bootstrap().init(blade); - - if(!blade.config().isInit()){ - blade.loadAppConf(Const.APP_PROPERTIES); - blade.config().setEnv(blade.environment()); - } - - // initialization ioc - IocApplication iocApplication = new IocApplication(); - iocApplication.initBeans(); - - blade.init(); - blade.bootstrap().contextInitialized(); - } catch (Exception e) { - LOGGER.error("ApplicationContext init error", e); - } - - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.exception.BladeException; +import com.blade.ioc.IocApplication; + +/** + * Blade ApplicationContext, init context + * + * @author biezhi + * @since 1.6.6 + */ +public final class ApplicationContext { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContext.class); + + public static void init(Blade blade) throws BladeException{ + try { + + blade.bootstrap().init(blade); + + if(!blade.applicationConfig().isInit()){ + blade.loadAppConf(Const.APP_PROPERTIES); + blade.applicationConfig().setEnv(blade.config()); + } + + // initialization ioc + IocApplication iocApplication = new IocApplication(); + iocApplication.initBeans(); + + blade.init(); + blade.bootstrap().contextInitialized(); + } catch (Exception e) { + LOGGER.error("ApplicationContext init error", e); + } + + } + +} diff --git a/blade-core/src/main/java/com/blade/context/DynamicContext.java b/blade-core/src/main/java/com/blade/context/DynamicContext.java index 71b856104..c9d127921 100644 --- a/blade-core/src/main/java/com/blade/context/DynamicContext.java +++ b/blade-core/src/main/java/com/blade/context/DynamicContext.java @@ -41,7 +41,7 @@ private DynamicContext() { } public static void init(){ - Class clazz = Blade.$().config().getApplicationClass(); + Class clazz = Blade.$().applicationConfig().getApplicationClass(); String rs = clazz.getResource("").toString(); if(rs.indexOf(".jar") != -1){ CLASS_READER = new JarReaderImpl(); diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index b44a88571..9c1551a6a 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -72,7 +72,7 @@ public IocApplication() { */ private List loadCondigs() throws Exception { List configs = null; - String[] configPackages = blade.config().getConfigPackages(); + String[] configPackages = blade.applicationConfig().getConfigPackages(); if (null != configPackages && configPackages.length > 0) { configs = new ArrayList(10); for (String packageName : configPackages) { @@ -99,7 +99,7 @@ private List loadCondigs() throws Exception { private List loadServices() throws Exception { List services = null; - String[] configPackages = blade.config().getIocPackages(); + String[] configPackages = blade.applicationConfig().getIocPackages(); if (null != configPackages && configPackages.length > 0) { services = new ArrayList(20); for (String packageName : configPackages) { @@ -132,7 +132,7 @@ private List loadServices() throws Exception { private List loadControllers() { List controllers = null; - String[] routePackages = blade.config().getRoutePackages(); + String[] routePackages = blade.applicationConfig().getRoutePackages(); if (null != routePackages && routePackages.length > 0) { controllers = new ArrayList(); for (String packageName : routePackages) { @@ -146,7 +146,7 @@ private List loadControllers() { private List loadInterceptors() { List interceptors = null; - String interceptorPackage = blade.config().getInterceptorPackage(); + String interceptorPackage = blade.applicationConfig().getInterceptorPackage(); if (StringKit.isNotBlank(interceptorPackage)) { interceptors = new ArrayList(10); Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); diff --git a/blade-core/src/main/java/com/blade/kit/AsmKit.java b/blade-core/src/main/java/com/blade/kit/AsmKit.java index ddb94e92b..f1f0d0c3e 100644 --- a/blade-core/src/main/java/com/blade/kit/AsmKit.java +++ b/blade-core/src/main/java/com/blade/kit/AsmKit.java @@ -1,111 +1,129 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * ASM Tools - * - * @author biezhi - * @since 1.6.6 - */ -public final class AsmKit { - - /** - * - *

- * 比较参数类型是否一致 - *

- * - * @param types - * asm的类型({@link Type}) - * @param clazzes - * java 类型({@link Class}) - * @return - */ - private static boolean sameType(Type[] types, Class[] clazzes) { - // 个数不同 - if (types.length != clazzes.length) { - return false; - } - for (int i = 0; i < types.length; i++) { - if (!Type.getType(clazzes[i]).equals(types[i])) { - return false; - } - } - return true; - } - - /** - * - *

- * 获取方法的参数名 - *

- * - * @param m - * @return - */ - public static String[] getMethodParamNames(final Method m) throws IOException { - final String[] paramNames = new String[m.getParameterTypes().length]; - final String n = m.getDeclaringClass().getName(); - ClassReader cr = null; - try { - cr = new ClassReader(n); - } catch (IOException e) { - return null; - } - cr.accept(new ClassVisitor(Opcodes.ASM5) { - @Override - public MethodVisitor visitMethod(final int access, final String name, final String desc, - final String signature, final String[] exceptions) { - final Type[] args = Type.getArgumentTypes(desc); - // 方法名相同并且参数个数相同 - if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { - return super.visitMethod(access, name, desc, signature, exceptions); - } - MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); - return new MethodVisitor(Opcodes.ASM5, v) { - @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, - int index) { - int i = index - 1; - // 如果是静态方法,则第一就是参数 - // 如果不是静态方法,则第一个是"this",然后才是方法的参数 - if (Modifier.isStatic(m.getModifiers())) { - i = index; - } - if (i >= 0 && i < paramNames.length) { - paramNames[i] = name; - } - super.visitLocalVariable(name, desc, signature, start, end, index); - } - }; - } - }, 0); - return paramNames; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * ASM Tools + * + * @author biezhi + * @since 1.6.6 + */ +public final class AsmKit { + + /** + * + *

+ * 比较参数类型是否一致 + *

+ * + * @param types + * asm的类型({@link Type}) + * @param clazzes + * java 类型({@link Class}) + * @return + */ + private static boolean sameType(Type[] types, Class[] clazzes) { + // 个数不同 + if (types.length != clazzes.length) { + return false; + } + for (int i = 0; i < types.length; i++) { + if (!Type.getType(clazzes[i]).equals(types[i])) { + return false; + } + } + return true; + } + + /** + * + *

+ * 获取方法的参数名 + *

+ * + * @param m + * @return + */ + public static String[] getMethodParamNames(final Method m) throws IOException { + final String[] paramNames = new String[m.getParameterTypes().length]; + final String n = m.getDeclaringClass().getName(); + ClassReader cr = null; + try { + cr = new ClassReader(n); + } catch (IOException e) { + return null; + } + cr.accept(new ClassVisitor(Opcodes.ASM5) { + + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + super.visitInnerClass(name, outerName, innerName, access); + System.out.println("name = " + name); + System.out.println("outerName = " + outerName); + System.out.println("innerName = " + innerName); + System.out.println("access = " + access); + } + + @Override + public void visitOuterClass(String owner, String name, String desc) { + super.visitOuterClass(owner, name, desc); + System.out.println("owner = " + owner); + System.out.println("name = " + name); + System.out.println("desc = " + desc); + } + + @Override + public MethodVisitor visitMethod(final int access, final String name, final String desc, + final String signature, final String[] exceptions) { + final Type[] args = Type.getArgumentTypes(desc); + // 方法名相同并且参数个数相同 + if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { + return super.visitMethod(access, name, desc, signature, exceptions); + } + MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); + return new MethodVisitor(Opcodes.ASM5, v) { + @Override + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, + int index) { + int i = index - 1; + // 如果是静态方法,则第一就是参数 + // 如果不是静态方法,则第一个是"this",然后才是方法的参数 + if (Modifier.isStatic(m.getModifiers())) { + i = index; + } + if (i >= 0 && i < paramNames.length) { + paramNames[i] = name; + } + super.visitLocalVariable(name, desc, signature, start, end, index); + } + }; + } + }, 0); + return paramNames; + } + +} diff --git a/blade-core/src/main/java/com/blade/kit/DispatchKit.java b/blade-core/src/main/java/com/blade/kit/DispatchKit.java index be243c6bc..bde4582dc 100644 --- a/blade-core/src/main/java/com/blade/kit/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/kit/DispatchKit.java @@ -1,216 +1,212 @@ -package com.blade.kit; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLDecoder; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.kit.FileKit; -import com.blade.kit.IOKit; -import com.blade.kit.StreamKit; -import com.blade.kit.StringKit; -import com.blade.mvc.http.HttpException; -import com.blade.mvc.http.Response; -import com.blade.mvc.view.ViewSettings; - -import static com.blade.Blade.$; - -public class DispatchKit { - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatchKit.class); - - static final boolean isWeb = !$().enableServer(); - - static final Class appClass = $().config().getApplicationClass(); - - private static Boolean isDev = null; - - public static String getPath(Class clazz) { - URL url = clazz.getProtectionDomain().getCodeSource().getLocation(); - String filePath = null; - try { - filePath = URLDecoder.decode(url.getPath(), "utf-8"); - } catch (Exception e) { - e.printStackTrace(); - } - if (filePath.endsWith(".jar")) { - filePath = "jar:file:" + filePath + "!/"; - return filePath; - } - File file = new File(filePath); - filePath = file.getAbsolutePath(); - return filePath; - } - - public static String getWebRoot(ServletContext sc) { - if(isWeb){ - String dir = sc.getRealPath("/"); - if (dir == null) { - try { - URL url = sc.getResource("/"); - if (url != null && "file".equals(url.getProtocol())) { - dir = URLDecoder.decode(url.getFile(), "utf-8"); - } else { - throw new IllegalStateException("Can't get webroot dir, url = " + url); - } - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - return dir; - } - return getPath(appClass); - } - - public static void setNoCache(HttpServletResponse response) { - // Http 1.0 header - response.setHeader("Buffer", "false"); - response.setHeader("Pragma", "no-cache"); - response.setDateHeader("Expires", 1L); - // Http 1.1 header - response.setHeader("Cache-Control", "no-cache, no-store, max-age=0"); - } - - public static void setFileDownloadHeader(HttpServletResponse response, String fileName, String contentType) { - if (contentType == null) { - contentType = "application/x-download"; - } - response.setContentType(contentType); - // 中文文件名支持 - try { - String encodedfileName = new String(fileName.getBytes(), "ISO8859-1"); - response.setHeader("Content-Disposition", "attachment; filename=" + encodedfileName); - } catch (UnsupportedEncodingException e) { - } - } - - /** - * Print Error Message - * - * @param err - * @param code - * @param response - */ - public static void printError(Throwable err, int code, Response response) { - if (null == isDev) { - isDev = Blade.$().isDev(); - } - try { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final PrintWriter writer = new PrintWriter(baos); - - // If the developer mode, the error output to the page - if (isDev) { - writer.println(String.format(HTML, err.getClass() + " : " + err.getMessage())); - writer.println(); - err.printStackTrace(writer); - writer.println(END); - } else { - if (code == 404) { - String view404 = ViewSettings.$().getView404(); - if (StringKit.isNotBlank(view404)) { - response.render(view404); - return; - } else { - writer.write(err.getMessage()); - } - } else { - String view500 = ViewSettings.$().getView500(); - if (StringKit.isNotBlank(view500)) { - response.render(view500); - return; - } else { - writer.write(Const.INTERNAL_ERROR); - } - } - } - writer.close(); - response.status(code); - InputStream body = new ByteArrayInputStream(baos.toByteArray()); - print(body, response.writer()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Print - * - * @param body - * @param out - * @throws IOException - */ - public static void print(InputStream in, OutputStream out) throws IOException { - StreamKit.io(in, out); - } - - public static void print(InputStream body, PrintWriter writer) throws IOException { - print(IOKit.toString(body), writer); - } - - public static void print(String content, PrintWriter writer) throws IOException { - writer.print(content); - writer.flush(); - writer.close(); - } - - /** - * Print static file - * - * @param uri - * @param realpath - * @param httpResponse - */ - public static void printStatic(String uri, HttpServletRequest request, Response response) { - try { - String realpath = ""; - InputStream ins = null; - if (isWeb) { - realpath = request.getServletContext().getRealPath(uri); - File file = new File(realpath); - if (FileKit.exist(file)) { - ins = new FileInputStream(file); - } - } else { - ins = appClass.getResourceAsStream(uri); - } - - if (null != ins) { - print(ins, response.outputStream()); - } else { - LOGGER.debug("request realpath is [{}]", realpath); - HttpException httpException = new HttpException(404, uri + " not found"); - DispatchKit.printError(httpException, 404, response); - } - } catch (FileNotFoundException e) { - DispatchKit.printError(e, 404, response); - } catch (IOException e) { - DispatchKit.printError(e, 500, response); - } - } - - private static final String HTML = "Blade Error Page" - + "" - + "

%s

";
-
-	private static final String END = "
Blade-" + Const.BLADE_VERSION - + "(Blade Framework
"; - -} +package com.blade.kit; + +import static com.blade.Blade.$; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.mvc.http.HttpException; +import com.blade.mvc.http.Response; +import com.blade.mvc.view.ViewSettings; + +public class DispatchKit { + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatchKit.class); + + static final boolean isWeb = !$().enableServer(); + + static final Class appClass = $().applicationConfig().getApplicationClass(); + + private static Boolean isDev = null; + + public static String getPath(Class clazz) { + URL url = clazz.getProtectionDomain().getCodeSource().getLocation(); + String filePath = null; + try { + filePath = URLDecoder.decode(url.getPath(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } + if (filePath.endsWith(".jar")) { + filePath = "jar:file:" + filePath + "!/"; + return filePath; + } + File file = new File(filePath); + filePath = file.getAbsolutePath(); + return filePath; + } + + public static String getWebRoot(ServletContext sc) { + if(isWeb){ + String dir = sc.getRealPath("/"); + if (dir == null) { + try { + URL url = sc.getResource("/"); + if (url != null && "file".equals(url.getProtocol())) { + dir = URLDecoder.decode(url.getFile(), "utf-8"); + } else { + throw new IllegalStateException("Can't get webroot dir, url = " + url); + } + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + return dir; + } + return getPath(appClass); + } + + public static void setNoCache(HttpServletResponse response) { + // Http 1.0 header + response.setHeader("Buffer", "false"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 1L); + // Http 1.1 header + response.setHeader("Cache-Control", "no-cache, no-store, max-age=0"); + } + + public static void setFileDownloadHeader(HttpServletResponse response, String fileName, String contentType) { + if (contentType == null) { + contentType = "application/x-download"; + } + response.setContentType(contentType); + // 中文文件名支持 + try { + String encodedfileName = new String(fileName.getBytes(), "ISO8859-1"); + response.setHeader("Content-Disposition", "attachment; filename=" + encodedfileName); + } catch (UnsupportedEncodingException e) { + } + } + + /** + * Print Error Message + * + * @param err + * @param code + * @param response + */ + public static void printError(Throwable err, int code, Response response) { + if (null == isDev) { + isDev = Blade.$().isDev(); + } + try { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final PrintWriter writer = new PrintWriter(baos); + + // If the developer mode, the error output to the page + if (isDev) { + writer.println(String.format(HTML, err.getClass() + " : " + err.getMessage())); + writer.println(); + err.printStackTrace(writer); + writer.println(END); + } else { + if (code == 404) { + String view404 = ViewSettings.$().getView404(); + if (StringKit.isNotBlank(view404)) { + response.render(view404); + return; + } else { + writer.write(err.getMessage()); + } + } else { + String view500 = ViewSettings.$().getView500(); + if (StringKit.isNotBlank(view500)) { + response.render(view500); + return; + } else { + writer.write(Const.INTERNAL_ERROR); + } + } + } + writer.close(); + response.status(code); + InputStream body = new ByteArrayInputStream(baos.toByteArray()); + print(body, response.writer()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Print + * + * @param body + * @param out + * @throws IOException + */ + public static void print(InputStream in, OutputStream out) throws IOException { + StreamKit.io(in, out); + } + + public static void print(InputStream body, PrintWriter writer) throws IOException { + print(IOKit.toString(body), writer); + } + + public static void print(String content, PrintWriter writer) throws IOException { + writer.print(content); + writer.flush(); + writer.close(); + } + + /** + * Print static file + * + * @param uri + * @param realpath + * @param httpResponse + */ + public static void printStatic(String uri, HttpServletRequest request, Response response) { + try { + String realpath = ""; + InputStream ins = null; + if (isWeb) { + realpath = request.getServletContext().getRealPath(uri); + File file = new File(realpath); + if (FileKit.exist(file)) { + ins = new FileInputStream(file); + } + } else { + ins = appClass.getResourceAsStream(uri); + } + + if (null != ins) { + print(ins, response.outputStream()); + } else { + LOGGER.debug("request realpath is [{}]", realpath); + HttpException httpException = new HttpException(404, uri + " not found"); + DispatchKit.printError(httpException, 404, response); + } + } catch (FileNotFoundException e) { + DispatchKit.printError(e, 404, response); + } catch (IOException e) { + DispatchKit.printError(e, 500, response); + } + } + + private static final String HTML = "Blade Error Page" + + "" + + "

%s

";
+
+	private static final String END = "
Blade-" + Const.BLADE_VERSION + + "(Blade Framework
"; + +} diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java index f9a7e219a..733ea0855 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java @@ -117,7 +117,7 @@ public void init(Blade blade) { BannerStarter.printStart(); - String appName = blade.environment().getString("app.name", "Blade"); + String appName = blade.config().get("app.name", "Blade"); LOGGER.info("{} initialize successfully, Time elapsed: {} ms.", appName, System.currentTimeMillis() - initStart); } diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java index e65ad9933..6b5cd693a 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java @@ -68,8 +68,8 @@ public RouteBuilder(Routers routers) { */ public void building() { - this.routePackages = Blade.$().config().getRoutePackages(); - this.interceptorPackage = Blade.$().config().getInterceptorPackage(); + this.routePackages = Blade.$().applicationConfig().getRoutePackages(); + this.interceptorPackage = Blade.$().applicationConfig().getInterceptorPackage(); // Route if(null != routePackages && routePackages.length > 0){ diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index e5f13fb9f..4d1e96630 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -15,7 +15,7 @@ import org.slf4j.LoggerFactory; import com.blade.Const; -import com.blade.kit.Environment; +import com.blade.kit.base.Config; import com.blade.mvc.DispatcherServlet; public class EmbedJettyServer implements EmbedServer { @@ -28,12 +28,12 @@ public class EmbedJettyServer implements EmbedServer { private WebAppContext webAppContext; - private Environment environment = null; + private Config config = null; public EmbedJettyServer() { System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); $().loadAppConf("jetty.properties"); - environment = $().environment(); + config = $().config(); $().enableServer(true); } @@ -59,8 +59,8 @@ public void startup(int port, String contextPath, String webRoot) throws Excepti // Setup Threadpool QueuedThreadPool threadPool = new QueuedThreadPool(); - int minThreads = environment.getInt("server.jetty.min-threads", 100); - int maxThreads = environment.getInt("server.jetty.max-threads", 500); + int minThreads = config.getInt("server.jetty.min-threads", 100); + int maxThreads = config.getInt("server.jetty.max-threads", 500); threadPool.setMinThreads(minThreads); threadPool.setMaxThreads(maxThreads); @@ -74,10 +74,10 @@ public void startup(int port, String contextPath, String webRoot) throws Excepti webAppContext.setContextPath(contextPath); webAppContext.setResourceBase(""); - int securePort = environment.getInt("server.jetty.http.secure-port", 8443); - int outputBufferSize = environment.getInt("server.jetty.http.output-buffersize", 32768); - int requestHeaderSize = environment.getInt("server.jetty.http.request-headersize", 8192); - int responseHeaderSize = environment.getInt("server.jetty.http.response-headersize", 8192); + int securePort = config.getInt("server.jetty.http.secure-port", 8443); + int outputBufferSize = config.getInt("server.jetty.http.output-buffersize", 32768); + int requestHeaderSize = config.getInt("server.jetty.http.request-headersize", 8192); + int responseHeaderSize = config.getInt("server.jetty.http.response-headersize", 8192); // HTTP Configuration HttpConfiguration http_config = new HttpConfiguration(); @@ -88,7 +88,7 @@ public void startup(int port, String contextPath, String webRoot) throws Excepti http_config.setSendServerVersion(true); http_config.setSendDateHeader(false); - long idleTimeout = environment.getLong("server.jetty.http.idle-timeout", 30000L); + long idleTimeout = config.getLong("server.jetty.http.idle-timeout", 30000L); ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(http_config)); http.setPort(this.port); diff --git a/blade-kit/src/main/java/com/blade/kit/Environment.java b/blade-kit/src/main/java/com/blade/kit/Environment.java deleted file mode 100644 index 9870b776f..000000000 --- a/blade-kit/src/main/java/com/blade/kit/Environment.java +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Environment - * - * @author biezhi - * @since 1.0 - */ -public class Environment { - - private static final Logger LOGGER = LoggerFactory.getLogger(Environment.class); - - private Map envMap = new HashMap(20); - - public Environment() { - - } - - public Environment(String confPath){ - this.envMap = loadMap(confPath); - } - - private Map loadMap(String confPath){ - Map envMap = new HashMap(20); - Properties config = new Properties(); - - InputStreamReader inr = null; - try { - InputStream inputStream = Environment.class.getClassLoader().getResourceAsStream(confPath); - if(null != inputStream){ - inr = new InputStreamReader(inputStream, "UTF-8"); - config.load(inr); - // parse properties file - Set> set = config.entrySet(); - if(CollectionKit.isNotEmpty(set)){ - Iterator> it = set.iterator(); - while (it.hasNext()) { - Entry entry = it.next(); - String key = entry.getKey().toString(); - String value = entry.getValue().toString(); - String fuKey = getWildcard(value); - if(null != fuKey && null != config.get(fuKey)){ - String fuValue = config.get(fuKey).toString(); - value = value.replaceAll("\\$\\{" + fuKey + "\\}", fuValue); - } - envMap.put(key, value); - } - LOGGER.info("Load environment config [classpath:" + confPath + "]"); - } - } - } catch (IOException e) { - LOGGER.error("Load environment config error", e); - } finally { - IOKit.closeQuietly(inr); - } - return envMap; - } - - public static Environment load(String confPath) { - return new Environment(confPath); - } - - public Environment add(String confPath){ - this.envMap.putAll(loadMap(confPath)); - return this; - } - - private static String getWildcard(String str) { - if (null != str && str.indexOf("${") != -1) { - int start = str.indexOf("${"); - int end = str.indexOf("}"); - if (start != -1 && end != -1) { - return str.substring(start + 2, end); - } - } - return null; - } - - public Map getEnvMap(){ - return envMap; - } - - public String getString(String key) { - String value = envMap.get(key); - return null != value ? value.trim() : null; - } - - public String getString(String key, String defaultValue) { - return null != envMap.get(key) ? envMap.get(key) : defaultValue; - } - - public Integer getInt(String key) { - String value = getString(key); - if (StringKit.isNotBlank(value)) { - return Integer.valueOf(value); - } - return null; - } - - public Integer getInt(String key, Integer defaultValue) { - return null != getInt(key) ? getInt(key) : defaultValue; - } - - public Long getLong(String key) { - String value = getString(key); - if (StringKit.isNotBlank(value)) { - return Long.valueOf(value); - } - return null; - } - - public Long getLong(String key, Long defaultValue) { - return null != getLong(key) ? getLong(key) : defaultValue; - } - - public Boolean getBoolean(String key) { - String value = getString(key); - if (StringKit.isNotBlank(value)) { - return Boolean.valueOf(value); - } - return null; - } - - public Boolean getBoolean(String key, boolean defaultValue) { - return null != getBoolean(key) ? getBoolean(key) : defaultValue; - } - -} diff --git a/blade-kit/src/main/java/com/blade/kit/base/ConfigLoader.java b/blade-kit/src/main/java/com/blade/kit/base/Config.java similarity index 53% rename from blade-kit/src/main/java/com/blade/kit/base/ConfigLoader.java rename to blade-kit/src/main/java/com/blade/kit/base/Config.java index f9c778be9..7b1cdd15c 100644 --- a/blade-kit/src/main/java/com/blade/kit/base/ConfigLoader.java +++ b/blade-kit/src/main/java/com/blade/kit/base/Config.java @@ -1,154 +1,244 @@ -package com.blade.kit.base; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLDecoder; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import javax.servlet.ServletContext; - -import com.blade.kit.IOKit; - -public class ConfigLoader { - - private final Map config; - - public ConfigLoader() { - config = new HashMap(32); - } - - public ConfigLoader load(Properties props) { - for (String key : props.stringPropertyNames()) { - String value = props.getProperty(key); - config.put(key, value); - } - return this; - } - - public ConfigLoader load(Map map) { - config.putAll(map); - return this; - } - - /** - * 从文件路径或者classpath路径中载入配置. - * @param location - 配置文件路径 - * @return this - */ - public ConfigLoader load(String location) { - if (location.startsWith("classpath:")) { - location = location.substring("classpath:".length()); - return loadClasspath(location); - } else if (location.startsWith("file:")) { - location = location.substring("file:".length()); - return load(new File(location)); - } else { - return load(new File(location)); - } - } - - // 从 URL 载入 - public ConfigLoader load(URL url) { - String location = url.getPath(); - try { - location = URLDecoder.decode(location, "utf-8"); - } catch (UnsupportedEncodingException e) { - } - - try { - return loadInputStream(url.openStream(), location); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - // 从 classpath 下面载入 - private ConfigLoader loadClasspath(String classpath) { - if (classpath.startsWith("/")) { - classpath = classpath.substring(1); - } - InputStream is = getDefault().getResourceAsStream(classpath); - return loadInputStream(is, classpath); - } - - // 从 File 载入 - public ConfigLoader load(File file) { - try { - return loadInputStream(new FileInputStream(file), file.getName()); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - // 载入 web 资源文件 - public ConfigLoader load(String location, ServletContext sc) { - if (location.startsWith("classpath:") || location.startsWith("file:")) { - return load(location); - } else { - if (location.startsWith("webroot:")) { - location = location.substring("webroot:".length()); - } - if (!location.startsWith("/")) { - location = "/" + location; - } - InputStream is = sc.getResourceAsStream(location); - return loadInputStream(is, location); - } - } - - private ConfigLoader loadInputStream(InputStream is, String location) { - if (is == null) { - throw new IllegalStateException("InputStream not found: " + location); - } - - location = location.toLowerCase(); - try { - Properties config = new Properties(); - config.load(is); - load(config); - return this; - } catch (IOException e) { - throw new IllegalStateException(e); - } finally { - IOKit.closeQuietly(is); - } - } - - public ConfigLoader loadSystemProperties() { - return load(System.getProperties()); - } - - public ConfigLoader loadSystemEnvs() { - return load(System.getenv()); - } - - /** - * Returns current thread's context class loader - */ - public static ClassLoader getDefault() { - ClassLoader loader = null; - try { - loader = Thread.currentThread().getContextClassLoader(); - } catch (Exception e) { - } - if (loader == null) { - loader = ConfigLoader.class.getClassLoader(); - if (loader == null) { - try { - // getClassLoader() returning null indicates the bootstrap ClassLoader - loader = ClassLoader.getSystemClassLoader(); - } catch (Exception e) { - // Cannot access system ClassLoader - oh well, maybe the caller can live with null... - } - } - } - return loader; - } - -} +package com.blade.kit.base; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.ServletContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.IOKit; +import com.blade.kit.StringKit; + +public class Config { + + private static final Logger LOGGER = LoggerFactory.getLogger(Config.class); + + private final Map config; + + public Config() { + config = new HashMap(32); + } + + public Config load(Properties props) { + for (String key : props.stringPropertyNames()) { + String value = props.getProperty(key); + config.put(key, value); + } + return this; + } + + /*private String getWildcard(String str) { + if (null != str && str.indexOf("${") != -1) { + int start = str.indexOf("${"); + int end = str.indexOf("}"); + if (start != -1 && end != -1) { + return str.substring(start + 2, end); + } + } + return null; + }*/ + + public Config load(Map map) { + config.putAll(map); + return this; + } + + /** + * 从文件路径或者classpath路径中载入配置. + * @param location - 配置文件路径 + * @return this + */ + public static Config load(String location) { + return new Config().loadLoaction(location); + } + + private Config loadLoaction(String location){ + if (location.startsWith("classpath:")) { + location = location.substring("classpath:".length()); + return loadClasspath(location); + } else if (location.startsWith("file:")) { + location = location.substring("file:".length()); + return load(new File(location)); + } else { + return loadClasspath(location); + } + } + + public void add(String location){ + Config config = loadLoaction(location); + if(null != config){ + this.config.putAll(config.asMap()); + } + } + + // 从 URL 载入 + public Config load(URL url) { + String location = url.getPath(); + try { + location = URLDecoder.decode(location, "utf-8"); + } catch (UnsupportedEncodingException e) { + } + + try { + return loadInputStream(url.openStream(), location); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + // 从 classpath 下面载入 + private Config loadClasspath(String classpath) { + if (classpath.startsWith("/")) { + classpath = classpath.substring(1); + } + InputStream is = getDefault().getResourceAsStream(classpath); + LOGGER.info("Load config [classpath:" + classpath + "]"); + return loadInputStream(is, classpath); + } + + // 从 File 载入 + public Config load(File file) { + try { + LOGGER.info("Load config [file:" + file.getPath() + "]"); + return loadInputStream(new FileInputStream(file), file.getName()); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + // 载入 web 资源文件 + public Config load(String location, ServletContext sc) { + if (location.startsWith("classpath:") || location.startsWith("file:")) { + return load(location); + } else { + if (location.startsWith("webroot:")) { + location = location.substring("webroot:".length()); + } + if (!location.startsWith("/")) { + location = "/" + location; + } + InputStream is = sc.getResourceAsStream(location); + return loadInputStream(is, location); + } + } + + private Config loadInputStream(InputStream is, String location) { + if (is == null) { + throw new IllegalStateException("InputStream not found: " + location); + } + location = location.toLowerCase(); + try { + Properties config = new Properties(); + config.load(is); + load(config); + return this; + } catch (IOException e) { + throw new IllegalStateException(e); + } finally { + IOKit.closeQuietly(is); + } + } + + public Config loadSystemProperties() { + return load(System.getProperties()); + } + + public Config loadSystemEnvs() { + return load(System.getenv()); + } + + public Map asMap(){ + return this.config; + } + + /** + * Returns current thread's context class loader + */ + private static ClassLoader getDefault() { + ClassLoader loader = null; + try { + loader = Thread.currentThread().getContextClassLoader(); + } catch (Exception e) { + } + if (loader == null) { + loader = Config.class.getClassLoader(); + if (loader == null) { + try { + // getClassLoader() returning null indicates the bootstrap ClassLoader + loader = ClassLoader.getSystemClassLoader(); + } catch (Exception e) { + // Cannot access system ClassLoader - oh well, maybe the caller can live with null... + } + } + } + return loader; + } + + public String get(String key){ + return config.get(key); + } + + public String get(String key, String defaultValue) { + return null != config.get(key) ? config.get(key) : defaultValue; + } + + public Integer getInt(String key) { + String value = get(key); + if (StringKit.isNotBlank(value)) { + return Integer.valueOf(value); + } + return null; + } + + public Integer getInt(String key, Integer defaultValue) { + return null != getInt(key) ? getInt(key) : defaultValue; + } + + public Long getLong(String key) { + String value = get(key); + if (StringKit.isNotBlank(value)) { + return Long.valueOf(value); + } + return null; + } + + public Long getLong(String key, Long defaultValue) { + return null != getLong(key) ? getLong(key) : defaultValue; + } + + public Double getDouble(String key) { + String value = get(key); + if (StringKit.isNotBlank(value)) { + return Double.valueOf(value); + } + return null; + } + + public double getDouble(String key, double defaultValue) { + return null != getDouble(key) ? getDouble(key) : defaultValue; + } + + public Boolean getBoolean(String key) { + String value = get(key); + if (StringKit.isNotBlank(value)) { + return Boolean.valueOf(value); + } + return null; + } + + public Boolean getBoolean(String key, boolean defaultValue) { + return null != getBoolean(key) ? getBoolean(key) : defaultValue; + } + + +} diff --git a/blade-starter/pom.xml b/blade-starter/pom.xml index 75aa9d796..8fe7eac09 100644 --- a/blade-starter/pom.xml +++ b/blade-starter/pom.xml @@ -1,105 +1,109 @@ - - - - blade - com.bladejava - 1.0 - - - 4.0.0 - - blade-starter - pom - 0.0.1 - - - UTF-8 - - 1.6.6 - 1.0.0 - 0.1.2 - 0.0.6 - 0.0.4 - 0.0.4 - - - - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - - - - com.bladejava - blade-core - ${blade-core.version} - - - com.bladejava - blade-template-jetbrick - ${blade-template-jetbrick.version} - - - com.bladejava - blade-template-velocity - ${blade-template-velocity.version} - - - com.bladejava - blade-embed-jetty - ${blade-embed-jetty.version} - - - com.bladejava - blade-aop - ${blade-aop.version} - - - com.bladejava - blade-jdbc - ${blade-jdbc.version} - - - - - - - ${artifactId}-${version} - - - src/main/java - false - - - src/main/resources - false - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.2 - - 1.6 - 1.6 - UTF-8 - - - - - - + + + + blade + com.bladejava + 1.0 + + + 4.0.0 + + blade-starter + pom + 0.0.1 + + + UTF-8 + + 1.6.6 + 1.0.0 + 0.1.3-alpha + 1.0.4 + 0.0.6 + 0.0.4 + 0.0.4 + + + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + + com.bladejava + blade-core + ${blade-core.version} + + + com.bladejava + blade-template-jetbrick + ${blade-template-jetbrick.version} + + + com.bladejava + blade-template-velocity + ${blade-template-velocity.version} + + + com.bladejava + blade-embed-jetty + ${blade-embed-jetty.version} + + + com.bladejava + blade-aop + ${blade-aop.version} + + + com.bladejava + blade-jdbc + ${blade-jdbc.version} + + + com.bladejava + blade-patchca + ${blade-patchca.version} + + + + + + + + src/main/java + false + + + src/main/resources + false + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.2 + + 1.6 + 1.6 + UTF-8 + + + + + + \ No newline at end of file From 43c460b966bc281d24191f249ebf2548110b2e61 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 5 Sep 2016 22:07:35 +0800 Subject: [PATCH 499/545] =?UTF-8?q?=E2=9C=84=20code=20optimization?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/blade/config/ConfigLoader.java | 178 +-- .../com/blade/context/ApplicationContext.java | 117 +- .../java/com/blade/embedd/EmbedServer.java | 74 +- .../java/com/blade/ioc/IocApplication.java | 449 +++---- .../java/com/blade/mvc/DispatcherHandler.java | 411 +++--- .../mvc/http/wrapper/ServletRequest.java | 83 +- .../mvc/http/wrapper/ServletResponse.java | 675 +++++----- .../com/blade/mvc/route/RouteBuilder.java | 489 ++++--- .../com/blade/mvc/route/RouteMatcher.java | 32 +- .../java/com/blade/mvc/route/Routers.java | 385 +++--- .../loader/ClassPathControllerLoader.java | 7 +- .../blade/mvc/view/handle/MethodArgument.java | 4 +- .../com/blade/embedd/EmbedJettyServer.java | 242 ++-- .../main/java/com/blade/kit/StreamKit.java | 1130 ++++++++--------- 14 files changed, 2143 insertions(+), 2133 deletions(-) diff --git a/blade-core/src/main/java/com/blade/config/ConfigLoader.java b/blade-core/src/main/java/com/blade/config/ConfigLoader.java index 91652746e..69690522e 100644 --- a/blade-core/src/main/java/com/blade/config/ConfigLoader.java +++ b/blade-core/src/main/java/com/blade/config/ConfigLoader.java @@ -1,89 +1,89 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.lang.reflect.Modifier; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.context.DynamicContext; -import com.blade.exception.ConfigException; -import com.blade.ioc.Ioc; -import com.blade.ioc.annotation.Component; -import com.blade.kit.CollectionKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; - -/** - * ConfigLoader - * - * @author biezhi - * @since 1.6.6 - */ -public class ConfigLoader { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); - - private ClassReader classReader; - private Ioc ioc; - private ApplicationConfig applicationConfig; - - public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { - this.ioc = ioc; - this.classReader = DynamicContext.getClassReader(); - this.applicationConfig = applicationConfig; - } - - public void setIoc(Ioc ioc){ - this.ioc = ioc; - } - - @SuppressWarnings("unchecked") - public void loadConfig() { - String[] configPackages = Blade.$().applicationConfig().getConfigPackages(); - if (null != configPackages && configPackages.length > 0) { - // Scan package all class - try { - for (String packageName : configPackages) { - Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); - if (CollectionKit.isNotEmpty(classes)) { - for (ClassInfo classInfo : classes) { - boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); - if(hasInterface){ - addConfig((Class) classInfo.getClazz()); - } - } - } - } - } catch (ConfigException e) { - LOGGER.error("load config error", e); - } - } - } - - public void addConfig(Class clazz) throws ConfigException { - if (!Modifier.isAbstract(clazz.getModifiers())) { - Object bean = ioc.addBean(clazz); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(applicationConfig); - } - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.lang.reflect.Modifier; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.blade.Blade.$; +import com.blade.context.DynamicContext; +import com.blade.exception.ConfigException; +import com.blade.ioc.Ioc; +import com.blade.ioc.annotation.Component; +import com.blade.kit.CollectionKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; + +/** + * ConfigLoader + * + * @author biezhi + * @since 1.6.6 + */ +public class ConfigLoader { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); + + private ClassReader classReader; + private Ioc ioc; + private ApplicationConfig applicationConfig; + + public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { + this.ioc = ioc; + this.classReader = DynamicContext.getClassReader(); + this.applicationConfig = applicationConfig; + } + + public void setIoc(Ioc ioc){ + this.ioc = ioc; + } + + @SuppressWarnings("unchecked") + public void loadConfig() { + String[] configPackages = $().applicationConfig().getConfigPackages(); + if (null != configPackages && configPackages.length > 0) { + // Scan package all class + try { + for (String packageName : configPackages) { + Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); + if (CollectionKit.isNotEmpty(classes)) { + for (ClassInfo classInfo : classes) { + boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); + if(hasInterface){ + addConfig((Class) classInfo.getClazz()); + } + } + } + } + } catch (ConfigException e) { + LOGGER.error("load config error", e); + } + } + } + + public void addConfig(Class clazz) throws ConfigException { + if (!Modifier.isAbstract(clazz.getModifiers())) { + Object bean = ioc.addBean(clazz); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(applicationConfig); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/context/ApplicationContext.java b/blade-core/src/main/java/com/blade/context/ApplicationContext.java index 9787cb06a..3090e8a6a 100644 --- a/blade-core/src/main/java/com/blade/context/ApplicationContext.java +++ b/blade-core/src/main/java/com/blade/context/ApplicationContext.java @@ -1,58 +1,59 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.exception.BladeException; -import com.blade.ioc.IocApplication; - -/** - * Blade ApplicationContext, init context - * - * @author biezhi - * @since 1.6.6 - */ -public final class ApplicationContext { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContext.class); - - public static void init(Blade blade) throws BladeException{ - try { - - blade.bootstrap().init(blade); - - if(!blade.applicationConfig().isInit()){ - blade.loadAppConf(Const.APP_PROPERTIES); - blade.applicationConfig().setEnv(blade.config()); - } - - // initialization ioc - IocApplication iocApplication = new IocApplication(); - iocApplication.initBeans(); - - blade.init(); - blade.bootstrap().contextInitialized(); - } catch (Exception e) { - LOGGER.error("ApplicationContext init error", e); - } - - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.exception.BladeException; +import com.blade.ioc.IocApplication; + +/** + * Blade ApplicationContext, init context + * + * @author biezhi + * @since 1.6.6 + */ +public final class ApplicationContext { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContext.class); + + public static void init(Blade blade) throws BladeException{ + try { + if(!blade.isInit()){ + blade.bootstrap().init(blade); + + if(!blade.applicationConfig().isInit()){ + blade.loadAppConf(Const.APP_PROPERTIES); + blade.applicationConfig().setEnv(blade.config()); + } + + // initialization ioc + IocApplication iocApplication = new IocApplication(); + iocApplication.initBeans(); + + blade.init(); + blade.bootstrap().contextInitialized(); + } + } catch (Exception e) { + LOGGER.error("ApplicationContext init error", e); + } + + } + +} diff --git a/blade-core/src/main/java/com/blade/embedd/EmbedServer.java b/blade-core/src/main/java/com/blade/embedd/EmbedServer.java index 6439cf741..3aa4b8d19 100644 --- a/blade-core/src/main/java/com/blade/embedd/EmbedServer.java +++ b/blade-core/src/main/java/com/blade/embedd/EmbedServer.java @@ -1,36 +1,38 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.embedd; - -/** - * Jetty Server - * - * @author biezhi - * @since 1.6.6 - */ -public interface EmbedServer { - - void startup(int port) throws Exception; - - void startup(int port, String contextPath) throws Exception; - - void startup(int port, String contextPath, String webRoot) throws Exception; - - void stop() throws Exception; - - void setWebRoot(String webRoot); - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.embedd; + +import com.blade.exception.EmbedServerException; + +/** + * Jetty Server + * + * @author biezhi + * @since 1.6.6 + */ +public interface EmbedServer { + + void startup(int port) throws EmbedServerException; + + void startup(int port, String contextPath) throws EmbedServerException; + + void startup(int port, String contextPath, String webRoot) throws EmbedServerException; + + void stop() throws EmbedServerException; + + void setWebRoot(String webRoot); + +} diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 9c1551a6a..021724507 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -1,224 +1,227 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.comparator.OrderComparator; -import com.blade.config.BaseConfig; -import com.blade.context.DynamicContext; -import com.blade.ioc.annotation.Component; -import com.blade.ioc.annotation.Service; -import com.blade.kit.StringKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; -import com.blade.mvc.annotation.Controller; -import com.blade.mvc.annotation.Intercept; -import com.blade.mvc.annotation.RestController; -import com.blade.mvc.interceptor.Interceptor; -import com.blade.mvc.route.RouteBuilder; - -/** - * IOC container, used to initialize the IOC object - * - * @author biezhi - * @since 1.0 - */ -public class IocApplication { - - private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); - - private static List aopInterceptors = new ArrayList(); - - /** - * Class to read object, load class - */ - private ClassReader classReader = null; - private Blade blade; - private OrderComparator orderComparator; - - public IocApplication() { - this.blade = Blade.$(); - this.classReader = DynamicContext.getClassReader(); - this.orderComparator = new OrderComparator(); - } - - /** - * load config beans - * - * @return - * @throws Exception - */ - private List loadCondigs() throws Exception { - List configs = null; - String[] configPackages = blade.applicationConfig().getConfigPackages(); - if (null != configPackages && configPackages.length > 0) { - configs = new ArrayList(10); - for (String packageName : configPackages) { - Set configClasses = classReader.getClassByAnnotation(packageName, Component.class, false); - if (null != configClasses) { - for (ClassInfo classInfo : configClasses) { - Class[] interfaces = classInfo.getClazz().getInterfaces(); - for (Class in : interfaces) { - if (in.equals(BaseConfig.class)) { - configs.add(classInfo); - } - } - if (classInfo.getClazz().getSuperclass().getName() - .equals("com.blade.aop.AbstractMethodInterceptor")) { - aopInterceptors.add(classInfo.newInstance()); - } - } - } - } - Collections.sort(configs, orderComparator); - } - return configs; - } - - private List loadServices() throws Exception { - List services = null; - String[] configPackages = blade.applicationConfig().getIocPackages(); - if (null != configPackages && configPackages.length > 0) { - services = new ArrayList(20); - for (String packageName : configPackages) { - if (StringKit.isBlank(packageName)) { - continue; - } - // Recursive scan - boolean recursive = false; - if (packageName.endsWith(".*")) { - packageName = packageName.substring(0, packageName.length() - 2); - recursive = true; - } - - // Scan package all class - Set iocClasses = classReader.getClass(packageName, recursive); - for (ClassInfo classInfo : iocClasses) { - Class clazz = classInfo.getClazz(); - if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { - Component component = clazz.getAnnotation(Component.class); - Service service = clazz.getAnnotation(Service.class); - if (null != service || null != component) { - services.add(classInfo); - } - } - } - } - } - return services; - } - - private List loadControllers() { - List controllers = null; - String[] routePackages = blade.applicationConfig().getRoutePackages(); - if (null != routePackages && routePackages.length > 0) { - controllers = new ArrayList(); - for (String packageName : routePackages) { - // Scan all Controoler - controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); - controllers.addAll(classReader.getClassByAnnotation(packageName, RestController.class, true)); - } - } - return controllers; - } - - private List loadInterceptors() { - List interceptors = null; - String interceptorPackage = blade.applicationConfig().getInterceptorPackage(); - if (StringKit.isNotBlank(interceptorPackage)) { - interceptors = new ArrayList(10); - Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); - if (null != intes) { - for (ClassInfo classInfo : intes) { - if (null != classInfo.getClazz().getInterfaces() - && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)) { - interceptors.add(classInfo); - } - } - Collections.sort(interceptors, orderComparator); - } - } - return interceptors; - } - - public void initBeans() throws Exception { - List services = this.loadServices(); - List configs = this.loadCondigs(); - List controllers = this.loadControllers(); - // web - List inteceptors = this.loadInterceptors(); - - Ioc ioc = blade.ioc(); - - RouteBuilder routeBuilder = blade.routeBuilder(); - - // 1. init service - if (null != services) { - for (ClassInfo classInfo : services) { - ioc.addBean(classInfo.getClazz()); - } - } - - // 2. init configs - if (null != configs) { - for (ClassInfo classInfo : configs) { - Object bean = ioc.addBean(classInfo.getClazz()); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(blade.applicationConfig()); - } - } - - // 3. init controller - if (null != controllers) { - for (ClassInfo classInfo : controllers) { - ioc.addBean(classInfo.getClazz()); - routeBuilder.addRouter(classInfo.getClazz()); - } - } - - // 4. init interceptor - if (null != inteceptors) { - for (ClassInfo classInfo : inteceptors) { - ioc.addBean(classInfo.getClazz()); - routeBuilder.addInterceptor(classInfo.getClazz()); - } - } - - LOGGER.info("Add Object: {}", ioc.getBeans()); - - // injection - List beanDefines = ioc.getBeanDefines(); - if (null != beanDefines) { - for (BeanDefine beanDefine : beanDefines) { - IocKit.injection(ioc, beanDefine); - } - } - } - - public static List getAopInterceptors() { - return aopInterceptors; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.comparator.OrderComparator; +import com.blade.config.BaseConfig; +import com.blade.context.DynamicContext; +import com.blade.ioc.annotation.Component; +import com.blade.ioc.annotation.Service; +import com.blade.kit.StringKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.mvc.annotation.Controller; +import com.blade.mvc.annotation.Intercept; +import com.blade.mvc.annotation.RestController; +import com.blade.mvc.interceptor.Interceptor; +import com.blade.mvc.route.RouteBuilder; + +/** + * IOC container, used to initialize the IOC object + * + * @author biezhi + * @since 1.0 + */ +public class IocApplication { + + private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); + + /** + * aop interceptor + */ + private static List aopInterceptors = new ArrayList(8); + + /** + * Class to read object, load class + */ + private ClassReader classReader = null; + private Blade blade; + private OrderComparator orderComparator; + + public IocApplication() { + this.blade = Blade.$(); + this.classReader = DynamicContext.getClassReader(); + this.orderComparator = new OrderComparator(); + } + + /** + * load config beans + * + * @return + * @throws Exception + */ + private List loadCondigs() throws Exception { + List configs = null; + String[] configPackages = blade.applicationConfig().getConfigPackages(); + if (null != configPackages && configPackages.length > 0) { + configs = new ArrayList(10); + for (String packageName : configPackages) { + Set configClasses = classReader.getClassByAnnotation(packageName, Component.class, false); + if (null != configClasses) { + for (ClassInfo classInfo : configClasses) { + Class[] interfaces = classInfo.getClazz().getInterfaces(); + for (Class in : interfaces) { + if (in.equals(BaseConfig.class)) { + configs.add(classInfo); + } + } + if (classInfo.getClazz().getSuperclass().getName() + .equals("com.blade.aop.AbstractMethodInterceptor")) { + aopInterceptors.add(classInfo.newInstance()); + } + } + } + } + Collections.sort(configs, orderComparator); + } + return configs; + } + + private List loadServices() throws Exception { + List services = null; + String[] configPackages = blade.applicationConfig().getIocPackages(); + if (null != configPackages && configPackages.length > 0) { + services = new ArrayList(20); + for (String packageName : configPackages) { + if (StringKit.isBlank(packageName)) { + continue; + } + // Recursive scan + boolean recursive = false; + if (packageName.endsWith(".*")) { + packageName = packageName.substring(0, packageName.length() - 2); + recursive = true; + } + + // Scan package all class + Set iocClasses = classReader.getClass(packageName, recursive); + for (ClassInfo classInfo : iocClasses) { + Class clazz = classInfo.getClazz(); + if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { + Component component = clazz.getAnnotation(Component.class); + Service service = clazz.getAnnotation(Service.class); + if (null != service || null != component) { + services.add(classInfo); + } + } + } + } + } + return services; + } + + private List loadControllers() { + List controllers = null; + String[] routePackages = blade.applicationConfig().getRoutePackages(); + if (null != routePackages && routePackages.length > 0) { + controllers = new ArrayList(); + for (String packageName : routePackages) { + // Scan all Controoler + controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); + controllers.addAll(classReader.getClassByAnnotation(packageName, RestController.class, true)); + } + } + return controllers; + } + + private List loadInterceptors() { + List interceptors = null; + String interceptorPackage = blade.applicationConfig().getInterceptorPackage(); + if (StringKit.isNotBlank(interceptorPackage)) { + interceptors = new ArrayList(10); + Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); + if (null != intes) { + for (ClassInfo classInfo : intes) { + if (null != classInfo.getClazz().getInterfaces() + && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)) { + interceptors.add(classInfo); + } + } + Collections.sort(interceptors, orderComparator); + } + } + return interceptors; + } + + public void initBeans() throws Exception { + List services = this.loadServices(); + List configs = this.loadCondigs(); + List controllers = this.loadControllers(); + // web + List inteceptors = this.loadInterceptors(); + + Ioc ioc = blade.ioc(); + + RouteBuilder routeBuilder = blade.routeBuilder(); + + // 1. init service + if (null != services) { + for (ClassInfo classInfo : services) { + ioc.addBean(classInfo.getClazz()); + } + } + + // 2. init configs + if (null != configs) { + for (ClassInfo classInfo : configs) { + Object bean = ioc.addBean(classInfo.getClazz()); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(blade.applicationConfig()); + } + } + + // 3. init controller + if (null != controllers) { + for (ClassInfo classInfo : controllers) { + ioc.addBean(classInfo.getClazz()); + routeBuilder.addRouter(classInfo.getClazz()); + } + } + + // 4. init interceptor + if (null != inteceptors) { + for (ClassInfo classInfo : inteceptors) { + ioc.addBean(classInfo.getClazz()); + routeBuilder.addInterceptor(classInfo.getClazz()); + } + } + + LOGGER.info("Add Object: {}", ioc.getBeans()); + + // injection + List beanDefines = ioc.getBeanDefines(); + if (null != beanDefines) { + for (BeanDefine beanDefine : beanDefines) { + IocKit.injection(ioc, beanDefine); + } + } + } + + public static List getAopInterceptors() { + return aopInterceptors; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index 3668bacf8..42ea7149a 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -1,206 +1,207 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; - -import java.io.IOException; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.context.WebApplicationContext; -import com.blade.exception.BladeException; -import com.blade.ioc.Ioc; -import com.blade.kit.DispatchKit; -import com.blade.kit.StringKit; -import com.blade.mvc.http.HttpStatus; -import com.blade.mvc.http.Path; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.http.wrapper.ServletRequest; -import com.blade.mvc.http.wrapper.ServletResponse; -import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteHandler; -import com.blade.mvc.route.RouteMatcher; -import com.blade.mvc.route.Routers; -import com.blade.mvc.view.ModelAndView; -import com.blade.mvc.view.ViewSettings; -import com.blade.mvc.view.handle.RouteViewHandler; -import com.blade.mvc.view.template.TemplateException; - -/** - * Synchronous request processor - * - * @author biezhi - * @since 1.5 - */ -public class DispatcherHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); - - private Ioc ioc; - - private Blade blade; - - private ServletContext servletContext; - - private RouteMatcher routeMatcher; - - private StaticFileFilter staticFileFilter; - - private RouteViewHandler routeViewHandler; - - public DispatcherHandler(ServletContext servletContext, Routers routers) { - this.servletContext = servletContext; - this.blade = Blade.$(); - this.ioc = blade.ioc(); - this.routeMatcher = new RouteMatcher(routers); - this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); - this.routeViewHandler = new RouteViewHandler(this.ioc); - } - - public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ - - // http method, GET/POST ... - String method = httpRequest.getMethod(); - - // reuqest uri - String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - - // Create Response - Response response = new ServletResponse(httpResponse);; - - // If it is static, the resource is handed over to the filter - if(staticFileFilter.isStatic(uri)){ - LOGGER.debug("Request : {}\t{}", method, uri); - DispatchKit.printStatic(uri, httpRequest, response); - return; - } - - LOGGER.info("Request : {}\t{}", method, uri); - - try { - - Request request = new ServletRequest(httpRequest); - WebApplicationContext.init(servletContext, request, response); - Route route = routeMatcher.getRoute(method, uri); - if (null != route) { - request.setRoute(route); - - // before inteceptor - List befores = routeMatcher.getBefore(uri); - boolean result = invokeInterceptor(request, response, befores); - if(result){ - // execute - this.routeHandle(request, response, route); - if(!request.isAbort()){ - // after inteceptor - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - } - } - } else { - // Not found - render404(response, uri); - } - return; - } catch (TemplateException e) { - LOGGER.error("Template error", e); - DispatchKit.printError(e, 500, response); - } catch (BladeException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - }catch (Exception e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } - return; - } - - /** - * 404 view render - * - * @param response response object - * @param uri 404 uri - * @throws IOException - * @throws TemplateException - */ - private void render404(Response response, String uri) throws Exception { - String view404 = ViewSettings.$().getView404(); - if(StringKit.isNotBlank(view404)){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", uri); - response.render( modelAndView ); - } else { - response.status(HttpStatus.NOT_FOUND); - response.html(String.format(Const.VIEW_NOTFOUND, uri)); - } - } - - /** - * Methods to perform the interceptor - * - * @param request request object - * @param response response object - * @param interceptors execute the interceptor list - * @return Return execute is ok - */ - private boolean invokeInterceptor(Request request, Response response, List interceptors) throws Exception { - for(Route route : interceptors){ - boolean flag = routeViewHandler.intercept(request, response, route); - if(!flag){ - return false; - } - } - return true; - } - - /** - * Actual routing method execution - * - * @param request request object - * @param response response object - * @param route route object - */ - private void routeHandle(Request request, Response response, Route route) throws Exception{ - Object target = route.getTarget(); - if(null == target){ - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - request.initPathParams(route.getPath()); - - // Init context - WebApplicationContext.init(servletContext, request, response); - if(route.getTargetType() == RouteHandler.class){ - RouteHandler routeHandler = (RouteHandler) target; - routeHandler.handle(request, response); - } else { - routeViewHandler.handle(request, response, route); - } - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.context.WebApplicationContext; +import com.blade.exception.BladeException; +import com.blade.ioc.Ioc; +import com.blade.kit.DispatchKit; +import com.blade.kit.StringKit; +import com.blade.mvc.http.HttpStatus; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.http.wrapper.ServletRequest; +import com.blade.mvc.http.wrapper.ServletResponse; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteHandler; +import com.blade.mvc.route.RouteMatcher; +import com.blade.mvc.route.Routers; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; +import com.blade.mvc.view.handle.RouteViewHandler; +import com.blade.mvc.view.template.TemplateException; + +/** + * Synchronous request processor + * + * @author biezhi + * @since 1.5 + */ +public class DispatcherHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); + + private Ioc ioc; + + private Blade blade; + + private ServletContext servletContext; + + private RouteMatcher routeMatcher; + + private StaticFileFilter staticFileFilter; + + private RouteViewHandler routeViewHandler; + + public DispatcherHandler(ServletContext servletContext, Routers routers) { + this.servletContext = servletContext; + this.blade = Blade.$(); + this.ioc = blade.ioc(); + this.routeMatcher = new RouteMatcher(routers); + this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); + this.routeViewHandler = new RouteViewHandler(this.ioc); + } + + public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ + + // http method, GET/POST ... + String method = httpRequest.getMethod(); + + // reuqest uri + String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); + + // Create Response + Response response = new ServletResponse(httpResponse);; + + // If it is static, the resource is handed over to the filter + if(staticFileFilter.isStatic(uri)){ + LOGGER.debug("Request : {}\t{}", method, uri); + DispatchKit.printStatic(uri, httpRequest, response); + return; + } + + try { + + LOGGER.info("Request : {}\t{}", method, uri); + + Request request = new ServletRequest(httpRequest); + WebApplicationContext.init(servletContext, request, response); + Route route = routeMatcher.getRoute(method, uri); + if (null != route) { + request.setRoute(route); + + // before inteceptor + List befores = routeMatcher.getBefore(uri); + boolean result = invokeInterceptor(request, response, befores); + if(result){ + // execute + this.routeHandle(request, response, route); + if(!request.isAbort()){ + // after inteceptor + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + } + } + } else { + // Not found + render404(response, uri); + } + return; + } catch (TemplateException e) { + LOGGER.error("Template error", e); + DispatchKit.printError(e, 500, response); + } catch (BladeException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + }catch (Exception e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } + return; + } + + /** + * 404 view render + * + * @param response response object + * @param uri 404 uri + * @throws IOException + * @throws TemplateException + */ + private void render404(Response response, String uri) throws Exception { + String view404 = ViewSettings.$().getView404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(Const.VIEW_NOTFOUND, uri)); + } + } + + /** + * Methods to perform the interceptor + * + * @param request request object + * @param response response object + * @param interceptors execute the interceptor list + * @return Return execute is ok + */ + private boolean invokeInterceptor(Request request, Response response, List interceptors) throws Exception { + for (int i = 0, len = interceptors.size(); i < len; i++) { + Route route = interceptors.get(i); + boolean flag = routeViewHandler.intercept(request, response, route); + if (!flag) { + return false; + } + } + return true; + } + + /** + * Actual routing method execution + * + * @param request request object + * @param response response object + * @param route route object + */ + private void routeHandle(Request request, Response response, Route route) throws Exception{ + Object target = route.getTarget(); + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + request.initPathParams(route.getPath()); + + // Init context + WebApplicationContext.init(servletContext, request, response); + if(route.getTargetType() == RouteHandler.class){ + RouteHandler routeHandler = (RouteHandler) target; + routeHandler.handle(request, response); + } else { + routeViewHandler.handle(request, response, route); + } + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java index 556179fa4..1193515e4 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java @@ -37,6 +37,9 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.blade.kit.IOKit; import com.blade.kit.ObjectKit; import com.blade.kit.StringKit; @@ -57,15 +60,19 @@ */ public class ServletRequest implements Request { + private static final Logger LOGGER = LoggerFactory.getLogger(ServletRequest.class); + private static final String USER_AGENT = "user-agent"; protected Route route; private HttpServletRequest request; - protected Map pathParams = null; + // path parameter eg: /user/12 + private Map pathParams = null; - private Map multipartParams = null; + // query parameter eg: /user?name=jack + private Map queryParams = null; private List files = null; @@ -75,47 +82,43 @@ public class ServletRequest implements Request { public ServletRequest(HttpServletRequest request) throws MultipartException, IOException { this.request = request; - this.pathParams = new HashMap(); - this.multipartParams = new HashMap(); - this.files = new ArrayList(); - init(); + this.pathParams = new HashMap(8); + this.queryParams = new HashMap(16); + this.files = new ArrayList(8); + this.init(); } - public ServletRequest init() throws IOException, MultipartException { + public void init() throws IOException, MultipartException { // retrieve multipart/form-data parameters if (Multipart.isMultipartContent(request)) { Multipart multipart = new Multipart(); multipart.parse(request, new MultipartHandler() { - @Override public void handleFormItem(String name, String value) { - multipartParams.put( name, value ); + queryParams.put( name, value ); } - @Override public void handleFileItem(String name, FileItem fileItem) { files.add(fileItem); } - }); } - return this; } private String join(String[] arr) { - String ret = ""; + StringBuffer ret = new StringBuffer(); for (String item : arr) { - ret += "," + item; + ret.append(',').append(item); } if (ret.length() > 0) { - ret = ret.substring(1); + return ret.substring(1); } - return ret; + return ret.toString(); } @Override public void initPathParams(String routePath) { - pathParams.clear(); + this.pathParams.clear(); List variables = getPathParam(routePath); String regexPath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); @@ -128,13 +131,13 @@ public void initPathParams(String routePath) { // start index at 1 as group(0) always stands for the entire expression for (int i=1, len = variables.size(); i <= len; i++) { String value = matcher.group(i); - pathParams.put(variables.get(i-1), value); + this.pathParams.put(variables.get(i-1), value); } } } private List getPathParam(String routePath) { - List variables = new ArrayList(); + List variables = new ArrayList(8); Matcher matcher = Pattern.compile(Path.VAR_REGEXP).matcher(routePath); while (matcher.find()) { variables.add(matcher.group(1)); @@ -251,7 +254,7 @@ public Map querys() { for (Map.Entry entry : requestParams.entrySet()) { params.put( entry.getKey(), join(entry.getValue()) ); } - params.putAll(multipartParams); + params.putAll(queryParams); return Collections.unmodifiableMap(params); } @@ -262,7 +265,7 @@ public String query(String name) { if (param != null) { val = join(param); } else { - val = multipartParams.get(name); + val = queryParams.get(name); } return val; } @@ -274,7 +277,7 @@ public String query(String name, String defaultValue) { if (param != null) { val = join(param); } else { - val = multipartParams.get(name); + val = queryParams.get(name); } if(null == val){ val = defaultValue; @@ -384,7 +387,7 @@ public T attribute(String name) { @Override public Set attributes() { - Set attrList = new HashSet(); + Set attrList = new HashSet(8); Enumeration attributes = (Enumeration) request.getAttributeNames(); while (attributes.hasMoreElements()) { attrList.add(attributes.nextElement()); @@ -409,21 +412,19 @@ public boolean isSecure() { @Override public boolean isAjax() { - if (request.getHeader("x-requested-with") == null) { + if (null == header("x-requested-with")) { return false; } - return "XMLHttpRequest".equals(request.getHeader("x-requested-with")); + return "XMLHttpRequest".equals(header("x-requested-with")); } @Override public Map cookies() { javax.servlet.http.Cookie[] servletCookies = request.getCookies(); - - Map cookies = new HashMap(); + Map cookies = new HashMap(8); for (javax.servlet.http.Cookie c : servletCookies) { cookies.put( c.getName(), map(c) ); } - return Collections.unmodifiableMap(cookies); } @@ -455,11 +456,9 @@ public String cookie(String name) { @Override public Cookie cookieRaw(String name) { javax.servlet.http.Cookie[] servletCookies = request.getCookies(); - if (servletCookies == null) { return null; } - for (javax.servlet.http.Cookie c : servletCookies) { if (c.getName().equals(name)) { return map(c); @@ -471,7 +470,7 @@ public Cookie cookieRaw(String name) { @Override public Map headers() { Enumeration servletHeaders = request.getHeaderNames(); - Map headers = new HashMap(); + Map headers = new HashMap(16); while(servletHeaders.hasMoreElements()) { String headerName = servletHeaders.nextElement(); headers.put(headerName, request.getHeader(headerName)); @@ -489,7 +488,7 @@ public void encoding(String encoding) { try { request.setCharacterEncoding(encoding); } catch (UnsupportedEncodingException e) { - e.printStackTrace(); + LOGGER.error(e.getMessage(), e); } } @@ -525,7 +524,7 @@ public T model(String slug, Class clazz) { @Override public FileItem[] files() { FileItem[] fileParts = new FileItem[files.size()]; - for (int i=0; i < files.size(); i++) { + for (int i=0, len=files.size(); i < len; i++) { fileParts[i] = files.get(i); } return fileParts; @@ -540,26 +539,24 @@ public String asString() { BufferedReader reader = new BufferedReader( new InputStreamReader(request.getInputStream()) ); StringBuilder sb = new StringBuilder(); String line = reader.readLine(); - while (line != null) { - sb.append(line + "\n"); + while (null != line) { + sb.append(line + "\r\n"); line = reader.readLine(); } reader.close(); - String data = sb.toString(); - - return data; + return sb.toString(); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e.getMessage(), e); } return null; } - + @Override public InputStream asInputStream() { try { return request.getInputStream(); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e.getMessage(), e); } return null; } @@ -569,11 +566,11 @@ public byte[] asByte() { try { return IOKit.toByteArray(request.getInputStream()); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(e.getMessage(), e); } return null; } }; } - + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java index 817fc34f5..e5e2be723 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java @@ -1,340 +1,335 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http.wrapper; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.context.WebApplicationContext; -import com.blade.kit.Assert; -import com.blade.kit.DispatchKit; -import com.blade.mvc.http.HttpStatus; -import com.blade.mvc.http.Path; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.view.ModelAndView; -import com.blade.mvc.view.ViewSettings; -import com.blade.mvc.view.parser.JSONParser; -import com.blade.mvc.view.template.TemplateEngine; -import com.blade.mvc.view.template.TemplateException; - -/** - * ServletResponse - * - * @author biezhi - * @since 1.5 - */ -public class ServletResponse implements Response { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServletResponse.class); - - private HttpServletResponse response; - - private boolean written = false; - - private ViewSettings viewSettings; - - private TemplateEngine templateEngine; - - private JSONParser jsonParser; - - public ServletResponse(HttpServletResponse response) { - this.response = response; - this.viewSettings = ViewSettings.$(); - this.templateEngine = viewSettings.templateEngine(); - this.jsonParser = viewSettings.JSONParser(); - } - - @Override - public HttpServletResponse raw() { - return response; - } - - @Override - public int status() { - return response.getStatus(); - } - - @Override - public Response status(int status) { - response.setStatus(status); - return this; - } - - @Override - public Response badRequest() { - response.setStatus(HttpStatus.BAD_REQUEST); - return this; - } - - @Override - public Response unauthorized() { - response.setStatus(HttpStatus.UNAUTHORIZED); - return this; - } - - @Override - public Response notFound() { - response.setStatus(HttpStatus.NOT_FOUND); - return this; - } - - @Override - public Response conflict() { - response.setStatus(HttpStatus.CONFLICT); - return this; - } - - @Override - public String contentType() { - return response.getContentType(); - } - - @Override - public Response contentType(String contentType) { - response.setContentType(contentType); - return this; - } - - @Override - public String header(String name) { - return response.getHeader(name); - } - - @Override - public Response header(String name, String value) { - response.setHeader(name, value); - return this; - } - - @Override - public Response cookie(Cookie cookie) { - response.addCookie(cookie); - return this; - } - - @Override - public Response cookie(String name, String value) { - return cookie(name, value); - } - - @Override - public Response cookie(String name, String value, int maxAge) { - return cookie(name, value, maxAge, false); - } - - @Override - public Response cookie(String name, String value, int maxAge, boolean secured) { - return cookie(null, name, value, maxAge, secured); - } - - @Override - public Response cookie(String path, String name, String value, int maxAge, boolean secured) { - Cookie cookie = new Cookie(name, value); - if(null != path){ - cookie.setPath(path); - } - cookie.setMaxAge(maxAge); - cookie.setSecure(secured); - response.addCookie(cookie); - return this; - } - - @Override - public Response removeCookie(Cookie cookie) { - cookie.setMaxAge(0); - response.addCookie(map(cookie)); - return this; - } - - javax.servlet.http.Cookie map(Cookie cookie) { - javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); - servletCookie.setMaxAge(cookie.getMaxAge()); - if (cookie.getPath() != null) { - servletCookie.setPath(cookie.getPath()); - } - if (cookie.getDomain() != null) { - servletCookie.setDomain(cookie.getDomain()); - } - servletCookie.setHttpOnly(cookie.isHttpOnly()); - servletCookie.setSecure(cookie.getSecure()); - return servletCookie; - } - - @Override - public Response removeCookie(String name) { - Cookie cookie = new Cookie(name, ""); - cookie.setMaxAge(0); - response.addCookie(cookie); - return this; - } - - @Override - public Response text(String text) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/plain;charset=utf-8"); - DispatchKit.print(text, response.getWriter()); - this.written = true; - return this; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Response html(String html) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/html;charset=utf-8"); - - PrintWriter writer = response.getWriter(); - DispatchKit.print(html, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public Response json(String json) { - Request request = WebApplicationContext.request(); - String userAgent = request.userAgent(); - if (userAgent.contains("MSIE")) { - response.setContentType("text/html;charset=utf-8"); - } else { - response.setContentType("application/json;charset=utf-8"); - } - try { - response.setHeader("Cache-Control", "no-cache"); - PrintWriter writer = response.getWriter(); - DispatchKit.print(json, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public Response json(Object bean) { - return this.json(jsonParser.toJSONSting(bean)); - } - - @Override - public Response xml(String xml) { - try { - response.setHeader("Cache-Control", "no-cache"); - response.setContentType("text/xml;charset=utf-8"); - PrintWriter writer = response.getWriter(); - DispatchKit.print(xml, writer); - this.written = true; - return this; - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public ServletOutputStream outputStream() throws IOException { - return response.getOutputStream(); - } - - @Override - public PrintWriter writer() throws IOException { - return response.getWriter(); - } - - @Override - public Response render(String view){ - Assert.notBlank(view, "view not is null"); - - String viewPath = Path.cleanPath(view); - ModelAndView modelAndView = new ModelAndView(viewPath); - try { - templateEngine.render(modelAndView, response.getWriter()); - } catch (TemplateException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return this; - } - - @Override - public Response render(ModelAndView modelAndView) { - Assert.notNull(modelAndView, "ModelAndView not is null!"); - Assert.notBlank(modelAndView.getView(), "view not is null"); - - String viewPath = Path.cleanPath(modelAndView.getView()); - modelAndView.setView(viewPath); - try { - templateEngine.render(modelAndView, response.getWriter()); - } catch (TemplateException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return this; - } - - @Override - public void redirect(String path) { - try { - response.sendRedirect(path); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void go(String path) { - try { - String ctx = WebApplicationContext.servletContext().getContextPath(); - String location = Path.fixPath(ctx + path); - response.sendRedirect(location); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public boolean isWritten() { - return written; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http.wrapper; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.WebApplicationContext; +import com.blade.kit.Assert; +import com.blade.kit.DispatchKit; +import com.blade.mvc.http.HttpStatus; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; +import com.blade.mvc.view.parser.JSONParser; +import com.blade.mvc.view.template.TemplateEngine; +import com.blade.mvc.view.template.TemplateException; + +/** + * ServletResponse + * + * @author biezhi + * @since 1.5 + */ +public class ServletResponse implements Response { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServletResponse.class); + + private HttpServletResponse response; + + private boolean written = false; + + private ViewSettings viewSettings; + + private TemplateEngine templateEngine; + + private JSONParser jsonParser; + + public ServletResponse(HttpServletResponse response) { + this.response = response; + this.viewSettings = ViewSettings.$(); + this.templateEngine = viewSettings.templateEngine(); + this.jsonParser = viewSettings.JSONParser(); + } + + @Override + public HttpServletResponse raw() { + return response; + } + + @Override + public int status() { + return response.getStatus(); + } + + @Override + public Response status(int status) { + response.setStatus(status); + return this; + } + + @Override + public Response badRequest() { + response.setStatus(HttpStatus.BAD_REQUEST); + return this; + } + + @Override + public Response unauthorized() { + response.setStatus(HttpStatus.UNAUTHORIZED); + return this; + } + + @Override + public Response notFound() { + response.setStatus(HttpStatus.NOT_FOUND); + return this; + } + + @Override + public Response conflict() { + response.setStatus(HttpStatus.CONFLICT); + return this; + } + + @Override + public String contentType() { + return response.getContentType(); + } + + @Override + public Response contentType(String contentType) { + response.setContentType(contentType); + return this; + } + + @Override + public String header(String name) { + return response.getHeader(name); + } + + @Override + public Response header(String name, String value) { + response.setHeader(name, value); + return this; + } + + @Override + public Response cookie(Cookie cookie) { + response.addCookie(cookie); + return this; + } + + @Override + public Response cookie(String name, String value) { + return cookie(name, value); + } + + @Override + public Response cookie(String name, String value, int maxAge) { + return cookie(name, value, maxAge, false); + } + + @Override + public Response cookie(String name, String value, int maxAge, boolean secured) { + return cookie(null, name, value, maxAge, secured); + } + + @Override + public Response cookie(String path, String name, String value, int maxAge, boolean secured) { + Cookie cookie = new Cookie(name, value); + if(null != path){ + cookie.setPath(path); + } + cookie.setMaxAge(maxAge); + cookie.setSecure(secured); + response.addCookie(cookie); + return this; + } + + @Override + public Response removeCookie(Cookie cookie) { + cookie.setMaxAge(0); + response.addCookie(map(cookie)); + return this; + } + + javax.servlet.http.Cookie map(Cookie cookie) { + javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); + servletCookie.setMaxAge(cookie.getMaxAge()); + if (null != cookie.getPath()) { + servletCookie.setPath(cookie.getPath()); + } + if (null != cookie.getDomain()) { + servletCookie.setDomain(cookie.getDomain()); + } + servletCookie.setHttpOnly(cookie.isHttpOnly()); + servletCookie.setSecure(cookie.getSecure()); + return servletCookie; + } + + @Override + public Response removeCookie(String name) { + Cookie cookie = new Cookie(name, ""); + cookie.setMaxAge(0); + response.addCookie(cookie); + return this; + } + + @Override + public Response text(String text) { + try { + this.header("Cache-Control", "no-cache"); + this.contentType("text/plain;charset=utf-8"); + DispatchKit.print(text, response.getWriter()); + this.written = true; + return this; + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + @Override + public Response html(String html) { + try { + this.header("Cache-Control", "no-cache"); + this.contentType("text/html;charset=utf-8"); + + DispatchKit.print(html, response.getWriter()); + this.written = true; + return this; + } catch (UnsupportedEncodingException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + @Override + public Response json(String json) { + Request request = WebApplicationContext.request(); + String userAgent = request.userAgent(); + if (userAgent.contains("MSIE")) { + this.contentType("text/html;charset=utf-8"); + } else { + this.contentType("application/json;charset=utf-8"); + } + try { + this.header("Cache-Control", "no-cache"); + DispatchKit.print(json, response.getWriter()); + this.written = true; + return this; + } catch (UnsupportedEncodingException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + @Override + public Response json(Object bean) { + return this.json(jsonParser.toJSONSting(bean)); + } + + @Override + public Response xml(String xml) { + try { + this.header("Cache-Control", "no-cache"); + this.contentType("text/xml;charset=utf-8"); + DispatchKit.print(xml, response.getWriter()); + this.written = true; + return this; + } catch (UnsupportedEncodingException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + @Override + public ServletOutputStream outputStream() throws IOException { + return response.getOutputStream(); + } + + @Override + public PrintWriter writer() throws IOException { + return response.getWriter(); + } + + @Override + public Response render(String view){ + Assert.notBlank(view, "view not is null"); + + String viewPath = Path.cleanPath(view); + ModelAndView modelAndView = new ModelAndView(viewPath); + try { + templateEngine.render(modelAndView, response.getWriter()); + } catch (TemplateException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return this; + } + + @Override + public Response render(ModelAndView modelAndView) { + Assert.notNull(modelAndView, "ModelAndView not is null!"); + Assert.notBlank(modelAndView.getView(), "view not is null"); + + String viewPath = Path.cleanPath(modelAndView.getView()); + modelAndView.setView(viewPath); + try { + templateEngine.render(modelAndView, response.getWriter()); + } catch (TemplateException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return this; + } + + @Override + public void redirect(String path) { + try { + response.sendRedirect(path); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + } + + @Override + public void go(String path) { + try { + String ctx = WebApplicationContext.servletContext().getContextPath(); + String location = Path.fixPath(ctx + path); + response.sendRedirect(location); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + } + + @Override + public boolean isWritten() { + return written; + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java index 6b5cd693a..00597f3c8 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java @@ -1,247 +1,244 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.route; - -import java.lang.reflect.Method; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.context.DynamicContext; -import com.blade.kit.CollectionKit; -import com.blade.kit.StringKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; -import com.blade.mvc.annotation.Controller; -import com.blade.mvc.annotation.Intercept; -import com.blade.mvc.annotation.RestController; -import com.blade.mvc.annotation.Route; -import com.blade.mvc.http.HttpMethod; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.interceptor.Interceptor; - -/** - * Route builder - * - * @author biezhi - * @since 1.5 - */ -public class RouteBuilder { - - private static final Logger LOGGER = LoggerFactory.getLogger(RouteBuilder.class); - - /** - * Class reader, used to scan the class specified in the rules - */ - private ClassReader classReader; - - private Routers routers; - - private String[] routePackages; - - private String interceptorPackage; - - public RouteBuilder(Routers routers) { - this.routers = routers; - this.classReader = DynamicContext.getClassReader(); - } - - /** - * Start building route - */ - public void building() { - - this.routePackages = Blade.$().applicationConfig().getRoutePackages(); - this.interceptorPackage = Blade.$().applicationConfig().getInterceptorPackage(); - - // Route - if(null != routePackages && routePackages.length > 0){ - this.buildRoute(routePackages); - } - - // Inteceptor - if(StringKit.isNotBlank(interceptorPackage)){ - this.buildInterceptor(interceptorPackage); - } - - } - - /** - * Build interceptor - * - * @param interceptorPackages add the interceptor package - */ - private void buildInterceptor(String... interceptorPackages){ - - // Scan all Interceptor - Set classes = null; - - // Traversal Interceptor - for(String packageName : interceptorPackages){ - - // Scan all Interceptor - classes = classReader.getClass(packageName, Interceptor.class, false); - if(CollectionKit.isNotEmpty(classes)){ - for(ClassInfo classInfo : classes){ - Class interceptorClazz = classInfo.getClazz(); - addInterceptor(interceptorClazz); - } - } - } - } - - /** - * Build Route - * - * @param routePackages route packets to add - */ - private void buildRoute(String... routePackages){ - Set classes = null; - // Traverse route - for(String packageName : routePackages){ - // Scan all Controoler - classes = classReader.getClassByAnnotation(packageName, Controller.class, true); - if(CollectionKit.isNotEmpty(classes)){ - for(ClassInfo classInfo : classes){ - Class pathClazz = classInfo.getClazz(); - addRouter(pathClazz); - } - } - } - - } - - /** - * Parse Interceptor - * - * @param interceptor resolve the interceptor class - */ - public void addInterceptor(final Class interceptor){ - - boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); - - if(null == interceptor || !hasInterface){ - return; - } - - Intercept intercept = interceptor.getAnnotation(Intercept.class); - String partten = "/.*"; - if(null != intercept){ - partten = intercept.value(); - } - - try { - Method before = interceptor.getMethod("before", Request.class, Response.class); - Method after = interceptor.getMethod("after", Request.class, Response.class); - buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); - buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - - } - - /** - * Parse all routing in a controller - * - * @param controller resolve the routing class - */ - public void addRouter(final Class router){ - - Method[] methods = router.getMethods(); - if(null == methods || methods.length == 0){ - return; - } - String nameSpace = null, suffix = null; - - if(null != router.getAnnotation(Controller.class)){ - nameSpace = router.getAnnotation(Controller.class).value(); - suffix = router.getAnnotation(Controller.class).suffix(); - } - - if(null != router.getAnnotation(RestController.class)){ - nameSpace = router.getAnnotation(RestController.class).value(); - suffix = router.getAnnotation(RestController.class).suffix(); - } - - if(null == nameSpace && null == suffix){ - LOGGER.warn("Route [{}] not controller annotation", router.getName()); - return; - } - - for (Method method : methods) { - Route mapping = method.getAnnotation(Route.class); - //route method - if (null != mapping) { - // build multiple route - HttpMethod methodType = mapping.method(); - String[] paths = mapping.value(); - if(null != paths && paths.length > 0){ - for(String value : paths){ - String pathV = getRoutePath(value, nameSpace, suffix); - buildRoute(router, method, pathV, methodType); - } - } - } - } - } - - private String getRoutePath(String value, String nameSpace, String suffix){ - String path = value.startsWith("/") ? value : "/" + value; - - nameSpace = nameSpace.startsWith("/") ? nameSpace : "/" + nameSpace; - path = nameSpace + path; - - path = path.replaceAll("[/]+", "/"); - - path = path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - - path = path + suffix; - - return path; - } - - /** - * Build a route - * - * @param target route target execution class - * @param execMethod route execution method - * @param path route path - * @param method route httpmethod - */ - private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - - /** - * Build a route - * - * @param path route path - * @param target route target execution class - * @param execMethod route execution method - * @param method route httpmethod - */ - private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.route; + +import java.lang.reflect.Method; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.context.DynamicContext; +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.mvc.annotation.Controller; +import com.blade.mvc.annotation.Intercept; +import com.blade.mvc.annotation.RestController; +import com.blade.mvc.annotation.Route; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.interceptor.Interceptor; + +/** + * Route builder + * + * @author biezhi + * @since 1.5 + */ +public class RouteBuilder { + + private static final Logger LOGGER = LoggerFactory.getLogger(RouteBuilder.class); + + /** + * Class reader, used to scan the class specified in the rules + */ + private ClassReader classReader; + + private Routers routers; + + private String[] routePackages; + + private String interceptorPackage; + + public RouteBuilder(Routers routers) { + this.routers = routers; + this.classReader = DynamicContext.getClassReader(); + } + + /** + * Start building route + */ + public void building() { + + this.routePackages = Blade.$().applicationConfig().getRoutePackages(); + this.interceptorPackage = Blade.$().applicationConfig().getInterceptorPackage(); + + // Route + if(null != routePackages && routePackages.length > 0){ + this.buildRoute(routePackages); + } + + // Inteceptor + if(StringKit.isNotBlank(interceptorPackage)){ + this.buildInterceptor(interceptorPackage); + } + + } + + /** + * Build interceptor + * + * @param interceptorPackages add the interceptor package + */ + private void buildInterceptor(String... interceptorPackages){ + + // Scan all Interceptor + Set classes = null; + + // Traversal Interceptor + for(int i=0, len=interceptorPackages.length; i interceptorClazz = classInfo.getClazz(); + addInterceptor(interceptorClazz); + } + } + } + } + + /** + * Build Route + * + * @param routePackages route packets to add + */ + private void buildRoute(String... routePackages){ + Set classes = null; + // Traverse route + for(int i=0,len=routePackages.length; i pathClazz = classInfo.getClazz(); + this.addRouter(pathClazz); + } + } + } + } + + /** + * Parse Interceptor + * + * @param interceptor resolve the interceptor class + */ + public void addInterceptor(final Class interceptor){ + + boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); + if(null == interceptor || !hasInterface){ + return; + } + + Intercept intercept = interceptor.getAnnotation(Intercept.class); + String partten = "/.*"; + if(null != intercept){ + partten = intercept.value(); + } + + try { + Method before = interceptor.getMethod("before", Request.class, Response.class); + Method after = interceptor.getMethod("after", Request.class, Response.class); + buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); + buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + + } + + /** + * Parse all routing in a controller + * + * @param controller resolve the routing class + */ + public void addRouter(final Class router){ + + Method[] methods = router.getMethods(); + if(null == methods || methods.length == 0){ + return; + } + String nameSpace = null, suffix = null; + + if(null != router.getAnnotation(Controller.class)){ + nameSpace = router.getAnnotation(Controller.class).value(); + suffix = router.getAnnotation(Controller.class).suffix(); + } + + if(null != router.getAnnotation(RestController.class)){ + nameSpace = router.getAnnotation(RestController.class).value(); + suffix = router.getAnnotation(RestController.class).suffix(); + } + + if(null == nameSpace && null == suffix){ + LOGGER.warn("Route [{}] not controller annotation", router.getName()); + return; + } + for (int i = 0, len = methods.length; i < len; i++) { + Method method = methods[i]; + Route mapping = method.getAnnotation(Route.class); + //route method + if (null != mapping) { + // build multiple route + HttpMethod methodType = mapping.method(); + String[] paths = mapping.value(); + if(null != paths && paths.length > 0){ + for(int j=0, plen = paths.length; j 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + + path = path + suffix; + + return path; + } + + /** + * Build a route + * + * @param target route target execution class + * @param execMethod route execution method + * @param path route path + * @param method route httpmethod + */ + private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + + /** + * Build a route + * + * @param path route path + * @param target route target execution class + * @param execMethod route execution method + * @param method route httpmethod + */ + private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java index 9713d4fcb..8fc06767c 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Set; +import com.blade.kit.StringKit; import com.blade.mvc.http.HttpMethod; import com.blade.mvc.http.Path; @@ -44,14 +45,14 @@ public class RouteMatcher { // Storage Map Key private Set routeKeys = null; - private List interceptorRoutes = new ArrayList(); + private List interceptorRoutes = new ArrayList(8); public RouteMatcher(Routers routers) { this.routes = routers.getRoutes(); this.interceptors = routers.getInterceptors(); this.routeKeys = routes.keySet(); Collection inters = interceptors.values(); - if (null != inters && inters.size() > 0) { + if (null != inters && !inters.isEmpty()) { this.interceptorRoutes.addAll(inters); } } @@ -65,7 +66,7 @@ public RouteMatcher(Routers routers) { public Route getRoute(String httpMethod, String path) { String cleanPath = parsePath(path); - String routeKey = path + "#" + httpMethod.toUpperCase(); + String routeKey = path + '#' + httpMethod.toUpperCase(); Route route = routes.get(routeKey); if(null != route){ return route; @@ -75,9 +76,9 @@ public Route getRoute(String httpMethod, String path) { return route; } - List matchRoutes = new ArrayList(); + List matchRoutes = new ArrayList(6); for(String key : routeKeys){ - String[] keyArr = key.split("#"); + String[] keyArr = StringKit.split("#"); HttpMethod routeMethod = HttpMethod.valueOf(keyArr[1]); if (matchesPath(keyArr[0], cleanPath)) { if (routeMethod == HttpMethod.ALL || HttpMethod.valueOf(httpMethod) == routeMethod) { @@ -88,9 +89,9 @@ public Route getRoute(String httpMethod, String path) { } // Priority matching principle - giveMatch(path, matchRoutes); + this.giveMatch(path, matchRoutes); - return matchRoutes.size() > 0 ? matchRoutes.get(0) : null; + return matchRoutes.isEmpty() ? null : matchRoutes.get(0); } /** @@ -99,15 +100,15 @@ public Route getRoute(String httpMethod, String path) { * @return return interceptor list */ public List getBefore(String path) { - - List befores = new ArrayList(); + List befores = new ArrayList(8); String cleanPath = parsePath(path); - for (Route route : interceptorRoutes) { + for (int i = 0, len = interceptorRoutes.size(); i < len; i++) { + Route route = interceptorRoutes.get(i); if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.BEFORE){ befores.add(route); } - } - giveMatch(path, befores); + } + this.giveMatch(path, befores); return befores; } @@ -117,14 +118,15 @@ public List getBefore(String path) { * @return return interceptor list */ public List getAfter(String path) { - List afters = new ArrayList(); + List afters = new ArrayList(8); String cleanPath = parsePath(path); - for (Route route : interceptorRoutes) { + for (int i = 0, len = interceptorRoutes.size(); i < len; i++) { + Route route = interceptorRoutes.get(i); if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.AFTER){ afters.add(route); } } - giveMatch(path, afters); + this.giveMatch(path, afters); return afters; } diff --git a/blade-core/src/main/java/com/blade/mvc/route/Routers.java b/blade-core/src/main/java/com/blade/mvc/route/Routers.java index e2c52cca6..77b520fbb 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/Routers.java +++ b/blade-core/src/main/java/com/blade/mvc/route/Routers.java @@ -1,192 +1,193 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.route; - -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.kit.Assert; -import com.blade.kit.reflect.ReflectKit; -import com.blade.mvc.http.HttpMethod; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; - -/** - * Registration, management route - * - * @author biezhi - * @since 1.5 - */ -public class Routers { - - private static final Logger LOGGER = LoggerFactory.getLogger(Routers.class); - - private Map routes = null; - - private Map interceptors = null; - - private static final String METHOD_NAME = "handle"; - - public Routers() { - this.routes = new HashMap(); - this.interceptors = new HashMap(); - } - - public Map getRoutes() { - return routes; - } - - public Map getInterceptors() { - return interceptors; - } - - public void addRoute(Route route) { - String path = route.getPath(); - HttpMethod httpMethod = route.getHttpMethod(); - String key = path + "#" + httpMethod.toString(); - - // existent - if (null != this.routes.get(key)) { - LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); - } - - if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ - if (null != this.interceptors.get(key)) { - LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); - } - this.interceptors.put(key, route); - LOGGER.debug("Add Interceptor => {}", route); - } else { - this.routes.put(key, route); - LOGGER.debug("Add Route => {}", route); - } - } - - public void addRoutes(List routes) { - Assert.notNull(routes); - for(Route route : routes){ - this.addRoute(route); - } - } - - public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, String methodName) throws NoSuchMethodException { - Class handleType = handler.getClass(); - Method method = handleType.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, handler, RouteHandler.class, method); - } - - public void addRoute(HttpMethod httpMethod, String path, Object controller, Class controllerType, Method method) { - - Assert.notNull(httpMethod); - Assert.notBlank(path); - Assert.notNull(method); - - String key = path + "#" + httpMethod.toString(); - // existent - if (null != this.routes.get(key)) { - LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); - } - - Route route = new Route(httpMethod, path, controller, controllerType, method); - if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ - if (null != this.interceptors.get(key)) { - LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); - } - this.interceptors.put(key, route); - LOGGER.info("Add Interceptor: {}", route); - } else { - this.routes.put(key, route); - LOGGER.info("Add Route => {}", route); - } - - } - - public void route(String path, RouteHandler handler, HttpMethod httpMethod) { - try { - addRoute(httpMethod, path, handler, METHOD_NAME); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) { - for(String path : paths){ - route(path, handler, httpMethod); - } - } - - private Map classMethosPool = new HashMap(8); - - public void route(String path, Class clazz, String methodName) { - - Assert.notNull(path, "Route path not is null!"); - Assert.notNull(clazz, "Class Type not is null!"); - Assert.notNull(methodName, "Method name not is null"); - - HttpMethod httpMethod = HttpMethod.ALL; - if(methodName.indexOf(":") != -1){ - String[] methodArr = methodName.split(":"); - httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); - methodName = methodArr[1]; - } - try { - - Method[] methods = classMethosPool.get(clazz.getName()); - if(null == methods){ - methods = clazz.getMethods(); - classMethosPool.put(clazz.getName(), methods); - } - if(null != methods){ - for(Method method : methods){ - if(method.getName().equals(methodName)){ - addRoute(httpMethod, path, ReflectKit.newInstance(clazz), clazz, method); - } - } - } - } catch (SecurityException e) { - LOGGER.error(e.getMessage(), e); - } catch (InstantiationException e) { - LOGGER.error(e.getMessage(), e); - } catch (IllegalAccessException e) { - LOGGER.error(e.getMessage(), e); - } - } - - public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) { - try { - Assert.notNull(path, "Route path not is null!"); - Assert.notNull(clazz, "Class Type not is null!"); - Assert.notNull(methodName, "Method name not is null"); - Assert.notNull(httpMethod, "Request Method not is null"); - Method method = clazz.getMethod(methodName, Request.class, Response.class); - addRoute(httpMethod, path, null, clazz, method); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - } - - public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { - addRoute(httpMethod, path, null, clazz, method); - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.route; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.kit.reflect.ReflectKit; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; + +/** + * Registration, management route + * + * @author biezhi + * @since 1.5 + */ +public class Routers { + + private static final Logger LOGGER = LoggerFactory.getLogger(Routers.class); + + private Map routes = null; + + private Map interceptors = null; + + private static final String METHOD_NAME = "handle"; + + public Routers() { + this.routes = new HashMap(); + this.interceptors = new HashMap(); + } + + public Map getRoutes() { + return routes; + } + + public Map getInterceptors() { + return interceptors; + } + + public void addRoute(Route route) { + String path = route.getPath(); + HttpMethod httpMethod = route.getHttpMethod(); + String key = path + "#" + httpMethod.toString(); + + // existent + if (null != this.routes.get(key)) { + LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); + } + + if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ + if (null != this.interceptors.get(key)) { + LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); + } + this.interceptors.put(key, route); + LOGGER.debug("Add Interceptor => {}", route); + } else { + this.routes.put(key, route); + LOGGER.debug("Add Route => {}", route); + } + } + + public void addRoutes(List routes) { + Assert.notNull(routes); + for (int i = 0, len = routes.size(); i < len; i++) { + this.addRoute(routes.get(i)); + } + } + + public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, String methodName) throws NoSuchMethodException { + Class handleType = handler.getClass(); + Method method = handleType.getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, handler, RouteHandler.class, method); + } + + public void addRoute(HttpMethod httpMethod, String path, Object controller, Class controllerType, Method method) { + + Assert.notNull(httpMethod); + Assert.notBlank(path); + Assert.notNull(method); + + String key = path + "#" + httpMethod.toString(); + // existent + if (null != this.routes.get(key)) { + LOGGER.warn("\tRoute {} -> {} has exist", path, httpMethod.toString()); + } + + Route route = new Route(httpMethod, path, controller, controllerType, method); + if(httpMethod == HttpMethod.BEFORE || httpMethod == HttpMethod.AFTER){ + if (null != this.interceptors.get(key)) { + LOGGER.warn("\tInterceptor {} -> {} has exist", path, httpMethod.toString()); + } + this.interceptors.put(key, route); + LOGGER.info("Add Interceptor: {}", route); + } else { + this.routes.put(key, route); + LOGGER.info("Add Route => {}", route); + } + + } + + public void route(String path, RouteHandler handler, HttpMethod httpMethod) { + try { + addRoute(httpMethod, path, handler, METHOD_NAME); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) { + for (int i = 0, len = paths.length; i < len; i++) { + route(paths[i], handler, httpMethod); + } + } + + private Map classMethosPool = new HashMap(8); + + public void route(String path, Class clazz, String methodName) { + + Assert.notNull(path, "Route path not is null!"); + Assert.notNull(clazz, "Class Type not is null!"); + Assert.notNull(methodName, "Method name not is null"); + + HttpMethod httpMethod = HttpMethod.ALL; + if(methodName.indexOf(":") != -1){ + String[] methodArr = methodName.split(":"); + httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); + methodName = methodArr[1]; + } + try { + + Method[] methods = classMethosPool.get(clazz.getName()); + if(null == methods){ + methods = clazz.getMethods(); + classMethosPool.put(clazz.getName(), methods); + } + if(null != methods){ + for (int i = 0, len = methods.length; i < len; i++) { + Method method = methods[i]; + if (method.getName().equals(methodName)) { + addRoute(httpMethod, path, ReflectKit.newInstance(clazz), clazz, method); + } + } + } + } catch (SecurityException e) { + LOGGER.error(e.getMessage(), e); + } catch (InstantiationException e) { + LOGGER.error(e.getMessage(), e); + } catch (IllegalAccessException e) { + LOGGER.error(e.getMessage(), e); + } + } + + public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) { + try { + Assert.notNull(path, "Route path not is null!"); + Assert.notNull(clazz, "Class Type not is null!"); + Assert.notNull(methodName, "Method name not is null"); + Assert.notNull(httpMethod, "Request Method not is null"); + Method method = clazz.getMethod(methodName, Request.class, Response.class); + addRoute(httpMethod, path, null, clazz, method); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + } + + public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { + addRoute(httpMethod, path, null, clazz, method); + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java index 8b93ae5eb..88efa34c1 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java @@ -17,6 +17,7 @@ import com.blade.Blade; import com.blade.ioc.Ioc; +import com.blade.kit.StringKit; import com.blade.mvc.route.RouteException; /** @@ -39,10 +40,10 @@ public ClassPathControllerLoader() { public ClassPathControllerLoader(String basePackage) { this.basePackage = basePackage; - - if (this.basePackage != null && !"".equals(this.basePackage)) { + + if (StringKit.isNotBlank(basePackage)) { if (!this.basePackage.endsWith(".")) { - this.basePackage += "."; + this.basePackage += '.'; } } } diff --git a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java index 7ab0a5cc2..ab4ffab49 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java @@ -112,7 +112,7 @@ private static Object getRequestParam(Class parameterType, String val) { } else if (parameterType.equals(Integer.class)) { result = Integer.parseInt(val); } else if (parameterType.equals(int.class)) { - if("".equals(val)){ + if(StringKit.isBlank(val)){ result = 0; } else { result = Integer.parseInt(val); @@ -120,7 +120,7 @@ private static Object getRequestParam(Class parameterType, String val) { } else if (parameterType.equals(Long.class)) { result = Long.parseLong(val); } else if (parameterType.equals(long.class)) { - if("".equals(val)){ + if(StringKit.isBlank(val)){ result = 0L; } else { result = Integer.parseInt(val); diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index 4d1e96630..062678d59 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -1,117 +1,127 @@ -package com.blade.embedd; - -import static com.blade.Blade.$; - -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.handler.DefaultHandler; -import org.eclipse.jetty.server.handler.HandlerList; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.eclipse.jetty.webapp.WebAppContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Const; -import com.blade.kit.base.Config; -import com.blade.mvc.DispatcherServlet; - -public class EmbedJettyServer implements EmbedServer { - - private static final Logger LOGGER = LoggerFactory.getLogger(EmbedJettyServer.class); - - private int port = Const.DEFAULT_PORT; - - private org.eclipse.jetty.server.Server server; - - private WebAppContext webAppContext; - - private Config config = null; - - public EmbedJettyServer() { - System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); - $().loadAppConf("jetty.properties"); - config = $().config(); - $().enableServer(true); - } - - @Override - public void startup(int port) throws Exception { - this.startup(port, Const.DEFAULT_CONTEXTPATH, null); - } - - @Override - public void startup(int port, String contextPath) throws Exception { - this.startup(port, contextPath, null); - } - - @Override - public void setWebRoot(String webRoot) { - webAppContext.setResourceBase(webRoot); - } - - @Override - public void startup(int port, String contextPath, String webRoot) throws Exception { - this.port = port; - - // Setup Threadpool - QueuedThreadPool threadPool = new QueuedThreadPool(); - - int minThreads = config.getInt("server.jetty.min-threads", 100); - int maxThreads = config.getInt("server.jetty.max-threads", 500); - - threadPool.setMinThreads(minThreads); - threadPool.setMaxThreads(maxThreads); - - server = new org.eclipse.jetty.server.Server(threadPool); - - // 设置在JVM退出时关闭Jetty的钩子。 - server.setStopAtShutdown(true); - - webAppContext = new WebAppContext(); - webAppContext.setContextPath(contextPath); - webAppContext.setResourceBase(""); - - int securePort = config.getInt("server.jetty.http.secure-port", 8443); - int outputBufferSize = config.getInt("server.jetty.http.output-buffersize", 32768); - int requestHeaderSize = config.getInt("server.jetty.http.request-headersize", 8192); - int responseHeaderSize = config.getInt("server.jetty.http.response-headersize", 8192); - - // HTTP Configuration - HttpConfiguration http_config = new HttpConfiguration(); - http_config.setSecurePort(securePort); - http_config.setOutputBufferSize(outputBufferSize); - http_config.setRequestHeaderSize(requestHeaderSize); - http_config.setResponseHeaderSize(responseHeaderSize); - http_config.setSendServerVersion(true); - http_config.setSendDateHeader(false); - - long idleTimeout = config.getLong("server.jetty.http.idle-timeout", 30000L); - - ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(http_config)); - http.setPort(this.port); - http.setIdleTimeout(idleTimeout); - server.addConnector(http); - - ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); - servletHolder.setAsyncSupported(false); - servletHolder.setInitOrder(1); - - webAppContext.addServlet(servletHolder, "/"); - - HandlerList handlers = new HandlerList(); - handlers.setHandlers(new Handler[] { webAppContext, new DefaultHandler() }); - server.setHandler(handlers); - - server.start(); - LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); - server.join(); - } - - public void stop() throws Exception { - server.stop(); - } - +package com.blade.embedd; + +import static com.blade.Blade.$; + +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.HandlerList; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.eclipse.jetty.webapp.WebAppContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Const; +import com.blade.exception.EmbedServerException; +import com.blade.kit.base.Config; +import com.blade.mvc.DispatcherServlet; + +public class EmbedJettyServer implements EmbedServer { + + private static final Logger LOGGER = LoggerFactory.getLogger(EmbedJettyServer.class); + + private int port = Const.DEFAULT_PORT; + + private Server server; + + private WebAppContext webAppContext; + + private Config config = null; + + public EmbedJettyServer() { + System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); + $().loadAppConf("jetty.properties"); + config = $().config(); + $().enableServer(true); + } + + @Override + public void startup(int port) throws EmbedServerException { + this.startup(port, Const.DEFAULT_CONTEXTPATH, null); + } + + @Override + public void startup(int port, String contextPath) throws EmbedServerException { + this.startup(port, contextPath, null); + } + + @Override + public void setWebRoot(String webRoot) { + webAppContext.setResourceBase(webRoot); + } + + @Override + public void startup(int port, String contextPath, String webRoot) throws EmbedServerException { + this.port = port; + + // Setup Threadpool + QueuedThreadPool threadPool = new QueuedThreadPool(); + + int minThreads = config.getInt("server.jetty.min-threads", 100); + int maxThreads = config.getInt("server.jetty.max-threads", 500); + + threadPool.setMinThreads(minThreads); + threadPool.setMaxThreads(maxThreads); + + server = new org.eclipse.jetty.server.Server(threadPool); + + // 设置在JVM退出时关闭Jetty的钩子。 + server.setStopAtShutdown(true); + + webAppContext = new WebAppContext(); + webAppContext.setContextPath(contextPath); + webAppContext.setResourceBase(""); + + int securePort = config.getInt("server.jetty.http.secure-port", 8443); + int outputBufferSize = config.getInt("server.jetty.http.output-buffersize", 32768); + int requestHeaderSize = config.getInt("server.jetty.http.request-headersize", 8192); + int responseHeaderSize = config.getInt("server.jetty.http.response-headersize", 8192); + + // HTTP Configuration + HttpConfiguration http_config = new HttpConfiguration(); + http_config.setSecurePort(securePort); + http_config.setOutputBufferSize(outputBufferSize); + http_config.setRequestHeaderSize(requestHeaderSize); + http_config.setResponseHeaderSize(responseHeaderSize); + http_config.setSendServerVersion(true); + http_config.setSendDateHeader(false); + + long idleTimeout = config.getLong("server.jetty.http.idle-timeout", 30000L); + + ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(http_config)); + http.setPort(this.port); + http.setIdleTimeout(idleTimeout); + server.addConnector(http); + + ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); + servletHolder.setAsyncSupported(false); + servletHolder.setInitOrder(1); + + webAppContext.addServlet(servletHolder, "/"); + + HandlerList handlers = new HandlerList(); + handlers.setHandlers(new Handler[] { webAppContext, new DefaultHandler() }); + server.setHandler(handlers); + + try { + server.start(); + LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); + server.join(); + } catch (Exception e) { + throw new EmbedServerException(e); + } + } + + public void stop() throws EmbedServerException { + try { + server.stop(); + } catch (Exception e) { + throw new EmbedServerException(e); + } + } + } \ No newline at end of file diff --git a/blade-kit/src/main/java/com/blade/kit/StreamKit.java b/blade-kit/src/main/java/com/blade/kit/StreamKit.java index 5b41cbebe..6f74f42bd 100644 --- a/blade-kit/src/main/java/com/blade/kit/StreamKit.java +++ b/blade-kit/src/main/java/com/blade/kit/StreamKit.java @@ -1,566 +1,566 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; - -import java.io.Closeable; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; - -import com.blade.kit.io.ByteArray; -import com.blade.kit.io.ByteArrayOutputStream; -import com.blade.kit.io.FastByteArrayOutputStream; - -/** - * 基于流的工具类 - * - * @author biezhi - * @since 1.0 - */ -public abstract class StreamKit { - - /** - * 从输入流读取内容, 写入到输出流中. 此方法使用大小为8192字节的默认的缓冲区. - * - * @param in 输入流 - * @param out 输出流 - * - * @throws IOException 输入输出异常 - */ - public static void io(InputStream in, OutputStream out) throws IOException { - io(in, out, -1); - } - - /** - * 从输入流读取内容, 写入到输出流中. 使用指定大小的缓冲区. - * - * @param in 输入流 - * @param out 输出流 - * @param bufferSize 缓冲区大小(字节数) - * - * @throws IOException 输入输出异常 - */ - public static void io(InputStream in, OutputStream out, int bufferSize) throws IOException { - if (bufferSize == -1) { - bufferSize = IOKit.DEFAULT_BUFFER_SIZE; - } - - byte[] buffer = new byte[bufferSize]; - int amount; - - while ((amount = in.read(buffer)) >= 0) { - out.write(buffer, 0, amount); - } - - out.flush(); - } - - /** - * 从输入流读取内容, 写入到输出流中. 此方法使用大小为8192字符的默认的缓冲区. - * - * @param in 输入流 - * @param out 输出流 - * - * @throws IOException 输入输出异常 - */ - public static void io(Reader in, Writer out) throws IOException { - io(in, out, -1); - } - - /** - * 从输入流读取内容, 写入到输出流中. 使用指定大小的缓冲区. - * - * @param in 输入流 - * @param out 输出流 - * @param bufferSize 缓冲区大小(字符数) - * - * @throws IOException 输入输出异常 - */ - public static void io(Reader in, Writer out, int bufferSize) throws IOException { - if (bufferSize == -1) { - bufferSize = IOKit.DEFAULT_BUFFER_SIZE >> 1; - } - - char[] buffer = new char[bufferSize]; - int amount; - - while ((amount = in.read(buffer)) >= 0) { - out.write(buffer, 0, amount); - } - - out.flush(); - } - - /** - * 从输入流读取内容, 写入到输出流中. 此方法使用大小为8192字节的默认的缓冲区. - * - * @param in 输入流 - * @param out 输出流 - * @param closeIn 是否关闭输入流 - * @param closeOut 是否关闭输出流 - * @throws IOException 输入输出异常 - */ - public static void io(InputStream in, OutputStream out, boolean closeIn, boolean closeOut) throws IOException { - - try { - io(in, out); - } finally { - if (closeIn) { - close(in); - } - - if (closeOut) { - close(out); - } - } - } - - /** - * 从输入流读取内容, 写入到输出流中. 此方法使用大小为8192字节的默认的缓冲区. - * - * @param in 输入流 - * @param out 输出流 - * @param closeIn 是否关闭输入流 - * @param closeOut 是否关闭输出流 - * @throws IOException 输入输出异常 - */ - public static void io(Reader in, Writer out, boolean closeIn, boolean closeOut) throws IOException { - try { - io(in, out); - } finally { - if (closeIn) { - close(in); - } - - if (closeOut) { - close(out); - } - } - } - - /** 从输入流读取内容, 写入到目标文件 */ - public static void io(InputStream in, File dest) throws IOException { - OutputStream out = new FileOutputStream(dest); - io(in, out); - } - - /** 从输入流读取内容, 写入到目标文件 */ - public static void io(InputStream in, File dest, boolean closeIn, boolean closeOut) throws IOException { - OutputStream out = new FileOutputStream(dest); - try { - io(in, out); - } finally { - if (closeIn) { - close(in); - } - - if (closeOut) { - close(out); - } - } - } - - /** 从输入流读取内容, 写入到目标文件 */ - public static void io(InputStream in, String dest) throws IOException { - OutputStream out = new FileOutputStream(dest); - io(in, out); - } - - /** 从输入流读取内容, 写入到目标文件 */ - public static void io(InputStream in, String dest, boolean closeIn, boolean closeOut) throws IOException { - OutputStream out = new FileOutputStream(dest); - try { - io(in, out); - } finally { - if (closeIn) { - close(in); - } - - if (closeOut) { - close(out); - } - } - } - - /** 从输入流读取内容, 写入到目标文件 */ - public static void io(Reader in, File dest) throws IOException { - Writer out = new FileWriter(dest); - io(in, out); - } - - /** 从输入流读取内容, 写入到目标文件 */ - public static void io(Reader in, File dest, boolean closeIn, boolean closeOut) throws IOException { - Writer out = new FileWriter(dest); - try { - io(in, out); - } finally { - if (closeIn) { - close(in); - } - - if (closeOut) { - close(out); - } - } - } - - /** 从输入流读取内容, 写入到目标文件 */ - public static void io(Reader in, String dest) throws IOException { - Writer out = new FileWriter(dest); - io(in, out); - } - - /** 从输入流读取内容, 写入到目标文件 */ - public static void io(Reader in, String dest, boolean closeIn, boolean closeOut) throws IOException { - Writer out = new FileWriter(dest); - try { - io(in, out); - } finally { - if (closeIn) { - close(in); - } - - if (closeOut) { - close(out); - } - } - } - - /** - * 取得同步化的输出流. - * - * @param out 要包裹的输出流 - * - * @return 线程安全的同步化输出流 - */ - public static OutputStream synchronizedOutputStream(OutputStream out) { - return new SynchronizedOutputStream(out); - } - - /** - * 取得同步化的输出流. - * - * @param out 要包裹的输出流 - * @param lock 同步锁 - * - * @return 线程安全的同步化输出流 - */ - public static OutputStream synchronizedOutputStream(OutputStream out, Object lock) { - return new SynchronizedOutputStream(out, lock); - } - - /** - * 将指定输入流的所有文本全部读出到一个字符串中. - * - * @param in 要读取的输入流 - * - * @return 从输入流中取得的文本 - * - * @throws IOException 输入输出异常 - */ - public static String readText(InputStream in) throws IOException { - return readText(in, null, -1); - } - - /** - * 将指定输入流的所有文本全部读出到一个字符串中. - * - * @param in 要读取的输入流 - * @param encoding 文本编码方式 - * - * @return 从输入流中取得的文本 - * - * @throws IOException 输入输出异常 - */ - public static String readText(InputStream in, String encoding) throws IOException { - return readText(in, encoding, -1); - } - - /** - * 将指定输入流的所有文本全部读出到一个字符串中. - * - * @param in 要读取的输入流 - * @param charset 文本编码方式 - * @param bufferSize 缓冲区大小(字符数) - * - * @return 从输入流中取得的文本 - * - * @throws IOException 输入输出异常 - */ - public static String readText(InputStream in, String charset, int bufferSize) throws IOException { - Reader reader = (charset == null) ? new InputStreamReader(in) : new InputStreamReader(in, charset); - - return readText(reader, bufferSize); - } - - /** - * 将指定输入流的所有文本全部读出到一个字符串中. - * - * @param in 要读取的输入流 - * @param charset 文本编码方式 - * @param closeIn 是否关闭输入流 - * @return 从输入流中取得的文本 - * @throws IOException 输入输出异常 - */ - public static String readText(InputStream in, String charset, boolean closeIn) throws IOException { - Reader reader = charset == null ? new InputStreamReader(in) : new InputStreamReader(in, charset); - - return readText(reader, closeIn); - } - - /** - * 将指定输入流的所有文本全部读出到一个字符串中. - * - * @param in 要读取的输入流 - * @param closeIn 是否关闭输入流 - * @return 从输入流中取得的文本 - * @throws IOException 输入输出异常 - */ - public static String readText(Reader in, boolean closeIn) throws IOException { - StringWriter out = new StringWriter(); - - io(in, out, closeIn, true); - - return out.toString(); - } - - /** - * 将指定Reader的所有文本全部读出到一个字符串中. - * - * @param reader 要读取的Reader - * - * @return 从Reader中取得的文本 - * - * @throws IOException 输入输出异常 - */ - public static String readText(Reader reader) throws IOException { - return readText(reader, -1); - } - - /** - * 将指定Reader的所有文本全部读出到一个字符串中. - * - * @param reader 要读取的Reader - * @param bufferSize 缓冲区的大小(字符数) - * - * @return 从Reader中取得的文本 - * - * @throws IOException 输入输出异常 - */ - public static String readText(Reader reader, int bufferSize) throws IOException { - StringWriter writer = new StringWriter(); - - io(reader, writer, bufferSize); - - return writer.toString(); - } - - /** - * 将指定InputStream的所有内容全部读出到一个byte数组中。 - * - * @param in 要读取的InputStream - * @return ByteArray # @see ByteArray - * @throws IOException - */ - public static ByteArray readBytes(InputStream in) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - io(in, out); - - return out.toByteArray(); - } - - /** 将指定InputStream的所有内容全部读出到一个byte数组中。 */ - public static ByteArray readBytes(InputStream in, boolean closeIn) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - io(in, out, closeIn, true); - - return out.toByteArray(); - } - - /** - * 将指定File的所有内容全部读出到一个byte数组中。 - * - * @param file 要读取的文件 - * @return ByteArray # @see ByteArray - * @throws IOException - */ - public static ByteArray readBytes(File file) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - io(new FileInputStream(file), out); - - return out.toByteArray(); - } - - /** 将指定File的所有内容全部读出到一个byte数组中。 */ - public static ByteArray readBytes(File file, boolean closeIn) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - io(new FileInputStream(file), out, closeIn, true); - - return out.toByteArray(); - } - - /** - * 通过快速缓冲将指定InputStream的所有内容全部读出到一个byte数组中。 - * - * @param in 要读取的InputStream - * @return byte[]字节数组 - * @throws IOException - */ - public static byte[] readBytesByFast(InputStream in) throws IOException { - FastByteArrayOutputStream out = new FastByteArrayOutputStream(); - io(in, out); - return out.toByteArray(); - } - - /** 通过快速缓冲将指定InputStream的所有内容全部读出到一个byte数组中。 */ - public static byte[] readBytesByFast(InputStream in, boolean closeIn) throws IOException { - FastByteArrayOutputStream out = new FastByteArrayOutputStream(); - - io(in, out, closeIn, true); - - return out.toByteArray(); - } - - /** 将字符串写入到指定输出流中。 */ - public static void writeText(CharSequence chars, OutputStream out, String charset, boolean closeOut) - throws IOException { - Writer writer = charset == null ? new OutputStreamWriter(out) : new OutputStreamWriter(out, charset); - - writeText(chars, writer, closeOut); - } - - /** 将字符串写入到指定Writer中。 */ - public static void writeText(CharSequence chars, Writer out, boolean closeOut) throws IOException { - try { - out.write(chars.toString()); - out.flush(); - } finally { - if (closeOut) { - try { - out.close(); - } catch (IOException e) { - // ignore - } - } - } - } - - /** 将byte数组写入到指定filePath中。 */ - public static void writeBytes(byte[] bytes, String filePath, boolean closeOut) throws IOException { - writeBytes(new ByteArray(bytes), new FileOutputStream(filePath), closeOut); - } - - /** 将byte数组写入到指定File中。 */ - public static void writeBytes(byte[] bytes, File file, boolean closeOut) throws IOException { - writeBytes(new ByteArray(bytes), new FileOutputStream(file), closeOut); - } - - /** 将byte数组写入到指定OutputStream中。 */ - public static void writeBytes(byte[] bytes, OutputStream out, boolean closeOut) throws IOException { - writeBytes(new ByteArray(bytes), out, closeOut); - } - - /** 将byte数组写入到指定OutputStream中。 */ - public static void writeBytes(ByteArray bytes, OutputStream out, boolean closeOut) throws IOException { - try { - out.write(bytes.getRawBytes(), bytes.getOffset(), bytes.getLength()); - out.flush(); - } finally { - if (closeOut) { - try { - out.close(); - } catch (IOException e) { - } - } - } - } - - /** - * 关闭流 - * - * @param closed 可关闭的流 - */ - public static void close(Closeable closed) { - if (closed != null) { - try { - closed.close(); - } catch (IOException ignore) { - // can ignore - } - } - } - - /** - * 同步化的输出流包裹器. - */ - private static class SynchronizedOutputStream extends OutputStream { - private OutputStream out; - private Object lock; - - SynchronizedOutputStream(OutputStream out) { - this(out, out); - } - - SynchronizedOutputStream(OutputStream out, Object lock) { - this.out = out; - this.lock = lock; - } - - public void write(int datum) throws IOException { - synchronized (lock) { - out.write(datum); - } - } - - public void write(byte[] data) throws IOException { - synchronized (lock) { - out.write(data); - } - } - - public void write(byte[] data, int offset, int length) throws IOException { - synchronized (lock) { - out.write(data, offset, length); - } - } - - public void flush() throws IOException { - synchronized (lock) { - out.flush(); - } - } - - public void close() throws IOException { - synchronized (lock) { - out.close(); - } - } - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; + +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.StringWriter; +import java.io.Writer; + +import com.blade.kit.io.ByteArray; +import com.blade.kit.io.ByteArrayOutputStream; +import com.blade.kit.io.FastByteArrayOutputStream; + +/** + * 基于流的工具类 + * + * @author biezhi + * @since 1.0 + */ +public abstract class StreamKit { + + /** + * 从输入流读取内容, 写入到输出流中. 此方法使用大小为8192字节的默认的缓冲区. + * + * @param in 输入流 + * @param out 输出流 + * + * @throws IOException 输入输出异常 + */ + public static void io(InputStream in, OutputStream out) throws IOException { + io(in, out, -1); + } + + /** + * 从输入流读取内容, 写入到输出流中. 使用指定大小的缓冲区. + * + * @param in 输入流 + * @param out 输出流 + * @param bufferSize 缓冲区大小(字节数) + * + * @throws IOException 输入输出异常 + */ + public static void io(InputStream in, OutputStream out, int bufferSize) throws IOException { + if (bufferSize == -1) { + bufferSize = IOKit.DEFAULT_BUFFER_SIZE; + } + + byte[] buffer = new byte[bufferSize]; + int amount; + + while ((amount = in.read(buffer)) >= 0) { + out.write(buffer, 0, amount); + } + + out.flush(); + } + + /** + * 从输入流读取内容, 写入到输出流中. 此方法使用大小为8192字符的默认的缓冲区. + * + * @param in 输入流 + * @param out 输出流 + * + * @throws IOException 输入输出异常 + */ + public static void io(Reader in, Writer out) throws IOException { + io(in, out, -1); + } + + /** + * 从输入流读取内容, 写入到输出流中. 使用指定大小的缓冲区. + * + * @param in 输入流 + * @param out 输出流 + * @param bufferSize 缓冲区大小(字符数) + * + * @throws IOException 输入输出异常 + */ + public static void io(Reader in, Writer out, int bufferSize) throws IOException { + if (bufferSize == -1) { + bufferSize = IOKit.DEFAULT_BUFFER_SIZE >> 1; + } + + char[] buffer = new char[bufferSize]; + int amount; + + while ((amount = in.read(buffer)) >= 0) { + out.write(buffer, 0, amount); + } + + out.flush(); + } + + /** + * 从输入流读取内容, 写入到输出流中. 此方法使用大小为8192字节的默认的缓冲区. + * + * @param in 输入流 + * @param out 输出流 + * @param closeIn 是否关闭输入流 + * @param closeOut 是否关闭输出流 + * @throws IOException 输入输出异常 + */ + public static void io(InputStream in, OutputStream out, boolean closeIn, boolean closeOut) throws IOException { + + try { + io(in, out); + } finally { + if (closeIn) { + close(in); + } + + if (closeOut) { + close(out); + } + } + } + + /** + * 从输入流读取内容, 写入到输出流中. 此方法使用大小为8192字节的默认的缓冲区. + * + * @param in 输入流 + * @param out 输出流 + * @param closeIn 是否关闭输入流 + * @param closeOut 是否关闭输出流 + * @throws IOException 输入输出异常 + */ + public static void io(Reader in, Writer out, boolean closeIn, boolean closeOut) throws IOException { + try { + io(in, out); + } finally { + if (closeIn) { + close(in); + } + + if (closeOut) { + close(out); + } + } + } + + /** 从输入流读取内容, 写入到目标文件 */ + public static void io(InputStream in, File dest) throws IOException { + OutputStream out = new FileOutputStream(dest); + io(in, out); + } + + /** 从输入流读取内容, 写入到目标文件 */ + public static void io(InputStream in, File dest, boolean closeIn, boolean closeOut) throws IOException { + OutputStream out = new FileOutputStream(dest); + try { + io(in, out); + } finally { + if (closeIn) { + close(in); + } + + if (closeOut) { + close(out); + } + } + } + + /** 从输入流读取内容, 写入到目标文件 */ + public static void io(InputStream in, String dest) throws IOException { + OutputStream out = new FileOutputStream(dest); + io(in, out); + } + + /** 从输入流读取内容, 写入到目标文件 */ + public static void io(InputStream in, String dest, boolean closeIn, boolean closeOut) throws IOException { + OutputStream out = new FileOutputStream(dest); + try { + io(in, out); + } finally { + if (closeIn) { + close(in); + } + + if (closeOut) { + close(out); + } + } + } + + /** 从输入流读取内容, 写入到目标文件 */ + public static void io(Reader in, File dest) throws IOException { + Writer out = new FileWriter(dest); + io(in, out); + } + + /** 从输入流读取内容, 写入到目标文件 */ + public static void io(Reader in, File dest, boolean closeIn, boolean closeOut) throws IOException { + Writer out = new FileWriter(dest); + try { + io(in, out); + } finally { + if (closeIn) { + close(in); + } + + if (closeOut) { + close(out); + } + } + } + + /** 从输入流读取内容, 写入到目标文件 */ + public static void io(Reader in, String dest) throws IOException { + Writer out = new FileWriter(dest); + io(in, out); + } + + /** 从输入流读取内容, 写入到目标文件 */ + public static void io(Reader in, String dest, boolean closeIn, boolean closeOut) throws IOException { + Writer out = new FileWriter(dest); + try { + io(in, out); + } finally { + if (closeIn) { + close(in); + } + + if (closeOut) { + close(out); + } + } + } + + /** + * 取得同步化的输出流. + * + * @param out 要包裹的输出流 + * + * @return 线程安全的同步化输出流 + */ + public static OutputStream synchronizedOutputStream(OutputStream out) { + return new SynchronizedOutputStream(out); + } + + /** + * 取得同步化的输出流. + * + * @param out 要包裹的输出流 + * @param lock 同步锁 + * + * @return 线程安全的同步化输出流 + */ + public static OutputStream synchronizedOutputStream(OutputStream out, Object lock) { + return new SynchronizedOutputStream(out, lock); + } + + /** + * 将指定输入流的所有文本全部读出到一个字符串中. + * + * @param in 要读取的输入流 + * + * @return 从输入流中取得的文本 + * + * @throws IOException 输入输出异常 + */ + public static String readText(InputStream in) throws IOException { + return readText(in, null, -1); + } + + /** + * 将指定输入流的所有文本全部读出到一个字符串中. + * + * @param in 要读取的输入流 + * @param encoding 文本编码方式 + * + * @return 从输入流中取得的文本 + * + * @throws IOException 输入输出异常 + */ + public static String readText(InputStream in, String encoding) throws IOException { + return readText(in, encoding, -1); + } + + /** + * 将指定输入流的所有文本全部读出到一个字符串中. + * + * @param in 要读取的输入流 + * @param charset 文本编码方式 + * @param bufferSize 缓冲区大小(字符数) + * + * @return 从输入流中取得的文本 + * + * @throws IOException 输入输出异常 + */ + public static String readText(InputStream in, String charset, int bufferSize) throws IOException { + Reader reader = (charset == null) ? new InputStreamReader(in) : new InputStreamReader(in, charset); + + return readText(reader, bufferSize); + } + + /** + * 将指定输入流的所有文本全部读出到一个字符串中. + * + * @param in 要读取的输入流 + * @param charset 文本编码方式 + * @param closeIn 是否关闭输入流 + * @return 从输入流中取得的文本 + * @throws IOException 输入输出异常 + */ + public static String readText(InputStream in, String charset, boolean closeIn) throws IOException { + Reader reader = charset == null ? new InputStreamReader(in) : new InputStreamReader(in, charset); + + return readText(reader, closeIn); + } + + /** + * 将指定输入流的所有文本全部读出到一个字符串中. + * + * @param in 要读取的输入流 + * @param closeIn 是否关闭输入流 + * @return 从输入流中取得的文本 + * @throws IOException 输入输出异常 + */ + public static String readText(Reader in, boolean closeIn) throws IOException { + StringWriter out = new StringWriter(); + + io(in, out, closeIn, true); + + return out.toString(); + } + + /** + * 将指定Reader的所有文本全部读出到一个字符串中. + * + * @param reader 要读取的Reader + * + * @return 从Reader中取得的文本 + * + * @throws IOException 输入输出异常 + */ + public static String readText(Reader reader) throws IOException { + return readText(reader, -1); + } + + /** + * 将指定Reader的所有文本全部读出到一个字符串中. + * + * @param reader 要读取的Reader + * @param bufferSize 缓冲区的大小(字符数) + * + * @return 从Reader中取得的文本 + * + * @throws IOException 输入输出异常 + */ + public static String readText(Reader reader, int bufferSize) throws IOException { + StringWriter writer = new StringWriter(); + + io(reader, writer, bufferSize); + + return writer.toString(); + } + + /** + * 将指定InputStream的所有内容全部读出到一个byte数组中。 + * + * @param in 要读取的InputStream + * @return ByteArray # @see ByteArray + * @throws IOException + */ + public static ByteArray readBytes(InputStream in) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + io(in, out); + + return out.toByteArray(); + } + + /** 将指定InputStream的所有内容全部读出到一个byte数组中。 */ + public static ByteArray readBytes(InputStream in, boolean closeIn) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + io(in, out, closeIn, true); + + return out.toByteArray(); + } + + /** + * 将指定File的所有内容全部读出到一个byte数组中。 + * + * @param file 要读取的文件 + * @return ByteArray # @see ByteArray + * @throws IOException + */ + public static ByteArray readBytes(File file) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + io(new FileInputStream(file), out); + + return out.toByteArray(); + } + + /** 将指定File的所有内容全部读出到一个byte数组中。 */ + public static ByteArray readBytes(File file, boolean closeIn) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + io(new FileInputStream(file), out, closeIn, true); + + return out.toByteArray(); + } + + /** + * 通过快速缓冲将指定InputStream的所有内容全部读出到一个byte数组中。 + * + * @param in 要读取的InputStream + * @return byte[]字节数组 + * @throws IOException + */ + public static byte[] readBytesByFast(InputStream in) throws IOException { + FastByteArrayOutputStream out = new FastByteArrayOutputStream(); + io(in, out); + return out.toByteArray(); + } + + /** 通过快速缓冲将指定InputStream的所有内容全部读出到一个byte数组中。 */ + public static byte[] readBytesByFast(InputStream in, boolean closeIn) throws IOException { + FastByteArrayOutputStream out = new FastByteArrayOutputStream(); + + io(in, out, closeIn, true); + + return out.toByteArray(); + } + + /** 将字符串写入到指定输出流中。 */ + public static void writeText(CharSequence chars, OutputStream out, String charset, boolean closeOut) + throws IOException { + Writer writer = charset == null ? new OutputStreamWriter(out) : new OutputStreamWriter(out, charset); + + writeText(chars, writer, closeOut); + } + + /** 将字符串写入到指定Writer中。 */ + public static void writeText(CharSequence chars, Writer out, boolean closeOut) throws IOException { + try { + out.write(chars.toString()); + out.flush(); + } finally { + if (closeOut) { + try { + out.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + /** 将byte数组写入到指定filePath中。 */ + public static void writeBytes(byte[] bytes, String filePath, boolean closeOut) throws IOException { + writeBytes(new ByteArray(bytes), new FileOutputStream(filePath), closeOut); + } + + /** 将byte数组写入到指定File中。 */ + public static void writeBytes(byte[] bytes, File file, boolean closeOut) throws IOException { + writeBytes(new ByteArray(bytes), new FileOutputStream(file), closeOut); + } + + /** 将byte数组写入到指定OutputStream中。 */ + public static void writeBytes(byte[] bytes, OutputStream out, boolean closeOut) throws IOException { + writeBytes(new ByteArray(bytes), out, closeOut); + } + + /** 将byte数组写入到指定OutputStream中。 */ + public static void writeBytes(ByteArray bytes, OutputStream out, boolean closeOut) throws IOException { + try { + out.write(bytes.getRawBytes(), bytes.getOffset(), bytes.getLength()); + out.flush(); + } finally { + if (closeOut) { + try { + out.close(); + } catch (IOException e) { + } + } + } + } + + /** + * 关闭流 + * + * @param closed 可关闭的流 + */ + public static void close(Closeable closed) { + if (closed != null) { + try { + closed.close(); + } catch (IOException ignore) { + // can ignore + } + } + } + + /** + * 同步化的输出流包裹器. + */ + private static class SynchronizedOutputStream extends OutputStream { + private OutputStream out; + private Object lock; + + SynchronizedOutputStream(OutputStream out) { + this(out, out); + } + + SynchronizedOutputStream(OutputStream out, Object lock) { + this.out = out; + this.lock = lock; + } + + public void write(int datum) throws IOException { + synchronized (lock) { + out.write(datum); + } + } + + public void write(byte[] data) throws IOException { + synchronized (lock) { + out.write(data); + } + } + + public void write(byte[] data, int offset, int length) throws IOException { + synchronized (lock) { + out.write(data, offset, length); + } + } + + public void flush() throws IOException { + synchronized (lock) { + out.flush(); + } + } + + public void close() throws IOException { + synchronized (lock) { + out.close(); + } + } + } + } \ No newline at end of file From adb5c1f42ffb287836ddd9730a431d11424a2405 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 5 Sep 2016 22:29:35 +0800 Subject: [PATCH 500/545] =?UTF-8?q?=E2=9C=84=20update=20default=20template?= =?UTF-8?q?=20engine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/Blade.java | 1442 +++++++++-------- .../src/main/java/com/blade/kit/AsmKit.java | 240 ++- .../com/blade/mvc/route/RouteMatcher.java | 2 +- .../mvc/view/template/DefaultEngine.java | 140 +- 4 files changed, 897 insertions(+), 927 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 445e19021..b815a29f4 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -1,720 +1,724 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.io.InputStream; -import java.text.ParseException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.blade.config.ApplicationConfig; -import com.blade.config.BaseConfig; -import com.blade.config.ConfigLoader; -import com.blade.embedd.EmbedServer; -import com.blade.exception.EmbedServerException; -import com.blade.ioc.Ioc; -import com.blade.ioc.SimpleIoc; -import com.blade.kit.Assert; -import com.blade.kit.StringKit; -import com.blade.kit.base.Config; -import com.blade.kit.reflect.ReflectKit; -import com.blade.mvc.http.HttpMethod; -import com.blade.mvc.interceptor.Interceptor; -import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteBuilder; -import com.blade.mvc.route.RouteException; -import com.blade.mvc.route.RouteGroup; -import com.blade.mvc.route.RouteHandler; -import com.blade.mvc.route.Routers; -import com.blade.mvc.route.loader.ClassPathRouteLoader; -import com.blade.plugin.Plugin; - -/** - * Blade Core Class - * - * @author biezhi - * @since 1.6.6 - */ -public final class Blade { - - // blade initialize - private boolean isInit = false; - - // blade bootstrap config class - private Bootstrap bootstrap = null; - - // global configuration Object - private ApplicationConfig applicationConfig = null; - - // ioc container - private Ioc ioc = new SimpleIoc(); - - // routes - private Routers routers = new Routers(); - - // routebuilder - private RouteBuilder routeBuilder; - - // jetty start port - private int port = Const.DEFAULT_PORT; - - // default context path - private String contextPath = Const.DEFAULT_CONTEXTPATH; - - // enableServer - private Boolean enableServer = false; - - // plugins - private Set> plugins; - - // global config - private Config config; - - // config loader - private ConfigLoader configLoader; - - // embed server - private EmbedServer embedServer; - - private Blade() { - this.config = new Config(); - this.applicationConfig = new ApplicationConfig(); - this.plugins = new HashSet>(); - this.routeBuilder = new RouteBuilder(this.routers); - this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); - } - - static final class BladeHolder { - private static final Blade $ = new Blade(); - } - - /** - * @return Single case method returns Blade object - */ - @Deprecated - public static final Blade me() { - return BladeHolder.$; - } - - /** - * - * @param location - * @return - */ - @Deprecated - public static final Blade me(String location) { - Blade blade = BladeHolder.$; - blade.config.add(location); - return blade; - } - - /** - * @return Single case method returns Blade object - */ - public static final Blade $() { - return BladeHolder.$; - } - - /** - * @param confPath - * @return - */ - public static final Blade $(String location) { - Assert.notEmpty(location); - Blade blade = BladeHolder.$; - blade.config.add(location); - return blade; - } - - /** - * Set Blade initialize - * - * @param isInit - * initialize - */ - public void init() { - if (!this.isInit) { - this.isInit = true; - } - } - - /** - * @return return route manager - */ - public Routers routers() { - return routers; - } - - /** - * @return return RouteBuilder - */ - public RouteBuilder routeBuilder() { - return routeBuilder; - } - - /** - * @return return ConfigLoader - */ - public ConfigLoader configLoader() { - return configLoader; - } - - /** - * @return return blade ioc container - */ - public Ioc ioc() { - return ioc; - } - - /** - * Setting a ioc container - * - * @param container - * ioc object - * @return return blade - */ - public Blade container(Ioc ioc) { - Assert.notNull(ioc); - this.ioc = ioc; - this.configLoader.setIoc(ioc); - return this; - } - - /** - * Setting Properties configuration file File path based on classpath - * - * @param location properties file name - * @return return blade - */ - public Blade loadAppConf(String location) { - Assert.notBlank(location); - config.add(location); - return this; - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackage(String packageName) { - return this.addRoutePackages(packageName); - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackages(String... packages) { - Assert.notNull(packages); - applicationConfig.addRoutePackages(packages); - return this; - } - - /** - * - * @param basePackage - * @return - */ - public Blade basePackage(String basePackage) { - Assert.notBlank(basePackage); - applicationConfig.setBasePackage(basePackage); - applicationConfig.addIocPackages(basePackage + ".service.*"); - applicationConfig.addRoutePackages(basePackage + ".controller"); - applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); - return this; - } - - /** - * Setting the path where the interceptor, e.g:com.bladejava.interceptor - * - * @param packageName - * interceptor packagename - * @return return blade - */ - public Blade interceptor(String packageName) { - Assert.notBlank(packageName); - applicationConfig.setInterceptorPackage(packageName); - return this; - } - - /** - * Setting Ioc packages, e.g:com.bladejava.service - * - * @param packages - * All need to do into the package, can be introduced into a - * number of - * @return return blade - */ - public Blade ioc(String... packages) { - Assert.notNull(packages); - applicationConfig.addIocPackages(packages); - return this; - } - - /** - * Add a route - * - * @param path - * route path - * @param target - * Target object for routing - * @param method - * The method name of the route (at the same time, the HttpMethod - * is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @return return blade - */ - public Blade route(String path, Class clazz, String method) { - routers.route(path, clazz, method); - return this; - } - - /** - * Register a functional route - * - * @param path - * route url - * @param clazz - * route processing class - * @param method - * route processing method name - * @param httpMethod - * HttpMethod Type, GET/POST/... - * @return Blade return blade - */ - public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { - routers.route(path, clazz, method, httpMethod); - return this; - } - - /** - * Add a route list - * - * @param routes - * route list - * @return return blade - */ - public Blade routes(List routes) { - Assert.notEmpty(routes, "Routes not is empty!"); - routers.addRoutes(routes); - return this; - } - - /** - * Register a GET request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade get(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.GET); - return this; - } - - /** - * Register a POST request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade post(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.POST); - return this; - } - - /** - * Register a DELETE request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade delete(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.DELETE); - return this; - } - - /** - * Register a PUT request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade put(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.PUT); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade all(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade any(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Route Group. e.g blade.group('/users').get().post() - * - * @param g - * @return return blade - */ - public RouteGroup group(String prefix) { - Assert.notNull(prefix, "Route group prefix not is null"); - return new RouteGroup(this, prefix); - } - - /** - * Register a pre routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade before(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.BEFORE); - return this; - } - - /** - * Register a after routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade after(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.AFTER); - return this; - } - - /** - * Setting the frame static file folder - * - * @param resources - * List of directories to filter, e.g: "/public,/static,/images" - * @return return blade - */ - public Blade addResources(final String... resources) { - applicationConfig.addResources(resources); - return this; - } - - /** - * Dynamically set the global initialization class, the embedded Jetty boot - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Bootstrap bootstrap) { - Assert.notNull(bootstrap); - this.bootstrap = bootstrap; - return this; - } - - /** - * Dynamically set global initialization class - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Class bootstrap) { - Assert.notNull(bootstrap); - try { - Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); - ioc.addBean(Bootstrap.class.getName(), object); - this.bootstrap = object; - } catch (Exception e) { - e.printStackTrace(); - } - return this; - } - - /** - * add interceptor - * - * @param interceptor interceptor class - * @return return blade obj - */ - public Blade addInterceptor(Class interceptor) { - routeBuilder.addInterceptor(interceptor); - return this; - } - - /** - * add config - * - * @param config config class - * @return return blade obj - */ - public Blade addConfig(Class config) { - configLoader.addConfig(config); - return this; - } - - /** - * Setting blade web root path - * - * @param webRoot - * web root path - * @return return blade - */ - public Blade webRoot(final String webRoot) { - Assert.notBlank(webRoot); - applicationConfig.setWebRoot(webRoot); - return this; - } - - /** - * Setting blade run mode - * - * @param isDev - * is dev mode - * @return return blade - */ - public Blade isDev(boolean isDev) { - applicationConfig.setDev(isDev); - return this; - } - - /** - * Setting jetty listen port - * - * @param port - * port, default is 9000 - * @return return blade - */ - public Blade listen(int port) { - this.port = port; - return this; - } - - /** - * start web server - */ - public void start() { - this.start(null); - } - - /** - * start web server - * - * @param applicationClass your app root package starter - */ - public void start(Class applicationClass) { - - this.loadAppConf(Const.APP_PROPERTIES); - - // init blade environment config - applicationConfig.setEnv(config); - - if(null != applicationClass){ - applicationConfig.setApplicationClass(applicationClass); - if(StringKit.isBlank(applicationConfig.getBasePackage())){ - applicationConfig.setBasePackage(applicationClass.getPackage().getName()); - } - } - - try { - Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); - if(null == embedClazz){ - embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); - } - if(null != embedClazz){ - this.embedServer = (EmbedServer) embedClazz.newInstance(); - this.embedServer.startup(port, contextPath); - this.enableServer = true; - } else { - throw new EmbedServerException("Not found EmbedServer"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * @return Return EmbedServer - */ - public EmbedServer embedServer() { - return this.embedServer; - } - - /** - * @return Return blade config object - */ - public ApplicationConfig applicationConfig() { - return applicationConfig; - } - - /** - * @return Return blade config object - */ - public Config config() { - return this.config; - } - - /** - * @return Return blade encoding, default is UTF-8 - */ - public String encoding() { - return applicationConfig.getEncoding(); - } - - /** - * @return Return blade web root path - */ - public String webRoot() { - return applicationConfig.getWebRoot(); - } - - /** - * @return Return is dev mode - */ - public boolean isDev() { - return applicationConfig.isDev(); - } - - /** - * @return Return static resource directory - */ - public Set staticFolder() { - return applicationConfig.getStaticFolders(); - } - - /** - * @return Return bootstrap object - */ - public Bootstrap bootstrap() { - return this.bootstrap; - } - - /** - * return register plugin object - * - * @param plugin - * plugin class - * @return return blade - */ - public Blade plugin(Class plugin) { - Assert.notNull(plugin); - plugins.add(plugin); - return this; - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @return return blade - */ - public Blade routeConf(String basePackage) { - return routeConf(basePackage, "route.conf"); - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @param conf - * Configuration file path, the configuration file must be in - * classpath - * @return return blade - */ - public Blade routeConf(String basePackage, String conf) { - try { - Assert.notBlank(basePackage); - Assert.notBlank(conf); - InputStream ins = Blade.class.getResourceAsStream("/" + conf); - ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); - routesLoader.setBasePackage(basePackage); - List routes = routesLoader.load(); - routers.addRoutes(routes); - } catch (RouteException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - return this; - } - - /** - * @return Return blade is initialize - */ - public boolean isInit() { - return isInit; - } - - public Blade enableServer(boolean enableServer) { - this.enableServer = enableServer; - return this; - } - - public boolean enableServer() { - return this.enableServer; - } - - public Set> plugins() { - return this.plugins; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +import java.io.InputStream; +import java.text.ParseException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.blade.config.ApplicationConfig; +import com.blade.config.BaseConfig; +import com.blade.config.ConfigLoader; +import com.blade.embedd.EmbedServer; +import com.blade.exception.EmbedServerException; +import com.blade.ioc.Ioc; +import com.blade.ioc.SimpleIoc; +import com.blade.kit.Assert; +import com.blade.kit.StringKit; +import com.blade.kit.base.Config; +import com.blade.kit.reflect.ReflectKit; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.interceptor.Interceptor; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteBuilder; +import com.blade.mvc.route.RouteException; +import com.blade.mvc.route.RouteGroup; +import com.blade.mvc.route.RouteHandler; +import com.blade.mvc.route.Routers; +import com.blade.mvc.route.loader.ClassPathRouteLoader; +import com.blade.plugin.Plugin; + +/** + * Blade Core Class + * + * @author biezhi + * @since 1.6.6 + */ +public final class Blade { + + // blade initialize + private boolean isInit = false; + + // blade bootstrap config class + private Bootstrap bootstrap = null; + + // global configuration Object + private ApplicationConfig applicationConfig = null; + + // ioc container + private Ioc ioc = new SimpleIoc(); + + // routes + private Routers routers = new Routers(); + + // routebuilder + private RouteBuilder routeBuilder; + + // jetty start port + private int port = Const.DEFAULT_PORT; + + // default context path + private String contextPath = Const.DEFAULT_CONTEXTPATH; + + // enableServer + private Boolean enableServer = false; + + // plugins + private Set> plugins; + + // global config + private Config config; + + // config loader + private ConfigLoader configLoader; + + // embed server + private EmbedServer embedServer; + + private Blade() { + this.config = new Config(); + this.applicationConfig = new ApplicationConfig(); + this.plugins = new HashSet>(); + this.routeBuilder = new RouteBuilder(this.routers); + this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); + } + + static final class BladeHolder { + private static final Blade $ = new Blade(); + } + + /** + * @return Single case method returns Blade object + */ + @Deprecated + public static final Blade me() { + return BladeHolder.$; + } + + /** + * + * @param location + * @return + */ + @Deprecated + public static final Blade me(String location) { + Blade blade = BladeHolder.$; + blade.config.add(location); + return blade; + } + + /** + * @return Single case method returns Blade object + */ + public static final Blade $() { + return BladeHolder.$; + } + + /** + * @param confPath + * @return + */ + public static final Blade $(String location) { + Assert.notEmpty(location); + Blade blade = BladeHolder.$; + blade.config.add(location); + return blade; + } + + /** + * Set Blade initialize + * + * @param isInit + * initialize + */ + public void init() { + if (!this.isInit) { + this.isInit = true; + } + } + + /** + * @return return route manager + */ + public Routers routers() { + return routers; + } + + /** + * @return return RouteBuilder + */ + public RouteBuilder routeBuilder() { + return routeBuilder; + } + + /** + * @return return ConfigLoader + */ + public ConfigLoader configLoader() { + return configLoader; + } + + /** + * @return return blade ioc container + */ + public Ioc ioc() { + return ioc; + } + + /** + * Setting a ioc container + * + * @param container + * ioc object + * @return return blade + */ + public Blade container(Ioc ioc) { + Assert.notNull(ioc); + this.ioc = ioc; + this.configLoader.setIoc(ioc); + return this; + } + + /** + * Setting Properties configuration file File path based on classpath + * + * @param location properties file name + * @return return blade + */ + public Blade loadAppConf(String location) { + Assert.notBlank(location); + try { + config.add(location); + } catch (Exception e) { + + } + return this; + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackage(String packageName) { + return this.addRoutePackages(packageName); + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackages(String... packages) { + Assert.notNull(packages); + applicationConfig.addRoutePackages(packages); + return this; + } + + /** + * + * @param basePackage + * @return + */ + public Blade basePackage(String basePackage) { + Assert.notBlank(basePackage); + applicationConfig.setBasePackage(basePackage); + applicationConfig.addIocPackages(basePackage + ".service.*"); + applicationConfig.addRoutePackages(basePackage + ".controller"); + applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); + return this; + } + + /** + * Setting the path where the interceptor, e.g:com.bladejava.interceptor + * + * @param packageName + * interceptor packagename + * @return return blade + */ + public Blade interceptor(String packageName) { + Assert.notBlank(packageName); + applicationConfig.setInterceptorPackage(packageName); + return this; + } + + /** + * Setting Ioc packages, e.g:com.bladejava.service + * + * @param packages + * All need to do into the package, can be introduced into a + * number of + * @return return blade + */ + public Blade ioc(String... packages) { + Assert.notNull(packages); + applicationConfig.addIocPackages(packages); + return this; + } + + /** + * Add a route + * + * @param path + * route path + * @param target + * Target object for routing + * @param method + * The method name of the route (at the same time, the HttpMethod + * is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade + */ + public Blade route(String path, Class clazz, String method) { + routers.route(path, clazz, method); + return this; + } + + /** + * Register a functional route + * + * @param path + * route url + * @param clazz + * route processing class + * @param method + * route processing method name + * @param httpMethod + * HttpMethod Type, GET/POST/... + * @return Blade return blade + */ + public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { + routers.route(path, clazz, method, httpMethod); + return this; + } + + /** + * Add a route list + * + * @param routes + * route list + * @return return blade + */ + public Blade routes(List routes) { + Assert.notEmpty(routes, "Routes not is empty!"); + routers.addRoutes(routes); + return this; + } + + /** + * Register a GET request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade get(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.GET); + return this; + } + + /** + * Register a POST request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade post(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.POST); + return this; + } + + /** + * Register a DELETE request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade delete(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.DELETE); + return this; + } + + /** + * Register a PUT request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade put(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.PUT); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade all(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade any(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Route Group. e.g blade.group('/users').get().post() + * + * @param g + * @return return blade + */ + public RouteGroup group(String prefix) { + Assert.notNull(prefix, "Route group prefix not is null"); + return new RouteGroup(this, prefix); + } + + /** + * Register a pre routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade before(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.BEFORE); + return this; + } + + /** + * Register a after routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade after(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.AFTER); + return this; + } + + /** + * Setting the frame static file folder + * + * @param resources + * List of directories to filter, e.g: "/public,/static,/images" + * @return return blade + */ + public Blade addResources(final String... resources) { + applicationConfig.addResources(resources); + return this; + } + + /** + * Dynamically set the global initialization class, the embedded Jetty boot + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Bootstrap bootstrap) { + Assert.notNull(bootstrap); + this.bootstrap = bootstrap; + return this; + } + + /** + * Dynamically set global initialization class + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Class bootstrap) { + Assert.notNull(bootstrap); + try { + Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); + ioc.addBean(Bootstrap.class.getName(), object); + this.bootstrap = object; + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + /** + * add interceptor + * + * @param interceptor interceptor class + * @return return blade obj + */ + public Blade addInterceptor(Class interceptor) { + routeBuilder.addInterceptor(interceptor); + return this; + } + + /** + * add config + * + * @param config config class + * @return return blade obj + */ + public Blade addConfig(Class config) { + configLoader.addConfig(config); + return this; + } + + /** + * Setting blade web root path + * + * @param webRoot + * web root path + * @return return blade + */ + public Blade webRoot(final String webRoot) { + Assert.notBlank(webRoot); + applicationConfig.setWebRoot(webRoot); + return this; + } + + /** + * Setting blade run mode + * + * @param isDev + * is dev mode + * @return return blade + */ + public Blade isDev(boolean isDev) { + applicationConfig.setDev(isDev); + return this; + } + + /** + * Setting jetty listen port + * + * @param port + * port, default is 9000 + * @return return blade + */ + public Blade listen(int port) { + this.port = port; + return this; + } + + /** + * start web server + */ + public void start() { + this.start(null); + } + + /** + * start web server + * + * @param applicationClass your app root package starter + */ + public void start(Class applicationClass) { + + this.loadAppConf(Const.APP_PROPERTIES); + + // init blade environment config + applicationConfig.setEnv(config); + + if(null != applicationClass){ + applicationConfig.setApplicationClass(applicationClass); + if(StringKit.isBlank(applicationConfig.getBasePackage())){ + applicationConfig.setBasePackage(applicationClass.getPackage().getName()); + } + } + + try { + Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); + if(null == embedClazz){ + embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); + } + if(null != embedClazz){ + this.embedServer = (EmbedServer) embedClazz.newInstance(); + this.embedServer.startup(port, contextPath); + this.enableServer = true; + } else { + throw new EmbedServerException("Not found EmbedServer"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * @return Return EmbedServer + */ + public EmbedServer embedServer() { + return this.embedServer; + } + + /** + * @return Return blade config object + */ + public ApplicationConfig applicationConfig() { + return applicationConfig; + } + + /** + * @return Return blade config object + */ + public Config config() { + return this.config; + } + + /** + * @return Return blade encoding, default is UTF-8 + */ + public String encoding() { + return applicationConfig.getEncoding(); + } + + /** + * @return Return blade web root path + */ + public String webRoot() { + return applicationConfig.getWebRoot(); + } + + /** + * @return Return is dev mode + */ + public boolean isDev() { + return applicationConfig.isDev(); + } + + /** + * @return Return static resource directory + */ + public Set staticFolder() { + return applicationConfig.getStaticFolders(); + } + + /** + * @return Return bootstrap object + */ + public Bootstrap bootstrap() { + return this.bootstrap; + } + + /** + * return register plugin object + * + * @param plugin + * plugin class + * @return return blade + */ + public Blade plugin(Class plugin) { + Assert.notNull(plugin); + plugins.add(plugin); + return this; + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @return return blade + */ + public Blade routeConf(String basePackage) { + return routeConf(basePackage, "route.conf"); + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @param conf + * Configuration file path, the configuration file must be in + * classpath + * @return return blade + */ + public Blade routeConf(String basePackage, String conf) { + try { + Assert.notBlank(basePackage); + Assert.notBlank(conf); + InputStream ins = Blade.class.getResourceAsStream("/" + conf); + ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); + routesLoader.setBasePackage(basePackage); + List routes = routesLoader.load(); + routers.addRoutes(routes); + } catch (RouteException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return this; + } + + /** + * @return Return blade is initialize + */ + public boolean isInit() { + return isInit; + } + + public Blade enableServer(boolean enableServer) { + this.enableServer = enableServer; + return this; + } + + public boolean enableServer() { + return this.enableServer; + } + + public Set> plugins() { + return this.plugins; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/kit/AsmKit.java b/blade-core/src/main/java/com/blade/kit/AsmKit.java index f1f0d0c3e..ddb94e92b 100644 --- a/blade-core/src/main/java/com/blade/kit/AsmKit.java +++ b/blade-core/src/main/java/com/blade/kit/AsmKit.java @@ -1,129 +1,111 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * ASM Tools - * - * @author biezhi - * @since 1.6.6 - */ -public final class AsmKit { - - /** - * - *

- * 比较参数类型是否一致 - *

- * - * @param types - * asm的类型({@link Type}) - * @param clazzes - * java 类型({@link Class}) - * @return - */ - private static boolean sameType(Type[] types, Class[] clazzes) { - // 个数不同 - if (types.length != clazzes.length) { - return false; - } - for (int i = 0; i < types.length; i++) { - if (!Type.getType(clazzes[i]).equals(types[i])) { - return false; - } - } - return true; - } - - /** - * - *

- * 获取方法的参数名 - *

- * - * @param m - * @return - */ - public static String[] getMethodParamNames(final Method m) throws IOException { - final String[] paramNames = new String[m.getParameterTypes().length]; - final String n = m.getDeclaringClass().getName(); - ClassReader cr = null; - try { - cr = new ClassReader(n); - } catch (IOException e) { - return null; - } - cr.accept(new ClassVisitor(Opcodes.ASM5) { - - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - super.visitInnerClass(name, outerName, innerName, access); - System.out.println("name = " + name); - System.out.println("outerName = " + outerName); - System.out.println("innerName = " + innerName); - System.out.println("access = " + access); - } - - @Override - public void visitOuterClass(String owner, String name, String desc) { - super.visitOuterClass(owner, name, desc); - System.out.println("owner = " + owner); - System.out.println("name = " + name); - System.out.println("desc = " + desc); - } - - @Override - public MethodVisitor visitMethod(final int access, final String name, final String desc, - final String signature, final String[] exceptions) { - final Type[] args = Type.getArgumentTypes(desc); - // 方法名相同并且参数个数相同 - if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { - return super.visitMethod(access, name, desc, signature, exceptions); - } - MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); - return new MethodVisitor(Opcodes.ASM5, v) { - @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, - int index) { - int i = index - 1; - // 如果是静态方法,则第一就是参数 - // 如果不是静态方法,则第一个是"this",然后才是方法的参数 - if (Modifier.isStatic(m.getModifiers())) { - i = index; - } - if (i >= 0 && i < paramNames.length) { - paramNames[i] = name; - } - super.visitLocalVariable(name, desc, signature, start, end, index); - } - }; - } - }, 0); - return paramNames; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.kit; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * ASM Tools + * + * @author biezhi + * @since 1.6.6 + */ +public final class AsmKit { + + /** + * + *

+ * 比较参数类型是否一致 + *

+ * + * @param types + * asm的类型({@link Type}) + * @param clazzes + * java 类型({@link Class}) + * @return + */ + private static boolean sameType(Type[] types, Class[] clazzes) { + // 个数不同 + if (types.length != clazzes.length) { + return false; + } + for (int i = 0; i < types.length; i++) { + if (!Type.getType(clazzes[i]).equals(types[i])) { + return false; + } + } + return true; + } + + /** + * + *

+ * 获取方法的参数名 + *

+ * + * @param m + * @return + */ + public static String[] getMethodParamNames(final Method m) throws IOException { + final String[] paramNames = new String[m.getParameterTypes().length]; + final String n = m.getDeclaringClass().getName(); + ClassReader cr = null; + try { + cr = new ClassReader(n); + } catch (IOException e) { + return null; + } + cr.accept(new ClassVisitor(Opcodes.ASM5) { + @Override + public MethodVisitor visitMethod(final int access, final String name, final String desc, + final String signature, final String[] exceptions) { + final Type[] args = Type.getArgumentTypes(desc); + // 方法名相同并且参数个数相同 + if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { + return super.visitMethod(access, name, desc, signature, exceptions); + } + MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); + return new MethodVisitor(Opcodes.ASM5, v) { + @Override + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, + int index) { + int i = index - 1; + // 如果是静态方法,则第一就是参数 + // 如果不是静态方法,则第一个是"this",然后才是方法的参数 + if (Modifier.isStatic(m.getModifiers())) { + i = index; + } + if (i >= 0 && i < paramNames.length) { + paramNames[i] = name; + } + super.visitLocalVariable(name, desc, signature, start, end, index); + } + }; + } + }, 0); + return paramNames; + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java index 8fc06767c..55ab88741 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java @@ -78,7 +78,7 @@ public Route getRoute(String httpMethod, String path) { List matchRoutes = new ArrayList(6); for(String key : routeKeys){ - String[] keyArr = StringKit.split("#"); + String[] keyArr = StringKit.split(key, '#'); HttpMethod routeMethod = HttpMethod.valueOf(keyArr[1]); if (matchesPath(keyArr[0], cleanPath)) { if (routeMethod == HttpMethod.ALL || HttpMethod.valueOf(httpMethod) == routeMethod) { diff --git a/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java b/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java index 88b4585ed..e514d2c09 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java +++ b/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java @@ -1,78 +1,62 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.template; - -import java.io.IOException; -import java.io.Writer; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.context.WebApplicationContext; -import com.blade.mvc.view.ModelAndView; - - -/** - * JSP Render, Default Render - * - * @author biezhi - * @since 1.6.6 - */ -public final class DefaultEngine implements TemplateEngine { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultEngine.class); - - private String viewPath = "/"; - - public DefaultEngine() { - } - - public DefaultEngine(String viewPath) { - this.viewPath = viewPath; - } - - @Override - public void render(ModelAndView modelAndView, Writer writer) { - HttpServletRequest servletRequest = WebApplicationContext.request().raw(); - HttpServletResponse servletResponse = WebApplicationContext.response().raw(); - - try { - Map model = modelAndView.getModel(); - String realPath = viewPath + modelAndView.getView(); - - if (null != model && !model.isEmpty()) { - Set keys = model.keySet(); - for (String key : keys) { - servletRequest.setAttribute(key, model.get(key)); - } - } - servletRequest.getRequestDispatcher(realPath).forward(servletRequest, servletResponse); - } catch (ServletException e) { - e.printStackTrace(); - LOGGER.error("", e); - } catch (IOException e) { - e.printStackTrace(); - LOGGER.error("", e); - } - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.template; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Writer; + +import javax.servlet.http.HttpServletResponse; + +import com.blade.Blade; +import com.blade.context.WebApplicationContext; +import com.blade.kit.StreamKit; +import com.blade.mvc.view.ModelAndView; + + +/** + * JSP Render, Default Render + * + * @author biezhi + * @since 1.6.6 + */ +public final class DefaultEngine implements TemplateEngine { + + private String templatePath = "/templates/"; + + public DefaultEngine() { + } + + public DefaultEngine(String templatePath) { + this.templatePath = templatePath; + } + + @Override + public void render(ModelAndView modelAndView, Writer writer) throws TemplateException { + try { + HttpServletResponse servletResponse = WebApplicationContext.response().raw(); + servletResponse.setContentType("text/html;charset=utf-8"); + String realPath = new File(Blade.$().webRoot() + File.separatorChar + templatePath + File.separatorChar + modelAndView.getView()).getPath(); + String content = StreamKit.readText(new BufferedReader(new FileReader(new File(realPath)))); + servletResponse.getWriter().print(content); + } catch (IOException e) { + throw new TemplateException(e); + } + } + +} From a46ffa672af8d4118654a34352b15c11da1993cf Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 6 Sep 2016 09:30:28 +0800 Subject: [PATCH 501/545] =?UTF-8?q?=E2=9C=84=20rename=20WebContext=20class?= =?UTF-8?q?=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...tionContext.java => WebContextHolder.java} | 12 +- .../java/com/blade/mvc/DispatcherHandler.java | 412 +++++------ .../java/com/blade/mvc/DispatcherServlet.java | 4 +- .../mvc/http/wrapper/ServletResponse.java | 670 +++++++++--------- .../mvc/view/template/DefaultEngine.java | 124 ++-- .../blade/mvc/view/template/JspEngine.java | 6 +- 6 files changed, 614 insertions(+), 614 deletions(-) rename blade-core/src/main/java/com/blade/context/{WebApplicationContext.java => WebContextHolder.java} (82%) diff --git a/blade-core/src/main/java/com/blade/context/WebApplicationContext.java b/blade-core/src/main/java/com/blade/context/WebContextHolder.java similarity index 82% rename from blade-core/src/main/java/com/blade/context/WebApplicationContext.java rename to blade-core/src/main/java/com/blade/context/WebContextHolder.java index 981784dde..77f6eb3ef 100644 --- a/blade-core/src/main/java/com/blade/context/WebApplicationContext.java +++ b/blade-core/src/main/java/com/blade/context/WebContextHolder.java @@ -27,12 +27,12 @@ * @author biezhi * @since 1.6.6 */ -public class WebApplicationContext { +public class WebContextHolder { /** * BladeWebContext object for the current thread */ - private static ThreadLocal ctx = new ThreadLocal(); + private static ThreadLocal ctx = new ThreadLocal(); /** * ServletContext Object that is created when the application is initialized @@ -49,20 +49,20 @@ public class WebApplicationContext { */ private Response response; - private WebApplicationContext(){} + private WebContextHolder(){} - public static WebApplicationContext me(){ + public static WebContextHolder me(){ return ctx.get(); } public static void init(ServletContext context) { - WebApplicationContext bladeWebContext = new WebApplicationContext(); + WebContextHolder bladeWebContext = new WebContextHolder(); bladeWebContext.context = context; ctx.set(bladeWebContext); } public static void init(ServletContext context, Request request, Response response) { - WebApplicationContext bladeWebContext = new WebApplicationContext(); + WebContextHolder bladeWebContext = new WebContextHolder(); bladeWebContext.context = context; bladeWebContext.request = request; bladeWebContext.response = response; diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index 42ea7149a..4bdb5ed4d 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -1,207 +1,207 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; - -import java.io.IOException; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.context.WebApplicationContext; -import com.blade.exception.BladeException; -import com.blade.ioc.Ioc; -import com.blade.kit.DispatchKit; -import com.blade.kit.StringKit; -import com.blade.mvc.http.HttpStatus; -import com.blade.mvc.http.Path; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.http.wrapper.ServletRequest; -import com.blade.mvc.http.wrapper.ServletResponse; -import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteHandler; -import com.blade.mvc.route.RouteMatcher; -import com.blade.mvc.route.Routers; -import com.blade.mvc.view.ModelAndView; -import com.blade.mvc.view.ViewSettings; -import com.blade.mvc.view.handle.RouteViewHandler; -import com.blade.mvc.view.template.TemplateException; - -/** - * Synchronous request processor - * - * @author biezhi - * @since 1.5 - */ -public class DispatcherHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); - - private Ioc ioc; - - private Blade blade; - - private ServletContext servletContext; - - private RouteMatcher routeMatcher; - - private StaticFileFilter staticFileFilter; - - private RouteViewHandler routeViewHandler; - - public DispatcherHandler(ServletContext servletContext, Routers routers) { - this.servletContext = servletContext; - this.blade = Blade.$(); - this.ioc = blade.ioc(); - this.routeMatcher = new RouteMatcher(routers); - this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); - this.routeViewHandler = new RouteViewHandler(this.ioc); - } - - public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ - - // http method, GET/POST ... - String method = httpRequest.getMethod(); - - // reuqest uri - String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - - // Create Response - Response response = new ServletResponse(httpResponse);; - - // If it is static, the resource is handed over to the filter - if(staticFileFilter.isStatic(uri)){ - LOGGER.debug("Request : {}\t{}", method, uri); - DispatchKit.printStatic(uri, httpRequest, response); - return; - } - - try { - - LOGGER.info("Request : {}\t{}", method, uri); - - Request request = new ServletRequest(httpRequest); - WebApplicationContext.init(servletContext, request, response); - Route route = routeMatcher.getRoute(method, uri); - if (null != route) { - request.setRoute(route); - - // before inteceptor - List befores = routeMatcher.getBefore(uri); - boolean result = invokeInterceptor(request, response, befores); - if(result){ - // execute - this.routeHandle(request, response, route); - if(!request.isAbort()){ - // after inteceptor - List afters = routeMatcher.getAfter(uri); - invokeInterceptor(request, response, afters); - } - } - } else { - // Not found - render404(response, uri); - } - return; - } catch (TemplateException e) { - LOGGER.error("Template error", e); - DispatchKit.printError(e, 500, response); - } catch (BladeException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - }catch (Exception e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } - return; - } - - /** - * 404 view render - * - * @param response response object - * @param uri 404 uri - * @throws IOException - * @throws TemplateException - */ - private void render404(Response response, String uri) throws Exception { - String view404 = ViewSettings.$().getView404(); - if(StringKit.isNotBlank(view404)){ - ModelAndView modelAndView = new ModelAndView(view404); - modelAndView.add("viewName", uri); - response.render( modelAndView ); - } else { - response.status(HttpStatus.NOT_FOUND); - response.html(String.format(Const.VIEW_NOTFOUND, uri)); - } - } - - /** - * Methods to perform the interceptor - * - * @param request request object - * @param response response object - * @param interceptors execute the interceptor list - * @return Return execute is ok - */ - private boolean invokeInterceptor(Request request, Response response, List interceptors) throws Exception { - for (int i = 0, len = interceptors.size(); i < len; i++) { - Route route = interceptors.get(i); - boolean flag = routeViewHandler.intercept(request, response, route); - if (!flag) { - return false; - } - } - return true; - } - - /** - * Actual routing method execution - * - * @param request request object - * @param response response object - * @param route route object - */ - private void routeHandle(Request request, Response response, Route route) throws Exception{ - Object target = route.getTarget(); - if(null == target){ - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - request.initPathParams(route.getPath()); - - // Init context - WebApplicationContext.init(servletContext, request, response); - if(route.getTargetType() == RouteHandler.class){ - RouteHandler routeHandler = (RouteHandler) target; - routeHandler.handle(request, response); - } else { - routeViewHandler.handle(request, response, route); - } - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.context.WebContextHolder; +import com.blade.exception.BladeException; +import com.blade.ioc.Ioc; +import com.blade.kit.DispatchKit; +import com.blade.kit.StringKit; +import com.blade.mvc.http.HttpStatus; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.http.wrapper.ServletRequest; +import com.blade.mvc.http.wrapper.ServletResponse; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteHandler; +import com.blade.mvc.route.RouteMatcher; +import com.blade.mvc.route.Routers; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; +import com.blade.mvc.view.handle.RouteViewHandler; +import com.blade.mvc.view.template.TemplateException; + +/** + * Synchronous request processor + * + * @author biezhi + * @since 1.5 + */ +public class DispatcherHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); + + private Ioc ioc; + + private Blade blade; + + private ServletContext servletContext; + + private RouteMatcher routeMatcher; + + private StaticFileFilter staticFileFilter; + + private RouteViewHandler routeViewHandler; + + public DispatcherHandler(ServletContext servletContext, Routers routers) { + this.servletContext = servletContext; + this.blade = Blade.$(); + this.ioc = blade.ioc(); + this.routeMatcher = new RouteMatcher(routers); + this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); + this.routeViewHandler = new RouteViewHandler(this.ioc); + } + + public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ + + // http method, GET/POST ... + String method = httpRequest.getMethod(); + + // reuqest uri + String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); + + // Create Response + Response response = new ServletResponse(httpResponse);; + + // If it is static, the resource is handed over to the filter + if(staticFileFilter.isStatic(uri)){ + LOGGER.debug("Request : {}\t{}", method, uri); + DispatchKit.printStatic(uri, httpRequest, response); + return; + } + + try { + + LOGGER.info("Request : {}\t{}", method, uri); + + Request request = new ServletRequest(httpRequest); + WebContextHolder.init(servletContext, request, response); + Route route = routeMatcher.getRoute(method, uri); + if (null != route) { + request.setRoute(route); + + // before inteceptor + List befores = routeMatcher.getBefore(uri); + boolean result = invokeInterceptor(request, response, befores); + if(result){ + // execute + this.routeHandle(request, response, route); + if(!request.isAbort()){ + // after inteceptor + List afters = routeMatcher.getAfter(uri); + invokeInterceptor(request, response, afters); + } + } + } else { + // Not found + render404(response, uri); + } + return; + } catch (TemplateException e) { + LOGGER.error("Template error", e); + DispatchKit.printError(e, 500, response); + } catch (BladeException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + }catch (Exception e) { + LOGGER.error(e.getMessage(), e); + DispatchKit.printError(e, 500, response); + } + return; + } + + /** + * 404 view render + * + * @param response response object + * @param uri 404 uri + * @throws IOException + * @throws TemplateException + */ + private void render404(Response response, String uri) throws Exception { + String view404 = ViewSettings.$().getView404(); + if(StringKit.isNotBlank(view404)){ + ModelAndView modelAndView = new ModelAndView(view404); + modelAndView.add("viewName", uri); + response.render( modelAndView ); + } else { + response.status(HttpStatus.NOT_FOUND); + response.html(String.format(Const.VIEW_NOTFOUND, uri)); + } + } + + /** + * Methods to perform the interceptor + * + * @param request request object + * @param response response object + * @param interceptors execute the interceptor list + * @return Return execute is ok + */ + private boolean invokeInterceptor(Request request, Response response, List interceptors) throws Exception { + for (int i = 0, len = interceptors.size(); i < len; i++) { + Route route = interceptors.get(i); + boolean flag = routeViewHandler.intercept(request, response, route); + if (!flag) { + return false; + } + } + return true; + } + + /** + * Actual routing method execution + * + * @param request request object + * @param response response object + * @param route route object + */ + private void routeHandle(Request request, Response response, Route route) throws Exception{ + Object target = route.getTarget(); + if(null == target){ + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + request.initPathParams(route.getPath()); + + // Init context + WebContextHolder.init(servletContext, request, response); + if(route.getTargetType() == RouteHandler.class){ + RouteHandler routeHandler = (RouteHandler) target; + routeHandler.handle(request, response); + } else { + routeViewHandler.handle(request, response, route); + } + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java index 733ea0855..a28368762 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java @@ -31,7 +31,7 @@ import com.blade.Bootstrap; import com.blade.banner.BannerStarter; import com.blade.context.ApplicationContext; -import com.blade.context.WebApplicationContext; +import com.blade.context.WebContextHolder; import com.blade.context.DynamicContext; import com.blade.embedd.EmbedServer; import com.blade.kit.DispatchKit; @@ -91,7 +91,7 @@ public void init(ServletConfig config) throws ServletException { DynamicContext.init(); - WebApplicationContext.init(servletContext); + WebContextHolder.init(servletContext); this.bootstrap = blade.bootstrap(); diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java index e5e2be723..1ef8fa4f5 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java @@ -1,335 +1,335 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http.wrapper; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.context.WebApplicationContext; -import com.blade.kit.Assert; -import com.blade.kit.DispatchKit; -import com.blade.mvc.http.HttpStatus; -import com.blade.mvc.http.Path; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.view.ModelAndView; -import com.blade.mvc.view.ViewSettings; -import com.blade.mvc.view.parser.JSONParser; -import com.blade.mvc.view.template.TemplateEngine; -import com.blade.mvc.view.template.TemplateException; - -/** - * ServletResponse - * - * @author biezhi - * @since 1.5 - */ -public class ServletResponse implements Response { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServletResponse.class); - - private HttpServletResponse response; - - private boolean written = false; - - private ViewSettings viewSettings; - - private TemplateEngine templateEngine; - - private JSONParser jsonParser; - - public ServletResponse(HttpServletResponse response) { - this.response = response; - this.viewSettings = ViewSettings.$(); - this.templateEngine = viewSettings.templateEngine(); - this.jsonParser = viewSettings.JSONParser(); - } - - @Override - public HttpServletResponse raw() { - return response; - } - - @Override - public int status() { - return response.getStatus(); - } - - @Override - public Response status(int status) { - response.setStatus(status); - return this; - } - - @Override - public Response badRequest() { - response.setStatus(HttpStatus.BAD_REQUEST); - return this; - } - - @Override - public Response unauthorized() { - response.setStatus(HttpStatus.UNAUTHORIZED); - return this; - } - - @Override - public Response notFound() { - response.setStatus(HttpStatus.NOT_FOUND); - return this; - } - - @Override - public Response conflict() { - response.setStatus(HttpStatus.CONFLICT); - return this; - } - - @Override - public String contentType() { - return response.getContentType(); - } - - @Override - public Response contentType(String contentType) { - response.setContentType(contentType); - return this; - } - - @Override - public String header(String name) { - return response.getHeader(name); - } - - @Override - public Response header(String name, String value) { - response.setHeader(name, value); - return this; - } - - @Override - public Response cookie(Cookie cookie) { - response.addCookie(cookie); - return this; - } - - @Override - public Response cookie(String name, String value) { - return cookie(name, value); - } - - @Override - public Response cookie(String name, String value, int maxAge) { - return cookie(name, value, maxAge, false); - } - - @Override - public Response cookie(String name, String value, int maxAge, boolean secured) { - return cookie(null, name, value, maxAge, secured); - } - - @Override - public Response cookie(String path, String name, String value, int maxAge, boolean secured) { - Cookie cookie = new Cookie(name, value); - if(null != path){ - cookie.setPath(path); - } - cookie.setMaxAge(maxAge); - cookie.setSecure(secured); - response.addCookie(cookie); - return this; - } - - @Override - public Response removeCookie(Cookie cookie) { - cookie.setMaxAge(0); - response.addCookie(map(cookie)); - return this; - } - - javax.servlet.http.Cookie map(Cookie cookie) { - javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); - servletCookie.setMaxAge(cookie.getMaxAge()); - if (null != cookie.getPath()) { - servletCookie.setPath(cookie.getPath()); - } - if (null != cookie.getDomain()) { - servletCookie.setDomain(cookie.getDomain()); - } - servletCookie.setHttpOnly(cookie.isHttpOnly()); - servletCookie.setSecure(cookie.getSecure()); - return servletCookie; - } - - @Override - public Response removeCookie(String name) { - Cookie cookie = new Cookie(name, ""); - cookie.setMaxAge(0); - response.addCookie(cookie); - return this; - } - - @Override - public Response text(String text) { - try { - this.header("Cache-Control", "no-cache"); - this.contentType("text/plain;charset=utf-8"); - DispatchKit.print(text, response.getWriter()); - this.written = true; - return this; - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return null; - } - - @Override - public Response html(String html) { - try { - this.header("Cache-Control", "no-cache"); - this.contentType("text/html;charset=utf-8"); - - DispatchKit.print(html, response.getWriter()); - this.written = true; - return this; - } catch (UnsupportedEncodingException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return null; - } - - @Override - public Response json(String json) { - Request request = WebApplicationContext.request(); - String userAgent = request.userAgent(); - if (userAgent.contains("MSIE")) { - this.contentType("text/html;charset=utf-8"); - } else { - this.contentType("application/json;charset=utf-8"); - } - try { - this.header("Cache-Control", "no-cache"); - DispatchKit.print(json, response.getWriter()); - this.written = true; - return this; - } catch (UnsupportedEncodingException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return null; - } - - @Override - public Response json(Object bean) { - return this.json(jsonParser.toJSONSting(bean)); - } - - @Override - public Response xml(String xml) { - try { - this.header("Cache-Control", "no-cache"); - this.contentType("text/xml;charset=utf-8"); - DispatchKit.print(xml, response.getWriter()); - this.written = true; - return this; - } catch (UnsupportedEncodingException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return null; - } - - @Override - public ServletOutputStream outputStream() throws IOException { - return response.getOutputStream(); - } - - @Override - public PrintWriter writer() throws IOException { - return response.getWriter(); - } - - @Override - public Response render(String view){ - Assert.notBlank(view, "view not is null"); - - String viewPath = Path.cleanPath(view); - ModelAndView modelAndView = new ModelAndView(viewPath); - try { - templateEngine.render(modelAndView, response.getWriter()); - } catch (TemplateException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return this; - } - - @Override - public Response render(ModelAndView modelAndView) { - Assert.notNull(modelAndView, "ModelAndView not is null!"); - Assert.notBlank(modelAndView.getView(), "view not is null"); - - String viewPath = Path.cleanPath(modelAndView.getView()); - modelAndView.setView(viewPath); - try { - templateEngine.render(modelAndView, response.getWriter()); - } catch (TemplateException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return this; - } - - @Override - public void redirect(String path) { - try { - response.sendRedirect(path); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - } - - @Override - public void go(String path) { - try { - String ctx = WebApplicationContext.servletContext().getContextPath(); - String location = Path.fixPath(ctx + path); - response.sendRedirect(location); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - } - - @Override - public boolean isWritten() { - return written; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http.wrapper; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.WebContextHolder; +import com.blade.kit.Assert; +import com.blade.kit.DispatchKit; +import com.blade.mvc.http.HttpStatus; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; +import com.blade.mvc.view.parser.JSONParser; +import com.blade.mvc.view.template.TemplateEngine; +import com.blade.mvc.view.template.TemplateException; + +/** + * ServletResponse + * + * @author biezhi + * @since 1.5 + */ +public class ServletResponse implements Response { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServletResponse.class); + + private HttpServletResponse response; + + private boolean written = false; + + private ViewSettings viewSettings; + + private TemplateEngine templateEngine; + + private JSONParser jsonParser; + + public ServletResponse(HttpServletResponse response) { + this.response = response; + this.viewSettings = ViewSettings.$(); + this.templateEngine = viewSettings.templateEngine(); + this.jsonParser = viewSettings.JSONParser(); + } + + @Override + public HttpServletResponse raw() { + return response; + } + + @Override + public int status() { + return response.getStatus(); + } + + @Override + public Response status(int status) { + response.setStatus(status); + return this; + } + + @Override + public Response badRequest() { + response.setStatus(HttpStatus.BAD_REQUEST); + return this; + } + + @Override + public Response unauthorized() { + response.setStatus(HttpStatus.UNAUTHORIZED); + return this; + } + + @Override + public Response notFound() { + response.setStatus(HttpStatus.NOT_FOUND); + return this; + } + + @Override + public Response conflict() { + response.setStatus(HttpStatus.CONFLICT); + return this; + } + + @Override + public String contentType() { + return response.getContentType(); + } + + @Override + public Response contentType(String contentType) { + response.setContentType(contentType); + return this; + } + + @Override + public String header(String name) { + return response.getHeader(name); + } + + @Override + public Response header(String name, String value) { + response.setHeader(name, value); + return this; + } + + @Override + public Response cookie(Cookie cookie) { + response.addCookie(cookie); + return this; + } + + @Override + public Response cookie(String name, String value) { + return cookie(name, value); + } + + @Override + public Response cookie(String name, String value, int maxAge) { + return cookie(name, value, maxAge, false); + } + + @Override + public Response cookie(String name, String value, int maxAge, boolean secured) { + return cookie(null, name, value, maxAge, secured); + } + + @Override + public Response cookie(String path, String name, String value, int maxAge, boolean secured) { + Cookie cookie = new Cookie(name, value); + if(null != path){ + cookie.setPath(path); + } + cookie.setMaxAge(maxAge); + cookie.setSecure(secured); + response.addCookie(cookie); + return this; + } + + @Override + public Response removeCookie(Cookie cookie) { + cookie.setMaxAge(0); + response.addCookie(map(cookie)); + return this; + } + + javax.servlet.http.Cookie map(Cookie cookie) { + javax.servlet.http.Cookie servletCookie = new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue()); + servletCookie.setMaxAge(cookie.getMaxAge()); + if (null != cookie.getPath()) { + servletCookie.setPath(cookie.getPath()); + } + if (null != cookie.getDomain()) { + servletCookie.setDomain(cookie.getDomain()); + } + servletCookie.setHttpOnly(cookie.isHttpOnly()); + servletCookie.setSecure(cookie.getSecure()); + return servletCookie; + } + + @Override + public Response removeCookie(String name) { + Cookie cookie = new Cookie(name, ""); + cookie.setMaxAge(0); + response.addCookie(cookie); + return this; + } + + @Override + public Response text(String text) { + try { + this.header("Cache-Control", "no-cache"); + this.contentType("text/plain;charset=utf-8"); + DispatchKit.print(text, response.getWriter()); + this.written = true; + return this; + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + @Override + public Response html(String html) { + try { + this.header("Cache-Control", "no-cache"); + this.contentType("text/html;charset=utf-8"); + + DispatchKit.print(html, response.getWriter()); + this.written = true; + return this; + } catch (UnsupportedEncodingException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + @Override + public Response json(String json) { + Request request = WebContextHolder.request(); + String userAgent = request.userAgent(); + if (userAgent.contains("MSIE")) { + this.contentType("text/html;charset=utf-8"); + } else { + this.contentType("application/json;charset=utf-8"); + } + try { + this.header("Cache-Control", "no-cache"); + DispatchKit.print(json, response.getWriter()); + this.written = true; + return this; + } catch (UnsupportedEncodingException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + @Override + public Response json(Object bean) { + return this.json(jsonParser.toJSONSting(bean)); + } + + @Override + public Response xml(String xml) { + try { + this.header("Cache-Control", "no-cache"); + this.contentType("text/xml;charset=utf-8"); + DispatchKit.print(xml, response.getWriter()); + this.written = true; + return this; + } catch (UnsupportedEncodingException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + @Override + public ServletOutputStream outputStream() throws IOException { + return response.getOutputStream(); + } + + @Override + public PrintWriter writer() throws IOException { + return response.getWriter(); + } + + @Override + public Response render(String view){ + Assert.notBlank(view, "view not is null"); + + String viewPath = Path.cleanPath(view); + ModelAndView modelAndView = new ModelAndView(viewPath); + try { + templateEngine.render(modelAndView, response.getWriter()); + } catch (TemplateException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return this; + } + + @Override + public Response render(ModelAndView modelAndView) { + Assert.notNull(modelAndView, "ModelAndView not is null!"); + Assert.notBlank(modelAndView.getView(), "view not is null"); + + String viewPath = Path.cleanPath(modelAndView.getView()); + modelAndView.setView(viewPath); + try { + templateEngine.render(modelAndView, response.getWriter()); + } catch (TemplateException e) { + LOGGER.error(e.getMessage(), e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return this; + } + + @Override + public void redirect(String path) { + try { + response.sendRedirect(path); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + } + + @Override + public void go(String path) { + try { + String ctx = WebContextHolder.servletContext().getContextPath(); + String location = Path.fixPath(ctx + path); + response.sendRedirect(location); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + } + + @Override + public boolean isWritten() { + return written; + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java b/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java index e514d2c09..72799835e 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java +++ b/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java @@ -1,62 +1,62 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.template; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.Writer; - -import javax.servlet.http.HttpServletResponse; - -import com.blade.Blade; -import com.blade.context.WebApplicationContext; -import com.blade.kit.StreamKit; -import com.blade.mvc.view.ModelAndView; - - -/** - * JSP Render, Default Render - * - * @author biezhi - * @since 1.6.6 - */ -public final class DefaultEngine implements TemplateEngine { - - private String templatePath = "/templates/"; - - public DefaultEngine() { - } - - public DefaultEngine(String templatePath) { - this.templatePath = templatePath; - } - - @Override - public void render(ModelAndView modelAndView, Writer writer) throws TemplateException { - try { - HttpServletResponse servletResponse = WebApplicationContext.response().raw(); - servletResponse.setContentType("text/html;charset=utf-8"); - String realPath = new File(Blade.$().webRoot() + File.separatorChar + templatePath + File.separatorChar + modelAndView.getView()).getPath(); - String content = StreamKit.readText(new BufferedReader(new FileReader(new File(realPath)))); - servletResponse.getWriter().print(content); - } catch (IOException e) { - throw new TemplateException(e); - } - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.template; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Writer; + +import javax.servlet.http.HttpServletResponse; + +import com.blade.Blade; +import com.blade.context.WebContextHolder; +import com.blade.kit.StreamKit; +import com.blade.mvc.view.ModelAndView; + + +/** + * JSP Render, Default Render + * + * @author biezhi + * @since 1.6.6 + */ +public final class DefaultEngine implements TemplateEngine { + + private String templatePath = "/templates/"; + + public DefaultEngine() { + } + + public DefaultEngine(String templatePath) { + this.templatePath = templatePath; + } + + @Override + public void render(ModelAndView modelAndView, Writer writer) throws TemplateException { + try { + HttpServletResponse servletResponse = WebContextHolder.response().raw(); + servletResponse.setContentType("text/html;charset=utf-8"); + String realPath = new File(Blade.$().webRoot() + File.separatorChar + templatePath + File.separatorChar + modelAndView.getView()).getPath(); + String content = StreamKit.readText(new BufferedReader(new FileReader(new File(realPath)))); + servletResponse.getWriter().print(content); + } catch (IOException e) { + throw new TemplateException(e); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java b/blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java index 9ba8ac37c..1b0d1d5a2 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java +++ b/blade-core/src/main/java/com/blade/mvc/view/template/JspEngine.java @@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.blade.context.WebApplicationContext; +import com.blade.context.WebContextHolder; import com.blade.mvc.view.ModelAndView; @@ -64,8 +64,8 @@ public void setSuffix(String suffix) { @Override public void render(ModelAndView modelAndView, Writer writer) throws TemplateException { - HttpServletRequest request = WebApplicationContext.request().raw(); - HttpServletResponse response = WebApplicationContext.response().raw(); + HttpServletRequest request = WebContextHolder.request().raw(); + HttpServletResponse response = WebContextHolder.response().raw(); try { Map model = modelAndView.getModel(); String realPath = viewPath + modelAndView.getView() + suffix; From 0d86feb78bde15f3b5277e88b25dabb7185fa5d8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 6 Sep 2016 11:05:10 +0800 Subject: [PATCH 502/545] =?UTF-8?q?=E2=9C=84=20optimized=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/Blade.java | 1432 ++++++++--------- blade-core/src/main/java/com/blade/Const.java | 118 +- .../com/blade/config/ApplicationConfig.java | 188 +-- .../java/com/blade/config/ConfigLoader.java | 178 +- .../main/java/com/blade/config/Packages.java | 56 + .../java/com/blade/ioc/IocApplication.java | 449 +++--- .../java/com/blade/mvc/DispatcherHandler.java | 2 +- .../com/blade/mvc/route/RouteBuilder.java | 486 +++--- blade-core/src/test/java/config.txt | 31 + .../java/com/blade/kit/timw/TimwCounter.java | 59 - .../java/com/blade/kit/timw/TimwManager.java | 39 - .../java/com/blade/kit/timw/TimwMonitor.java | 118 -- .../java/com/blade/kit/timw/package-info.java | 4 - 13 files changed, 1499 insertions(+), 1661 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/config/Packages.java create mode 100644 blade-core/src/test/java/config.txt delete mode 100644 blade-kit/src/main/java/com/blade/kit/timw/TimwCounter.java delete mode 100644 blade-kit/src/main/java/com/blade/kit/timw/TimwManager.java delete mode 100644 blade-kit/src/main/java/com/blade/kit/timw/TimwMonitor.java delete mode 100644 blade-kit/src/main/java/com/blade/kit/timw/package-info.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index b815a29f4..94450c7ea 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -1,724 +1,710 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -import java.io.InputStream; -import java.text.ParseException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.blade.config.ApplicationConfig; -import com.blade.config.BaseConfig; -import com.blade.config.ConfigLoader; -import com.blade.embedd.EmbedServer; -import com.blade.exception.EmbedServerException; -import com.blade.ioc.Ioc; -import com.blade.ioc.SimpleIoc; -import com.blade.kit.Assert; -import com.blade.kit.StringKit; -import com.blade.kit.base.Config; -import com.blade.kit.reflect.ReflectKit; -import com.blade.mvc.http.HttpMethod; -import com.blade.mvc.interceptor.Interceptor; -import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteBuilder; -import com.blade.mvc.route.RouteException; -import com.blade.mvc.route.RouteGroup; -import com.blade.mvc.route.RouteHandler; -import com.blade.mvc.route.Routers; -import com.blade.mvc.route.loader.ClassPathRouteLoader; -import com.blade.plugin.Plugin; - -/** - * Blade Core Class - * - * @author biezhi - * @since 1.6.6 - */ -public final class Blade { - - // blade initialize - private boolean isInit = false; - - // blade bootstrap config class - private Bootstrap bootstrap = null; - - // global configuration Object - private ApplicationConfig applicationConfig = null; - - // ioc container - private Ioc ioc = new SimpleIoc(); - - // routes - private Routers routers = new Routers(); - - // routebuilder - private RouteBuilder routeBuilder; - - // jetty start port - private int port = Const.DEFAULT_PORT; - - // default context path - private String contextPath = Const.DEFAULT_CONTEXTPATH; - - // enableServer - private Boolean enableServer = false; - - // plugins - private Set> plugins; - - // global config - private Config config; - - // config loader - private ConfigLoader configLoader; - - // embed server - private EmbedServer embedServer; - - private Blade() { - this.config = new Config(); - this.applicationConfig = new ApplicationConfig(); - this.plugins = new HashSet>(); - this.routeBuilder = new RouteBuilder(this.routers); - this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); - } - - static final class BladeHolder { - private static final Blade $ = new Blade(); - } - - /** - * @return Single case method returns Blade object - */ - @Deprecated - public static final Blade me() { - return BladeHolder.$; - } - - /** - * - * @param location - * @return - */ - @Deprecated - public static final Blade me(String location) { - Blade blade = BladeHolder.$; - blade.config.add(location); - return blade; - } - - /** - * @return Single case method returns Blade object - */ - public static final Blade $() { - return BladeHolder.$; - } - - /** - * @param confPath - * @return - */ - public static final Blade $(String location) { - Assert.notEmpty(location); - Blade blade = BladeHolder.$; - blade.config.add(location); - return blade; - } - - /** - * Set Blade initialize - * - * @param isInit - * initialize - */ - public void init() { - if (!this.isInit) { - this.isInit = true; - } - } - - /** - * @return return route manager - */ - public Routers routers() { - return routers; - } - - /** - * @return return RouteBuilder - */ - public RouteBuilder routeBuilder() { - return routeBuilder; - } - - /** - * @return return ConfigLoader - */ - public ConfigLoader configLoader() { - return configLoader; - } - - /** - * @return return blade ioc container - */ - public Ioc ioc() { - return ioc; - } - - /** - * Setting a ioc container - * - * @param container - * ioc object - * @return return blade - */ - public Blade container(Ioc ioc) { - Assert.notNull(ioc); - this.ioc = ioc; - this.configLoader.setIoc(ioc); - return this; - } - - /** - * Setting Properties configuration file File path based on classpath - * - * @param location properties file name - * @return return blade - */ - public Blade loadAppConf(String location) { - Assert.notBlank(location); - try { - config.add(location); - } catch (Exception e) { - - } - return this; - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackage(String packageName) { - return this.addRoutePackages(packageName); - } - - /** - * Setting route package,e.g:com.baldejava.route Can be introduced into - * multiple packages, all of which are in the package. - * - * @param packages - * route package path, is your package name - * @return return blade - */ - public Blade addRoutePackages(String... packages) { - Assert.notNull(packages); - applicationConfig.addRoutePackages(packages); - return this; - } - - /** - * - * @param basePackage - * @return - */ - public Blade basePackage(String basePackage) { - Assert.notBlank(basePackage); - applicationConfig.setBasePackage(basePackage); - applicationConfig.addIocPackages(basePackage + ".service.*"); - applicationConfig.addRoutePackages(basePackage + ".controller"); - applicationConfig.setInterceptorPackage(basePackage + ".interceptor"); - return this; - } - - /** - * Setting the path where the interceptor, e.g:com.bladejava.interceptor - * - * @param packageName - * interceptor packagename - * @return return blade - */ - public Blade interceptor(String packageName) { - Assert.notBlank(packageName); - applicationConfig.setInterceptorPackage(packageName); - return this; - } - - /** - * Setting Ioc packages, e.g:com.bladejava.service - * - * @param packages - * All need to do into the package, can be introduced into a - * number of - * @return return blade - */ - public Blade ioc(String... packages) { - Assert.notNull(packages); - applicationConfig.addIocPackages(packages); - return this; - } - - /** - * Add a route - * - * @param path - * route path - * @param target - * Target object for routing - * @param method - * The method name of the route (at the same time, the HttpMethod - * is specified: post:saveUser, if not specified, HttpMethod.ALL) - * @return return blade - */ - public Blade route(String path, Class clazz, String method) { - routers.route(path, clazz, method); - return this; - } - - /** - * Register a functional route - * - * @param path - * route url - * @param clazz - * route processing class - * @param method - * route processing method name - * @param httpMethod - * HttpMethod Type, GET/POST/... - * @return Blade return blade - */ - public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { - routers.route(path, clazz, method, httpMethod); - return this; - } - - /** - * Add a route list - * - * @param routes - * route list - * @return return blade - */ - public Blade routes(List routes) { - Assert.notEmpty(routes, "Routes not is empty!"); - routers.addRoutes(routes); - return this; - } - - /** - * Register a GET request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade get(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.GET); - return this; - } - - /** - * Register a POST request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade post(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.POST); - return this; - } - - /** - * Register a DELETE request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade delete(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.DELETE); - return this; - } - - /** - * Register a PUT request route - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade put(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.PUT); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade all(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Register for any request routing - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade any(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.ALL); - return this; - } - - /** - * Route Group. e.g blade.group('/users').get().post() - * - * @param g - * @return return blade - */ - public RouteGroup group(String prefix) { - Assert.notNull(prefix, "Route group prefix not is null"); - return new RouteGroup(this, prefix); - } - - /** - * Register a pre routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade before(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.BEFORE); - return this; - } - - /** - * Register a after routing request interceptor - * - * @param path - * route path, request url - * @param handler - * execute route Handle - * @return return blade - */ - public Blade after(String path, RouteHandler handler) { - routers.route(path, handler, HttpMethod.AFTER); - return this; - } - - /** - * Setting the frame static file folder - * - * @param resources - * List of directories to filter, e.g: "/public,/static,/images" - * @return return blade - */ - public Blade addResources(final String... resources) { - applicationConfig.addResources(resources); - return this; - } - - /** - * Dynamically set the global initialization class, the embedded Jetty boot - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Bootstrap bootstrap) { - Assert.notNull(bootstrap); - this.bootstrap = bootstrap; - return this; - } - - /** - * Dynamically set global initialization class - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Class bootstrap) { - Assert.notNull(bootstrap); - try { - Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); - ioc.addBean(Bootstrap.class.getName(), object); - this.bootstrap = object; - } catch (Exception e) { - e.printStackTrace(); - } - return this; - } - - /** - * add interceptor - * - * @param interceptor interceptor class - * @return return blade obj - */ - public Blade addInterceptor(Class interceptor) { - routeBuilder.addInterceptor(interceptor); - return this; - } - - /** - * add config - * - * @param config config class - * @return return blade obj - */ - public Blade addConfig(Class config) { - configLoader.addConfig(config); - return this; - } - - /** - * Setting blade web root path - * - * @param webRoot - * web root path - * @return return blade - */ - public Blade webRoot(final String webRoot) { - Assert.notBlank(webRoot); - applicationConfig.setWebRoot(webRoot); - return this; - } - - /** - * Setting blade run mode - * - * @param isDev - * is dev mode - * @return return blade - */ - public Blade isDev(boolean isDev) { - applicationConfig.setDev(isDev); - return this; - } - - /** - * Setting jetty listen port - * - * @param port - * port, default is 9000 - * @return return blade - */ - public Blade listen(int port) { - this.port = port; - return this; - } - - /** - * start web server - */ - public void start() { - this.start(null); - } - - /** - * start web server - * - * @param applicationClass your app root package starter - */ - public void start(Class applicationClass) { - - this.loadAppConf(Const.APP_PROPERTIES); - - // init blade environment config - applicationConfig.setEnv(config); - - if(null != applicationClass){ - applicationConfig.setApplicationClass(applicationClass); - if(StringKit.isBlank(applicationConfig.getBasePackage())){ - applicationConfig.setBasePackage(applicationClass.getPackage().getName()); - } - } - - try { - Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); - if(null == embedClazz){ - embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); - } - if(null != embedClazz){ - this.embedServer = (EmbedServer) embedClazz.newInstance(); - this.embedServer.startup(port, contextPath); - this.enableServer = true; - } else { - throw new EmbedServerException("Not found EmbedServer"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * @return Return EmbedServer - */ - public EmbedServer embedServer() { - return this.embedServer; - } - - /** - * @return Return blade config object - */ - public ApplicationConfig applicationConfig() { - return applicationConfig; - } - - /** - * @return Return blade config object - */ - public Config config() { - return this.config; - } - - /** - * @return Return blade encoding, default is UTF-8 - */ - public String encoding() { - return applicationConfig.getEncoding(); - } - - /** - * @return Return blade web root path - */ - public String webRoot() { - return applicationConfig.getWebRoot(); - } - - /** - * @return Return is dev mode - */ - public boolean isDev() { - return applicationConfig.isDev(); - } - - /** - * @return Return static resource directory - */ - public Set staticFolder() { - return applicationConfig.getStaticFolders(); - } - - /** - * @return Return bootstrap object - */ - public Bootstrap bootstrap() { - return this.bootstrap; - } - - /** - * return register plugin object - * - * @param plugin - * plugin class - * @return return blade - */ - public Blade plugin(Class plugin) { - Assert.notNull(plugin); - plugins.add(plugin); - return this; - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @return return blade - */ - public Blade routeConf(String basePackage) { - return routeConf(basePackage, "route.conf"); - } - - /** - * Registration of a configuration file, e.g: "com.xxx.route","route.conf" - * - * @param basePackage - * controller package name - * @param conf - * Configuration file path, the configuration file must be in - * classpath - * @return return blade - */ - public Blade routeConf(String basePackage, String conf) { - try { - Assert.notBlank(basePackage); - Assert.notBlank(conf); - InputStream ins = Blade.class.getResourceAsStream("/" + conf); - ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); - routesLoader.setBasePackage(basePackage); - List routes = routesLoader.load(); - routers.addRoutes(routes); - } catch (RouteException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - return this; - } - - /** - * @return Return blade is initialize - */ - public boolean isInit() { - return isInit; - } - - public Blade enableServer(boolean enableServer) { - this.enableServer = enableServer; - return this; - } - - public boolean enableServer() { - return this.enableServer; - } - - public Set> plugins() { - return this.plugins; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +import java.io.InputStream; +import java.text.ParseException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.blade.config.ApplicationConfig; +import com.blade.config.BaseConfig; +import com.blade.config.ConfigLoader; +import com.blade.embedd.EmbedServer; +import com.blade.exception.EmbedServerException; +import com.blade.ioc.Ioc; +import com.blade.ioc.SimpleIoc; +import com.blade.kit.Assert; +import com.blade.kit.StringKit; +import com.blade.kit.base.Config; +import com.blade.kit.reflect.ReflectKit; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.interceptor.Interceptor; +import com.blade.mvc.route.Route; +import com.blade.mvc.route.RouteBuilder; +import com.blade.mvc.route.RouteException; +import com.blade.mvc.route.RouteGroup; +import com.blade.mvc.route.RouteHandler; +import com.blade.mvc.route.Routers; +import com.blade.mvc.route.loader.ClassPathRouteLoader; +import com.blade.plugin.Plugin; + +/** + * Blade Core Class + * + * @author biezhi + * @since 1.6.6 + */ +public final class Blade { + + // blade initialize + private boolean isInit = false; + + // blade bootstrap config class + private Bootstrap bootstrap = null; + + // global configuration Object + private ApplicationConfig applicationConfig = null; + + // ioc container + private Ioc ioc = new SimpleIoc(); + + // routes + private Routers routers = new Routers(); + + // routebuilder + private RouteBuilder routeBuilder; + + // jetty start port + private int port = Const.DEFAULT_PORT; + + // default context path + private String contextPath = Const.DEFAULT_CONTEXTPATH; + + // enableServer + private Boolean enableServer = false; + + // plugins + private Set> plugins; + + // global config + private Config config; + + // config loader + private ConfigLoader configLoader; + + // embed server + private EmbedServer embedServer; + + private Blade() { + this.config = new Config(); + this.applicationConfig = new ApplicationConfig(); + this.plugins = new HashSet>(); + this.routeBuilder = new RouteBuilder(this.routers); + this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); + } + + static final class BladeHolder { + private static final Blade $ = new Blade(); + } + + /** + * @return Single case method returns Blade object + */ + @Deprecated + public static final Blade me() { + return BladeHolder.$; + } + + /** + * + * @param location + * @return + */ + @Deprecated + public static final Blade me(String location) { + Blade blade = BladeHolder.$; + blade.config.add(location); + return blade; + } + + /** + * @return Single case method returns Blade object + */ + public static final Blade $() { + return BladeHolder.$; + } + + /** + * @param confPath + * @return + */ + public static final Blade $(String location) { + Assert.notEmpty(location); + Blade blade = BladeHolder.$; + blade.config.add(location); + return blade; + } + + /** + * Set Blade initialize + * + * @param isInit + * initialize + */ + public void init() { + if (!this.isInit) { + this.isInit = true; + } + } + + /** + * @return return route manager + */ + public Routers routers() { + return routers; + } + + /** + * @return return RouteBuilder + */ + public RouteBuilder routeBuilder() { + return routeBuilder; + } + + /** + * @return return ConfigLoader + */ + public ConfigLoader configLoader() { + return configLoader; + } + + /** + * @return return blade ioc container + */ + public Ioc ioc() { + return ioc; + } + + /** + * Setting a ioc container + * + * @param container + * ioc object + * @return return blade + */ + public Blade container(Ioc ioc) { + Assert.notNull(ioc); + this.ioc = ioc; + this.configLoader.setIoc(ioc); + return this; + } + + /** + * Setting Properties configuration file File path based on classpath + * + * @param location properties file name + * @return return blade + */ + public Blade loadAppConf(String location) { + Assert.notBlank(location); + try { + config.add(location); + } catch (Exception e) { + + } + return this; + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackage(String packageName) { + return this.addRoutePackages(packageName); + } + + /** + * Setting route package,e.g:com.baldejava.route Can be introduced into + * multiple packages, all of which are in the package. + * + * @param packages + * route package path, is your package name + * @return return blade + */ + public Blade addRoutePackages(String... packages) { + applicationConfig.addRoutePkgs(packages); + return this; + } + + /** + * set base package + * + * @param basePackage + * @return + */ + public Blade basePackage(String basePackage) { + applicationConfig.setBasePackage(basePackage); + return this; + } + + /** + * Setting the path where the interceptor, e.g:com.bladejava.interceptor + * + * @param packageName interceptor packagename + * @return return blade + */ + public Blade interceptor(String packageName) { + applicationConfig.setInterceptorPackage(packageName); + return this; + } + + /** + * Setting Ioc packages, e.g:com.bladejava.service + * + * @param packages + * All need to do into the package, can be introduced into a + * number of + * @return return blade + */ + public Blade ioc(String... packages) { + applicationConfig.addIocPkgs(packages); + return this; + } + + /** + * Add a route + * + * @param path + * route path + * @param target + * Target object for routing + * @param method + * The method name of the route (at the same time, the HttpMethod + * is specified: post:saveUser, if not specified, HttpMethod.ALL) + * @return return blade + */ + public Blade route(String path, Class clazz, String method) { + routers.route(path, clazz, method); + return this; + } + + /** + * Register a functional route + * + * @param path + * route url + * @param clazz + * route processing class + * @param method + * route processing method name + * @param httpMethod + * HttpMethod Type, GET/POST/... + * @return Blade return blade + */ + public Blade route(String path, Class clazz, String method, HttpMethod httpMethod) { + routers.route(path, clazz, method, httpMethod); + return this; + } + + /** + * Add a route list + * + * @param routes + * route list + * @return return blade + */ + public Blade routes(List routes) { + Assert.notEmpty(routes, "Routes not is empty!"); + routers.addRoutes(routes); + return this; + } + + /** + * Register a GET request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade get(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.GET); + return this; + } + + /** + * Register a POST request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade post(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.POST); + return this; + } + + /** + * Register a DELETE request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade delete(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.DELETE); + return this; + } + + /** + * Register a PUT request route + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade put(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.PUT); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade all(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Register for any request routing + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade any(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.ALL); + return this; + } + + /** + * Route Group. e.g blade.group('/users').get().post() + * + * @param g + * @return return blade + */ + public RouteGroup group(String prefix) { + Assert.notNull(prefix, "Route group prefix not is null"); + return new RouteGroup(this, prefix); + } + + /** + * Register a pre routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade before(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.BEFORE); + return this; + } + + /** + * Register a after routing request interceptor + * + * @param path + * route path, request url + * @param handler + * execute route Handle + * @return return blade + */ + public Blade after(String path, RouteHandler handler) { + routers.route(path, handler, HttpMethod.AFTER); + return this; + } + + /** + * Setting the frame static file folder + * + * @param resources + * List of directories to filter, e.g: "/public,/static,/images" + * @return return blade + */ + public Blade addResources(final String... resources) { + applicationConfig.addResources(resources); + return this; + } + + /** + * Dynamically set the global initialization class, the embedded Jetty boot + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Bootstrap bootstrap) { + Assert.notNull(bootstrap); + this.bootstrap = bootstrap; + return this; + } + + /** + * Dynamically set global initialization class + * + * @param bootstrap + * global initialization config class + * @return return blade + */ + public Blade app(Class bootstrap) { + Assert.notNull(bootstrap); + try { + Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); + ioc.addBean(Bootstrap.class.getName(), object); + this.bootstrap = object; + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + /** + * add interceptor + * + * @param interceptor interceptor class + * @return return blade obj + */ + public Blade addInterceptor(Class interceptor) { + routeBuilder.addInterceptor(interceptor); + return this; + } + + /** + * add config + * + * @param config config class + * @return return blade obj + */ + public Blade addConfig(Class config) { + configLoader.addConfig(config); + return this; + } + + /** + * Setting blade web root path + * + * @param webRoot + * web root path + * @return return blade + */ + public Blade webRoot(final String webRoot) { + Assert.notBlank(webRoot); + applicationConfig.setWebRoot(webRoot); + return this; + } + + /** + * Setting blade run mode + * + * @param isDev + * is dev mode + * @return return blade + */ + public Blade isDev(boolean isDev) { + applicationConfig.setDev(isDev); + return this; + } + + /** + * Setting jetty listen port + * + * @param port + * port, default is 9000 + * @return return blade + */ + public Blade listen(int port) { + this.port = port; + return this; + } + + /** + * start web server + */ + public void start() { + this.start(null); + } + + /** + * start web server + * + * @param applicationClass your app root package starter + */ + public void start(Class applicationClass) { + + this.loadAppConf(Const.APP_PROPERTIES); + + // init blade environment config + applicationConfig.setEnv(config); + + if(null != applicationClass){ + applicationConfig.setApplicationClass(applicationClass); + if(StringKit.isBlank(applicationConfig.getBasePackage())){ + applicationConfig.setBasePackage(applicationClass.getPackage().getName()); + } + } + + try { + Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); + if(null == embedClazz){ + embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); + } + if(null != embedClazz){ + this.embedServer = (EmbedServer) embedClazz.newInstance(); + this.embedServer.startup(port, contextPath); + this.enableServer = true; + } else { + throw new EmbedServerException("Not found EmbedServer"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * @return Return EmbedServer + */ + public EmbedServer embedServer() { + return this.embedServer; + } + + /** + * @return Return blade config object + */ + public ApplicationConfig applicationConfig() { + return applicationConfig; + } + + /** + * @return Return blade config object + */ + public Config config() { + return this.config; + } + + /** + * @return Return blade encoding, default is UTF-8 + */ + public String encoding() { + return applicationConfig.getEncoding(); + } + + /** + * @return Return blade web root path + */ + public String webRoot() { + return applicationConfig.webRoot(); + } + + /** + * @return Return is dev mode + */ + public boolean isDev() { + return applicationConfig.isDev(); + } + + /** + * @return Return bootstrap object + */ + public Bootstrap bootstrap() { + return this.bootstrap; + } + + /** + * return register plugin object + * + * @param plugin + * plugin class + * @return return blade + */ + public Blade plugin(Class plugin) { + Assert.notNull(plugin); + plugins.add(plugin); + return this; + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @return return blade + */ + public Blade routeConf(String basePackage) { + return routeConf(basePackage, "route.conf"); + } + + /** + * Registration of a configuration file, e.g: "com.xxx.route","route.conf" + * + * @param basePackage + * controller package name + * @param conf + * Configuration file path, the configuration file must be in + * classpath + * @return return blade + */ + public Blade routeConf(String basePackage, String conf) { + try { + Assert.notBlank(basePackage); + Assert.notBlank(conf); + InputStream ins = Blade.class.getResourceAsStream("/" + conf); + ClassPathRouteLoader routesLoader = new ClassPathRouteLoader(ins); + routesLoader.setBasePackage(basePackage); + List routes = routesLoader.load(); + routers.addRoutes(routes); + } catch (RouteException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } + return this; + } + + /** + * @return Return blade is initialize + */ + public boolean isInit() { + return isInit; + } + + public Blade enableServer(boolean enableServer) { + this.enableServer = enableServer; + return this; + } + + public boolean enableServer() { + return this.enableServer; + } + + public Set> plugins() { + return this.plugins; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 639ed20b9..e8a30765f 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -1,54 +1,64 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -/** - * Const Interface - * - * @author biezhi - * @since 1.6.6 - */ -public interface Const { - - // current blade version - String BLADE_VERSION = "1.6.6"; - - // default embedd server context path - String DEFAULT_CONTEXTPATH = "/"; - - // Server 500 error HTML - String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; - - // Server 404 error HTML - String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; - - // Default jetty server port - int DEFAULT_PORT = 9000; - - // Request ThreadPoll context key - String BLADE_EXECUTOR = "blade-req-executor"; - - /**************** - * blade properties - * **************/ - String BLADE_ROUTE = "blade.route"; - String BLADE_IOC = "blade.ioc"; - String BLADE_VIEW_404 = "blade.view404"; - String BLADE_VIEW_500 = "blade.view500"; - String BLADE_DEV = "blade.dev"; - String APP_PROPERTIES = "app.properties"; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; + +/** + * Const Interface + * + * @author biezhi + * @since 1.6.6 + */ +public interface Const { + + // current blade version + String BLADE_VERSION = "1.6.6"; + + // default embedd server context path + String DEFAULT_CONTEXTPATH = "/"; + + // Server 500 error HTML + String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; + + // Server 404 error HTML + String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; + + // Default jetty server port + int DEFAULT_PORT = 9000; + + // Request ThreadPoll context key + String BLADE_EXECUTOR = "blade-req-executor"; + + /*************** + * package names + ***************/ + String ROUTE_PKGS = "route_packages"; + String IOC_PKGS = "ioc_packages"; + String CONFIG_PKGS = "config_packages"; + String RESOURCE_PKGS = "resouce_packages"; + String BASE_PKG = "base_package"; + String INTERCEPTOR_PKG = "interceptor_package"; + + /**************** + * blade properties + * **************/ + String BLADE_ROUTE = "blade.route"; + String BLADE_IOC = "blade.ioc"; + String BLADE_VIEW_404 = "blade.view404"; + String BLADE_VIEW_500 = "blade.view500"; + String BLADE_DEV = "blade.dev"; + String APP_PROPERTIES = "app.properties"; + +} diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 82a6609f1..53af2f24b 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -15,14 +15,14 @@ */ package com.blade.config; -import java.util.Arrays; -import java.util.HashSet; +import static com.blade.Blade.$; + import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.blade.Blade; +import com.blade.Const; import com.blade.kit.Assert; import com.blade.kit.StringKit; import com.blade.kit.base.Config; @@ -39,169 +39,147 @@ public class ApplicationConfig { private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfig.class); - // Storage of all routing packets - private Set routePackages = new HashSet(8); - - // Store all IOC packages - private Set iocPackages = new HashSet(8); - - // Strore all config packages - private Set configPackages = new HashSet(2); - - // Store all filter directories - private Set staticFolders = new HashSet(5); - - // Base package - private String basePackage; + private Packages packages; - // Interceptor package - private String interceptorPackage; - // Encoding private String encoding = "utf-8"; - - // web root path - private String webRoot = ""; // Is dev mode private boolean isDev = true; private boolean isInit = false; + private String webRoot; + private Class applicationClass; public ApplicationConfig() { + this.packages = new Packages(); this.addResources("/public", "/assets", "/static"); } public void setEnv(Config config) { if (null != config && !isInit) { + + // get dev mode this.isDev = config.getBoolean("app.dev", true); - this.addIocPackages(config.get("app.ioc")); + // get ioc packages + packages.put(Const.IOC_PKGS, config.get("app.ioc")); + // get view 404, 500 page ViewSettings.$().setView500(config.get("mvc.view.500")); ViewSettings.$().setView404(config.get("mvc.view.404")); - this.encoding = config.get("mvc.http.encoding", "UTF-8"); + + // get http encoding + this.encoding = config.get("http.encoding", "UTF-8"); + + // get mvc static folders String statics = config.get("mvc.statics"); + // get app base package String basePackage = config.get("app.base-package"); - Integer port = config.getInt("server.port"); - - if (null != port) { - Blade.$().listen(port); - } + + // get server start port + Integer port = config.getInt("server.port", Const.DEFAULT_PORT); + $().listen(port); if (StringKit.isNotBlank(statics)) { - this.addResources(statics.split(",")); + this.addResources(StringKit.split(statics, ',')); } - if (StringKit.isNotBlank(basePackage) && StringKit.isBlank(basePackage)) { + if (StringKit.isNotBlank(basePackage)) { this.setBasePackage(basePackage); } isInit = true; } } - - public String[] getRoutePackages() { - String[] routeArr = new String[routePackages.size()]; - return routePackages.toArray(routeArr); + + public void addRoutePkgs(String... pkgs){ + packages.add(Const.ROUTE_PKGS, pkgs); } - - public void addRoutePackages(String... packages) { - if (null != packages && packages.length > 0) { - routePackages.addAll(Arrays.asList(packages)); - } + + public void addIocPkgs(String... pkgs){ + packages.add(Const.IOC_PKGS, pkgs); } - + public String getBasePackage() { - return basePackage; + return packages.first(Const.BASE_PKG); } - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - this.addConfigPackages(basePackage + ".config"); - this.addIocPackages(basePackage + ".service.*"); - this.addRoutePackages(basePackage + ".controller"); - this.setInterceptorPackage(basePackage + ".interceptor"); + public String[] getConfigPkgs(){ + return packages.array(Const.CONFIG_PKGS); } - - public String[] getIocPackages() { - String[] iocArr = new String[iocPackages.size()]; - return iocPackages.toArray(iocArr); + + public String[] getIocPkgs(){ + return packages.array(Const.IOC_PKGS); } - - public String[] getConfigPackages() { - String[] configArr = new String[configPackages.size()]; - return configPackages.toArray(configArr); + + public String[] getRoutePkgs(){ + return packages.array(Const.ROUTE_PKGS); } - - public void addIocPackages(String... packages) { - if (null != packages && packages.length > 0) { - iocPackages.addAll(Arrays.asList(packages)); - } + + public Set getResources(){ + return packages.values(Const.RESOURCE_PKGS); } - - public void addConfigPackages(String... packages) { - if (null != packages && packages.length > 0) { - configPackages.addAll(Arrays.asList(packages)); - } + + public String getInterceptorPkg(){ + return packages.first(Const.INTERCEPTOR_PKG); } - - public String getInterceptorPackage() { - return interceptorPackage; + + public boolean isDev() { + return isDev; } - - public void setInterceptorPackage(String interceptorPackage) { - this.interceptorPackage = interceptorPackage; + + public String getEncoding() { + return encoding; } - public Set getStaticFolders() { - return staticFolders; + public boolean isInit(){ + return this.isInit; } + public String webRoot() { + return this.webRoot; + } + + public Class getApplicationClass() { + return applicationClass; + } + + public void setApplicationClass(Class applicationClass) { + this.applicationClass = applicationClass; + } + + public void setInterceptorPackage(String interceptorPkg) { + packages.put(Const.INTERCEPTOR_PKG, interceptorPkg); + } + + public void setBasePackage(String basePackage) { + Assert.notBlank(basePackage); + + packages.put(Const.BASE_PKG, basePackage); + packages.put(Const.INTERCEPTOR_PKG, basePackage + ".interceptor"); + + packages.add(Const.CONFIG_PKGS, basePackage + ".config"); + packages.add(Const.IOC_PKGS, basePackage + ".service.*"); + packages.add(Const.ROUTE_PKGS, basePackage + ".controller"); + } + public void addResources(String... resources) { Assert.notNull(resources); for(String resource : resources){ LOGGER.debug("Add Resource: {}", resource); } - staticFolders.addAll(Arrays.asList(resources)); - } - - public String getWebRoot() { - return webRoot; + packages.add(Const.RESOURCE_PKGS, resources); } public void setWebRoot(String webRoot) { this.webRoot = webRoot; } - - public boolean isDev() { - return isDev; - } - + public void setDev(boolean isDev) { this.isDev = isDev; } - - public String getEncoding() { - return encoding; - } - - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - public boolean isInit(){ - return this.isInit; - } - - public Class getApplicationClass() { - return applicationClass; - } - - public void setApplicationClass(Class applicationClass) { - this.applicationClass = applicationClass; - } } diff --git a/blade-core/src/main/java/com/blade/config/ConfigLoader.java b/blade-core/src/main/java/com/blade/config/ConfigLoader.java index 69690522e..b1463fdda 100644 --- a/blade-core/src/main/java/com/blade/config/ConfigLoader.java +++ b/blade-core/src/main/java/com/blade/config/ConfigLoader.java @@ -1,89 +1,89 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.lang.reflect.Modifier; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static com.blade.Blade.$; -import com.blade.context.DynamicContext; -import com.blade.exception.ConfigException; -import com.blade.ioc.Ioc; -import com.blade.ioc.annotation.Component; -import com.blade.kit.CollectionKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; - -/** - * ConfigLoader - * - * @author biezhi - * @since 1.6.6 - */ -public class ConfigLoader { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); - - private ClassReader classReader; - private Ioc ioc; - private ApplicationConfig applicationConfig; - - public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { - this.ioc = ioc; - this.classReader = DynamicContext.getClassReader(); - this.applicationConfig = applicationConfig; - } - - public void setIoc(Ioc ioc){ - this.ioc = ioc; - } - - @SuppressWarnings("unchecked") - public void loadConfig() { - String[] configPackages = $().applicationConfig().getConfigPackages(); - if (null != configPackages && configPackages.length > 0) { - // Scan package all class - try { - for (String packageName : configPackages) { - Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); - if (CollectionKit.isNotEmpty(classes)) { - for (ClassInfo classInfo : classes) { - boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); - if(hasInterface){ - addConfig((Class) classInfo.getClazz()); - } - } - } - } - } catch (ConfigException e) { - LOGGER.error("load config error", e); - } - } - } - - public void addConfig(Class clazz) throws ConfigException { - if (!Modifier.isAbstract(clazz.getModifiers())) { - Object bean = ioc.addBean(clazz); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(applicationConfig); - } - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import java.lang.reflect.Modifier; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.blade.Blade.$; +import com.blade.context.DynamicContext; +import com.blade.exception.ConfigException; +import com.blade.ioc.Ioc; +import com.blade.ioc.annotation.Component; +import com.blade.kit.CollectionKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; + +/** + * ConfigLoader + * + * @author biezhi + * @since 1.6.6 + */ +public class ConfigLoader { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); + + private ClassReader classReader; + private Ioc ioc; + private ApplicationConfig applicationConfig; + + public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { + this.ioc = ioc; + this.classReader = DynamicContext.getClassReader(); + this.applicationConfig = applicationConfig; + } + + public void setIoc(Ioc ioc){ + this.ioc = ioc; + } + + @SuppressWarnings("unchecked") + public void loadConfig() { + String[] configPackages = $().applicationConfig().getConfigPkgs(); + if (null != configPackages && configPackages.length > 0) { + // Scan package all class + try { + for (String packageName : configPackages) { + Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); + if (CollectionKit.isNotEmpty(classes)) { + for (ClassInfo classInfo : classes) { + boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); + if(hasInterface){ + addConfig((Class) classInfo.getClazz()); + } + } + } + } + } catch (ConfigException e) { + LOGGER.error("load config error", e); + } + } + } + + public void addConfig(Class clazz) throws ConfigException { + if (!Modifier.isAbstract(clazz.getModifiers())) { + Object bean = ioc.addBean(clazz); + BaseConfig baseConfig = (BaseConfig) bean; + baseConfig.config(applicationConfig); + } + } + +} diff --git a/blade-core/src/main/java/com/blade/config/Packages.java b/blade-core/src/main/java/com/blade/config/Packages.java new file mode 100644 index 000000000..6927dca27 --- /dev/null +++ b/blade-core/src/main/java/com/blade/config/Packages.java @@ -0,0 +1,56 @@ +package com.blade.config; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.blade.kit.StringKit; + +public class Packages { + + private Map> pool = new HashMap>(8); + + public Packages() { + } + + public void put(String name, String pkg) { + if(null != name && StringKit.isNotBlank(pkg)){ + Set values = new HashSet(1); + values.add(pkg); + pool.put(name, values); + } + } + + public void add(String name, String...pkgs) { + if(null != name && null != pkgs && pkgs.length > 0){ + Set values = pool.get(name); + if(null == values){ + values = new HashSet(pkgs.length); + } + values.addAll(Arrays.asList(pkgs)); + } + } + + public String[] array(String name){ + Set values = pool.get(name); + if(null != values){ + return values.toArray(new String[values.size()]); + } + return null; + } + + public Set values(String name){ + return pool.get(name); + } + + public String first(String name){ + Set values = pool.get(name); + if(null != values && !values.isEmpty()){ + return values.iterator().next(); + } + return null; + } + +} diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 021724507..9f93d6bd1 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -1,227 +1,224 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.comparator.OrderComparator; -import com.blade.config.BaseConfig; -import com.blade.context.DynamicContext; -import com.blade.ioc.annotation.Component; -import com.blade.ioc.annotation.Service; -import com.blade.kit.StringKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; -import com.blade.mvc.annotation.Controller; -import com.blade.mvc.annotation.Intercept; -import com.blade.mvc.annotation.RestController; -import com.blade.mvc.interceptor.Interceptor; -import com.blade.mvc.route.RouteBuilder; - -/** - * IOC container, used to initialize the IOC object - * - * @author biezhi - * @since 1.0 - */ -public class IocApplication { - - private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); - - /** - * aop interceptor - */ - private static List aopInterceptors = new ArrayList(8); - - /** - * Class to read object, load class - */ - private ClassReader classReader = null; - private Blade blade; - private OrderComparator orderComparator; - - public IocApplication() { - this.blade = Blade.$(); - this.classReader = DynamicContext.getClassReader(); - this.orderComparator = new OrderComparator(); - } - - /** - * load config beans - * - * @return - * @throws Exception - */ - private List loadCondigs() throws Exception { - List configs = null; - String[] configPackages = blade.applicationConfig().getConfigPackages(); - if (null != configPackages && configPackages.length > 0) { - configs = new ArrayList(10); - for (String packageName : configPackages) { - Set configClasses = classReader.getClassByAnnotation(packageName, Component.class, false); - if (null != configClasses) { - for (ClassInfo classInfo : configClasses) { - Class[] interfaces = classInfo.getClazz().getInterfaces(); - for (Class in : interfaces) { - if (in.equals(BaseConfig.class)) { - configs.add(classInfo); - } - } - if (classInfo.getClazz().getSuperclass().getName() - .equals("com.blade.aop.AbstractMethodInterceptor")) { - aopInterceptors.add(classInfo.newInstance()); - } - } - } - } - Collections.sort(configs, orderComparator); - } - return configs; - } - - private List loadServices() throws Exception { - List services = null; - String[] configPackages = blade.applicationConfig().getIocPackages(); - if (null != configPackages && configPackages.length > 0) { - services = new ArrayList(20); - for (String packageName : configPackages) { - if (StringKit.isBlank(packageName)) { - continue; - } - // Recursive scan - boolean recursive = false; - if (packageName.endsWith(".*")) { - packageName = packageName.substring(0, packageName.length() - 2); - recursive = true; - } - - // Scan package all class - Set iocClasses = classReader.getClass(packageName, recursive); - for (ClassInfo classInfo : iocClasses) { - Class clazz = classInfo.getClazz(); - if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { - Component component = clazz.getAnnotation(Component.class); - Service service = clazz.getAnnotation(Service.class); - if (null != service || null != component) { - services.add(classInfo); - } - } - } - } - } - return services; - } - - private List loadControllers() { - List controllers = null; - String[] routePackages = blade.applicationConfig().getRoutePackages(); - if (null != routePackages && routePackages.length > 0) { - controllers = new ArrayList(); - for (String packageName : routePackages) { - // Scan all Controoler - controllers.addAll(classReader.getClassByAnnotation(packageName, Controller.class, true)); - controllers.addAll(classReader.getClassByAnnotation(packageName, RestController.class, true)); - } - } - return controllers; - } - - private List loadInterceptors() { - List interceptors = null; - String interceptorPackage = blade.applicationConfig().getInterceptorPackage(); - if (StringKit.isNotBlank(interceptorPackage)) { - interceptors = new ArrayList(10); - Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); - if (null != intes) { - for (ClassInfo classInfo : intes) { - if (null != classInfo.getClazz().getInterfaces() - && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)) { - interceptors.add(classInfo); - } - } - Collections.sort(interceptors, orderComparator); - } - } - return interceptors; - } - - public void initBeans() throws Exception { - List services = this.loadServices(); - List configs = this.loadCondigs(); - List controllers = this.loadControllers(); - // web - List inteceptors = this.loadInterceptors(); - - Ioc ioc = blade.ioc(); - - RouteBuilder routeBuilder = blade.routeBuilder(); - - // 1. init service - if (null != services) { - for (ClassInfo classInfo : services) { - ioc.addBean(classInfo.getClazz()); - } - } - - // 2. init configs - if (null != configs) { - for (ClassInfo classInfo : configs) { - Object bean = ioc.addBean(classInfo.getClazz()); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(blade.applicationConfig()); - } - } - - // 3. init controller - if (null != controllers) { - for (ClassInfo classInfo : controllers) { - ioc.addBean(classInfo.getClazz()); - routeBuilder.addRouter(classInfo.getClazz()); - } - } - - // 4. init interceptor - if (null != inteceptors) { - for (ClassInfo classInfo : inteceptors) { - ioc.addBean(classInfo.getClazz()); - routeBuilder.addInterceptor(classInfo.getClazz()); - } - } - - LOGGER.info("Add Object: {}", ioc.getBeans()); - - // injection - List beanDefines = ioc.getBeanDefines(); - if (null != beanDefines) { - for (BeanDefine beanDefine : beanDefines) { - IocKit.injection(ioc, beanDefine); - } - } - } - - public static List getAopInterceptors() { - return aopInterceptors; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.ioc; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.comparator.OrderComparator; +import com.blade.config.BaseConfig; +import com.blade.context.DynamicContext; +import com.blade.ioc.annotation.Component; +import com.blade.ioc.annotation.Service; +import com.blade.kit.StringKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.mvc.annotation.Controller; +import com.blade.mvc.annotation.Intercept; +import com.blade.mvc.annotation.RestController; +import com.blade.mvc.interceptor.Interceptor; +import com.blade.mvc.route.RouteBuilder; + +/** + * IOC container, used to initialize the IOC object + * + * @author biezhi + * @since 1.0 + */ +public class IocApplication { + + private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); + + /** + * aop interceptor + */ + private static List aopInterceptors = new ArrayList(8); + + /** + * Class to read object, load class + */ + private ClassReader classReader = null; + private Blade blade; + private OrderComparator orderComparator; + + public IocApplication() { + this.blade = Blade.$(); + this.classReader = DynamicContext.getClassReader(); + this.orderComparator = new OrderComparator(); + } + + /** + * load config beans + * + * @return + * @throws Exception + */ + private List loadCondigs() throws Exception { + List configs = null; + String[] configPkgs = blade.applicationConfig().getConfigPkgs(); + if (null != configPkgs && configPkgs.length > 0) { + configs = new ArrayList(10); + for (int i = 0, len = configPkgs.length; i < len; i++) { + Set configClasses = classReader.getClassByAnnotation(configPkgs[i], Component.class, false); + if (null != configClasses) { + for (ClassInfo classInfo : configClasses) { + Class[] interfaces = classInfo.getClazz().getInterfaces(); + for (Class in : interfaces) { + if (in.equals(BaseConfig.class)) { + configs.add(classInfo); + } + } + if (classInfo.getClazz().getSuperclass().getName() + .equals("com.blade.aop.AbstractMethodInterceptor")) { + aopInterceptors.add(classInfo.newInstance()); + } + } + } + } + Collections.sort(configs, orderComparator); + } + return configs; + } + + private List loadServices() throws Exception { + String[] iocPkgs = blade.applicationConfig().getIocPkgs(); + if (null != iocPkgs && iocPkgs.length > 0) { + List services = new ArrayList(20); + for (int i = 0, len = iocPkgs.length; i < len; i++) { + String pkgName = iocPkgs[i]; + if (StringKit.isBlank(pkgName)) { + continue; + } + // Recursive scan + boolean recursive = false; + if (pkgName.endsWith(".*")) { + pkgName = pkgName.substring(0, pkgName.length() - 2); + recursive = true; + } + + // Scan package all class + Set iocClasses = classReader.getClass(pkgName, recursive); + for (ClassInfo classInfo : iocClasses) { + Class clazz = classInfo.getClazz(); + if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { + Component component = clazz.getAnnotation(Component.class); + Service service = clazz.getAnnotation(Service.class); + if (null != service || null != component) { + services.add(classInfo); + } + } + } + } + } + return null; + } + + private List loadControllers() { + String[] routePkgs = blade.applicationConfig().getRoutePkgs(); + if (null != routePkgs && routePkgs.length > 0) { + List controllers = new ArrayList(); + for(int i=0, len=routePkgs.length; i loadInterceptors() { + String interceptorPackage = blade.applicationConfig().getInterceptorPkg(); + if (StringKit.isNotBlank(interceptorPackage)) { + List interceptors = new ArrayList(10); + Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); + if (null != intes) { + for (ClassInfo classInfo : intes) { + if (null != classInfo.getClazz().getInterfaces() + && classInfo.getClazz().getInterfaces()[0].equals(Interceptor.class)) { + interceptors.add(classInfo); + } + } + } + } + return null; + } + + public void initBeans() throws Exception { + List services = this.loadServices(); + List configs = this.loadCondigs(); + List controllers = this.loadControllers(); + // web + List inteceptors = this.loadInterceptors(); + + Ioc ioc = blade.ioc(); + + RouteBuilder routeBuilder = blade.routeBuilder(); + + // 1. init service + if (null != services) { + for(int i=0, len=services.size(); i beanDefines = ioc.getBeanDefines(); + if (null != beanDefines) { + for(int i=0, len=beanDefines.size(); i getAopInterceptors() { + return aopInterceptors; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index 4bdb5ed4d..e78d8b81b 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -74,7 +74,7 @@ public DispatcherHandler(ServletContext servletContext, Routers routers) { this.blade = Blade.$(); this.ioc = blade.ioc(); this.routeMatcher = new RouteMatcher(routers); - this.staticFileFilter = new StaticFileFilter(blade.staticFolder()); + this.staticFileFilter = new StaticFileFilter(blade.applicationConfig().getResources()); this.routeViewHandler = new RouteViewHandler(this.ioc); } diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java index 00597f3c8..478c772d9 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java @@ -1,244 +1,244 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.route; - -import java.lang.reflect.Method; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.context.DynamicContext; -import com.blade.kit.CollectionKit; -import com.blade.kit.StringKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; -import com.blade.mvc.annotation.Controller; -import com.blade.mvc.annotation.Intercept; -import com.blade.mvc.annotation.RestController; -import com.blade.mvc.annotation.Route; -import com.blade.mvc.http.HttpMethod; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.interceptor.Interceptor; - -/** - * Route builder - * - * @author biezhi - * @since 1.5 - */ -public class RouteBuilder { - - private static final Logger LOGGER = LoggerFactory.getLogger(RouteBuilder.class); - - /** - * Class reader, used to scan the class specified in the rules - */ - private ClassReader classReader; - - private Routers routers; - - private String[] routePackages; - - private String interceptorPackage; - - public RouteBuilder(Routers routers) { - this.routers = routers; - this.classReader = DynamicContext.getClassReader(); - } - - /** - * Start building route - */ - public void building() { - - this.routePackages = Blade.$().applicationConfig().getRoutePackages(); - this.interceptorPackage = Blade.$().applicationConfig().getInterceptorPackage(); - - // Route - if(null != routePackages && routePackages.length > 0){ - this.buildRoute(routePackages); - } - - // Inteceptor - if(StringKit.isNotBlank(interceptorPackage)){ - this.buildInterceptor(interceptorPackage); - } - - } - - /** - * Build interceptor - * - * @param interceptorPackages add the interceptor package - */ - private void buildInterceptor(String... interceptorPackages){ - - // Scan all Interceptor - Set classes = null; - - // Traversal Interceptor - for(int i=0, len=interceptorPackages.length; i interceptorClazz = classInfo.getClazz(); - addInterceptor(interceptorClazz); - } - } - } - } - - /** - * Build Route - * - * @param routePackages route packets to add - */ - private void buildRoute(String... routePackages){ - Set classes = null; - // Traverse route - for(int i=0,len=routePackages.length; i pathClazz = classInfo.getClazz(); - this.addRouter(pathClazz); - } - } - } - } - - /** - * Parse Interceptor - * - * @param interceptor resolve the interceptor class - */ - public void addInterceptor(final Class interceptor){ - - boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); - if(null == interceptor || !hasInterface){ - return; - } - - Intercept intercept = interceptor.getAnnotation(Intercept.class); - String partten = "/.*"; - if(null != intercept){ - partten = intercept.value(); - } - - try { - Method before = interceptor.getMethod("before", Request.class, Response.class); - Method after = interceptor.getMethod("after", Request.class, Response.class); - buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); - buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - - } - - /** - * Parse all routing in a controller - * - * @param controller resolve the routing class - */ - public void addRouter(final Class router){ - - Method[] methods = router.getMethods(); - if(null == methods || methods.length == 0){ - return; - } - String nameSpace = null, suffix = null; - - if(null != router.getAnnotation(Controller.class)){ - nameSpace = router.getAnnotation(Controller.class).value(); - suffix = router.getAnnotation(Controller.class).suffix(); - } - - if(null != router.getAnnotation(RestController.class)){ - nameSpace = router.getAnnotation(RestController.class).value(); - suffix = router.getAnnotation(RestController.class).suffix(); - } - - if(null == nameSpace && null == suffix){ - LOGGER.warn("Route [{}] not controller annotation", router.getName()); - return; - } - for (int i = 0, len = methods.length; i < len; i++) { - Method method = methods[i]; - Route mapping = method.getAnnotation(Route.class); - //route method - if (null != mapping) { - // build multiple route - HttpMethod methodType = mapping.method(); - String[] paths = mapping.value(); - if(null != paths && paths.length > 0){ - for(int j=0, plen = paths.length; j 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; - - path = path + suffix; - - return path; - } - - /** - * Build a route - * - * @param target route target execution class - * @param execMethod route execution method - * @param path route path - * @param method route httpmethod - */ - private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - - /** - * Build a route - * - * @param path route path - * @param target route target execution class - * @param execMethod route execution method - * @param method route httpmethod - */ - private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ - routers.buildRoute(path, clazz, execMethod, method); - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.route; + +import static com.blade.Blade.$; + +import java.lang.reflect.Method; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.context.DynamicContext; +import com.blade.kit.CollectionKit; +import com.blade.kit.StringKit; +import com.blade.kit.reflect.ReflectKit; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.mvc.annotation.Controller; +import com.blade.mvc.annotation.Intercept; +import com.blade.mvc.annotation.RestController; +import com.blade.mvc.annotation.Route; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.interceptor.Interceptor; +/** + * Route builder + * + * @author biezhi + * @since 1.5 + */ +public class RouteBuilder { + + private static final Logger LOGGER = LoggerFactory.getLogger(RouteBuilder.class); + + /** + * Class reader, used to scan the class specified in the rules + */ + private ClassReader classReader; + + private Routers routers; + + private String[] routePackages; + + private String interceptorPackage; + + public RouteBuilder(Routers routers) { + this.routers = routers; + this.classReader = DynamicContext.getClassReader(); + } + + /** + * Start building route + */ + public void building() { + + this.routePackages = $().applicationConfig().getRoutePkgs(); + this.interceptorPackage = $().applicationConfig().getInterceptorPkg(); + + // Route + if(null != routePackages && routePackages.length > 0){ + this.buildRoute(routePackages); + } + + // Inteceptor + if(StringKit.isNotBlank(interceptorPackage)){ + this.buildInterceptor(interceptorPackage); + } + + } + + /** + * Build interceptor + * + * @param interceptorPackages add the interceptor package + */ + private void buildInterceptor(String... interceptorPackages){ + + // Scan all Interceptor + Set classes = null; + + // Traversal Interceptor + for(int i=0, len=interceptorPackages.length; i interceptorClazz = classInfo.getClazz(); + addInterceptor(interceptorClazz); + } + } + } + } + + /** + * Build Route + * + * @param routePackages route packets to add + */ + private void buildRoute(String... routePackages){ + Set classes = null; + // Traverse route + for(int i=0,len=routePackages.length; i pathClazz = classInfo.getClazz(); + this.addRouter(pathClazz); + } + } + } + } + + /** + * Parse Interceptor + * + * @param interceptor resolve the interceptor class + */ + public void addInterceptor(final Class interceptor){ + + boolean hasInterface = ReflectKit.hasInterface(interceptor, Interceptor.class); + if(null == interceptor || !hasInterface){ + return; + } + + Intercept intercept = interceptor.getAnnotation(Intercept.class); + String partten = "/.*"; + if(null != intercept){ + partten = intercept.value(); + } + + try { + Method before = interceptor.getMethod("before", Request.class, Response.class); + Method after = interceptor.getMethod("after", Request.class, Response.class); + buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); + buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + + } + + /** + * Parse all routing in a controller + * + * @param controller resolve the routing class + */ + public void addRouter(final Class router){ + + Method[] methods = router.getMethods(); + if(null == methods || methods.length == 0){ + return; + } + String nameSpace = null, suffix = null; + + if(null != router.getAnnotation(Controller.class)){ + nameSpace = router.getAnnotation(Controller.class).value(); + suffix = router.getAnnotation(Controller.class).suffix(); + } + + if(null != router.getAnnotation(RestController.class)){ + nameSpace = router.getAnnotation(RestController.class).value(); + suffix = router.getAnnotation(RestController.class).suffix(); + } + + if(null == nameSpace && null == suffix){ + LOGGER.warn("Route [{}] not controller annotation", router.getName()); + return; + } + for (int i = 0, len = methods.length; i < len; i++) { + Method method = methods[i]; + Route mapping = method.getAnnotation(Route.class); + //route method + if (null != mapping) { + // build multiple route + HttpMethod methodType = mapping.method(); + String[] paths = mapping.value(); + if(null != paths && paths.length > 0){ + for(int j=0, plen = paths.length; j 1 && path.endsWith("/") ? path.substring(0, path.length() - 1) : path; + + path = path + suffix; + + return path; + } + + /** + * Build a route + * + * @param target route target execution class + * @param execMethod route execution method + * @param path route path + * @param method route httpmethod + */ + private void buildRoute(Class clazz, Method execMethod, String path, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + + /** + * Build a route + * + * @param path route path + * @param target route target execution class + * @param execMethod route execution method + * @param method route httpmethod + */ + private void buildInterceptor(String path, Class clazz, Method execMethod, HttpMethod method){ + routers.buildRoute(path, clazz, execMethod, method); + } + } \ No newline at end of file diff --git a/blade-core/src/test/java/config.txt b/blade-core/src/test/java/config.txt new file mode 100644 index 000000000..ab00168f4 --- /dev/null +++ b/blade-core/src/test/java/config.txt @@ -0,0 +1,31 @@ +# this is config struct + +app + base-package + ioc + mvc + view + 404 + 500 + statics + http + encoding + cached + xss +server + port + timeout + + +=> to properties + +app.base-package +app.ioc +app.mvc.view.404 +app.mvc.view.500 +app.mvc.statics +app.http.encoding +app.http.cached +app.http.xss +server.port +server.timeout \ No newline at end of file diff --git a/blade-kit/src/main/java/com/blade/kit/timw/TimwCounter.java b/blade-kit/src/main/java/com/blade/kit/timw/TimwCounter.java deleted file mode 100644 index 89b9a7b63..000000000 --- a/blade-kit/src/main/java/com/blade/kit/timw/TimwCounter.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.timw; - -/** - * 计数器 - *

- *

- * - * @author biezhi - * @since 1.0 - */ -class TimwCounter { - - private long time; - - public TimwCounter() { - start(); - } - - /** - * @return 开始计时并返回当前时间 - */ - public long start() { - time = System.currentTimeMillis(); - return time; - } - - /** - * @return 重新计时并返回当前时间 - */ - public long durationRestart() { - long now = System.currentTimeMillis(); - long d = now - time; - time = now; - return d; - } - - /** - * @return 返回计时花费的时间 - */ - public long duration() { - return System.currentTimeMillis() - time; - } - -} \ No newline at end of file diff --git a/blade-kit/src/main/java/com/blade/kit/timw/TimwManager.java b/blade-kit/src/main/java/com/blade/kit/timw/TimwManager.java deleted file mode 100644 index 822233e8c..000000000 --- a/blade-kit/src/main/java/com/blade/kit/timw/TimwManager.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.timw; - -/** - * 计时管理器 - *

- * 用于创建计时器 - *

- * - * @author biezhi - * @since 1.0 - */ -public final class TimwManager { - - private TimwManager() { - } - - /** - * @return 返回一个计时器对象 - */ - public static TimwMonitor getTimerMonitor(){ - return new TimwMonitor(); - } - -} diff --git a/blade-kit/src/main/java/com/blade/kit/timw/TimwMonitor.java b/blade-kit/src/main/java/com/blade/kit/timw/TimwMonitor.java deleted file mode 100644 index 2c1fc370b..000000000 --- a/blade-kit/src/main/java/com/blade/kit/timw/TimwMonitor.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.timw; - -import com.blade.kit.TimwKit; - -/** - * 计时器 - *

- * 用于统计计时的类 - *

- * - * @author biezhi - * @since 1.0 - */ -public class TimwMonitor { - - /** - * 计时器 - */ - private TimwCounter timeCounter; - - /** - * 均值器 - */ - private TimwKit timwKit; - - TimwMonitor() { - this.timeCounter = new TimwCounter(); - this.timwKit = new TimwKit(); - } - - - public TimwCounter getTimeCounter() { - return timeCounter; - } - - public TimwKit getTimwKit() { - return timwKit; - } - - /** - * 一个计时开始 - */ - public void start() { - timeCounter.start(); - } - - /** - * 一个计时结束 - */ - public void end() { - long time = timeCounter.duration(); - timwKit.add(time); - } - - /** - * 一个计时结束,并且启动下次计时。 - */ - public long endAndRestart() { - long time = timeCounter.durationRestart(); - timwKit.add(time); - return time; - } - - public int size() { - return timwKit.size(); - } - - /** - * 求全部计时均值 - */ - public Number avg() { - return timwKit.avg(); - } - - /** - * 求全部计时均值 - */ - public Number current() { - return timwKit.current(); - } - - /** - * 打印全部时间值 - */ - public String render() { - return timwKit.print(); - } - - /** - * 打印全部时间值 - */ - public String renderAvg() { - return timwKit.printAvg(); - } - - /** - * 清楚数据 - */ - public void clear() { - timwKit.clear(); - } - -} diff --git a/blade-kit/src/main/java/com/blade/kit/timw/package-info.java b/blade-kit/src/main/java/com/blade/kit/timw/package-info.java deleted file mode 100644 index e89c0c7a6..000000000 --- a/blade-kit/src/main/java/com/blade/kit/timw/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 计时器包 - */ -package com.blade.kit.timw; \ No newline at end of file From 53e868f17368450fa9526a5f62210065881a13bb Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 6 Sep 2016 13:48:58 +0800 Subject: [PATCH 503/545] =?UTF-8?q?=E2=9C=84=20add=20custom=20banner=20tex?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LAST_VERSION.md | 4 +- blade-core/pom.xml | 5 + .../java/com/blade/banner/BannerFont.java | 247 ++ .../java/com/blade/banner/BannerStarter.java | 67 +- blade-core/src/main/java/standard.flf | 2227 +++++++++++++++++ 5 files changed, 2519 insertions(+), 31 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/banner/BannerFont.java create mode 100644 blade-core/src/main/java/standard.flf diff --git a/LAST_VERSION.md b/LAST_VERSION.md index ac62fcac5..89418b7a3 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -25,7 +25,7 @@     com.bladejava     blade-kit -    1.3.3 +    1.3.4 ``` @@ -43,7 +43,7 @@     com.bladejava     blade-embed-jetty -    0.0.4 +    0.0.5 ``` diff --git a/blade-core/pom.xml b/blade-core/pom.xml index d35da3f20..93505d3fe 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -34,6 +34,11 @@ + com.github.lalyos + jfiglet + 0.0.7 + + javax.servlet javax.servlet-api ${servlet.version} diff --git a/blade-core/src/main/java/com/blade/banner/BannerFont.java b/blade-core/src/main/java/com/blade/banner/BannerFont.java new file mode 100644 index 000000000..3b24d9699 --- /dev/null +++ b/blade-core/src/main/java/com/blade/banner/BannerFont.java @@ -0,0 +1,247 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.banner; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.StringTokenizer; + +public class BannerFont { + + private final int height; + private final int heightWithoutDescenders; + private final int maxLine; + private final int smushMode; + private final char font[][][] = new char[256][][]; + private final String fontName; + + public static BannerFont load() throws IOException { + return load("standard.flf"); + } + + public static BannerFont load(String fontName) throws IOException { + return new BannerFont(BannerFont.class.getResource('/' + fontName)); + } + + public BannerFont(URL url) throws IOException { + this(fontLines(url)); + } + + private BannerFont(Iterator lines) { + String dummyS = lines.next(); + StringTokenizer st = new StringTokenizer(dummyS, " "); + String s = st.nextToken(); + char hardblank = s.charAt(s.length() - 1); + height = Integer.parseInt(st.nextToken()); + heightWithoutDescenders = Integer.parseInt(st.nextToken()); + maxLine = Integer.parseInt(st.nextToken()); + smushMode = Integer.parseInt(st.nextToken()); + int dummyI = Integer.parseInt(st.nextToken()); + + st = new StringTokenizer(lines.next(), " "); + if (st.hasMoreElements()) + fontName = st.nextToken(); + else + fontName = ""; + + for (int i = 0; i < dummyI - 1; i++){ + dummyS = lines.next(); + } + for (int i = 32; i < 256; i++) { + for (int h = 0; h < height; h++) { + dummyS = lines.hasNext() ? lines.next() : null; + if (dummyS == null){ + i = 256; + } else { + // System.out.println(dummyS); + int iNormal = i; + boolean abnormal = true; + if (h == 0) { + try { + i = Integer.parseInt(dummyS); + } catch (NumberFormatException e) { + abnormal = false; + } + if (abnormal) { + dummyS = lines.next(); + } else { + i = iNormal; + } + } + if (h == 0) + font[i] = new char[height][]; + int t = dummyS.length() - 1 - ((h == height - 1) ? 1 : 0); + if (height == 1) + t++; + font[i][h] = new char[t]; + for (int l = 0; l < t; l++) { + char a = dummyS.charAt(l); + font[i][h][l] = (a == hardblank) ? ' ' : a; + } + } + } + } + } + + @SuppressWarnings("deprecation") + private static Iterator fontLines(URL url) throws IOException { + InputStream ins = url.openStream(); + DataInputStream dis = new DataInputStream(new BufferedInputStream(ins)); + ArrayList list = new ArrayList(); + String line = null; + while (true) { + line = dis.readLine(); + if (line != null) { + list.add(line); + } else { + break; + } + } + dis.close(); + return list.iterator(); + } + + public int getHeight() { + return height; + } + + public int getMaxLine() { + return maxLine; + } + + public int getSmushMode() { + return smushMode; + } + + public int getHeightWithoutDescenders() { + return heightWithoutDescenders; + } + + public String getFontName() { + return fontName; + } + + private String getCharLineString(int c, int l) { + if (font[c][l] == null){ + return null; + } else { + return new String(font[c][l]); + } + } + + private static String scroll(String text, int offset) { + StringBuffer result = new StringBuffer(); + StringBuffer shift = new StringBuffer(); + for (int i = 0; i < offset; i++){ + shift.append(' '); + } + StringTokenizer st = new StringTokenizer(text, "\r\n"); + while (st.hasMoreElements()){ + result.append(shift.toString() + st.nextToken() + "\r\n"); + } + return result.toString(); + } + + private static String addLine(String text, String line, boolean leftJustify, int splitWidth) { + String result = text; + if (leftJustify){ + result += line; + } else { + result += scroll(line, (splitWidth / 2 - width(line) / 2)); + } + return result; + } + + public String asAscii(String text) { + return asAscii(text, false, true, 1024); + } + + public String asAscii(String text, boolean splitAtWord, boolean leftJustify, int splitWidth) { + String result = ""; + StringTokenizer st = new StringTokenizer(text, " "); + if (splitAtWord) { + while (st.hasMoreElements()){ + result = addLine(result, convertOneLine(st.nextToken()), leftJustify, splitWidth); + } + } else { + String line = ""; + while (st.hasMoreElements()) { + String w = st.nextToken(), word; + if (line.length() == 0) { + word = w; + } else { + word = ' ' + w; + } + String newLine = append(line, word); + if ((width(newLine) > splitWidth) && (line.length() > 0)) { + result = addLine(result, line + "\r\n", leftJustify, splitWidth); + line = append("", w); + } else + line = newLine; + } + if (line.length() > 0){ + result = addLine(result, line + "\r\n", leftJustify, splitWidth); + } + } + return result; + } + + private static int width(String text) { + int w = 0; + StringTokenizer st = new StringTokenizer(text, "\r\n"); + while (st.hasMoreElements()) + w = Math.max(w, st.nextToken().length()); + return w; + } + + private String convertOneLine(String text) { + String result = ""; + for (int l = 0; l < height; l++) { // for each line + for (int c = 0; c < text.length(); c++) // for each char + result += getCharLineString((int) text.charAt(c), l); + result += "\r\n"; + } + return result; + } + + private String append(String text, String end) { + StringBuffer result = new StringBuffer(); + int h = 0; + if (text.length() == 0){ + for (int i = 0; i < height; i++){ + text += " \r\n"; + } + } + StringTokenizer st = new StringTokenizer(text, "\r\n"); + int count = st.countTokens(); + while (st.hasMoreElements()) { + result.append(st.nextToken()); + for (int c = 0; c < end.length(); c++){ + result.append(getCharLineString((int) end.charAt(c), h)); + } + if(h < (count - 2)){ + result.append("\r\n"); + } + h++; + } + return result.toString(); + } +} diff --git a/blade-core/src/main/java/com/blade/banner/BannerStarter.java b/blade-core/src/main/java/com/blade/banner/BannerStarter.java index 529be89e2..0fcc3ea3f 100644 --- a/blade-core/src/main/java/com/blade/banner/BannerStarter.java +++ b/blade-core/src/main/java/com/blade/banner/BannerStarter.java @@ -1,29 +1,38 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.banner; - -public final class BannerStarter { - - private static Banner BANNER = new BladeBanner(); - - public static void printStart(){ - System.out.println(BANNER.startText()); - } - - public static void banner(Banner banner){ - BANNER = banner; - } -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.banner; + +public final class BannerStarter { + + private static Banner BANNER = new BladeBanner(); + + public static void printStart(){ + System.out.println(BANNER.startText()); + } + + public static void banner(Banner banner){ + BANNER = banner; + } + + public static void banner(final String text){ + BANNER = new Banner() { + @Override + public String startText() { + return text; + } + }; + } +} diff --git a/blade-core/src/main/java/standard.flf b/blade-core/src/main/java/standard.flf new file mode 100644 index 000000000..b1fc5eb17 --- /dev/null +++ b/blade-core/src/main/java/standard.flf @@ -0,0 +1,2227 @@ +flf2a$ 6 5 16 15 11 0 24463 229 +Standard by Glenn Chappell & Ian Chai 3/93 -- based on Frank's .sig +Includes ISO Latin-1 +figlet release 2.1 -- 12 Aug 1994 +Modified for figlet 2.2 by John Cowan + to add Latin-{2,3,4,5} support (Unicode U+0100-017F). +Permission is hereby given to modify this font, as long as the +modifier's name is placed on a comment line. + +Modified by Paul Burton 12/96 to include new parameter +supported by FIGlet and FIGWin. May also be slightly modified for better use +of new full-width/kern/smush alternatives, but default output is NOT changed. + $@ + $@ + $@ + $@ + $@ + $@@ + _ @ + | |@ + | |@ + |_|@ + (_)@ + @@ + _ _ @ + ( | )@ + V V @ + $ @ + $ @ + @@ + _ _ @ + _| || |_ @ + |_ .. _|@ + |_ _|@ + |_||_| @ + @@ + _ @ + | | @ + / __)@ + \__ \@ + ( /@ + |_| @@ + _ __@ + (_)/ /@ + / / @ + / /_ @ + /_/(_)@ + @@ + ___ @ + ( _ ) @ + / _ \/\@ + | (_> <@ + \___/\/@ + @@ + _ @ + ( )@ + |/ @ + $ @ + $ @ + @@ + __@ + / /@ + | | @ + | | @ + | | @ + \_\@@ + __ @ + \ \ @ + | |@ + | |@ + | |@ + /_/ @@ + @ + __/\__@ + \ /@ + /_ _\@ + \/ @ + @@ + @ + _ @ + _| |_ @ + |_ _|@ + |_| @ + @@ + @ + @ + @ + _ @ + ( )@ + |/ @@ + @ + @ + _____ @ + |_____|@ + $ @ + @@ + @ + @ + @ + _ @ + (_)@ + @@ + __@ + / /@ + / / @ + / / @ + /_/ @ + @@ + ___ @ + / _ \ @ + | | | |@ + | |_| |@ + \___/ @ + @@ + _ @ + / |@ + | |@ + | |@ + |_|@ + @@ + ____ @ + |___ \ @ + __) |@ + / __/ @ + |_____|@ + @@ + _____ @ + |___ / @ + |_ \ @ + ___) |@ + |____/ @ + @@ + _ _ @ + | || | @ + | || |_ @ + |__ _|@ + |_| @ + @@ + ____ @ + | ___| @ + |___ \ @ + ___) |@ + |____/ @ + @@ + __ @ + / /_ @ + | '_ \ @ + | (_) |@ + \___/ @ + @@ + _____ @ + |___ |@ + / / @ + / / @ + /_/ @ + @@ + ___ @ + ( _ ) @ + / _ \ @ + | (_) |@ + \___/ @ + @@ + ___ @ + / _ \ @ + | (_) |@ + \__, |@ + /_/ @ + @@ + @ + _ @ + (_)@ + _ @ + (_)@ + @@ + @ + _ @ + (_)@ + _ @ + ( )@ + |/ @@ + __@ + / /@ + / / @ + \ \ @ + \_\@ + @@ + @ + _____ @ + |_____|@ + |_____|@ + $ @ + @@ + __ @ + \ \ @ + \ \@ + / /@ + /_/ @ + @@ + ___ @ + |__ \@ + / /@ + |_| @ + (_) @ + @@ + ____ @ + / __ \ @ + / / _` |@ + | | (_| |@ + \ \__,_|@ + \____/ @@ + _ @ + / \ @ + / _ \ @ + / ___ \ @ + /_/ \_\@ + @@ + ____ @ + | __ ) @ + | _ \ @ + | |_) |@ + |____/ @ + @@ + ____ @ + / ___|@ + | | @ + | |___ @ + \____|@ + @@ + ____ @ + | _ \ @ + | | | |@ + | |_| |@ + |____/ @ + @@ + _____ @ + | ____|@ + | _| @ + | |___ @ + |_____|@ + @@ + _____ @ + | ___|@ + | |_ @ + | _| @ + |_| @ + @@ + ____ @ + / ___|@ + | | _ @ + | |_| |@ + \____|@ + @@ + _ _ @ + | | | |@ + | |_| |@ + | _ |@ + |_| |_|@ + @@ + ___ @ + |_ _|@ + | | @ + | | @ + |___|@ + @@ + _ @ + | |@ + _ | |@ + | |_| |@ + \___/ @ + @@ + _ __@ + | |/ /@ + | ' / @ + | . \ @ + |_|\_\@ + @@ + _ @ + | | @ + | | @ + | |___ @ + |_____|@ + @@ + __ __ @ + | \/ |@ + | |\/| |@ + | | | |@ + |_| |_|@ + @@ + _ _ @ + | \ | |@ + | \| |@ + | |\ |@ + |_| \_|@ + @@ + ___ @ + / _ \ @ + | | | |@ + | |_| |@ + \___/ @ + @@ + ____ @ + | _ \ @ + | |_) |@ + | __/ @ + |_| @ + @@ + ___ @ + / _ \ @ + | | | |@ + | |_| |@ + \__\_\@ + @@ + ____ @ + | _ \ @ + | |_) |@ + | _ < @ + |_| \_\@ + @@ + ____ @ + / ___| @ + \___ \ @ + ___) |@ + |____/ @ + @@ + _____ @ + |_ _|@ + | | @ + | | @ + |_| @ + @@ + _ _ @ + | | | |@ + | | | |@ + | |_| |@ + \___/ @ + @@ + __ __@ + \ \ / /@ + \ \ / / @ + \ V / @ + \_/ @ + @@ + __ __@ + \ \ / /@ + \ \ /\ / / @ + \ V V / @ + \_/\_/ @ + @@ + __ __@ + \ \/ /@ + \ / @ + / \ @ + /_/\_\@ + @@ + __ __@ + \ \ / /@ + \ V / @ + | | @ + |_| @ + @@ + _____@ + |__ /@ + / / @ + / /_ @ + /____|@ + @@ + __ @ + | _|@ + | | @ + | | @ + | | @ + |__|@@ + __ @ + \ \ @ + \ \ @ + \ \ @ + \_\@ + @@ + __ @ + |_ |@ + | |@ + | |@ + | |@ + |__|@@ + /\ @ + |/\|@ + $ @ + $ @ + $ @ + @@ + @ + @ + @ + @ + _____ @ + |_____|@@ + _ @ + ( )@ + \|@ + $ @ + $ @ + @@ + @ + __ _ @ + / _` |@ + | (_| |@ + \__,_|@ + @@ + _ @ + | |__ @ + | '_ \ @ + | |_) |@ + |_.__/ @ + @@ + @ + ___ @ + / __|@ + | (__ @ + \___|@ + @@ + _ @ + __| |@ + / _` |@ + | (_| |@ + \__,_|@ + @@ + @ + ___ @ + / _ \@ + | __/@ + \___|@ + @@ + __ @ + / _|@ + | |_ @ + | _|@ + |_| @ + @@ + @ + __ _ @ + / _` |@ + | (_| |@ + \__, |@ + |___/ @@ + _ @ + | |__ @ + | '_ \ @ + | | | |@ + |_| |_|@ + @@ + _ @ + (_)@ + | |@ + | |@ + |_|@ + @@ + _ @ + (_)@ + | |@ + | |@ + _/ |@ + |__/ @@ + _ @ + | | __@ + | |/ /@ + | < @ + |_|\_\@ + @@ + _ @ + | |@ + | |@ + | |@ + |_|@ + @@ + @ + _ __ ___ @ + | '_ ` _ \ @ + | | | | | |@ + |_| |_| |_|@ + @@ + @ + _ __ @ + | '_ \ @ + | | | |@ + |_| |_|@ + @@ + @ + ___ @ + / _ \ @ + | (_) |@ + \___/ @ + @@ + @ + _ __ @ + | '_ \ @ + | |_) |@ + | .__/ @ + |_| @@ + @ + __ _ @ + / _` |@ + | (_| |@ + \__, |@ + |_|@@ + @ + _ __ @ + | '__|@ + | | @ + |_| @ + @@ + @ + ___ @ + / __|@ + \__ \@ + |___/@ + @@ + _ @ + | |_ @ + | __|@ + | |_ @ + \__|@ + @@ + @ + _ _ @ + | | | |@ + | |_| |@ + \__,_|@ + @@ + @ + __ __@ + \ \ / /@ + \ V / @ + \_/ @ + @@ + @ + __ __@ + \ \ /\ / /@ + \ V V / @ + \_/\_/ @ + @@ + @ + __ __@ + \ \/ /@ + > < @ + /_/\_\@ + @@ + @ + _ _ @ + | | | |@ + | |_| |@ + \__, |@ + |___/ @@ + @ + ____@ + |_ /@ + / / @ + /___|@ + @@ + __@ + / /@ + | | @ + < < @ + | | @ + \_\@@ + _ @ + | |@ + | |@ + | |@ + | |@ + |_|@@ + __ @ + \ \ @ + | | @ + > >@ + | | @ + /_/ @@ + /\/|@ + |/\/ @ + $ @ + $ @ + $ @ + @@ + _ _ @ + (_)_(_)@ + /_\ @ + / _ \ @ + /_/ \_\@ + @@ + _ _ @ + (_)_(_)@ + / _ \ @ + | |_| |@ + \___/ @ + @@ + _ _ @ + (_) (_)@ + | | | |@ + | |_| |@ + \___/ @ + @@ + _ _ @ + (_)_(_)@ + / _` |@ + | (_| |@ + \__,_|@ + @@ + _ _ @ + (_)_(_)@ + / _ \ @ + | (_) |@ + \___/ @ + @@ + _ _ @ + (_) (_)@ + | | | |@ + | |_| |@ + \__,_|@ + @@ + ___ @ + / _ \@ + | |/ /@ + | |\ \@ + | ||_/@ + |_| @@ +160 NO-BREAK SPACE + $@ + $@ + $@ + $@ + $@ + $@@ +161 INVERTED EXCLAMATION MARK + _ @ + (_)@ + | |@ + | |@ + |_|@ + @@ +162 CENT SIGN + _ @ + | | @ + / __)@ + | (__ @ + \ )@ + |_| @@ +163 POUND SIGN + ___ @ + / ,_\ @ + _| |_ @ + | |___ @ + (_,____|@ + @@ +164 CURRENCY SIGN + /\___/\@ + \ _ /@ + | (_) |@ + / ___ \@ + \/ \/@ + @@ +165 YEN SIGN + __ __ @ + \ V / @ + |__ __|@ + |__ __|@ + |_| @ + @@ +166 BROKEN BAR + _ @ + | |@ + |_|@ + _ @ + | |@ + |_|@@ +167 SECTION SIGN + __ @ + _/ _)@ + / \ \ @ + \ \\ \@ + \ \_/@ + (__/ @@ +168 DIAERESIS + _ _ @ + (_) (_)@ + $ $ @ + $ $ @ + $ $ @ + @@ +169 COPYRIGHT SIGN + _____ @ + / ___ \ @ + / / __| \ @ + | | (__ |@ + \ \___| / @ + \_____/ @@ +170 FEMININE ORDINAL INDICATOR + __ _ @ + / _` |@ + \__,_|@ + |____|@ + $ @ + @@ +171 LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + ____@ + / / /@ + / / / @ + \ \ \ @ + \_\_\@ + @@ +172 NOT SIGN + @ + _____ @ + |___ |@ + |_|@ + $ @ + @@ +173 SOFT HYPHEN + @ + @ + ____ @ + |____|@ + $ @ + @@ +174 REGISTERED SIGN + _____ @ + / ___ \ @ + / | _ \ \ @ + | | / |@ + \ |_|_\ / @ + \_____/ @@ +175 MACRON + _____ @ + |_____|@ + $ @ + $ @ + $ @ + @@ +176 DEGREE SIGN + __ @ + / \ @ + | () |@ + \__/ @ + $ @ + @@ +177 PLUS-MINUS SIGN + _ @ + _| |_ @ + |_ _|@ + _|_|_ @ + |_____|@ + @@ +178 SUPERSCRIPT TWO + ___ @ + |_ )@ + / / @ + /___|@ + $ @ + @@ +179 SUPERSCRIPT THREE + ____@ + |__ /@ + |_ \@ + |___/@ + $ @ + @@ +180 ACUTE ACCENT + __@ + /_/@ + $ @ + $ @ + $ @ + @@ +181 MICRO SIGN + @ + _ _ @ + | | | |@ + | |_| |@ + | ._,_|@ + |_| @@ +182 PILCROW SIGN + _____ @ + / |@ + | (| | |@ + \__ | |@ + |_|_|@ + @@ +183 MIDDLE DOT + @ + _ @ + (_)@ + $ @ + $ @ + @@ +184 CEDILLA + @ + @ + @ + @ + _ @ + )_)@@ +185 SUPERSCRIPT ONE + _ @ + / |@ + | |@ + |_|@ + $ @ + @@ +186 MASCULINE ORDINAL INDICATOR + ___ @ + / _ \@ + \___/@ + |___|@ + $ @ + @@ +187 RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + ____ @ + \ \ \ @ + \ \ \@ + / / /@ + /_/_/ @ + @@ +188 VULGAR FRACTION ONE QUARTER + _ __ @ + / | / / _ @ + | |/ / | | @ + |_/ /|_ _|@ + /_/ |_| @ + @@ +189 VULGAR FRACTION ONE HALF + _ __ @ + / | / /__ @ + | |/ /_ )@ + |_/ / / / @ + /_/ /___|@ + @@ +190 VULGAR FRACTION THREE QUARTERS + ____ __ @ + |__ / / / _ @ + |_ \/ / | | @ + |___/ /|_ _|@ + /_/ |_| @ + @@ +191 INVERTED QUESTION MARK + _ @ + (_) @ + | | @ + / /_ @ + \___|@ + @@ +192 LATIN CAPITAL LETTER A WITH GRAVE + __ @ + \_\ @ + /_\ @ + / _ \ @ + /_/ \_\@ + @@ +193 LATIN CAPITAL LETTER A WITH ACUTE + __ @ + /_/ @ + /_\ @ + / _ \ @ + /_/ \_\@ + @@ +194 LATIN CAPITAL LETTER A WITH CIRCUMFLEX + //\ @ + |/_\| @ + /_\ @ + / _ \ @ + /_/ \_\@ + @@ +195 LATIN CAPITAL LETTER A WITH TILDE + /\/| @ + |/\/ @ + /_\ @ + / _ \ @ + /_/ \_\@ + @@ +196 LATIN CAPITAL LETTER A WITH DIAERESIS + _ _ @ + (_)_(_)@ + /_\ @ + / _ \ @ + /_/ \_\@ + @@ +197 LATIN CAPITAL LETTER A WITH RING ABOVE + _ @ + (o) @ + /_\ @ + / _ \ @ + /_/ \_\@ + @@ +198 LATIN CAPITAL LETTER AE + ______ @ + / ____|@ + / _ _| @ + / __ |___ @ + /_/ |_____|@ + @@ +199 LATIN CAPITAL LETTER C WITH CEDILLA + ____ @ + / ___|@ + | | @ + | |___ @ + \____|@ + )_) @@ +200 LATIN CAPITAL LETTER E WITH GRAVE + __ @ + _\_\_ @ + | ____|@ + | _|_ @ + |_____|@ + @@ +201 LATIN CAPITAL LETTER E WITH ACUTE + __ @ + _/_/_ @ + | ____|@ + | _|_ @ + |_____|@ + @@ +202 LATIN CAPITAL LETTER E WITH CIRCUMFLEX + //\ @ + |/_\| @ + | ____|@ + | _|_ @ + |_____|@ + @@ +203 LATIN CAPITAL LETTER E WITH DIAERESIS + _ _ @ + (_)_(_)@ + | ____|@ + | _|_ @ + |_____|@ + @@ +204 LATIN CAPITAL LETTER I WITH GRAVE + __ @ + \_\ @ + |_ _|@ + | | @ + |___|@ + @@ +205 LATIN CAPITAL LETTER I WITH ACUTE + __ @ + /_/ @ + |_ _|@ + | | @ + |___|@ + @@ +206 LATIN CAPITAL LETTER I WITH CIRCUMFLEX + //\ @ + |/_\|@ + |_ _|@ + | | @ + |___|@ + @@ +207 LATIN CAPITAL LETTER I WITH DIAERESIS + _ _ @ + (_)_(_)@ + |_ _| @ + | | @ + |___| @ + @@ +208 LATIN CAPITAL LETTER ETH + ____ @ + | _ \ @ + _| |_| |@ + |__ __| |@ + |____/ @ + @@ +209 LATIN CAPITAL LETTER N WITH TILDE + /\/|@ + |/\/ @ + | \| |@ + | .` |@ + |_|\_|@ + @@ +210 LATIN CAPITAL LETTER O WITH GRAVE + __ @ + \_\ @ + / _ \ @ + | |_| |@ + \___/ @ + @@ +211 LATIN CAPITAL LETTER O WITH ACUTE + __ @ + /_/ @ + / _ \ @ + | |_| |@ + \___/ @ + @@ +212 LATIN CAPITAL LETTER O WITH CIRCUMFLEX + //\ @ + |/_\| @ + / _ \ @ + | |_| |@ + \___/ @ + @@ +213 LATIN CAPITAL LETTER O WITH TILDE + /\/| @ + |/\/ @ + / _ \ @ + | |_| |@ + \___/ @ + @@ +214 LATIN CAPITAL LETTER O WITH DIAERESIS + _ _ @ + (_)_(_)@ + / _ \ @ + | |_| |@ + \___/ @ + @@ +215 MULTIPLICATION SIGN + @ + @ + /\/\@ + > <@ + \/\/@ + @@ +216 LATIN CAPITAL LETTER O WITH STROKE + ____ @ + / _// @ + | |// |@ + | //| |@ + //__/ @ + @@ +217 LATIN CAPITAL LETTER U WITH GRAVE + __ @ + _\_\_ @ + | | | |@ + | |_| |@ + \___/ @ + @@ +218 LATIN CAPITAL LETTER U WITH ACUTE + __ @ + _/_/_ @ + | | | |@ + | |_| |@ + \___/ @ + @@ +219 LATIN CAPITAL LETTER U WITH CIRCUMFLEX + //\ @ + |/ \| @ + | | | |@ + | |_| |@ + \___/ @ + @@ +220 LATIN CAPITAL LETTER U WITH DIAERESIS + _ _ @ + (_) (_)@ + | | | |@ + | |_| |@ + \___/ @ + @@ +221 LATIN CAPITAL LETTER Y WITH ACUTE + __ @ + __/_/__@ + \ \ / /@ + \ V / @ + |_| @ + @@ +222 LATIN CAPITAL LETTER THORN + _ @ + | |___ @ + | __ \@ + | ___/@ + |_| @ + @@ +223 LATIN SMALL LETTER SHARP S + ___ @ + / _ \@ + | |/ /@ + | |\ \@ + | ||_/@ + |_| @@ +224 LATIN SMALL LETTER A WITH GRAVE + __ @ + \_\_ @ + / _` |@ + | (_| |@ + \__,_|@ + @@ +225 LATIN SMALL LETTER A WITH ACUTE + __ @ + /_/_ @ + / _` |@ + | (_| |@ + \__,_|@ + @@ +226 LATIN SMALL LETTER A WITH CIRCUMFLEX + //\ @ + |/_\| @ + / _` |@ + | (_| |@ + \__,_|@ + @@ +227 LATIN SMALL LETTER A WITH TILDE + /\/| @ + |/\/_ @ + / _` |@ + | (_| |@ + \__,_|@ + @@ +228 LATIN SMALL LETTER A WITH DIAERESIS + _ _ @ + (_)_(_)@ + / _` |@ + | (_| |@ + \__,_|@ + @@ +229 LATIN SMALL LETTER A WITH RING ABOVE + __ @ + (()) @ + / _ '|@ + | (_| |@ + \__,_|@ + @@ +230 LATIN SMALL LETTER AE + @ + __ ____ @ + / _` _ \@ + | (_| __/@ + \__,____|@ + @@ +231 LATIN SMALL LETTER C WITH CEDILLA + @ + ___ @ + / __|@ + | (__ @ + \___|@ + )_) @@ +232 LATIN SMALL LETTER E WITH GRAVE + __ @ + \_\ @ + / _ \@ + | __/@ + \___|@ + @@ +233 LATIN SMALL LETTER E WITH ACUTE + __ @ + /_/ @ + / _ \@ + | __/@ + \___|@ + @@ +234 LATIN SMALL LETTER E WITH CIRCUMFLEX + //\ @ + |/_\|@ + / _ \@ + | __/@ + \___|@ + @@ +235 LATIN SMALL LETTER E WITH DIAERESIS + _ _ @ + (_)_(_)@ + / _ \ @ + | __/ @ + \___| @ + @@ +236 LATIN SMALL LETTER I WITH GRAVE + __ @ + \_\@ + | |@ + | |@ + |_|@ + @@ +237 LATIN SMALL LETTER I WITH ACUTE + __@ + /_/@ + | |@ + | |@ + |_|@ + @@ +238 LATIN SMALL LETTER I WITH CIRCUMFLEX + //\ @ + |/_\|@ + | | @ + | | @ + |_| @ + @@ +239 LATIN SMALL LETTER I WITH DIAERESIS + _ _ @ + (_)_(_)@ + | | @ + | | @ + |_| @ + @@ +240 LATIN SMALL LETTER ETH + /\/\ @ + > < @ + _\/\ |@ + / __` |@ + \____/ @ + @@ +241 LATIN SMALL LETTER N WITH TILDE + /\/| @ + |/\/ @ + | '_ \ @ + | | | |@ + |_| |_|@ + @@ +242 LATIN SMALL LETTER O WITH GRAVE + __ @ + \_\ @ + / _ \ @ + | (_) |@ + \___/ @ + @@ +243 LATIN SMALL LETTER O WITH ACUTE + __ @ + /_/ @ + / _ \ @ + | (_) |@ + \___/ @ + @@ +244 LATIN SMALL LETTER O WITH CIRCUMFLEX + //\ @ + |/_\| @ + / _ \ @ + | (_) |@ + \___/ @ + @@ +245 LATIN SMALL LETTER O WITH TILDE + /\/| @ + |/\/ @ + / _ \ @ + | (_) |@ + \___/ @ + @@ +246 LATIN SMALL LETTER O WITH DIAERESIS + _ _ @ + (_)_(_)@ + / _ \ @ + | (_) |@ + \___/ @ + @@ +247 DIVISION SIGN + @ + _ @ + _(_)_ @ + |_____|@ + (_) @ + @@ +248 LATIN SMALL LETTER O WITH STROKE + @ + ____ @ + / _//\ @ + | (//) |@ + \//__/ @ + @@ +249 LATIN SMALL LETTER U WITH GRAVE + __ @ + _\_\_ @ + | | | |@ + | |_| |@ + \__,_|@ + @@ +250 LATIN SMALL LETTER U WITH ACUTE + __ @ + _/_/_ @ + | | | |@ + | |_| |@ + \__,_|@ + @@ +251 LATIN SMALL LETTER U WITH CIRCUMFLEX + //\ @ + |/ \| @ + | | | |@ + | |_| |@ + \__,_|@ + @@ +252 LATIN SMALL LETTER U WITH DIAERESIS + _ _ @ + (_) (_)@ + | | | |@ + | |_| |@ + \__,_|@ + @@ +253 LATIN SMALL LETTER Y WITH ACUTE + __ @ + _/_/_ @ + | | | |@ + | |_| |@ + \__, |@ + |___/ @@ +254 LATIN SMALL LETTER THORN + _ @ + | |__ @ + | '_ \ @ + | |_) |@ + | .__/ @ + |_| @@ +255 LATIN SMALL LETTER Y WITH DIAERESIS + _ _ @ + (_) (_)@ + | | | |@ + | |_| |@ + \__, |@ + |___/ @@ +0x0100 LATIN CAPITAL LETTER A WITH MACRON + ____ @ + /___/ @ + /_\ @ + / _ \ @ + /_/ \_\@ + @@ +0x0101 LATIN SMALL LETTER A WITH MACRON + ___ @ + /_ _/@ + / _` |@ + | (_| |@ + \__,_|@ + @@ +0x0102 LATIN CAPITAL LETTER A WITH BREVE + _ _ @ + \\_// @ + /_\ @ + / _ \ @ + /_/ \_\@ + @@ +0x0103 LATIN SMALL LETTER A WITH BREVE + \_/ @ + ___ @ + / _` |@ + | (_| |@ + \__,_|@ + @@ +0x0104 LATIN CAPITAL LETTER A WITH OGONEK + @ + _ @ + /_\ @ + / _ \ @ + /_/ \_\@ + (_(@@ +0x0105 LATIN SMALL LETTER A WITH OGONEK + @ + __ _ @ + / _` |@ + | (_| |@ + \__,_|@ + (_(@@ +0x0106 LATIN CAPITAL LETTER C WITH ACUTE + __ @ + _/_/ @ + / ___|@ + | |___ @ + \____|@ + @@ +0x0107 LATIN SMALL LETTER C WITH ACUTE + __ @ + /__/@ + / __|@ + | (__ @ + \___|@ + @@ +0x0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX + /\ @ + _//\\@ + / ___|@ + | |___ @ + \____|@ + @@ +0x0109 LATIN SMALL LETTER C WITH CIRCUMFLEX + /\ @ + /_\ @ + / __|@ + | (__ @ + \___|@ + @@ +0x010A LATIN CAPITAL LETTER C WITH DOT ABOVE + [] @ + ____ @ + / ___|@ + | |___ @ + \____|@ + @@ +0x010B LATIN SMALL LETTER C WITH DOT ABOVE + [] @ + ___ @ + / __|@ + | (__ @ + \___|@ + @@ +0x010C LATIN CAPITAL LETTER C WITH CARON + \\// @ + _\/_ @ + / ___|@ + | |___ @ + \____|@ + @@ +0x010D LATIN SMALL LETTER C WITH CARON + \\//@ + _\/ @ + / __|@ + | (__ @ + \___|@ + @@ +0x010E LATIN CAPITAL LETTER D WITH CARON + \\// @ + __\/ @ + | _ \ @ + | |_| |@ + |____/ @ + @@ +0x010F LATIN SMALL LETTER D WITH CARON + \/ _ @ + __| |@ + / _` |@ + | (_| |@ + \__,_|@ + @@ +0x0110 LATIN CAPITAL LETTER D WITH STROKE + ____ @ + |_ __ \ @ + /| |/ | |@ + /|_|/_| |@ + |_____/ @ + @@ +0x0111 LATIN SMALL LETTER D WITH STROKE + ---|@ + __| |@ + / _` |@ + | (_| |@ + \__,_|@ + @@ +0x0112 LATIN CAPITAL LETTER E WITH MACRON + ____ @ + /___/ @ + | ____|@ + | _|_ @ + |_____|@ + @@ +0x0113 LATIN SMALL LETTER E WITH MACRON + ____@ + /_ _/@ + / _ \ @ + | __/ @ + \___| @ + @@ +0x0114 LATIN CAPITAL LETTER E WITH BREVE + _ _ @ + \\_// @ + | ____|@ + | _|_ @ + |_____|@ + @@ +0x0115 LATIN SMALL LETTER E WITH BREVE + \\ //@ + -- @ + / _ \ @ + | __/ @ + \___| @ + @@ +0x0116 LATIN CAPITAL LETTER E WITH DOT ABOVE + [] @ + _____ @ + | ____|@ + | _|_ @ + |_____|@ + @@ +0x0117 LATIN SMALL LETTER E WITH DOT ABOVE + [] @ + __ @ + / _ \@ + | __/@ + \___|@ + @@ +0x0118 LATIN CAPITAL LETTER E WITH OGONEK + @ + _____ @ + | ____|@ + | _|_ @ + |_____|@ + (__(@@ +0x0119 LATIN SMALL LETTER E WITH OGONEK + @ + ___ @ + / _ \@ + | __/@ + \___|@ + (_(@@ +0x011A LATIN CAPITAL LETTER E WITH CARON + \\// @ + __\/_ @ + | ____|@ + | _|_ @ + |_____|@ + @@ +0x011B LATIN SMALL LETTER E WITH CARON + \\//@ + \/ @ + / _ \@ + | __/@ + \___|@ + @@ +0x011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX + _/\_ @ + / ___|@ + | | _ @ + | |_| |@ + \____|@ + @@ +0x011D LATIN SMALL LETTER G WITH CIRCUMFLEX + /\ @ + _/_ \@ + / _` |@ + | (_| |@ + \__, |@ + |___/ @@ +0x011E LATIN CAPITAL LETTER G WITH BREVE + _\/_ @ + / ___|@ + | | _ @ + | |_| |@ + \____|@ + @@ +0x011F LATIN SMALL LETTER G WITH BREVE + \___/ @ + __ _ @ + / _` |@ + | (_| |@ + \__, |@ + |___/ @@ +0x0120 LATIN CAPITAL LETTER G WITH DOT ABOVE + _[]_ @ + / ___|@ + | | _ @ + | |_| |@ + \____|@ + @@ +0x0121 LATIN SMALL LETTER G WITH DOT ABOVE + [] @ + __ _ @ + / _` |@ + | (_| |@ + \__, |@ + |___/ @@ +0x0122 LATIN CAPITAL LETTER G WITH CEDILLA + ____ @ + / ___|@ + | | _ @ + | |_| |@ + \____|@ + )__) @@ +0x0123 LATIN SMALL LETTER G WITH CEDILLA + @ + __ _ @ + / _` |@ + | (_| |@ + \__, |@ + |_))))@@ +0x0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX + _/ \_ @ + | / \ |@ + | |_| |@ + | _ |@ + |_| |_|@ + @@ +0x0125 LATIN SMALL LETTER H WITH CIRCUMFLEX + _ /\ @ + | |//\ @ + | '_ \ @ + | | | |@ + |_| |_|@ + @@ +0x0126 LATIN CAPITAL LETTER H WITH STROKE + _ _ @ + | |=| |@ + | |_| |@ + | _ |@ + |_| |_|@ + @@ +0x0127 LATIN SMALL LETTER H WITH STROKE + _ @ + |=|__ @ + | '_ \ @ + | | | |@ + |_| |_|@ + @@ +0x0128 LATIN CAPITAL LETTER I WITH TILDE + /\//@ + |_ _|@ + | | @ + | | @ + |___|@ + @@ +0x0129 LATIN SMALL LETTER I WITH TILDE + @ + /\/@ + | |@ + | |@ + |_|@ + @@ +0x012A LATIN CAPITAL LETTER I WITH MACRON + /___/@ + |_ _|@ + | | @ + | | @ + |___|@ + @@ +0x012B LATIN SMALL LETTER I WITH MACRON + ____@ + /___/@ + | | @ + | | @ + |_| @ + @@ +0x012C LATIN CAPITAL LETTER I WITH BREVE + \__/@ + |_ _|@ + | | @ + | | @ + |___|@ + @@ +0x012D LATIN SMALL LETTER I WITH BREVE + @ + \_/@ + | |@ + | |@ + |_|@ + @@ +0x012E LATIN CAPITAL LETTER I WITH OGONEK + ___ @ + |_ _|@ + | | @ + | | @ + |___|@ + (__(@@ +0x012F LATIN SMALL LETTER I WITH OGONEK + _ @ + (_) @ + | | @ + | | @ + |_|_@ + (_(@@ +0x0130 LATIN CAPITAL LETTER I WITH DOT ABOVE + _[] @ + |_ _|@ + | | @ + | | @ + |___|@ + @@ +0x0131 LATIN SMALL LETTER DOTLESS I + @ + _ @ + | |@ + | |@ + |_|@ + @@ +0x0132 LATIN CAPITAL LIGATURE IJ + ___ _ @ + |_ _|| |@ + | | | |@ + | |_| |@ + |__|__/ @ + @@ +0x0133 LATIN SMALL LIGATURE IJ + _ _ @ + (_) (_)@ + | | | |@ + | | | |@ + |_|_/ |@ + |__/ @@ +0x0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX + /\ @ + /_\|@ + _ | | @ + | |_| | @ + \___/ @ + @@ +0x0135 LATIN SMALL LETTER J WITH CIRCUMFLEX + /\@ + /_\@ + | |@ + | |@ + _/ |@ + |__/ @@ +0x0136 LATIN CAPITAL LETTER K WITH CEDILLA + _ _ @ + | |/ / @ + | ' / @ + | . \ @ + |_|\_\ @ + )__)@@ +0x0137 LATIN SMALL LETTER K WITH CEDILLA + _ @ + | | __@ + | |/ /@ + | < @ + |_|\_\@ + )_)@@ +0x0138 LATIN SMALL LETTER KRA + @ + _ __ @ + | |/ \@ + | < @ + |_|\_\@ + @@ +0x0139 LATIN CAPITAL LETTER L WITH ACUTE + _ //@ + | | // @ + | | @ + | |___ @ + |_____|@ + @@ +0x013A LATIN SMALL LETTER L WITH ACUTE + //@ + | |@ + | |@ + | |@ + |_|@ + @@ +0x013B LATIN CAPITAL LETTER L WITH CEDILLA + _ @ + | | @ + | | @ + | |___ @ + |_____|@ + )__)@@ +0x013C LATIN SMALL LETTER L WITH CEDILLA + _ @ + | | @ + | | @ + | | @ + |_| @ + )_)@@ +0x013D LATIN CAPITAL LETTER L WITH CARON + _ \\//@ + | | \/ @ + | | @ + | |___ @ + |_____|@ + @@ +0x013E LATIN SMALL LETTER L WITH CARON + _ \\//@ + | | \/ @ + | | @ + | | @ + |_| @ + @@ +0x013F LATIN CAPITAL LETTER L WITH MIDDLE DOT + _ @ + | | @ + | | [] @ + | |___ @ + |_____|@ + @@ +0x0140 LATIN SMALL LETTER L WITH MIDDLE DOT + _ @ + | | @ + | | []@ + | | @ + |_| @ + @@ +0x0141 LATIN CAPITAL LETTER L WITH STROKE + __ @ + | // @ + |//| @ + // |__ @ + |_____|@ + @@ +0x0142 LATIN SMALL LETTER L WITH STROKE + _ @ + | |@ + |//@ + //|@ + |_|@ + @@ +0x0143 LATIN CAPITAL LETTER N WITH ACUTE + _/ /_ @ + | \ | |@ + | \| |@ + | |\ |@ + |_| \_|@ + @@ +0x0144 LATIN SMALL LETTER N WITH ACUTE + _ @ + _ /_/ @ + | '_ \ @ + | | | |@ + |_| |_|@ + @@ +0x0145 LATIN CAPITAL LETTER N WITH CEDILLA + _ _ @ + | \ | |@ + | \| |@ + | |\ |@ + |_| \_|@ + )_) @@ +0x0146 LATIN SMALL LETTER N WITH CEDILLA + @ + _ __ @ + | '_ \ @ + | | | |@ + |_| |_|@ + )_) @@ +0x0147 LATIN CAPITAL LETTER N WITH CARON + _\/ _ @ + | \ | |@ + | \| |@ + | |\ |@ + |_| \_|@ + @@ +0x0148 LATIN SMALL LETTER N WITH CARON + \\// @ + _\/_ @ + | '_ \ @ + | | | |@ + |_| |_|@ + @@ +0x0149 LATIN SMALL LETTER N PRECEDED BY APOSTROPHE + @ + _ __ @ + ( )| '_\ @ + |/| | | |@ + |_| |_|@ + @@ +0x014A LATIN CAPITAL LETTER ENG + _ _ @ + | \ | |@ + | \| |@ + | |\ |@ + |_| \ |@ + )_)@@ +0x014B LATIN SMALL LETTER ENG + _ __ @ + | '_ \ @ + | | | |@ + |_| | |@ + | |@ + |__ @@ +0x014C LATIN CAPITAL LETTER O WITH MACRON + ____ @ + /_ _/ @ + / _ \ @ + | (_) |@ + \___/ @ + @@ +0x014D LATIN SMALL LETTER O WITH MACRON + ____ @ + /_ _/ @ + / _ \ @ + | (_) |@ + \___/ @ + @@ +0x014E LATIN CAPITAL LETTER O WITH BREVE + \ / @ + _-_ @ + / _ \ @ + | |_| |@ + \___/ @ + @@ +0x014F LATIN SMALL LETTER O WITH BREVE + \ / @ + _-_ @ + / _ \ @ + | |_| |@ + \___/ @ + @@ +0x0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + ___ @ + /_/_/@ + / _ \ @ + | |_| |@ + \___/ @ + @@ +0x0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE + ___ @ + /_/_/@ + / _ \ @ + | |_| |@ + \___/ @ + @@ +0x0152 LATIN CAPITAL LIGATURE OE + ___ ___ @ + / _ \| __|@ + | | | | | @ + | |_| | |__@ + \___/|____@ + @@ +0x0153 LATIN SMALL LIGATURE OE + @ + ___ ___ @ + / _ \ / _ \@ + | (_) | __/@ + \___/ \___|@ + @@ +0x0154 LATIN CAPITAL LETTER R WITH ACUTE + _/_/ @ + | _ \ @ + | |_) |@ + | _ < @ + |_| \_\@ + @@ +0x0155 LATIN SMALL LETTER R WITH ACUTE + __@ + _ /_/@ + | '__|@ + | | @ + |_| @ + @@ +0x0156 LATIN CAPITAL LETTER R WITH CEDILLA + ____ @ + | _ \ @ + | |_) |@ + | _ < @ + |_| \_\@ + )_) @@ +0x0157 LATIN SMALL LETTER R WITH CEDILLA + @ + _ __ @ + | '__|@ + | | @ + |_| @ + )_) @@ +0x0158 LATIN CAPITAL LETTER R WITH CARON + _\_/ @ + | _ \ @ + | |_) |@ + | _ < @ + |_| \_\@ + @@ +0x0159 LATIN SMALL LETTER R WITH CARON + \\// @ + _\/_ @ + | '__|@ + | | @ + |_| @ + @@ +0x015A LATIN CAPITAL LETTER S WITH ACUTE + _/_/ @ + / ___| @ + \___ \ @ + ___) |@ + |____/ @ + @@ +0x015B LATIN SMALL LETTER S WITH ACUTE + __@ + _/_/@ + / __|@ + \__ \@ + |___/@ + @@ +0x015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX + _/\_ @ + / ___| @ + \___ \ @ + ___) |@ + |____/ @ + @@ +0x015D LATIN SMALL LETTER S WITH CIRCUMFLEX + @ + /_\_@ + / __|@ + \__ \@ + |___/@ + @@ +0x015E LATIN CAPITAL LETTER S WITH CEDILLA + ____ @ + / ___| @ + \___ \ @ + ___) |@ + |____/ @ + )__)@@ +0x015F LATIN SMALL LETTER S WITH CEDILLA + @ + ___ @ + / __|@ + \__ \@ + |___/@ + )_)@@ +0x0160 LATIN CAPITAL LETTER S WITH CARON + _\_/ @ + / ___| @ + \___ \ @ + ___) |@ + |____/ @ + @@ +0x0161 LATIN SMALL LETTER S WITH CARON + \\//@ + _\/ @ + / __|@ + \__ \@ + |___/@ + @@ +0x0162 LATIN CAPITAL LETTER T WITH CEDILLA + _____ @ + |_ _|@ + | | @ + | | @ + |_| @ + )__)@@ +0x0163 LATIN SMALL LETTER T WITH CEDILLA + _ @ + | |_ @ + | __|@ + | |_ @ + \__|@ + )_)@@ +0x0164 LATIN CAPITAL LETTER T WITH CARON + _____ @ + |_ _|@ + | | @ + | | @ + |_| @ + @@ +0x0165 LATIN SMALL LETTER T WITH CARON + \/ @ + | |_ @ + | __|@ + | |_ @ + \__|@ + @@ +0x0166 LATIN CAPITAL LETTER T WITH STROKE + _____ @ + |_ _|@ + | | @ + -|-|- @ + |_| @ + @@ +0x0167 LATIN SMALL LETTER T WITH STROKE + _ @ + | |_ @ + | __|@ + |-|_ @ + \__|@ + @@ +0x0168 LATIN CAPITAL LETTER U WITH TILDE + @ + _/\/_ @ + | | | |@ + | |_| |@ + \___/ @ + @@ +0x0169 LATIN SMALL LETTER U WITH TILDE + @ + _/\/_ @ + | | | |@ + | |_| |@ + \__,_|@ + @@ +0x016A LATIN CAPITAL LETTER U WITH MACRON + ____ @ + /__ _/@ + | | | |@ + | |_| |@ + \___/ @ + @@ +0x016B LATIN SMALL LETTER U WITH MACRON + ____ @ + / _ /@ + | | | |@ + | |_| |@ + \__,_|@ + @@ +0x016C LATIN CAPITAL LETTER U WITH BREVE + @ + \_/_ @ + | | | |@ + | |_| |@ + \____|@ + @@ +0x016D LATIN SMALL LETTER U WITH BREVE + @ + \_/_ @ + | | | |@ + | |_| |@ + \__,_|@ + @@ +0x016E LATIN CAPITAL LETTER U WITH RING ABOVE + O @ + __ _ @ + | | | |@ + | |_| |@ + \___/ @ + @@ +0x016F LATIN SMALL LETTER U WITH RING ABOVE + O @ + __ __ @ + | | | |@ + | |_| |@ + \__,_|@ + @@ +0x0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + -- --@ + /_//_/@ + | | | |@ + | |_| |@ + \___/ @ + @@ +0x0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE + ____@ + _/_/_/@ + | | | |@ + | |_| |@ + \__,_|@ + @@ +0x0172 LATIN CAPITAL LETTER U WITH OGONEK + _ _ @ + | | | |@ + | | | |@ + | |_| |@ + \___/ @ + (__(@@ +0x0173 LATIN SMALL LETTER U WITH OGONEK + @ + _ _ @ + | | | |@ + | |_| |@ + \__,_|@ + (_(@@ +0x0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX + __ /\ __@ + \ \ //\\/ /@ + \ \ /\ / / @ + \ V V / @ + \_/\_/ @ + @@ +0x0175 LATIN SMALL LETTER W WITH CIRCUMFLEX + /\ @ + __ //\\__@ + \ \ /\ / /@ + \ V V / @ + \_/\_/ @ + @@ +0x0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX + /\ @ + __//\\ @ + \ \ / /@ + \ V / @ + |_| @ + @@ +0x0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX + /\ @ + //\\ @ + | | | |@ + | |_| |@ + \__, |@ + |___/ @@ +0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS + [] []@ + __ _@ + \ \ / /@ + \ V / @ + |_| @ + @@ +0x0179 LATIN CAPITAL LETTER Z WITH ACUTE + __/_/@ + |__ /@ + / / @ + / /_ @ + /____|@ + @@ +0x017A LATIN SMALL LETTER Z WITH ACUTE + _ @ + _/_/@ + |_ /@ + / / @ + /___|@ + @@ +0x017B LATIN CAPITAL LETTER Z WITH DOT ABOVE + __[]_@ + |__ /@ + / / @ + / /_ @ + /____|@ + @@ +0x017C LATIN SMALL LETTER Z WITH DOT ABOVE + [] @ + ____@ + |_ /@ + / / @ + /___|@ + @@ +0x017D LATIN CAPITAL LETTER Z WITH CARON + _\_/_@ + |__ /@ + / / @ + / /_ @ + /____|@ + @@ +0x017E LATIN SMALL LETTER Z WITH CARON + \\//@ + _\/_@ + |_ /@ + / / @ + /___|@ + @@ +0x017F LATIN SMALL LETTER LONG S + __ @ + / _|@ + |-| | @ + |-| | @ + |_| @ + @@ +0x02C7 CARON + \\//@ + \/ @ + $@ + $@ + $@ + $@@ +0x02D8 BREVE + \\_//@ + \_/ @ + $@ + $@ + $@ + $@@ +0x02D9 DOT ABOVE + []@ + $@ + $@ + $@ + $@ + $@@ +0x02DB OGONEK + $@ + $@ + $@ + $@ + $@ + )_) @@ +0x02DD DOUBLE ACUTE ACCENT + _ _ @ + /_/_/@ + $@ + $@ + $@ + $@@ From 3182bdac0bd49acb45ce088eb4c24d947100e2df Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 6 Sep 2016 13:53:25 +0800 Subject: [PATCH 504/545] =?UTF-8?q?=E2=9C=84=20update=20banner=20font?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/banner/BannerFont.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/blade-core/src/main/java/com/blade/banner/BannerFont.java b/blade-core/src/main/java/com/blade/banner/BannerFont.java index 3b24d9699..9f312256f 100644 --- a/blade-core/src/main/java/com/blade/banner/BannerFont.java +++ b/blade-core/src/main/java/com/blade/banner/BannerFont.java @@ -194,8 +194,9 @@ public String asAscii(String text, boolean splitAtWord, boolean leftJustify, int if ((width(newLine) > splitWidth) && (line.length() > 0)) { result = addLine(result, line + "\r\n", leftJustify, splitWidth); line = append("", w); - } else + } else{ line = newLine; + } } if (line.length() > 0){ result = addLine(result, line + "\r\n", leftJustify, splitWidth); From 5bf0afafc96cb97b0418207054b2a8070658fbb3 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 6 Sep 2016 13:59:11 +0800 Subject: [PATCH 505/545] =?UTF-8?q?=E2=9C=84=20remove=20log=20by=20ioc=20b?= =?UTF-8?q?ean=20is=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/ioc/IocApplication.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 9f93d6bd1..88bd3b019 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -206,8 +206,10 @@ public void initBeans() throws Exception { } } - LOGGER.info("Add Object: {}", ioc.getBeans()); - + if(null != ioc.getBeans() && !ioc.getBeans().isEmpty()){ + LOGGER.info("Add Object: {}", ioc.getBeans()); + } + // injection List beanDefines = ioc.getBeanDefines(); if (null != beanDefines) { From 76985ed5d64c8ac72ac408a1a2e826803bc1c122 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 6 Sep 2016 14:17:26 +0800 Subject: [PATCH 506/545] =?UTF-8?q?=E2=9C=84=20update=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 366 ++++++++++++++++++++++++------------------------- README_CN.md | 378 +++++++++++++++++++++++++-------------------------- 2 files changed, 372 insertions(+), 372 deletions(-) diff --git a/README.md b/README.md index ba14aa3ba..39525508e 100644 --- a/README.md +++ b/README.md @@ -1,183 +1,183 @@ - -[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) - -[Quick Start](https://bladejava.com/docs)  |  [Demo Project](https://github.com/blade-samples)  |  [Contribute](https://bladejava.com/docs/appendix/contribute)  |  [Donate]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) - -[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - - -## What Is Blade? - -Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. -If you like it, please [star](https://github.com/biezhi/blade/stargazers) / [fork](https://github.com/biezhi/blade). Thx :blush: - -## Features - -* [x] Lightweight: the code is simple and the structure is clear -* [x] Modular (you can choose which components to use) -* [x] Supports plug-in extension mechanism -* [x] RESTful style routing interface -* [x] Supports multiple configuration files (currently properties, json and coding) -* [x] Embedded jetty server and template engine support -* [x] Supports JDK 1.6 and up - -## Overview - -* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. -* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. - -## Get Start - -To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : - -Grab via `Maven`: - -```xml - - com.bladejava - blade-core - 1.6.6 - - - com.bladejava - blade-embed-jetty - 0.0.4 - -``` -or `Gradle`: -```sh -compile 'com.bladejava:blade-core:1.6.6-beta' -compile 'com.bladejava:blade-embed-jetty:0.0.4' -``` - -Create `Main` method like this: - -```java -public static void main(String[] args) { - $().get("/", (request, response) -> { - response.html("

Hello blade!

"); - }).start(Application.class); -} -``` - -Run it and point your browser to [http://localhost:9000](http://localhost:9000). There you go, you've just created your first Blade app! - -## API Example - -```java -public static void main(String[] args) { - $().get("/user/21", getxxx); - $().post("/save", postxxx); - $().delete("/del/21", deletexxx); - $().put("/put", putxxx); -} -``` - -## REST URL Parameters - -```java -public static void main(String[] args) { - $().get("/user/:uid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - response.text("uid : " + uid); - }); - - $().get("/users/:uid/post/:pid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - Integer pid = request.paramAsInt("pid"); - String msg = "uid = " + uid + ", pid = " + pid; - response.text(msg); - }); - - $().start(Application.class); -} -``` - -## Form URL Parameters - -```java -public static void main(String[] args) { - $().get("/user", (request, response) -> { - Integer uid = request.queryAsInt("uid"); - response.text("uid : " + uid); - }).start(Application.class); -} -``` - -## Upload File - -```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; - File file = fileItem.getFile(); - - String fileRealPath = "your upload file path!"; - - nioTransferCopy(file, fileRealPath); - } -} -``` - -## Route Config File - -`route.conf` - -```sh -GET / IndexRoute.home -GET /signin IndexRoute.show_signin -POST /signin IndexRoute.signin -GET /signout IndexRoute.signout -POST /upload_img UploadRoute.upload_img -``` - -## Route Intercept - -```java -public static void main(String[] args) { - $().before("/.*", (request, response) -> { - System.out.println("before..."); - }).start(Application.class); -} -``` - -You may refer to these examples for additional guidance: - -+ [Hello Blade](https://github.com/blade-samples/hello) -+ [BBS WebSite](https://github.com/junicorn/java-china) -+ [Doc Service](https://github.com/biezhi/grice) -+ [More Examples](https://github.com/blade-samples) - - -## Update - -[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## Contact - -- Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me@gmail.com - -## Contributor - -Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! - -- [mfarid](https://github.com/mfarid) -- [daimajia](https://github.com/daimajia) -- [shenjie1993](https://github.com/shenjie1993) -- [sumory](https://github.com/sumory) -- [udaykadaboina](https://github.com/udaykadaboina) -- [SyedWasiHaider](https://github.com/SyedWasiHaider) -- [Awakens](https://github.com/Awakens) -- [shellac](https://github.com/shellac) -- [SudarAbisheck](https://github.com/SudarAbisheck) - -## Licenses - -Please see [Apache License](LICENSE) + +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) + +[Quick Start](https://bladejava.com/docs)  |  [Demo Project](https://github.com/blade-samples)  |  [Contribute](https://bladejava.com/docs/appendix/contribute)  |  [Donate]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [中文说明](https://github.com/biezhi/blade/blob/master/README_CN.md) + +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![Gitter](https://badges.gitter.im/biezhi/blade.svg)](https://gitter.im/biezhi/blade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + + +## What Is Blade? + +Blade is a lightweight MVC framework. It is based on the principles of simplicity and elegance. +If you like it, please [star](https://github.com/biezhi/blade/stargazers) / [fork](https://github.com/biezhi/blade). Thx :blush: + +## Features + +* [x] Lightweight: the code is simple and the structure is clear +* [x] Modular (you can choose which components to use) +* [x] Supports plug-in extension mechanism +* [x] RESTful style routing interface +* [x] Supports multiple configuration files (currently properties, json and coding) +* [x] Embedded jetty server and template engine support +* [x] Supports JDK 1.6 and up + +## Overview + +* Simplicity: The design is simple, easy to understand and doesn't introduce many layers between you and the standard library. The goal of this project is that the users should be able to understand the whole framework in a single day. +* Elegance: `blade` supports the RESTful style routing interface, has no invasive interceptors and provides the writing of DSL grammar. + +## Get Start + +To get started, first [include the Blade library](http://bladejava.com/docs/intro/getting_start) : + +Grab via `Maven`: + +```xml + + com.bladejava + blade-core + 1.6.6 + + + com.bladejava + blade-embed-jetty + 0.0.5 + +``` +or `Gradle`: +```sh +compile 'com.bladejava:blade-core:1.6.6' +compile 'com.bladejava:blade-embed-jetty:0.0.5' +``` + +Create `Main` method like this: + +```java +public static void main(String[] args) { + $().get("/", (request, response) -> { + response.html("

Hello blade!

"); + }).start(Application.class); +} +``` + +Run it and point your browser to [http://localhost:9000](http://localhost:9000). There you go, you've just created your first Blade app! + +## API Example + +```java +public static void main(String[] args) { + $().get("/user/21", getxxx); + $().post("/save", postxxx); + $().delete("/del/21", deletexxx); + $().put("/put", putxxx); +} +``` + +## REST URL Parameters + +```java +public static void main(String[] args) { + $().get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + $().get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + $().start(Application.class); +} +``` + +## Form URL Parameters + +```java +public static void main(String[] args) { + $().get("/user", (request, response) -> { + Integer uid = request.queryAsInt("uid"); + response.text("uid : " + uid); + }).start(Application.class); +} +``` + +## Upload File + +```java +public void upload_img(Request request, Response response){ + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## Route Config File + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## Route Intercept + +```java +public static void main(String[] args) { + $().before("/.*", (request, response) -> { + System.out.println("before..."); + }).start(Application.class); +} +``` + +You may refer to these examples for additional guidance: + ++ [Hello Blade](https://github.com/blade-samples/hello) ++ [BBS WebSite](https://github.com/junicorn/java-china) ++ [Doc Service](https://github.com/biezhi/grice) ++ [More Examples](https://github.com/blade-samples) + + +## Update + +[update log](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## Contact + +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me@gmail.com + +## Contributor + +Thank you very much for the developers to help in the project, if you are willing to contribute, welcome! + +- [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) + +## Licenses + +Please see [Apache License](LICENSE) diff --git a/README_CN.md b/README_CN.md index b5015d4b4..cf57a5923 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,189 +1,189 @@ - -[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) - -[开始使用](https://bladejava.com/docs)  |  [示例项目](https://github.com/blade-samples)  |  [贡献代码](https://bladejava.com/docs/appendix/contribute)  |  [捐赠]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [English](https://github.com/biezhi/blade/blob/master/README.md) - -[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) -[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) - -## Blade是什么? - -Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁的代码,优雅的设计。 - -如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade/stargazers) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush: - -## 特性 - -* [x] 轻量级, 代码简洁,结构清晰,更容易开发 -* [x] 模块化(你可以选择使用哪些组件) -* [x] 插件扩展机制 -* [x] Restful风格的路由接口 -* [x] 多种配置文件支持(当前支持properties、json和硬编码) -* [x] 多种模板引擎支持 -* [x] 更方便的启动和部署 -* [x] 支持JDK1.6或者更高版本(JDK8写起来更爽) - -## 概述 - -* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 -* 优雅的:`Blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 -* 易部署:支持 `maven` 打成 `jar` 包直接运行。 - -## 快速入门 - -开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : - -`Maven` 配置: - -```xml - - com.bladejava - blade-core - 1.6.6 - - - com.bladejava - blade-embed-jetty - 0.0.4 - -``` - -或者 `Gradle`: - -```sh -compile 'com.bladejava:blade-core:1.6.6-beta' -compile 'com.bladejava:blade-embed-jetty:0.0.4' -``` - -编写 `Main`函数: - -```java -public static void main(String[] args) { - $().get("/", (request, response) -> { - response.html("

Hello blade!

"); - }).start(Application.class); -} -``` - -用浏览器打开 http://localhost:9000 这样就可以看到第一个Blade应用了! - -## API示例 - -```java -public static void main(String[] args) { - $().get("/user/21", getxxx); - $().post("/save", postxxx); - $().delete("/del/21", deletexxx); - $().put("/put", putxxx); -} -``` - -## REST URL参数获取 - -```java -public static void main(String[] args) { - $().get("/user/:uid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - response.text("uid : " + uid); - }); - - $().get("/users/:uid/post/:pid", (request, response) -> { - Integer uid = request.paramAsInt("uid"); - Integer pid = request.paramAsInt("pid"); - String msg = "uid = " + uid + ", pid = " + pid; - response.text(msg); - }); - - $().start(Application.class); -} -``` - -## 表单参数获取 - -```java -public static void main(String[] args) { - $().get("/user", (request, response) -> { - Integer uid = request.queryAsInt("uid"); - response.text("uid : " + uid); - }).start(Application.class); -} -``` - -## 上传文件 - -```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; - File file = fileItem.getFile(); - - String fileRealPath = "your upload file path!"; - - nioTransferCopy(file, fileRealPath); - } -} -``` - -## 配置文件路由 - -`route.conf` - -```sh -GET / IndexRoute.home -GET /signin IndexRoute.show_signin -POST /signin IndexRoute.signin -GET /signout IndexRoute.signout -POST /upload_img UploadRoute.upload_img -``` - -## 路由拦截 - -```java -public static void main(String[] args) { - $().before("/.*", (request, response) -> { - System.out.println("before..."); - }).start(Application.class); -} -``` - - -这一切看起来多么的简单,不过上面的功能可是冰山一角,查看文档和示例项目有更多惊喜: - -+ [hello工程](https://github.com/blade-samples/hello) -+ [论坛程序](https://github.com/junicorn/java-china) -+ [文档服务](https://github.com/biezhi/grice) -+ [更多例子](https://github.com/blade-samples) - - -## 更新日志 - -[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) - -## 联系我 - -- Blog:[https://biezhi.me](https://biezhi.me) -- Mail: biezhi.me#gmail.com -- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) - -## 贡献 - -非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! - -- [mfarid](https://github.com/mfarid) -- [daimajia](https://github.com/daimajia) -- [shenjie1993](https://github.com/shenjie1993) -- [sumory](https://github.com/sumory) -- [udaykadaboina](https://github.com/udaykadaboina) -- [SyedWasiHaider](https://github.com/SyedWasiHaider) -- [Awakens](https://github.com/Awakens) -- [shellac](https://github.com/shellac) -- [SudarAbisheck](https://github.com/SudarAbisheck) - -## 开源协议 - -请查看 [Apache License](LICENSE) + +[![](https://dn-biezhi.qbox.me/LOGO_BIG.png)](http://bladejava.com) + +[开始使用](https://bladejava.com/docs)  |  [示例项目](https://github.com/blade-samples)  |  [贡献代码](https://bladejava.com/docs/appendix/contribute)  |  [捐赠]()  |  [FAQ](https://bladejava.com/docs/faqs) |  [English](https://github.com/biezhi/blade/blob/master/README.md) + +[![Build Status](https://img.shields.io/travis/biezhi/blade.svg?style=flat-square)](https://travis-ci.org/biezhi/blade) +[![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![@biezhi on weibo](https://img.shields.io/badge/weibo-%40biezhi-red.svg?style=flat-square)](http://weibo.com/u/5238733773) + +## Blade是什么? + +Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁的代码,优雅的设计。 + +如果你觉得不错, 欢迎 [Star](https://github.com/biezhi/blade/stargazers) / [Fork](https://github.com/biezhi/blade), 谢谢 :blush: + +## 特性 + +* [x] 轻量级, 代码简洁,结构清晰,更容易开发 +* [x] 模块化(你可以选择使用哪些组件) +* [x] 插件扩展机制 +* [x] Restful风格的路由接口 +* [x] 多种配置文件支持(当前支持properties、json和硬编码) +* [x] 多种模板引擎支持 +* [x] 更方便的启动和部署 +* [x] 支持JDK1.6或者更高版本(JDK8写起来更爽) + +## 概述 + +* 简洁的:框架设计简单,容易理解,不依赖于更多第三方库。Blade框架目标让用户在一天内理解并使用。 +* 优雅的:`Blade` 支持 REST 风格路由接口, 提供 DSL 语法编写,无侵入式的拦截器。 +* 易部署:支持 `maven` 打成 `jar` 包直接运行。 + +## 快速入门 + +开始之前,首先 [引入Blade的库文件](http://bladejava.com/docs/intro/getting_start) : + +`Maven` 配置: + +```xml + + com.bladejava + blade-core + 1.6.6 + + + com.bladejava + blade-embed-jetty + 0.0.5 + +``` + +或者 `Gradle`: + +```sh +compile 'com.bladejava:blade-core:1.6.6' +compile 'com.bladejava:blade-embed-jetty:0.0.5' +``` + +编写 `Main`函数: + +```java +public static void main(String[] args) { + $().get("/", (request, response) -> { + response.html("

Hello blade!

"); + }).start(Application.class); +} +``` + +用浏览器打开 http://localhost:9000 这样就可以看到第一个Blade应用了! + +## API示例 + +```java +public static void main(String[] args) { + $().get("/user/21", getxxx); + $().post("/save", postxxx); + $().delete("/del/21", deletexxx); + $().put("/put", putxxx); +} +``` + +## REST URL参数获取 + +```java +public static void main(String[] args) { + $().get("/user/:uid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + response.text("uid : " + uid); + }); + + $().get("/users/:uid/post/:pid", (request, response) -> { + Integer uid = request.paramAsInt("uid"); + Integer pid = request.paramAsInt("pid"); + String msg = "uid = " + uid + ", pid = " + pid; + response.text(msg); + }); + + $().start(Application.class); +} +``` + +## 表单参数获取 + +```java +public static void main(String[] args) { + $().get("/user", (request, response) -> { + Integer uid = request.queryAsInt("uid"); + response.text("uid : " + uid); + }).start(Application.class); +} +``` + +## 上传文件 + +```java +public void upload_img(Request request, Response response){ + + FileItem[] fileItems = request.files(); + if(null != fileItems && fileItems.length > 0){ + + FileItem fileItem = fileItems[0]; + File file = fileItem.getFile(); + + String fileRealPath = "your upload file path!"; + + nioTransferCopy(file, fileRealPath); + } +} +``` + +## 配置文件路由 + +`route.conf` + +```sh +GET / IndexRoute.home +GET /signin IndexRoute.show_signin +POST /signin IndexRoute.signin +GET /signout IndexRoute.signout +POST /upload_img UploadRoute.upload_img +``` + +## 路由拦截 + +```java +public static void main(String[] args) { + $().before("/.*", (request, response) -> { + System.out.println("before..."); + }).start(Application.class); +} +``` + + +这一切看起来多么的简单,不过上面的功能可是冰山一角,查看文档和示例项目有更多惊喜: + ++ [hello工程](https://github.com/blade-samples/hello) ++ [论坛程序](https://github.com/junicorn/java-china) ++ [文档服务](https://github.com/biezhi/grice) ++ [更多例子](https://github.com/blade-samples) + + +## 更新日志 + +[更新日志](https://github.com/biezhi/blade/blob/master/UPDATE_LOG.md) + +## 联系我 + +- Blog:[https://biezhi.me](https://biezhi.me) +- Mail: biezhi.me#gmail.com +- Java交流群: [1013565](http://shang.qq.com/wpa/qunwpa?idkey=932642920a5c0ef5f1ae902723c4f168c58ea63f3cef1139e30d68145d3b5b2f) + +## 贡献 + +非常感谢下面的开发者朋友对本项目的帮助,如果你也愿意提交PR,欢迎你! + +- [mfarid](https://github.com/mfarid) +- [daimajia](https://github.com/daimajia) +- [shenjie1993](https://github.com/shenjie1993) +- [sumory](https://github.com/sumory) +- [udaykadaboina](https://github.com/udaykadaboina) +- [SyedWasiHaider](https://github.com/SyedWasiHaider) +- [Awakens](https://github.com/Awakens) +- [shellac](https://github.com/shellac) +- [SudarAbisheck](https://github.com/SudarAbisheck) + +## 开源协议 + +请查看 [Apache License](LICENSE) From 77abe698cfb77eec8f59111b34f6b95530f417a9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 6 Sep 2016 14:41:52 +0800 Subject: [PATCH 507/545] =?UTF-8?q?=E2=9C=84=20fix=20Packages=20not=20put?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/blade/config/Packages.java | 3 +++ .../src/main/java/com/blade/ioc/IocApplication.java | 12 +++++++----- .../main/java/com/blade/mvc/route/RouteBuilder.java | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/blade-core/src/main/java/com/blade/config/Packages.java b/blade-core/src/main/java/com/blade/config/Packages.java index 6927dca27..2523b4e6b 100644 --- a/blade-core/src/main/java/com/blade/config/Packages.java +++ b/blade-core/src/main/java/com/blade/config/Packages.java @@ -28,8 +28,11 @@ public void add(String name, String...pkgs) { Set values = pool.get(name); if(null == values){ values = new HashSet(pkgs.length); + } else { + pool.remove(name); } values.addAll(Arrays.asList(pkgs)); + pool.put(name, values); } } diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 88bd3b019..88e05e292 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -74,10 +74,9 @@ public IocApplication() { * @throws Exception */ private List loadCondigs() throws Exception { - List configs = null; String[] configPkgs = blade.applicationConfig().getConfigPkgs(); if (null != configPkgs && configPkgs.length > 0) { - configs = new ArrayList(10); + List configs = new ArrayList(10); for (int i = 0, len = configPkgs.length; i < len; i++) { Set configClasses = classReader.getClassByAnnotation(configPkgs[i], Component.class, false); if (null != configClasses) { @@ -88,16 +87,16 @@ private List loadCondigs() throws Exception { configs.add(classInfo); } } - if (classInfo.getClazz().getSuperclass().getName() - .equals("com.blade.aop.AbstractMethodInterceptor")) { + if (classInfo.getClazz().getSuperclass().getName().equals("com.blade.aop.AbstractMethodInterceptor")) { aopInterceptors.add(classInfo.newInstance()); } } } } Collections.sort(configs, orderComparator); + return configs; } - return configs; + return null; } private List loadServices() throws Exception { @@ -129,6 +128,7 @@ private List loadServices() throws Exception { } } } + return services; } return null; } @@ -142,6 +142,7 @@ private List loadControllers() { controllers.addAll(classReader.getClassByAnnotation(routePkgs[i], Controller.class, true)); controllers.addAll(classReader.getClassByAnnotation(routePkgs[i], RestController.class, true)); } + return controllers; } return null; } @@ -159,6 +160,7 @@ private List loadInterceptors() { } } } + return interceptors; } return null; } diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java index 478c772d9..4a70e321e 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java @@ -194,7 +194,7 @@ public void addRouter(final Class router){ String[] paths = mapping.value(); if(null != paths && paths.length > 0){ for(int j=0, plen = paths.length; j Date: Tue, 6 Sep 2016 14:42:12 +0800 Subject: [PATCH 508/545] =?UTF-8?q?=E2=9C=84=20update=20blade-embed-jetty.?= =?UTF-8?q?version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-starter/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-starter/pom.xml b/blade-starter/pom.xml index 8fe7eac09..777faa065 100644 --- a/blade-starter/pom.xml +++ b/blade-starter/pom.xml @@ -23,7 +23,7 @@ 1.0.4 0.0.6 0.0.4 - 0.0.4 + 0.0.5 From 2614805e135b11cbe401a9e20d018cded6ee5777 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 6 Sep 2016 18:43:36 +0800 Subject: [PATCH 509/545] =?UTF-8?q?=E2=9C=84=20update=20config=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/test/java/config.txt | 33 ++++++++++++++++------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/blade-core/src/test/java/config.txt b/blade-core/src/test/java/config.txt index ab00168f4..93b2ecf60 100644 --- a/blade-core/src/test/java/config.txt +++ b/blade-core/src/test/java/config.txt @@ -3,15 +3,15 @@ app base-package ioc - mvc - view - 404 - 500 - statics - http - encoding - cached - xss +mvc + view + 404 + 500 + statics +http + encoding + cached + xss server port timeout @@ -21,11 +21,14 @@ server app.base-package app.ioc -app.mvc.view.404 -app.mvc.view.500 -app.mvc.statics -app.http.encoding -app.http.cached -app.http.xss + +mvc.view.404 +mvc.view.500 +mvc.statics + +http.encoding +http.cached +http.xss + server.port server.timeout \ No newline at end of file From bc96f14946b177cbfe2d253e4cdbe3766a34791e Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 7 Sep 2016 09:11:29 +0800 Subject: [PATCH 510/545] =?UTF-8?q?=E2=9C=84=20update=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++---- README_CN.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 39525508e..ef2d8d56a 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Create `Main` method like this: public static void main(String[] args) { $().get("/", (request, response) -> { response.html("

Hello blade!

"); - }).start(Application.class); + }).start(); } ``` @@ -92,7 +92,7 @@ public static void main(String[] args) { response.text(msg); }); - $().start(Application.class); + $().start(); } ``` @@ -103,7 +103,7 @@ public static void main(String[] args) { $().get("/user", (request, response) -> { Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); - }).start(Application.class); + }).start(); } ``` @@ -143,7 +143,7 @@ POST /upload_img UploadRoute.upload_img public static void main(String[] args) { $().before("/.*", (request, response) -> { System.out.println("before..."); - }).start(Application.class); + }).start(); } ``` diff --git a/README_CN.md b/README_CN.md index cf57a5923..cc8d1bd4e 100644 --- a/README_CN.md +++ b/README_CN.md @@ -63,7 +63,7 @@ compile 'com.bladejava:blade-embed-jetty:0.0.5' public static void main(String[] args) { $().get("/", (request, response) -> { response.html("

Hello blade!

"); - }).start(Application.class); + }).start(); } ``` @@ -96,7 +96,7 @@ public static void main(String[] args) { response.text(msg); }); - $().start(Application.class); + $().start(); } ``` @@ -107,7 +107,7 @@ public static void main(String[] args) { $().get("/user", (request, response) -> { Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); - }).start(Application.class); + }).start(); } ``` @@ -147,7 +147,7 @@ POST /upload_img UploadRoute.upload_img public static void main(String[] args) { $().before("/.*", (request, response) -> { System.out.println("before..."); - }).start(Application.class); + }).start(); } ``` From 6c1d2cf4352516454fc935c69940f21e645efc88 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 7 Sep 2016 16:05:19 +0800 Subject: [PATCH 511/545] =?UTF-8?q?=E2=9C=84=20fix=20start=20Class=20is=20?= =?UTF-8?q?null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 +- README_CN.md | 12 +- blade-core/src/main/java/com/blade/Blade.java | 7 - pom.xml | 176 +++++++++--------- 4 files changed, 100 insertions(+), 110 deletions(-) diff --git a/README.md b/README.md index ef2d8d56a..f1ecb2f62 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,10 @@ If you like it, please [star](https://github.com/biezhi/blade/stargazers) / [for * [x] Lightweight: the code is simple and the structure is clear * [x] Modular (you can choose which components to use) -* [x] Supports plug-in extension mechanism * [x] RESTful style routing interface -* [x] Supports multiple configuration files (currently properties, json and coding) -* [x] Embedded jetty server and template engine support -* [x] Supports JDK 1.6 and up +* [x] Template engine support +* [x] Run with jar file +* [x] Supports JDK 1.6 and up (java8 is cool) ## Overview @@ -59,7 +58,7 @@ Create `Main` method like this: public static void main(String[] args) { $().get("/", (request, response) -> { response.html("

Hello blade!

"); - }).start(); + }).start(Application.class); } ``` @@ -92,7 +91,7 @@ public static void main(String[] args) { response.text(msg); }); - $().start(); + $().start(Application.class); } ``` @@ -103,7 +102,7 @@ public static void main(String[] args) { $().get("/user", (request, response) -> { Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); - }).start(); + }).start(Application.class); } ``` @@ -143,7 +142,7 @@ POST /upload_img UploadRoute.upload_img public static void main(String[] args) { $().before("/.*", (request, response) -> { System.out.println("before..."); - }).start(); + }).start(Application.class); } ``` diff --git a/README_CN.md b/README_CN.md index cc8d1bd4e..d37557a89 100644 --- a/README_CN.md +++ b/README_CN.md @@ -18,11 +18,9 @@ Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁 * [x] 轻量级, 代码简洁,结构清晰,更容易开发 * [x] 模块化(你可以选择使用哪些组件) -* [x] 插件扩展机制 * [x] Restful风格的路由接口 -* [x] 多种配置文件支持(当前支持properties、json和硬编码) * [x] 多种模板引擎支持 -* [x] 更方便的启动和部署 +* [x] 支持以jar文件发布运行 * [x] 支持JDK1.6或者更高版本(JDK8写起来更爽) ## 概述 @@ -63,7 +61,7 @@ compile 'com.bladejava:blade-embed-jetty:0.0.5' public static void main(String[] args) { $().get("/", (request, response) -> { response.html("

Hello blade!

"); - }).start(); + }).start(Application.class); } ``` @@ -96,7 +94,7 @@ public static void main(String[] args) { response.text(msg); }); - $().start(); + $().start(Application.class); } ``` @@ -107,7 +105,7 @@ public static void main(String[] args) { $().get("/user", (request, response) -> { Integer uid = request.queryAsInt("uid"); response.text("uid : " + uid); - }).start(); + }).start(Application.class); } ``` @@ -147,7 +145,7 @@ POST /upload_img UploadRoute.upload_img public static void main(String[] args) { $().before("/.*", (request, response) -> { System.out.println("before..."); - }).start(); + }).start(Application.class); } ``` diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 94450c7ea..e1e6b3502 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -544,13 +544,6 @@ public Blade listen(int port) { return this; } - /** - * start web server - */ - public void start() { - this.start(null); - } - /** * start web server * diff --git a/pom.xml b/pom.xml index 51a471c38..c8abbf098 100644 --- a/pom.xml +++ b/pom.xml @@ -1,89 +1,89 @@ - - - 4.0.0 - - com.bladejava - blade - 1.0 - pom - - blade - https://github.com/biezhi/blade - - - 1.6 - 1.6 - UTF-8 - - 3.0.1 - 4.12 - 1.7.21 - 1.7.21 - - 1.6.6 - 1.3.3 - 1.0.0 - 0.0.4 - - - - - blade-kit - blade-core - blade-embed-jetty - blade-auth - blade-aop - blade-starter - - - - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - - - - org.slf4j - slf4j-api - ${slf4j-api.version} - - - org.slf4j - slf4j-log4j12 - ${slf4j-log4j12.version} - - - junit - junit - ${junit.version} - test - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.6 - 1.6 - UTF-8 - - - - - + + + 4.0.0 + + com.bladejava + blade + 1.0 + pom + + blade + https://github.com/biezhi/blade + + + 1.6 + 1.6 + UTF-8 + + 3.0.1 + 4.12 + 1.7.21 + 1.7.21 + + 1.6.7-alpha + 1.3.3 + 1.0.0 + 0.0.4 + + + + + blade-kit + blade-core + blade-embed-jetty + blade-auth + blade-aop + blade-starter + + + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + + org.slf4j + slf4j-api + ${slf4j-api.version} + + + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} + + + junit + junit + ${junit.version} + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + UTF-8 + + + + + \ No newline at end of file From 433b29c4eda625c7dbc0c802c7f8c1a963b2c58d Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 12 Sep 2016 14:11:13 +0800 Subject: [PATCH 512/545] =?UTF-8?q?=E2=9C=84=20add=20rest=20respose=20mode?= =?UTF-8?q?l?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/blade/mvc/view/RestResponse.java | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 blade-core/src/main/java/com/blade/mvc/view/RestResponse.java diff --git a/blade-core/src/main/java/com/blade/mvc/view/RestResponse.java b/blade-core/src/main/java/com/blade/mvc/view/RestResponse.java new file mode 100644 index 000000000..e271706f4 --- /dev/null +++ b/blade-core/src/main/java/com/blade/mvc/view/RestResponse.java @@ -0,0 +1,109 @@ +package com.blade.mvc.view; + +/** + * rest返回对象 + * + * @param + */ +public class RestResponse { + + /** + * 服务器响应数据 + */ + private T payload; + + /** + * 请求是否成功 + */ + private boolean success; + + /** + * 错误信息 + */ + private String msg; + + /** + * 服务器响应时间 + */ + private long timestamp; + + public static RestResponse build(T data){ + RestResponse r = new RestResponse(); + r.setPayload(data); + r.setSuccess(true); + return r; + } + public RestResponse() { + this.timestamp = System.currentTimeMillis() / 1000; + } + + public RestResponse(T payload) { + this.success = true; + this.payload = payload; + this.timestamp = System.currentTimeMillis() / 1000; + } + + public RestResponse(boolean success) { + this.success = success; + this.timestamp = System.currentTimeMillis() / 1000; + } + + public RestResponse(String msg) { + this.success = false; + this.msg = msg; + this.timestamp = System.currentTimeMillis() / 1000; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public boolean isSuccess() { + return success; + } + + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public T getPayload() { + return payload; + } + + public void setPayload(T payload) { + this.setPayload(payload, true); + } + + public void setPayload(T payload, boolean success) { + this.payload = payload; + this.success = success; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + @Override + public String toString() { + return "RestResponse{" + + "payload=" + payload + + ", success=" + success + + ", msg=" + msg + + ", timestamp=" + timestamp + + '}'; + } + + public void error(String msg) { + this.msg = msg; + this.success = false; + } +} \ No newline at end of file From af14210ba79d8f165d1f973635a8d69aa48d799e Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 17 Sep 2016 22:34:26 +0800 Subject: [PATCH 513/545] =?UTF-8?q?=E2=9C=84=20add=20blade=20websocket=20s?= =?UTF-8?q?erver?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blade/websocket/WebSocketException.java | 28 +++ .../com/blade/websocket/WebSocketServer.java | 13 ++ blade-websocket-jetty/pom.xml | 38 ++++ .../blade/websocket/JettyWebSocketServer.java | 65 +++++++ pom.xml | 176 +++++++++--------- 5 files changed, 232 insertions(+), 88 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/websocket/WebSocketException.java create mode 100644 blade-core/src/main/java/com/blade/websocket/WebSocketServer.java create mode 100644 blade-websocket-jetty/pom.xml create mode 100644 blade-websocket-jetty/src/main/java/com/blade/websocket/JettyWebSocketServer.java diff --git a/blade-core/src/main/java/com/blade/websocket/WebSocketException.java b/blade-core/src/main/java/com/blade/websocket/WebSocketException.java new file mode 100644 index 000000000..1c959244a --- /dev/null +++ b/blade-core/src/main/java/com/blade/websocket/WebSocketException.java @@ -0,0 +1,28 @@ +package com.blade.websocket; + +import com.blade.exception.BladeException; + +public class WebSocketException extends BladeException { + + /** + * + */ + private static final long serialVersionUID = -5109944185187744851L; + + public WebSocketException() { + super(); + } + + public WebSocketException(String message, Throwable cause) { + super(message, cause); + } + + public WebSocketException(String message) { + super(message); + } + + public WebSocketException(Throwable cause) { + super(cause); + } + +} diff --git a/blade-core/src/main/java/com/blade/websocket/WebSocketServer.java b/blade-core/src/main/java/com/blade/websocket/WebSocketServer.java new file mode 100644 index 000000000..795611e1b --- /dev/null +++ b/blade-core/src/main/java/com/blade/websocket/WebSocketServer.java @@ -0,0 +1,13 @@ +package com.blade.websocket; + +public interface WebSocketServer { + + void start(int port) throws WebSocketException; + + void start(int port, String context) throws WebSocketException; + + void stop() throws WebSocketException; + + void addEndpoints(Class... endPoints); + +} \ No newline at end of file diff --git a/blade-websocket-jetty/pom.xml b/blade-websocket-jetty/pom.xml new file mode 100644 index 000000000..3734cdca6 --- /dev/null +++ b/blade-websocket-jetty/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + com.bladejava + blade + 1.0 + + blade-websocket-jetty + 0.0.1 + blade-websocket-jetty + http://maven.apache.org + + + UTF-8 + 9.2.12.v20150709 + + + + + com.bladejava + blade-core + ${blade-core.version} + + + javax.websocket + javax.websocket-api + 1.0 + + + org.eclipse.jetty.websocket + javax-websocket-server-impl + ${jetty.version} + + + diff --git a/blade-websocket-jetty/src/main/java/com/blade/websocket/JettyWebSocketServer.java b/blade-websocket-jetty/src/main/java/com/blade/websocket/JettyWebSocketServer.java new file mode 100644 index 000000000..73298f839 --- /dev/null +++ b/blade-websocket-jetty/src/main/java/com/blade/websocket/JettyWebSocketServer.java @@ -0,0 +1,65 @@ +package com.blade.websocket; + +import javax.websocket.server.ServerContainer; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; + +public class JettyWebSocketServer implements WebSocketServer { + + private Server server; + private ServletContextHandler context; + private ServerContainer wscontainer; + private Class[] endPoints; + + @Override + public void start(int port) throws WebSocketException{ + this.start(port, "/"); + } + + @Override + public void start(int port, String contextPath) throws WebSocketException{ + server = new Server(); + ServerConnector connector = new ServerConnector(server); + connector.setPort(port); + server.addConnector(connector); + + // Setup the basic application "context" for this application at "/" + // This is also known as the handler tree (in jetty speak) + context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath(contextPath); + server.setHandler(context); + try { + // Initialize javax.websocket layer + wscontainer = WebSocketServerContainerInitializer.configureContext(context); + if (null != endPoints) { + // Add WebSocket endpoint to javax.websocket layer + for (int i = 0; i < endPoints.length; i++) { + wscontainer.addEndpoint(endPoints[i]); + } + } + server.start(); + server.dump(System.err); + server.join(); + } catch (Throwable t) { + throw new WebSocketException(t); + } + } + + @Override + public void stop() throws WebSocketException{ + try { + server.stop(); + } catch (Exception e) { + throw new WebSocketException(e); + } + } + + @Override + public void addEndpoints(Class... endPoints) { + this.endPoints = endPoints; + } + +} diff --git a/pom.xml b/pom.xml index c8abbf098..3251a10ea 100644 --- a/pom.xml +++ b/pom.xml @@ -1,89 +1,89 @@ - - - 4.0.0 - - com.bladejava - blade - 1.0 - pom - - blade - https://github.com/biezhi/blade - - - 1.6 - 1.6 - UTF-8 - - 3.0.1 - 4.12 - 1.7.21 - 1.7.21 - - 1.6.7-alpha - 1.3.3 - 1.0.0 - 0.0.4 - - - - - blade-kit - blade-core - blade-embed-jetty - blade-auth - blade-aop - blade-starter - - - - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - - - - org.slf4j - slf4j-api - ${slf4j-api.version} - - - org.slf4j - slf4j-log4j12 - ${slf4j-log4j12.version} - - - junit - junit - ${junit.version} - test - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.6 - 1.6 - UTF-8 - - - - - + + + 4.0.0 + + com.bladejava + blade + 1.0 + pom + + blade + https://github.com/biezhi/blade + + + 1.6 + 1.6 + UTF-8 + + 3.0.1 + 4.12 + 1.7.21 + 1.7.21 + + 1.6.7-alpha + 1.3.3 + 1.0.0 + 0.0.4 + + + + + blade-kit + blade-core + blade-embed-jetty + blade-auth + blade-aop + blade-starter + blade-websocket-jetty + + + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + + org.slf4j + slf4j-api + ${slf4j-api.version} + + + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} + + + junit + junit + ${junit.version} + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + UTF-8 + + + + + \ No newline at end of file From bbba6d60629bb31480af3dbb6cc415ea284baa0a Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 18 Sep 2016 10:38:32 +0800 Subject: [PATCH 514/545] =?UTF-8?q?=E2=9C=84=20add=20test=20code=20and=20r?= =?UTF-8?q?ename=20@RequestParam=20annotation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LAST_VERSION.md | 9 + blade-core/pom.xml | 26 +- blade-core/src/main/java/com/blade/Blade.java | 11 +- .../java/com/blade/embedd/EmbedServer.java | 78 +++--- .../java/com/blade/ioc/IocApplication.java | 13 +- .../{PathVariable.java => PathParam.java} | 74 ++--- .../{RequestParam.java => QueryParam.java} | 80 +++--- .../blade/mvc/view/handle/MethodArgument.java | 264 +++++++++--------- .../blade/websocket/WebSocketException.java | 21 ++ .../com/blade/websocket/WebSocketServer.java | 23 ++ .../com/blade/embedd/EmbedJettyServer.java | 135 +++++++++ .../test/java/com/blade/test/BladeTest.java | 65 +++++ blade-core/src/test/java/log4j.properties | 6 + blade-embed-jetty/pom.xml | 104 ++++--- .../com/blade/embedd/EmbedJettyServer.java | 260 ++++++++--------- .../blade/websocket/JettyWebSocketServer.java | 36 ++- pom.xml | 21 +- 17 files changed, 780 insertions(+), 446 deletions(-) rename blade-core/src/main/java/com/blade/mvc/annotation/{PathVariable.java => PathParam.java} (94%) rename blade-core/src/main/java/com/blade/mvc/annotation/{RequestParam.java => QueryParam.java} (94%) create mode 100644 blade-core/src/test/java/com/blade/embedd/EmbedJettyServer.java create mode 100644 blade-core/src/test/java/com/blade/test/BladeTest.java create mode 100644 blade-core/src/test/java/log4j.properties diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 89418b7a3..5d4596e66 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -56,6 +56,15 @@
``` +## [blade-websocket-jetty](http://search.maven.org/#search%7Cga%7C1%7Cblade-websocket-jetty) +```xml + +    com.bladejava +    blade-websocket-jetty +    0.0.1 + +``` + ## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache) ```xml diff --git a/blade-core/pom.xml b/blade-core/pom.xml index 93505d3fe..b2a83c0e5 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -34,11 +34,6 @@ - com.github.lalyos - jfiglet - 0.0.7 - - javax.servlet javax.servlet-api ${servlet.version} @@ -50,6 +45,25 @@ junit test - + + + org.mockito + mockito-all + test + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + test + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + test + + diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index e1e6b3502..01bb65f67 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -549,7 +549,13 @@ public Blade listen(int port) { * * @param applicationClass your app root package starter */ - public void start(Class applicationClass) { + public EmbedServer start(Class applicationClass) { + startNoJoin(applicationClass); + embedServer.join(); + return embedServer; + } + + public EmbedServer startNoJoin(Class applicationClass) { this.loadAppConf(Const.APP_PROPERTIES); @@ -578,8 +584,9 @@ public void start(Class applicationClass) { } catch (Exception e) { e.printStackTrace(); } + return embedServer; } - + /** * @return Return EmbedServer */ diff --git a/blade-core/src/main/java/com/blade/embedd/EmbedServer.java b/blade-core/src/main/java/com/blade/embedd/EmbedServer.java index 3aa4b8d19..eebd6e92f 100644 --- a/blade-core/src/main/java/com/blade/embedd/EmbedServer.java +++ b/blade-core/src/main/java/com/blade/embedd/EmbedServer.java @@ -1,38 +1,40 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.embedd; - -import com.blade.exception.EmbedServerException; - -/** - * Jetty Server - * - * @author biezhi - * @since 1.6.6 - */ -public interface EmbedServer { - - void startup(int port) throws EmbedServerException; - - void startup(int port, String contextPath) throws EmbedServerException; - - void startup(int port, String contextPath, String webRoot) throws EmbedServerException; - - void stop() throws EmbedServerException; - - void setWebRoot(String webRoot); - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.embedd; + +import com.blade.exception.EmbedServerException; + +/** + * Jetty Server + * + * @author biezhi + * @since 1.6.6 + */ +public interface EmbedServer { + + void startup(int port) throws EmbedServerException; + + void startup(int port, String contextPath) throws EmbedServerException; + + void startup(int port, String contextPath, String webRoot) throws EmbedServerException; + + void join() throws EmbedServerException; + + void shutdown() throws EmbedServerException; + + void setWebRoot(String webRoot); + +} diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 88e05e292..ae7081b80 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -18,6 +18,7 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -60,7 +61,7 @@ public class IocApplication { private ClassReader classReader = null; private Blade blade; private OrderComparator orderComparator; - + public IocApplication() { this.blade = Blade.$(); this.classReader = DynamicContext.getClassReader(); @@ -182,13 +183,14 @@ public void initBeans() throws Exception { ioc.addBean(services.get(i).getClazz()); } } + + Set baseConfigs = new HashSet(); // 2. init configs if (null != configs) { for(int i=0, len=configs.size(); i getAopInterceptors() { diff --git a/blade-core/src/main/java/com/blade/mvc/annotation/PathVariable.java b/blade-core/src/main/java/com/blade/mvc/annotation/PathParam.java similarity index 94% rename from blade-core/src/main/java/com/blade/mvc/annotation/PathVariable.java rename to blade-core/src/main/java/com/blade/mvc/annotation/PathParam.java index 15d0a549e..773503706 100644 --- a/blade-core/src/main/java/com/blade/mvc/annotation/PathVariable.java +++ b/blade-core/src/main/java/com/blade/mvc/annotation/PathParam.java @@ -1,37 +1,37 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Request Path Parameter Annotation - * - * @author biezhi - * @since 1.6.6 - */ -@Target(ElementType.PARAMETER) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface PathVariable { - - String value() default ""; - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Request Path Parameter Annotation + * + * @author biezhi + * @since 1.6.6 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface PathParam { + + String value() default ""; + +} diff --git a/blade-core/src/main/java/com/blade/mvc/annotation/RequestParam.java b/blade-core/src/main/java/com/blade/mvc/annotation/QueryParam.java similarity index 94% rename from blade-core/src/main/java/com/blade/mvc/annotation/RequestParam.java rename to blade-core/src/main/java/com/blade/mvc/annotation/QueryParam.java index 7e1a3eba7..1d3511884 100644 --- a/blade-core/src/main/java/com/blade/mvc/annotation/RequestParam.java +++ b/blade-core/src/main/java/com/blade/mvc/annotation/QueryParam.java @@ -1,41 +1,41 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Request Query ParmeterAnnotation - * - * @author biezhi - * @since 1.6.6 - */ -@Target(ElementType.PARAMETER) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface RequestParam { - - String value() default ""; - - boolean required() default true; - - String defaultValue() default ""; - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Request Query ParmeterAnnotation + * + * @author biezhi + * @since 1.6.6 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface QueryParam { + + String value() default ""; + + boolean required() default true; + + String defaultValue() default ""; + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java index ab4ffab49..4d146cf40 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java @@ -1,132 +1,132 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.handle; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - -import com.blade.exception.BladeException; -import com.blade.exception.NotFoundException; -import com.blade.kit.AsmKit; -import com.blade.kit.StringKit; -import com.blade.mvc.annotation.PathVariable; -import com.blade.mvc.annotation.RequestParam; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.multipart.FileItem; -import com.blade.mvc.view.ModelAndView; - -public final class MethodArgument { - - public static Object[] getArgs(Request request, Response response, Method actionMethod) throws Exception{ - Class[] parameters = actionMethod.getParameterTypes(); - Annotation[][] paramterAnnotations = actionMethod.getParameterAnnotations(); - - Object[] args = new Object[parameters.length]; - - try { - actionMethod.setAccessible(true); - String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); - - for (int i = 0, len = parameters.length; i < len; i++) { - - Class argType = parameters[i]; - if (argType.getName().equals(Request.class.getName())) { - args[i] = request; - continue; - } - - if (argType.getName().equals(Response.class.getName())) { - args[i] = response; - continue; - } - - if (argType.getName().equals(ModelAndView.class.getName())) { - args[i] = new ModelAndView(); - continue; - } - - if(argType.getName().equals(FileItem.class.getName())){ - args[i] = new ModelAndView(); - continue; - } - - Annotation annotation = paramterAnnotations[i][0]; - - if(null != annotation){ - if(annotation.annotationType().equals(RequestParam.class)){ - RequestParam requestParam = (RequestParam) annotation; - String paramName = requestParam.value(); - String val = request.query(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.query(paramName); - } - if (StringKit.isBlank(val)) { - val = requestParam.defaultValue(); - } - args[i] = getRequestParam(argType, val); - continue; - } - - if(annotation.annotationType().equals(PathVariable.class)){ - PathVariable pathVariable = (PathVariable) annotation; - String paramName = pathVariable.value(); - String val = request.param(paramName); - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.param(paramName); - } - if (StringKit.isBlank(val)) { - throw new NotFoundException("path param [" + paramName + "] is null"); - } - args[i] = getRequestParam(argType, val); - continue; - } - } - } - return args; - } catch (BladeException e) { - throw e; - } - } - - private static Object getRequestParam(Class parameterType, String val) { - Object result = null; - if (parameterType.equals(String.class)) { - result = val; - } else if (parameterType.equals(Integer.class)) { - result = Integer.parseInt(val); - } else if (parameterType.equals(int.class)) { - if(StringKit.isBlank(val)){ - result = 0; - } else { - result = Integer.parseInt(val); - } - } else if (parameterType.equals(Long.class)) { - result = Long.parseLong(val); - } else if (parameterType.equals(long.class)) { - if(StringKit.isBlank(val)){ - result = 0L; - } else { - result = Integer.parseInt(val); - } - } - return result; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.handle; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import com.blade.exception.BladeException; +import com.blade.exception.NotFoundException; +import com.blade.kit.AsmKit; +import com.blade.kit.StringKit; +import com.blade.mvc.annotation.PathParam; +import com.blade.mvc.annotation.QueryParam; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.multipart.FileItem; +import com.blade.mvc.view.ModelAndView; + +public final class MethodArgument { + + public static Object[] getArgs(Request request, Response response, Method actionMethod) throws Exception{ + Class[] parameters = actionMethod.getParameterTypes(); + Annotation[][] paramterAnnotations = actionMethod.getParameterAnnotations(); + + Object[] args = new Object[parameters.length]; + + try { + actionMethod.setAccessible(true); + String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); + + for (int i = 0, len = parameters.length; i < len; i++) { + + Class argType = parameters[i]; + if (argType.getName().equals(Request.class.getName())) { + args[i] = request; + continue; + } + + if (argType.getName().equals(Response.class.getName())) { + args[i] = response; + continue; + } + + if (argType.getName().equals(ModelAndView.class.getName())) { + args[i] = new ModelAndView(); + continue; + } + + if(argType.getName().equals(FileItem.class.getName())){ + args[i] = new ModelAndView(); + continue; + } + + Annotation annotation = paramterAnnotations[i][0]; + + if(null != annotation){ + if(annotation.annotationType().equals(QueryParam.class)){ + QueryParam queryParam = (QueryParam) annotation; + String paramName = queryParam.value(); + String val = request.query(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.query(paramName); + } + if (StringKit.isBlank(val)) { + val = queryParam.defaultValue(); + } + args[i] = getRequestParam(argType, val); + continue; + } + + if(annotation.annotationType().equals(PathParam.class)){ + PathParam pathParam = (PathParam) annotation; + String paramName = pathParam.value(); + String val = request.param(paramName); + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.param(paramName); + } + if (StringKit.isBlank(val)) { + throw new NotFoundException("path param [" + paramName + "] is null"); + } + args[i] = getRequestParam(argType, val); + continue; + } + } + } + return args; + } catch (BladeException e) { + throw e; + } + } + + private static Object getRequestParam(Class parameterType, String val) { + Object result = null; + if (parameterType.equals(String.class)) { + result = val; + } else if (parameterType.equals(Integer.class)) { + result = Integer.parseInt(val); + } else if (parameterType.equals(int.class)) { + if(StringKit.isBlank(val)){ + result = 0; + } else { + result = Integer.parseInt(val); + } + } else if (parameterType.equals(Long.class)) { + result = Long.parseLong(val); + } else if (parameterType.equals(long.class)) { + if(StringKit.isBlank(val)){ + result = 0L; + } else { + result = Integer.parseInt(val); + } + } + return result; + } + +} diff --git a/blade-core/src/main/java/com/blade/websocket/WebSocketException.java b/blade-core/src/main/java/com/blade/websocket/WebSocketException.java index 1c959244a..2748cbdce 100644 --- a/blade-core/src/main/java/com/blade/websocket/WebSocketException.java +++ b/blade-core/src/main/java/com/blade/websocket/WebSocketException.java @@ -1,7 +1,28 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.websocket; import com.blade.exception.BladeException; +/** + * WebSocketException + * + * @author biezhi + * @since 1.6.6 + */ public class WebSocketException extends BladeException { /** diff --git a/blade-core/src/main/java/com/blade/websocket/WebSocketServer.java b/blade-core/src/main/java/com/blade/websocket/WebSocketServer.java index 795611e1b..19b7a2407 100644 --- a/blade-core/src/main/java/com/blade/websocket/WebSocketServer.java +++ b/blade-core/src/main/java/com/blade/websocket/WebSocketServer.java @@ -1,11 +1,34 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.websocket; +/** + * WebSocket API + * + * @author biezhi + * @since 1.6.6 + */ public interface WebSocketServer { void start(int port) throws WebSocketException; void start(int port, String context) throws WebSocketException; + void join() throws WebSocketException; + void stop() throws WebSocketException; void addEndpoints(Class... endPoints); diff --git a/blade-core/src/test/java/com/blade/embedd/EmbedJettyServer.java b/blade-core/src/test/java/com/blade/embedd/EmbedJettyServer.java new file mode 100644 index 000000000..b5a8f34e8 --- /dev/null +++ b/blade-core/src/test/java/com/blade/embedd/EmbedJettyServer.java @@ -0,0 +1,135 @@ +package com.blade.embedd; + +import static com.blade.Blade.$; + +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.HandlerList; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.eclipse.jetty.webapp.WebAppContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Const; +import com.blade.exception.EmbedServerException; +import com.blade.kit.base.Config; +import com.blade.mvc.DispatcherServlet; + +public class EmbedJettyServer implements EmbedServer { + + private static final Logger LOGGER = LoggerFactory.getLogger(EmbedJettyServer.class); + + private int port = Const.DEFAULT_PORT; + + private Server server; + + private WebAppContext webAppContext; + + private Config config = null; + + public EmbedJettyServer() { + System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); + $().loadAppConf("jetty.properties"); + config = $().config(); + $().enableServer(true); + } + + @Override + public void startup(int port) throws EmbedServerException { + this.startup(port, Const.DEFAULT_CONTEXTPATH, null); + } + + @Override + public void startup(int port, String contextPath) throws EmbedServerException { + this.startup(port, contextPath, null); + } + + @Override + public void setWebRoot(String webRoot) { + webAppContext.setResourceBase(webRoot); + } + + @Override + public void startup(int port, String contextPath, String webRoot) throws EmbedServerException { + this.port = port; + + // Setup Threadpool + QueuedThreadPool threadPool = new QueuedThreadPool(); + + int minThreads = config.getInt("server.jetty.min-threads", 100); + int maxThreads = config.getInt("server.jetty.max-threads", 500); + + threadPool.setMinThreads(minThreads); + threadPool.setMaxThreads(maxThreads); + + server = new org.eclipse.jetty.server.Server(threadPool); + + // 设置在JVM退出时关闭Jetty的钩子。 + server.setStopAtShutdown(true); + + webAppContext = new WebAppContext(); + webAppContext.setContextPath(contextPath); + webAppContext.setResourceBase(""); + + int securePort = config.getInt("server.jetty.http.secure-port", 8443); + int outputBufferSize = config.getInt("server.jetty.http.output-buffersize", 32768); + int requestHeaderSize = config.getInt("server.jetty.http.request-headersize", 8192); + int responseHeaderSize = config.getInt("server.jetty.http.response-headersize", 8192); + + // HTTP Configuration + HttpConfiguration http_config = new HttpConfiguration(); + http_config.setSecurePort(securePort); + http_config.setOutputBufferSize(outputBufferSize); + http_config.setRequestHeaderSize(requestHeaderSize); + http_config.setResponseHeaderSize(responseHeaderSize); + http_config.setSendServerVersion(true); + http_config.setSendDateHeader(false); + + long idleTimeout = config.getLong("server.jetty.http.idle-timeout", 30000L); + + ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(http_config)); + http.setPort(this.port); + http.setIdleTimeout(idleTimeout); + server.addConnector(http); + + ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); + servletHolder.setAsyncSupported(false); + servletHolder.setInitOrder(1); + + webAppContext.addServlet(servletHolder, "/"); + + HandlerList handlers = new HandlerList(); + handlers.setHandlers(new Handler[] { webAppContext, new DefaultHandler() }); + server.setHandler(handlers); + + try { + server.start(); + LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); + } catch (Exception e) { + throw new EmbedServerException(e); + } + } + + public void shutdown() throws EmbedServerException { + try { + server.stop(); + } catch (Exception e) { + throw new EmbedServerException(e); + } + } + + @Override + public void join() throws EmbedServerException { + try { + server.join(); + } catch (InterruptedException e) { + throw new EmbedServerException(e); + } + } + +} \ No newline at end of file diff --git a/blade-core/src/test/java/com/blade/test/BladeTest.java b/blade-core/src/test/java/com/blade/test/BladeTest.java new file mode 100644 index 000000000..0746c3ef2 --- /dev/null +++ b/blade-core/src/test/java/com/blade/test/BladeTest.java @@ -0,0 +1,65 @@ +package com.blade.test; + +import org.junit.Assert; +import org.junit.Test; + +import com.blade.Blade; +import com.blade.kit.http.HttpRequest; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.route.RouteHandler; + +public class BladeTest { + + @Test + public void testCode200() throws Exception { + Blade blade = Blade.$(); + blade.get("/", new RouteHandler() { + @Override + public void handle(Request request, Response response) { + + } + }).startNoJoin(BladeTest.class); + try { + Thread.sleep(100); + int resCode = HttpRequest.get("http://127.0.0.1:9000").code(); + Assert.assertEquals(resCode, 200); + } finally { + blade.embedServer().shutdown(); + } + } + + @Test + public void testCode404() throws Exception { + Blade blade = Blade.$(); + blade.startNoJoin(BladeTest.class); + try { + Thread.sleep(100); + int resCode = HttpRequest.get("http://127.0.0.1:9000/hello").code(); + Assert.assertEquals(resCode, 404); + } finally { + blade.embedServer().shutdown(); + } + } + + @Test + public void testCode500() throws Exception { + Blade blade = Blade.$(); + try { + blade.get("/:id", new RouteHandler() { + @Override + public void handle(Request request, Response response) { + int id = request.paramAsInt("id"); + System.out.println(id); + } + }).startNoJoin(BladeTest.class); + Thread.sleep(100); + int resCode = HttpRequest.get("http://127.0.0.1:9000/abc").code(); + Assert.assertEquals(resCode, 500); + } catch (Exception e) { + } finally { + blade.embedServer().shutdown(); + } + } + +} diff --git a/blade-core/src/test/java/log4j.properties b/blade-core/src/test/java/log4j.properties new file mode 100644 index 000000000..aeb65bb06 --- /dev/null +++ b/blade-core/src/test/java/log4j.properties @@ -0,0 +1,6 @@ +log4j.rootLogger = info, stdout + +log4j.appender.stdout = org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout = org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern = [blade-core] %d %-5p [%t] %c | %m%n +log4j.logger.com.blade = debug \ No newline at end of file diff --git a/blade-embed-jetty/pom.xml b/blade-embed-jetty/pom.xml index 63543267a..18043792d 100644 --- a/blade-embed-jetty/pom.xml +++ b/blade-embed-jetty/pom.xml @@ -1,54 +1,50 @@ - - - 4.0.0 - - com.bladejava - blade - 1.0 - - - blade-embed-jetty - ${blade-embed-jetty.version} - blade-embed-jetty - http://maven.apache.org - - - 9.2.12.v20150709 - - - - - - org.slf4j - slf4j-api - - - - com.bladejava - blade-core - ${blade-core.version} - - - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - - - org.eclipse.jetty - jetty-server - ${jetty.version} - - - org.eclipse.jetty - jetty-webapp - ${jetty.version} - - - - - + + + 4.0.0 + + com.bladejava + blade + 1.0 + + + blade-embed-jetty + ${blade-embed-jetty.version} + blade-embed-jetty + http://maven.apache.org + + + + + org.slf4j + slf4j-api + + + + com.bladejava + blade-core + ${blade-core.version} + + + + javax.servlet + javax.servlet-api + ${servlet.version} + provided + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + + + + + diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index 062678d59..d0cca9b82 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -1,127 +1,135 @@ -package com.blade.embedd; - -import static com.blade.Blade.$; - -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.handler.DefaultHandler; -import org.eclipse.jetty.server.handler.HandlerList; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.eclipse.jetty.webapp.WebAppContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Const; -import com.blade.exception.EmbedServerException; -import com.blade.kit.base.Config; -import com.blade.mvc.DispatcherServlet; - -public class EmbedJettyServer implements EmbedServer { - - private static final Logger LOGGER = LoggerFactory.getLogger(EmbedJettyServer.class); - - private int port = Const.DEFAULT_PORT; - - private Server server; - - private WebAppContext webAppContext; - - private Config config = null; - - public EmbedJettyServer() { - System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); - $().loadAppConf("jetty.properties"); - config = $().config(); - $().enableServer(true); - } - - @Override - public void startup(int port) throws EmbedServerException { - this.startup(port, Const.DEFAULT_CONTEXTPATH, null); - } - - @Override - public void startup(int port, String contextPath) throws EmbedServerException { - this.startup(port, contextPath, null); - } - - @Override - public void setWebRoot(String webRoot) { - webAppContext.setResourceBase(webRoot); - } - - @Override - public void startup(int port, String contextPath, String webRoot) throws EmbedServerException { - this.port = port; - - // Setup Threadpool - QueuedThreadPool threadPool = new QueuedThreadPool(); - - int minThreads = config.getInt("server.jetty.min-threads", 100); - int maxThreads = config.getInt("server.jetty.max-threads", 500); - - threadPool.setMinThreads(minThreads); - threadPool.setMaxThreads(maxThreads); - - server = new org.eclipse.jetty.server.Server(threadPool); - - // 设置在JVM退出时关闭Jetty的钩子。 - server.setStopAtShutdown(true); - - webAppContext = new WebAppContext(); - webAppContext.setContextPath(contextPath); - webAppContext.setResourceBase(""); - - int securePort = config.getInt("server.jetty.http.secure-port", 8443); - int outputBufferSize = config.getInt("server.jetty.http.output-buffersize", 32768); - int requestHeaderSize = config.getInt("server.jetty.http.request-headersize", 8192); - int responseHeaderSize = config.getInt("server.jetty.http.response-headersize", 8192); - - // HTTP Configuration - HttpConfiguration http_config = new HttpConfiguration(); - http_config.setSecurePort(securePort); - http_config.setOutputBufferSize(outputBufferSize); - http_config.setRequestHeaderSize(requestHeaderSize); - http_config.setResponseHeaderSize(responseHeaderSize); - http_config.setSendServerVersion(true); - http_config.setSendDateHeader(false); - - long idleTimeout = config.getLong("server.jetty.http.idle-timeout", 30000L); - - ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(http_config)); - http.setPort(this.port); - http.setIdleTimeout(idleTimeout); - server.addConnector(http); - - ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); - servletHolder.setAsyncSupported(false); - servletHolder.setInitOrder(1); - - webAppContext.addServlet(servletHolder, "/"); - - HandlerList handlers = new HandlerList(); - handlers.setHandlers(new Handler[] { webAppContext, new DefaultHandler() }); - server.setHandler(handlers); - - try { - server.start(); - LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); - server.join(); - } catch (Exception e) { - throw new EmbedServerException(e); - } - } - - public void stop() throws EmbedServerException { - try { - server.stop(); - } catch (Exception e) { - throw new EmbedServerException(e); - } - } - +package com.blade.embedd; + +import static com.blade.Blade.$; + +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.HandlerList; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.eclipse.jetty.webapp.WebAppContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Const; +import com.blade.exception.EmbedServerException; +import com.blade.kit.base.Config; +import com.blade.mvc.DispatcherServlet; + +public class EmbedJettyServer implements EmbedServer { + + private static final Logger LOGGER = LoggerFactory.getLogger(EmbedJettyServer.class); + + private int port = Const.DEFAULT_PORT; + + private Server server; + + private WebAppContext webAppContext; + + private Config config = null; + + public EmbedJettyServer() { + System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); + $().loadAppConf("jetty.properties"); + config = $().config(); + $().enableServer(true); + } + + @Override + public void startup(int port) throws EmbedServerException { + this.startup(port, Const.DEFAULT_CONTEXTPATH, null); + } + + @Override + public void startup(int port, String contextPath) throws EmbedServerException { + this.startup(port, contextPath, null); + } + + @Override + public void setWebRoot(String webRoot) { + webAppContext.setResourceBase(webRoot); + } + + @Override + public void startup(int port, String contextPath, String webRoot) throws EmbedServerException { + this.port = port; + + // Setup Threadpool + QueuedThreadPool threadPool = new QueuedThreadPool(); + + int minThreads = config.getInt("server.jetty.min-threads", 100); + int maxThreads = config.getInt("server.jetty.max-threads", 500); + + threadPool.setMinThreads(minThreads); + threadPool.setMaxThreads(maxThreads); + + server = new org.eclipse.jetty.server.Server(threadPool); + + // 设置在JVM退出时关闭Jetty的钩子。 + server.setStopAtShutdown(true); + + webAppContext = new WebAppContext(); + webAppContext.setContextPath(contextPath); + webAppContext.setResourceBase(""); + + int securePort = config.getInt("server.jetty.http.secure-port", 8443); + int outputBufferSize = config.getInt("server.jetty.http.output-buffersize", 32768); + int requestHeaderSize = config.getInt("server.jetty.http.request-headersize", 8192); + int responseHeaderSize = config.getInt("server.jetty.http.response-headersize", 8192); + + // HTTP Configuration + HttpConfiguration http_config = new HttpConfiguration(); + http_config.setSecurePort(securePort); + http_config.setOutputBufferSize(outputBufferSize); + http_config.setRequestHeaderSize(requestHeaderSize); + http_config.setResponseHeaderSize(responseHeaderSize); + http_config.setSendServerVersion(true); + http_config.setSendDateHeader(false); + + long idleTimeout = config.getLong("server.jetty.http.idle-timeout", 30000L); + + ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(http_config)); + http.setPort(this.port); + http.setIdleTimeout(idleTimeout); + server.addConnector(http); + + ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); + servletHolder.setAsyncSupported(false); + servletHolder.setInitOrder(1); + + webAppContext.addServlet(servletHolder, "/"); + + HandlerList handlers = new HandlerList(); + handlers.setHandlers(new Handler[] { webAppContext, new DefaultHandler() }); + server.setHandler(handlers); + + try { + server.start(); + LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); + } catch (Exception e) { + throw new EmbedServerException(e); + } + } + + public void shutdown() throws EmbedServerException { + try { + server.stop(); + } catch (Exception e) { + throw new EmbedServerException(e); + } + } + + @Override + public void join() throws EmbedServerException { + try { + server.join(); + } catch (InterruptedException e) { + throw new EmbedServerException(e); + } + } + } \ No newline at end of file diff --git a/blade-websocket-jetty/src/main/java/com/blade/websocket/JettyWebSocketServer.java b/blade-websocket-jetty/src/main/java/com/blade/websocket/JettyWebSocketServer.java index 73298f839..78ac7159e 100644 --- a/blade-websocket-jetty/src/main/java/com/blade/websocket/JettyWebSocketServer.java +++ b/blade-websocket-jetty/src/main/java/com/blade/websocket/JettyWebSocketServer.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.websocket; import javax.websocket.server.ServerContainer; @@ -7,6 +22,12 @@ import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; +/** + * JettyWebSocketServer + * + * @author biezhi + * @since 1.6.7 + */ public class JettyWebSocketServer implements WebSocketServer { private Server server; @@ -14,6 +35,10 @@ public class JettyWebSocketServer implements WebSocketServer { private ServerContainer wscontainer; private Class[] endPoints; + public JettyWebSocketServer(Class...endPoints) { + this.endPoints = endPoints; + } + @Override public void start(int port) throws WebSocketException{ this.start(port, "/"); @@ -41,8 +66,6 @@ public void start(int port, String contextPath) throws WebSocketException{ } } server.start(); - server.dump(System.err); - server.join(); } catch (Throwable t) { throw new WebSocketException(t); } @@ -61,5 +84,14 @@ public void stop() throws WebSocketException{ public void addEndpoints(Class... endPoints) { this.endPoints = endPoints; } + + @Override + public void join() throws WebSocketException { + try { + server.join(); + } catch (InterruptedException e) { + throw new WebSocketException(e); + } + } } diff --git a/pom.xml b/pom.xml index 3251a10ea..ec56899a4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 com.bladejava @@ -14,16 +15,18 @@ 1.6 1.6 UTF-8 - - 3.0.1 + + 3.1.0 4.12 + 2.0.2-beta 1.7.21 1.7.21 - + 1.6.7-alpha 1.3.3 1.0.0 0.0.4 + 9.2.12.v20150709 @@ -34,8 +37,8 @@ blade-auth blade-aop blade-starter - blade-websocket-jetty - + blade-websocket-jetty + @@ -68,6 +71,12 @@ ${junit.version} test + + org.mockito + mockito-all + ${mockito.version} + test + From 6a898824908c98ee03f659c22980e25457362531 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 19 Sep 2016 10:12:14 +0800 Subject: [PATCH 515/545] =?UTF-8?q?=E2=9C=84=20add=20fileitem=20params?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/blade/mvc/annotation/CookieParam.java | 37 + .../com/blade/mvc/annotation/HeaderParam.java | 37 + .../blade/mvc/annotation/MultipartParam.java | 37 + .../main/java/com/blade/mvc/http/Request.java | 727 ++++++----- .../mvc/http/wrapper/ServletRequest.java | 1156 +++++++++-------- .../com/blade/mvc/multipart/FileItem.java | 157 +-- .../blade/mvc/view/handle/MethodArgument.java | 64 +- 7 files changed, 1193 insertions(+), 1022 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/mvc/annotation/CookieParam.java create mode 100644 blade-core/src/main/java/com/blade/mvc/annotation/HeaderParam.java create mode 100644 blade-core/src/main/java/com/blade/mvc/annotation/MultipartParam.java diff --git a/blade-core/src/main/java/com/blade/mvc/annotation/CookieParam.java b/blade-core/src/main/java/com/blade/mvc/annotation/CookieParam.java new file mode 100644 index 000000000..6cc726909 --- /dev/null +++ b/blade-core/src/main/java/com/blade/mvc/annotation/CookieParam.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Request Cookie ParmeterAnnotation + * + * @author biezhi + * @since 1.6.6 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface CookieParam { + + String value() default ""; + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/annotation/HeaderParam.java b/blade-core/src/main/java/com/blade/mvc/annotation/HeaderParam.java new file mode 100644 index 000000000..1ccad885c --- /dev/null +++ b/blade-core/src/main/java/com/blade/mvc/annotation/HeaderParam.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Request Header ParmeterAnnotation + * + * @author biezhi + * @since 1.6.6 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface HeaderParam { + + String value() default ""; + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/annotation/MultipartParam.java b/blade-core/src/main/java/com/blade/mvc/annotation/MultipartParam.java new file mode 100644 index 000000000..5a8f0053d --- /dev/null +++ b/blade-core/src/main/java/com/blade/mvc/annotation/MultipartParam.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Form Multipart ParmeterAnnotation + * + * @author biezhi + * @since 1.6.6 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface MultipartParam { + + String value() default "file"; + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/http/Request.java b/blade-core/src/main/java/com/blade/mvc/http/Request.java index d2f3bb382..af3d2e780 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/Request.java +++ b/blade-core/src/main/java/com/blade/mvc/http/Request.java @@ -1,362 +1,367 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http; - -import java.io.InputStream; -import java.io.Serializable; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletContext; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; - -import com.blade.mvc.http.wrapper.Session; -import com.blade.mvc.multipart.FileItem; -import com.blade.mvc.route.Route; - -/** - * HTTP Request - * - * @author biezhi - * @since 1.5 - */ -public interface Request { - - /** - * @return Return HttpServletRequest - */ - HttpServletRequest raw(); - - /** - * URL parameters on the initial route, e.g:/user/23 - * @param routePath Route URL - */ - void initPathParams(String routePath); - - /** - * @return Return client request host - */ - String host(); - - /** - * @return Return request URL - */ - String url(); - - /** - * @return Return request URI - */ - String uri(); - - /** - * @return Return UA - */ - String userAgent(); - - /** - * @return Return PathInfo - */ - String pathInfo(); - - /** - * @return Return protocol - */ - String protocol(); - - /** - * @return Return servletPath - */ - String servletPath(); - - /** - * @return Return contextPath - */ - String contextPath(); - - /** - * @return Return ServletContext - */ - ServletContext context(); - - /** - * @return Return parameters on the path Map - */ - Map pathParams(); - - /** - * Get a URL parameter - * @param name Parameter name - * @return Return parameter value - */ - String param(String name); - - /** - * Get a URL parameter, and returns defaultValue if it is NULL - * @param name Parameter name - * @param defaultValue Default Value - * @return Return parameter value - */ - String param(String name, String defaultValue); - - /** - * Return a URL parameter for a Int type - * @param name Parameter name - * @return Return Int parameter value - */ - Integer paramAsInt(String name); - - /** - * Return a URL parameter for a Long type - * @param name Parameter name - * @return Return Long parameter value - */ - Long paramAsLong(String name); - - /** - * Return a URL parameter for a Boolean type - * @param name Parameter name - * @return Return Boolean parameter value - */ - Boolean paramAsBool(String name); - - /** - * @return Return query string - */ - String queryString(); - - /** - * @return Return request query Map - */ - Map querys(); - - /** - * Get a request parameter - * - * @param name Parameter name - * @return Return request parameter value - */ - String query(String name); - - /** - * Get a request parameter, if NULL is returned to defaultValue - * - * @param name Parameter name - * @param defaultValue Default value - * @return Return request parameter values - */ - String query(String name, String defaultValue); - - /** - * Returns a request parameter for a Int type - * - * @param name Parameter name - * @return Return Int parameter values - */ - Integer queryAsInt(String name); - - /** - * Returns a request parameter for a Long type - * - * @param name Parameter name - * @return Return Long parameter values - */ - Long queryAsLong(String name); - - /** - * Returns a request parameter for a Boolean type - * - * @param name Parameter name - * @return Return Boolean parameter values - */ - Boolean queryAsBool(String name); - - /** - * Returns a request parameter for a Float type - * - * @param name Parameter name - * @return Return Float parameter values - */ - Float queryAsFloat(String name); - - /** - * Returns a request parameter for a Double type - * - * @param name Parameter name - * @return Return Double parameter values - */ - Double queryAsDouble(String name); - - /** - * @return Return request method - */ - String method(); - - /** - * @return Return HttpMethod - */ - HttpMethod httpMethod(); - - /** - * @return Return server remote address - */ - String address(); - - /** - * @return Return current session - */ - Session session(); - - /** - * Return to the current or create a session - * @param create create session - * @return Return session - */ - Session session(boolean create); - - /** - * @return Return contentType - */ - String contentType(); - - /** - * @return Return Server Port - */ - int port(); - - /** - * @return Return whether to use the SSL connection - */ - boolean isSecure(); - - /** - * @return Return current request is a AJAX request - */ - boolean isAjax(); - - /** - * @return Return Cookie Map - */ - Map cookies(); - - /** - * Get String Cookie Value - * - * @param name cookie name - * @return Return Cookie Value - */ - String cookie(String name); - - /** - * Get Cookie - * - * @param name cookie name - * @return Return Cookie - */ - Cookie cookieRaw(String name); - - /** - * @return Return header information Map - */ - Map headers(); - - /** - * Get header information - * - * @param name Parameter name - * @return Return header information - */ - String header(String name); - - /** - * Setting request encoding - * - * @param encoding coded string - */ - void encoding(String encoding); - - /** - * Setting Request Attribute - * - * @param name Parameter name - * @param value Parameter Value - */ - void attribute(String name, Object value); - - /** - * Get a Request Attribute - * @param name Parameter name - * @return Return parameter value - */ - T attribute(String name); - - /** - * @return Return all Attribute in Request - */ - Set attributes(); - - /** - * @return Return the requested file list - */ - FileItem[] files(); - - /** - * @return Return request body - */ - BodyParser body(); - - /** - * Serialized form data, converted to the javabean - * - * @param slug bean slug, e.g: , the slug is person - * @param clazz bean type - * @return Return converted Bean Object - */ - T model(String slug, Class clazz); - - /** - * Setting route, execute request for use - * - * @param route route object - */ - void setRoute(Route route); - - /** - * @return Return Route of the current request - */ - Route route(); - - /** - * Abort current request - */ - void abort(); - - /** - * @return Return is abort request - */ - boolean isAbort(); - - /** - * Request body interface - * @author biezhi - */ - interface BodyParser { - String asString(); - InputStream asInputStream(); - byte[] asByte(); - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http; + +import java.io.InputStream; +import java.io.Serializable; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletContext; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; + +import com.blade.mvc.http.wrapper.Session; +import com.blade.mvc.multipart.FileItem; +import com.blade.mvc.route.Route; + +/** + * HTTP Request + * + * @author biezhi + * @since 1.5 + */ +public interface Request { + + /** + * @return Return HttpServletRequest + */ + HttpServletRequest raw(); + + /** + * URL parameters on the initial route, e.g:/user/23 + * @param routePath Route URL + */ + void initPathParams(String routePath); + + /** + * @return Return client request host + */ + String host(); + + /** + * @return Return request URL + */ + String url(); + + /** + * @return Return request URI + */ + String uri(); + + /** + * @return Return UA + */ + String userAgent(); + + /** + * @return Return PathInfo + */ + String pathInfo(); + + /** + * @return Return protocol + */ + String protocol(); + + /** + * @return Return servletPath + */ + String servletPath(); + + /** + * @return Return contextPath + */ + String contextPath(); + + /** + * @return Return ServletContext + */ + ServletContext context(); + + /** + * @return Return parameters on the path Map + */ + Map pathParams(); + + /** + * Get a URL parameter + * @param name Parameter name + * @return Return parameter value + */ + String param(String name); + + /** + * Get a URL parameter, and returns defaultValue if it is NULL + * @param name Parameter name + * @param defaultValue Default Value + * @return Return parameter value + */ + String param(String name, String defaultValue); + + /** + * Return a URL parameter for a Int type + * @param name Parameter name + * @return Return Int parameter value + */ + Integer paramAsInt(String name); + + /** + * Return a URL parameter for a Long type + * @param name Parameter name + * @return Return Long parameter value + */ + Long paramAsLong(String name); + + /** + * Return a URL parameter for a Boolean type + * @param name Parameter name + * @return Return Boolean parameter value + */ + Boolean paramAsBool(String name); + + /** + * @return Return query string + */ + String queryString(); + + /** + * @return Return request query Map + */ + Map querys(); + + /** + * Get a request parameter + * + * @param name Parameter name + * @return Return request parameter value + */ + String query(String name); + + /** + * Get a request parameter, if NULL is returned to defaultValue + * + * @param name Parameter name + * @param defaultValue Default value + * @return Return request parameter values + */ + String query(String name, String defaultValue); + + /** + * Returns a request parameter for a Int type + * + * @param name Parameter name + * @return Return Int parameter values + */ + Integer queryAsInt(String name); + + /** + * Returns a request parameter for a Long type + * + * @param name Parameter name + * @return Return Long parameter values + */ + Long queryAsLong(String name); + + /** + * Returns a request parameter for a Boolean type + * + * @param name Parameter name + * @return Return Boolean parameter values + */ + Boolean queryAsBool(String name); + + /** + * Returns a request parameter for a Float type + * + * @param name Parameter name + * @return Return Float parameter values + */ + Float queryAsFloat(String name); + + /** + * Returns a request parameter for a Double type + * + * @param name Parameter name + * @return Return Double parameter values + */ + Double queryAsDouble(String name); + + /** + * @return Return request method + */ + String method(); + + /** + * @return Return HttpMethod + */ + HttpMethod httpMethod(); + + /** + * @return Return server remote address + */ + String address(); + + /** + * @return Return current session + */ + Session session(); + + /** + * Return to the current or create a session + * @param create create session + * @return Return session + */ + Session session(boolean create); + + /** + * @return Return contentType + */ + String contentType(); + + /** + * @return Return Server Port + */ + int port(); + + /** + * @return Return whether to use the SSL connection + */ + boolean isSecure(); + + /** + * @return Return current request is a AJAX request + */ + boolean isAjax(); + + /** + * @return Return Cookie Map + */ + Map cookies(); + + /** + * Get String Cookie Value + * + * @param name cookie name + * @return Return Cookie Value + */ + String cookie(String name); + + /** + * Get Cookie + * + * @param name cookie name + * @return Return Cookie + */ + Cookie cookieRaw(String name); + + /** + * @return Return header information Map + */ + Map headers(); + + /** + * Get header information + * + * @param name Parameter name + * @return Return header information + */ + String header(String name); + + /** + * Setting request encoding + * + * @param encoding coded string + */ + void encoding(String encoding); + + /** + * Setting Request Attribute + * + * @param name Parameter name + * @param value Parameter Value + */ + void attribute(String name, Object value); + + /** + * Get a Request Attribute + * @param name Parameter name + * @return Return parameter value + */ + T attribute(String name); + + /** + * @return Return all Attribute in Request + */ + Set attributes(); + + /** + * @return Return the requested file list + */ + @Deprecated + FileItem[] files(); + + Map fileItems(); + + FileItem fileItem(String name); + + /** + * @return Return request body + */ + BodyParser body(); + + /** + * Serialized form data, converted to the javabean + * + * @param slug bean slug, e.g: , the slug is person + * @param clazz bean type + * @return Return converted Bean Object + */ + T model(String slug, Class clazz); + + /** + * Setting route, execute request for use + * + * @param route route object + */ + void setRoute(Route route); + + /** + * @return Return Route of the current request + */ + Route route(); + + /** + * Abort current request + */ + void abort(); + + /** + * @return Return is abort request + */ + boolean isAbort(); + + /** + * Request body interface + * @author biezhi + */ + interface BodyParser { + String asString(); + InputStream asInputStream(); + byte[] asByte(); + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java index 1193515e4..cb48b3517 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java @@ -1,576 +1,582 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http.wrapper; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.ServletContext; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.kit.IOKit; -import com.blade.kit.ObjectKit; -import com.blade.kit.StringKit; -import com.blade.mvc.http.HttpMethod; -import com.blade.mvc.http.Path; -import com.blade.mvc.http.Request; -import com.blade.mvc.multipart.FileItem; -import com.blade.mvc.multipart.Multipart; -import com.blade.mvc.multipart.MultipartException; -import com.blade.mvc.multipart.MultipartHandler; -import com.blade.mvc.route.Route; - -/** - * ServletRequest - * - * @author biezhi - * @since 1.5 - */ -public class ServletRequest implements Request { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServletRequest.class); - - private static final String USER_AGENT = "user-agent"; - - protected Route route; - - private HttpServletRequest request; - - // path parameter eg: /user/12 - private Map pathParams = null; - - // query parameter eg: /user?name=jack - private Map queryParams = null; - - private List files = null; - - private Session session = null; - - private boolean isAbort = false; - - public ServletRequest(HttpServletRequest request) throws MultipartException, IOException { - this.request = request; - this.pathParams = new HashMap(8); - this.queryParams = new HashMap(16); - this.files = new ArrayList(8); - this.init(); - } - - public void init() throws IOException, MultipartException { - // retrieve multipart/form-data parameters - if (Multipart.isMultipartContent(request)) { - Multipart multipart = new Multipart(); - multipart.parse(request, new MultipartHandler() { - @Override - public void handleFormItem(String name, String value) { - queryParams.put( name, value ); - } - @Override - public void handleFileItem(String name, FileItem fileItem) { - files.add(fileItem); - } - }); - } - } - - private String join(String[] arr) { - StringBuffer ret = new StringBuffer(); - for (String item : arr) { - ret.append(',').append(item); - } - if (ret.length() > 0) { - return ret.substring(1); - } - return ret.toString(); - } - - @Override - public void initPathParams(String routePath) { - this.pathParams.clear(); - - List variables = getPathParam(routePath); - String regexPath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); - - String uri = Path.getRelativePath(uri(), contextPath()); - - Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(uri); - - if(matcher.matches()){ - // start index at 1 as group(0) always stands for the entire expression - for (int i=1, len = variables.size(); i <= len; i++) { - String value = matcher.group(i); - this.pathParams.put(variables.get(i-1), value); - } - } - } - - private List getPathParam(String routePath) { - List variables = new ArrayList(8); - Matcher matcher = Pattern.compile(Path.VAR_REGEXP).matcher(routePath); - while (matcher.find()) { - variables.add(matcher.group(1)); - } - return variables; - } - - @Override - public HttpServletRequest raw() { - return request; - } - - @Override - public String host() { - return request.getServerName(); - } - - @Override - public String url() { - return request.getRequestURL().toString(); - } - - @Override - public String uri() { - return Path.fixPath(request.getRequestURI()); - } - - @Override - public String userAgent() { - return request.getHeader(USER_AGENT); - } - - @Override - public String pathInfo() { - return request.getPathInfo(); - } - - @Override - public String protocol() { - return request.getProtocol(); - } - - @Override - public String servletPath() { - return request.getServletPath(); - } - - @Override - public String contextPath() { - return request.getContextPath(); - } - - @Override - public ServletContext context() { - return request.getServletContext(); - } - - @Override - public Map pathParams() { - return pathParams; - } - - @Override - public String param(String name) { - return pathParams.get(name); - } - - @Override - public String param(String name, String defaultValue) { - String val = pathParams.get(name); - if(null == val){ - val = defaultValue; - } - return val; - } - - @Override - public Integer paramAsInt(String name) { - String value = param(name); - if (StringKit.isNotBlank(value)) { - return Integer.parseInt(value); - } - return null; - } - - @Override - public Long paramAsLong(String name) { - String value = param(name); - if (StringKit.isNotBlank(value)) { - return Long.parseLong(value); - } - return null; - } - - @Override - public Boolean paramAsBool(String name) { - String value = param(name); - if (StringKit.isNotBlank(value)) { - return Boolean.parseBoolean(value); - } - return null; - } - - @Override - public String queryString() { - return request.getQueryString(); - } - - @Override - public Map querys() { - Map params = new HashMap(); - - Map requestParams = request.getParameterMap(); - for (Map.Entry entry : requestParams.entrySet()) { - params.put( entry.getKey(), join(entry.getValue()) ); - } - params.putAll(queryParams); - return Collections.unmodifiableMap(params); - } - - @Override - public String query(String name) { - String[] param = request.getParameterValues(name); - String val = null; - if (param != null) { - val = join(param); - } else { - val = queryParams.get(name); - } - return val; - } - - @Override - public String query(String name, String defaultValue) { - String[] param = request.getParameterValues(name); - String val = null; - if (param != null) { - val = join(param); - } else { - val = queryParams.get(name); - } - if(null == val){ - val = defaultValue; - } - return val; - } - - @Override - public Integer queryAsInt(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { - return Integer.parseInt(value); - } - return null; - } - - @Override - public Long queryAsLong(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { - return Long.parseLong(value); - } - return null; - } - - @Override - public Boolean queryAsBool(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isBoolean(value)) { - return Boolean.parseBoolean(value); - } - return null; - } - - @Override - public Float queryAsFloat(String name) { - String value = query(name); - if (StringKit.isNotBlank(value)) { - try { - return Float.parseFloat(value); - } catch (NumberFormatException e) { - } - } - return null; - } - - @Override - public Double queryAsDouble(String name) { - String value = query(name); - if (StringKit.isNotBlank(value)) { - try { - return Double.parseDouble(value); - } catch (NumberFormatException e) { - } - } - return null; - } - - @Override - public String method() { - return request.getMethod(); - } - - @Override - public HttpMethod httpMethod() { - return HttpMethod.valueOf(request.getMethod().toUpperCase()); - } - - @Override - public String address() { - return request.getRemoteAddr(); - } - - @Override - public Session session() { - if (session == null) { - session = new Session(request.getSession()); - } - return session; - } - - @Override - public Session session(boolean create) { - if (session == null) { - HttpSession httpSession = request.getSession(create); - if (httpSession != null) { - session = new Session(httpSession); - } - } - return session; - } - - @Override - public void attribute(String name, Object value) { - request.setAttribute(name, value); - } - - @SuppressWarnings("unchecked") - @Override - public T attribute(String name) { - Object object = request.getAttribute(name); - if(null != object){ - return (T) object; - } - return null; - } - - @Override - public Set attributes() { - Set attrList = new HashSet(8); - Enumeration attributes = (Enumeration) request.getAttributeNames(); - while (attributes.hasMoreElements()) { - attrList.add(attributes.nextElement()); - } - return attrList; - } - - @Override - public String contentType() { - return request.getContentType(); - } - - @Override - public int port() { - return request.getServerPort(); - } - - @Override - public boolean isSecure() { - return request.isSecure(); - } - - @Override - public boolean isAjax() { - if (null == header("x-requested-with")) { - return false; - } - return "XMLHttpRequest".equals(header("x-requested-with")); - } - - @Override - public Map cookies() { - javax.servlet.http.Cookie[] servletCookies = request.getCookies(); - Map cookies = new HashMap(8); - for (javax.servlet.http.Cookie c : servletCookies) { - cookies.put( c.getName(), map(c) ); - } - return Collections.unmodifiableMap(cookies); - } - - private Cookie map(Cookie servletCookie) { - Cookie cookie = new Cookie(servletCookie.getName(), servletCookie.getValue()); - cookie.setMaxAge(servletCookie.getMaxAge()); - cookie.setHttpOnly(servletCookie.isHttpOnly()); - String path = servletCookie.getPath(); - if(null != path){ - cookie.setPath(path); - } - String domain = servletCookie.getDomain(); - if(null != domain){ - cookie.setDomain(domain); - } - cookie.setSecure(servletCookie.getSecure()); - return cookie; - } - - @Override - public String cookie(String name) { - Cookie cookie = cookieRaw(name); - if(null != cookie){ - return cookie.getValue(); - } - return null; - } - - @Override - public Cookie cookieRaw(String name) { - javax.servlet.http.Cookie[] servletCookies = request.getCookies(); - if (servletCookies == null) { - return null; - } - for (javax.servlet.http.Cookie c : servletCookies) { - if (c.getName().equals(name)) { - return map(c); - } - } - return null; - } - - @Override - public Map headers() { - Enumeration servletHeaders = request.getHeaderNames(); - Map headers = new HashMap(16); - while(servletHeaders.hasMoreElements()) { - String headerName = servletHeaders.nextElement(); - headers.put(headerName, request.getHeader(headerName)); - } - return headers; - } - - @Override - public String header(String name) { - return request.getHeader(name); - } - - @Override - public void encoding(String encoding) { - try { - request.setCharacterEncoding(encoding); - } catch (UnsupportedEncodingException e) { - LOGGER.error(e.getMessage(), e); - } - } - - @Override - public void setRoute(Route route) { - this.route = route; - initPathParams(route.getPath()); - } - - @Override - public Route route() { - return this.route; - } - - @Override - public void abort() { - this.isAbort = true; - } - - @Override - public boolean isAbort() { - return this.isAbort; - } - - @Override - public T model(String slug, Class clazz) { - if(StringKit.isNotBlank(slug) && null != clazz){ - return ObjectKit.model(slug, clazz, querys()); - } - return null; - } - - @Override - public FileItem[] files() { - FileItem[] fileParts = new FileItem[files.size()]; - for (int i=0, len=files.size(); i < len; i++) { - fileParts[i] = files.get(i); - } - return fileParts; - } - - @Override - public BodyParser body() { - return new BodyParser() { - @Override - public String asString() { - try { - BufferedReader reader = new BufferedReader( new InputStreamReader(request.getInputStream()) ); - StringBuilder sb = new StringBuilder(); - String line = reader.readLine(); - while (null != line) { - sb.append(line + "\r\n"); - line = reader.readLine(); - } - reader.close(); - return sb.toString(); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return null; - } - - @Override - public InputStream asInputStream() { - try { - return request.getInputStream(); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return null; - } - - @Override - public byte[] asByte() { - try { - return IOKit.toByteArray(request.getInputStream()); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - return null; - } - }; - } - +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.http.wrapper; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.ServletContext; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.IOKit; +import com.blade.kit.ObjectKit; +import com.blade.kit.StringKit; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.multipart.FileItem; +import com.blade.mvc.multipart.Multipart; +import com.blade.mvc.multipart.MultipartException; +import com.blade.mvc.multipart.MultipartHandler; +import com.blade.mvc.route.Route; + +/** + * ServletRequest + * + * @author biezhi + * @since 1.5 + */ +public class ServletRequest implements Request { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServletRequest.class); + + private static final String USER_AGENT = "user-agent"; + + protected Route route; + + private HttpServletRequest request; + + // path parameter eg: /user/12 + private Map pathParams = null; + + // query parameter eg: /user?name=jack + private Map queryParams = null; + + private Map fileItems = null; + + private Session session = null; + + private boolean isAbort = false; + + public ServletRequest(HttpServletRequest request) throws MultipartException, IOException { + this.request = request; + this.pathParams = new HashMap(8); + this.queryParams = new HashMap(16); + this.fileItems = new HashMap(8); + this.init(); + } + + public void init() throws IOException, MultipartException { + // retrieve multipart/form-data parameters + if (Multipart.isMultipartContent(request)) { + Multipart multipart = new Multipart(); + multipart.parse(request, new MultipartHandler() { + @Override + public void handleFormItem(String name, String value) { + queryParams.put( name, value ); + } + @Override + public void handleFileItem(String name, FileItem fileItem) { + fileItems.put(name, fileItem); + } + }); + } + } + + private String join(String[] arr) { + StringBuffer ret = new StringBuffer(); + for (String item : arr) { + ret.append(',').append(item); + } + if (ret.length() > 0) { + return ret.substring(1); + } + return ret.toString(); + } + + @Override + public void initPathParams(String routePath) { + this.pathParams.clear(); + + List variables = getPathParam(routePath); + String regexPath = routePath.replaceAll(Path.VAR_REGEXP, Path.VAR_REPLACE); + + String uri = Path.getRelativePath(uri(), contextPath()); + + Matcher matcher = Pattern.compile("(?i)" + regexPath).matcher(uri); + + if(matcher.matches()){ + // start index at 1 as group(0) always stands for the entire expression + for (int i=1, len = variables.size(); i <= len; i++) { + String value = matcher.group(i); + this.pathParams.put(variables.get(i-1), value); + } + } + } + + private List getPathParam(String routePath) { + List variables = new ArrayList(8); + Matcher matcher = Pattern.compile(Path.VAR_REGEXP).matcher(routePath); + while (matcher.find()) { + variables.add(matcher.group(1)); + } + return variables; + } + + @Override + public HttpServletRequest raw() { + return request; + } + + @Override + public String host() { + return request.getServerName(); + } + + @Override + public String url() { + return request.getRequestURL().toString(); + } + + @Override + public String uri() { + return Path.fixPath(request.getRequestURI()); + } + + @Override + public String userAgent() { + return request.getHeader(USER_AGENT); + } + + @Override + public String pathInfo() { + return request.getPathInfo(); + } + + @Override + public String protocol() { + return request.getProtocol(); + } + + @Override + public String servletPath() { + return request.getServletPath(); + } + + @Override + public String contextPath() { + return request.getContextPath(); + } + + @Override + public ServletContext context() { + return request.getServletContext(); + } + + @Override + public Map pathParams() { + return pathParams; + } + + @Override + public String param(String name) { + return pathParams.get(name); + } + + @Override + public String param(String name, String defaultValue) { + String val = pathParams.get(name); + if(null == val){ + val = defaultValue; + } + return val; + } + + @Override + public Integer paramAsInt(String name) { + String value = param(name); + if (StringKit.isNotBlank(value)) { + return Integer.parseInt(value); + } + return null; + } + + @Override + public Long paramAsLong(String name) { + String value = param(name); + if (StringKit.isNotBlank(value)) { + return Long.parseLong(value); + } + return null; + } + + @Override + public Boolean paramAsBool(String name) { + String value = param(name); + if (StringKit.isNotBlank(value)) { + return Boolean.parseBoolean(value); + } + return null; + } + + @Override + public String queryString() { + return request.getQueryString(); + } + + @Override + public Map querys() { + Map params = new HashMap(); + + Map requestParams = request.getParameterMap(); + for (Map.Entry entry : requestParams.entrySet()) { + params.put( entry.getKey(), join(entry.getValue()) ); + } + params.putAll(queryParams); + return Collections.unmodifiableMap(params); + } + + @Override + public String query(String name) { + String[] param = request.getParameterValues(name); + String val = null; + if (param != null) { + val = join(param); + } else { + val = queryParams.get(name); + } + return val; + } + + @Override + public String query(String name, String defaultValue) { + String[] param = request.getParameterValues(name); + String val = null; + if (param != null) { + val = join(param); + } else { + val = queryParams.get(name); + } + if(null == val){ + val = defaultValue; + } + return val; + } + + @Override + public Integer queryAsInt(String name) { + String value = query(name); + if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { + return Integer.parseInt(value); + } + return null; + } + + @Override + public Long queryAsLong(String name) { + String value = query(name); + if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { + return Long.parseLong(value); + } + return null; + } + + @Override + public Boolean queryAsBool(String name) { + String value = query(name); + if (StringKit.isNotBlank(value) && StringKit.isBoolean(value)) { + return Boolean.parseBoolean(value); + } + return null; + } + + @Override + public Float queryAsFloat(String name) { + String value = query(name); + if (StringKit.isNotBlank(value)) { + try { + return Float.parseFloat(value); + } catch (NumberFormatException e) { + } + } + return null; + } + + @Override + public Double queryAsDouble(String name) { + String value = query(name); + if (StringKit.isNotBlank(value)) { + try { + return Double.parseDouble(value); + } catch (NumberFormatException e) { + } + } + return null; + } + + @Override + public String method() { + return request.getMethod(); + } + + @Override + public HttpMethod httpMethod() { + return HttpMethod.valueOf(request.getMethod().toUpperCase()); + } + + @Override + public String address() { + return request.getRemoteAddr(); + } + + @Override + public Session session() { + if (session == null) { + session = new Session(request.getSession()); + } + return session; + } + + @Override + public Session session(boolean create) { + if (session == null) { + HttpSession httpSession = request.getSession(create); + if (httpSession != null) { + session = new Session(httpSession); + } + } + return session; + } + + @Override + public void attribute(String name, Object value) { + request.setAttribute(name, value); + } + + @SuppressWarnings("unchecked") + @Override + public T attribute(String name) { + Object object = request.getAttribute(name); + if(null != object){ + return (T) object; + } + return null; + } + + @Override + public Set attributes() { + Set attrList = new HashSet(8); + Enumeration attributes = (Enumeration) request.getAttributeNames(); + while (attributes.hasMoreElements()) { + attrList.add(attributes.nextElement()); + } + return attrList; + } + + @Override + public String contentType() { + return request.getContentType(); + } + + @Override + public int port() { + return request.getServerPort(); + } + + @Override + public boolean isSecure() { + return request.isSecure(); + } + + @Override + public boolean isAjax() { + if (null == header("x-requested-with")) { + return false; + } + return "XMLHttpRequest".equals(header("x-requested-with")); + } + + @Override + public Map cookies() { + javax.servlet.http.Cookie[] servletCookies = request.getCookies(); + Map cookies = new HashMap(8); + for (javax.servlet.http.Cookie c : servletCookies) { + cookies.put( c.getName(), map(c) ); + } + return Collections.unmodifiableMap(cookies); + } + + private Cookie map(Cookie servletCookie) { + Cookie cookie = new Cookie(servletCookie.getName(), servletCookie.getValue()); + cookie.setMaxAge(servletCookie.getMaxAge()); + cookie.setHttpOnly(servletCookie.isHttpOnly()); + String path = servletCookie.getPath(); + if(null != path){ + cookie.setPath(path); + } + String domain = servletCookie.getDomain(); + if(null != domain){ + cookie.setDomain(domain); + } + cookie.setSecure(servletCookie.getSecure()); + return cookie; + } + + @Override + public String cookie(String name) { + Cookie cookie = cookieRaw(name); + if(null != cookie){ + return cookie.getValue(); + } + return null; + } + + @Override + public Cookie cookieRaw(String name) { + javax.servlet.http.Cookie[] servletCookies = request.getCookies(); + if (servletCookies == null) { + return null; + } + for (javax.servlet.http.Cookie c : servletCookies) { + if (c.getName().equals(name)) { + return map(c); + } + } + return null; + } + + @Override + public Map headers() { + Enumeration servletHeaders = request.getHeaderNames(); + Map headers = new HashMap(16); + while(servletHeaders.hasMoreElements()) { + String headerName = servletHeaders.nextElement(); + headers.put(headerName, request.getHeader(headerName)); + } + return headers; + } + + @Override + public String header(String name) { + return request.getHeader(name); + } + + @Override + public void encoding(String encoding) { + try { + request.setCharacterEncoding(encoding); + } catch (UnsupportedEncodingException e) { + LOGGER.error(e.getMessage(), e); + } + } + + @Override + public void setRoute(Route route) { + this.route = route; + initPathParams(route.getPath()); + } + + @Override + public Route route() { + return this.route; + } + + @Override + public void abort() { + this.isAbort = true; + } + + @Override + public boolean isAbort() { + return this.isAbort; + } + + @Override + public T model(String slug, Class clazz) { + if(StringKit.isNotBlank(slug) && null != clazz){ + return ObjectKit.model(slug, clazz, querys()); + } + return null; + } + + @Override + public FileItem[] files() { + return this.fileItems.values().toArray(new FileItem[fileItems.size()]); + } + + @Override + public Map fileItems() { + return this.fileItems; + } + + @Override + public FileItem fileItem(String name) { + return this.fileItems.get(name); + } + + @Override + public BodyParser body() { + return new BodyParser() { + @Override + public String asString() { + try { + BufferedReader reader = new BufferedReader( new InputStreamReader(request.getInputStream()) ); + StringBuilder sb = new StringBuilder(); + String line = reader.readLine(); + while (null != line) { + sb.append(line + "\r\n"); + line = reader.readLine(); + } + reader.close(); + return sb.toString(); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + @Override + public InputStream asInputStream() { + try { + return request.getInputStream(); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + @Override + public byte[] asByte() { + try { + return IOKit.toByteArray(request.getInputStream()); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + }; + } + } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/multipart/FileItem.java b/blade-core/src/main/java/com/blade/mvc/multipart/FileItem.java index a25b0ffe4..90840f794 100644 --- a/blade-core/src/main/java/com/blade/mvc/multipart/FileItem.java +++ b/blade-core/src/main/java/com/blade/mvc/multipart/FileItem.java @@ -1,78 +1,79 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.multipart; - -import java.io.File; -import java.util.HashMap; -import java.util.Map; - -/** - * HTTP multipart/form-data Request - * - * @author biezhi - * @since 1.5 - */ -public class FileItem { - - private String name; - - private String fileName; - - private String contentType; - - private long contentLength; - - private File file; - - private Map headers; - - public FileItem(String fieldName, String fileName, String contentType, long contentLength, File file, Map headers) { - - this.fileName = fileName; - this.contentType = contentType; - this.contentLength = contentLength; - this.file = file; - this.headers = headers; - if (headers == null) { - this.headers = new HashMap(); - } - } - - public String getName() { - return name; - } - - public String getFileName() { - return fileName; - } - - public String getContentType() { - return contentType; - } - - public long getContentLength() { - return contentLength; - } - - public File getFile() { - return file; - } - - public Map getHeaders() { - return headers; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.multipart; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +/** + * HTTP multipart/form-data Request + * + * @author biezhi + * @since 1.5 + */ +public class FileItem { + + private String name; + + private String fileName; + + private String contentType; + + private long contentLength; + + private File file; + + private Map headers; + + public FileItem(String fieldName, String fileName, String contentType, long contentLength, File file, Map headers) { + + this.fileName = fileName; + this.contentType = contentType; + this.contentLength = contentLength; + this.file = file; + this.headers = headers; + if (headers == null) { + this.headers = new HashMap(); + } + } + + + public String name() { + return name; + } + + public String fileName() { + return fileName; + } + + public String contentType() { + return contentType; + } + + public long contentLength() { + return contentLength; + } + + public File file() { + return file; + } + + public Map headers() { + return headers; + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java index 4d146cf40..b15fedeb5 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java @@ -17,11 +17,15 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; +import java.util.Map; import com.blade.exception.BladeException; import com.blade.exception.NotFoundException; import com.blade.kit.AsmKit; import com.blade.kit.StringKit; +import com.blade.mvc.annotation.CookieParam; +import com.blade.mvc.annotation.HeaderParam; +import com.blade.mvc.annotation.MultipartParam; import com.blade.mvc.annotation.PathParam; import com.blade.mvc.annotation.QueryParam; import com.blade.mvc.http.Request; @@ -44,30 +48,31 @@ public static Object[] getArgs(Request request, Response response, Method action for (int i = 0, len = parameters.length; i < len; i++) { Class argType = parameters[i]; - if (argType.getName().equals(Request.class.getName())) { + if (argType == Request.class) { args[i] = request; continue; } - if (argType.getName().equals(Response.class.getName())) { + if (argType == Response.class) { args[i] = response; continue; } - if (argType.getName().equals(ModelAndView.class.getName())) { + if (argType == ModelAndView.class) { args[i] = new ModelAndView(); continue; } - if(argType.getName().equals(FileItem.class.getName())){ - args[i] = new ModelAndView(); + if (argType == Map.class) { + args[i] = request.querys(); continue; } Annotation annotation = paramterAnnotations[i][0]; - if(null != annotation){ - if(annotation.annotationType().equals(QueryParam.class)){ + + // query param + if(annotation.annotationType() == QueryParam.class){ QueryParam queryParam = (QueryParam) annotation; String paramName = queryParam.value(); String val = request.query(paramName); @@ -83,7 +88,50 @@ public static Object[] getArgs(Request request, Response response, Method action continue; } - if(annotation.annotationType().equals(PathParam.class)){ + // header param + if(annotation.annotationType() == HeaderParam.class){ + HeaderParam headerParam = (HeaderParam) annotation; + String paramName = headerParam.value(); + String val = request.header(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.header(paramName); + } + args[i] = getRequestParam(argType, val); + continue; + } + + // cookie param + if(annotation.annotationType() == CookieParam.class){ + CookieParam cookieParam = (CookieParam) annotation; + String paramName = cookieParam.value(); + String val = request.cookie(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.cookie(paramName); + } + args[i] = getRequestParam(argType, val); + continue; + } + + // form multipart + if(annotation.annotationType() == MultipartParam.class && argType == FileItem.class){ + MultipartParam multipartParam = (MultipartParam) annotation; + String paramName = multipartParam.value(); + FileItem val = request.fileItem(paramName); + + if (StringKit.isBlank(paramName)) { + paramName = paramaterNames[i]; + val = request.fileItem(paramName); + } + args[i] = val; + continue; + } + + // path param + if(annotation.annotationType() == PathParam.class){ PathParam pathParam = (PathParam) annotation; String paramName = pathParam.value(); String val = request.param(paramName); From 70f0f467d9273e464ac85fbb246d5cd5519ec706 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 19 Sep 2016 13:19:54 +0800 Subject: [PATCH 516/545] =?UTF-8?q?=E2=9C=84=20fix=20blade=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/Const.java | 2 +- .../main/java/com/blade/mvc/view/handle/MethodArgument.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index e8a30765f..af2eb07ac 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -24,7 +24,7 @@ public interface Const { // current blade version - String BLADE_VERSION = "1.6.6"; + String BLADE_VERSION = "1.6.7-alpha"; // default embedd server context path String DEFAULT_CONTEXTPATH = "/"; diff --git a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java index b15fedeb5..3fe61cfaa 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java @@ -157,15 +157,15 @@ private static Object getRequestParam(Class parameterType, String val) { Object result = null; if (parameterType.equals(String.class)) { result = val; - } else if (parameterType.equals(Integer.class)) { + } else if (parameterType.equals(Integer.class) && StringKit.isNotBlank(val)) { result = Integer.parseInt(val); - } else if (parameterType.equals(int.class)) { + } else if (parameterType.equals(int.class) && StringKit.isNotBlank(val)) { if(StringKit.isBlank(val)){ result = 0; } else { result = Integer.parseInt(val); } - } else if (parameterType.equals(Long.class)) { + } else if (parameterType.equals(Long.class) && StringKit.isNotBlank(val)) { result = Long.parseLong(val); } else if (parameterType.equals(long.class)) { if(StringKit.isBlank(val)){ From ccde52364e69e2a2ef63c859ebe2f65a5d8efbaf Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 19 Sep 2016 15:11:59 +0800 Subject: [PATCH 517/545] =?UTF-8?q?=E2=9C=84=20rename=20package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/blade/mvc/DispatcherHandler.java | 6 +- .../mvc/http/wrapper/ServletResponse.java | 2 +- .../java/com/blade/mvc/view/ViewSettings.java | 214 +++++++++--------- .../DefaultJSONParser.java | 66 +++--- .../view/{parser => resolve}/JSONParser.java | 56 ++--- .../{handle => resolve}/MethodArgument.java | 2 +- .../RouteViewResolve.java} | 206 ++++++++--------- blade-core/src/test/java/config.txt | 1 - 8 files changed, 276 insertions(+), 277 deletions(-) rename blade-core/src/main/java/com/blade/mvc/view/{parser => resolve}/DefaultJSONParser.java (93%) rename blade-core/src/main/java/com/blade/mvc/view/{parser => resolve}/JSONParser.java (92%) rename blade-core/src/main/java/com/blade/mvc/view/{handle => resolve}/MethodArgument.java (96%) rename blade-core/src/main/java/com/blade/mvc/view/{handle/RouteViewHandler.java => resolve/RouteViewResolve.java} (93%) diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index e78d8b81b..033ff6091 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -44,7 +44,7 @@ import com.blade.mvc.route.Routers; import com.blade.mvc.view.ModelAndView; import com.blade.mvc.view.ViewSettings; -import com.blade.mvc.view.handle.RouteViewHandler; +import com.blade.mvc.view.resolve.RouteViewResolve; import com.blade.mvc.view.template.TemplateException; /** @@ -67,7 +67,7 @@ public class DispatcherHandler { private StaticFileFilter staticFileFilter; - private RouteViewHandler routeViewHandler; + private RouteViewResolve routeViewHandler; public DispatcherHandler(ServletContext servletContext, Routers routers) { this.servletContext = servletContext; @@ -75,7 +75,7 @@ public DispatcherHandler(ServletContext servletContext, Routers routers) { this.ioc = blade.ioc(); this.routeMatcher = new RouteMatcher(routers); this.staticFileFilter = new StaticFileFilter(blade.applicationConfig().getResources()); - this.routeViewHandler = new RouteViewHandler(this.ioc); + this.routeViewHandler = new RouteViewResolve(this.ioc); } public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java index 1ef8fa4f5..3db3233c3 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java @@ -35,7 +35,7 @@ import com.blade.mvc.http.Response; import com.blade.mvc.view.ModelAndView; import com.blade.mvc.view.ViewSettings; -import com.blade.mvc.view.parser.JSONParser; +import com.blade.mvc.view.resolve.JSONParser; import com.blade.mvc.view.template.TemplateEngine; import com.blade.mvc.view.template.TemplateException; diff --git a/blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java b/blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java index 1bad311d1..25f6b7179 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java +++ b/blade-core/src/main/java/com/blade/mvc/view/ViewSettings.java @@ -1,107 +1,107 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.kit.Assert; -import com.blade.mvc.view.parser.DefaultJSONParser; -import com.blade.mvc.view.parser.JSONParser; -import com.blade.mvc.view.template.DefaultEngine; -import com.blade.mvc.view.template.TemplateEngine; - -/** - * ViewSettings - * - * @author biezhi - * @since 1.6.6 - */ -public final class ViewSettings { - - private static final Logger LOGGER = LoggerFactory.getLogger(ViewSettings.class); - - private JSONParser jsonParser = new DefaultJSONParser(); - private TemplateEngine templateEngine = new DefaultEngine(); - private String view404 = "404.html"; - private String view500 = "500.html"; - - private ViewSettings() { - } - - static final class ViewSettingsHolder { - private static final ViewSettings $ = new ViewSettings(); - } - - public static ViewSettings $() { - return ViewSettingsHolder.$; - } - - public ViewSettings JSONParser(JSONParser jsonParser) { - Assert.notNull(jsonParser); - LOGGER.debug("Switch JSONParser With [{}]", jsonParser); - this.jsonParser = jsonParser; - return this; - } - - public JSONParser JSONParser() { - return this.jsonParser; - } - - public String toJSONString(Object object) { - return jsonParser.toJSONSting(object); - } - - /** - * Setting Render Engin, Default is static file render - * - * @param templateEngine - * Render engine object - * @return return blade - */ - public ViewSettings templateEngine(TemplateEngine templateEngine) { - Assert.notNull(templateEngine); - LOGGER.debug("Switch TemplateEngine With [{}]", templateEngine); - this.templateEngine = templateEngine; - return this; - } - - /** - * @return Return Current TemplateEngine - */ - public TemplateEngine templateEngine() { - return this.templateEngine; - } - - public String getView404() { - return view404; - } - - public ViewSettings setView404(String view404) { - this.view404 = view404; - return this; - } - - public String getView500() { - return view500; - } - - public ViewSettings setView500(String view500) { - this.view500 = view500; - return this; - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.kit.Assert; +import com.blade.mvc.view.resolve.DefaultJSONParser; +import com.blade.mvc.view.resolve.JSONParser; +import com.blade.mvc.view.template.DefaultEngine; +import com.blade.mvc.view.template.TemplateEngine; + +/** + * ViewSettings + * + * @author biezhi + * @since 1.6.6 + */ +public final class ViewSettings { + + private static final Logger LOGGER = LoggerFactory.getLogger(ViewSettings.class); + + private JSONParser jsonParser = new DefaultJSONParser(); + private TemplateEngine templateEngine = new DefaultEngine(); + private String view404 = "404.html"; + private String view500 = "500.html"; + + private ViewSettings() { + } + + static final class ViewSettingsHolder { + private static final ViewSettings $ = new ViewSettings(); + } + + public static ViewSettings $() { + return ViewSettingsHolder.$; + } + + public ViewSettings JSONParser(JSONParser jsonParser) { + Assert.notNull(jsonParser); + LOGGER.debug("Switch JSONParser With [{}]", jsonParser); + this.jsonParser = jsonParser; + return this; + } + + public JSONParser JSONParser() { + return this.jsonParser; + } + + public String toJSONString(Object object) { + return jsonParser.toJSONSting(object); + } + + /** + * Setting Render Engin, Default is static file render + * + * @param templateEngine + * Render engine object + * @return return blade + */ + public ViewSettings templateEngine(TemplateEngine templateEngine) { + Assert.notNull(templateEngine); + LOGGER.debug("Switch TemplateEngine With [{}]", templateEngine); + this.templateEngine = templateEngine; + return this; + } + + /** + * @return Return Current TemplateEngine + */ + public TemplateEngine templateEngine() { + return this.templateEngine; + } + + public String getView404() { + return view404; + } + + public ViewSettings setView404(String view404) { + this.view404 = view404; + return this; + } + + public String getView500() { + return view500; + } + + public ViewSettings setView500(String view500) { + this.view500 = view500; + return this; + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/view/parser/DefaultJSONParser.java b/blade-core/src/main/java/com/blade/mvc/view/resolve/DefaultJSONParser.java similarity index 93% rename from blade-core/src/main/java/com/blade/mvc/view/parser/DefaultJSONParser.java rename to blade-core/src/main/java/com/blade/mvc/view/resolve/DefaultJSONParser.java index 27fab881f..06c7f63ab 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/parser/DefaultJSONParser.java +++ b/blade-core/src/main/java/com/blade/mvc/view/resolve/DefaultJSONParser.java @@ -1,33 +1,33 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.parser; - -import com.blade.kit.json.JSONKit; - -/** - * Default json parser implment - * - * @author biezhi - * @since 1.6.6 - */ -public class DefaultJSONParser implements JSONParser { - - @Override - public String toJSONSting(Object object) { - return JSONKit.toJSONString(object); - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.resolve; + +import com.blade.kit.json.JSONKit; + +/** + * Default json parser implment + * + * @author biezhi + * @since 1.6.6 + */ +public class DefaultJSONParser implements JSONParser { + + @Override + public String toJSONSting(Object object) { + return JSONKit.toJSONString(object); + } + +} diff --git a/blade-core/src/main/java/com/blade/mvc/view/parser/JSONParser.java b/blade-core/src/main/java/com/blade/mvc/view/resolve/JSONParser.java similarity index 92% rename from blade-core/src/main/java/com/blade/mvc/view/parser/JSONParser.java rename to blade-core/src/main/java/com/blade/mvc/view/resolve/JSONParser.java index 0151685ce..ca05b55e6 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/parser/JSONParser.java +++ b/blade-core/src/main/java/com/blade/mvc/view/resolve/JSONParser.java @@ -1,28 +1,28 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.parser; - -/** - * Route render json parser - * - * @author biezhi - * @since 1.6.6 - */ -public interface JSONParser { - - String toJSONSting(Object object); - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.resolve; + +/** + * Route render json parser + * + * @author biezhi + * @since 1.6.6 + */ +public interface JSONParser { + + String toJSONSting(Object object); + +} diff --git a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java b/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java similarity index 96% rename from blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java rename to blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java index 3fe61cfaa..01e73af1e 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/handle/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.mvc.view.handle; +package com.blade.mvc.view.resolve; import java.lang.annotation.Annotation; import java.lang.reflect.Method; diff --git a/blade-core/src/main/java/com/blade/mvc/view/handle/RouteViewHandler.java b/blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java similarity index 93% rename from blade-core/src/main/java/com/blade/mvc/view/handle/RouteViewHandler.java rename to blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java index 7eef5e5c3..d2998dce3 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/handle/RouteViewHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java @@ -1,103 +1,103 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.handle; - -import java.lang.reflect.Method; - -import com.blade.ioc.Ioc; -import com.blade.kit.reflect.ReflectKit; -import com.blade.mvc.annotation.JSON; -import com.blade.mvc.annotation.RestController; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.route.Route; -import com.blade.mvc.view.ModelAndView; -import com.blade.mvc.view.ViewSettings; - -public class RouteViewHandler { - - private Ioc ioc; - private ViewSettings viewSettings; - public RouteViewHandler(Ioc ioc) { - this.ioc = ioc; - this.viewSettings = ViewSettings.$(); - } - - public void handle(Request request, Response response, Route route) throws Exception { - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - - int len = actionMethod.getParameterTypes().length; - Object returnParam = null; - if (len > 0) { - Object[] args = MethodArgument.getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if (null != returnParam) { - Class returnType = returnParam.getClass(); - RestController restController = target.getClass().getAnnotation(RestController.class); - JSON json = actionMethod.getAnnotation(JSON.class); - if(null != restController || null != json){ - response.json(viewSettings.toJSONString(returnParam)); - } else{ - if (returnType == String.class) { - response.render(returnParam.toString()); - } else if (returnType == ModelAndView.class) { - ModelAndView modelAndView = (ModelAndView) returnParam; - response.render(modelAndView); - } - } - } - } - - public boolean intercept(Request request, Response response, Route route) throws Exception { - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - - if (null == target) { - Class clazz = route.getAction().getDeclaringClass(); - target = ioc.getBean(clazz); - route.setTarget(target); - } - - // execute - int len = actionMethod.getParameterTypes().length; - actionMethod.setAccessible(true); - try { - Object returnParam = null; - if (len > 0) { - Object[] args = MethodArgument.getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if (null != returnParam) { - Class returnType = returnParam.getClass(); - if (returnType == Boolean.class || returnType == boolean.class) { - return (Boolean) returnParam; - } - } - return true; - } catch (Exception e) { - throw e; - } - } - -} +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.resolve; + +import java.lang.reflect.Method; + +import com.blade.ioc.Ioc; +import com.blade.kit.reflect.ReflectKit; +import com.blade.mvc.annotation.JSON; +import com.blade.mvc.annotation.RestController; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.route.Route; +import com.blade.mvc.view.ModelAndView; +import com.blade.mvc.view.ViewSettings; + +public class RouteViewResolve { + + private Ioc ioc; + private ViewSettings viewSettings; + public RouteViewResolve(Ioc ioc) { + this.ioc = ioc; + this.viewSettings = ViewSettings.$(); + } + + public void handle(Request request, Response response, Route route) throws Exception { + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + int len = actionMethod.getParameterTypes().length; + Object returnParam = null; + if (len > 0) { + Object[] args = MethodArgument.getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if (null != returnParam) { + Class returnType = returnParam.getClass(); + RestController restController = target.getClass().getAnnotation(RestController.class); + JSON json = actionMethod.getAnnotation(JSON.class); + if(null != restController || null != json){ + response.json(viewSettings.toJSONString(returnParam)); + } else{ + if (returnType == String.class) { + response.render(returnParam.toString()); + } else if (returnType == ModelAndView.class) { + ModelAndView modelAndView = (ModelAndView) returnParam; + response.render(modelAndView); + } + } + } + } + + public boolean intercept(Request request, Response response, Route route) throws Exception { + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + if (null == target) { + Class clazz = route.getAction().getDeclaringClass(); + target = ioc.getBean(clazz); + route.setTarget(target); + } + + // execute + int len = actionMethod.getParameterTypes().length; + actionMethod.setAccessible(true); + try { + Object returnParam = null; + if (len > 0) { + Object[] args = MethodArgument.getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if (null != returnParam) { + Class returnType = returnParam.getClass(); + if (returnType == Boolean.class || returnType == boolean.class) { + return (Boolean) returnParam; + } + } + return true; + } catch (Exception e) { + throw e; + } + } + +} diff --git a/blade-core/src/test/java/config.txt b/blade-core/src/test/java/config.txt index 93b2ecf60..04ea2732e 100644 --- a/blade-core/src/test/java/config.txt +++ b/blade-core/src/test/java/config.txt @@ -28,7 +28,6 @@ mvc.statics http.encoding http.cached -http.xss server.port server.timeout \ No newline at end of file From 12431bd626ecde861235b0b0b974d2930b92b76f Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 19 Sep 2016 15:29:13 +0800 Subject: [PATCH 518/545] =?UTF-8?q?=E2=9C=84=20update=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LAST_VERSION.md | 2 +- README.md | 14 ++++---------- README_CN.md | 14 ++++---------- pom.xml | 2 +- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 5d4596e66..32dd91410 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -34,7 +34,7 @@     com.bladejava     blade-core -    1.6.6 +    1.6.7-alpha ``` diff --git a/README.md b/README.md index f1ecb2f62..8730009b8 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.6 + 1.6.7-alpha com.bladejava @@ -48,7 +48,7 @@ Grab via `Maven`: ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.6' +compile 'com.bladejava:blade-core:1.6.7-alpha' compile 'com.bladejava:blade-embed-jetty:0.0.5' ``` @@ -109,16 +109,10 @@ public static void main(String[] args) { ## Upload File ```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; +public void upload_img(@MultipartParam FileItem fileItem){ + if(null != fileItem){ File file = fileItem.getFile(); - String fileRealPath = "your upload file path!"; - nioTransferCopy(file, fileRealPath); } } diff --git a/README_CN.md b/README_CN.md index d37557a89..5c6cf4aa7 100644 --- a/README_CN.md +++ b/README_CN.md @@ -39,7 +39,7 @@ Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁 com.bladejava blade-core - 1.6.6 + 1.6.7-alpha com.bladejava @@ -51,7 +51,7 @@ Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁 或者 `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.6' +compile 'com.bladejava:blade-core:1.6.7-alpha' compile 'com.bladejava:blade-embed-jetty:0.0.5' ``` @@ -112,16 +112,10 @@ public static void main(String[] args) { ## 上传文件 ```java -public void upload_img(Request request, Response response){ - - FileItem[] fileItems = request.files(); - if(null != fileItems && fileItems.length > 0){ - - FileItem fileItem = fileItems[0]; +public void upload_img(@MultipartParam FileItem fileItem){ + if(null != fileItem){ File file = fileItem.getFile(); - String fileRealPath = "your upload file path!"; - nioTransferCopy(file, fileRealPath); } } diff --git a/pom.xml b/pom.xml index ec56899a4..82842dcc5 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ 1.6.7-alpha 1.3.3 1.0.0 - 0.0.4 + 0.0.5 9.2.12.v20150709 From 35650dabd4c6dfcca33b065353361365abe29d46 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 19 Sep 2016 15:30:23 +0800 Subject: [PATCH 519/545] =?UTF-8?q?=E2=9C=84=20update=20.travis.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3015bb3e7..3199172d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,6 @@ jdk: - oraclejdk8 - oraclejdk7 - openjdk6 -after_success: - - mvn cobertura:cobertura coveralls:report +script: + - mvn install -Dmaven.test.skip=true From b548877249a0335685b01a7b5467ed957308bfde Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 19 Sep 2016 17:56:44 +0800 Subject: [PATCH 520/545] =?UTF-8?q?=E2=9C=84=20update=20last=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LAST_VERSION.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 32dd91410..010949d8c 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -47,21 +47,21 @@ ``` -## [blade-jdbc](http://search.maven.org/#search%7Cga%7C1%7Cblade-jdbc) +## [blade-websocket-jetty](http://search.maven.org/#search%7Cga%7C1%7Cblade-websocket-jetty) ```xml     com.bladejava -    blade-jdbc -    0.1.3-alpha +    blade-websocket-jetty +    0.0.1 ``` -## [blade-websocket-jetty](http://search.maven.org/#search%7Cga%7C1%7Cblade-websocket-jetty) +## [blade-jdbc](http://search.maven.org/#search%7Cga%7C1%7Cblade-jdbc) ```xml     com.bladejava -    blade-websocket-jetty -    0.0.1 +    blade-jdbc +    0.1.3-beta ``` From 5c6f383a7a6ff0851d2e478a5904ec35402d3df7 Mon Sep 17 00:00:00 2001 From: biezhi Date: Tue, 20 Sep 2016 19:06:39 +0800 Subject: [PATCH 521/545] =?UTF-8?q?=E2=9C=84=20add=20custom=20filter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/Blade.java | 27 +--- blade-core/src/main/java/com/blade/Const.java | 2 + .../com/blade/config/ApplicationConfig.java | 12 ++ .../java/com/blade/config/ConfigLoader.java | 89 ------------ .../com/blade/context/DynamicContext.java | 4 +- .../java/com/blade/ioc/IocApplication.java | 8 +- .../blade/listener/WebContextListener.java | 34 +++++ .../java/com/blade/mvc/DispatcherServlet.java | 6 +- .../com/blade/embedd/EmbedJettyServer.java | 135 ------------------ .../test/java/com/blade/test/BladeTest.java | 65 --------- .../com/blade/embedd/EmbedJettyServer.java | 57 +++++++- blade-starter/pom.xml | 8 +- pom.xml | 4 +- 13 files changed, 113 insertions(+), 338 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/config/ConfigLoader.java create mode 100644 blade-core/src/main/java/com/blade/listener/WebContextListener.java delete mode 100644 blade-core/src/test/java/com/blade/embedd/EmbedJettyServer.java delete mode 100644 blade-core/src/test/java/com/blade/test/BladeTest.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 01bb65f67..17a15fd63 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -22,8 +22,6 @@ import java.util.Set; import com.blade.config.ApplicationConfig; -import com.blade.config.BaseConfig; -import com.blade.config.ConfigLoader; import com.blade.embedd.EmbedServer; import com.blade.exception.EmbedServerException; import com.blade.ioc.Ioc; @@ -83,9 +81,6 @@ public final class Blade { // global config private Config config; - - // config loader - private ConfigLoader configLoader; // embed server private EmbedServer embedServer; @@ -95,7 +90,6 @@ private Blade() { this.applicationConfig = new ApplicationConfig(); this.plugins = new HashSet>(); this.routeBuilder = new RouteBuilder(this.routers); - this.configLoader = new ConfigLoader(this.ioc, this.applicationConfig); } static final class BladeHolder { @@ -166,13 +160,6 @@ public RouteBuilder routeBuilder() { return routeBuilder; } - /** - * @return return ConfigLoader - */ - public ConfigLoader configLoader() { - return configLoader; - } - /** * @return return blade ioc container */ @@ -190,7 +177,6 @@ public Ioc ioc() { public Blade container(Ioc ioc) { Assert.notNull(ioc); this.ioc = ioc; - this.configLoader.setIoc(ioc); return this; } @@ -495,18 +481,7 @@ public Blade addInterceptor(Class interceptor) { routeBuilder.addInterceptor(interceptor); return this; } - - /** - * add config - * - * @param config config class - * @return return blade obj - */ - public Blade addConfig(Class config) { - configLoader.addConfig(config); - return this; - } - + /** * Setting blade web root path * diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index af2eb07ac..bbfc8bb80 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -50,6 +50,8 @@ public interface Const { String RESOURCE_PKGS = "resouce_packages"; String BASE_PKG = "base_package"; String INTERCEPTOR_PKG = "interceptor_package"; + String FILTER_PKG = "filter_package"; + String LISTENER_PKG = "listener_package"; /**************** * blade properties diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java index 53af2f24b..7711eb5de 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/ApplicationConfig.java @@ -23,6 +23,7 @@ import org.slf4j.LoggerFactory; import com.blade.Const; +import com.blade.context.DynamicContext; import com.blade.kit.Assert; import com.blade.kit.StringKit; import com.blade.kit.base.Config; @@ -127,6 +128,14 @@ public String getInterceptorPkg(){ return packages.first(Const.INTERCEPTOR_PKG); } + public String getFilterPkg(){ + return packages.first(Const.FILTER_PKG); + } + + public String getListenerPkg(){ + return packages.first(Const.LISTENER_PKG); + } + public boolean isDev() { return isDev; } @@ -149,6 +158,7 @@ public Class getApplicationClass() { public void setApplicationClass(Class applicationClass) { this.applicationClass = applicationClass; + DynamicContext.init(applicationClass); } public void setInterceptorPackage(String interceptorPkg) { @@ -160,6 +170,8 @@ public void setBasePackage(String basePackage) { packages.put(Const.BASE_PKG, basePackage); packages.put(Const.INTERCEPTOR_PKG, basePackage + ".interceptor"); + packages.put(Const.FILTER_PKG, basePackage + ".filter"); + packages.put(Const.LISTENER_PKG, basePackage + ".listener"); packages.add(Const.CONFIG_PKGS, basePackage + ".config"); packages.add(Const.IOC_PKGS, basePackage + ".service.*"); diff --git a/blade-core/src/main/java/com/blade/config/ConfigLoader.java b/blade-core/src/main/java/com/blade/config/ConfigLoader.java deleted file mode 100644 index b1463fdda..000000000 --- a/blade-core/src/main/java/com/blade/config/ConfigLoader.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import java.lang.reflect.Modifier; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static com.blade.Blade.$; -import com.blade.context.DynamicContext; -import com.blade.exception.ConfigException; -import com.blade.ioc.Ioc; -import com.blade.ioc.annotation.Component; -import com.blade.kit.CollectionKit; -import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; - -/** - * ConfigLoader - * - * @author biezhi - * @since 1.6.6 - */ -public class ConfigLoader { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigLoader.class); - - private ClassReader classReader; - private Ioc ioc; - private ApplicationConfig applicationConfig; - - public ConfigLoader(Ioc ioc, ApplicationConfig applicationConfig) { - this.ioc = ioc; - this.classReader = DynamicContext.getClassReader(); - this.applicationConfig = applicationConfig; - } - - public void setIoc(Ioc ioc){ - this.ioc = ioc; - } - - @SuppressWarnings("unchecked") - public void loadConfig() { - String[] configPackages = $().applicationConfig().getConfigPkgs(); - if (null != configPackages && configPackages.length > 0) { - // Scan package all class - try { - for (String packageName : configPackages) { - Set classes = classReader.getClassByAnnotation(packageName, Component.class, false); - if (CollectionKit.isNotEmpty(classes)) { - for (ClassInfo classInfo : classes) { - boolean hasInterface = ReflectKit.hasInterface(classInfo.getClazz(), BaseConfig.class); - if(hasInterface){ - addConfig((Class) classInfo.getClazz()); - } - } - } - } - } catch (ConfigException e) { - LOGGER.error("load config error", e); - } - } - } - - public void addConfig(Class clazz) throws ConfigException { - if (!Modifier.isAbstract(clazz.getModifiers())) { - Object bean = ioc.addBean(clazz); - BaseConfig baseConfig = (BaseConfig) bean; - baseConfig.config(applicationConfig); - } - } - -} diff --git a/blade-core/src/main/java/com/blade/context/DynamicContext.java b/blade-core/src/main/java/com/blade/context/DynamicContext.java index c9d127921..7f5b181db 100644 --- a/blade-core/src/main/java/com/blade/context/DynamicContext.java +++ b/blade-core/src/main/java/com/blade/context/DynamicContext.java @@ -18,7 +18,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.blade.Blade; import com.blade.kit.resource.ClassPathClassReader; import com.blade.kit.resource.ClassReader; import com.blade.kit.resource.JarReaderImpl; @@ -40,8 +39,7 @@ public final class DynamicContext { private DynamicContext() { } - public static void init(){ - Class clazz = Blade.$().applicationConfig().getApplicationClass(); + public static void init(Class clazz){ String rs = clazz.getResource("").toString(); if(rs.indexOf(".jar") != -1){ CLASS_READER = new JarReaderImpl(); diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index ae7081b80..c74a045d9 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -46,15 +46,15 @@ * @author biezhi * @since 1.0 */ -public class IocApplication { - +public final class IocApplication { + private static final Logger LOGGER = LoggerFactory.getLogger(IocApplication.class); /** * aop interceptor */ private static List aopInterceptors = new ArrayList(8); - + /** * Class to read object, load class */ @@ -67,7 +67,7 @@ public IocApplication() { this.classReader = DynamicContext.getClassReader(); this.orderComparator = new OrderComparator(); } - + /** * load config beans * diff --git a/blade-core/src/main/java/com/blade/listener/WebContextListener.java b/blade-core/src/main/java/com/blade/listener/WebContextListener.java new file mode 100644 index 000000000..cc3609ec5 --- /dev/null +++ b/blade-core/src/main/java/com/blade/listener/WebContextListener.java @@ -0,0 +1,34 @@ +package com.blade.listener; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import com.blade.Blade; +import com.blade.context.WebContextHolder; + +public class WebContextListener implements ServletContextListener, HttpSessionListener { + + private int timeout = Blade.$().config().getInt("server.timeout", 15 * 60); + + @Override + public void sessionCreated(HttpSessionEvent event) { + event.getSession().setMaxInactiveInterval(timeout); + } + + @Override + public void contextInitialized(ServletContextEvent sce) { + WebContextHolder.init(sce.getServletContext()); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + + @Override + public void sessionDestroyed(HttpSessionEvent event) { + } + + +} diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java index a28368762..7ebdaeb35 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java @@ -31,8 +31,6 @@ import com.blade.Bootstrap; import com.blade.banner.BannerStarter; import com.blade.context.ApplicationContext; -import com.blade.context.WebContextHolder; -import com.blade.context.DynamicContext; import com.blade.embedd.EmbedServer; import com.blade.kit.DispatchKit; import com.blade.kit.StringKit; @@ -89,9 +87,7 @@ public void init(ServletConfig config) throws ServletException { LOGGER.info("blade.webroot\t=> {}", webRoot); - DynamicContext.init(); - - WebContextHolder.init(servletContext); +// WebContextHolder.init(servletContext); this.bootstrap = blade.bootstrap(); diff --git a/blade-core/src/test/java/com/blade/embedd/EmbedJettyServer.java b/blade-core/src/test/java/com/blade/embedd/EmbedJettyServer.java deleted file mode 100644 index b5a8f34e8..000000000 --- a/blade-core/src/test/java/com/blade/embedd/EmbedJettyServer.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.blade.embedd; - -import static com.blade.Blade.$; - -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.handler.DefaultHandler; -import org.eclipse.jetty.server.handler.HandlerList; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.eclipse.jetty.webapp.WebAppContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Const; -import com.blade.exception.EmbedServerException; -import com.blade.kit.base.Config; -import com.blade.mvc.DispatcherServlet; - -public class EmbedJettyServer implements EmbedServer { - - private static final Logger LOGGER = LoggerFactory.getLogger(EmbedJettyServer.class); - - private int port = Const.DEFAULT_PORT; - - private Server server; - - private WebAppContext webAppContext; - - private Config config = null; - - public EmbedJettyServer() { - System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); - $().loadAppConf("jetty.properties"); - config = $().config(); - $().enableServer(true); - } - - @Override - public void startup(int port) throws EmbedServerException { - this.startup(port, Const.DEFAULT_CONTEXTPATH, null); - } - - @Override - public void startup(int port, String contextPath) throws EmbedServerException { - this.startup(port, contextPath, null); - } - - @Override - public void setWebRoot(String webRoot) { - webAppContext.setResourceBase(webRoot); - } - - @Override - public void startup(int port, String contextPath, String webRoot) throws EmbedServerException { - this.port = port; - - // Setup Threadpool - QueuedThreadPool threadPool = new QueuedThreadPool(); - - int minThreads = config.getInt("server.jetty.min-threads", 100); - int maxThreads = config.getInt("server.jetty.max-threads", 500); - - threadPool.setMinThreads(minThreads); - threadPool.setMaxThreads(maxThreads); - - server = new org.eclipse.jetty.server.Server(threadPool); - - // 设置在JVM退出时关闭Jetty的钩子。 - server.setStopAtShutdown(true); - - webAppContext = new WebAppContext(); - webAppContext.setContextPath(contextPath); - webAppContext.setResourceBase(""); - - int securePort = config.getInt("server.jetty.http.secure-port", 8443); - int outputBufferSize = config.getInt("server.jetty.http.output-buffersize", 32768); - int requestHeaderSize = config.getInt("server.jetty.http.request-headersize", 8192); - int responseHeaderSize = config.getInt("server.jetty.http.response-headersize", 8192); - - // HTTP Configuration - HttpConfiguration http_config = new HttpConfiguration(); - http_config.setSecurePort(securePort); - http_config.setOutputBufferSize(outputBufferSize); - http_config.setRequestHeaderSize(requestHeaderSize); - http_config.setResponseHeaderSize(responseHeaderSize); - http_config.setSendServerVersion(true); - http_config.setSendDateHeader(false); - - long idleTimeout = config.getLong("server.jetty.http.idle-timeout", 30000L); - - ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(http_config)); - http.setPort(this.port); - http.setIdleTimeout(idleTimeout); - server.addConnector(http); - - ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); - servletHolder.setAsyncSupported(false); - servletHolder.setInitOrder(1); - - webAppContext.addServlet(servletHolder, "/"); - - HandlerList handlers = new HandlerList(); - handlers.setHandlers(new Handler[] { webAppContext, new DefaultHandler() }); - server.setHandler(handlers); - - try { - server.start(); - LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); - } catch (Exception e) { - throw new EmbedServerException(e); - } - } - - public void shutdown() throws EmbedServerException { - try { - server.stop(); - } catch (Exception e) { - throw new EmbedServerException(e); - } - } - - @Override - public void join() throws EmbedServerException { - try { - server.join(); - } catch (InterruptedException e) { - throw new EmbedServerException(e); - } - } - -} \ No newline at end of file diff --git a/blade-core/src/test/java/com/blade/test/BladeTest.java b/blade-core/src/test/java/com/blade/test/BladeTest.java deleted file mode 100644 index 0746c3ef2..000000000 --- a/blade-core/src/test/java/com/blade/test/BladeTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.blade.test; - -import org.junit.Assert; -import org.junit.Test; - -import com.blade.Blade; -import com.blade.kit.http.HttpRequest; -import com.blade.mvc.http.Request; -import com.blade.mvc.http.Response; -import com.blade.mvc.route.RouteHandler; - -public class BladeTest { - - @Test - public void testCode200() throws Exception { - Blade blade = Blade.$(); - blade.get("/", new RouteHandler() { - @Override - public void handle(Request request, Response response) { - - } - }).startNoJoin(BladeTest.class); - try { - Thread.sleep(100); - int resCode = HttpRequest.get("http://127.0.0.1:9000").code(); - Assert.assertEquals(resCode, 200); - } finally { - blade.embedServer().shutdown(); - } - } - - @Test - public void testCode404() throws Exception { - Blade blade = Blade.$(); - blade.startNoJoin(BladeTest.class); - try { - Thread.sleep(100); - int resCode = HttpRequest.get("http://127.0.0.1:9000/hello").code(); - Assert.assertEquals(resCode, 404); - } finally { - blade.embedServer().shutdown(); - } - } - - @Test - public void testCode500() throws Exception { - Blade blade = Blade.$(); - try { - blade.get("/:id", new RouteHandler() { - @Override - public void handle(Request request, Response response) { - int id = request.paramAsInt("id"); - System.out.println(id); - } - }).startNoJoin(BladeTest.class); - Thread.sleep(100); - int resCode = HttpRequest.get("http://127.0.0.1:9000/abc").code(); - Assert.assertEquals(resCode, 500); - } catch (Exception e) { - } finally { - blade.embedServer().shutdown(); - } - } - -} diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index d0cca9b82..a258b66a7 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -2,6 +2,15 @@ import static com.blade.Blade.$; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import javax.servlet.DispatcherType; +import javax.servlet.Filter; +import javax.servlet.annotation.WebFilter; + import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; @@ -15,9 +24,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.blade.Blade; import com.blade.Const; +import com.blade.context.DynamicContext; import com.blade.exception.EmbedServerException; +import com.blade.kit.StringKit; import com.blade.kit.base.Config; +import com.blade.kit.resource.ClassInfo; +import com.blade.kit.resource.ClassReader; +import com.blade.listener.WebContextListener; import com.blade.mvc.DispatcherServlet; public class EmbedJettyServer implements EmbedServer { @@ -31,11 +46,14 @@ public class EmbedJettyServer implements EmbedServer { private WebAppContext webAppContext; private Config config = null; + + private ClassReader classReader = null; public EmbedJettyServer() { System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); $().loadAppConf("jetty.properties"); config = $().config(); + classReader = DynamicContext.getClassReader(); $().enableServer(true); } @@ -100,14 +118,17 @@ public void startup(int port, String contextPath, String webRoot) throws EmbedSe ServletHolder servletHolder = new ServletHolder(DispatcherServlet.class); servletHolder.setAsyncSupported(false); servletHolder.setInitOrder(1); - + + webAppContext.addEventListener(new WebContextListener()); webAppContext.addServlet(servletHolder, "/"); - HandlerList handlers = new HandlerList(); - handlers.setHandlers(new Handler[] { webAppContext, new DefaultHandler() }); - server.setHandler(handlers); - try { + + loadFilters(webAppContext); + + HandlerList handlers = new HandlerList(); + handlers.setHandlers(new Handler[] { webAppContext, new DefaultHandler() }); + server.setHandler(handlers); server.start(); LOGGER.info("Blade Server Listen on 0.0.0.0:{}", this.port); } catch (Exception e) { @@ -115,6 +136,32 @@ public void startup(int port, String contextPath, String webRoot) throws EmbedSe } } + public List loadFilters(WebAppContext webAppContext) throws Exception{ + String filterPkg = Blade.$().applicationConfig().getFilterPkg(); + if (StringKit.isNotBlank(filterPkg)) { + List filters = new ArrayList(10); + Set intes = classReader.getClass(filterPkg, false); + if (null != intes) { + for (ClassInfo classInfo : intes) { + if (null != classInfo.getClazz().getInterfaces() + && classInfo.getClazz().getInterfaces()[0].equals(Filter.class)) { + + WebFilter webFilter = classInfo.getClazz().getAnnotation(WebFilter.class); + if(null != webFilter){ + String[] pathSpecs = webFilter.value(); + Class filterClazz = (Class) classInfo.getClazz(); + for(String pathSpec : pathSpecs){ + webAppContext.addFilter(filterClazz, pathSpec, EnumSet.of(DispatcherType.REQUEST)); + } + } + } + } + } + return filters; + } + return null; + } + public void shutdown() throws EmbedServerException { try { server.stop(); diff --git a/blade-starter/pom.xml b/blade-starter/pom.xml index 777faa065..28e700af4 100644 --- a/blade-starter/pom.xml +++ b/blade-starter/pom.xml @@ -12,18 +12,18 @@ blade-starter pom - 0.0.1 + 0.0.2 UTF-8 - 1.6.6 + 1.6.7-alpha 1.0.0 - 0.1.3-alpha + 0.1.3-beta 1.0.4 0.0.6 0.0.4 - 0.0.5 + 0.0.6 diff --git a/pom.xml b/pom.xml index 82842dcc5..d447a974c 100644 --- a/pom.xml +++ b/pom.xml @@ -22,10 +22,10 @@ 1.7.21 1.7.21 - 1.6.7-alpha + 1.6.7-beta 1.3.3 1.0.0 - 0.0.5 + 0.0.6 9.2.12.v20150709 From 3d88518acdbe328014461c39d53f0757dd2f84da Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Sep 2016 10:50:46 +0800 Subject: [PATCH 522/545] =?UTF-8?q?=E2=9C=84=20optimization=20of=20structu?= =?UTF-8?q?re?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/Blade.java | 47 +------ .../src/main/java/com/blade/Bootstrap.java | 39 ------ .../com/blade/context/ApplicationContext.java | 59 --------- .../com/blade/context/WebContextListener.java | 116 ++++++++++++++++++ .../blade/listener/WebContextListener.java | 34 ----- .../java/com/blade/mvc/DispatcherServlet.java | 103 +--------------- .../com/blade/embedd/EmbedJettyServer.java | 2 +- 7 files changed, 122 insertions(+), 278 deletions(-) delete mode 100644 blade-core/src/main/java/com/blade/Bootstrap.java delete mode 100644 blade-core/src/main/java/com/blade/context/ApplicationContext.java create mode 100644 blade-core/src/main/java/com/blade/context/WebContextListener.java delete mode 100644 blade-core/src/main/java/com/blade/listener/WebContextListener.java diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 17a15fd63..eeaa5ab41 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -29,7 +29,6 @@ import com.blade.kit.Assert; import com.blade.kit.StringKit; import com.blade.kit.base.Config; -import com.blade.kit.reflect.ReflectKit; import com.blade.mvc.http.HttpMethod; import com.blade.mvc.interceptor.Interceptor; import com.blade.mvc.route.Route; @@ -51,10 +50,7 @@ public final class Blade { // blade initialize private boolean isInit = false; - - // blade bootstrap config class - private Bootstrap bootstrap = null; - + // global configuration Object private ApplicationConfig applicationConfig = null; @@ -438,39 +434,7 @@ public Blade addResources(final String... resources) { applicationConfig.addResources(resources); return this; } - - /** - * Dynamically set the global initialization class, the embedded Jetty boot - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Bootstrap bootstrap) { - Assert.notNull(bootstrap); - this.bootstrap = bootstrap; - return this; - } - - /** - * Dynamically set global initialization class - * - * @param bootstrap - * global initialization config class - * @return return blade - */ - public Blade app(Class bootstrap) { - Assert.notNull(bootstrap); - try { - Bootstrap object = (Bootstrap) ReflectKit.newInstance(bootstrap); - ioc.addBean(Bootstrap.class.getName(), object); - this.bootstrap = object; - } catch (Exception e) { - e.printStackTrace(); - } - return this; - } - + /** * add interceptor * @@ -604,13 +568,6 @@ public boolean isDev() { return applicationConfig.isDev(); } - /** - * @return Return bootstrap object - */ - public Bootstrap bootstrap() { - return this.bootstrap; - } - /** * return register plugin object * diff --git a/blade-core/src/main/java/com/blade/Bootstrap.java b/blade-core/src/main/java/com/blade/Bootstrap.java deleted file mode 100644 index af17162db..000000000 --- a/blade-core/src/main/java/com/blade/Bootstrap.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade; - -/** - * Blade global initialization class, you can do some operations at the start of the application - * - * @author biezhi - * @since 1.6.6 - */ -public abstract class Bootstrap { - - /** - * Initialization method, do some initialization operation when the application starts - * @param blade blade global object - */ - public abstract void init(Blade blade); - - /** - * After initialization configuration - * @param blade blade global object - */ - public void contextInitialized(){ - // - } -} diff --git a/blade-core/src/main/java/com/blade/context/ApplicationContext.java b/blade-core/src/main/java/com/blade/context/ApplicationContext.java deleted file mode 100644 index 3090e8a6a..000000000 --- a/blade-core/src/main/java/com/blade/context/ApplicationContext.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Blade; -import com.blade.Const; -import com.blade.exception.BladeException; -import com.blade.ioc.IocApplication; - -/** - * Blade ApplicationContext, init context - * - * @author biezhi - * @since 1.6.6 - */ -public final class ApplicationContext { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationContext.class); - - public static void init(Blade blade) throws BladeException{ - try { - if(!blade.isInit()){ - blade.bootstrap().init(blade); - - if(!blade.applicationConfig().isInit()){ - blade.loadAppConf(Const.APP_PROPERTIES); - blade.applicationConfig().setEnv(blade.config()); - } - - // initialization ioc - IocApplication iocApplication = new IocApplication(); - iocApplication.initBeans(); - - blade.init(); - blade.bootstrap().contextInitialized(); - } - } catch (Exception e) { - LOGGER.error("ApplicationContext init error", e); - } - - } - -} diff --git a/blade-core/src/main/java/com/blade/context/WebContextListener.java b/blade-core/src/main/java/com/blade/context/WebContextListener.java new file mode 100644 index 000000000..41559cc80 --- /dev/null +++ b/blade-core/src/main/java/com/blade/context/WebContextListener.java @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.context; + +import static com.blade.Blade.$; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Blade; +import com.blade.Const; +import com.blade.banner.BannerStarter; +import com.blade.embedd.EmbedServer; +import com.blade.ioc.IocApplication; +import com.blade.kit.DispatchKit; +import com.blade.kit.SystemKit; + +/** + * Blade Web Context Listener + * + * @author biezhi + * @since 1.6.7 + */ +public class WebContextListener implements ServletContextListener, HttpSessionListener { + + private static final Logger LOGGER = LoggerFactory.getLogger(WebContextListener.class); + + @Override + public void sessionCreated(HttpSessionEvent event) { + // session time out, default is 15 minutes, unit is minutes + int timeout = $().config().getInt("server.timeout", 15); + event.getSession().setMaxInactiveInterval(timeout * 60); + } + + @Override + public void contextInitialized(ServletContextEvent sce) { + + System.out.println("WebContextListener >>>>> contextInitialized"); + Blade blade = Blade.$(); + if(!blade.isInit()){ + + ServletContext servletContext = sce.getServletContext(); + + WebContextHolder.init(servletContext); + + LOGGER.info("jdk.version\t=> {}", SystemKit.getJavaInfo().getVersion()); + LOGGER.info("user.dir\t\t=> {}", System.getProperty("user.dir")); + LOGGER.info("java.io.tmpdir\t=> {}", System.getProperty("java.io.tmpdir")); + LOGGER.info("user.timezone\t=> {}", System.getProperty("user.timezone")); + LOGGER.info("file.encodin\t=> {}", System.getProperty("file.encoding")); + + long initStart = System.currentTimeMillis(); + + String webRoot = DispatchKit.getWebRoot(servletContext); + + blade.webRoot(webRoot); + EmbedServer embedServer = blade.embedServer(); + if(null != embedServer){ + embedServer.setWebRoot(webRoot); + } + + LOGGER.info("blade.webroot\t=> {}", webRoot); + + try { + if(!blade.isInit()){ + if(!blade.applicationConfig().isInit()){ + blade.loadAppConf(Const.APP_PROPERTIES); + blade.applicationConfig().setEnv(blade.config()); + } + + // initialization ioc + IocApplication iocApplication = new IocApplication(); + iocApplication.initBeans(); + + blade.init(); + } + + LOGGER.info("blade.isDev = {}", blade.isDev()); + + BannerStarter.printStart(); + String appName = blade.config().get("app.name", "Blade"); + LOGGER.info("{} initialize successfully, Time elapsed: {} ms.", appName, System.currentTimeMillis() - initStart); + } catch (Exception e) { + LOGGER.error("ApplicationContext init error", e); + } + } + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + + @Override + public void sessionDestroyed(HttpSessionEvent event) { + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/listener/WebContextListener.java b/blade-core/src/main/java/com/blade/listener/WebContextListener.java deleted file mode 100644 index cc3609ec5..000000000 --- a/blade-core/src/main/java/com/blade/listener/WebContextListener.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.blade.listener; - -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.http.HttpSessionEvent; -import javax.servlet.http.HttpSessionListener; - -import com.blade.Blade; -import com.blade.context.WebContextHolder; - -public class WebContextListener implements ServletContextListener, HttpSessionListener { - - private int timeout = Blade.$().config().getInt("server.timeout", 15 * 60); - - @Override - public void sessionCreated(HttpSessionEvent event) { - event.getSession().setMaxInactiveInterval(timeout); - } - - @Override - public void contextInitialized(ServletContextEvent sce) { - WebContextHolder.init(sce.getServletContext()); - } - - @Override - public void contextDestroyed(ServletContextEvent sce) { - } - - @Override - public void sessionDestroyed(HttpSessionEvent event) { - } - - -} diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java index 7ebdaeb35..961789fd8 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java @@ -18,23 +18,12 @@ import java.io.IOException; import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.Blade; -import com.blade.Bootstrap; -import com.blade.banner.BannerStarter; -import com.blade.context.ApplicationContext; -import com.blade.embedd.EmbedServer; -import com.blade.kit.DispatchKit; -import com.blade.kit.StringKit; -import com.blade.kit.SystemKit; /** * Blade Core DispatcherServlet @@ -46,77 +35,16 @@ public class DispatcherServlet extends HttpServlet { private static final long serialVersionUID = -2607425162473178733L; - private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); - - private Blade blade = Blade.$(); - - private Bootstrap bootstrap; - - private ServletContext servletContext; - + private Blade blade; private DispatcherHandler dispatcherHandler; public DispatcherServlet() { } - public DispatcherServlet(Bootstrap bootstrap) { - this.bootstrap = bootstrap; - blade.init(); - } - @Override public void init(ServletConfig config) throws ServletException { - servletContext = config.getServletContext(); - if(!blade.isInit()){ - - LOGGER.info("jdk.version\t=> {}", SystemKit.getJavaInfo().getVersion()); - LOGGER.info("user.dir\t\t=> {}", System.getProperty("user.dir")); - LOGGER.info("java.io.tmpdir\t=> {}", System.getProperty("java.io.tmpdir")); - LOGGER.info("user.timezone\t=> {}", System.getProperty("user.timezone")); - LOGGER.info("file.encodin\t=> {}", System.getProperty("file.encoding")); - - long initStart = System.currentTimeMillis(); - - String webRoot = DispatchKit.getWebRoot(servletContext); - - blade.webRoot(webRoot); - EmbedServer embedServer = blade.embedServer(); - if(null != embedServer){ - embedServer.setWebRoot(webRoot); - } - - LOGGER.info("blade.webroot\t=> {}", webRoot); - -// WebContextHolder.init(servletContext); - - this.bootstrap = blade.bootstrap(); - - if(null == bootstrap){ - String bootStrapClassName = config.getInitParameter("bootstrap"); - if(StringKit.isNotBlank(bootStrapClassName)){ - this.bootstrap = getBootstrap(bootStrapClassName); - } else { - this.bootstrap = new Bootstrap() { - @Override - public void init(Blade blade) { - } - }; - } - blade.app(this.bootstrap); - } - - ApplicationContext.init(blade); - - LOGGER.info("blade.isDev = {}", blade.isDev()); - - dispatcherHandler = new DispatcherHandler(servletContext, blade.routers()); - - BannerStarter.printStart(); - - String appName = blade.config().get("app.name", "Blade"); - - LOGGER.info("{} initialize successfully, Time elapsed: {} ms.", appName, System.currentTimeMillis() - initStart); - } + blade = Blade.$(); + dispatcherHandler = new DispatcherHandler(config.getServletContext(), blade.routers()); } @Override @@ -130,29 +58,4 @@ protected void service(HttpServletRequest httpRequest, HttpServletResponse httpR public void destroy() { super.destroy(); } - - /** - * Get global initialization object, the application of the initialization - * - * @param botstrapClassName botstrap class name - * @return return bootstrap object - * @throws ServletException - */ - @SuppressWarnings("unchecked") - private Bootstrap getBootstrap(String botstrapClassName) throws ServletException { - Bootstrap bootstrapClass = null; - try { - if(null != botstrapClassName){ - Class applicationClass = (Class) Class.forName(botstrapClassName); - if(null != applicationClass){ - bootstrapClass = applicationClass.newInstance(); - } - } else { - throw new ServletException("bootstrapClass is null !"); - } - } catch (Exception e) { - throw new ServletException(e); - } - return bootstrapClass; - } } diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index a258b66a7..928a82a35 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -27,12 +27,12 @@ import com.blade.Blade; import com.blade.Const; import com.blade.context.DynamicContext; +import com.blade.context.WebContextListener; import com.blade.exception.EmbedServerException; import com.blade.kit.StringKit; import com.blade.kit.base.Config; import com.blade.kit.resource.ClassInfo; import com.blade.kit.resource.ClassReader; -import com.blade.listener.WebContextListener; import com.blade.mvc.DispatcherServlet; public class EmbedJettyServer implements EmbedServer { From a53ee8e12f4b542590d53d7d2ff0890650987857 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Sep 2016 11:04:18 +0800 Subject: [PATCH 523/545] =?UTF-8?q?=E2=9C=84=20add=20register=20filter=20m?= =?UTF-8?q?ethod?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/Blade.java | 36 +++++++++++++--- blade-core/src/main/java/com/blade/Const.java | 2 +- .../com/blade/embedd/EmbedJettyServer.java | 43 ++++++------------- 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index eeaa5ab41..df3787526 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -17,10 +17,14 @@ import java.io.InputStream; import java.text.ParseException; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import javax.servlet.Filter; + import com.blade.config.ApplicationConfig; import com.blade.embedd.EmbedServer; import com.blade.exception.EmbedServerException; @@ -68,12 +72,15 @@ public final class Blade { // default context path private String contextPath = Const.DEFAULT_CONTEXTPATH; - + // enableServer private Boolean enableServer = false; - + // plugins private Set> plugins; + + // filters + private Map, String[]> filters = new HashMap, String[]>(8); // global config private Config config; @@ -91,7 +98,7 @@ private Blade() { static final class BladeHolder { private static final Blade $ = new Blade(); } - + /** * @return Single case method returns Blade object */ @@ -201,6 +208,7 @@ public Blade loadAppConf(String location) { * @return return blade */ public Blade addRoutePackage(String packageName) { + Assert.notBlank(packageName); return this.addRoutePackages(packageName); } @@ -213,6 +221,7 @@ public Blade addRoutePackage(String packageName) { * @return return blade */ public Blade addRoutePackages(String... packages) { + Assert.notNull(packages); applicationConfig.addRoutePkgs(packages); return this; } @@ -224,6 +233,7 @@ public Blade addRoutePackages(String... packages) { * @return */ public Blade basePackage(String basePackage) { + Assert.notBlank(basePackage); applicationConfig.setBasePackage(basePackage); return this; } @@ -235,6 +245,7 @@ public Blade basePackage(String basePackage) { * @return return blade */ public Blade interceptor(String packageName) { + Assert.notBlank(packageName); applicationConfig.setInterceptorPackage(packageName); return this; } @@ -251,7 +262,7 @@ public Blade ioc(String... packages) { applicationConfig.addIocPkgs(packages); return this; } - + /** * Add a route * @@ -268,7 +279,22 @@ public Blade route(String path, Class clazz, String method) { routers.route(path, clazz, method); return this; } - + + /** + * regsiter filter + * @param clazz + * @param pathSpec + * @return + */ + public Blade registerFilter(Class clazz, String... pathSpec){ + filters.put(clazz, pathSpec); + return this; + } + + public Map, String[]> filters(){ + return filters; + } + /** * Register a functional route * diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index bbfc8bb80..cede6793b 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -24,7 +24,7 @@ public interface Const { // current blade version - String BLADE_VERSION = "1.6.7-alpha"; + String BLADE_VERSION = "1.6.7-beta"; // default embedd server context path String DEFAULT_CONTEXTPATH = "/"; diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index 928a82a35..0f1b029c6 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -2,14 +2,13 @@ import static com.blade.Blade.$; -import java.util.ArrayList; import java.util.EnumSet; -import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import javax.servlet.DispatcherType; import javax.servlet.Filter; -import javax.servlet.annotation.WebFilter; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; @@ -26,13 +25,10 @@ import com.blade.Blade; import com.blade.Const; -import com.blade.context.DynamicContext; import com.blade.context.WebContextListener; import com.blade.exception.EmbedServerException; -import com.blade.kit.StringKit; +import com.blade.kit.CollectionKit; import com.blade.kit.base.Config; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; import com.blade.mvc.DispatcherServlet; public class EmbedJettyServer implements EmbedServer { @@ -47,13 +43,10 @@ public class EmbedJettyServer implements EmbedServer { private Config config = null; - private ClassReader classReader = null; - public EmbedJettyServer() { System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); $().loadAppConf("jetty.properties"); config = $().config(); - classReader = DynamicContext.getClassReader(); $().enableServer(true); } @@ -136,30 +129,18 @@ public void startup(int port, String contextPath, String webRoot) throws EmbedSe } } - public List loadFilters(WebAppContext webAppContext) throws Exception{ - String filterPkg = Blade.$().applicationConfig().getFilterPkg(); - if (StringKit.isNotBlank(filterPkg)) { - List filters = new ArrayList(10); - Set intes = classReader.getClass(filterPkg, false); - if (null != intes) { - for (ClassInfo classInfo : intes) { - if (null != classInfo.getClazz().getInterfaces() - && classInfo.getClazz().getInterfaces()[0].equals(Filter.class)) { - - WebFilter webFilter = classInfo.getClazz().getAnnotation(WebFilter.class); - if(null != webFilter){ - String[] pathSpecs = webFilter.value(); - Class filterClazz = (Class) classInfo.getClazz(); - for(String pathSpec : pathSpecs){ - webAppContext.addFilter(filterClazz, pathSpec, EnumSet.of(DispatcherType.REQUEST)); - } - } - } + public void loadFilters(WebAppContext webAppContext) throws Exception{ + Map, String[]> filters = Blade.$().filters(); + if(CollectionKit.isNotEmpty(filters)){ + Set, String[]>> entrySet = filters.entrySet(); + for(Entry, String[]> entry : entrySet){ + Class filterClazz = entry.getKey(); + String[] pathSpecs = entry.getValue(); + for(String pathSpec : pathSpecs){ + webAppContext.addFilter(filterClazz, pathSpec, EnumSet.of(DispatcherType.REQUEST)); } } - return filters; } - return null; } public void shutdown() throws EmbedServerException { From 9042460c077362bd3e058e5f14f35846f5fe8648 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Sep 2016 11:08:45 +0800 Subject: [PATCH 524/545] =?UTF-8?q?=E2=9C=84=20add=20custom=20servlets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-core/src/main/java/com/blade/Blade.java | 19 +++++++++++++++++++ .../com/blade/embedd/EmbedJettyServer.java | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index df3787526..7a18713a4 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -24,6 +24,7 @@ import java.util.Set; import javax.servlet.Filter; +import javax.servlet.http.HttpServlet; import com.blade.config.ApplicationConfig; import com.blade.embedd.EmbedServer; @@ -81,6 +82,9 @@ public final class Blade { // filters private Map, String[]> filters = new HashMap, String[]>(8); + + // servlets + private Map, String[]> servlets = new HashMap, String[]>(8); // global config private Config config; @@ -291,10 +295,25 @@ public Blade registerFilter(Class clazz, String... pathSpec){ return this; } + /** + * regsiter servlet + * @param clazz + * @param pathSpec + * @return + */ + public Blade registerServlet(Class clazz, String... pathSpec){ + servlets.put(clazz, pathSpec); + return this; + } + public Map, String[]> filters(){ return filters; } + public Map, String[]> servlets(){ + return servlets; + } + /** * Register a functional route * diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index 0f1b029c6..33a559e08 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -9,6 +9,7 @@ import javax.servlet.DispatcherType; import javax.servlet.Filter; +import javax.servlet.http.HttpServlet; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; @@ -117,6 +118,7 @@ public void startup(int port, String contextPath, String webRoot) throws EmbedSe try { + loadServlets(webAppContext); loadFilters(webAppContext); HandlerList handlers = new HandlerList(); @@ -143,6 +145,20 @@ public void loadFilters(WebAppContext webAppContext) throws Exception{ } } + public void loadServlets(WebAppContext webAppContext) throws Exception{ + Map, String[]> servlets = Blade.$().servlets(); + if(CollectionKit.isNotEmpty(servlets)){ + Set, String[]>> entrySet = servlets.entrySet(); + for(Entry, String[]> entry : entrySet){ + Class servletClazz = entry.getKey(); + String[] pathSpecs = entry.getValue(); + for(String pathSpec : pathSpecs){ + webAppContext.addServlet(servletClazz, pathSpec); + } + } + } + } + public void shutdown() throws EmbedServerException { try { server.stop(); From 8e289fddb528012046351d2da72ca6d316fc27c8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Sep 2016 11:09:50 +0800 Subject: [PATCH 525/545] =?UTF-8?q?=E2=9C=84=20remove=20extra=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/blade/context/WebContextListener.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/blade-core/src/main/java/com/blade/context/WebContextListener.java b/blade-core/src/main/java/com/blade/context/WebContextListener.java index 41559cc80..127cb4808 100644 --- a/blade-core/src/main/java/com/blade/context/WebContextListener.java +++ b/blade-core/src/main/java/com/blade/context/WebContextListener.java @@ -81,18 +81,16 @@ public void contextInitialized(ServletContextEvent sce) { LOGGER.info("blade.webroot\t=> {}", webRoot); try { - if(!blade.isInit()){ - if(!blade.applicationConfig().isInit()){ - blade.loadAppConf(Const.APP_PROPERTIES); - blade.applicationConfig().setEnv(blade.config()); - } - - // initialization ioc - IocApplication iocApplication = new IocApplication(); - iocApplication.initBeans(); - - blade.init(); - } + if(!blade.applicationConfig().isInit()){ + blade.loadAppConf(Const.APP_PROPERTIES); + blade.applicationConfig().setEnv(blade.config()); + } + + // initialization ioc + IocApplication iocApplication = new IocApplication(); + iocApplication.initBeans(); + + blade.init(); LOGGER.info("blade.isDev = {}", blade.isDev()); From 72f4f24a3bf2778de48296a6e3f1ef576cefcdd3 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Sep 2016 11:21:40 +0800 Subject: [PATCH 526/545] =?UTF-8?q?=E2=9C=84=20update=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LAST_VERSION.md | 4 ++-- README.md | 8 ++++---- README_CN.md | 8 ++++---- UPDATE_LOG.md | 8 ++++++++ pom.xml | 2 +- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/LAST_VERSION.md b/LAST_VERSION.md index 010949d8c..c4fd9cb0e 100644 --- a/LAST_VERSION.md +++ b/LAST_VERSION.md @@ -34,7 +34,7 @@     com.bladejava     blade-core -    1.6.7-alpha +    1.6.7-beta ``` @@ -43,7 +43,7 @@     com.bladejava     blade-embed-jetty -    0.0.5 +    0.0.6 ``` diff --git a/README.md b/README.md index 8730009b8..a9c2c8f7d 100644 --- a/README.md +++ b/README.md @@ -38,18 +38,18 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.7-alpha + 1.6.7-beta com.bladejava blade-embed-jetty - 0.0.5 + 0.0.6 ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.7-alpha' -compile 'com.bladejava:blade-embed-jetty:0.0.5' +compile 'com.bladejava:blade-core:1.6.7-beta' +compile 'com.bladejava:blade-embed-jetty:0.0.6' ``` Create `Main` method like this: diff --git a/README_CN.md b/README_CN.md index 5c6cf4aa7..715429c6c 100644 --- a/README_CN.md +++ b/README_CN.md @@ -39,20 +39,20 @@ Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁 com.bladejava blade-core - 1.6.7-alpha + 1.6.7-beta com.bladejava blade-embed-jetty - 0.0.5 + 0.0.6 ``` 或者 `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.7-alpha' -compile 'com.bladejava:blade-embed-jetty:0.0.5' +compile 'com.bladejava:blade-core:1.6.7-beta' +compile 'com.bladejava:blade-embed-jetty:0.0.6' ``` 编写 `Main`函数: diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 0e90a9140..b75ea5156 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -1,5 +1,13 @@ # Blade 更新日志 +### v1.6.7 + 1. 支持自定义filter, servlet + 2. 支持websocket + 3. 添加启动监听器 + 4. 配置类自动注入 + 5. 增强路由注解功能 + + ### v1.6.6 1. 支持内置jetty服务器启动 2. 支持@JSON和@RestController diff --git a/pom.xml b/pom.xml index d447a974c..8720f0e56 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ - + From 2f2f14a0bc67cb476f1b4b5810469e2080de2aa9 Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 21 Sep 2016 11:22:44 +0800 Subject: [PATCH 527/545] =?UTF-8?q?=E2=9C=84=20update=20pom.xml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8720f0e56..24d3c82fc 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 1.7.21 1.6.7-beta - 1.3.3 + 1.3.4 1.0.0 0.0.6 9.2.12.v20150709 From cebe7f079be14c6b88bdd3ef352a69eb13193d0f Mon Sep 17 00:00:00 2001 From: biezhi Date: Wed, 23 Nov 2016 18:12:12 +0800 Subject: [PATCH 528/545] update pom.xml --- blade-core/pom.xml | 1 + .../com/blade/context/WebContextListener.java | 2 - .../java/com/blade/mvc/DispatcherHandler.java | 17 +- blade-embed-jetty/pom.xml | 1 - pom.xml | 155 +++++++++++++++--- 5 files changed, 133 insertions(+), 43 deletions(-) diff --git a/blade-core/pom.xml b/blade-core/pom.xml index b2a83c0e5..c80b313e9 100644 --- a/blade-core/pom.xml +++ b/blade-core/pom.xml @@ -66,4 +66,5 @@ + diff --git a/blade-core/src/main/java/com/blade/context/WebContextListener.java b/blade-core/src/main/java/com/blade/context/WebContextListener.java index 127cb4808..e1523d1fe 100644 --- a/blade-core/src/main/java/com/blade/context/WebContextListener.java +++ b/blade-core/src/main/java/com/blade/context/WebContextListener.java @@ -53,8 +53,6 @@ public void sessionCreated(HttpSessionEvent event) { @Override public void contextInitialized(ServletContextEvent sce) { - - System.out.println("WebContextListener >>>>> contextInitialized"); Blade blade = Blade.$(); if(!blade.isInit()){ diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index 033ff6091..e891d05cc 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -78,7 +78,7 @@ public DispatcherHandler(ServletContext servletContext, Routers routers) { this.routeViewHandler = new RouteViewResolve(this.ioc); } - public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse){ + public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse) { // http method, GET/POST ... String method = httpRequest.getMethod(); @@ -122,21 +122,10 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo // Not found render404(response, uri); } - return; - } catch (TemplateException e) { - LOGGER.error("Template error", e); - DispatchKit.printError(e, 500, response); - } catch (BladeException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); - }catch (Exception e) { + } catch (Exception e) { LOGGER.error(e.getMessage(), e); - DispatchKit.printError(e, 500, response); + DispatchKit.printError(new BladeException(e), 500, response); } - return; } /** diff --git a/blade-embed-jetty/pom.xml b/blade-embed-jetty/pom.xml index 18043792d..ad5fabb0a 100644 --- a/blade-embed-jetty/pom.xml +++ b/blade-embed-jetty/pom.xml @@ -12,7 +12,6 @@ blade-embed-jetty ${blade-embed-jetty.version} blade-embed-jetty - http://maven.apache.org diff --git a/pom.xml b/pom.xml index 24d3c82fc..48c9ffcc7 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,39 @@ blade https://github.com/biezhi/blade + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + + biezhi + biezhi.me@gmail.com + + + + + scm:git@github.com:biezhi/blade.git + scm:git@github.com:biezhi/blade.git + git@github.com:biezhi/blade.git + + + + + oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + true + + + + 1.6 1.6 @@ -40,19 +73,6 @@ blade-websocket-jetty - - - oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - @@ -81,18 +101,101 @@ - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.6 - 1.6 - UTF-8 - - - - + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + UTF-8 + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.17 + + true + + + + + + + + release + + + oss + https://oss.sonatype.org/content/repositories/snapshots/ + + + oss + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.4 + + + package + + jar-no-fork + + + + + true + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.2 + + UTF-8 + UTF-8 + + + + package + + jar + + + -Xdoclint:none + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + + \ No newline at end of file From c6880e77ca75ba3ce276b94a8225221458a372ad Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 17 Dec 2016 15:57:11 +0800 Subject: [PATCH 529/545] => fix throw exception bug --- blade-core/src/main/java/com/blade/Blade.java | 184 ++++---- blade-core/src/main/java/com/blade/Const.java | 85 ++-- .../java/com/blade/banner/BladeBanner.java | 2 +- .../java/com/blade/config/BaseConfig.java | 2 +- ...licationConfig.java => Configuration.java} | 408 +++++++++--------- .../main/java/com/blade/config/Packages.java | 5 +- .../main/java/com/blade/kit/DispatchKit.java | 14 +- .../java/com/blade/mvc/DispatcherHandler.java | 2 +- .../main/java/com/blade/mvc/http/Request.java | 12 +- .../mvc/http/wrapper/ServletRequest.java | 148 +++---- .../mvc/http/wrapper/ServletResponse.java | 36 +- .../com/blade/mvc/route/RouteBuilder.java | 6 +- .../mvc/view/resolve/MethodArgument.java | 209 +++++---- .../mvc/view/resolve/RouteViewResolve.java | 9 +- .../mvc/view/template/DefaultEngine.java | 2 +- blade-sample/pom.xml | 39 ++ .../main/java/com/xxx/hello/Application.java | 37 ++ .../src/main/resources/log4j.properties | 4 + pom.xml | 14 +- 19 files changed, 656 insertions(+), 562 deletions(-) rename blade-core/src/main/java/com/blade/config/{ApplicationConfig.java => Configuration.java} (93%) create mode 100644 blade-sample/pom.xml create mode 100644 blade-sample/src/main/java/com/xxx/hello/Application.java create mode 100644 blade-sample/src/main/resources/log4j.properties diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 7a18713a4..d3735bf48 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -15,91 +15,102 @@ */ package com.blade; -import java.io.InputStream; -import java.text.ParseException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.servlet.Filter; -import javax.servlet.http.HttpServlet; - -import com.blade.config.ApplicationConfig; +import com.blade.config.Configuration; import com.blade.embedd.EmbedServer; import com.blade.exception.EmbedServerException; import com.blade.ioc.Ioc; import com.blade.ioc.SimpleIoc; import com.blade.kit.Assert; +import com.blade.kit.CollectionKit; import com.blade.kit.StringKit; import com.blade.kit.base.Config; import com.blade.mvc.http.HttpMethod; import com.blade.mvc.interceptor.Interceptor; -import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteBuilder; -import com.blade.mvc.route.RouteException; -import com.blade.mvc.route.RouteGroup; -import com.blade.mvc.route.RouteHandler; -import com.blade.mvc.route.Routers; +import com.blade.mvc.route.*; import com.blade.mvc.route.loader.ClassPathRouteLoader; import com.blade.plugin.Plugin; +import javax.servlet.Filter; +import javax.servlet.http.HttpServlet; +import java.io.InputStream; +import java.text.ParseException; +import java.util.*; + /** * Blade Core Class - * + * * @author biezhi * @since 1.6.6 */ public final class Blade { - // blade initialize + /** + * Indicates whether the framework has been initialized + */ private boolean isInit = false; - - // global configuration Object - private ApplicationConfig applicationConfig = null; - // ioc container + /** + * Framework Global Configuration + */ + private Configuration configuration; + + /** + * Default ioc container + */ private Ioc ioc = new SimpleIoc(); - // routes + /** + * Default routes + */ private Routers routers = new Routers(); - // routebuilder + /** + * Route builder + */ private RouteBuilder routeBuilder; - // jetty start port + /** + * Web server startup port + */ private int port = Const.DEFAULT_PORT; - - // default context path + + /** + * Web context path + */ private String contextPath = Const.DEFAULT_CONTEXTPATH; - - // enableServer + + /** + * Is enabled server + */ private Boolean enableServer = false; - - // plugins + + /** + * plugins + */ private Set> plugins; - - // filters - private Map, String[]> filters = new HashMap, String[]>(8); - - // servlets - private Map, String[]> servlets = new HashMap, String[]>(8); - // global config - private Config config; - - // embed server + /** + * filters + */ + private Map, String[]> filters = CollectionKit.newHashMap(8); + + /** + * servlets + */ + private Map, String[]> servlets = CollectionKit.newHashMap(8); + + /** + * embed web server e.g:jetty/tomcat + */ private EmbedServer embedServer; private Blade() { - this.config = new Config(); - this.applicationConfig = new ApplicationConfig(); - this.plugins = new HashSet>(); + this.configuration = new Configuration(); + this.plugins = CollectionKit.newHashSet(); this.routeBuilder = new RouteBuilder(this.routers); } - static final class BladeHolder { + private static final class BladeHolder { private static final Blade $ = new Blade(); } @@ -107,7 +118,7 @@ static final class BladeHolder { * @return Single case method returns Blade object */ @Deprecated - public static final Blade me() { + public static Blade me() { return BladeHolder.$; } @@ -117,36 +128,30 @@ public static final Blade me() { * @return */ @Deprecated - public static final Blade me(String location) { - Blade blade = BladeHolder.$; - blade.config.add(location); - return blade; + public static Blade me(String location) { + return $(location); } /** * @return Single case method returns Blade object */ - public static final Blade $() { + public static Blade $() { return BladeHolder.$; } /** - * @param confPath + * load blade application config file + * + * @param location * @return */ - public static final Blade $(String location) { + public static Blade $(String location) { Assert.notEmpty(location); Blade blade = BladeHolder.$; - blade.config.add(location); + blade.loadAppConf(location); return blade; } - /** - * Set Blade initialize - * - * @param isInit - * initialize - */ public void init() { if (!this.isInit) { this.isInit = true; @@ -160,9 +165,6 @@ public Routers routers() { return routers; } - /** - * @return return RouteBuilder - */ public RouteBuilder routeBuilder() { return routeBuilder; } @@ -177,8 +179,7 @@ public Ioc ioc() { /** * Setting a ioc container * - * @param container - * ioc object + * @param ioc object * @return return blade */ public Blade container(Ioc ioc) { @@ -195,11 +196,7 @@ public Blade container(Ioc ioc) { */ public Blade loadAppConf(String location) { Assert.notBlank(location); - try { - config.add(location); - } catch (Exception e) { - - } + configuration.load(location); return this; } @@ -207,7 +204,7 @@ public Blade loadAppConf(String location) { * Setting route package,e.g:com.baldejava.route Can be introduced into * multiple packages, all of which are in the package. * - * @param packages + * @param packageName * route package path, is your package name * @return return blade */ @@ -226,7 +223,7 @@ public Blade addRoutePackage(String packageName) { */ public Blade addRoutePackages(String... packages) { Assert.notNull(packages); - applicationConfig.addRoutePkgs(packages); + configuration.addRoutePkgs(packages); return this; } @@ -238,7 +235,7 @@ public Blade addRoutePackages(String... packages) { */ public Blade basePackage(String basePackage) { Assert.notBlank(basePackage); - applicationConfig.setBasePackage(basePackage); + configuration.setBasePackage(basePackage); return this; } @@ -250,7 +247,7 @@ public Blade basePackage(String basePackage) { */ public Blade interceptor(String packageName) { Assert.notBlank(packageName); - applicationConfig.setInterceptorPackage(packageName); + configuration.setInterceptorPackage(packageName); return this; } @@ -263,7 +260,7 @@ public Blade interceptor(String packageName) { * @return return blade */ public Blade ioc(String... packages) { - applicationConfig.addIocPkgs(packages); + configuration.addIocPkgs(packages); return this; } @@ -272,7 +269,7 @@ public Blade ioc(String... packages) { * * @param path * route path - * @param target + * @param clazz * Target object for routing * @param method * The method name of the route (at the same time, the HttpMethod @@ -432,7 +429,7 @@ public Blade any(String path, RouteHandler handler) { /** * Route Group. e.g blade.group('/users').get().post() * - * @param g + * @param prefix * @return return blade */ public RouteGroup group(String prefix) { @@ -476,7 +473,7 @@ public Blade after(String path, RouteHandler handler) { * @return return blade */ public Blade addResources(final String... resources) { - applicationConfig.addResources(resources); + configuration.addResources(resources); return this; } @@ -500,7 +497,7 @@ public Blade addInterceptor(Class interceptor) { */ public Blade webRoot(final String webRoot) { Assert.notBlank(webRoot); - applicationConfig.setWebRoot(webRoot); + configuration.setWebRoot(webRoot); return this; } @@ -512,7 +509,7 @@ public Blade webRoot(final String webRoot) { * @return return blade */ public Blade isDev(boolean isDev) { - applicationConfig.setDev(isDev); + configuration.setDev(isDev); return this; } @@ -542,14 +539,11 @@ public EmbedServer start(Class applicationClass) { public EmbedServer startNoJoin(Class applicationClass) { this.loadAppConf(Const.APP_PROPERTIES); - - // init blade environment config - applicationConfig.setEnv(config); - + if(null != applicationClass){ - applicationConfig.setApplicationClass(applicationClass); - if(StringKit.isBlank(applicationConfig.getBasePackage())){ - applicationConfig.setBasePackage(applicationClass.getPackage().getName()); + configuration.setApplicationClass(applicationClass); + if(StringKit.isBlank(configuration.getBasePackage())){ + configuration.setBasePackage(applicationClass.getPackage().getName()); } } @@ -581,36 +575,36 @@ public EmbedServer embedServer() { /** * @return Return blade config object */ - public ApplicationConfig applicationConfig() { - return applicationConfig; + public Configuration applicationConfig() { + return configuration; } /** * @return Return blade config object */ public Config config() { - return this.config; + return configuration.config(); } /** * @return Return blade encoding, default is UTF-8 */ public String encoding() { - return applicationConfig.getEncoding(); + return configuration.getEncoding(); } /** * @return Return blade web root path */ public String webRoot() { - return applicationConfig.webRoot(); + return configuration.webRoot(); } /** * @return Return is dev mode */ public boolean isDev() { - return applicationConfig.isDev(); + return configuration.isDev(); } /** diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index cede6793b..20aa9a842 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -17,50 +17,57 @@ /** * Const Interface + * + *
+ *     The basic configuration of the blade framework is stored
+ * 
* * @author biezhi * @since 1.6.6 */ public interface Const { - // current blade version - String BLADE_VERSION = "1.6.7-beta"; - - // default embedd server context path - String DEFAULT_CONTEXTPATH = "/"; - - // Server 500 error HTML - String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + BLADE_VERSION +"
"; - - // Server 404 error HTML - String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + BLADE_VERSION +"
"; - - // Default jetty server port - int DEFAULT_PORT = 9000; - - // Request ThreadPoll context key - String BLADE_EXECUTOR = "blade-req-executor"; - - /*************** - * package names - ***************/ - String ROUTE_PKGS = "route_packages"; - String IOC_PKGS = "ioc_packages"; - String CONFIG_PKGS = "config_packages"; - String RESOURCE_PKGS = "resouce_packages"; - String BASE_PKG = "base_package"; - String INTERCEPTOR_PKG = "interceptor_package"; - String FILTER_PKG = "filter_package"; - String LISTENER_PKG = "listener_package"; + /** + * the last blade framework version + */ + String VERSION = "1.7.0-alpha"; + + /** + * default embedd server context path + */ + String DEFAULT_CONTEXTPATH = "/"; + + /** + * server 500 error HTML + */ + String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + VERSION +"
"; + + /** + * server 404 error HTML + */ + String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + VERSION +"
"; + + /** + * default web server port + */ + int DEFAULT_PORT = 9000; + + /**** package names ****/ + String ROUTE_PKGS = "route_packages"; + String IOC_PKGS = "ioc_packages"; + String CONFIG_PKGS = "config_packages"; + String RESOURCE_PKGS = "resouce_packages"; + String BASE_PKG = "base_package"; + String INTERCEPTOR_PKG = "interceptor_package"; + String FILTER_PKG = "filter_package"; + String LISTENER_PKG = "listener_package"; - /**************** - * blade properties - * **************/ - String BLADE_ROUTE = "blade.route"; - String BLADE_IOC = "blade.ioc"; - String BLADE_VIEW_404 = "blade.view404"; - String BLADE_VIEW_500 = "blade.view500"; - String BLADE_DEV = "blade.dev"; - String APP_PROPERTIES = "app.properties"; + /**** blade properties ****/ + String BLADE_ROUTE = "blade.route"; + String BLADE_IOC = "blade.ioc"; + String BLADE_VIEW_404 = "blade.view404"; + String BLADE_VIEW_500 = "blade.view500"; + String BLADE_DEV = "blade.dev"; + String APP_PROPERTIES = "app.properties"; -} +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/banner/BladeBanner.java b/blade-core/src/main/java/com/blade/banner/BladeBanner.java index bfc441876..489285d62 100644 --- a/blade-core/src/main/java/com/blade/banner/BladeBanner.java +++ b/blade-core/src/main/java/com/blade/banner/BladeBanner.java @@ -32,7 +32,7 @@ public String startText() { for (String s : banner) { text.append("\r\n\t\t" + s); } - text.append("\r\n\t\t :: Blade :: (v" + Const.BLADE_VERSION + ")\r\n"); + text.append("\r\n\t\t :: Blade :: (v" + Const.VERSION + ")\r\n"); return text.toString(); } } diff --git a/blade-core/src/main/java/com/blade/config/BaseConfig.java b/blade-core/src/main/java/com/blade/config/BaseConfig.java index 873bb6c62..9bcf8bc5c 100644 --- a/blade-core/src/main/java/com/blade/config/BaseConfig.java +++ b/blade-core/src/main/java/com/blade/config/BaseConfig.java @@ -23,6 +23,6 @@ */ public interface BaseConfig { - void config(ApplicationConfig applicationConfig); + void config(Configuration configuration); } diff --git a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java b/blade-core/src/main/java/com/blade/config/Configuration.java similarity index 93% rename from blade-core/src/main/java/com/blade/config/ApplicationConfig.java rename to blade-core/src/main/java/com/blade/config/Configuration.java index 7711eb5de..06de99413 100644 --- a/blade-core/src/main/java/com/blade/config/ApplicationConfig.java +++ b/blade-core/src/main/java/com/blade/config/Configuration.java @@ -1,197 +1,211 @@ -/** - * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.config; - -import static com.blade.Blade.$; - -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.Const; -import com.blade.context.DynamicContext; -import com.blade.kit.Assert; -import com.blade.kit.StringKit; -import com.blade.kit.base.Config; -import com.blade.mvc.view.ViewSettings; - -/** - * Blade Application Config Class - * - * @author biezhi - * @since 1.6.6 - * - */ -public class ApplicationConfig { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfig.class); - - private Packages packages; - - // Encoding - private String encoding = "utf-8"; - - // Is dev mode - private boolean isDev = true; - - private boolean isInit = false; - - private String webRoot; - - private Class applicationClass; - - public ApplicationConfig() { - this.packages = new Packages(); - this.addResources("/public", "/assets", "/static"); - } - - public void setEnv(Config config) { - if (null != config && !isInit) { - - // get dev mode - this.isDev = config.getBoolean("app.dev", true); - - // get ioc packages - packages.put(Const.IOC_PKGS, config.get("app.ioc")); - - // get view 404, 500 page - ViewSettings.$().setView500(config.get("mvc.view.500")); - ViewSettings.$().setView404(config.get("mvc.view.404")); - - // get http encoding - this.encoding = config.get("http.encoding", "UTF-8"); - - // get mvc static folders - String statics = config.get("mvc.statics"); - - // get app base package - String basePackage = config.get("app.base-package"); - - // get server start port - Integer port = config.getInt("server.port", Const.DEFAULT_PORT); - $().listen(port); - - if (StringKit.isNotBlank(statics)) { - this.addResources(StringKit.split(statics, ',')); - } - - if (StringKit.isNotBlank(basePackage)) { - this.setBasePackage(basePackage); - } - isInit = true; - } - } - - public void addRoutePkgs(String... pkgs){ - packages.add(Const.ROUTE_PKGS, pkgs); - } - - public void addIocPkgs(String... pkgs){ - packages.add(Const.IOC_PKGS, pkgs); - } - - public String getBasePackage() { - return packages.first(Const.BASE_PKG); - } - - public String[] getConfigPkgs(){ - return packages.array(Const.CONFIG_PKGS); - } - - public String[] getIocPkgs(){ - return packages.array(Const.IOC_PKGS); - } - - public String[] getRoutePkgs(){ - return packages.array(Const.ROUTE_PKGS); - } - - public Set getResources(){ - return packages.values(Const.RESOURCE_PKGS); - } - - public String getInterceptorPkg(){ - return packages.first(Const.INTERCEPTOR_PKG); - } - - public String getFilterPkg(){ - return packages.first(Const.FILTER_PKG); - } - - public String getListenerPkg(){ - return packages.first(Const.LISTENER_PKG); - } - - public boolean isDev() { - return isDev; - } - - public String getEncoding() { - return encoding; - } - - public boolean isInit(){ - return this.isInit; - } - - public String webRoot() { - return this.webRoot; - } - - public Class getApplicationClass() { - return applicationClass; - } - - public void setApplicationClass(Class applicationClass) { - this.applicationClass = applicationClass; - DynamicContext.init(applicationClass); - } - - public void setInterceptorPackage(String interceptorPkg) { - packages.put(Const.INTERCEPTOR_PKG, interceptorPkg); - } - - public void setBasePackage(String basePackage) { - Assert.notBlank(basePackage); - - packages.put(Const.BASE_PKG, basePackage); - packages.put(Const.INTERCEPTOR_PKG, basePackage + ".interceptor"); - packages.put(Const.FILTER_PKG, basePackage + ".filter"); - packages.put(Const.LISTENER_PKG, basePackage + ".listener"); - - packages.add(Const.CONFIG_PKGS, basePackage + ".config"); - packages.add(Const.IOC_PKGS, basePackage + ".service.*"); - packages.add(Const.ROUTE_PKGS, basePackage + ".controller"); - } - - public void addResources(String... resources) { - Assert.notNull(resources); - for(String resource : resources){ - LOGGER.debug("Add Resource: {}", resource); - } - packages.add(Const.RESOURCE_PKGS, resources); - } - - public void setWebRoot(String webRoot) { - this.webRoot = webRoot; - } - - public void setDev(boolean isDev) { - this.isDev = isDev; - } - -} +/** + * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.config; + +import static com.blade.Blade.$; + +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.blade.Const; +import com.blade.context.DynamicContext; +import com.blade.kit.Assert; +import com.blade.kit.StringKit; +import com.blade.kit.base.Config; +import com.blade.mvc.view.ViewSettings; + +/** + * Blade Application Config Class + * + * @author biezhi + * @since 1.6.6 + * + */ +public class Configuration { + + private static final Logger LOGGER = LoggerFactory.getLogger(Configuration.class); + + private Packages packages; + + // Encoding + private String encoding = "utf-8"; + + // Is dev mode + private boolean isDev = true; + + private boolean isInit = false; + + private String webRoot; + + private Class applicationClass; + + private Config config = new Config(); + + public Configuration() { + this.packages = new Packages(); + this.addResources("/public", "/assets", "/static"); + } + + public void setEnv(Config config) { + + if (null != config && !isInit) { + + // get dev mode + this.isDev = config.getBoolean("app.dev", true); + + // get ioc packages + packages.put(Const.IOC_PKGS, config.get("app.ioc")); + + // get view 404, 500 page + ViewSettings.$().setView500(config.get("mvc.view.500")); + ViewSettings.$().setView404(config.get("mvc.view.404")); + + // get http encoding + this.encoding = config.get("http.encoding", "UTF-8"); + + // get mvc static folders + String statics = config.get("mvc.statics"); + + // get app base package + String basePackage = config.get("app.base-package"); + + // get server start port + Integer port = config.getInt("server.port", Const.DEFAULT_PORT); + $().listen(port); + + if (StringKit.isNotBlank(statics)) { + this.addResources(StringKit.split(statics, ',')); + } + + if (StringKit.isNotBlank(basePackage)) { + this.setBasePackage(basePackage); + } + isInit = true; + } + } + + public void addRoutePkgs(String... pkgs){ + packages.add(Const.ROUTE_PKGS, pkgs); + } + + public void addIocPkgs(String... pkgs){ + packages.add(Const.IOC_PKGS, pkgs); + } + + public String getBasePackage() { + return packages.first(Const.BASE_PKG); + } + + public String[] getConfigPkgs(){ + return packages.array(Const.CONFIG_PKGS); + } + + public String[] getIocPkgs(){ + return packages.array(Const.IOC_PKGS); + } + + public String[] getRoutePkgs(){ + return packages.array(Const.ROUTE_PKGS); + } + + public Set getResources(){ + return packages.values(Const.RESOURCE_PKGS); + } + + public String getInterceptorPkg(){ + return packages.first(Const.INTERCEPTOR_PKG); + } + + public String getFilterPkg(){ + return packages.first(Const.FILTER_PKG); + } + + public String getListenerPkg(){ + return packages.first(Const.LISTENER_PKG); + } + + public boolean isDev() { + return isDev; + } + + public String getEncoding() { + return encoding; + } + + public boolean isInit(){ + return this.isInit; + } + + public String webRoot() { + return this.webRoot; + } + + public Class getApplicationClass() { + return applicationClass; + } + + public void setApplicationClass(Class applicationClass) { + this.applicationClass = applicationClass; + DynamicContext.init(applicationClass); + } + + public void setInterceptorPackage(String interceptorPkg) { + packages.put(Const.INTERCEPTOR_PKG, interceptorPkg); + } + + public void setBasePackage(String basePackage) { + Assert.notBlank(basePackage); + + packages.put(Const.BASE_PKG, basePackage); + packages.put(Const.INTERCEPTOR_PKG, basePackage + ".interceptor"); + packages.put(Const.FILTER_PKG, basePackage + ".filter"); + packages.put(Const.LISTENER_PKG, basePackage + ".listener"); + + packages.add(Const.CONFIG_PKGS, basePackage + ".config"); + packages.add(Const.IOC_PKGS, basePackage + ".service.*"); + packages.add(Const.ROUTE_PKGS, basePackage + ".controller"); + } + + public void addResources(String... resources) { + Assert.notNull(resources); + for(String resource : resources){ + LOGGER.debug("Add Resource: {}", resource); + } + packages.add(Const.RESOURCE_PKGS, resources); + } + + public void setWebRoot(String webRoot) { + this.webRoot = webRoot; + } + + public void setDev(boolean isDev) { + this.isDev = isDev; + } + + public void load(String location) { + try { + config.add(location); + } catch (Exception e){ + + } + } + + public Config config() { + return config; + } +} diff --git a/blade-core/src/main/java/com/blade/config/Packages.java b/blade-core/src/main/java/com/blade/config/Packages.java index 2523b4e6b..c863d3b3c 100644 --- a/blade-core/src/main/java/com/blade/config/Packages.java +++ b/blade-core/src/main/java/com/blade/config/Packages.java @@ -6,18 +6,19 @@ import java.util.Map; import java.util.Set; +import com.blade.kit.CollectionKit; import com.blade.kit.StringKit; public class Packages { - private Map> pool = new HashMap>(8); + private Map> pool = CollectionKit.newHashMap(8); public Packages() { } public void put(String name, String pkg) { if(null != name && StringKit.isNotBlank(pkg)){ - Set values = new HashSet(1); + Set values = CollectionKit.newHashSet(1); values.add(pkg); pool.put(name, values); } diff --git a/blade-core/src/main/java/com/blade/kit/DispatchKit.java b/blade-core/src/main/java/com/blade/kit/DispatchKit.java index bde4582dc..f44bb3666 100644 --- a/blade-core/src/main/java/com/blade/kit/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/kit/DispatchKit.java @@ -122,7 +122,11 @@ public static void printError(Throwable err, int code, Response response) { if (code == 404) { String view404 = ViewSettings.$().getView404(); if (StringKit.isNotBlank(view404)) { - response.render(view404); + try { + response.render(view404); + } catch (Exception e){ + LOGGER.error("", e); + } return; } else { writer.write(err.getMessage()); @@ -130,7 +134,11 @@ public static void printError(Throwable err, int code, Response response) { } else { String view500 = ViewSettings.$().getView500(); if (StringKit.isNotBlank(view500)) { - response.render(view500); + try { + response.render(view500); + } catch (Exception e){ + LOGGER.error("", e); + } return; } else { writer.write(Const.INTERNAL_ERROR); @@ -206,7 +214,7 @@ public static void printStatic(String uri, HttpServletRequest request, Response + "" + "

%s

";
 
-	private static final String END = "
Blade-" + Const.BLADE_VERSION + private static final String END = "
Blade-" + Const.VERSION + "(Blade Framework
"; } diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index e891d05cc..4b4b78a9c 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -124,7 +124,7 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo } } catch (Exception e) { LOGGER.error(e.getMessage(), e); - DispatchKit.printError(new BladeException(e), 500, response); + DispatchKit.printError(e, 500, response); } } diff --git a/blade-core/src/main/java/com/blade/mvc/http/Request.java b/blade-core/src/main/java/com/blade/mvc/http/Request.java index af3d2e780..7bc3ab4a0 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/Request.java +++ b/blade-core/src/main/java/com/blade/mvc/http/Request.java @@ -102,7 +102,7 @@ public interface Request { * @param name Parameter name * @return Return parameter value */ - String param(String name); + String pathParam(String name); /** * Get a URL parameter, and returns defaultValue if it is NULL @@ -110,28 +110,28 @@ public interface Request { * @param defaultValue Default Value * @return Return parameter value */ - String param(String name, String defaultValue); + String pathParam(String name, String defaultValue); /** * Return a URL parameter for a Int type * @param name Parameter name * @return Return Int parameter value */ - Integer paramAsInt(String name); + Integer pathParamAsInt(String name); /** * Return a URL parameter for a Long type * @param name Parameter name * @return Return Long parameter value */ - Long paramAsLong(String name); + Long pathParamAsLong(String name); /** * Return a URL parameter for a Boolean type * @param name Parameter name * @return Return Boolean parameter value */ - Boolean paramAsBool(String name); + Boolean pathParamAsBool(String name); /** * @return Return query string @@ -159,7 +159,7 @@ public interface Request { * @return Return request parameter values */ String query(String name, String defaultValue); - + /** * Returns a request parameter for a Int type * diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java index cb48b3517..a2493a0c7 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java @@ -15,31 +15,8 @@ */ package com.blade.mvc.http.wrapper; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.ServletContext; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import com.blade.exception.BladeException; +import com.blade.kit.CollectionKit; import com.blade.kit.IOKit; import com.blade.kit.ObjectKit; import com.blade.kit.StringKit; @@ -51,6 +28,17 @@ import com.blade.mvc.multipart.MultipartException; import com.blade.mvc.multipart.MultipartHandler; import com.blade.mvc.route.Route; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletContext; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.io.*; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * ServletRequest @@ -67,11 +55,15 @@ public class ServletRequest implements Request { protected Route route; private HttpServletRequest request; - - // path parameter eg: /user/12 + + /** + * path parameter eg: /user/12 + */ private Map pathParams = null; - - // query parameter eg: /user?name=jack + + /** + * query parameter eg: /user?name=jack + */ private Map queryParams = null; private Map fileItems = null; @@ -89,7 +81,9 @@ public ServletRequest(HttpServletRequest request) throws MultipartException, IOE } public void init() throws IOException, MultipartException { - // retrieve multipart/form-data parameters + /** + * retrieve multipart/form-data parameters + */ if (Multipart.isMultipartContent(request)) { Multipart multipart = new Multipart(); multipart.parse(request, new MultipartHandler() { @@ -201,12 +195,12 @@ public Map pathParams() { } @Override - public String param(String name) { + public String pathParam(String name) { return pathParams.get(name); } @Override - public String param(String name, String defaultValue) { + public String pathParam(String name, String defaultValue) { String val = pathParams.get(name); if(null == val){ val = defaultValue; @@ -215,8 +209,8 @@ public String param(String name, String defaultValue) { } @Override - public Integer paramAsInt(String name) { - String value = param(name); + public Integer pathParamAsInt(String name) { + String value = pathParam(name); if (StringKit.isNotBlank(value)) { return Integer.parseInt(value); } @@ -224,8 +218,8 @@ public Integer paramAsInt(String name) { } @Override - public Long paramAsLong(String name) { - String value = param(name); + public Long pathParamAsLong(String name) { + String value = pathParam(name); if (StringKit.isNotBlank(value)) { return Long.parseLong(value); } @@ -233,8 +227,8 @@ public Long paramAsLong(String name) { } @Override - public Boolean paramAsBool(String name) { - String value = param(name); + public Boolean pathParamAsBool(String name) { + String value = pathParam(name); if (StringKit.isNotBlank(value)) { return Boolean.parseBoolean(value); } @@ -248,8 +242,7 @@ public String queryString() { @Override public Map querys() { - Map params = new HashMap(); - + Map params = CollectionKit.newHashMap(8); Map requestParams = request.getParameterMap(); for (Map.Entry entry : requestParams.entrySet()) { params.put( entry.getKey(), join(entry.getValue()) ); @@ -261,7 +254,7 @@ public Map querys() { @Override public String query(String name) { String[] param = request.getParameterValues(name); - String val = null; + String val; if (param != null) { val = join(param); } else { @@ -273,7 +266,7 @@ public String query(String name) { @Override public String query(String name, String defaultValue) { String[] param = request.getParameterValues(name); - String val = null; + String val; if (param != null) { val = join(param); } else { @@ -287,53 +280,67 @@ public String query(String name, String defaultValue) { @Override public Integer queryAsInt(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { - return Integer.parseInt(value); + try { + String value = query(name); + if(StringKit.isBlank(value)){ + return null; + } + return Integer.valueOf(value); + } catch (Exception e){ + throw new BladeException(e.getMessage()); } - return null; } @Override public Long queryAsLong(String name) { - String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isNumber(value)) { - return Long.parseLong(value); + try { + String value = query(name); + if(StringKit.isBlank(value)){ + return null; + } + return Long.valueOf(value); + } catch (Exception e){ + throw new BladeException(e.getMessage()); } - return null; } @Override public Boolean queryAsBool(String name) { String value = query(name); - if (StringKit.isNotBlank(value) && StringKit.isBoolean(value)) { - return Boolean.parseBoolean(value); + if(StringKit.isBlank(value)){ + return null; + } + if(StringKit.isBoolean(value)){ + return Boolean.valueOf(value); + } else { + throw new BladeException("for string \"" + value + "\""); } - return null; } @Override public Float queryAsFloat(String name) { - String value = query(name); - if (StringKit.isNotBlank(value)) { - try { - return Float.parseFloat(value); - } catch (NumberFormatException e) { + try { + String value = query(name); + if(StringKit.isBlank(value)){ + return null; } + return Float.valueOf(value); + } catch (Exception e){ + throw new BladeException(e.getMessage()); } - return null; } @Override public Double queryAsDouble(String name) { - String value = query(name); - if (StringKit.isNotBlank(value)) { - try { - return Double.parseDouble(value); - } catch (NumberFormatException e) { + try { + String value = query(name); + if(StringKit.isBlank(value)){ + return null; } + return Double.valueOf(value); + } catch (Exception e){ + throw new BladeException(e.getMessage()); } - return null; } @Override @@ -388,7 +395,7 @@ public T attribute(String name) { @Override public Set attributes() { Set attrList = new HashSet(8); - Enumeration attributes = (Enumeration) request.getAttributeNames(); + Enumeration attributes = request.getAttributeNames(); while (attributes.hasMoreElements()) { attrList.add(attributes.nextElement()); } @@ -412,16 +419,13 @@ public boolean isSecure() { @Override public boolean isAjax() { - if (null == header("x-requested-with")) { - return false; - } - return "XMLHttpRequest".equals(header("x-requested-with")); + return null != header("x-requested-with") && "XMLHttpRequest".equals(header("x-requested-with")); } @Override public Map cookies() { javax.servlet.http.Cookie[] servletCookies = request.getCookies(); - Map cookies = new HashMap(8); + Map cookies = CollectionKit.newHashMap(8); for (javax.servlet.http.Cookie c : servletCookies) { cookies.put( c.getName(), map(c) ); } @@ -546,7 +550,7 @@ public String asString() { StringBuilder sb = new StringBuilder(); String line = reader.readLine(); while (null != line) { - sb.append(line + "\r\n"); + sb.append(line).append("\r\n"); line = reader.readLine(); } reader.close(); diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java index 3db3233c3..3128f7222 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java @@ -15,17 +15,6 @@ */ package com.blade.mvc.http.wrapper; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.context.WebContextHolder; import com.blade.kit.Assert; import com.blade.kit.DispatchKit; @@ -37,7 +26,15 @@ import com.blade.mvc.view.ViewSettings; import com.blade.mvc.view.resolve.JSONParser; import com.blade.mvc.view.template.TemplateEngine; -import com.blade.mvc.view.template.TemplateException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; /** * ServletResponse @@ -275,17 +272,14 @@ public PrintWriter writer() throws IOException { } @Override - public Response render(String view){ + public Response render(String view) { Assert.notBlank(view, "view not is null"); - String viewPath = Path.cleanPath(view); ModelAndView modelAndView = new ModelAndView(viewPath); try { templateEngine.render(modelAndView, response.getWriter()); - } catch (TemplateException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); + } catch (Exception e){ + LOGGER.error("", e); } return this; } @@ -299,10 +293,8 @@ public Response render(ModelAndView modelAndView) { modelAndView.setView(viewPath); try { templateEngine.render(modelAndView, response.getWriter()); - } catch (TemplateException e) { - LOGGER.error(e.getMessage(), e); - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); + } catch (Exception e){ + LOGGER.error("", e); } return this; } diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java index 4a70e321e..4b9708961 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java @@ -160,7 +160,7 @@ public void addInterceptor(final Class interceptor){ /** * Parse all routing in a controller * - * @param controller resolve the routing class + * @param router resolve the routing class */ public void addRouter(final Class router){ @@ -220,7 +220,7 @@ private String getRoutePath(String value, String nameSpace, String suffix){ /** * Build a route * - * @param target route target execution class + * @param clazz route target execution class * @param execMethod route execution method * @param path route path * @param method route httpmethod @@ -233,7 +233,7 @@ private void buildRoute(Class clazz, Method execMethod, String path, HttpMeth * Build a route * * @param path route path - * @param target route target execution class + * @param clazz route target execution class * @param execMethod route execution method * @param method route httpmethod */ diff --git a/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java b/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java index 01e73af1e..fbdfd002e 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java +++ b/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java @@ -15,142 +15,137 @@ */ package com.blade.mvc.view.resolve; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Map; - -import com.blade.exception.BladeException; import com.blade.exception.NotFoundException; import com.blade.kit.AsmKit; import com.blade.kit.StringKit; -import com.blade.mvc.annotation.CookieParam; -import com.blade.mvc.annotation.HeaderParam; -import com.blade.mvc.annotation.MultipartParam; -import com.blade.mvc.annotation.PathParam; -import com.blade.mvc.annotation.QueryParam; +import com.blade.mvc.annotation.*; import com.blade.mvc.http.Request; import com.blade.mvc.http.Response; import com.blade.mvc.multipart.FileItem; import com.blade.mvc.view.ModelAndView; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.Map; + public final class MethodArgument { public static Object[] getArgs(Request request, Response response, Method actionMethod) throws Exception{ + Class[] parameters = actionMethod.getParameterTypes(); - Annotation[][] paramterAnnotations = actionMethod.getParameterAnnotations(); + Annotation[][] annotations = actionMethod.getParameterAnnotations(); Object[] args = new Object[parameters.length]; - try { - actionMethod.setAccessible(true); - String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); - - for (int i = 0, len = parameters.length; i < len; i++) { - - Class argType = parameters[i]; - if (argType == Request.class) { - args[i] = request; + actionMethod.setAccessible(true); + String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod); + + for (int i = 0, len = parameters.length; i < len; i++) { + + Class argType = parameters[i]; + if (argType == Request.class) { + args[i] = request; + continue; + } + + if (argType == Response.class) { + args[i] = response; + continue; + } + + if (argType == ModelAndView.class) { + args[i] = new ModelAndView(); + continue; + } + + if (argType == Map.class) { + args[i] = request.querys(); + continue; + } + + Annotation annotation = annotations[i][0]; + if(null != annotation){ + // query param + if(annotation.annotationType() == QueryParam.class){ + QueryParam queryParam = (QueryParam) annotation; + String paramName = queryParam.value(); + String val = request.query(paramName); + + if (StringKit.isBlank(paramName)) { + assert paramaterNames != null; + paramName = paramaterNames[i]; + val = request.query(paramName); + } + if (StringKit.isBlank(val)) { + val = queryParam.defaultValue(); + } + args[i] = getRequestParam(argType, val); continue; } - - if (argType == Response.class) { - args[i] = response; + + // header param + if(annotation.annotationType() == HeaderParam.class){ + HeaderParam headerParam = (HeaderParam) annotation; + String paramName = headerParam.value(); + String val = request.header(paramName); + + if (StringKit.isBlank(paramName)) { + assert paramaterNames != null; + paramName = paramaterNames[i]; + val = request.header(paramName); + } + args[i] = getRequestParam(argType, val); continue; } - if (argType == ModelAndView.class) { - args[i] = new ModelAndView(); + // cookie param + if(annotation.annotationType() == CookieParam.class){ + CookieParam cookieParam = (CookieParam) annotation; + String paramName = cookieParam.value(); + String val = request.cookie(paramName); + + if (StringKit.isBlank(paramName)) { + assert paramaterNames != null; + paramName = paramaterNames[i]; + val = request.cookie(paramName); + } + args[i] = getRequestParam(argType, val); continue; } - - if (argType == Map.class) { - args[i] = request.querys(); + + // form multipart + if(annotation.annotationType() == MultipartParam.class && argType == FileItem.class){ + MultipartParam multipartParam = (MultipartParam) annotation; + String paramName = multipartParam.value(); + FileItem val = request.fileItem(paramName); + + if (StringKit.isBlank(paramName)) { + assert paramaterNames != null; + paramName = paramaterNames[i]; + val = request.fileItem(paramName); + } + args[i] = val; continue; } - - Annotation annotation = paramterAnnotations[i][0]; - if(null != annotation){ - - // query param - if(annotation.annotationType() == QueryParam.class){ - QueryParam queryParam = (QueryParam) annotation; - String paramName = queryParam.value(); - String val = request.query(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.query(paramName); - } - if (StringKit.isBlank(val)) { - val = queryParam.defaultValue(); - } - args[i] = getRequestParam(argType, val); - continue; - } - - // header param - if(annotation.annotationType() == HeaderParam.class){ - HeaderParam headerParam = (HeaderParam) annotation; - String paramName = headerParam.value(); - String val = request.header(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.header(paramName); - } - args[i] = getRequestParam(argType, val); - continue; - } - - // cookie param - if(annotation.annotationType() == CookieParam.class){ - CookieParam cookieParam = (CookieParam) annotation; - String paramName = cookieParam.value(); - String val = request.cookie(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.cookie(paramName); - } - args[i] = getRequestParam(argType, val); - continue; - } - - // form multipart - if(annotation.annotationType() == MultipartParam.class && argType == FileItem.class){ - MultipartParam multipartParam = (MultipartParam) annotation; - String paramName = multipartParam.value(); - FileItem val = request.fileItem(paramName); - - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.fileItem(paramName); - } - args[i] = val; - continue; + + // path param + if(annotation.annotationType() == PathParam.class){ + PathParam pathParam = (PathParam) annotation; + String paramName = pathParam.value(); + String val = request.pathParam(paramName); + if (StringKit.isBlank(paramName)) { + assert paramaterNames != null; + paramName = paramaterNames[i]; + val = request.pathParam(paramName); } - - // path param - if(annotation.annotationType() == PathParam.class){ - PathParam pathParam = (PathParam) annotation; - String paramName = pathParam.value(); - String val = request.param(paramName); - if (StringKit.isBlank(paramName)) { - paramName = paramaterNames[i]; - val = request.param(paramName); - } - if (StringKit.isBlank(val)) { - throw new NotFoundException("path param [" + paramName + "] is null"); - } - args[i] = getRequestParam(argType, val); - continue; + if (StringKit.isBlank(val)) { + throw new NotFoundException("path param [" + paramName + "] is null"); } + args[i] = getRequestParam(argType, val); } } - return args; - } catch (BladeException e) { - throw e; } + return args; } private static Object getRequestParam(Class parameterType, String val) { diff --git a/blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java b/blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java index d2998dce3..382d03fd5 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java +++ b/blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java @@ -17,6 +17,7 @@ import java.lang.reflect.Method; +import com.blade.exception.BladeException; import com.blade.ioc.Ioc; import com.blade.kit.reflect.ReflectKit; import com.blade.mvc.annotation.JSON; @@ -41,7 +42,7 @@ public void handle(Request request, Response response, Route route) throws Excep Object target = route.getTarget(); int len = actionMethod.getParameterTypes().length; - Object returnParam = null; + Object returnParam; if (len > 0) { Object[] args = MethodArgument.getArgs(request, response, actionMethod); returnParam = ReflectKit.invokeMehod(target, actionMethod, args); @@ -66,7 +67,7 @@ public void handle(Request request, Response response, Route route) throws Excep } } - public boolean intercept(Request request, Response response, Route route) throws Exception { + public boolean intercept(Request request, Response response, Route route) throws BladeException { Method actionMethod = route.getAction(); Object target = route.getTarget(); @@ -80,7 +81,7 @@ public boolean intercept(Request request, Response response, Route route) throws int len = actionMethod.getParameterTypes().length; actionMethod.setAccessible(true); try { - Object returnParam = null; + Object returnParam; if (len > 0) { Object[] args = MethodArgument.getArgs(request, response, actionMethod); returnParam = ReflectKit.invokeMehod(target, actionMethod, args); @@ -96,7 +97,7 @@ public boolean intercept(Request request, Response response, Route route) throws } return true; } catch (Exception e) { - throw e; + throw new BladeException(e); } } diff --git a/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java b/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java index 72799835e..00df9fec5 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java +++ b/blade-core/src/main/java/com/blade/mvc/view/template/DefaultEngine.java @@ -55,7 +55,7 @@ public void render(ModelAndView modelAndView, Writer writer) throws TemplateExce String content = StreamKit.readText(new BufferedReader(new FileReader(new File(realPath)))); servletResponse.getWriter().print(content); } catch (IOException e) { - throw new TemplateException(e); + throw new TemplateException(e.getMessage()); } } diff --git a/blade-sample/pom.xml b/blade-sample/pom.xml new file mode 100644 index 000000000..44696a6da --- /dev/null +++ b/blade-sample/pom.xml @@ -0,0 +1,39 @@ + + + + blade + com.bladejava + 1.0 + + 4.0.0 + + blade-sample + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + com.bladejava + blade-core + 1.7.0-alpha + + + com.bladejava + blade-embed-jetty + 0.0.6 + + + + \ No newline at end of file diff --git a/blade-sample/src/main/java/com/xxx/hello/Application.java b/blade-sample/src/main/java/com/xxx/hello/Application.java new file mode 100644 index 000000000..80849e7a0 --- /dev/null +++ b/blade-sample/src/main/java/com/xxx/hello/Application.java @@ -0,0 +1,37 @@ +package com.xxx.hello; + +import com.blade.Const; +import com.blade.kit.json.JSONObject; +import com.blade.mvc.multipart.FileItem; +import com.blade.mvc.view.RestResponse; + +import static com.blade.Blade.$; + +/** + * Created by biezhi on 2016/12/17. + */ +public class Application { + + public static void main(String[] args) { + + $().get("/", (request, response) -> { + + RestResponse restResponse = new RestResponse<>(); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("name", "blade"); + jsonObject.put("version", Const.VERSION); + restResponse.setPayload(jsonObject); + response.json(restResponse); + + }).get("/hello", (request, response) -> { + + FileItem name = request.fileItem("asas"); + + System.out.println(name); +// response.text("hello blade"); + response.render("aa.html"); + + }).start(Application.class); + } + +} diff --git a/blade-sample/src/main/resources/log4j.properties b/blade-sample/src/main/resources/log4j.properties new file mode 100644 index 000000000..4ed357e98 --- /dev/null +++ b/blade-sample/src/main/resources/log4j.properties @@ -0,0 +1,4 @@ +log4j.rootLogger=info, stdout, R +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=[blade-sample] %d %-5p [%t] %c | %m%n diff --git a/pom.xml b/pom.xml index 48c9ffcc7..a49470feb 100644 --- a/pom.xml +++ b/pom.xml @@ -45,22 +45,19 @@
- 1.6 - 1.6 + 1.8 + 1.8 UTF-8 - 3.1.0 4.12 2.0.2-beta 1.7.21 1.7.21 - - 1.6.7-beta - 1.3.4 + 1.7.0-alpha + 1.4.0-alpha 1.0.0 0.0.6 9.2.12.v20150709 - @@ -71,7 +68,8 @@ blade-aop blade-starter blade-websocket-jetty - + blade-sample + From 556d869020f21845a4ae4ba7e06082355b9624b8 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 17 Dec 2016 17:12:09 +0800 Subject: [PATCH 530/545] => upgrade jdk version to 8 --- blade-core/src/main/java/com/blade/Blade.java | 22 +++--- blade-core/src/main/java/com/blade/Const.java | 5 -- .../com/blade/kit/AbortPolicyWithReport.java | 23 ++++++ .../java/com/blade/kit/BladeThreadPool.java | 20 ++++++ .../com/blade/kit/NamedThreadFactory.java | 43 ++++++++++++ .../java/com/blade/mvc/DispatcherHandler.java | 56 +++++++-------- .../java/com/blade/mvc/StaticFileFilter.java | 9 ++- .../MultipartHandler.java | 4 +- .../mvc/{route => handler}/RouteHandler.java | 5 +- .../mvc/http/wrapper/ServletRequest.java | 2 +- .../mvc/http/wrapper/ServletResponse.java | 2 - .../com/blade/mvc/multipart/Multipart.java | 1 + .../java/com/blade/mvc/route/RouteGroup.java | 1 + .../com/blade/mvc/route/RouteMatcher.java | 70 ++++++++----------- .../java/com/blade/mvc/route/Routers.java | 38 +++++----- blade-sample/pom.xml | 2 +- .../main/java/com/xxx/hello/Application.java | 11 +-- pom.xml | 6 +- 18 files changed, 190 insertions(+), 130 deletions(-) create mode 100644 blade-core/src/main/java/com/blade/kit/AbortPolicyWithReport.java create mode 100644 blade-core/src/main/java/com/blade/kit/BladeThreadPool.java create mode 100644 blade-core/src/main/java/com/blade/kit/NamedThreadFactory.java rename blade-core/src/main/java/com/blade/mvc/{multipart => handler}/MultipartHandler.java (92%) rename blade-core/src/main/java/com/blade/mvc/{route => handler}/RouteHandler.java (89%) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index d3735bf48..6383a07e1 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -24,6 +24,7 @@ import com.blade.kit.CollectionKit; import com.blade.kit.StringKit; import com.blade.kit.base.Config; +import com.blade.mvc.handler.RouteHandler; import com.blade.mvc.http.HttpMethod; import com.blade.mvc.interceptor.Interceptor; import com.blade.mvc.route.*; @@ -34,7 +35,9 @@ import javax.servlet.http.HttpServlet; import java.io.InputStream; import java.text.ParseException; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Blade Core Class @@ -74,11 +77,6 @@ public final class Blade { */ private int port = Const.DEFAULT_PORT; - /** - * Web context path - */ - private String contextPath = Const.DEFAULT_CONTEXTPATH; - /** * Is enabled server */ @@ -530,13 +528,17 @@ public Blade listen(int port) { * * @param applicationClass your app root package starter */ - public EmbedServer start(Class applicationClass) { - startNoJoin(applicationClass); + public EmbedServer start(Class applicationClass, String contextPath) { + startNoJoin(applicationClass, contextPath); embedServer.join(); return embedServer; } - - public EmbedServer startNoJoin(Class applicationClass) { + + public EmbedServer start(Class applicationClass) { + return start(applicationClass, "/"); + } + + public EmbedServer startNoJoin(Class applicationClass, String contextPath) { this.loadAppConf(Const.APP_PROPERTIES); diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 20aa9a842..0cbae7429 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -32,11 +32,6 @@ public interface Const { */ String VERSION = "1.7.0-alpha"; - /** - * default embedd server context path - */ - String DEFAULT_CONTEXTPATH = "/"; - /** * server 500 error HTML */ diff --git a/blade-core/src/main/java/com/blade/kit/AbortPolicyWithReport.java b/blade-core/src/main/java/com/blade/kit/AbortPolicyWithReport.java new file mode 100644 index 000000000..3b5ddcbad --- /dev/null +++ b/blade-core/src/main/java/com/blade/kit/AbortPolicyWithReport.java @@ -0,0 +1,23 @@ +package com.blade.kit; + +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadPoolExecutor; + +public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy { + + private final String threadName; + + public AbortPolicyWithReport(String threadName) { + this.threadName = threadName; + } + + public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { + String msg = String.format("Blade[" + + " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d)," + + " Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s)]", + threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(), e.getLargestPoolSize(), + e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminating()); + System.out.println(msg); + throw new RejectedExecutionException(msg); + } +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/kit/BladeThreadPool.java b/blade-core/src/main/java/com/blade/kit/BladeThreadPool.java new file mode 100644 index 000000000..89f54a2d8 --- /dev/null +++ b/blade-core/src/main/java/com/blade/kit/BladeThreadPool.java @@ -0,0 +1,20 @@ +package com.blade.kit; + +import java.util.concurrent.*; + +public class BladeThreadPool { + + public static Executor getExecutor(int threads, int queues) { + return getThreadPoolExecutor(threads, queues); + } + + public static ThreadPoolExecutor getThreadPoolExecutor(int threads, int queues) { + String name = "blade-pool"; + return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS, + queues == 0 ? new SynchronousQueue() + : (queues < 0 ? new LinkedBlockingQueue() + : new LinkedBlockingQueue(queues)), + new NamedThreadFactory(name, true), new AbortPolicyWithReport(name)); + } + +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/kit/NamedThreadFactory.java b/blade-core/src/main/java/com/blade/kit/NamedThreadFactory.java new file mode 100644 index 000000000..6195170a3 --- /dev/null +++ b/blade-core/src/main/java/com/blade/kit/NamedThreadFactory.java @@ -0,0 +1,43 @@ +package com.blade.kit; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +public class NamedThreadFactory implements ThreadFactory { + + private static final AtomicInteger threadNumber = new AtomicInteger(1); + + private final AtomicInteger mThreadNum = new AtomicInteger(1); + + private final String prefix; + + private final boolean daemoThread; + + private final ThreadGroup threadGroup; + + public NamedThreadFactory() { + this("blade-threadpool-" + threadNumber.getAndIncrement(), false); + } + + public NamedThreadFactory(String prefix) { + this(prefix, false); + } + + public NamedThreadFactory(String prefix, boolean daemo) { + this.prefix = prefix + "-thread-"; + daemoThread = daemo; + SecurityManager s = System.getSecurityManager(); + threadGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup(); + } + + public Thread newThread(Runnable runnable) { + String name = prefix + mThreadNum.getAndIncrement(); + Thread ret = new Thread(threadGroup, runnable, name, 0); + ret.setDaemon(daemoThread); + return ret; + } + + public ThreadGroup getThreadGroup() { + return threadGroup; + } +} \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index 4b4b78a9c..00e4b5f5a 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -15,23 +15,13 @@ */ package com.blade.mvc; -import java.io.IOException; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.Blade; import com.blade.Const; import com.blade.context.WebContextHolder; -import com.blade.exception.BladeException; import com.blade.ioc.Ioc; import com.blade.kit.DispatchKit; import com.blade.kit.StringKit; +import com.blade.mvc.handler.RouteHandler; import com.blade.mvc.http.HttpStatus; import com.blade.mvc.http.Path; import com.blade.mvc.http.Request; @@ -39,13 +29,20 @@ import com.blade.mvc.http.wrapper.ServletRequest; import com.blade.mvc.http.wrapper.ServletResponse; import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteHandler; import com.blade.mvc.route.RouteMatcher; import com.blade.mvc.route.Routers; import com.blade.mvc.view.ModelAndView; import com.blade.mvc.view.ViewSettings; import com.blade.mvc.view.resolve.RouteViewResolve; import com.blade.mvc.view.template.TemplateException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; /** * Synchronous request processor @@ -79,25 +76,24 @@ public DispatcherHandler(ServletContext servletContext, Routers routers) { } public void handle(HttpServletRequest httpRequest, HttpServletResponse httpResponse) { - - // http method, GET/POST ... - String method = httpRequest.getMethod(); - - // reuqest uri - String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); - - // Create Response - Response response = new ServletResponse(httpResponse);; - - // If it is static, the resource is handed over to the filter - if(staticFileFilter.isStatic(uri)){ - LOGGER.debug("Request : {}\t{}", method, uri); - DispatchKit.printStatic(uri, httpRequest, response); - return; - } - + // Create Response + Response response = new ServletResponse(httpResponse); + try { - + + // http method, GET/POST ... + String method = httpRequest.getMethod(); + + // reuqest uri + String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath()); + + // If it is static, the resource is handed over to the filter + if(staticFileFilter.isStatic(uri)){ + LOGGER.debug("Request : {}\t{}", method, uri); + DispatchKit.printStatic(uri, httpRequest, response); + return; + } + LOGGER.info("Request : {}\t{}", method, uri); Request request = new ServletRequest(httpRequest); diff --git a/blade-core/src/main/java/com/blade/mvc/StaticFileFilter.java b/blade-core/src/main/java/com/blade/mvc/StaticFileFilter.java index 5a383b54d..8b72d5daa 100644 --- a/blade-core/src/main/java/com/blade/mvc/StaticFileFilter.java +++ b/blade-core/src/main/java/com/blade/mvc/StaticFileFilter.java @@ -15,7 +15,8 @@ */ package com.blade.mvc; -import java.util.HashMap; +import com.blade.kit.CollectionKit; + import java.util.Map; import java.util.Set; @@ -26,7 +27,7 @@ public class StaticFileFilter { public StaticFileFilter(Set prefixList) { this.prefixList = prefixList; - this.cache = new HashMap(128); + this.cache = CollectionKit.newHashMap(128); } public boolean isStatic(String path){ @@ -36,7 +37,7 @@ public boolean isStatic(String path){ return found == Boolean.TRUE; } } - + for(String prefix : prefixList){ if(path.startsWith(prefix)){ if (cache != null) { @@ -45,11 +46,9 @@ public boolean isStatic(String path){ return true; } } - if (cache != null) { cache.put(path, Boolean.FALSE); } - return false; } diff --git a/blade-core/src/main/java/com/blade/mvc/multipart/MultipartHandler.java b/blade-core/src/main/java/com/blade/mvc/handler/MultipartHandler.java similarity index 92% rename from blade-core/src/main/java/com/blade/mvc/multipart/MultipartHandler.java rename to blade-core/src/main/java/com/blade/mvc/handler/MultipartHandler.java index 0cb021e1d..ededf20c9 100644 --- a/blade-core/src/main/java/com/blade/mvc/multipart/MultipartHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/handler/MultipartHandler.java @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.mvc.multipart; +package com.blade.mvc.handler; + +import com.blade.mvc.multipart.FileItem; /** * MultipartHandler diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteHandler.java b/blade-core/src/main/java/com/blade/mvc/handler/RouteHandler.java similarity index 89% rename from blade-core/src/main/java/com/blade/mvc/route/RouteHandler.java rename to blade-core/src/main/java/com/blade/mvc/handler/RouteHandler.java index ccbb00031..f6bb27643 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/handler/RouteHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.mvc.route; +package com.blade.mvc.handler; import com.blade.mvc.http.Request; import com.blade.mvc.http.Response; @@ -24,8 +24,9 @@ * @author biezhi * @since 1.5 */ +@FunctionalInterface public interface RouteHandler { - public void handle(Request request, Response response); + void handle(Request request, Response response); } diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java index a2493a0c7..5b74830c5 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java @@ -26,7 +26,7 @@ import com.blade.mvc.multipart.FileItem; import com.blade.mvc.multipart.Multipart; import com.blade.mvc.multipart.MultipartException; -import com.blade.mvc.multipart.MultipartHandler; +import com.blade.mvc.handler.MultipartHandler; import com.blade.mvc.route.Route; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java index 3128f7222..0b512c72b 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletResponse.java @@ -273,7 +273,6 @@ public PrintWriter writer() throws IOException { @Override public Response render(String view) { - Assert.notBlank(view, "view not is null"); String viewPath = Path.cleanPath(view); ModelAndView modelAndView = new ModelAndView(viewPath); try { @@ -286,7 +285,6 @@ public Response render(String view) { @Override public Response render(ModelAndView modelAndView) { - Assert.notNull(modelAndView, "ModelAndView not is null!"); Assert.notBlank(modelAndView.getView(), "view not is null"); String viewPath = Path.cleanPath(modelAndView.getView()); diff --git a/blade-core/src/main/java/com/blade/mvc/multipart/Multipart.java b/blade-core/src/main/java/com/blade/mvc/multipart/Multipart.java index a8a669986..cb8ee5d34 100644 --- a/blade-core/src/main/java/com/blade/mvc/multipart/Multipart.java +++ b/blade-core/src/main/java/com/blade/mvc/multipart/Multipart.java @@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest; import com.blade.kit.IOKit; +import com.blade.mvc.handler.MultipartHandler; /** * Multipart diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteGroup.java b/blade-core/src/main/java/com/blade/mvc/route/RouteGroup.java index 8f0939e68..7369f94a2 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteGroup.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteGroup.java @@ -16,6 +16,7 @@ package com.blade.mvc.route; import com.blade.Blade; +import com.blade.mvc.handler.RouteHandler; /** * Route Group. diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java index 55ab88741..4e4f4840d 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java @@ -15,20 +15,15 @@ */ package com.blade.mvc.route; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Set; - +import com.blade.kit.CollectionKit; import com.blade.kit.StringKit; import com.blade.mvc.http.HttpMethod; import com.blade.mvc.http.Path; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; + /** * Default Route Matcher * @@ -45,14 +40,15 @@ public class RouteMatcher { // Storage Map Key private Set routeKeys = null; - private List interceptorRoutes = new ArrayList(8); + + private List interceptorRoutes = CollectionKit.newArrayList(8); public RouteMatcher(Routers routers) { this.routes = routers.getRoutes(); this.interceptors = routers.getInterceptors(); this.routeKeys = routes.keySet(); Collection inters = interceptors.values(); - if (null != inters && !inters.isEmpty()) { + if (!inters.isEmpty()) { this.interceptorRoutes.addAll(inters); } } @@ -67,27 +63,28 @@ public Route getRoute(String httpMethod, String path) { String cleanPath = parsePath(path); String routeKey = path + '#' + httpMethod.toUpperCase(); - Route route = routes.get(routeKey); - if(null != route){ - return route; + final Route[] route = {routes.get(routeKey)}; + if(null != route[0]){ + return route[0]; } - route = routes.get(path + "#ALL"); - if(null != route){ - return route; + route[0] = routes.get(path + "#ALL"); + if(null != route[0]){ + return route[0]; } - List matchRoutes = new ArrayList(6); - for(String key : routeKeys){ + List matchRoutes = CollectionKit.newArrayList(); + + routeKeys.forEach(key -> { String[] keyArr = StringKit.split(key, '#'); HttpMethod routeMethod = HttpMethod.valueOf(keyArr[1]); if (matchesPath(keyArr[0], cleanPath)) { if (routeMethod == HttpMethod.ALL || HttpMethod.valueOf(httpMethod) == routeMethod) { - route = routes.get(key); - matchRoutes.add(route); + route[0] = routes.get(key); + matchRoutes.add(route[0]); } } - } - + }); + // Priority matching principle this.giveMatch(path, matchRoutes); @@ -100,14 +97,13 @@ public Route getRoute(String httpMethod, String path) { * @return return interceptor list */ public List getBefore(String path) { - List befores = new ArrayList(8); + List befores = CollectionKit.newArrayList(); String cleanPath = parsePath(path); - for (int i = 0, len = interceptorRoutes.size(); i < len; i++) { - Route route = interceptorRoutes.get(i); + interceptorRoutes.forEach(route -> { if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.BEFORE){ befores.add(route); } - } + }); this.giveMatch(path, befores); return befores; } @@ -118,14 +114,13 @@ public List getBefore(String path) { * @return return interceptor list */ public List getAfter(String path) { - List afters = new ArrayList(8); + List afters = CollectionKit.newArrayList(); String cleanPath = parsePath(path); - for (int i = 0, len = interceptorRoutes.size(); i < len; i++) { - Route route = interceptorRoutes.get(i); + interceptorRoutes.forEach(route -> { if(matchesPath(route.getPath(), cleanPath) && route.getHttpMethod() == HttpMethod.AFTER){ afters.add(route); } - } + }); this.giveMatch(path, afters); return afters; } @@ -136,14 +131,11 @@ public List getAfter(String path) { * @param routes route list */ private void giveMatch(final String uri, List routes) { - Collections.sort(routes, new Comparator() { - @Override - public int compare(Route o1, Route o2) { - if(o2.getPath().equals(uri)){ - return o2.getPath().indexOf(uri); - } - return -1; + Collections.sort(routes, (o1, o2) -> { + if(o2.getPath().equals(uri)){ + return o2.getPath().indexOf(uri); } + return -1; }); } diff --git a/blade-core/src/main/java/com/blade/mvc/route/Routers.java b/blade-core/src/main/java/com/blade/mvc/route/Routers.java index 77b520fbb..4f9e74315 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/Routers.java +++ b/blade-core/src/main/java/com/blade/mvc/route/Routers.java @@ -20,6 +20,9 @@ import java.util.List; import java.util.Map; +import com.blade.exception.BladeException; +import com.blade.kit.CollectionKit; +import com.blade.mvc.handler.RouteHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -82,8 +85,8 @@ public void addRoute(Route route) { public void addRoutes(List routes) { Assert.notNull(routes); - for (int i = 0, len = routes.size(); i < len; i++) { - this.addRoute(routes.get(i)); + for (Route route : routes) { + this.addRoute(route); } } @@ -95,10 +98,8 @@ public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, S public void addRoute(HttpMethod httpMethod, String path, Object controller, Class controllerType, Method method) { - Assert.notNull(httpMethod); Assert.notBlank(path); - Assert.notNull(method); - + String key = path + "#" + httpMethod.toString(); // existent if (null != this.routes.get(key)) { @@ -123,17 +124,17 @@ public void route(String path, RouteHandler handler, HttpMethod httpMethod) { try { addRoute(httpMethod, path, handler, METHOD_NAME); } catch (NoSuchMethodException e) { - throw new RuntimeException(e); + throw new BladeException(e); } } public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) { - for (int i = 0, len = paths.length; i < len; i++) { - route(paths[i], handler, httpMethod); + for (String path : paths) { + route(path, handler, httpMethod); } } - private Map classMethosPool = new HashMap(8); + private Map classMethosPool = CollectionKit.newHashMap(8); public void route(String path, Class clazz, String methodName) { @@ -142,7 +143,7 @@ public void route(String path, Class clazz, String methodName) { Assert.notNull(methodName, "Method name not is null"); HttpMethod httpMethod = HttpMethod.ALL; - if(methodName.indexOf(":") != -1){ + if(methodName.contains(":")){ String[] methodArr = methodName.split(":"); httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase()); methodName = methodArr[1]; @@ -155,19 +156,14 @@ public void route(String path, Class clazz, String methodName) { classMethosPool.put(clazz.getName(), methods); } if(null != methods){ - for (int i = 0, len = methods.length; i < len; i++) { - Method method = methods[i]; + for (Method method : methods) { if (method.getName().equals(methodName)) { addRoute(httpMethod, path, ReflectKit.newInstance(clazz), clazz, method); } } } - } catch (SecurityException e) { - LOGGER.error(e.getMessage(), e); - } catch (InstantiationException e) { - LOGGER.error(e.getMessage(), e); - } catch (IllegalAccessException e) { - LOGGER.error(e.getMessage(), e); + } catch (Exception e) { + LOGGER.error("", e); } } @@ -179,10 +175,8 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt Assert.notNull(httpMethod, "Request Method not is null"); Method method = clazz.getMethod(methodName, Request.class, Response.class); addRoute(httpMethod, path, null, clazz, method); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); + } catch (Exception e) { + LOGGER.error("", e); } } diff --git a/blade-sample/pom.xml b/blade-sample/pom.xml index 44696a6da..729fb3fbb 100644 --- a/blade-sample/pom.xml +++ b/blade-sample/pom.xml @@ -32,7 +32,7 @@ com.bladejava blade-embed-jetty - 0.0.6 + 0.0.7 diff --git a/blade-sample/src/main/java/com/xxx/hello/Application.java b/blade-sample/src/main/java/com/xxx/hello/Application.java index 80849e7a0..86dbcbe0a 100644 --- a/blade-sample/src/main/java/com/xxx/hello/Application.java +++ b/blade-sample/src/main/java/com/xxx/hello/Application.java @@ -2,7 +2,6 @@ import com.blade.Const; import com.blade.kit.json.JSONObject; -import com.blade.mvc.multipart.FileItem; import com.blade.mvc.view.RestResponse; import static com.blade.Blade.$; @@ -23,14 +22,8 @@ public static void main(String[] args) { restResponse.setPayload(jsonObject); response.json(restResponse); - }).get("/hello", (request, response) -> { - - FileItem name = request.fileItem("asas"); - - System.out.println(name); -// response.text("hello blade"); - response.render("aa.html"); - + }).get("/hello", (req, res)->{ + System.out.println(""); }).start(Application.class); } diff --git a/pom.xml b/pom.xml index a49470feb..4713a16fa 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,7 @@ 1.7.0-alpha 1.4.0-alpha 1.0.0 - 0.0.6 + 0.0.7 9.2.12.v20150709 @@ -106,8 +106,8 @@ maven-compiler-plugin 3.1 - 1.6 - 1.6 + 1.8 + 1.8 UTF-8 From 7a52407035a172f998cd3f6eaf76c7f3529c1c6b Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 17 Dec 2016 17:12:36 +0800 Subject: [PATCH 531/545] => modify default thread pool name --- .../com/blade/embedd/EmbedJettyServer.java | 47 +++++++++---------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index 33a559e08..b552670c3 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -1,21 +1,13 @@ package com.blade.embedd; -import static com.blade.Blade.$; - -import java.util.EnumSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import javax.servlet.DispatcherType; -import javax.servlet.Filter; -import javax.servlet.http.HttpServlet; - -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; +import com.blade.Blade; +import com.blade.Const; +import com.blade.context.WebContextListener; +import com.blade.exception.EmbedServerException; +import com.blade.kit.CollectionKit; +import com.blade.kit.base.Config; +import com.blade.mvc.DispatcherServlet; +import org.eclipse.jetty.server.*; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.servlet.ServletHolder; @@ -24,13 +16,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.blade.Blade; -import com.blade.Const; -import com.blade.context.WebContextListener; -import com.blade.exception.EmbedServerException; -import com.blade.kit.CollectionKit; -import com.blade.kit.base.Config; -import com.blade.mvc.DispatcherServlet; +import javax.servlet.DispatcherType; +import javax.servlet.Filter; +import javax.servlet.http.HttpServlet; +import java.util.EnumSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import static com.blade.Blade.$; public class EmbedJettyServer implements EmbedServer { @@ -53,7 +47,7 @@ public EmbedJettyServer() { @Override public void startup(int port) throws EmbedServerException { - this.startup(port, Const.DEFAULT_CONTEXTPATH, null); + this.startup(port, "/", null); } @Override @@ -73,11 +67,12 @@ public void startup(int port, String contextPath, String webRoot) throws EmbedSe // Setup Threadpool QueuedThreadPool threadPool = new QueuedThreadPool(); - int minThreads = config.getInt("server.jetty.min-threads", 100); - int maxThreads = config.getInt("server.jetty.max-threads", 500); + int minThreads = config.getInt("server.jetty.min-threads", 10); + int maxThreads = config.getInt("server.jetty.max-threads", 100); threadPool.setMinThreads(minThreads); threadPool.setMaxThreads(maxThreads); + threadPool.setName("blade-pool"); server = new org.eclipse.jetty.server.Server(threadPool); From 89eb63300b5815d917f6ef196ded851b0e78ed84 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 17 Dec 2016 17:29:11 +0800 Subject: [PATCH 532/545] => add template --- README.md | 10 +++++----- README_CN.md | 10 +++++----- blade-sample/pom.xml | 9 +++++++-- .../src/main/java/com/xxx/hello/Application.java | 12 ++++++++++-- blade-sample/src/main/resources/templates/hello.vm | 12 ++++++++++++ 5 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 blade-sample/src/main/resources/templates/hello.vm diff --git a/README.md b/README.md index a9c2c8f7d..d6b455bb3 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ If you like it, please [star](https://github.com/biezhi/blade/stargazers) / [for * [x] RESTful style routing interface * [x] Template engine support * [x] Run with jar file -* [x] Supports JDK 1.6 and up (java8 is cool) +* [x] JDK8+ ## Overview @@ -38,18 +38,18 @@ Grab via `Maven`: com.bladejava blade-core - 1.6.7-beta + 1.7.0-alpha com.bladejava blade-embed-jetty - 0.0.6 + 0.0.7 ``` or `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.7-beta' -compile 'com.bladejava:blade-embed-jetty:0.0.6' +compile 'com.bladejava:blade-core:1.7.0-alpha' +compile 'com.bladejava:blade-embed-jetty:0.0.7' ``` Create `Main` method like this: diff --git a/README_CN.md b/README_CN.md index 715429c6c..64d87f449 100644 --- a/README_CN.md +++ b/README_CN.md @@ -21,7 +21,7 @@ Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁 * [x] Restful风格的路由接口 * [x] 多种模板引擎支持 * [x] 支持以jar文件发布运行 -* [x] 支持JDK1.6或者更高版本(JDK8写起来更爽) +* [x] JDK8以上 ## 概述 @@ -39,20 +39,20 @@ Blade 是一款轻量级的MVC框架, 重新定义JavaWeb开发,它拥有简洁 com.bladejava blade-core - 1.6.7-beta + 1.7.0-alpha com.bladejava blade-embed-jetty - 0.0.6 + 0.0.7 ``` 或者 `Gradle`: ```sh -compile 'com.bladejava:blade-core:1.6.7-beta' -compile 'com.bladejava:blade-embed-jetty:0.0.6' +compile 'com.bladejava:blade-core:1.7.0-alpha' +compile 'com.bladejava:blade-embed-jetty:0.0.7' ``` 编写 `Main`函数: diff --git a/blade-sample/pom.xml b/blade-sample/pom.xml index 729fb3fbb..f94b70b11 100644 --- a/blade-sample/pom.xml +++ b/blade-sample/pom.xml @@ -27,12 +27,17 @@ com.bladejava blade-core - 1.7.0-alpha + ${blade-core.version} com.bladejava blade-embed-jetty - 0.0.7 + ${blade-embed-jetty.version} + + + com.bladejava + blade-template-velocity + 0.0.4 diff --git a/blade-sample/src/main/java/com/xxx/hello/Application.java b/blade-sample/src/main/java/com/xxx/hello/Application.java index 86dbcbe0a..f77054ffe 100644 --- a/blade-sample/src/main/java/com/xxx/hello/Application.java +++ b/blade-sample/src/main/java/com/xxx/hello/Application.java @@ -3,6 +3,8 @@ import com.blade.Const; import com.blade.kit.json.JSONObject; import com.blade.mvc.view.RestResponse; +import com.blade.mvc.view.ViewSettings; +import com.blade.mvc.view.template.VelocityTemplateEngine; import static com.blade.Blade.$; @@ -13,6 +15,9 @@ public class Application { public static void main(String[] args) { + // setting default template engine is velocity :) + ViewSettings.$().templateEngine(new VelocityTemplateEngine()); + $().get("/", (request, response) -> { RestResponse restResponse = new RestResponse<>(); @@ -22,8 +27,11 @@ public static void main(String[] args) { restResponse.setPayload(jsonObject); response.json(restResponse); - }).get("/hello", (req, res)->{ - System.out.println(""); + }).get("/hello", (request, response)-> { + + request.attribute("name", "boy"); + response.render("hello.vm"); + }).start(Application.class); } diff --git a/blade-sample/src/main/resources/templates/hello.vm b/blade-sample/src/main/resources/templates/hello.vm new file mode 100644 index 000000000..e8283c602 --- /dev/null +++ b/blade-sample/src/main/resources/templates/hello.vm @@ -0,0 +1,12 @@ + + + + + Hello Page + + + +

Hi ${name}!

+ + + \ No newline at end of file From dc5590dc30b62c168573a4b469bde873b59c8003 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sat, 17 Dec 2016 18:06:28 +0800 Subject: [PATCH 533/545] => fix config server port --- blade-core/src/main/java/com/blade/Blade.java | 14 ++--- .../mvc/view/resolve/RouteViewResolve.java | 52 ++++++++++--------- .../main/java/com/blade/kit/base/Config.java | 18 +++---- 3 files changed, 41 insertions(+), 43 deletions(-) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 6383a07e1..4bcdbea94 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -72,11 +72,6 @@ public final class Blade { */ private RouteBuilder routeBuilder; - /** - * Web server startup port - */ - private int port = Const.DEFAULT_PORT; - /** * Is enabled server */ @@ -519,7 +514,7 @@ public Blade isDev(boolean isDev) { * @return return blade */ public Blade listen(int port) { - this.port = port; + config().put("server.port", port); return this; } @@ -556,7 +551,7 @@ public EmbedServer startNoJoin(Class applicationClass, String contextPath) { } if(null != embedClazz){ this.embedServer = (EmbedServer) embedClazz.newInstance(); - this.embedServer.startup(port, contextPath); + this.embedServer.startup(config().getInt("server.port", Const.DEFAULT_PORT), contextPath); this.enableServer = true; } else { throw new EmbedServerException("Not found EmbedServer"); @@ -577,10 +572,15 @@ public EmbedServer embedServer() { /** * @return Return blade config object */ + @Deprecated public Configuration applicationConfig() { return configuration; } + public Configuration configuration() { + return configuration; + } + /** * @return Return blade config object */ diff --git a/blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java b/blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java index 382d03fd5..f615812c1 100644 --- a/blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java +++ b/blade-core/src/main/java/com/blade/mvc/view/resolve/RouteViewResolve.java @@ -38,32 +38,36 @@ public RouteViewResolve(Ioc ioc) { } public void handle(Request request, Response response, Route route) throws Exception { - Method actionMethod = route.getAction(); - Object target = route.getTarget(); - - int len = actionMethod.getParameterTypes().length; - Object returnParam; - if (len > 0) { - Object[] args = MethodArgument.getArgs(request, response, actionMethod); - returnParam = ReflectKit.invokeMehod(target, actionMethod, args); - } else { - returnParam = ReflectKit.invokeMehod(target, actionMethod); - } - - if (null != returnParam) { - Class returnType = returnParam.getClass(); - RestController restController = target.getClass().getAnnotation(RestController.class); - JSON json = actionMethod.getAnnotation(JSON.class); - if(null != restController || null != json){ - response.json(viewSettings.toJSONString(returnParam)); - } else{ - if (returnType == String.class) { - response.render(returnParam.toString()); - } else if (returnType == ModelAndView.class) { - ModelAndView modelAndView = (ModelAndView) returnParam; - response.render(modelAndView); + try { + Method actionMethod = route.getAction(); + Object target = route.getTarget(); + + int len = actionMethod.getParameterTypes().length; + Object returnParam; + if (len > 0) { + Object[] args = MethodArgument.getArgs(request, response, actionMethod); + returnParam = ReflectKit.invokeMehod(target, actionMethod, args); + } else { + returnParam = ReflectKit.invokeMehod(target, actionMethod); + } + + if (null != returnParam) { + Class returnType = returnParam.getClass(); + RestController restController = target.getClass().getAnnotation(RestController.class); + JSON json = actionMethod.getAnnotation(JSON.class); + if(null != restController || null != json){ + response.json(viewSettings.toJSONString(returnParam)); + } else{ + if (returnType == String.class) { + response.render(returnParam.toString()); + } else if (returnType == ModelAndView.class) { + ModelAndView modelAndView = (ModelAndView) returnParam; + response.render(modelAndView); + } } } + } catch (Exception e){ + throw new BladeException(e); } } diff --git a/blade-kit/src/main/java/com/blade/kit/base/Config.java b/blade-kit/src/main/java/com/blade/kit/base/Config.java index 7b1cdd15c..ae1136833 100644 --- a/blade-kit/src/main/java/com/blade/kit/base/Config.java +++ b/blade-kit/src/main/java/com/blade/kit/base/Config.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Properties; +import java.util.concurrent.locks.Condition; import javax.servlet.ServletContext; @@ -36,18 +37,7 @@ public Config load(Properties props) { } return this; } - - /*private String getWildcard(String str) { - if (null != str && str.indexOf("${") != -1) { - int start = str.indexOf("${"); - int end = str.indexOf("}"); - if (start != -1 && end != -1) { - return str.substring(start + 2, end); - } - } - return null; - }*/ - + public Config load(Map map) { config.putAll(map); return this; @@ -240,5 +230,9 @@ public Boolean getBoolean(String key, boolean defaultValue) { return null != getBoolean(key) ? getBoolean(key) : defaultValue; } + public Config put(String key, Object value){ + config.put(key, value.toString()); + return this; + } } From ffed9b7b8374bd3b7bd7423bbfafa0e9aff7df95 Mon Sep 17 00:00:00 2001 From: biezhi Date: Sun, 25 Dec 2016 17:04:56 +0800 Subject: [PATCH 534/545] => fix config order --- blade-core/src/main/java/com/blade/Blade.java | 11 +- blade-core/src/main/java/com/blade/Const.java | 15 ++- .../java/com/blade/config/Configuration.java | 22 ++-- .../route => exception}/RouteException.java | 2 +- .../java/com/blade/ioc/IocApplication.java | 38 +++--- .../java/com/blade/mvc/DispatcherHandler.java | 13 +- .../main/java/com/blade/mvc/route/Route.java | 10 +- .../com/blade/mvc/route/RouteBuilder.java | 118 +++--------------- .../java/com/blade/mvc/route/Routers.java | 30 ++--- .../route/loader/AbstractFileRouteLoader.java | 2 +- .../loader/ClassPathControllerLoader.java | 2 +- .../mvc/route/loader/ControllerLoader.java | 2 +- .../blade/mvc/route/loader/RouteLoader.java | 2 +- blade-starter/pom.xml | 12 +- 14 files changed, 94 insertions(+), 185 deletions(-) rename blade-core/src/main/java/com/blade/{mvc/route => exception}/RouteException.java (97%) diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java index 4bcdbea94..a7e0dcd95 100644 --- a/blade-core/src/main/java/com/blade/Blade.java +++ b/blade-core/src/main/java/com/blade/Blade.java @@ -18,6 +18,7 @@ import com.blade.config.Configuration; import com.blade.embedd.EmbedServer; import com.blade.exception.EmbedServerException; +import com.blade.exception.RouteException; import com.blade.ioc.Ioc; import com.blade.ioc.SimpleIoc; import com.blade.kit.Assert; @@ -514,7 +515,7 @@ public Blade isDev(boolean isDev) { * @return return blade */ public Blade listen(int port) { - config().put("server.port", port); + config().put(Const.SERVER_PORT, port); return this; } @@ -545,13 +546,13 @@ public EmbedServer startNoJoin(Class applicationClass, String contextPath) { } try { - Class embedClazz = Class.forName("com.blade.embedd.EmbedJettyServer"); + Class embedClazz = Class.forName(Const.JETTY_SERVER_CLASS); if(null == embedClazz){ - embedClazz = Class.forName("com.blade.embedd.EmbedTomcatServer"); + embedClazz = Class.forName(Const.TOMCAT_SERVER_CLASS); } if(null != embedClazz){ this.embedServer = (EmbedServer) embedClazz.newInstance(); - this.embedServer.startup(config().getInt("server.port", Const.DEFAULT_PORT), contextPath); + this.embedServer.startup(config().getInt(Const.SERVER_PORT, Const.DEFAULT_PORT), contextPath); this.enableServer = true; } else { throw new EmbedServerException("Not found EmbedServer"); @@ -630,7 +631,7 @@ public Blade plugin(Class plugin) { * @return return blade */ public Blade routeConf(String basePackage) { - return routeConf(basePackage, "route.conf"); + return routeConf(basePackage, Const.DEFAULT_ROUTE_CONF); } /** diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index 0cbae7429..f95edb6a4 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -47,6 +47,10 @@ public interface Const { */ int DEFAULT_PORT = 9000; + String DEFAULT_ENCODING = "UTF-8"; + + String DEFAULT_ROUTE_CONF = "route.conf"; + /**** package names ****/ String ROUTE_PKGS = "route_packages"; String IOC_PKGS = "ioc_packages"; @@ -64,5 +68,14 @@ public interface Const { String BLADE_VIEW_500 = "blade.view500"; String BLADE_DEV = "blade.dev"; String APP_PROPERTIES = "app.properties"; - + String SERVER_PORT = "server.port"; + String JETTY_SERVER_CLASS = "com.blade.embedd.EmbedJettyServer"; + String TOMCAT_SERVER_CLASS = "com.blade.embedd.EmbedTomcatServer"; + String MVC_VIEW_404 = "mvc.view.404"; + String MVC_VIEW_500 = "mvc.view.500"; + String HTTP_ENCODING = "http.encoding"; + String MVC_STATICS = "mvc.statics"; + String APP_DEV = "app.dev"; + String APP_IOC = "app.ioc"; + String APP_BASE_PKG = "app.base-package"; } \ No newline at end of file diff --git a/blade-core/src/main/java/com/blade/config/Configuration.java b/blade-core/src/main/java/com/blade/config/Configuration.java index 06de99413..dcedb7119 100644 --- a/blade-core/src/main/java/com/blade/config/Configuration.java +++ b/blade-core/src/main/java/com/blade/config/Configuration.java @@ -43,8 +43,8 @@ public class Configuration { private Packages packages; // Encoding - private String encoding = "utf-8"; - + private String encoding = Const.DEFAULT_ENCODING; + // Is dev mode private boolean isDev = true; @@ -66,26 +66,26 @@ public void setEnv(Config config) { if (null != config && !isInit) { // get dev mode - this.isDev = config.getBoolean("app.dev", true); + this.isDev = config.getBoolean(Const.APP_DEV, true); // get ioc packages - packages.put(Const.IOC_PKGS, config.get("app.ioc")); + packages.put(Const.IOC_PKGS, config.get(Const.APP_IOC)); // get view 404, 500 page - ViewSettings.$().setView500(config.get("mvc.view.500")); - ViewSettings.$().setView404(config.get("mvc.view.404")); + ViewSettings.$().setView500(config.get(Const.MVC_VIEW_500)); + ViewSettings.$().setView404(config.get(Const.MVC_VIEW_404)); // get http encoding - this.encoding = config.get("http.encoding", "UTF-8"); + this.encoding = config.get(Const.HTTP_ENCODING, Const.DEFAULT_ENCODING); // get mvc static folders - String statics = config.get("mvc.statics"); + String statics = config.get(Const.MVC_STATICS); // get app base package - String basePackage = config.get("app.base-package"); + String basePackage = config.get(Const.APP_BASE_PKG); // get server start port - Integer port = config.getInt("server.port", Const.DEFAULT_PORT); + Integer port = config.getInt(Const.SERVER_PORT, Const.DEFAULT_PORT); $().listen(port); if (StringKit.isNotBlank(statics)) { @@ -201,7 +201,7 @@ public void load(String location) { try { config.add(location); } catch (Exception e){ - + System.out.println("[load config] " + e.getMessage()); } } diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteException.java b/blade-core/src/main/java/com/blade/exception/RouteException.java similarity index 97% rename from blade-core/src/main/java/com/blade/mvc/route/RouteException.java rename to blade-core/src/main/java/com/blade/exception/RouteException.java index ff85e4349..085b20312 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteException.java +++ b/blade-core/src/main/java/com/blade/exception/RouteException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.blade.mvc.route; +package com.blade.exception; /** * RouteException diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index c74a045d9..9b4223b06 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -15,22 +15,13 @@ */ package com.blade.ioc; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.Blade; import com.blade.comparator.OrderComparator; import com.blade.config.BaseConfig; import com.blade.context.DynamicContext; import com.blade.ioc.annotation.Component; import com.blade.ioc.annotation.Service; +import com.blade.kit.CollectionKit; import com.blade.kit.StringKit; import com.blade.kit.resource.ClassInfo; import com.blade.kit.resource.ClassReader; @@ -39,6 +30,11 @@ import com.blade.mvc.annotation.RestController; import com.blade.mvc.interceptor.Interceptor; import com.blade.mvc.route.RouteBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Modifier; +import java.util.*; /** * IOC container, used to initialize the IOC object @@ -53,7 +49,7 @@ public final class IocApplication { /** * aop interceptor */ - private static List aopInterceptors = new ArrayList(8); + private static List aopInterceptors = CollectionKit.newArrayList(8); /** * Class to read object, load class @@ -75,9 +71,9 @@ public IocApplication() { * @throws Exception */ private List loadCondigs() throws Exception { - String[] configPkgs = blade.applicationConfig().getConfigPkgs(); + String[] configPkgs = blade.configuration().getConfigPkgs(); if (null != configPkgs && configPkgs.length > 0) { - List configs = new ArrayList(10); + List configs = CollectionKit.newArrayList(10); for (int i = 0, len = configPkgs.length; i < len; i++) { Set configClasses = classReader.getClassByAnnotation(configPkgs[i], Component.class, false); if (null != configClasses) { @@ -101,9 +97,9 @@ private List loadCondigs() throws Exception { } private List loadServices() throws Exception { - String[] iocPkgs = blade.applicationConfig().getIocPkgs(); + String[] iocPkgs = blade.configuration().getIocPkgs(); if (null != iocPkgs && iocPkgs.length > 0) { - List services = new ArrayList(20); + List services = CollectionKit.newArrayList(16); for (int i = 0, len = iocPkgs.length; i < len; i++) { String pkgName = iocPkgs[i]; if (StringKit.isBlank(pkgName)) { @@ -135,9 +131,9 @@ private List loadServices() throws Exception { } private List loadControllers() { - String[] routePkgs = blade.applicationConfig().getRoutePkgs(); + String[] routePkgs = blade.configuration().getRoutePkgs(); if (null != routePkgs && routePkgs.length > 0) { - List controllers = new ArrayList(); + List controllers = CollectionKit.newArrayList(8); for(int i=0, len=routePkgs.length; i loadControllers() { } private List loadInterceptors() { - String interceptorPackage = blade.applicationConfig().getInterceptorPkg(); + String interceptorPackage = blade.configuration().getInterceptorPkg(); if (StringKit.isNotBlank(interceptorPackage)) { - List interceptors = new ArrayList(10); + List interceptors = CollectionKit.newArrayList(8); Set intes = classReader.getClassByAnnotation(interceptorPackage, Intercept.class, true); if (null != intes) { for (ClassInfo classInfo : intes) { @@ -184,7 +180,7 @@ public void initBeans() throws Exception { } } - Set baseConfigs = new HashSet(); + List baseConfigs = CollectionKit.newArrayList(); // 2. init configs if (null != configs) { @@ -224,7 +220,7 @@ public void initBeans() throws Exception { // init configs for(BaseConfig baseConfig : baseConfigs){ - baseConfig.config(blade.applicationConfig()); + baseConfig.config(blade.configuration()); } } diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java index 00e4b5f5a..fbe5da776 100644 --- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java +++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java @@ -50,14 +50,12 @@ * @author biezhi * @since 1.5 */ -public class DispatcherHandler { +class DispatcherHandler { private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherHandler.class); private Ioc ioc; - - private Blade blade; - + private ServletContext servletContext; private RouteMatcher routeMatcher; @@ -68,10 +66,10 @@ public class DispatcherHandler { public DispatcherHandler(ServletContext servletContext, Routers routers) { this.servletContext = servletContext; - this.blade = Blade.$(); + Blade blade = Blade.$(); this.ioc = blade.ioc(); this.routeMatcher = new RouteMatcher(routers); - this.staticFileFilter = new StaticFileFilter(blade.applicationConfig().getResources()); + this.staticFileFilter = new StaticFileFilter(blade.configuration().getResources()); this.routeViewHandler = new RouteViewResolve(this.ioc); } @@ -153,8 +151,7 @@ private void render404(Response response, String uri) throws Exception { * @return Return execute is ok */ private boolean invokeInterceptor(Request request, Response response, List interceptors) throws Exception { - for (int i = 0, len = interceptors.size(); i < len; i++) { - Route route = interceptors.get(i); + for (Route route : interceptors) { boolean flag = routeViewHandler.intercept(request, response, route); if (!flag) { return false; diff --git a/blade-core/src/main/java/com/blade/mvc/route/Route.java b/blade-core/src/main/java/com/blade/mvc/route/Route.java index 64287b4b6..2a9c5a1d5 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/Route.java +++ b/blade-core/src/main/java/com/blade/mvc/route/Route.java @@ -65,14 +65,10 @@ public Route(HttpMethod httpMethod, String path, Object target, Class targetT this.action = action; } - public HttpMethod getHttpMethod() { + HttpMethod getHttpMethod() { return httpMethod; } - public void setHttpMethod(HttpMethod httpMethod) { - this.httpMethod = httpMethod; - } - public String getPath() { return path; } @@ -93,10 +89,6 @@ public Method getAction() { return action; } - public void setAction(Method action) { - this.action = action; - } - public Class getTargetType() { return targetType; } diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java index 4b9708961..7d497aa47 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java +++ b/blade-core/src/main/java/com/blade/mvc/route/RouteBuilder.java @@ -15,20 +15,7 @@ */ package com.blade.mvc.route; -import static com.blade.Blade.$; - -import java.lang.reflect.Method; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.blade.context.DynamicContext; -import com.blade.kit.CollectionKit; -import com.blade.kit.StringKit; import com.blade.kit.reflect.ReflectKit; -import com.blade.kit.resource.ClassInfo; -import com.blade.kit.resource.ClassReader; import com.blade.mvc.annotation.Controller; import com.blade.mvc.annotation.Intercept; import com.blade.mvc.annotation.RestController; @@ -37,6 +24,10 @@ import com.blade.mvc.http.Request; import com.blade.mvc.http.Response; import com.blade.mvc.interceptor.Interceptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; /** * Route builder * @@ -46,86 +37,13 @@ public class RouteBuilder { private static final Logger LOGGER = LoggerFactory.getLogger(RouteBuilder.class); - - /** - * Class reader, used to scan the class specified in the rules - */ - private ClassReader classReader; - - private Routers routers; - - private String[] routePackages; - - private String interceptorPackage; - - public RouteBuilder(Routers routers) { + + private Routers routers; + + public RouteBuilder(Routers routers) { this.routers = routers; - this.classReader = DynamicContext.getClassReader(); } - - /** - * Start building route - */ - public void building() { - - this.routePackages = $().applicationConfig().getRoutePkgs(); - this.interceptorPackage = $().applicationConfig().getInterceptorPkg(); - - // Route - if(null != routePackages && routePackages.length > 0){ - this.buildRoute(routePackages); - } - - // Inteceptor - if(StringKit.isNotBlank(interceptorPackage)){ - this.buildInterceptor(interceptorPackage); - } - - } - - /** - * Build interceptor - * - * @param interceptorPackages add the interceptor package - */ - private void buildInterceptor(String... interceptorPackages){ - - // Scan all Interceptor - Set classes = null; - - // Traversal Interceptor - for(int i=0, len=interceptorPackages.length; i interceptorClazz = classInfo.getClazz(); - addInterceptor(interceptorClazz); - } - } - } - } - - /** - * Build Route - * - * @param routePackages route packets to add - */ - private void buildRoute(String... routePackages){ - Set classes = null; - // Traverse route - for(int i=0,len=routePackages.length; i pathClazz = classInfo.getClazz(); - this.addRouter(pathClazz); - } - } - } - } - + /** * Parse Interceptor * @@ -149,12 +67,9 @@ public void addInterceptor(final Class interceptor){ Method after = interceptor.getMethod("after", Request.class, Response.class); buildInterceptor(partten, interceptor, before, HttpMethod.BEFORE); buildInterceptor(partten, interceptor, after, HttpMethod.AFTER); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); + } catch (Exception e) { + LOGGER.error("", e); } - } /** @@ -180,21 +95,20 @@ public void addRouter(final Class router){ suffix = router.getAnnotation(RestController.class).suffix(); } - if(null == nameSpace && null == suffix){ + if(null == nameSpace){ LOGGER.warn("Route [{}] not controller annotation", router.getName()); return; } - for (int i = 0, len = methods.length; i < len; i++) { - Method method = methods[i]; + for (Method method : methods) { Route mapping = method.getAnnotation(Route.class); //route method if (null != mapping) { // build multiple route HttpMethod methodType = mapping.method(); String[] paths = mapping.value(); - if(null != paths && paths.length > 0){ - for(int j=0, plen = paths.length; j 0) { + for (String path : paths) { + String pathV = getRoutePath(path, nameSpace, suffix); this.buildRoute(router, method, pathV, methodType); } } diff --git a/blade-core/src/main/java/com/blade/mvc/route/Routers.java b/blade-core/src/main/java/com/blade/mvc/route/Routers.java index 4f9e74315..0e164aa72 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/Routers.java +++ b/blade-core/src/main/java/com/blade/mvc/route/Routers.java @@ -15,22 +15,20 @@ */ package com.blade.mvc.route; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import com.blade.exception.BladeException; -import com.blade.kit.CollectionKit; -import com.blade.mvc.handler.RouteHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.kit.Assert; +import com.blade.kit.CollectionKit; import com.blade.kit.reflect.ReflectKit; +import com.blade.mvc.handler.RouteHandler; import com.blade.mvc.http.HttpMethod; import com.blade.mvc.http.Request; import com.blade.mvc.http.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; /** * Registration, management route @@ -49,8 +47,8 @@ public class Routers { private static final String METHOD_NAME = "handle"; public Routers() { - this.routes = new HashMap(); - this.interceptors = new HashMap(); + this.routes = CollectionKit.newHashMap(); + this.interceptors = CollectionKit.newHashMap(); } public Map getRoutes() { @@ -85,9 +83,7 @@ public void addRoute(Route route) { public void addRoutes(List routes) { Assert.notNull(routes); - for (Route route : routes) { - this.addRoute(route); - } + routes.forEach(this::addRoute); } public void addRoute(HttpMethod httpMethod, String path, RouteHandler handler, String methodName) throws NoSuchMethodException { @@ -179,9 +175,9 @@ public void route(String path, Class clazz, String methodName, HttpMethod htt LOGGER.error("", e); } } - + public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) { addRoute(httpMethod, path, null, clazz, method); } - + } diff --git a/blade-core/src/main/java/com/blade/mvc/route/loader/AbstractFileRouteLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/AbstractFileRouteLoader.java index 8bcf82b36..7a2834dea 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/loader/AbstractFileRouteLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/AbstractFileRouteLoader.java @@ -30,7 +30,7 @@ import com.blade.mvc.http.Request; import com.blade.mvc.http.Response; import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteException; +import com.blade.exception.RouteException; /** * Abstract loader implementation diff --git a/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java index 88efa34c1..4cd7427d3 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/ClassPathControllerLoader.java @@ -18,7 +18,7 @@ import com.blade.Blade; import com.blade.ioc.Ioc; import com.blade.kit.StringKit; -import com.blade.mvc.route.RouteException; +import com.blade.exception.RouteException; /** * ClassPath controller of loader diff --git a/blade-core/src/main/java/com/blade/mvc/route/loader/ControllerLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/ControllerLoader.java index 56d2928ad..82ff2a5b8 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/loader/ControllerLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/ControllerLoader.java @@ -15,7 +15,7 @@ */ package com.blade.mvc.route.loader; -import com.blade.mvc.route.RouteException; +import com.blade.exception.RouteException; /** * Controller loading interface diff --git a/blade-core/src/main/java/com/blade/mvc/route/loader/RouteLoader.java b/blade-core/src/main/java/com/blade/mvc/route/loader/RouteLoader.java index 2b57d37a7..be621fd24 100644 --- a/blade-core/src/main/java/com/blade/mvc/route/loader/RouteLoader.java +++ b/blade-core/src/main/java/com/blade/mvc/route/loader/RouteLoader.java @@ -19,7 +19,7 @@ import java.util.List; import com.blade.mvc.route.Route; -import com.blade.mvc.route.RouteException; +import com.blade.exception.RouteException; /** * Route loader diff --git a/blade-starter/pom.xml b/blade-starter/pom.xml index 28e700af4..ca0c41ef4 100644 --- a/blade-starter/pom.xml +++ b/blade-starter/pom.xml @@ -12,18 +12,18 @@ blade-starter pom - 0.0.2 + 0.0.3 UTF-8 - 1.6.7-alpha + 1.7.0-alpha 1.0.0 0.1.3-beta 1.0.4 - 0.0.6 + 0.0.7 0.0.4 - 0.0.6 + 0.0.7 @@ -97,8 +97,8 @@ maven-compiler-plugin 3.2 - 1.6 - 1.6 + 1.8 + 1.8 UTF-8 From f9cc953867cf3f1627d80a9ee9bdb36493055aa3 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 2 Jan 2017 20:28:38 +0800 Subject: [PATCH 535/545] => add jetty http cache --- .../java/com/blade/config/Configuration.java | 2 +- .../java/com/blade/ioc/IocApplication.java | 11 +++++----- .../mvc/http/wrapper/ServletRequest.java | 19 +++--------------- .../com/blade/embedd/EmbedJettyServer.java | 15 +++++++++++--- .../main/java/com/xxx/hello/Application.java | 4 +++- .../src/main/resources/log4j.properties | 2 +- .../src/main/resources/public/avatar.jpeg | Bin 0 -> 12355 bytes .../src/main/resources/static/img/avatar.jpeg | Bin 0 -> 12355 bytes 8 files changed, 26 insertions(+), 27 deletions(-) create mode 100644 blade-sample/src/main/resources/public/avatar.jpeg create mode 100644 blade-sample/src/main/resources/static/img/avatar.jpeg diff --git a/blade-core/src/main/java/com/blade/config/Configuration.java b/blade-core/src/main/java/com/blade/config/Configuration.java index dcedb7119..8cc081a6f 100644 --- a/blade-core/src/main/java/com/blade/config/Configuration.java +++ b/blade-core/src/main/java/com/blade/config/Configuration.java @@ -58,7 +58,7 @@ public class Configuration { public Configuration() { this.packages = new Packages(); - this.addResources("/public", "/assets", "/static"); + this.addResources("/public/*", "/assets/*", "/static/*"); } public void setEnv(Config config) { diff --git a/blade-core/src/main/java/com/blade/ioc/IocApplication.java b/blade-core/src/main/java/com/blade/ioc/IocApplication.java index 9b4223b06..f67a568aa 100644 --- a/blade-core/src/main/java/com/blade/ioc/IocApplication.java +++ b/blade-core/src/main/java/com/blade/ioc/IocApplication.java @@ -209,6 +209,11 @@ public void initBeans() throws Exception { if(null != ioc.getBeans() && !ioc.getBeans().isEmpty()){ LOGGER.info("Add Object: {}", ioc.getBeans()); } + + // init configs + for(BaseConfig baseConfig : baseConfigs){ + baseConfig.config(blade.configuration()); + } // injection List beanDefines = ioc.getBeanDefines(); @@ -217,11 +222,7 @@ public void initBeans() throws Exception { IocKit.injection(ioc, beanDefines.get(i)); } } - - // init configs - for(BaseConfig baseConfig : baseConfigs){ - baseConfig.config(blade.configuration()); - } + } public static List getAopInterceptors() { diff --git a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java index 5b74830c5..2678b660a 100644 --- a/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java +++ b/blade-core/src/main/java/com/blade/mvc/http/wrapper/ServletRequest.java @@ -20,13 +20,13 @@ import com.blade.kit.IOKit; import com.blade.kit.ObjectKit; import com.blade.kit.StringKit; +import com.blade.mvc.handler.MultipartHandler; import com.blade.mvc.http.HttpMethod; import com.blade.mvc.http.Path; import com.blade.mvc.http.Request; import com.blade.mvc.multipart.FileItem; import com.blade.mvc.multipart.Multipart; import com.blade.mvc.multipart.MultipartException; -import com.blade.mvc.handler.MultipartHandler; import com.blade.mvc.route.Route; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -253,25 +253,12 @@ public Map querys() { @Override public String query(String name) { - String[] param = request.getParameterValues(name); - String val; - if (param != null) { - val = join(param); - } else { - val = queryParams.get(name); - } - return val; + return request.getParameter(name); } @Override public String query(String name, String defaultValue) { - String[] param = request.getParameterValues(name); - String val; - if (param != null) { - val = join(param); - } else { - val = queryParams.get(name); - } + String val = this.query(name); if(null == val){ val = defaultValue; } diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java index b552670c3..96473a229 100644 --- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java +++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java @@ -10,6 +10,7 @@ import org.eclipse.jetty.server.*; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerList; +import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.webapp.WebAppContext; @@ -35,13 +36,16 @@ public class EmbedJettyServer implements EmbedServer { private Server server; private WebAppContext webAppContext; - + + private Set staticFolders; + private Config config = null; public EmbedJettyServer() { System.setProperty("org.apache.jasper.compiler.disablejsr199", "true"); $().loadAppConf("jetty.properties"); config = $().config(); + staticFolders = $().configuration().getResources(); $().enableServer(true); } @@ -108,9 +112,14 @@ public void startup(int port, String contextPath, String webRoot) throws EmbedSe servletHolder.setAsyncSupported(false); servletHolder.setInitOrder(1); - webAppContext.addEventListener(new WebContextListener()); + webAppContext.addEventListener(new WebContextListener()); webAppContext.addServlet(servletHolder, "/"); - + + ServletHolder defaultHolder = new ServletHolder(DefaultServlet.class); + for(String s : staticFolders){ + webAppContext.addServlet(defaultHolder, s); + } + try { loadServlets(webAppContext); diff --git a/blade-sample/src/main/java/com/xxx/hello/Application.java b/blade-sample/src/main/java/com/xxx/hello/Application.java index f77054ffe..deeb48c45 100644 --- a/blade-sample/src/main/java/com/xxx/hello/Application.java +++ b/blade-sample/src/main/java/com/xxx/hello/Application.java @@ -29,7 +29,9 @@ public static void main(String[] args) { }).get("/hello", (request, response)-> { - request.attribute("name", "boy"); + String name = request.query("name", "boy"); + + request.attribute("name", name); response.render("hello.vm"); }).start(Application.class); diff --git a/blade-sample/src/main/resources/log4j.properties b/blade-sample/src/main/resources/log4j.properties index 4ed357e98..1061a1743 100644 --- a/blade-sample/src/main/resources/log4j.properties +++ b/blade-sample/src/main/resources/log4j.properties @@ -1,4 +1,4 @@ -log4j.rootLogger=info, stdout, R +log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[blade-sample] %d %-5p [%t] %c | %m%n diff --git a/blade-sample/src/main/resources/public/avatar.jpeg b/blade-sample/src/main/resources/public/avatar.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..e6f4dd4a4ee82995e3a65bc98e5032a19de059f6 GIT binary patch literal 12355 zcmb7qRajg>v*2LCHAn;r7Muiv6FkUZ1A}{l1k2#=fe?bjV8Iz+aEHMmxI2Rm7TgK$ zu>AM#KHUBGW$Sc*{ZK8{b-Jp$tLky~aRor4C6OifCK;`!kQg`_kUN8m)QXyWIYoc!;<@dn)5LiR&ARN(SDH>V&6E5i1~ne+ngw- zZiO6MPO@s~YLxwQ$tZFrII;WMwR&Kc9ISu`eDUTYiwI6Wyx02P%^9-Z^6I*t(ruGZ z>?)R)cL{q%ZA=||-MTD!)xR=UJGaicRSB?`9R6YU5unW$6QsLV#?z8kYnWR`P2##x;eju#Pkcy6D?Eu( zqDF_iyYS#uHVZ(@`CXCHv7zihTrug3^ke$VD5j8WPhAOi@{oyu|G3P1?dh>JuLAYF z((#o`h3{k{tg4ulV&eW86Ej+_BQUg=9|`%ntT#k~zx)_G-M_P1=me;y3y(@AOg$m9+akp-*ko;+*r) z{hO4rRM(e@a*hn=%ubZ@u#@=>MZaRcg_hneQg^|@&}Q9I!nhceTVgz!IPJ0e1K)5A z_GfHmmlxR$qk6VmEXJ+riiR-nVxi!L`!Ds4wuTDGNGasBt#|FHJ)(y+evgPtNsaXq z>O36P=AE_1kQy#}^K&upFi~QMc|@%7FEiLUn#dqhU^ijhMqdg|R`+F}Sn*Vvx|(Q7 zlACT+V!cDQgQ-=j=BHdwc9-aBW3(Frof_*wu>X}e-9}j?#q0P?H|656{irXK0&s#C z1isJ1P87xk>L#T14TSgA{_dRdFJ;F$8-}fBy0DZ?bBsh~B+nbDDOV3k;VV^|7`m>z zU8XWhsDp`Z?_}MRYz$4sOJqcLhXToR9MKx+h4%)TF$(W%ijwC=1BunVNPKO&_&)?4 zYE>&~g~#hpw>ehVHcL@{)<0CNw$aLGuUHJzkI9K@1y>LJyAR6zMg9Y1AuKlG9nIG-Pq;4DIfzuC zQX3Env`KcIMFo}>Ji#d4LgA0}{N4VP`p!R9-q0lsx=cMEgV|QWJT!7$xa;LLdE*w1 z`nNM$ik!hq=K|-u`G}s?1(W)LMBXm5LzcnO#vhEgdGc8_AirFwFMdLS;H2S#JGP;s zR)^+{C+gd}faEQ!wBH^p4Oyn~7Bb;e>PJrtC0(80epl*!C5OdE4f~;0V`q;5JaMK5 zQ>~dW=+6!?N+p6mmw+B)1>aw>I826I+P2E6c473a}XW_^^H%7y{A>%8x4VHB( z)$#v4K$XDjwKm1Fp}rL`8@G{mxz_N~Cn^hOg3giTQ6=9Zf3l=XiCw=!qvj{^2w;=) ztj}IOwWyF*OEZsnZg}IvG{fW+=0iM#ZunVsP7Fl#?R==4Lr&F0&@S!dMt@0fo7cZy zPfUJ6eN<9QyD{w#iUEtQ*)XH0F*Y319J};9ijjJA~H}%RhjLrTZN6{mo zX5K&B%Z86O(Co@jI-q^?%2(8v(8+aX-+;>b&&1hnYOT_DyGbjHTo{0!4UJ7v4uFwG zQGArmf$!S+gUR*!u25(i9*_EhhvSZM!0K9#IT&;rk6+wJ0~J9#E14+WiZfbesu!!Z zeC2nTZ^EXSkie2!CtwSat2M0Oz~a!A#ACafVThU%SaOnT;=pdX{?-8b60k)3Ev7OJ(QRp4W%TE1BDG6`LjAc) zgaUG7a${qpw&igS$RnZD|@ zeiBT@XJ_iN80Zyc0n@grh4zHj2V%~Rt(u!l^8PF7-z017V4p zt5tqX1v;OgK&JIf{Q(>1*3Emui$uI4Msm|I)}r-a|2Z{y9GjtBTpLwMYWZrsxmf7A z(Z9>#!em`fIQ74>4(0PnXG~WSg)w>Q)PoKgS(Y>s>F#7%SvYTkkfeJ`Aq(MMThFYr zW8ZVD&LbjzA2lO*PvMwcpT1{S$!}t@N3Hkhaeg*Xm!+V@GJM*$v`huXY75VSKxpKe zu(e6s*A~PnG{b5XV-{x8H@Viyn3ViE9CHe8Dwu;lV;nfc=jT zy&?OULD=JLtw7A542_8c8RR8@=aJc!?4^@`5mnBzw&(^w1qzKy=U;7vrESS%Y zNtanItV;Ms@Zn`xwKs05cyMvc(-A3x#c0oM!1tdoPVNBVDTdb zEHS|O5%4c}&{&+)|x zK;8Cdts*eP6fe&n|02e#FyOXmK(w)h!F`5im25rbY0|&W;k--Mc5-PCad!!OgeSYO z8xM{I-~Hsnvf@aMW3ZmFwOuXkfaVVhBD0`v34#eT)j@BSVN>NiLp#16yvf6@A$eXX zxj17o9-WLfxnY)CeEe4-4k^ zC6m3fR+41LSHl*I2K6*=>7oeoW@W-%mDE7IB%X49uA()W!IWV^Tz0!+);_I#REe`c z2h~DYvcN6p&yN|&r;fKeqT*(`SaSGP0}-P3KNmLI8>ryI^r~FIEejhCmh$>lug|VD zY)k0t#Wd!I@uu%FO)K>g^ki#QxBg$cu%g={rl(Yn+ovNE(OW-IzW#L+{dqq6AOA&} zaY5|<^vkf91F?NP$LihqiSmMraf2NU=<_HpU%qI^TNGFBLzj8nBfu9_6ej-COJ!KF z1Ce1+`fSE4lXor66^x&uk9$8IthhS`uEdPsI$8Xda{gqe^XUIeUsJ3#q2`+OH`-%j zYMJ?Jse$K;P_X}Z{{0eG3nn!zta%7%yHu;lC8CQm&%m;Q#%k1p7a>soH^``ZVRCX+ z7y%Wi{sk*z=yVnF2UmrH#OHCW$>Qz}`q=mJ0;GFD;2iaA<3?Rb9ixG^W~ort^SCfesifgDfY)CA(r|sc!v{ygz}<7nk@68J?iK z3*%EgmSgK~;srQ7`lr$D0@{WYswo1eoUyp>Z7g9`+yhHI@jAQZ0TnvFJpLtN?SfJg z(_ZlM*`%F5HIZMW3q7l(V*L9mX^@~Yttr}0imRHV3U67CI^|?I$35yE5zlO!GJqZ+ zwAD{1Wz4_Fq39gS?tJlDy_j_3f$FuE6=8!%W+6Y>Hi*f_%*?VJGIpyC_Hv`yGC4U|py zi92?`6(uSyX2U=!ux+x6s6W&ic2A>GgZGn)%9B(qWyef~`HZ)Wa48@&vm`SMn>HGz z%bTf2hh?kDn|F4l61kj>bn?5`%4lxkdFc^}gWu)jotZxsFK!5Jz9Dl2DcLati3CdE zGTCEZq$dpU*_2M!QswvsD4SeojloQ5Quy2XWjx}`D1*cS>?5%Ow#kVl8qu9%CB;_N znjNd+T^P52%BuXm0NUQ|l)3j}Q!OMC<(*gc2Y$KIj;m1ga{wj_(7?5}G=xboQ*}>^2XPp(p8T8l_!IliE)@4J;in zdicuSCG)46B!mad(Az;YXuUb{%iA(vYw&WT>mnhu zTQ%XiVjqg5ZY=d=&C2Kl4PDV>RsbRWs`J_OfoD48BvlmwXsqhe9ntDR$NBD`h2kefazfJSe5X^Y zhON`?-hHX}i%UV_IbMWXPY%G%Pccs|XHpXIJG!#9R727aYWWz2ISX=V>&4_x%N_yK zP^$|ui9-I!R?MDFgB&p?*~E^9m{Ti9Ylt;tJsaDbyB(EEQR0T%&4t-{N`MoAJQ?$X zMeFZBh z2tQPEMZdq-*0hG`DzrWDr%b?ugJ{xDp6nrO-hbbSytQqy5de=v?RxiLw&5Zi&l%rQ z5A{K~>2-x)Dt^Z<7?zbFQ)#X?sW)fL2+Kjoc(>iW=@KSaX2yKQ z#3{o&gL(R+Oxjz2L?hIqfVOkTyB+%40vmdII-vWs> zka-bz^=SW|=VF2X-M((DHj)XXmtekZ&~vC&e5Iy{p5_pbX_@V{RqFB#zGmj5v1xFy zH>O>ua~Lxy(5mL`J#zXHc8cEG`T~@rc=&8*+u+AntX=#Yr20;p)QcWm+3VXuxqTKJ8Q9a=FPp% zQF8s|ul!t7GcXZUM&I6HA;EPCF+UNET^)z$J^cCY8`o~#11rUSY&t1c(Wf>4=4a)^)f#P)-xoaH)olINRT^(6%REX{f^3(In#w z(0S8HV`rzLAR(kTuLJ#P&*TzXJ|(+P*S#=37Z`;|lkKs`EB$&``Ux|WGYj)vn@q%v zVqs|sy)3n}JCMJtaO^oO|3&%Y3yrV~I9oh3o&{?Ujsv~;g%=h_zD>-H%+Gs@+)Fx* zy)J{`L5*eekQv^U_{J|;^lSvZm|tp$)KN=kBLMQ>Tl5x1*7RsqA59LDC=Lu=!d4`n zZLqUX+y`F#VEdrkLrqx91oxonl_k2`iKX+9HZ>twaJ41ORoeAx_mU|HOCr|jTdwKW zyDA>gh|G+#0UKUPk5yf6jy93%$6Eg}h)$_@dyvZ>@J;|Kl`*k=oK+ve*=!pfd52Q+ zy6yfgW~b-IAIBE6<}0m5iw5z01Ptkd*1$5M4A^zwpa+42SmZ>3VY@ldrx!k)+Fn-- z>nlRP0_r>;+wAmyE&CyUaR#^NnrED2bY7^eO;;`NN9eMJox{t+ zR`GGimnd1o@+^Lp_aliDuX;mN9CKg~VIQbo7{9m(ZW(lp=I2t-X$68rD1)7%0ys^} zzO)a((Pqim!*y4-bx%1XL&!vX1gI?E%@4ny6xV!@;xXfl388cRLU>9#6aPFes-D8A z$$r(KVY28KCSEB3Nja;*#U@F?o4XRsL>-VV)kEwv6@Mg-oWHF5c9g<< zxH=o^Y|hO43Q!sX&dOU<5F5}$>n&H`Q1n?A!lel_*B6WI~iXAtZX-m64&_XD$ zudtLNXbAlI8&4Bwn)YHWY7bMG1d_tu4vE;+9_SLa?$e!7gaYgQmMSax2NUY66MFe{TNvoQR_j~Q0MgwPW5qzF{{+; z>g~WjF>;*u0`DSty)aU6`igGnOi1?1mQ_`MEqgN$pgaO)h>W|;wjx}fDbb9Ajtu&A ze5g0`9zqs|*&5uCpozwxivnJOL33Gh~4LNaSWMqQSA435hxmy)IJ3x(M)<0%aTXHTYUPBSw*+G!D zO;Y5xVTd@;T3Am)(HtH{)EXyqm2x@v@zddPc~ea7?N47lZa$>9@89UL3Smm&_`MbQ zC%-{I)9Am3#6(;z&N2>@wyE^x?5f%E2g}%hpd|vMn?Kv{cSGF05nE9Q8`bllWs_`C z#UI+iv<|KiIO(QPv&(6k!n!oCr#x~Bwp5 z-cVM_NBL&2wWXf-SnS4Y2B8qgM?m#i?O+2Wt(gf(8CoUmf7|?vF04qIx2*Tpym?jL zuk@qXLGU10#kG#xM*4S68@Oc$+ILBY?WdXPDL?+^PF8-IfH0$h#|GKdUWmTfWRp)h z#FCDk-t%#yZh3Eet)*3EtCBn(m4PWJ>Wk>|wd@kR-;n(l{I(|<*GcBrh!51@p-fbM zign=EId-XTWZ4u^zg;*w=2uup*o3aBC>ySfN-iKim#7T@ps*?WcQSA>M?n+oY2UDy z9mc-%>AyUIxg$l5VlQxpqtsRg627K`8Wxq~kc94$gGtOu|M5_?4ywKF9vNa9O~vhr7C4X5fHIUB>}<&m`pKWw|J zz+|=Noi0N213w*OXM+}Kvwzz^H_G>SsP`7E=VZH{2Y+s4!+H6Z2MD?IdvcyX;PB%J z(1nzG7P*bLKx&#|!hQ0Vc*-ucfNrm2&ArIfheAkl{{q2KA|f$Dom$bC^RVKJhMTob z-LrcYk<}eXaN_rjP>3#iqrShcV!-aFBr1ltz7NhBQpckMSrTU$;o4QRQ(wA>GCnu< z?45IM*7yheUM+wVUCY+#Q$25$A7Z>fkAO&AX=3D*_-I2(nr)hZ2UGlNbaW|KP2!w3 z4HdUQ!33wpo$DK-^?;_oqu-61XO~S|xJ6SkHDS2=+&Z6F5_x|eb}}x0dj$O2 zFcE?JWalgQeSGJ}Y~MSl%64VtcbO|tI69fay~bwOkvLi{RKGAwedQ6@`5V9*ksE)C z7yFUOq1*lMsiFzXZXpCX)fl?D_ak? z63R?1c8#Q*kVSoOMS-NRbh_9i3(fuTC`@&lh8x>${np&lDN%M`K8_6j-qp9jScS6& zuoE5~{o)R+RPdUqqcqmoa|}Mu~Z<%?>bR-Rqn@ z>4K;wNNvh|Dc5t5wbDmhuI%@hj6JHt(M8iaQ#Rs7>P&YwURJ*A;N4eO2K;}^7F)4{ zEH83E`(@v2t!enldupZRgcF_i4rz;ByNPQMw7Cxe7XWw+?er#Pm|_z6c~k&3NMIV) ze^#O%ASFumHL=EoV!SqdIUa=ITFr@%>Eo6Yb-w zpDe_ao{+=SBzBN`6P>P2x&KXj?H@;j4xv9{oaPT?X#du=1_ojfW!B?ahlyV%LP3cq zUimXLo+TILxylhCF}_m~5i?U(N&&$DsjErKVObjoPf&b+aavJayNRe{&%=~$kG{&t z=H}0gnvHM9;Cx1my?*8jDLSIhabS7rB|ep_N?z{j$(h_@JZloWZzXg;P zVYW2=^I>{@)zh>rD5?B;-I@=6$fKYid7N~X5EF6tFfYHIg8R~s%9kGu4Nd3yxRdIv z&753$Rwdp&a4Qw*Uy}~x3%^p;bW9`7)K5&Q3mAqqLl&2n=lIeHg$2xL4XA4M-wj2r zsDZU95frpp=H}*P>~*=2;-h2YY`3!Z!bdZNt?wJqA<&xL462heWL^N)DA*EhAQAu`0EQ8TbDvdT&+h7BNf=57d zwP7T(_I2L!QnI3yV_x%FgjZIu%MFGBZTe)*O$*kE<8aLWLo%L7+EHKfM+6uCodu{M~FC-{#-!c*97YV(wPEzbrVK#EJ?>41%I z^Y8|%%vclXJXJDHIx58Hr;z148pZkY!goteKL3m+MAmHFsEftU2erXcu28Rhq#rpV zh`(WJt?A{bzFl>VP|Hc!8CF40|L%k3D{ z9dv%vJt`T=`WjNGE(Q9QVh$#c=Q7o$m=2MrOKJs?*+!s)Em zq>(c@ZhK%a|0#z@K#QP{WKA8P2KVO}cgU|B7?)AZi*}0h>ivozs?*1H7yoqpNdLq@TrrmyYKEE@+O&>{ zfI0}Ly?Gu1z;@q!VnV7nTu-Ae-9Epx59Dvt_&zSPGnH@1_Q`LM9z9MVy5E>Eti^+o zYk+C-XULD%ron)2GgmFxr&dH;&vXvwuMZAGa07VfG=1PkpA0ss#2 ze;KoSrGfdFS+c5yTfYQsV^Fhdo?P8*M^9QU0%{AiAZV5kOf9_dPKk^%dmw`7T zBP@<_Kz3xoP=@8`55)qt-&*)x5%M@Cr)GDsoXAH~_wv<5Z^i(#w_-AO!aHUlYfQU% zT0cAEG4@0mqorUu&^{w3y1*r2E;T|6PQNJ};K$y#iyFR^?j404;?mf@^nIt|vYkZ4 zb>AHM1EOE_r7(mY=zG@{P5BxPUbkk$?SMeDTV|i{tp04=z`Kr37MNWgDusbBZz}$o zl>8&(`9oI2r|EgwOC1hnlsc`Cbd^HHX|b+8X-2;;NL&nu<>-}{577NLYzT=@r-{3p*av;QaW%<#aR^5Det9hKKEEs)`P9)yk3UCmIi*xC=J4J*v3Q;$2KJr&XJ@!jc^;+XnLtk&6Vf zC)LIo?=2?%F}b9&QFjv&M~Tic{o%{g8DY1gcDZ-E5s&%JzgsWlLgh2dnsqcUpchLy`V$p$ERy?Xa~w0 zD)a7Cp|ZXWE9R)#NGW>`o8>~aPIeu^b6d}}yFOr#t?a*Jx40vvKfN9q8w!q{4>_v$ zhnG|!{anMZr3&FR9|u`MJVyb5bEa68_(S?s@BqY(YCSW2WMyk|Q9)t^KIO6$ngflT z1GVy=-VlzTtG1K{CA_e9Oq2C1Ic@t}#Xylvl@KU#?NJE4>*vd>{brn0SBU3ZD9D^& zey21mb&p(y5*@uoWIh5KtZQH_6{NHd555u!RxNssla3qu%TeNlZ3>To#=;p(xx&qK zKKMP?Bfx1f!F5pQ7{L>L&U_zpW>8wmMXK?NKs#F=^mR^B;eldT;%l-POG9J!Txqr* zLPX&coVh9_MUisOWLAysY=rGVx1Ya!XMWceQKxL^*338k>gGi&9QH@XTx(*n!GiB3 zg$wgG*OhSyAZk$qe0?9C;n7pV%EOTRZHU2dduENRYR$O$jg{B}pque0x# zyVjdTPF$wtBY((iI~fj(>CRFiXfRBMUh?b>(ntxej-)^0RB`kF!{C=Zb+i-LW&HWJ z{4L8=p{x6^KctOvgwtePwFU1{cFt-@I1eQ|j%L1;Sa{JT7`JcW8Hn5Z?wI^9j6gTb zZaO@o*kTgI{L_v#D84|>K7msKNE1Io2KCp$KGgjBH^fW#ufZ?Rylo@nq~BWK>YZG< zs^H8JiD(nfmDq*A60P=uXuBx^?BAXQh6g$?x)J&G5Cw~_&(Yr%q2+xup$53p{nAF0 zy|Wkfv+x%qh+l|=^H+!XS7Gv`-lAkXJUu=6wXBlORT0E{9ZpG-XG)%vfc2bRw8 zf(FsKMSYiCiT|5jfv+(9BNtD&|JB&4rv1mqGnH$7!d%O1K>(yy2?8D@5sDvmC+`f#Qevf zWI4MeX|dNu>Ai&B#MSXvM&iWRRgVCFv)=o>rtV!0lfmE{LJ*0qugKT=*X#sEdPHWG zAAjUa^dzRbEx2rpqD7E_zX&GeH|Ugs)>2T0JD+T6-tnS_NKV=e@O8}VGYVNY7JRMq zQIK9|Nui5$B&SH%S0inz!GvD*Lp)!w_qva-vsQVP2vO;pjZkoGhaa$9(}fk{(M>7y6vtKG%(OG zb(Mkah2*6++D3l4f7kpb?}MFZX+eIx$jWxi_nX3^LVttgde3?rZ4(>gk8;+`aG=KlCOHO`b-l_h>4>wEpVp`MT#;4DlSgZ9RC zAjDb2th4bbU+`q=gW{fVRmHOTjxJ~R+kymJ>u#aGkCDBeiXa`bG^ez4MX&D>nRvUd zkAOZSy892yB0iHlE~-l6yNolWO~VdrA&wuKxxZ24D{?Y~(TkGkv7(n1^Jc#Yao>S#SP7bUAby<^F`oZS7#CgPmmp)q zr~wSjSNSWZ?~uth4Pi>S*n}xj%Y_$Il0$VyFPeE%ITa3-qRPyZ3@lh3S&(e(Kup@K xFsCA>D|3S-gv0duOEd;$BU$IDZIGRd2w91*R3Sv0el~}{7V>21K_riJ{|gCUo16du literal 0 HcmV?d00001 diff --git a/blade-sample/src/main/resources/static/img/avatar.jpeg b/blade-sample/src/main/resources/static/img/avatar.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..e6f4dd4a4ee82995e3a65bc98e5032a19de059f6 GIT binary patch literal 12355 zcmb7qRajg>v*2LCHAn;r7Muiv6FkUZ1A}{l1k2#=fe?bjV8Iz+aEHMmxI2Rm7TgK$ zu>AM#KHUBGW$Sc*{ZK8{b-Jp$tLky~aRor4C6OifCK;`!kQg`_kUN8m)QXyWIYoc!;<@dn)5LiR&ARN(SDH>V&6E5i1~ne+ngw- zZiO6MPO@s~YLxwQ$tZFrII;WMwR&Kc9ISu`eDUTYiwI6Wyx02P%^9-Z^6I*t(ruGZ z>?)R)cL{q%ZA=||-MTD!)xR=UJGaicRSB?`9R6YU5unW$6QsLV#?z8kYnWR`P2##x;eju#Pkcy6D?Eu( zqDF_iyYS#uHVZ(@`CXCHv7zihTrug3^ke$VD5j8WPhAOi@{oyu|G3P1?dh>JuLAYF z((#o`h3{k{tg4ulV&eW86Ej+_BQUg=9|`%ntT#k~zx)_G-M_P1=me;y3y(@AOg$m9+akp-*ko;+*r) z{hO4rRM(e@a*hn=%ubZ@u#@=>MZaRcg_hneQg^|@&}Q9I!nhceTVgz!IPJ0e1K)5A z_GfHmmlxR$qk6VmEXJ+riiR-nVxi!L`!Ds4wuTDGNGasBt#|FHJ)(y+evgPtNsaXq z>O36P=AE_1kQy#}^K&upFi~QMc|@%7FEiLUn#dqhU^ijhMqdg|R`+F}Sn*Vvx|(Q7 zlACT+V!cDQgQ-=j=BHdwc9-aBW3(Frof_*wu>X}e-9}j?#q0P?H|656{irXK0&s#C z1isJ1P87xk>L#T14TSgA{_dRdFJ;F$8-}fBy0DZ?bBsh~B+nbDDOV3k;VV^|7`m>z zU8XWhsDp`Z?_}MRYz$4sOJqcLhXToR9MKx+h4%)TF$(W%ijwC=1BunVNPKO&_&)?4 zYE>&~g~#hpw>ehVHcL@{)<0CNw$aLGuUHJzkI9K@1y>LJyAR6zMg9Y1AuKlG9nIG-Pq;4DIfzuC zQX3Env`KcIMFo}>Ji#d4LgA0}{N4VP`p!R9-q0lsx=cMEgV|QWJT!7$xa;LLdE*w1 z`nNM$ik!hq=K|-u`G}s?1(W)LMBXm5LzcnO#vhEgdGc8_AirFwFMdLS;H2S#JGP;s zR)^+{C+gd}faEQ!wBH^p4Oyn~7Bb;e>PJrtC0(80epl*!C5OdE4f~;0V`q;5JaMK5 zQ>~dW=+6!?N+p6mmw+B)1>aw>I826I+P2E6c473a}XW_^^H%7y{A>%8x4VHB( z)$#v4K$XDjwKm1Fp}rL`8@G{mxz_N~Cn^hOg3giTQ6=9Zf3l=XiCw=!qvj{^2w;=) ztj}IOwWyF*OEZsnZg}IvG{fW+=0iM#ZunVsP7Fl#?R==4Lr&F0&@S!dMt@0fo7cZy zPfUJ6eN<9QyD{w#iUEtQ*)XH0F*Y319J};9ijjJA~H}%RhjLrTZN6{mo zX5K&B%Z86O(Co@jI-q^?%2(8v(8+aX-+;>b&&1hnYOT_DyGbjHTo{0!4UJ7v4uFwG zQGArmf$!S+gUR*!u25(i9*_EhhvSZM!0K9#IT&;rk6+wJ0~J9#E14+WiZfbesu!!Z zeC2nTZ^EXSkie2!CtwSat2M0Oz~a!A#ACafVThU%SaOnT;=pdX{?-8b60k)3Ev7OJ(QRp4W%TE1BDG6`LjAc) zgaUG7a${qpw&igS$RnZD|@ zeiBT@XJ_iN80Zyc0n@grh4zHj2V%~Rt(u!l^8PF7-z017V4p zt5tqX1v;OgK&JIf{Q(>1*3Emui$uI4Msm|I)}r-a|2Z{y9GjtBTpLwMYWZrsxmf7A z(Z9>#!em`fIQ74>4(0PnXG~WSg)w>Q)PoKgS(Y>s>F#7%SvYTkkfeJ`Aq(MMThFYr zW8ZVD&LbjzA2lO*PvMwcpT1{S$!}t@N3Hkhaeg*Xm!+V@GJM*$v`huXY75VSKxpKe zu(e6s*A~PnG{b5XV-{x8H@Viyn3ViE9CHe8Dwu;lV;nfc=jT zy&?OULD=JLtw7A542_8c8RR8@=aJc!?4^@`5mnBzw&(^w1qzKy=U;7vrESS%Y zNtanItV;Ms@Zn`xwKs05cyMvc(-A3x#c0oM!1tdoPVNBVDTdb zEHS|O5%4c}&{&+)|x zK;8Cdts*eP6fe&n|02e#FyOXmK(w)h!F`5im25rbY0|&W;k--Mc5-PCad!!OgeSYO z8xM{I-~Hsnvf@aMW3ZmFwOuXkfaVVhBD0`v34#eT)j@BSVN>NiLp#16yvf6@A$eXX zxj17o9-WLfxnY)CeEe4-4k^ zC6m3fR+41LSHl*I2K6*=>7oeoW@W-%mDE7IB%X49uA()W!IWV^Tz0!+);_I#REe`c z2h~DYvcN6p&yN|&r;fKeqT*(`SaSGP0}-P3KNmLI8>ryI^r~FIEejhCmh$>lug|VD zY)k0t#Wd!I@uu%FO)K>g^ki#QxBg$cu%g={rl(Yn+ovNE(OW-IzW#L+{dqq6AOA&} zaY5|<^vkf91F?NP$LihqiSmMraf2NU=<_HpU%qI^TNGFBLzj8nBfu9_6ej-COJ!KF z1Ce1+`fSE4lXor66^x&uk9$8IthhS`uEdPsI$8Xda{gqe^XUIeUsJ3#q2`+OH`-%j zYMJ?Jse$K;P_X}Z{{0eG3nn!zta%7%yHu;lC8CQm&%m;Q#%k1p7a>soH^``ZVRCX+ z7y%Wi{sk*z=yVnF2UmrH#OHCW$>Qz}`q=mJ0;GFD;2iaA<3?Rb9ixG^W~ort^SCfesifgDfY)CA(r|sc!v{ygz}<7nk@68J?iK z3*%EgmSgK~;srQ7`lr$D0@{WYswo1eoUyp>Z7g9`+yhHI@jAQZ0TnvFJpLtN?SfJg z(_ZlM*`%F5HIZMW3q7l(V*L9mX^@~Yttr}0imRHV3U67CI^|?I$35yE5zlO!GJqZ+ zwAD{1Wz4_Fq39gS?tJlDy_j_3f$FuE6=8!%W+6Y>Hi*f_%*?VJGIpyC_Hv`yGC4U|py zi92?`6(uSyX2U=!ux+x6s6W&ic2A>GgZGn)%9B(qWyef~`HZ)Wa48@&vm`SMn>HGz z%bTf2hh?kDn|F4l61kj>bn?5`%4lxkdFc^}gWu)jotZxsFK!5Jz9Dl2DcLati3CdE zGTCEZq$dpU*_2M!QswvsD4SeojloQ5Quy2XWjx}`D1*cS>?5%Ow#kVl8qu9%CB;_N znjNd+T^P52%BuXm0NUQ|l)3j}Q!OMC<(*gc2Y$KIj;m1ga{wj_(7?5}G=xboQ*}>^2XPp(p8T8l_!IliE)@4J;in zdicuSCG)46B!mad(Az;YXuUb{%iA(vYw&WT>mnhu zTQ%XiVjqg5ZY=d=&C2Kl4PDV>RsbRWs`J_OfoD48BvlmwXsqhe9ntDR$NBD`h2kefazfJSe5X^Y zhON`?-hHX}i%UV_IbMWXPY%G%Pccs|XHpXIJG!#9R727aYWWz2ISX=V>&4_x%N_yK zP^$|ui9-I!R?MDFgB&p?*~E^9m{Ti9Ylt;tJsaDbyB(EEQR0T%&4t-{N`MoAJQ?$X zMeFZBh z2tQPEMZdq-*0hG`DzrWDr%b?ugJ{xDp6nrO-hbbSytQqy5de=v?RxiLw&5Zi&l%rQ z5A{K~>2-x)Dt^Z<7?zbFQ)#X?sW)fL2+Kjoc(>iW=@KSaX2yKQ z#3{o&gL(R+Oxjz2L?hIqfVOkTyB+%40vmdII-vWs> zka-bz^=SW|=VF2X-M((DHj)XXmtekZ&~vC&e5Iy{p5_pbX_@V{RqFB#zGmj5v1xFy zH>O>ua~Lxy(5mL`J#zXHc8cEG`T~@rc=&8*+u+AntX=#Yr20;p)QcWm+3VXuxqTKJ8Q9a=FPp% zQF8s|ul!t7GcXZUM&I6HA;EPCF+UNET^)z$J^cCY8`o~#11rUSY&t1c(Wf>4=4a)^)f#P)-xoaH)olINRT^(6%REX{f^3(In#w z(0S8HV`rzLAR(kTuLJ#P&*TzXJ|(+P*S#=37Z`;|lkKs`EB$&``Ux|WGYj)vn@q%v zVqs|sy)3n}JCMJtaO^oO|3&%Y3yrV~I9oh3o&{?Ujsv~;g%=h_zD>-H%+Gs@+)Fx* zy)J{`L5*eekQv^U_{J|;^lSvZm|tp$)KN=kBLMQ>Tl5x1*7RsqA59LDC=Lu=!d4`n zZLqUX+y`F#VEdrkLrqx91oxonl_k2`iKX+9HZ>twaJ41ORoeAx_mU|HOCr|jTdwKW zyDA>gh|G+#0UKUPk5yf6jy93%$6Eg}h)$_@dyvZ>@J;|Kl`*k=oK+ve*=!pfd52Q+ zy6yfgW~b-IAIBE6<}0m5iw5z01Ptkd*1$5M4A^zwpa+42SmZ>3VY@ldrx!k)+Fn-- z>nlRP0_r>;+wAmyE&CyUaR#^NnrED2bY7^eO;;`NN9eMJox{t+ zR`GGimnd1o@+^Lp_aliDuX;mN9CKg~VIQbo7{9m(ZW(lp=I2t-X$68rD1)7%0ys^} zzO)a((Pqim!*y4-bx%1XL&!vX1gI?E%@4ny6xV!@;xXfl388cRLU>9#6aPFes-D8A z$$r(KVY28KCSEB3Nja;*#U@F?o4XRsL>-VV)kEwv6@Mg-oWHF5c9g<< zxH=o^Y|hO43Q!sX&dOU<5F5}$>n&H`Q1n?A!lel_*B6WI~iXAtZX-m64&_XD$ zudtLNXbAlI8&4Bwn)YHWY7bMG1d_tu4vE;+9_SLa?$e!7gaYgQmMSax2NUY66MFe{TNvoQR_j~Q0MgwPW5qzF{{+; z>g~WjF>;*u0`DSty)aU6`igGnOi1?1mQ_`MEqgN$pgaO)h>W|;wjx}fDbb9Ajtu&A ze5g0`9zqs|*&5uCpozwxivnJOL33Gh~4LNaSWMqQSA435hxmy)IJ3x(M)<0%aTXHTYUPBSw*+G!D zO;Y5xVTd@;T3Am)(HtH{)EXyqm2x@v@zddPc~ea7?N47lZa$>9@89UL3Smm&_`MbQ zC%-{I)9Am3#6(;z&N2>@wyE^x?5f%E2g}%hpd|vMn?Kv{cSGF05nE9Q8`bllWs_`C z#UI+iv<|KiIO(QPv&(6k!n!oCr#x~Bwp5 z-cVM_NBL&2wWXf-SnS4Y2B8qgM?m#i?O+2Wt(gf(8CoUmf7|?vF04qIx2*Tpym?jL zuk@qXLGU10#kG#xM*4S68@Oc$+ILBY?WdXPDL?+^PF8-IfH0$h#|GKdUWmTfWRp)h z#FCDk-t%#yZh3Eet)*3EtCBn(m4PWJ>Wk>|wd@kR-;n(l{I(|<*GcBrh!51@p-fbM zign=EId-XTWZ4u^zg;*w=2uup*o3aBC>ySfN-iKim#7T@ps*?WcQSA>M?n+oY2UDy z9mc-%>AyUIxg$l5VlQxpqtsRg627K`8Wxq~kc94$gGtOu|M5_?4ywKF9vNa9O~vhr7C4X5fHIUB>}<&m`pKWw|J zz+|=Noi0N213w*OXM+}Kvwzz^H_G>SsP`7E=VZH{2Y+s4!+H6Z2MD?IdvcyX;PB%J z(1nzG7P*bLKx&#|!hQ0Vc*-ucfNrm2&ArIfheAkl{{q2KA|f$Dom$bC^RVKJhMTob z-LrcYk<}eXaN_rjP>3#iqrShcV!-aFBr1ltz7NhBQpckMSrTU$;o4QRQ(wA>GCnu< z?45IM*7yheUM+wVUCY+#Q$25$A7Z>fkAO&AX=3D*_-I2(nr)hZ2UGlNbaW|KP2!w3 z4HdUQ!33wpo$DK-^?;_oqu-61XO~S|xJ6SkHDS2=+&Z6F5_x|eb}}x0dj$O2 zFcE?JWalgQeSGJ}Y~MSl%64VtcbO|tI69fay~bwOkvLi{RKGAwedQ6@`5V9*ksE)C z7yFUOq1*lMsiFzXZXpCX)fl?D_ak? z63R?1c8#Q*kVSoOMS-NRbh_9i3(fuTC`@&lh8x>${np&lDN%M`K8_6j-qp9jScS6& zuoE5~{o)R+RPdUqqcqmoa|}Mu~Z<%?>bR-Rqn@ z>4K;wNNvh|Dc5t5wbDmhuI%@hj6JHt(M8iaQ#Rs7>P&YwURJ*A;N4eO2K;}^7F)4{ zEH83E`(@v2t!enldupZRgcF_i4rz;ByNPQMw7Cxe7XWw+?er#Pm|_z6c~k&3NMIV) ze^#O%ASFumHL=EoV!SqdIUa=ITFr@%>Eo6Yb-w zpDe_ao{+=SBzBN`6P>P2x&KXj?H@;j4xv9{oaPT?X#du=1_ojfW!B?ahlyV%LP3cq zUimXLo+TILxylhCF}_m~5i?U(N&&$DsjErKVObjoPf&b+aavJayNRe{&%=~$kG{&t z=H}0gnvHM9;Cx1my?*8jDLSIhabS7rB|ep_N?z{j$(h_@JZloWZzXg;P zVYW2=^I>{@)zh>rD5?B;-I@=6$fKYid7N~X5EF6tFfYHIg8R~s%9kGu4Nd3yxRdIv z&753$Rwdp&a4Qw*Uy}~x3%^p;bW9`7)K5&Q3mAqqLl&2n=lIeHg$2xL4XA4M-wj2r zsDZU95frpp=H}*P>~*=2;-h2YY`3!Z!bdZNt?wJqA<&xL462heWL^N)DA*EhAQAu`0EQ8TbDvdT&+h7BNf=57d zwP7T(_I2L!QnI3yV_x%FgjZIu%MFGBZTe)*O$*kE<8aLWLo%L7+EHKfM+6uCodu{M~FC-{#-!c*97YV(wPEzbrVK#EJ?>41%I z^Y8|%%vclXJXJDHIx58Hr;z148pZkY!goteKL3m+MAmHFsEftU2erXcu28Rhq#rpV zh`(WJt?A{bzFl>VP|Hc!8CF40|L%k3D{ z9dv%vJt`T=`WjNGE(Q9QVh$#c=Q7o$m=2MrOKJs?*+!s)Em zq>(c@ZhK%a|0#z@K#QP{WKA8P2KVO}cgU|B7?)AZi*}0h>ivozs?*1H7yoqpNdLq@TrrmyYKEE@+O&>{ zfI0}Ly?Gu1z;@q!VnV7nTu-Ae-9Epx59Dvt_&zSPGnH@1_Q`LM9z9MVy5E>Eti^+o zYk+C-XULD%ron)2GgmFxr&dH;&vXvwuMZAGa07VfG=1PkpA0ss#2 ze;KoSrGfdFS+c5yTfYQsV^Fhdo?P8*M^9QU0%{AiAZV5kOf9_dPKk^%dmw`7T zBP@<_Kz3xoP=@8`55)qt-&*)x5%M@Cr)GDsoXAH~_wv<5Z^i(#w_-AO!aHUlYfQU% zT0cAEG4@0mqorUu&^{w3y1*r2E;T|6PQNJ};K$y#iyFR^?j404;?mf@^nIt|vYkZ4 zb>AHM1EOE_r7(mY=zG@{P5BxPUbkk$?SMeDTV|i{tp04=z`Kr37MNWgDusbBZz}$o zl>8&(`9oI2r|EgwOC1hnlsc`Cbd^HHX|b+8X-2;;NL&nu<>-}{577NLYzT=@r-{3p*av;QaW%<#aR^5Det9hKKEEs)`P9)yk3UCmIi*xC=J4J*v3Q;$2KJr&XJ@!jc^;+XnLtk&6Vf zC)LIo?=2?%F}b9&QFjv&M~Tic{o%{g8DY1gcDZ-E5s&%JzgsWlLgh2dnsqcUpchLy`V$p$ERy?Xa~w0 zD)a7Cp|ZXWE9R)#NGW>`o8>~aPIeu^b6d}}yFOr#t?a*Jx40vvKfN9q8w!q{4>_v$ zhnG|!{anMZr3&FR9|u`MJVyb5bEa68_(S?s@BqY(YCSW2WMyk|Q9)t^KIO6$ngflT z1GVy=-VlzTtG1K{CA_e9Oq2C1Ic@t}#Xylvl@KU#?NJE4>*vd>{brn0SBU3ZD9D^& zey21mb&p(y5*@uoWIh5KtZQH_6{NHd555u!RxNssla3qu%TeNlZ3>To#=;p(xx&qK zKKMP?Bfx1f!F5pQ7{L>L&U_zpW>8wmMXK?NKs#F=^mR^B;eldT;%l-POG9J!Txqr* zLPX&coVh9_MUisOWLAysY=rGVx1Ya!XMWceQKxL^*338k>gGi&9QH@XTx(*n!GiB3 zg$wgG*OhSyAZk$qe0?9C;n7pV%EOTRZHU2dduENRYR$O$jg{B}pque0x# zyVjdTPF$wtBY((iI~fj(>CRFiXfRBMUh?b>(ntxej-)^0RB`kF!{C=Zb+i-LW&HWJ z{4L8=p{x6^KctOvgwtePwFU1{cFt-@I1eQ|j%L1;Sa{JT7`JcW8Hn5Z?wI^9j6gTb zZaO@o*kTgI{L_v#D84|>K7msKNE1Io2KCp$KGgjBH^fW#ufZ?Rylo@nq~BWK>YZG< zs^H8JiD(nfmDq*A60P=uXuBx^?BAXQh6g$?x)J&G5Cw~_&(Yr%q2+xup$53p{nAF0 zy|Wkfv+x%qh+l|=^H+!XS7Gv`-lAkXJUu=6wXBlORT0E{9ZpG-XG)%vfc2bRw8 zf(FsKMSYiCiT|5jfv+(9BNtD&|JB&4rv1mqGnH$7!d%O1K>(yy2?8D@5sDvmC+`f#Qevf zWI4MeX|dNu>Ai&B#MSXvM&iWRRgVCFv)=o>rtV!0lfmE{LJ*0qugKT=*X#sEdPHWG zAAjUa^dzRbEx2rpqD7E_zX&GeH|Ugs)>2T0JD+T6-tnS_NKV=e@O8}VGYVNY7JRMq zQIK9|Nui5$B&SH%S0inz!GvD*Lp)!w_qva-vsQVP2vO;pjZkoGhaa$9(}fk{(M>7y6vtKG%(OG zb(Mkah2*6++D3l4f7kpb?}MFZX+eIx$jWxi_nX3^LVttgde3?rZ4(>gk8;+`aG=KlCOHO`b-l_h>4>wEpVp`MT#;4DlSgZ9RC zAjDb2th4bbU+`q=gW{fVRmHOTjxJ~R+kymJ>u#aGkCDBeiXa`bG^ez4MX&D>nRvUd zkAOZSy892yB0iHlE~-l6yNolWO~VdrA&wuKxxZ24D{?Y~(TkGkv7(n1^Jc#Yao>S#SP7bUAby<^F`oZS7#CgPmmp)q zr~wSjSNSWZ?~uth4Pi>S*n}xj%Y_$Il0$VyFPeE%ITa3-qRPyZ3@lh3S&(e(Kup@K xFsCA>D|3S-gv0duOEd;$BU$IDZIGRd2w91*R3Sv0el~}{7V>21K_riJ{|gCUo16du literal 0 HcmV?d00001 From 2885fe2e9a0b4f67642e640a6260716e866f9610 Mon Sep 17 00:00:00 2001 From: biezhi Date: Mon, 2 Jan 2017 21:01:43 +0800 Subject: [PATCH 536/545] => add http method 405 status --- blade-core/src/main/java/com/blade/Const.java | 13 ++- .../main/java/com/blade/kit/DispatchKit.java | 85 +++---------------- .../java/com/blade/mvc/DispatcherHandler.java | 59 +++++++------ .../java/com/blade/mvc/DispatcherServlet.java | 2 + .../java/com/blade/mvc/http/HttpStatus.java | 41 ++++----- .../main/java/com/blade/mvc/route/Route.java | 2 +- .../com/blade/mvc/route/RouteMatcher.java | 7 +- .../main/java/com/xxx/hello/Application.java | 3 + .../src/main/resources/app.properties | 1 + 9 files changed, 85 insertions(+), 128 deletions(-) create mode 100644 blade-sample/src/main/resources/app.properties diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java index f95edb6a4..0ec1960ff 100644 --- a/blade-core/src/main/java/com/blade/Const.java +++ b/blade-core/src/main/java/com/blade/Const.java @@ -33,14 +33,19 @@ public interface Const { String VERSION = "1.7.0-alpha"; /** - * server 500 error HTML + * server 500 */ - String INTERNAL_ERROR = "500 Internal Error

500 Internal Error


blade " + VERSION +"
"; + String VIEW_500 = "500 Internal Error

500 Internal Error


blade " + VERSION +"
"; /** - * server 404 error HTML + * server 404 */ - String VIEW_NOTFOUND = "404 Not Found

[ %s ] Not Found


blade " + VERSION +"
"; + String VIEW_404 = "404 Not Found

[ %s ] Not Found


blade " + VERSION +"
"; + + /** + * server 405 + */ + String VIEW_405 = "403 Uri Forbidden

[ %s ] Method Not Allowed


blade " + VERSION +"
"; /** * default web server port diff --git a/blade-core/src/main/java/com/blade/kit/DispatchKit.java b/blade-core/src/main/java/com/blade/kit/DispatchKit.java index f44bb3666..fa32b1a53 100644 --- a/blade-core/src/main/java/com/blade/kit/DispatchKit.java +++ b/blade-core/src/main/java/com/blade/kit/DispatchKit.java @@ -1,40 +1,27 @@ package com.blade.kit; -import static com.blade.Blade.$; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLDecoder; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.blade.Blade; import com.blade.Const; -import com.blade.mvc.http.HttpException; import com.blade.mvc.http.Response; import com.blade.mvc.view.ViewSettings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URL; +import java.net.URLDecoder; + +import static com.blade.Blade.$; public class DispatchKit { private static final Logger LOGGER = LoggerFactory.getLogger(DispatchKit.class); - static final boolean isWeb = !$().enableServer(); + private static final boolean isWeb = !$().enableServer(); - static final Class appClass = $().applicationConfig().getApplicationClass(); + private static final Class appClass = $().configuration().getApplicationClass(); private static Boolean isDev = null; @@ -141,7 +128,7 @@ public static void printError(Throwable err, int code, Response response) { } return; } else { - writer.write(Const.INTERNAL_ERROR); + writer.write(Const.VIEW_500); } } } @@ -154,17 +141,6 @@ public static void printError(Throwable err, int code, Response response) { } } - /** - * Print - * - * @param body - * @param out - * @throws IOException - */ - public static void print(InputStream in, OutputStream out) throws IOException { - StreamKit.io(in, out); - } - public static void print(InputStream body, PrintWriter writer) throws IOException { print(IOKit.toString(body), writer); } @@ -175,41 +151,6 @@ public static void print(String content, PrintWriter writer) throws IOException writer.close(); } - /** - * Print static file - * - * @param uri - * @param realpath - * @param httpResponse - */ - public static void printStatic(String uri, HttpServletRequest request, Response response) { - try { - String realpath = ""; - InputStream ins = null; - if (isWeb) { - realpath = request.getServletContext().getRealPath(uri); - File file = new File(realpath); - if (FileKit.exist(file)) { - ins = new FileInputStream(file); - } - } else { - ins = appClass.getResourceAsStream(uri); - } - - if (null != ins) { - print(ins, response.outputStream()); - } else { - LOGGER.debug("request realpath is [{}]", realpath); - HttpException httpException = new HttpException(404, uri + " not found"); - DispatchKit.printError(httpException, 404, response); - } - } catch (FileNotFoundException e) { - DispatchKit.printError(e, 404, response); - } catch (IOException e) { - DispatchKit.printError(e, 500, response); - } - } - private static final String HTML = "Blade Error Page" + "" + "

%s

";
diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java
index fbe5da776..4c82a39c3 100644
--- a/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java
+++ b/blade-core/src/main/java/com/blade/mvc/DispatcherHandler.java
@@ -22,10 +22,7 @@
 import com.blade.kit.DispatchKit;
 import com.blade.kit.StringKit;
 import com.blade.mvc.handler.RouteHandler;
-import com.blade.mvc.http.HttpStatus;
-import com.blade.mvc.http.Path;
-import com.blade.mvc.http.Request;
-import com.blade.mvc.http.Response;
+import com.blade.mvc.http.*;
 import com.blade.mvc.http.wrapper.ServletRequest;
 import com.blade.mvc.http.wrapper.ServletResponse;
 import com.blade.mvc.route.Route;
@@ -85,31 +82,29 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo
 			// reuqest uri
 			String uri = Path.getRelativePath(httpRequest.getRequestURI(), servletContext.getContextPath());
 
-			// If it is static, the resource is handed over to the filter
-			if(staticFileFilter.isStatic(uri)){
-				LOGGER.debug("Request : {}\t{}", method, uri);
-				DispatchKit.printStatic(uri, httpRequest, response);
-				return;
-			}
+        	LOGGER.info("{}\t{}\t{}", method, uri, httpRequest.getProtocol());
 
-        	LOGGER.info("Request : {}\t{}", method, uri);
-        	
         	Request request = new ServletRequest(httpRequest);
          	WebContextHolder.init(servletContext, request, response);
 			Route route = routeMatcher.getRoute(method, uri);
 			if (null != route) {
-				request.setRoute(route);
-				
-				// before inteceptor
-				List befores = routeMatcher.getBefore(uri);
-				boolean result = invokeInterceptor(request, response, befores);
-				if(result){
-					// execute
-					this.routeHandle(request, response, route);
-					if(!request.isAbort()){
-						// after inteceptor
-						List afters = routeMatcher.getAfter(uri);
-						invokeInterceptor(request, response, afters);
+
+				if(route.getHttpMethod() != HttpMethod.valueOf(method) && route.getHttpMethod() != HttpMethod.ALL){
+					render405(response, uri);
+				} else {
+					request.setRoute(route);
+
+					// before inteceptor
+					List befores = routeMatcher.getBefore(uri);
+					boolean result = invokeInterceptor(request, response, befores);
+					if(result){
+						// execute
+						this.routeHandle(request, response, route);
+						if(!request.isAbort()){
+							// after inteceptor
+							List afters = routeMatcher.getAfter(uri);
+							invokeInterceptor(request, response, afters);
+						}
 					}
 				}
 			} else {
@@ -121,7 +116,19 @@ public void handle(HttpServletRequest httpRequest, HttpServletResponse httpRespo
 			DispatchKit.printError(e, 500, response);
 		}
 	}
-	
+
+	private void render405(Response response, String uri) throws Exception {
+		String view404 = ViewSettings.$().getView404();
+		if(StringKit.isNotBlank(view404)){
+			ModelAndView modelAndView = new ModelAndView(view404);
+			modelAndView.add("viewName", uri);
+			response.render( modelAndView );
+		} else {
+			response.status(HttpStatus.METHOD_NOT_ALLOWED);
+			response.html(String.format(Const.VIEW_405, uri));
+		}
+	}
+
 	/**
 	 * 404 view render
 	 * 
@@ -138,7 +145,7 @@ private void render404(Response response, String uri) throws Exception {
     		response.render( modelAndView );
     	} else {
     		response.status(HttpStatus.NOT_FOUND);
-    		response.html(String.format(Const.VIEW_NOTFOUND, uri));
+    		response.html(String.format(Const.VIEW_404, uri));
 		}
 	}
 	
diff --git a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java
index 961789fd8..54acd7b2f 100644
--- a/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java
+++ b/blade-core/src/main/java/com/blade/mvc/DispatcherServlet.java
@@ -24,6 +24,7 @@
 import javax.servlet.http.HttpServletResponse;
 
 import com.blade.Blade;
+import com.blade.Const;
 
 /**
  * Blade Core DispatcherServlet
@@ -51,6 +52,7 @@ public void init(ServletConfig config) throws ServletException {
 	protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException {
 		httpRequest.setCharacterEncoding(blade.encoding());
 		httpResponse.setCharacterEncoding(blade.encoding());
+		httpResponse.setHeader("server", "blade " + Const.VERSION);
 		dispatcherHandler.handle(httpRequest, httpResponse);
 	}
 	
diff --git a/blade-core/src/main/java/com/blade/mvc/http/HttpStatus.java b/blade-core/src/main/java/com/blade/mvc/http/HttpStatus.java
index 8422318c1..4c7ba727f 100644
--- a/blade-core/src/main/java/com/blade/mvc/http/HttpStatus.java
+++ b/blade-core/src/main/java/com/blade/mvc/http/HttpStatus.java
@@ -21,26 +21,27 @@
  * @author	biezhi
  * @since	1.5
  */
-public final class HttpStatus {
+public interface HttpStatus {
 
-	public static final int OK = 200;
-	public static final int CREATED = 201;
-	public static final int ACCEPTED = 202;
-	public static final int PARTIAL_INFO = 203;
-	public static final int NO_RESPONSE = 204;
-	public static final int MOVED = 301;
-	public static final int FOUND = 302;
-	public static final int METHOD = 303;
-	public static final int NOT_MODIFIED = 304;
-	public static final int BAD_REQUEST = 400;
-	public static final int UNAUTHORIZED = 401;
-	public static final int PAYMENT_REQUIRED = 402;
-	public static final int FORBIDDEN = 403;
-	public static final int NOT_FOUND = 404;
-	public static final int CONFLICT = 409;
-	public static final int INTERNAL_ERROR = 500;
-	public static final int NOT_IMPLEMENTED = 501;
-	public static final int OVERLOADED = 502;
-	public static final int GATEWAY_TIMEOUT = 503;
+	int OK 					= 200;
+	int CREATED 			= 201;
+	int ACCEPTED 			= 202;
+	int PARTIAL_INFO 		= 203;
+	int NO_RESPONSE 		= 204;
+	int MOVED 				= 301;
+	int FOUND 				= 302;
+	int METHOD 				= 303;
+	int NOT_MODIFIED 		= 304;
+	int BAD_REQUEST 		= 400;
+	int UNAUTHORIZED 		= 401;
+	int PAYMENT_REQUIRED 	= 402;
+	int FORBIDDEN 			= 403;
+	int NOT_FOUND 			= 404;
+	int METHOD_NOT_ALLOWED 	= 405;
+	int CONFLICT 			= 409;
+	int INTERNAL_ERROR 		= 500;
+	int NOT_IMPLEMENTED 	= 501;
+	int OVERLOADED 			= 502;
+	int GATEWAY_TIMEOUT 	= 503;
 	
 }
diff --git a/blade-core/src/main/java/com/blade/mvc/route/Route.java b/blade-core/src/main/java/com/blade/mvc/route/Route.java
index 2a9c5a1d5..d8fbb8cf7 100644
--- a/blade-core/src/main/java/com/blade/mvc/route/Route.java
+++ b/blade-core/src/main/java/com/blade/mvc/route/Route.java
@@ -65,7 +65,7 @@ public Route(HttpMethod httpMethod, String path, Object target, Class targetT
 		this.action = action;
 	}
 	
-	HttpMethod getHttpMethod() {
+	public HttpMethod getHttpMethod() {
 		return httpMethod;
 	}
 
diff --git a/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java b/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java
index 4e4f4840d..8ae19f0e8 100644
--- a/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java
+++ b/blade-core/src/main/java/com/blade/mvc/route/RouteMatcher.java
@@ -76,12 +76,9 @@ public Route getRoute(String httpMethod, String path) {
 
 		routeKeys.forEach(key -> {
 			String[] keyArr =  StringKit.split(key, '#');
-			HttpMethod routeMethod = HttpMethod.valueOf(keyArr[1]);
 			if (matchesPath(keyArr[0], cleanPath)) {
-				if (routeMethod == HttpMethod.ALL || HttpMethod.valueOf(httpMethod) == routeMethod) {
-					route[0] = routes.get(key);
-					matchRoutes.add(route[0]);
-				}
+				route[0] = routes.get(key);
+				matchRoutes.add(route[0]);
 			}
 		});
 
diff --git a/blade-sample/src/main/java/com/xxx/hello/Application.java b/blade-sample/src/main/java/com/xxx/hello/Application.java
index deeb48c45..e11e3fb44 100644
--- a/blade-sample/src/main/java/com/xxx/hello/Application.java
+++ b/blade-sample/src/main/java/com/xxx/hello/Application.java
@@ -34,6 +34,9 @@ public static void main(String[] args) {
             request.attribute("name", name);
             response.render("hello.vm");
 
+        }).delete("/user/:id", (request, response)-> {
+            int id = request.pathParamAsInt("id");
+            System.out.println("userid is " + id);
         }).start(Application.class);
     }
 
diff --git a/blade-sample/src/main/resources/app.properties b/blade-sample/src/main/resources/app.properties
new file mode 100644
index 000000000..ba1fcd377
--- /dev/null
+++ b/blade-sample/src/main/resources/app.properties
@@ -0,0 +1 @@
+app.dev = true
\ No newline at end of file

From a37a599b182dc34307a2c77ec35d346046961eb2 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Mon, 2 Jan 2017 21:17:02 +0800
Subject: [PATCH 537/545] => fixed https://github.com/biezhi/blade/issues/82

---
 .../java/com/blade/mvc/route/Routers.java     | 39 +++++++++----------
 .../main/java/com/xxx/hello/Application.java  |  5 +++
 .../xxx/hello/controller/MsgController.java   | 15 +++++++
 3 files changed, 38 insertions(+), 21 deletions(-)
 create mode 100644 blade-sample/src/main/java/com/xxx/hello/controller/MsgController.java

diff --git a/blade-core/src/main/java/com/blade/mvc/route/Routers.java b/blade-core/src/main/java/com/blade/mvc/route/Routers.java
index 0e164aa72..fd75b43a0 100644
--- a/blade-core/src/main/java/com/blade/mvc/route/Routers.java
+++ b/blade-core/src/main/java/com/blade/mvc/route/Routers.java
@@ -130,22 +130,27 @@ public void route(String[] paths, RouteHandler handler, HttpMethod httpMethod) {
 		}
 	}
 	
-	private Map classMethosPool = CollectionKit.newHashMap(8);
-	
+	private Map classMethosPool = CollectionKit.newHashMap(16);
+	private Map, Object> controllerPool = CollectionKit.newHashMap(16);
+
 	public void route(String path, Class clazz, String methodName) {
-		
-		Assert.notNull(path, "Route path not is null!");
-		Assert.notNull(clazz, "Class Type not is null!");
 		Assert.notNull(methodName, "Method name not is null");
-		
 		HttpMethod httpMethod = HttpMethod.ALL;
 		if(methodName.contains(":")){
 			String[] methodArr = methodName.split(":");
 			httpMethod = HttpMethod.valueOf(methodArr[0].toUpperCase());
 			methodName = methodArr[1];
 		}
+		this.route(path, clazz, methodName, httpMethod);
+	}
+	
+	public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) {
 		try {
-			
+			Assert.notNull(path, "Route path not is null!");
+			Assert.notNull(clazz, "Class Type not is null!");
+			Assert.notNull(methodName, "Method name not is null");
+			Assert.notNull(httpMethod, "Request Method not is null");
+
 			Method[] methods = classMethosPool.get(clazz.getName());
 			if(null == methods){
 				methods = clazz.getMethods();
@@ -154,7 +159,12 @@ public void route(String path, Class clazz, String methodName) {
 			if(null != methods){
 				for (Method method : methods) {
 					if (method.getName().equals(methodName)) {
-						addRoute(httpMethod, path, ReflectKit.newInstance(clazz), clazz, method);
+						Object controller = controllerPool.get(clazz);
+						if(null == controller){
+							controller = ReflectKit.newInstance(clazz);
+							controllerPool.put(clazz, controller);
+						}
+						addRoute(httpMethod, path, controller, clazz, method);
 					}
 				}
 			}
@@ -162,19 +172,6 @@ public void route(String path, Class clazz, String methodName) {
 			LOGGER.error("", e);
 		}
 	}
-	
-	public void route(String path, Class clazz, String methodName, HttpMethod httpMethod) {
-		try {
-			Assert.notNull(path, "Route path not is null!");
-			Assert.notNull(clazz, "Class Type not is null!");
-			Assert.notNull(methodName, "Method name not is null");
-			Assert.notNull(httpMethod, "Request Method not is null");
-			Method method = clazz.getMethod(methodName, Request.class, Response.class);
-			addRoute(httpMethod, path, null, clazz, method);
-		} catch (Exception e) {
-			LOGGER.error("", e);
-		}
-	}
 
 	public void buildRoute(String path, Class clazz, Method method, HttpMethod httpMethod) {
 		addRoute(httpMethod, path, null, clazz, method);
diff --git a/blade-sample/src/main/java/com/xxx/hello/Application.java b/blade-sample/src/main/java/com/xxx/hello/Application.java
index e11e3fb44..5d03f3178 100644
--- a/blade-sample/src/main/java/com/xxx/hello/Application.java
+++ b/blade-sample/src/main/java/com/xxx/hello/Application.java
@@ -2,9 +2,11 @@
 
 import com.blade.Const;
 import com.blade.kit.json.JSONObject;
+import com.blade.mvc.http.HttpMethod;
 import com.blade.mvc.view.RestResponse;
 import com.blade.mvc.view.ViewSettings;
 import com.blade.mvc.view.template.VelocityTemplateEngine;
+import com.xxx.hello.controller.MsgController;
 
 import static com.blade.Blade.$;
 
@@ -18,6 +20,9 @@ public static void main(String[] args) {
         // setting default template engine is velocity :)
         ViewSettings.$().templateEngine(new VelocityTemplateEngine());
 
+        $().route("/msg", MsgController.class, "msg", HttpMethod.GET);
+
+
         $().get("/", (request, response) -> {
 
             RestResponse restResponse = new RestResponse<>();
diff --git a/blade-sample/src/main/java/com/xxx/hello/controller/MsgController.java b/blade-sample/src/main/java/com/xxx/hello/controller/MsgController.java
new file mode 100644
index 000000000..a3b30f17d
--- /dev/null
+++ b/blade-sample/src/main/java/com/xxx/hello/controller/MsgController.java
@@ -0,0 +1,15 @@
+package com.xxx.hello.controller;
+
+import com.blade.mvc.http.Request;
+import com.blade.mvc.http.Response;
+
+/**
+ * Created by biezhi on 2017/1/2.
+ */
+public class MsgController {
+
+    public void msg(){
+        System.out.println("进入msg");
+    }
+
+}

From f5ba9795f59b26f40be2d2a988371db9a2b5b7e8 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Mon, 2 Jan 2017 22:08:43 +0800
Subject: [PATCH 538/545] => add path param default value

---
 .../src/main/java/com/blade/kit/AsmKit.java   |   9 +-
 .../com/blade/mvc/annotation/PathParam.java   |   4 +-
 .../mvc/view/resolve/MethodArgument.java      |  13 +-
 .../mvc/view/resolve/MethodArgumentN.java     | 150 ++++++++++++++++++
 .../main/java/com/xxx/hello/Application.java  |   1 -
 .../xxx/hello/controller/IndexController.java |  24 +++
 6 files changed, 186 insertions(+), 15 deletions(-)
 create mode 100644 blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgumentN.java
 create mode 100644 blade-sample/src/main/java/com/xxx/hello/controller/IndexController.java

diff --git a/blade-core/src/main/java/com/blade/kit/AsmKit.java b/blade-core/src/main/java/com/blade/kit/AsmKit.java
index ddb94e92b..bed8beb0a 100644
--- a/blade-core/src/main/java/com/blade/kit/AsmKit.java
+++ b/blade-core/src/main/java/com/blade/kit/AsmKit.java
@@ -15,17 +15,12 @@
  */
 package com.blade.kit;
 
+import org.objectweb.asm.*;
+
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
 /**
  * ASM Tools
  *
diff --git a/blade-core/src/main/java/com/blade/mvc/annotation/PathParam.java b/blade-core/src/main/java/com/blade/mvc/annotation/PathParam.java
index 773503706..16241b0b0 100644
--- a/blade-core/src/main/java/com/blade/mvc/annotation/PathParam.java
+++ b/blade-core/src/main/java/com/blade/mvc/annotation/PathParam.java
@@ -33,5 +33,7 @@
 public @interface PathParam {
 	
 	String value() default "";
-	
+
+	String defaultValue() default "";
+
 }
diff --git a/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java b/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java
index fbdfd002e..dfd4ecd23 100644
--- a/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java
+++ b/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgument.java
@@ -34,10 +34,11 @@ public static Object[] getArgs(Request request, Response response, Method action
 
 		Class[] parameters = actionMethod.getParameterTypes();
 		Annotation[][] annotations = actionMethod.getParameterAnnotations();
-		
+
 		Object[] args = new Object[parameters.length];
-		
+
 		actionMethod.setAccessible(true);
+
 		String[] paramaterNames = AsmKit.getMethodParamNames(actionMethod);
 
 		for (int i = 0, len = parameters.length; i < len; i++) {
@@ -139,7 +140,7 @@ public static Object[] getArgs(Request request, Response response, Method action
 						val = request.pathParam(paramName);
 					}
 					if (StringKit.isBlank(val)) {
-						throw new NotFoundException("path param [" + paramName + "] is null");
+						val = pathParam.defaultValue();
 					}
 					args[i] = getRequestParam(argType, val);
 				}
@@ -147,8 +148,8 @@ public static Object[] getArgs(Request request, Response response, Method action
 		}
 		return args;
 	}
-	
-	private static Object getRequestParam(Class parameterType, String val) {
+
+	public static Object getRequestParam(Class parameterType, String val) {
 		Object result = null;
 		if (parameterType.equals(String.class)) {
 			result = val;
@@ -171,5 +172,5 @@ private static Object getRequestParam(Class parameterType, String val) {
 		}
 		return result;
 	}
-	
+
 }
diff --git a/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgumentN.java b/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgumentN.java
new file mode 100644
index 000000000..8dc1fd9bd
--- /dev/null
+++ b/blade-core/src/main/java/com/blade/mvc/view/resolve/MethodArgumentN.java
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.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.blade.mvc.view.resolve;
+
+import com.blade.exception.NotFoundException;
+import com.blade.kit.StringKit;
+import com.blade.mvc.annotation.*;
+import com.blade.mvc.http.Request;
+import com.blade.mvc.http.Response;
+import com.blade.mvc.multipart.FileItem;
+import com.blade.mvc.view.ModelAndView;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Parameter;
+import java.util.Map;
+
+public final class MethodArgumentN {
+
+	private static boolean isParameterFinal(final Parameter parameter)
+	{
+		return Modifier.isFinal(parameter.getModifiers());
+	}
+
+	public static Object[] getArgs(Request request, Response response, Method actionMethod) throws Exception{
+
+		int parameterCount = 0;
+		for (final Parameter parameter : actionMethod.getParameters())
+		{
+			System.out.println(
+					"\targ" + parameterCount++ + ": "
+							+ (parameter.isNamePresent() ? parameter.getName() : "Parameter Name not provided,")
+							+ (isParameterFinal(parameter) ? " IS " : " is NOT ")
+							+ "final, type " + parameter.getType().getCanonicalName()
+							+ ", and parameterized type of " + parameter.getParameterizedType()
+							+ " and " + (parameter.isVarArgs() ? "IS " : "is NOT ")
+							+ "variable." );
+		}
+
+		Parameter[] parameters = actionMethod.getParameters();
+		Object[] args = new Object[parameters.length];
+		actionMethod.setAccessible(true);
+
+		for (int i = 0, len = parameters.length; i < len; i++) {
+
+			Parameter parameter = parameters[i];
+
+			Class argType = parameter.getType();
+			if (argType == Request.class) {
+				args[i] = request;
+				continue;
+			}
+
+			if (argType == Response.class) {
+				args[i] = response;
+				continue;
+			}
+
+			if (argType == ModelAndView.class) {
+				args[i] = new ModelAndView();
+				continue;
+			}
+
+			if (argType == Map.class) {
+				args[i] = request.querys();
+				continue;
+			}
+
+			QueryParam queryParam = parameter.getAnnotation(QueryParam.class);
+			if(null != queryParam){
+				String paramName = queryParam.value();
+				String val = request.query(paramName);
+
+				if (StringKit.isBlank(paramName)) {
+					paramName = parameter.getName();
+					val = request.query(paramName);
+				}
+				if (StringKit.isBlank(val)) {
+					val = queryParam.defaultValue();
+				}
+				args[i] = MethodArgument.getRequestParam(argType, val);
+			}
+
+			PathParam pathParam = parameter.getAnnotation(PathParam.class);
+			if(null != pathParam){
+				String paramName = pathParam.value();
+				String val = request.pathParam(paramName);
+				if (StringKit.isBlank(paramName)) {
+					paramName = parameter.getName();
+					val = request.pathParam(paramName);
+				}
+				if (StringKit.isBlank(val)) {
+					throw new NotFoundException("path param [" + paramName + "] is null");
+				}
+				args[i] = MethodArgument.getRequestParam(argType, val);
+			}
+
+			HeaderParam headerParam = parameter.getAnnotation(HeaderParam.class);
+			if(null != headerParam){
+				String paramName = headerParam.value();
+				String val = request.header(paramName);
+
+				if (StringKit.isBlank(paramName)) {
+					paramName = parameter.getName();
+					val = request.header(paramName);
+				}
+				args[i] = MethodArgument.getRequestParam(argType, val);
+			}
+
+			CookieParam cookieParam = parameter.getAnnotation(CookieParam.class);
+			if(null != cookieParam){
+				String paramName = cookieParam.value();
+				String val = request.cookie(paramName);
+
+				if (StringKit.isBlank(paramName)) {
+					paramName = parameter.getName();
+					val = request.cookie(paramName);
+				}
+				args[i] = MethodArgument.getRequestParam(argType, val);
+			}
+
+			MultipartParam multipartParam = parameter.getAnnotation(MultipartParam.class);
+			if(null != multipartParam && argType == FileItem.class){
+				String paramName = multipartParam.value();
+				FileItem val = request.fileItem(paramName);
+
+				if (StringKit.isBlank(paramName)) {
+					paramName = parameter.getName();
+					val = request.fileItem(paramName);
+				}
+				args[i] = val;
+			}
+		}
+		return args;
+	}
+
+}
diff --git a/blade-sample/src/main/java/com/xxx/hello/Application.java b/blade-sample/src/main/java/com/xxx/hello/Application.java
index 5d03f3178..7a08575b6 100644
--- a/blade-sample/src/main/java/com/xxx/hello/Application.java
+++ b/blade-sample/src/main/java/com/xxx/hello/Application.java
@@ -22,7 +22,6 @@ public static void main(String[] args) {
 
         $().route("/msg", MsgController.class, "msg", HttpMethod.GET);
 
-
         $().get("/", (request, response) -> {
 
             RestResponse restResponse = new RestResponse<>();
diff --git a/blade-sample/src/main/java/com/xxx/hello/controller/IndexController.java b/blade-sample/src/main/java/com/xxx/hello/controller/IndexController.java
new file mode 100644
index 000000000..2b1134fb0
--- /dev/null
+++ b/blade-sample/src/main/java/com/xxx/hello/controller/IndexController.java
@@ -0,0 +1,24 @@
+package com.xxx.hello.controller;
+
+import com.blade.mvc.annotation.Controller;
+import com.blade.mvc.annotation.PathParam;
+import com.blade.mvc.annotation.QueryParam;
+import com.blade.mvc.annotation.Route;
+
+/**
+ * Created by biezhi on 2017/1/2.
+ */
+@Controller
+public class IndexController {
+
+    @Route("sayHi")
+    public void sayHi(@QueryParam("name") String name){
+        System.out.println("name = " + name);
+    }
+
+    @Route("sayHi/:name")
+    public void sayHi2(@PathParam String name){
+        System.out.println("name = " + name);
+    }
+
+}

From aa7f132a4e790934c50514664101e7e698a076a2 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Mon, 2 Jan 2017 22:58:26 +0800
Subject: [PATCH 539/545] =?UTF-8?q?=E2=9C=84=20add=20custom=20classpath=20?=
 =?UTF-8?q?folder?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 blade-core/src/main/java/com/blade/Const.java       |  1 +
 .../main/java/com/blade/config/Configuration.java   | 10 +++++++++-
 .../java/com/blade/embedd/EmbedJettyServer.java     | 13 ++++++++++++-
 .../com/xxx/hello/controller/IndexController.java   |  4 ++--
 4 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/blade-core/src/main/java/com/blade/Const.java b/blade-core/src/main/java/com/blade/Const.java
index 0ec1960ff..e9d5f5ef4 100644
--- a/blade-core/src/main/java/com/blade/Const.java
+++ b/blade-core/src/main/java/com/blade/Const.java
@@ -83,4 +83,5 @@ public interface Const {
 	String 	APP_DEV				= "app.dev";
 	String	APP_IOC				= "app.ioc";
 	String	APP_BASE_PKG		= "app.base-package";
+	String	APP_CLASSPATH		= "app.classpath";
 }
\ No newline at end of file
diff --git a/blade-core/src/main/java/com/blade/config/Configuration.java b/blade-core/src/main/java/com/blade/config/Configuration.java
index 8cc081a6f..fe008390c 100644
--- a/blade-core/src/main/java/com/blade/config/Configuration.java
+++ b/blade-core/src/main/java/com/blade/config/Configuration.java
@@ -54,6 +54,8 @@ public class Configuration {
 	
 	private Class applicationClass;
 
+	private String classPath = "config";
+
 	private Config config = new Config();
 
 	public Configuration() {
@@ -83,7 +85,9 @@ public void setEnv(Config config) {
 			
 			// get app base package
 			String basePackage = config.get(Const.APP_BASE_PKG);
-			
+
+			this.classPath = config.get(Const.APP_CLASSPATH, "config");
+
 			// get server start port
 			Integer port = config.getInt(Const.SERVER_PORT, Const.DEFAULT_PORT);
 			$().listen(port);
@@ -197,6 +201,10 @@ public void setDev(boolean isDev) {
 		this.isDev = isDev;
 	}
 
+	public String getClassPath() {
+		return classPath;
+	}
+
 	public void load(String location) {
 		try {
 			config.add(location);
diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java
index 96473a229..ab86f839b 100644
--- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java
+++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java
@@ -5,6 +5,7 @@
 import com.blade.context.WebContextListener;
 import com.blade.exception.EmbedServerException;
 import com.blade.kit.CollectionKit;
+import com.blade.kit.StringKit;
 import com.blade.kit.base.Config;
 import com.blade.mvc.DispatcherServlet;
 import org.eclipse.jetty.server.*;
@@ -20,6 +21,7 @@
 import javax.servlet.DispatcherType;
 import javax.servlet.Filter;
 import javax.servlet.http.HttpServlet;
+import java.io.File;
 import java.util.EnumSet;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -34,7 +36,9 @@ public class EmbedJettyServer implements EmbedServer {
     private int port = Const.DEFAULT_PORT;
 	
 	private Server server;
-	
+
+	private String classPath;
+
 	private WebAppContext webAppContext;
 
 	private Set staticFolders;
@@ -46,6 +50,8 @@ public EmbedJettyServer() {
 		$().loadAppConf("jetty.properties");
 		config = $().config();
 		staticFolders = $().configuration().getResources();
+		File f = new File(this.getClass().getResource("/").getPath());
+		this.classPath = f.getParent() + File.separator + $().configuration().getClassPath();
 		$().enableServer(true);
 	}
 	
@@ -116,6 +122,11 @@ public void startup(int port, String contextPath, String webRoot) throws EmbedSe
 	    webAppContext.addServlet(servletHolder, "/");
 
 		ServletHolder defaultHolder = new ServletHolder(DefaultServlet.class);
+		if(StringKit.isNotBlank(classPath)){
+			LOGGER.info("add classpath : {}", classPath);
+			defaultHolder.setInitParameter("resourceBase", classPath);
+		}
+
 		for(String s : staticFolders){
 			webAppContext.addServlet(defaultHolder, s);
 		}
diff --git a/blade-sample/src/main/java/com/xxx/hello/controller/IndexController.java b/blade-sample/src/main/java/com/xxx/hello/controller/IndexController.java
index 2b1134fb0..44395c052 100644
--- a/blade-sample/src/main/java/com/xxx/hello/controller/IndexController.java
+++ b/blade-sample/src/main/java/com/xxx/hello/controller/IndexController.java
@@ -12,12 +12,12 @@
 public class IndexController {
 
     @Route("sayHi")
-    public void sayHi(@QueryParam("name") String name){
+    public void sayHi(@QueryParam(value = "name", required = true) String name){
         System.out.println("name = " + name);
     }
 
     @Route("sayHi/:name")
-    public void sayHi2(@PathParam String name){
+    public void sayHi2(@PathParam Long name){
         System.out.println("name = " + name);
     }
 

From b3ec00126b487581c6adbe8b8644aa7487641230 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Tue, 3 Jan 2017 13:37:08 +0800
Subject: [PATCH 540/545] =?UTF-8?q?=E2=9C=84=20update=20last=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 LAST_VERSION.md | 34 ++++++++--------------------------
 1 file changed, 8 insertions(+), 26 deletions(-)

diff --git a/LAST_VERSION.md b/LAST_VERSION.md
index c4fd9cb0e..f5eb7fc09 100644
--- a/LAST_VERSION.md
+++ b/LAST_VERSION.md
@@ -25,7 +25,7 @@
 
     com.bladejava
     blade-kit
-    1.3.4
+    1.4.0-alpha
 
 ```
 
@@ -34,7 +34,7 @@
 
     com.bladejava
     blade-core
-    1.6.7-beta
+    1.7.0-alpha
 
 ```
 
@@ -43,16 +43,16 @@
 
     com.bladejava
     blade-embed-jetty
-    0.0.6
+    0.0.7
 
 ```
 
-## [blade-websocket-jetty](http://search.maven.org/#search%7Cga%7C1%7Cblade-websocket-jetty)
+## [blade-template-jetbrick](http://search.maven.org/#search%7Cga%7C1%7Cblade-template-jetbrick)
 ```xml
 
     com.bladejava
-    blade-websocket-jetty
-    0.0.1
+    blade-template-jetbrick
+    0.0.7
 
 ```
 
@@ -61,25 +61,7 @@
 
     com.bladejava
     blade-jdbc
-    0.1.3-beta
-
-```
-
-## [blade-cache](http://search.maven.org/#search%7Cga%7C1%7Cblade-cache)
-```xml
-
-    com.bladejava
-    blade-cache
-    1.2.3
-
-```
-
-## [blade-redis](http://search.maven.org/#search%7Cga%7C1%7Cblade-redis)
-```xml
-
-    com.bladejava
-    blade-redis
-    1.2.3
+    0.1.4-alpha
 
 ```
 
@@ -88,7 +70,7 @@
 
     com.bladejava
     blade-patchca
-    1.0.4
+    1.0.5
 
 ```
 

From 706bd5fa159514498afefbb36e876f5eef30ec86 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Tue, 3 Jan 2017 15:07:46 +0800
Subject: [PATCH 541/545] =?UTF-8?q?=E2=9C=84=20fixed=20jar=20package=20sta?=
 =?UTF-8?q?tic=20file=20not=20found?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../java/com/blade/embedd/EmbedJettyServer.java     | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java
index ab86f839b..683cc1d3f 100644
--- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java
+++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java
@@ -37,6 +37,8 @@ public class EmbedJettyServer implements EmbedServer {
 	
 	private Server server;
 
+	private String webRoot;
+
 	private String classPath;
 
 	private WebAppContext webAppContext;
@@ -50,8 +52,14 @@ public EmbedJettyServer() {
 		$().loadAppConf("jetty.properties");
 		config = $().config();
 		staticFolders = $().configuration().getResources();
-		File f = new File(this.getClass().getResource("/").getPath());
-		this.classPath = f.getParent() + File.separator + $().configuration().getClassPath();
+
+		String urlStr = EmbedJettyServer.class.getResource("").getPath();
+		int pos = urlStr.indexOf("jar!/");
+		if(pos != -1){
+			String jarPath = new File(urlStr.substring(5, pos + 2)).getParent();
+			this.classPath = new File(jarPath).getParent() + File.separator + $().configuration().getClassPath();
+		}
+
 		$().enableServer(true);
 	}
 	
@@ -67,6 +75,7 @@ public void startup(int port, String contextPath) throws EmbedServerException {
 	
 	@Override
 	public void setWebRoot(String webRoot) {
+		this.webRoot = webRoot;
 		webAppContext.setResourceBase(webRoot);
 	}
 	

From f2650729f361322c6954d6282a96ca97b6f5ae56 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Tue, 3 Jan 2017 15:08:13 +0800
Subject: [PATCH 542/545] =?UTF-8?q?=E2=9C=84=20fixed=20log=20file.encoding?=
 =?UTF-8?q?=20error?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../src/main/java/com/blade/context/WebContextListener.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/blade-core/src/main/java/com/blade/context/WebContextListener.java b/blade-core/src/main/java/com/blade/context/WebContextListener.java
index e1523d1fe..a5f0beceb 100644
--- a/blade-core/src/main/java/com/blade/context/WebContextListener.java
+++ b/blade-core/src/main/java/com/blade/context/WebContextListener.java
@@ -64,7 +64,7 @@ public void contextInitialized(ServletContextEvent sce) {
 			LOGGER.info("user.dir\t\t=> {}", System.getProperty("user.dir"));
 			LOGGER.info("java.io.tmpdir\t=> {}", System.getProperty("java.io.tmpdir"));
 			LOGGER.info("user.timezone\t=> {}", System.getProperty("user.timezone"));
-			LOGGER.info("file.encodin\t=> {}", System.getProperty("file.encoding"));
+			LOGGER.info("file.encoding\t=> {}", System.getProperty("file.encoding"));
 			
 			long initStart = System.currentTimeMillis();
 			
@@ -79,9 +79,9 @@ public void contextInitialized(ServletContextEvent sce) {
 		    LOGGER.info("blade.webroot\t=> {}", webRoot);
 		    
 		    try {
-				if(!blade.applicationConfig().isInit()){
+				if(!blade.configuration().isInit()){
 				    blade.loadAppConf(Const.APP_PROPERTIES);
-					blade.applicationConfig().setEnv(blade.config());
+					blade.configuration().setEnv(blade.config());
 			    }
 				
 				// initialization ioc

From 9062928b8d80bb21e31035adaedda42351a68934 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Tue, 3 Jan 2017 15:48:46 +0800
Subject: [PATCH 543/545] =?UTF-8?q?=E2=9C=84=20fixed=20configuration=20log?=
 =?UTF-8?q?=20and=20startup=20load=20config?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 blade-core/src/main/java/com/blade/Blade.java      | 14 ++++++++++----
 .../main/java/com/blade/config/Configuration.java  |  2 +-
 .../java/com/blade/context/DynamicContext.java     |  2 +-
 .../java/com/blade/context/WebContextListener.java |  5 -----
 4 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/blade-core/src/main/java/com/blade/Blade.java b/blade-core/src/main/java/com/blade/Blade.java
index a7e0dcd95..ed068bfb4 100644
--- a/blade-core/src/main/java/com/blade/Blade.java
+++ b/blade-core/src/main/java/com/blade/Blade.java
@@ -28,7 +28,10 @@
 import com.blade.mvc.handler.RouteHandler;
 import com.blade.mvc.http.HttpMethod;
 import com.blade.mvc.interceptor.Interceptor;
-import com.blade.mvc.route.*;
+import com.blade.mvc.route.Route;
+import com.blade.mvc.route.RouteBuilder;
+import com.blade.mvc.route.RouteGroup;
+import com.blade.mvc.route.Routers;
 import com.blade.mvc.route.loader.ClassPathRouteLoader;
 import com.blade.plugin.Plugin;
 
@@ -551,6 +554,11 @@ public EmbedServer startNoJoin(Class applicationClass, String contextPath) {
 				embedClazz = Class.forName(Const.TOMCAT_SERVER_CLASS);
 			}
 			if(null != embedClazz){
+				if(!configuration().isInit()){
+					loadAppConf(Const.APP_PROPERTIES);
+					configuration().setEnv(config());
+				}
+
 				this.embedServer = (EmbedServer) embedClazz.newInstance();
 				this.embedServer.startup(config().getInt(Const.SERVER_PORT, Const.DEFAULT_PORT), contextPath);
 				this.enableServer = true;
@@ -653,9 +661,7 @@ public Blade routeConf(String basePackage, String conf) {
 			routesLoader.setBasePackage(basePackage);
 			List routes = routesLoader.load();
 			routers.addRoutes(routes);
-		} catch (RouteException e) {
-			e.printStackTrace();
-		} catch (ParseException e) {
+		} catch (RouteException | ParseException e) {
 			e.printStackTrace();
 		}
 		return this;
diff --git a/blade-core/src/main/java/com/blade/config/Configuration.java b/blade-core/src/main/java/com/blade/config/Configuration.java
index fe008390c..a3b7ff2d6 100644
--- a/blade-core/src/main/java/com/blade/config/Configuration.java
+++ b/blade-core/src/main/java/com/blade/config/Configuration.java
@@ -209,7 +209,7 @@ public void load(String location) {
 		try {
 			config.add(location);
 		} catch (Exception e){
-			System.out.println("[load config] " + e.getMessage());
+			LOGGER.warn("[load config] " + e.getMessage());
 		}
 	}
 
diff --git a/blade-core/src/main/java/com/blade/context/DynamicContext.java b/blade-core/src/main/java/com/blade/context/DynamicContext.java
index 7f5b181db..f3abe56f4 100644
--- a/blade-core/src/main/java/com/blade/context/DynamicContext.java
+++ b/blade-core/src/main/java/com/blade/context/DynamicContext.java
@@ -41,7 +41,7 @@ private DynamicContext() {
 	
 	public static void init(Class clazz){
 		String rs = clazz.getResource("").toString();
-		if(rs.indexOf(".jar") != -1){
+		if(rs.contains(".jar")){
 			CLASS_READER = new JarReaderImpl();
 			isJarContext = true;
 			LOGGER.debug("{}", CLASS_READER);
diff --git a/blade-core/src/main/java/com/blade/context/WebContextListener.java b/blade-core/src/main/java/com/blade/context/WebContextListener.java
index a5f0beceb..d62f61f95 100644
--- a/blade-core/src/main/java/com/blade/context/WebContextListener.java
+++ b/blade-core/src/main/java/com/blade/context/WebContextListener.java
@@ -79,11 +79,6 @@ public void contextInitialized(ServletContextEvent sce) {
 		    LOGGER.info("blade.webroot\t=> {}", webRoot);
 		    
 		    try {
-				if(!blade.configuration().isInit()){
-				    blade.loadAppConf(Const.APP_PROPERTIES);
-					blade.configuration().setEnv(blade.config());
-			    }
-				
 				// initialization ioc
 				IocApplication iocApplication = new IocApplication();
 				iocApplication.initBeans();

From 4065cccf99f47520e90366606ba669b8ffcb7377 Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Tue, 3 Jan 2017 15:54:24 +0800
Subject: [PATCH 544/545] =?UTF-8?q?=E2=9C=84=20=E2=9C=84=20=E2=9C=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../com/blade/embedd/EmbedJettyServer.java    | 24 ++++++++++++-------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java
index 683cc1d3f..b200669c5 100644
--- a/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java
+++ b/blade-embed-jetty/src/main/java/com/blade/embedd/EmbedJettyServer.java
@@ -2,6 +2,7 @@
 
 import com.blade.Blade;
 import com.blade.Const;
+import com.blade.context.DynamicContext;
 import com.blade.context.WebContextListener;
 import com.blade.exception.EmbedServerException;
 import com.blade.kit.CollectionKit;
@@ -21,7 +22,7 @@
 import javax.servlet.DispatcherType;
 import javax.servlet.Filter;
 import javax.servlet.http.HttpServlet;
-import java.io.File;
+import java.net.URL;
 import java.util.EnumSet;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -37,8 +38,6 @@ public class EmbedJettyServer implements EmbedServer {
 	
 	private Server server;
 
-	private String webRoot;
-
 	private String classPath;
 
 	private WebAppContext webAppContext;
@@ -53,11 +52,19 @@ public EmbedJettyServer() {
 		config = $().config();
 		staticFolders = $().configuration().getResources();
 
-		String urlStr = EmbedJettyServer.class.getResource("").getPath();
-		int pos = urlStr.indexOf("jar!/");
-		if(pos != -1){
-			String jarPath = new File(urlStr.substring(5, pos + 2)).getParent();
-			this.classPath = new File(jarPath).getParent() + File.separator + $().configuration().getClassPath();
+		if(DynamicContext.isJarContext()){
+			URL url = EmbedJettyServer.class.getResource("/");
+			this.classPath = url.getPath();
+//			if(null == url){
+//				String urlStr = EmbedJettyServer.class.getResource("").getPath();
+//				int pos = urlStr.indexOf("jar!/");
+//				if(pos != -1){
+//					String jarPath = new File(urlStr.substring(5, pos + 2)).getParent();
+//					this.classPath = new File(jarPath).getParent() + File.separator + $().configuration().getClassPath();
+//
+//				}
+//			}
+			LOGGER.info("add classpath: {}", classPath);
 		}
 
 		$().enableServer(true);
@@ -75,7 +82,6 @@ public void startup(int port, String contextPath) throws EmbedServerException {
 	
 	@Override
 	public void setWebRoot(String webRoot) {
-		this.webRoot = webRoot;
 		webAppContext.setResourceBase(webRoot);
 	}
 	

From f2888730290154bbb2c586b01dd22703007181ee Mon Sep 17 00:00:00 2001
From: biezhi 
Date: Wed, 4 Jan 2017 10:43:13 +0800
Subject: [PATCH 545/545] =?UTF-8?q?=E2=9C=84=20fixed=20travis=20jdk=20vers?=
 =?UTF-8?q?ion?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .travis.yml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 3199172d7..a1407b9f6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,6 @@
 language: java
 jdk:
   - oraclejdk8
-  - oraclejdk7
-  - openjdk6
 script:
   - mvn install -Dmaven.test.skip=true